Loading drivers/platform/msm/ipa/ipa_v3/ipa.c +3 −0 Original line number Diff line number Diff line Loading @@ -3230,6 +3230,9 @@ static int ipa3_init(const struct ipa3_plat_drv_res *resource_p, spin_lock_init(&ipa3_ctx->ipa3_active_clients.spinlock); ipa3_ctx->ipa3_active_clients.cnt = 1; /* Assign resource limitation to each group */ ipa3_set_resorce_groups_min_max_limits(); /* Create workqueues for power management */ ipa3_ctx->power_mgmt_wq = create_singlethread_workqueue("ipa_power_mgmt"); Loading drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +0 −2 Original line number Diff line number Diff line Loading @@ -117,13 +117,11 @@ int _ipa_read_gen_reg_v3_0(char *buff, int max_len) "IPA_VERSION=0x%x\n" "IPA_COMP_HW_VERSION=0x%x\n" "IPA_ROUTE=0x%x\n" "IPA_FILTER=0x%x\n" "IPA_SHARED_MEM_RESTRICTED=0x%x\n" "IPA_SHARED_MEM_SIZE=0x%x\n", ipa_read_reg(ipa3_ctx->mmio, IPA_VERSION_OFST), ipa_read_reg(ipa3_ctx->mmio, IPA_COMP_HW_VERSION_OFST), ipa_read_reg(ipa3_ctx->mmio, IPA_ROUTE_OFST_v3_0), ipa_read_reg(ipa3_ctx->mmio, IPA_FILTER_OFST_v3_0), ipa_read_reg_field(ipa3_ctx->mmio, IPA_SHARED_MEM_SIZE_OFST_v3_0, IPA_SHARED_MEM_SIZE_SHARED_MEM_BADDR_BMSK_v3_0, Loading drivers/platform/msm/ipa/ipa_v3/ipa_flt.c +30 −7 Original line number Diff line number Diff line Loading @@ -1068,6 +1068,18 @@ static int __ipa_validate_flt_rule(const struct ipa_flt_rule *rule, } } if (rule->rule_id) { if (rule->rule_id >= IPA_RULE_ID_MIN_VAL && rule->rule_id <= IPA_RULE_ID_MAX_VAL) { IPAERR("invalid rule_id provided 0x%x\n" "rule_id 0x%x - 0x%x are auto generated\n", rule->rule_id, IPA_RULE_ID_MIN_VAL, IPA_RULE_ID_MAX_VAL); goto error; } } return 0; error: Loading @@ -1090,12 +1102,16 @@ static int __ipa_create_flt_entry(struct ipa3_flt_entry **entry, (*entry)->cookie = IPA_COOKIE; (*entry)->rt_tbl = rt_tbl; (*entry)->tbl = tbl; if (rule->rule_id) { id = rule->rule_id; } else { id = ipa3_alloc_rule_id(&tbl->rule_ids); if (id < 0) { IPAERR("failed to allocate rule id\n"); WARN_ON(1); goto rule_id_fail; } } (*entry)->rule_id = id; return 0; Loading Loading @@ -1221,6 +1237,9 @@ static int __ipa_del_flt_rule(u32 rule_hdl) IPADBG("del flt rule rule_cnt=%d rule_id=%d\n", entry->tbl->rule_cnt, entry->rule_id); entry->cookie = 0; /* if rule id was allocated from idr, remove it */ if (entry->rule_id >= IPA_RULE_ID_MIN_VAL && entry->rule_id <= IPA_RULE_ID_MAX_VAL) idr_remove(&entry->tbl->rule_ids, entry->rule_id); kmem_cache_free(ipa3_ctx->flt_rule_cache, entry); Loading Loading @@ -1632,7 +1651,11 @@ int ipa3_reset_flt(enum ipa_ip_type ip) entry->tbl->rule_cnt--; if (entry->rt_tbl) entry->rt_tbl->ref_cnt--; idr_remove(&entry->tbl->rule_ids, entry->rule_id); /* if rule id was allocated from idr, remove it */ if (entry->rule_id >= IPA_RULE_ID_MIN_VAL && entry->rule_id <= IPA_RULE_ID_MAX_VAL) idr_remove(&entry->tbl->rule_ids, entry->rule_id); entry->cookie = 0; id = entry->id; kmem_cache_free(ipa3_ctx->flt_rule_cache, entry); Loading drivers/platform/msm/ipa/ipa_v3/ipa_i.h +4 −3 Original line number Diff line number Diff line Loading @@ -155,8 +155,8 @@ #define IPA_RULE_MAX_PRIORITY (0) #define IPA_RULE_MIN_PRIORITY (1023) #define IPA_RULE_ID_MIN_VAL (0) #define IPA_RULE_ID_MAX_VAL (1022) #define IPA_RULE_ID_MIN_VAL (0x01) #define IPA_RULE_ID_MAX_VAL (0x1FF) #define IPA_RULE_ID_RULE_MISS (0x3FF) #define IPA_HDR_PROC_CTX_TABLE_ALIGNMENT_BYTE 8 Loading Loading @@ -208,7 +208,7 @@ struct ipa3_mem_buffer { * @tbl: filter table * @rt_tbl: routing table * @hw_len: entry's size * @id: rule handle - globaly unique * @id: rule handle - globally unique * @prio: rule 10bit priority which defines the order of the rule * among other rules at the same integrated table * @rule_id: rule 10bit ID to be returned in packet status Loading Loading @@ -2021,5 +2021,6 @@ int ipa3_release_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info); int ipa3_create_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info); int ipa3_set_flt_tuple_mask(int pipe_idx, struct ipa3_hash_tuple *tuple); int ipa3_set_rt_tuple_mask(int tbl_idx, struct ipa3_hash_tuple *tuple); void ipa3_set_resorce_groups_min_max_limits(void); #endif /* _IPA3_I_H_ */ drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c +70 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #include "ipa_i.h" #define INTERRUPT_WORKQUEUE_NAME "ipa_interrupt_wq" #define DIS_SUSPEND_INTERRUPT_TIMEOUT 5 struct ipa3_interrupt_info { ipa_irq_handler_t handler; Loading @@ -32,6 +33,14 @@ static struct ipa3_interrupt_info ipa_interrupt_to_cb[IPA_IRQ_MAX]; static struct workqueue_struct *ipa_interrupt_wq; static u32 ipa_ee; static void ipa3_tx_suspend_interrupt_wa(void); static void ipa3_enable_tx_suspend_wa(struct work_struct *work); static DECLARE_DELAYED_WORK(dwork_en_suspend_int, ipa3_enable_tx_suspend_wa); static spinlock_t suspend_wa_lock; static void ipa3_process_interrupts(void); static void ipa3_interrupt_defer(struct work_struct *work); static DECLARE_WORK(ipa3_interrupt_defer_work, ipa3_interrupt_defer); Loading Loading @@ -79,6 +88,8 @@ static int ipa3_handle_interrupt(enum ipa_irq_type interrupt) switch (interrupt) { case IPA_TX_SUSPEND_IRQ: IPADBG("processing TX_SUSPEND interrupt work-around\n"); ipa3_tx_suspend_interrupt_wa(); suspend_data = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_SUSPEND_INFO_EE_n_ADDR(ipa_ee)); if (!ipa3_is_valid_ep(suspend_data)) Loading Loading @@ -126,13 +137,62 @@ fail_alloc_work: return res; } static void ipa3_enable_tx_suspend_wa(struct work_struct *work) { u32 en; u32 suspend_bmask; IPADBG("Enter\n"); /* make sure ipa hw is clocked on*/ ipa3_inc_client_enable_clks(); en = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee)); suspend_bmask = 1 << IPA_TX_SUSPEND_IRQ; /*enable TX_SUSPEND_IRQ*/ en |= suspend_bmask; IPADBG("enable TX_SUSPEND_IRQ, IPA_IRQ_EN_EE reg, write val = %u\n" , en); ipa_write_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee), en); ipa3_process_interrupts(); ipa3_dec_client_disable_clks(); IPADBG("Exit\n"); } static void ipa3_tx_suspend_interrupt_wa(void) { u32 val; u32 suspend_bmask; IPADBG("Enter\n"); /*disable TX_SUSPEND_IRQ*/ val = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee)); suspend_bmask = 1 << IPA_TX_SUSPEND_IRQ; val &= ~suspend_bmask; IPADBG("Disabling TX_SUSPEND_IRQ, write val: %u to IPA_IRQ_EN_EE reg\n", val); ipa_write_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee), val); IPADBG(" processing suspend interrupt work-around, delayed work\n"); queue_delayed_work(ipa_interrupt_wq, &dwork_en_suspend_int, msecs_to_jiffies(DIS_SUSPEND_INTERRUPT_TIMEOUT)); IPADBG("Exit\n"); } static void ipa3_process_interrupts(void) { u32 reg; u32 bmsk; u32 i = 0; u32 en; unsigned long flags; IPADBG("Enter\n"); spin_lock_irqsave(&suspend_wa_lock, flags); en = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee)); reg = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_STTS_EE_n_ADDR(ipa_ee)); while (en & reg) { Loading @@ -146,7 +206,14 @@ static void ipa3_process_interrupts(void) IPA_IRQ_CLR_EE_n_ADDR(ipa_ee), reg); reg = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_STTS_EE_n_ADDR(ipa_ee)); /* since the suspend interrupt HW bug we must * read again the EN register, otherwise the while is endless */ en = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee)); } spin_unlock_irqrestore(&suspend_wa_lock, flags); IPADBG("Exit\n"); } static void ipa3_interrupt_defer(struct work_struct *work) Loading @@ -162,6 +229,7 @@ static irqreturn_t ipa3_isr(int irq, void *ctxt) { unsigned long flags; IPADBG("Enter\n"); /* defer interrupt handling in case IPA is not clocked on */ if (ipa3_active_clients_trylock(&flags) == 0) { IPADBG("defer interrupt processing\n"); Loading @@ -176,6 +244,7 @@ static irqreturn_t ipa3_isr(int irq, void *ctxt) } ipa3_process_interrupts(); IPADBG("Exit\n"); bail: ipa3_active_clients_trylock_unlock(&flags); Loading Loading @@ -293,5 +362,6 @@ int ipa3_interrupts_init(u32 ipa_irq, u32 ee, struct device *ipa_dev) else IPADBG("IPA IRQ wakeup enabled irq=%d\n", ipa_irq); spin_lock_init(&suspend_wa_lock); return 0; } Loading
drivers/platform/msm/ipa/ipa_v3/ipa.c +3 −0 Original line number Diff line number Diff line Loading @@ -3230,6 +3230,9 @@ static int ipa3_init(const struct ipa3_plat_drv_res *resource_p, spin_lock_init(&ipa3_ctx->ipa3_active_clients.spinlock); ipa3_ctx->ipa3_active_clients.cnt = 1; /* Assign resource limitation to each group */ ipa3_set_resorce_groups_min_max_limits(); /* Create workqueues for power management */ ipa3_ctx->power_mgmt_wq = create_singlethread_workqueue("ipa_power_mgmt"); Loading
drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +0 −2 Original line number Diff line number Diff line Loading @@ -117,13 +117,11 @@ int _ipa_read_gen_reg_v3_0(char *buff, int max_len) "IPA_VERSION=0x%x\n" "IPA_COMP_HW_VERSION=0x%x\n" "IPA_ROUTE=0x%x\n" "IPA_FILTER=0x%x\n" "IPA_SHARED_MEM_RESTRICTED=0x%x\n" "IPA_SHARED_MEM_SIZE=0x%x\n", ipa_read_reg(ipa3_ctx->mmio, IPA_VERSION_OFST), ipa_read_reg(ipa3_ctx->mmio, IPA_COMP_HW_VERSION_OFST), ipa_read_reg(ipa3_ctx->mmio, IPA_ROUTE_OFST_v3_0), ipa_read_reg(ipa3_ctx->mmio, IPA_FILTER_OFST_v3_0), ipa_read_reg_field(ipa3_ctx->mmio, IPA_SHARED_MEM_SIZE_OFST_v3_0, IPA_SHARED_MEM_SIZE_SHARED_MEM_BADDR_BMSK_v3_0, Loading
drivers/platform/msm/ipa/ipa_v3/ipa_flt.c +30 −7 Original line number Diff line number Diff line Loading @@ -1068,6 +1068,18 @@ static int __ipa_validate_flt_rule(const struct ipa_flt_rule *rule, } } if (rule->rule_id) { if (rule->rule_id >= IPA_RULE_ID_MIN_VAL && rule->rule_id <= IPA_RULE_ID_MAX_VAL) { IPAERR("invalid rule_id provided 0x%x\n" "rule_id 0x%x - 0x%x are auto generated\n", rule->rule_id, IPA_RULE_ID_MIN_VAL, IPA_RULE_ID_MAX_VAL); goto error; } } return 0; error: Loading @@ -1090,12 +1102,16 @@ static int __ipa_create_flt_entry(struct ipa3_flt_entry **entry, (*entry)->cookie = IPA_COOKIE; (*entry)->rt_tbl = rt_tbl; (*entry)->tbl = tbl; if (rule->rule_id) { id = rule->rule_id; } else { id = ipa3_alloc_rule_id(&tbl->rule_ids); if (id < 0) { IPAERR("failed to allocate rule id\n"); WARN_ON(1); goto rule_id_fail; } } (*entry)->rule_id = id; return 0; Loading Loading @@ -1221,6 +1237,9 @@ static int __ipa_del_flt_rule(u32 rule_hdl) IPADBG("del flt rule rule_cnt=%d rule_id=%d\n", entry->tbl->rule_cnt, entry->rule_id); entry->cookie = 0; /* if rule id was allocated from idr, remove it */ if (entry->rule_id >= IPA_RULE_ID_MIN_VAL && entry->rule_id <= IPA_RULE_ID_MAX_VAL) idr_remove(&entry->tbl->rule_ids, entry->rule_id); kmem_cache_free(ipa3_ctx->flt_rule_cache, entry); Loading Loading @@ -1632,7 +1651,11 @@ int ipa3_reset_flt(enum ipa_ip_type ip) entry->tbl->rule_cnt--; if (entry->rt_tbl) entry->rt_tbl->ref_cnt--; idr_remove(&entry->tbl->rule_ids, entry->rule_id); /* if rule id was allocated from idr, remove it */ if (entry->rule_id >= IPA_RULE_ID_MIN_VAL && entry->rule_id <= IPA_RULE_ID_MAX_VAL) idr_remove(&entry->tbl->rule_ids, entry->rule_id); entry->cookie = 0; id = entry->id; kmem_cache_free(ipa3_ctx->flt_rule_cache, entry); Loading
drivers/platform/msm/ipa/ipa_v3/ipa_i.h +4 −3 Original line number Diff line number Diff line Loading @@ -155,8 +155,8 @@ #define IPA_RULE_MAX_PRIORITY (0) #define IPA_RULE_MIN_PRIORITY (1023) #define IPA_RULE_ID_MIN_VAL (0) #define IPA_RULE_ID_MAX_VAL (1022) #define IPA_RULE_ID_MIN_VAL (0x01) #define IPA_RULE_ID_MAX_VAL (0x1FF) #define IPA_RULE_ID_RULE_MISS (0x3FF) #define IPA_HDR_PROC_CTX_TABLE_ALIGNMENT_BYTE 8 Loading Loading @@ -208,7 +208,7 @@ struct ipa3_mem_buffer { * @tbl: filter table * @rt_tbl: routing table * @hw_len: entry's size * @id: rule handle - globaly unique * @id: rule handle - globally unique * @prio: rule 10bit priority which defines the order of the rule * among other rules at the same integrated table * @rule_id: rule 10bit ID to be returned in packet status Loading Loading @@ -2021,5 +2021,6 @@ int ipa3_release_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info); int ipa3_create_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info); int ipa3_set_flt_tuple_mask(int pipe_idx, struct ipa3_hash_tuple *tuple); int ipa3_set_rt_tuple_mask(int tbl_idx, struct ipa3_hash_tuple *tuple); void ipa3_set_resorce_groups_min_max_limits(void); #endif /* _IPA3_I_H_ */
drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c +70 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #include "ipa_i.h" #define INTERRUPT_WORKQUEUE_NAME "ipa_interrupt_wq" #define DIS_SUSPEND_INTERRUPT_TIMEOUT 5 struct ipa3_interrupt_info { ipa_irq_handler_t handler; Loading @@ -32,6 +33,14 @@ static struct ipa3_interrupt_info ipa_interrupt_to_cb[IPA_IRQ_MAX]; static struct workqueue_struct *ipa_interrupt_wq; static u32 ipa_ee; static void ipa3_tx_suspend_interrupt_wa(void); static void ipa3_enable_tx_suspend_wa(struct work_struct *work); static DECLARE_DELAYED_WORK(dwork_en_suspend_int, ipa3_enable_tx_suspend_wa); static spinlock_t suspend_wa_lock; static void ipa3_process_interrupts(void); static void ipa3_interrupt_defer(struct work_struct *work); static DECLARE_WORK(ipa3_interrupt_defer_work, ipa3_interrupt_defer); Loading Loading @@ -79,6 +88,8 @@ static int ipa3_handle_interrupt(enum ipa_irq_type interrupt) switch (interrupt) { case IPA_TX_SUSPEND_IRQ: IPADBG("processing TX_SUSPEND interrupt work-around\n"); ipa3_tx_suspend_interrupt_wa(); suspend_data = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_SUSPEND_INFO_EE_n_ADDR(ipa_ee)); if (!ipa3_is_valid_ep(suspend_data)) Loading Loading @@ -126,13 +137,62 @@ fail_alloc_work: return res; } static void ipa3_enable_tx_suspend_wa(struct work_struct *work) { u32 en; u32 suspend_bmask; IPADBG("Enter\n"); /* make sure ipa hw is clocked on*/ ipa3_inc_client_enable_clks(); en = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee)); suspend_bmask = 1 << IPA_TX_SUSPEND_IRQ; /*enable TX_SUSPEND_IRQ*/ en |= suspend_bmask; IPADBG("enable TX_SUSPEND_IRQ, IPA_IRQ_EN_EE reg, write val = %u\n" , en); ipa_write_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee), en); ipa3_process_interrupts(); ipa3_dec_client_disable_clks(); IPADBG("Exit\n"); } static void ipa3_tx_suspend_interrupt_wa(void) { u32 val; u32 suspend_bmask; IPADBG("Enter\n"); /*disable TX_SUSPEND_IRQ*/ val = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee)); suspend_bmask = 1 << IPA_TX_SUSPEND_IRQ; val &= ~suspend_bmask; IPADBG("Disabling TX_SUSPEND_IRQ, write val: %u to IPA_IRQ_EN_EE reg\n", val); ipa_write_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee), val); IPADBG(" processing suspend interrupt work-around, delayed work\n"); queue_delayed_work(ipa_interrupt_wq, &dwork_en_suspend_int, msecs_to_jiffies(DIS_SUSPEND_INTERRUPT_TIMEOUT)); IPADBG("Exit\n"); } static void ipa3_process_interrupts(void) { u32 reg; u32 bmsk; u32 i = 0; u32 en; unsigned long flags; IPADBG("Enter\n"); spin_lock_irqsave(&suspend_wa_lock, flags); en = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee)); reg = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_STTS_EE_n_ADDR(ipa_ee)); while (en & reg) { Loading @@ -146,7 +206,14 @@ static void ipa3_process_interrupts(void) IPA_IRQ_CLR_EE_n_ADDR(ipa_ee), reg); reg = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_STTS_EE_n_ADDR(ipa_ee)); /* since the suspend interrupt HW bug we must * read again the EN register, otherwise the while is endless */ en = ipa_read_reg(ipa3_ctx->mmio, IPA_IRQ_EN_EE_n_ADDR(ipa_ee)); } spin_unlock_irqrestore(&suspend_wa_lock, flags); IPADBG("Exit\n"); } static void ipa3_interrupt_defer(struct work_struct *work) Loading @@ -162,6 +229,7 @@ static irqreturn_t ipa3_isr(int irq, void *ctxt) { unsigned long flags; IPADBG("Enter\n"); /* defer interrupt handling in case IPA is not clocked on */ if (ipa3_active_clients_trylock(&flags) == 0) { IPADBG("defer interrupt processing\n"); Loading @@ -176,6 +244,7 @@ static irqreturn_t ipa3_isr(int irq, void *ctxt) } ipa3_process_interrupts(); IPADBG("Exit\n"); bail: ipa3_active_clients_trylock_unlock(&flags); Loading Loading @@ -293,5 +362,6 @@ int ipa3_interrupts_init(u32 ipa_irq, u32 ee, struct device *ipa_dev) else IPADBG("IPA IRQ wakeup enabled irq=%d\n", ipa_irq); spin_lock_init(&suspend_wa_lock); return 0; }