@@ -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)
@@ -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);
}