From: Nischal Varide <nischal_@xxxxxx> Date: Thu, 12 Feb 2009 13:43:40 -0600 Subject: [PATCH] DSPBRIDGE Workqueue implementation for DVFS This patch will fix the BUG_ON message "Scheduling while atomic" that was seen when enabling DVFS. Signed-off-by: Nischal Varide <nischal_@xxxxxx> --- drivers/dsp/bridge/hw/hw_mbox.c | 2 +- drivers/dsp/bridge/wmd/io_sm.c | 47 +++++++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/drivers/dsp/bridge/hw/hw_mbox.c b/drivers/dsp/bridge/hw/hw_mbox.c index 2c14ade..bc61d64 100644 --- a/drivers/dsp/bridge/hw/hw_mbox.c +++ b/drivers/dsp/bridge/hw/hw_mbox.c @@ -33,7 +33,7 @@ /* width in bits of MBOX Id */ #define HW_MBOX_ID_WIDTH 2 -struct MAILBOX_CONTEXT mboxsetting = {0, 0, 0}; +struct MAILBOX_CONTEXT mboxsetting = {0x4, 0x1, 0x1}; /* Saves the mailbox context */ HW_STATUS HW_MBOX_saveSettings(u32 baseAddress) diff --git a/drivers/dsp/bridge/wmd/io_sm.c b/drivers/dsp/bridge/wmd/io_sm.c index ede25a3..040e87f 100644 --- a/drivers/dsp/bridge/wmd/io_sm.c +++ b/drivers/dsp/bridge/wmd/io_sm.c @@ -111,6 +111,7 @@ /* ----------------------------------- Host OS */ #include <dspbridge/host_os.h> +#include <linux/workqueue.h> #ifndef CONFIG_DISABLE_BRIDGE_PM #ifndef CONFIG_DISABLE_BRIDGE_DVFS #ifndef CONFIG_OMAP3_PM @@ -205,6 +206,7 @@ struct IO_MGR { /* private extnd proc info; mmu setup */ struct MGR_PROCESSOREXTINFO extProcInfo; struct CMM_OBJECT *hCmmMgr; /* Shared Mem Mngr */ + struct work_struct io_workq; /* workqueue */ u32 dQuePowerMbxVal[MAX_PM_REQS]; u32 iQuePowerHead; u32 iQuePowerTail; @@ -223,7 +225,7 @@ struct IO_MGR { static void IO_DispatchChnl(IN struct IO_MGR *pIOMgr, IN OUT struct CHNL_OBJECT *pChnl, u32 iMode); static void IO_DispatchMsg(IN struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr); -static void IO_DispatchPM(IN struct IO_MGR *pIOMgr); +static void IO_DispatchPM(struct work_struct *work); static void NotifyChnlComplete(struct CHNL_OBJECT *pChnl, struct CHNL_IRP *pChirp); static void InputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl, @@ -238,6 +240,8 @@ static u32 ReadData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest, void *pSrc, u32 uSize); static u32 WriteData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest, void *pSrc, u32 uSize); +static struct workqueue_struct *bridge_workqueue; + #ifndef DSP_TRACEBUF_DISABLED void PrintDSPDebugTrace(struct IO_MGR *hIOMgr); #endif @@ -281,6 +285,7 @@ DSP_STATUS WMD_IO_Create(OUT struct IO_MGR **phIOMgr, struct CFG_HOSTRES hostRes; struct CFG_DEVNODE *hDevNode; struct CHNL_MGR *hChnlMgr; + static int ref_count; u32 devType; /* Check DBC requirements: */ DBC_Require(phIOMgr != NULL); @@ -305,12 +310,32 @@ DSP_STATUS WMD_IO_Create(OUT struct IO_MGR **phIOMgr, if (DSP_FAILED(status)) goto func_cont; + /* + * Create a Single Threaded Work Queue + */ + + if (ref_count == 0) + bridge_workqueue = + create_singlethread_workqueue("bridge_work-queue"); + if (bridge_workqueue <= 0) + printk(KERN_ALERT "Bridge workqueue create failed in function \ + %s at line %i", __func__, __LINE__); + /* Allocate IO manager object: */ MEM_AllocObject(pIOMgr, struct IO_MGR, IO_MGRSIGNATURE); if (pIOMgr == NULL) { status = DSP_EMEMORY; goto func_cont; } + + + /* Intializing Work Element */ + if (ref_count == 0) { + INIT_WORK(&pIOMgr->io_workq, (void *)IO_DispatchPM); + ref_count = 1; + } else + PREPARE_WORK(&pIOMgr->io_workq, (void *)IO_DispatchPM); + /* Initialize CHNL_MGR object: */ #ifndef DSP_TRACEBUF_DISABLED pIOMgr->pMsg = NULL; @@ -379,10 +404,12 @@ DSP_STATUS WMD_IO_Destroy(struct IO_MGR *hIOMgr) /* Unplug IRQ: */ /* Disable interrupts from the board: */ if (DSP_SUCCEEDED(DEV_GetWMDContext(hIOMgr->hDevObject, - &hWmdContext))) { + &hWmdContext))) DBC_Assert(hWmdContext); - } + (void)CHNLSM_DisableInterrupt(hWmdContext); + + flush_workqueue(bridge_workqueue); /* Linux function to uninstall ISR */ free_irq(INT_MAIL_MPU_IRQ, (void *)hIOMgr); (void)DPC_Destroy(hIOMgr->hDPC); @@ -950,11 +977,14 @@ static void IO_DispatchMsg(IN struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr) * ======== IO_DispatchPM ======== * Performs I/O dispatch on PM related messages from DSP */ -static void IO_DispatchPM(IN struct IO_MGR *pIOMgr) +static void IO_DispatchPM(struct work_struct *work) { + + struct IO_MGR *pIOMgr = + container_of(work, struct IO_MGR, io_workq); + DSP_STATUS status; u32 pArg[2]; - DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE)); DBG_Trace(DBG_LEVEL7, "IO_DispatchPM: Entering IO_DispatchPM : \n"); @@ -1005,6 +1035,7 @@ static void IO_DispatchPM(IN struct IO_MGR *pIOMgr) pIOMgr->iQuePowerTail = 0; } + } /* @@ -1049,7 +1080,7 @@ void IO_DPC(IN OUT void *pRefData) PrintDSPDebugTrace(pIOMgr); } #endif - IO_DispatchPM(pIOMgr); + #ifndef DSP_TRACEBUF_DISABLED PrintDSPDebugTrace(pIOMgr); #endif @@ -1069,6 +1100,7 @@ irqreturn_t IO_ISR(int irq, IN void *pRefData) DBC_Require(irq == INT_MAIL_MPU_IRQ); DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE)); DBG_Trace(DBG_LEVEL3, "Entering IO_ISR(0x%x)\n", pRefData); + /* Call WMD's CHNLSM_ISR() to see if interrupt is ours, and process. */ if (IO_CALLISR(hIOMgr->hWmdContext, &fSchedDPC, &hIOMgr->wIntrVal)) { { @@ -1080,6 +1112,8 @@ irqreturn_t IO_ISR(int irq, IN void *pRefData) if (hIOMgr->iQuePowerHead >= MAX_PM_REQS) hIOMgr->iQuePowerHead = 0; + queue_work(bridge_workqueue, + &(hIOMgr->io_workq)); } if (hIOMgr->wIntrVal == MBX_DEH_RESET) { DBG_Trace(DBG_LEVEL6, "*** DSP RESET ***\n"); @@ -1139,7 +1173,6 @@ void IO_RequestChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl, void IO_Schedule(struct IO_MGR *pIOMgr) { DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE)); - DPC_Schedule(pIOMgr->hDPC); } -- 1.5.4.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html