qcacmn: Fix for crash during unload of driver modules

Cleanup usage of irq_request_done flag. This flag is
set after registering irq. Irq register is skipped for emulation.
Setting this flag here causes detach path to release
irq even though it was not registered. Add new bitmap
ce_register_irq_done to track CE irqs.

Change-Id: I84cb4463b8ad51f22cb17c55dab36a398ccbaef0
CRs-Fixed: 1097695
This commit is contained in:
Kiran Venkatappa 2016-12-20 11:32:06 +05:30 • committed by qcabuildsw
commit a17e5e546f
6 changed files with 14 additions and 8 deletions

View file

@ -2178,7 +2178,6 @@ void hif_unconfig_ce(struct hif_softc *hif_sc)
pipe_info = &hif_state->pipe_info[pipe_num];
if (pipe_info->ce_hdl) {
ce_unregister_irq(hif_state, (1 << pipe_num));
hif_sc->request_irq_done = false;
ce_fini(pipe_info->ce_hdl);
pipe_info->ce_hdl = NULL;
pipe_info->buf_sz = 0;
@ -2305,7 +2304,6 @@ int hif_config_ce(struct hif_softc *scn)
}
ce_tasklet_init(hif_state, (1 << pipe_num));
ce_register_irq(hif_state, (1 << pipe_num));
scn->request_irq_done = true;
}
if (athdiag_procfs_init(scn) != 0) {

View file

@ -144,6 +144,7 @@ struct HIF_CE_state {
qdf_timer_t sleep_timer;
bool sleep_timer_init;
qdf_time_t sleep_ticks;
uint32_t ce_register_irq_done;
struct CE_pipe_config *target_ce_config;
struct CE_attr *host_ce_config;

View file

@ -557,6 +557,8 @@ QDF_STATUS ce_unregister_irq(struct HIF_CE_state *hif_ce_state, uint32_t mask)
__func__, ret);
/* this is not fatal, continue */
/* filter mask to free only for ce's with irq registered */
mask &= hif_ce_state->ce_register_irq_done;
for (id = 0; id < ce_count; id++) {
if ((mask & (1 << id)) && hif_ce_state->tasklets[id].inited) {
ret = pld_ce_free_irq(scn->qdf_dev->dev, id,
@ -567,6 +569,8 @@ QDF_STATUS ce_unregister_irq(struct HIF_CE_state *hif_ce_state, uint32_t mask)
__func__, id, ret);
}
}
hif_ce_state->ce_register_irq_done &= ~mask;
return QDF_STATUS_SUCCESS;
}
/**
@ -607,6 +611,7 @@ QDF_STATUS ce_register_irq(struct HIF_CE_state *hif_ce_state, uint32_t mask)
}
}
}
hif_ce_state->ce_register_irq_done |= done_mask;
return QDF_STATUS_SUCCESS;
}

View file

@ -2593,6 +2593,8 @@ void hif_pci_nointrs(struct hif_softc *scn)
struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
ce_unregister_irq(hif_state, CE_ALL_BITMAP);
if (scn->request_irq_done == false)
return;
@ -2609,8 +2611,8 @@ void hif_pci_nointrs(struct hif_softc *scn)
platform_device pdev doesn't have an irq field */
free_irq(sc->irq, sc);
}
ce_unregister_irq(hif_state, 0xfff);
scn->request_irq_done = false;
}
/**

View file

@ -557,6 +557,8 @@ void hif_ahb_nointrs(struct hif_softc *scn)
struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
ce_unregister_irq(hif_state, CE_ALL_BITMAP);
if (scn->request_irq_done == false)
return;
@ -576,8 +578,8 @@ void hif_ahb_nointrs(struct hif_softc *scn)
}
}
}
ce_unregister_irq(hif_state, CE_ALL_BITMAP);
scn->request_irq_done = false;
}
/**

View file

@ -309,10 +309,8 @@ void hif_snoc_disable_bus(struct hif_softc *scn)
void hif_snoc_nointrs(struct hif_softc *scn)
{
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
if (scn->request_irq_done) {
ce_unregister_irq(hif_state, 0xfff);
scn->request_irq_done = false;
}
ce_unregister_irq(hif_state, CE_ALL_BITMAP);
}
/**