diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 20925f10d1..edeae7a1d2 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -852,6 +852,8 @@ uint32_t hif_register_ext_group_int_handler(struct hif_opaque_softc *hif_ctx, uint32_t numirq, uint32_t irq[], ext_intr_handler handler, void *context); +uint32_t hif_configure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx); + void hif_update_pipe_callback(struct hif_opaque_softc *osc, u_int8_t pipeid, struct hif_msg_callbacks *callbacks); diff --git a/hif/src/dispatcher/ahb_api.h b/hif/src/dispatcher/ahb_api.h index 75f1506484..1a05196866 100644 --- a/hif/src/dispatcher/ahb_api.h +++ b/hif/src/dispatcher/ahb_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -46,5 +46,6 @@ int hif_ahb_enable_radio(struct hif_pci_softc *sc, struct platform_device *pdev, const struct platform_device_id *id); int hif_ahb_configure_irq(struct hif_pci_softc *sc); +int hif_ahb_configure_grp_irq(struct hif_softc *scn); #endif diff --git a/hif/src/dispatcher/dummy.c b/hif/src/dispatcher/dummy.c index b83bf9aa06..dbf061ef89 100644 --- a/hif/src/dispatcher/dummy.c +++ b/hif/src/dispatcher/dummy.c @@ -261,6 +261,18 @@ void hif_dummy_irq_disable(struct hif_softc *hif_sc, int irq_id) */ void hif_dummy_grp_irq_disable(struct hif_softc *hif_sc, uint32_t grp_id) {} + +/** + * hif_dummy_grp_irq_configure - dummy call + * hif_ctx: hif context + * + * Return: none + */ +int hif_dummy_grp_irq_configure(struct hif_softc *hif_sc) +{ + return 0; +} + /** * hif_dummy_dump_registers - dummy call * hif_sc: hif context diff --git a/hif/src/dispatcher/dummy.h b/hif/src/dispatcher/dummy.h index 0bafe8a391..e3e9773210 100644 --- a/hif/src/dispatcher/dummy.h +++ b/hif/src/dispatcher/dummy.h @@ -49,6 +49,7 @@ void hif_dummy_irq_enable(struct hif_softc *hif_sc, int irq_id); void hif_dummy_irq_disable(struct hif_softc *hif_sc, int irq_id); void hif_dummy_grp_irq_enable(struct hif_softc *hif_sc, uint32_t grp_id); void hif_dummy_grp_irq_disable(struct hif_softc *hif_sc, uint32_t grp_id); +int hif_dummy_grp_irq_configure(struct hif_softc *hif_sc); int hif_dummy_dump_registers(struct hif_softc *hif_sc); void hif_dummy_dump_target_memory(struct hif_softc *hif_sc, void *ramdump_base, uint32_t address, uint32_t size); diff --git a/hif/src/dispatcher/multibus.c b/hif/src/dispatcher/multibus.c index 4a8f7e7705..a922ed5746 100644 --- a/hif/src/dispatcher/multibus.c +++ b/hif/src/dispatcher/multibus.c @@ -67,6 +67,7 @@ static void hif_intialize_default_ops(struct hif_softc *hif_sc) bus_ops->hif_grp_irq_disable = &hif_dummy_grp_irq_disable; bus_ops->hif_grp_irq_enable = &hif_dummy_grp_irq_enable; bus_ops->hif_map_ce_to_irq = &hif_dummy_map_ce_to_irq; + bus_ops->hif_grp_irq_configure = &hif_dummy_grp_irq_configure; } #define NUM_OPS (sizeof(struct hif_bus_ops) / sizeof(void *)) @@ -322,6 +323,11 @@ void hif_grp_irq_disable(struct hif_softc *hif_sc, uint32_t grp_id) hif_sc->bus_ops.hif_grp_irq_disable(hif_sc, grp_id); } +int hif_grp_irq_configure(struct hif_softc *hif_sc) +{ + return hif_sc->bus_ops.hif_grp_irq_configure(hif_sc); +} + int hif_dump_registers(struct hif_opaque_softc *hif_hdl) { struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_hdl); diff --git a/hif/src/dispatcher/multibus.h b/hif/src/dispatcher/multibus.h index 7d7768d7c1..eb5d77f844 100644 --- a/hif/src/dispatcher/multibus.h +++ b/hif/src/dispatcher/multibus.h @@ -66,6 +66,7 @@ struct hif_bus_ops { void (*hif_grp_irq_disable)(struct hif_softc *hif_sc, uint32_t grp_id); void (*hif_irq_enable)(struct hif_softc *hif_sc, int ce_id); void (*hif_grp_irq_enable)(struct hif_softc *hif_sc, uint32_t grp_id); + int (*hif_grp_irq_configure)(struct hif_softc *hif_sc); int (*hif_dump_registers)(struct hif_softc *hif_sc); void (*hif_dump_target_memory)(struct hif_softc *hif_sc, void *ramdump_base, diff --git a/hif/src/dispatcher/multibus_ahb.c b/hif/src/dispatcher/multibus_ahb.c index d67c9ec697..005e7f5bf0 100644 --- a/hif/src/dispatcher/multibus_ahb.c +++ b/hif/src/dispatcher/multibus_ahb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -68,6 +68,7 @@ QDF_STATUS hif_initialize_ahb_ops(struct hif_bus_ops *bus_ops) &hif_dummy_disable_power_management; bus_ops->hif_grp_irq_disable = &hif_ahb_grp_irq_disable; bus_ops->hif_grp_irq_enable = &hif_ahb_grp_irq_enable; + bus_ops->hif_grp_irq_configure = &hif_ahb_configure_grp_irq; return QDF_STATUS_SUCCESS; } diff --git a/hif/src/dispatcher/multibus_pci.c b/hif/src/dispatcher/multibus_pci.c index da4caedac9..e65763e35e 100644 --- a/hif/src/dispatcher/multibus_pci.c +++ b/hif/src/dispatcher/multibus_pci.c @@ -89,6 +89,7 @@ QDF_STATUS hif_initialize_pci_ops(struct hif_softc *hif_sc) &hif_pci_clear_stats; bus_ops->hif_grp_irq_disable = &hif_dummy_grp_irq_disable; bus_ops->hif_grp_irq_enable = &hif_dummy_grp_irq_enable; + bus_ops->hif_grp_irq_configure = &hif_dummy_grp_irq_configure; /* default to legacy mapping handler; override as needed */ bus_ops->hif_map_ce_to_irq = &hif_pci_legacy_map_ce_to_irq; diff --git a/hif/src/dispatcher/multibus_sdio.c b/hif/src/dispatcher/multibus_sdio.c index 1f957c4bfa..6c35963685 100644 --- a/hif/src/dispatcher/multibus_sdio.c +++ b/hif/src/dispatcher/multibus_sdio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -66,6 +66,7 @@ QDF_STATUS hif_initialize_sdio_ops(struct hif_softc *hif_sc) &hif_dummy_disable_power_management; bus_ops->hif_grp_irq_disable = &hif_dummy_grp_irq_disable; bus_ops->hif_grp_irq_enable = &hif_dummy_grp_irq_enable; + bus_ops->hif_grp_irq_configure = &hif_dummy_grp_irq_configure; return QDF_STATUS_SUCCESS; } diff --git a/hif/src/dispatcher/multibus_snoc.c b/hif/src/dispatcher/multibus_snoc.c index b0f4358e3e..bd9f291d7a 100644 --- a/hif/src/dispatcher/multibus_snoc.c +++ b/hif/src/dispatcher/multibus_snoc.c @@ -84,6 +84,7 @@ QDF_STATUS hif_initialize_snoc_ops(struct hif_bus_ops *bus_ops) bus_ops->hif_grp_irq_disable = &hif_dummy_grp_irq_disable; bus_ops->hif_grp_irq_enable = &hif_dummy_grp_irq_enable; bus_ops->hif_map_ce_to_irq = &hif_snoc_map_ce_to_irq; + bus_ops->hif_grp_irq_configure = &hif_dummy_grp_irq_configure; return QDF_STATUS_SUCCESS; } diff --git a/hif/src/dispatcher/multibus_usb.c b/hif/src/dispatcher/multibus_usb.c index 0f3af6007c..f4cee6f0f9 100644 --- a/hif/src/dispatcher/multibus_usb.c +++ b/hif/src/dispatcher/multibus_usb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -64,6 +64,7 @@ QDF_STATUS hif_initialize_usb_ops(struct hif_bus_ops *bus_ops) &hif_dummy_disable_power_management; bus_ops->hif_set_bundle_mode = hif_usb_set_bundle_mode; bus_ops->hif_bus_reset_resume = hif_usb_bus_reset_resume; + bus_ops->hif_grp_irq_configure = &hif_dummy_grp_irq_configure; return QDF_STATUS_SUCCESS; } diff --git a/hif/src/hif_io32.h b/hif/src/hif_io32.h index 8c1453f49f..96a3821714 100644 --- a/hif/src/hif_io32.h +++ b/hif/src/hif_io32.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -106,5 +106,6 @@ void hif_irq_enable(struct hif_softc *scn, int irq_id); void hif_irq_disable(struct hif_softc *scn, int irq_id); void hif_grp_irq_enable(struct hif_softc *scn, uint32_t grp_id); void hif_grp_irq_disable(struct hif_softc *scn, uint32_t grp_id); +int hif_grp_irq_configure(struct hif_softc *scn); #endif /* __HIF_IO32_H__ */ diff --git a/hif/src/hif_main.c b/hif/src/hif_main.c index c8847c36b5..b938ba2b27 100644 --- a/hif/src/hif_main.c +++ b/hif/src/hif_main.c @@ -1209,8 +1209,8 @@ uint32_t hif_register_ext_group_int_handler(struct hif_opaque_softc *hif_ctx, struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); struct hif_ext_group_entry *hif_ext_group; - if (scn->hif_init_done) { - HIF_ERROR("%s Called after HIF initialization \n", __func__); + if (scn->ext_grp_irq_configured) { + HIF_ERROR("%s Called after ext grp irq configured\n", __func__); return QDF_STATUS_E_FAILURE; } @@ -1238,6 +1238,28 @@ uint32_t hif_register_ext_group_int_handler(struct hif_opaque_softc *hif_ctx, return QDF_STATUS_SUCCESS; } +/** + * hif_configure_ext_group_interrupts() - API to configure external group + * interrpts + * @hif_ctx : HIF Context + * + * Return: status + */ +uint32_t hif_configure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + + if (scn->ext_grp_irq_configured) { + HIF_ERROR("%s Called after ext grp irq configured\n", __func__); + return QDF_STATUS_E_FAILURE; + } + + hif_grp_irq_configure(scn); + scn->ext_grp_irq_configured = true; + + return QDF_STATUS_SUCCESS; +} + /** * hif_ext_grp_tasklet() - grp tasklet * data: context diff --git a/hif/src/hif_main.h b/hif/src/hif_main.h index 481440ddd3..b70a46c9ef 100644 --- a/hif/src/hif_main.h +++ b/hif/src/hif_main.h @@ -142,6 +142,7 @@ struct hif_softc { qdf_device_t qdf_dev; bool hif_init_done; bool request_irq_done; + bool ext_grp_irq_configured; /* Packet statistics */ struct hif_ce_stats pkt_stats; enum hif_target_status target_status; diff --git a/hif/src/snoc/if_ahb.c b/hif/src/snoc/if_ahb.c index ee1ce6ff5f..00cb7e191e 100644 --- a/hif/src/snoc/if_ahb.c +++ b/hif/src/snoc/if_ahb.c @@ -250,9 +250,8 @@ int hif_ahb_configure_irq(struct hif_pci_softc *sc) struct hif_softc *scn = HIF_GET_SOFTC(sc); struct platform_device *pdev = (struct platform_device *)sc->pdev; struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); - struct hif_ext_group_entry *hif_ext_group; int irq = 0; - int i, j; + int i; /* configure per CE interrupts */ for (i = 0; i < scn->ce_count; i++) { @@ -270,6 +269,20 @@ int hif_ahb_configure_irq(struct hif_pci_softc *sc) hif_ahb_irq_enable(scn, i); } +end: + return ret; +} + +int hif_ahb_configure_grp_irq(struct hif_softc *scn) +{ + int ret = 0; + struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn); + struct platform_device *pdev = (struct platform_device *)sc->pdev; + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct hif_ext_group_entry *hif_ext_group; + int irq = 0; + int i, j; + /* configure external interrupts */ for (i = 0; i < hif_state->hif_num_extgroup; i++) { @@ -304,6 +317,25 @@ end: return ret; } +void hif_ahb_deconfigure_grp_irq(struct hif_softc *scn) +{ + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct hif_ext_group_entry *hif_ext_group; + int i, j; + + /* configure external interrupts */ + for (i = 0; i < hif_state->hif_num_extgroup; i++) { + hif_ext_group = &hif_state->hif_ext_group[i]; + if (hif_ext_group->inited == true) { + hif_ext_group->inited = false; + for (j = 0; j < hif_ext_group->numirq; j++) { + free_irq(ic_irqnum[hif_ext_group->irq[i]], + hif_ext_group); + } + } + } +} + irqreturn_t hif_ahb_interrupt_handler(int irq, void *context) { struct ce_tasklet_entry *tasklet_entry = context; @@ -581,6 +613,7 @@ void hif_ahb_nointrs(struct hif_softc *scn) free_irq(ic_irqnum[HIF_IC_CE0_IRQ_OFFSET + i], &hif_state->tasklets[i]); } + hif_ahb_deconfigure_grp_irq(scn); } } scn->request_irq_done = false;