From cf4ce59b3b70238352c7f1729f0f7223214828ad Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 20 Sep 2024 01:46:19 +0000 Subject: [PATCH] rtl88x2CE_WiFi_linux add concurrent mode --- kernel/kernel/irq/chip.c | 205 ++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 161 insertions(+), 44 deletions(-) diff --git a/kernel/kernel/irq/chip.c b/kernel/kernel/irq/chip.c index 2f4b9cd..afef871 100644 --- a/kernel/kernel/irq/chip.c +++ b/kernel/kernel/irq/chip.c @@ -282,7 +282,7 @@ } } if (resend) - check_irq_resend(desc); + check_irq_resend(desc, false); return ret; } @@ -674,16 +674,6 @@ } EXPORT_SYMBOL_GPL(handle_level_irq); -#ifdef CONFIG_IRQ_PREFLOW_FASTEOI -static inline void preflow_handler(struct irq_desc *desc) -{ - if (desc->preflow_handler) - desc->preflow_handler(&desc->irq_data); -} -#else -static inline void preflow_handler(struct irq_desc *desc) { } -#endif - static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip) { if (!(desc->istate & IRQS_ONESHOT)) { @@ -739,7 +729,6 @@ if (desc->istate & IRQS_ONESHOT) mask_irq(desc); - preflow_handler(desc); handle_irq_event(desc); cond_unmask_eoi_irq(desc, chip); @@ -752,6 +741,39 @@ raw_spin_unlock(&desc->lock); } EXPORT_SYMBOL_GPL(handle_fasteoi_irq); + +/** + * handle_fasteoi_nmi - irq handler for NMI interrupt lines + * @desc: the interrupt description structure for this irq + * + * A simple NMI-safe handler, considering the restrictions + * from request_nmi. + * + * Only a single callback will be issued to the chip: an ->eoi() + * call when the interrupt has been serviced. This enables support + * for modern forms of interrupt handlers, which handle the flow + * details in hardware, transparently. + */ +void handle_fasteoi_nmi(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct irqaction *action = desc->action; + unsigned int irq = irq_desc_get_irq(desc); + irqreturn_t res; + + __kstat_incr_irqs_this_cpu(desc); + + trace_irq_handler_entry(irq, action); + /* + * NMIs cannot be shared, there is only one action. + */ + res = action->handler(irq, action->dev_id); + trace_irq_handler_exit(irq, action, res); + + if (chip->irq_eoi) + chip->irq_eoi(&desc->irq_data); +} +EXPORT_SYMBOL_GPL(handle_fasteoi_nmi); /** * handle_edge_irq - edge type IRQ handler @@ -804,7 +826,7 @@ /* * When another irq arrived while we were handling * one, we could have masked the irq. - * Renable it, if it was not disabled in meantime. + * Reenable it, if it was not disabled in meantime. */ if (unlikely(desc->istate & IRQS_PENDING)) { if (!irqd_irq_disabled(&desc->irq_data) && @@ -940,6 +962,58 @@ chip->irq_eoi(&desc->irq_data); } +/** + * handle_percpu_devid_fasteoi_ipi - Per CPU local IPI handler with per cpu + * dev ids + * @desc: the interrupt description structure for this irq + * + * The biggest difference with the IRQ version is that the interrupt is + * EOIed early, as the IPI could result in a context switch, and we need to + * make sure the IPI can fire again. We also assume that the arch code has + * registered an action. If not, we are positively doomed. + */ +void handle_percpu_devid_fasteoi_ipi(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct irqaction *action = desc->action; + unsigned int irq = irq_desc_get_irq(desc); + irqreturn_t res; + + __kstat_incr_irqs_this_cpu(desc); + + if (chip->irq_eoi) + chip->irq_eoi(&desc->irq_data); + + trace_irq_handler_entry(irq, action); + res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id)); + trace_irq_handler_exit(irq, action, res); +} + +/** + * handle_percpu_devid_fasteoi_nmi - Per CPU local NMI handler with per cpu + * dev ids + * @desc: the interrupt description structure for this irq + * + * Similar to handle_fasteoi_nmi, but handling the dev_id cookie + * as a percpu pointer. + */ +void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct irqaction *action = desc->action; + unsigned int irq = irq_desc_get_irq(desc); + irqreturn_t res; + + __kstat_incr_irqs_this_cpu(desc); + + trace_irq_handler_entry(irq, action); + res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id)); + trace_irq_handler_exit(irq, action, res); + + if (chip->irq_eoi) + chip->irq_eoi(&desc->irq_data); +} + static void __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, int is_chained, const char *name) @@ -961,7 +1035,7 @@ break; /* * Bail out if the outer chip is not set up - * and the interrrupt supposed to be started + * and the interrupt supposed to be started * right away. */ if (WARN_ON(is_chained)) @@ -1051,7 +1125,8 @@ } EXPORT_SYMBOL_GPL(irq_set_chip_and_handler_name); -void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) +void __irq_modify_status(unsigned int irq, unsigned long clr, + unsigned long set, unsigned long mask) { unsigned long flags, trigger, tmp; struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0); @@ -1065,7 +1140,9 @@ */ WARN_ON_ONCE(!desc->depth && (set & _IRQ_NOAUTOEN)); - irq_settings_clr_and_set(desc, clr, set); + /* Warn when trying to clear or set a bit disallowed by the mask */ + WARN_ON((clr | set) & ~mask); + __irq_settings_clr_and_set(desc, clr, set, mask); trigger = irqd_get_trigger_type(&desc->irq_data); @@ -1087,6 +1164,11 @@ irqd_set(&desc->irq_data, trigger); irq_put_desc_unlock(desc, flags); +} + +void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) +{ + __irq_modify_status(irq, clr, set, _IRQF_MODIFY_MASK); } EXPORT_SYMBOL_GPL(irq_modify_status); @@ -1191,7 +1273,6 @@ /* Start handling the irq */ desc->irq_data.chip->irq_ack(&desc->irq_data); - preflow_handler(desc); handle_irq_event(desc); cond_unmask_eoi_irq(desc, chip); @@ -1241,7 +1322,6 @@ if (desc->istate & IRQS_ONESHOT) mask_irq(desc); - preflow_handler(desc); handle_irq_event(desc); cond_unmask_eoi_irq(desc, chip); @@ -1258,48 +1338,48 @@ #endif /* CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS */ /** - * irq_chip_set_parent_state - set the state of a parent interrupt. - * @data: Pointer to interrupt specific data - * @which: State to be restored (one of IRQCHIP_STATE_*) - * @val: Value corresponding to @which + * irq_chip_set_parent_state - set the state of a parent interrupt. * + * @data: Pointer to interrupt specific data + * @which: State to be restored (one of IRQCHIP_STATE_*) + * @val: Value corresponding to @which + * + * Conditional success, if the underlying irqchip does not implement it. */ int irq_chip_set_parent_state(struct irq_data *data, enum irqchip_irq_state which, bool val) { data = data->parent_data; - if (!data) + + if (!data || !data->chip->irq_set_irqchip_state) return 0; - if (data->chip->irq_set_irqchip_state) - return data->chip->irq_set_irqchip_state(data, which, val); - - return 0; + return data->chip->irq_set_irqchip_state(data, which, val); } -EXPORT_SYMBOL(irq_chip_set_parent_state); +EXPORT_SYMBOL_GPL(irq_chip_set_parent_state); /** - * irq_chip_get_parent_state - get the state of a parent interrupt. - * @data: Pointer to interrupt specific data - * @which: one of IRQCHIP_STATE_* the caller wants to know - * @state: a pointer to a boolean where the state is to be stored + * irq_chip_get_parent_state - get the state of a parent interrupt. * + * @data: Pointer to interrupt specific data + * @which: one of IRQCHIP_STATE_* the caller wants to know + * @state: a pointer to a boolean where the state is to be stored + * + * Conditional success, if the underlying irqchip does not implement it. */ int irq_chip_get_parent_state(struct irq_data *data, enum irqchip_irq_state which, bool *state) { data = data->parent_data; - if (!data) + + if (!data || !data->chip->irq_get_irqchip_state) return 0; - if (data->chip->irq_get_irqchip_state) - return data->chip->irq_get_irqchip_state(data, which, state); - - return 0; + return data->chip->irq_get_irqchip_state(data, which, state); } -EXPORT_SYMBOL(irq_chip_get_parent_state); +EXPORT_SYMBOL_GPL(irq_chip_get_parent_state); /** * irq_chip_enable_parent - Enable the parent interrupt (defaults to unmask if @@ -1352,6 +1432,17 @@ data->chip->irq_mask(data); } EXPORT_SYMBOL_GPL(irq_chip_mask_parent); + +/** + * irq_chip_mask_ack_parent - Mask and acknowledge the parent interrupt + * @data: Pointer to interrupt specific data + */ +void irq_chip_mask_ack_parent(struct irq_data *data) +{ + data = data->parent_data; + data->chip->irq_mask_ack(data); +} +EXPORT_SYMBOL_GPL(irq_chip_mask_ack_parent); /** * irq_chip_unmask_parent - Unmask the parent interrupt @@ -1443,7 +1534,6 @@ return -ENOSYS; } EXPORT_SYMBOL_GPL(irq_chip_set_vcpu_affinity_parent); - /** * irq_chip_set_wake_parent - Set/reset wake-up on the parent interrupt * @data: Pointer to interrupt specific data @@ -1464,6 +1554,34 @@ return -ENOSYS; } EXPORT_SYMBOL_GPL(irq_chip_set_wake_parent); + +/** + * irq_chip_request_resources_parent - Request resources on the parent interrupt + * @data: Pointer to interrupt specific data + */ +int irq_chip_request_resources_parent(struct irq_data *data) +{ + data = data->parent_data; + + if (data->chip->irq_request_resources) + return data->chip->irq_request_resources(data); + + /* no error on missing optional irq_chip::irq_request_resources */ + return 0; +} +EXPORT_SYMBOL_GPL(irq_chip_request_resources_parent); + +/** + * irq_chip_release_resources_parent - Release resources on the parent interrupt + * @data: Pointer to interrupt specific data + */ +void irq_chip_release_resources_parent(struct irq_data *data) +{ + data = data->parent_data; + if (data->chip->irq_release_resources) + data->chip->irq_release_resources(data); +} +EXPORT_SYMBOL_GPL(irq_chip_release_resources_parent); #endif /** @@ -1477,18 +1595,17 @@ */ int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) { - struct irq_data *pos = NULL; + struct irq_data *pos; -#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY - for (; data; data = data->parent_data) -#endif + for (pos = NULL; !pos && data; data = irqd_get_parent_data(data)) { if (data->chip && data->chip->irq_compose_msi_msg) pos = data; + } + if (!pos) return -ENOSYS; pos->chip->irq_compose_msi_msg(pos, msg); - return 0; } -- Gitblit v1.6.2