diff options
37 files changed, 1042 insertions, 152 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 54c97ee..7d66a6e 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -223,8 +223,8 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ while (1) { - tick_nohz_stop_sched_tick(1); idle_notifier_call_chain(IDLE_START); + tick_nohz_stop_sched_tick(1); while (!need_resched()) { #ifdef CONFIG_HOTPLUG_CPU if (cpu_is_offline(smp_processor_id())) diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 1b83cea..da13f2d 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -120,7 +120,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, } /* Execute ARM wfi */ - omap_sram_idle(); + omap_sram_idle(false); /* Re-allow idle for C1 */ if (state == &dev->states[0]) { diff --git a/arch/arm/mach-omap2/include/mach/omap_fiq_debugger.h b/arch/arm/mach-omap2/include/mach/omap_fiq_debugger.h index c49608e..4378a77 100644 --- a/arch/arm/mach-omap2/include/mach/omap_fiq_debugger.h +++ b/arch/arm/mach-omap2/include/mach/omap_fiq_debugger.h @@ -24,6 +24,7 @@ u32 omap_debug_uart_resume_idle(void); static inline int __init omap_serial_debug_init(int id, bool is_fiq, bool is_high_prio_irq, struct omap_device_pad *pads, int num_pads) { + return 0; } static inline u32 omap_debug_uart_resume_idle(void) diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 3862ccd..c9da6b9 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -17,7 +17,7 @@ extern void *omap3_secure_ram_storage; extern void omap3_pm_off_mode_enable(int); -extern void omap_sram_idle(void); +extern void omap_sram_idle(bool suspend); extern int omap3_can_sleep(void); extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state); extern int omap3_idle_init(void); diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 535480f..cb1e8d8 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -328,7 +328,7 @@ static void restore_table_entry(void) set_cr(control_reg_value); } -void omap_sram_idle(void) +void omap_sram_idle(bool suspend) { /* Variable to tell what needs to be saved and restored * in omap_sram_idle*/ @@ -386,7 +386,7 @@ void omap_sram_idle(void) /* PER */ if (per_next_state < PWRDM_POWER_ON) { per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0; - omap2_gpio_prepare_for_idle(per_going_off); + omap2_gpio_prepare_for_idle(per_going_off, suspend); } /* CORE */ @@ -485,7 +485,7 @@ static void omap3_pm_idle(void) trace_power_start(POWER_CSTATE, 1, smp_processor_id()); trace_cpu_idle(1, smp_processor_id()); - omap_sram_idle(); + omap_sram_idle(false); trace_power_end(smp_processor_id()); trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id()); @@ -518,7 +518,7 @@ static int omap3_pm_suspend(void) omap3_intc_suspend(); - omap_sram_idle(); + omap_sram_idle(true); restore: /* Restore next_pwrsts */ diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index 78bbf4a..329f37a 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -76,6 +76,8 @@ static struct voltagedomain *mpu_voltdm, *iva_voltdm, *core_voltdm; static struct clockdomain *tesla_clkdm; static struct powerdomain *tesla_pwrdm; +static struct clockdomain *emif_clkdm, *mpuss_clkdm; + /* Yet un-named erratum which requires AUTORET to be disabled for IVA PD */ #define OMAP4_PM_ERRATUM_IVA_AUTO_RET_iXXX BIT(1) /* @@ -85,6 +87,22 @@ static struct powerdomain *tesla_pwrdm; */ #define OMAP4_PM_ERRATUM_HSI_SWAKEUP_iXXX BIT(2) +/* Dynamic dependendency Cannot be enabled due to i688 erratum ID for 443x */ +#define OMAP4_PM_ERRATUM_MPU_EMIF_NO_DYNDEP_i688 BIT(3) +/* + * Dynamic dependendency Cannot be enabled due to i688 erratum ID for above 443x + * NOTE: this is NOT YET a confirmed erratum for 446x, but provided here in + * anticipation. + * If a fix is found at a later date, the code using this can be removed. + * WA involves: + * Enable MPU->EMIF SD before WFI and disable while coming out of WFI. + * This works around system hang/lockups seen when only MPU->EMIF + * dynamic dependency set. Allows dynamic dependency to be used + * in all active usecases and get all the power savings accordingly. + * TODO: Once this is available as final Errata, update with proper + * fix. + */ +#define OMAP4_PM_ERRATUM_MPU_EMIF_NO_DYNDEP_IDLE_iXXX BIT(4) u8 pm44xx_errata; #define is_pm44xx_erratum(erratum) (pm44xx_errata & OMAP4_PM_ERRATUM_##erratum) @@ -129,6 +147,7 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state, bool suspend) int core_next_state = PWRDM_POWER_ON; int mpu_next_state = PWRDM_POWER_ON; int ret; + int staticdep_wa_applied = 0; pwrdm_clear_all_prev_pwrst(cpu0_pwrdm); pwrdm_clear_all_prev_pwrst(mpu_pwrdm); @@ -152,9 +171,30 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state, bool suspend) if (ret) goto abort_gpio; + if (is_pm44xx_erratum(MPU_EMIF_NO_DYNDEP_IDLE_iXXX) && + mpu_next_state <= PWRDM_POWER_INACTIVE) { + /* Configures MEMIF clockdomain in SW_WKUP */ + if (clkdm_wakeup(emif_clkdm)) { + pr_err("%s: Failed to force wakeup of %s\n", + __func__, emif_clkdm->name); + } else { + /* Enable MPU-EMIF Static Dependency around WFI */ + if (clkdm_add_wkdep(mpuss_clkdm, emif_clkdm)) + pr_err("%s: Failed to Add wkdep %s->%s\n", + __func__, mpuss_clkdm->name, + emif_clkdm->name); + else + staticdep_wa_applied = 1; + + /* Configures MEMIF clockdomain back to HW_AUTO */ + clkdm_allow_idle(emif_clkdm); + } + } if (mpu_next_state < PWRDM_POWER_INACTIVE) { if (omap_sr_disable_reset_volt(mpu_voltdm)) goto abort_device_off; + + omap_sr_disable_reset_volt(mpu_voltdm); omap_vc_set_auto_trans(mpu_voltdm, OMAP_VC_CHANNEL_AUTO_TRANSITION_RETENTION); } @@ -252,6 +292,24 @@ abort_device_off: omap_voltage_get_curr_vdata(mpu_voltdm)); } + /* + * NOTE: is_pm44xx_erratum is not strictly required, but retained for + * code context redability. + */ + if (is_pm44xx_erratum(MPU_EMIF_NO_DYNDEP_IDLE_iXXX) && + staticdep_wa_applied) { + /* Configures MEMIF clockdomain in SW_WKUP */ + if (clkdm_wakeup(emif_clkdm)) + pr_err("%s: Failed to force wakeup of %s\n", + __func__, emif_clkdm->name); + /* Disable MPU-EMIF Static Dependency on WFI exit */ + else if (clkdm_del_wkdep(mpuss_clkdm, emif_clkdm)) + pr_err("%s: Failed to remove wkdep %s->%s\n", + __func__, mpuss_clkdm->name, + emif_clkdm->name); + /* Configures MEMIF clockdomain back to HW_AUTO */ + clkdm_allow_idle(emif_clkdm); + } abort_gpio: return; @@ -1137,6 +1195,11 @@ static void __init omap4_pm_setup_errata(void) if (cpu_is_omap44xx()) pm44xx_errata |= OMAP4_PM_ERRATUM_IVA_AUTO_RET_iXXX | OMAP4_PM_ERRATUM_HSI_SWAKEUP_iXXX; + /* Dynamic Dependency errata for all silicon !=443x */ + if (cpu_is_omap443x()) + pm44xx_errata |= OMAP4_PM_ERRATUM_MPU_EMIF_NO_DYNDEP_i688; + else + pm44xx_errata |= OMAP4_PM_ERRATUM_MPU_EMIF_NO_DYNDEP_IDLE_iXXX; } /** @@ -1148,7 +1211,7 @@ static void __init omap4_pm_setup_errata(void) static int __init omap4_pm_init(void) { int ret = 0; - struct clockdomain *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm; + struct clockdomain *l3_1_clkdm; struct clockdomain *ducati_clkdm, *l3_2_clkdm, *l4_per, *l4_cfg; if (!cpu_is_omap44xx()) @@ -1207,8 +1270,11 @@ static int __init omap4_pm_init(void) (!l3_2_clkdm) || (!ducati_clkdm) || (!l4_per) || (!l4_cfg)) goto err2; - if (cpu_is_omap443x()) { + /* if we cannot ever enable static dependency. */ + if (is_pm44xx_erratum(MPU_EMIF_NO_DYNDEP_i688)) ret |= clkdm_add_wkdep(mpuss_clkdm, emif_clkdm); + + if (cpu_is_omap443x()) { ret |= clkdm_add_wkdep(mpuss_clkdm, l3_1_clkdm); ret |= clkdm_add_wkdep(mpuss_clkdm, l3_2_clkdm); ret |= clkdm_add_wkdep(ducati_clkdm, l3_1_clkdm); @@ -1228,12 +1294,6 @@ static int __init omap4_pm_init(void) pr_info("OMAP4 PM: Static dependency added between" " DUCATI <-> L4_PER/CFG and DUCATI <-> L3.\n"); } else if (cpu_is_omap446x()) { - /* - * Static dependency between mpuss and emif can only be - * disabled if OSWR is disabled to avoid a HW bug that occurs - * when mpuss enters OSWR - */ - /*ret |= clkdm_add_wkdep(mpuss_clkdm, emif_clkdm);*/ ret |= clkdm_add_wkdep(mpuss_clkdm, l4_per); ret |= clkdm_add_wkdep(mpuss_clkdm, l4_cfg); diff --git a/arch/arm/mach-omap2/smartreflex-class1p5.c b/arch/arm/mach-omap2/smartreflex-class1p5.c index c8d14af..f870220 100644 --- a/arch/arm/mach-omap2/smartreflex-class1p5.c +++ b/arch/arm/mach-omap2/smartreflex-class1p5.c @@ -69,6 +69,8 @@ struct sr_class1p5_work_data { static struct delayed_work recal_work; #endif +static unsigned long class1p5_margin; + /** * sr_class1p5_notify() - isr notifier for status events * @voltdm: voltage domain for which we were triggered diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index b281955..abb2e7e 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1496,10 +1496,10 @@ static int omap2_gpio_set_edge_wakeup(struct gpio_bank *bank, bool suspend) * even if they are set for level detection only. */ __raw_writel(bank->context.edge_falling | - (bank->context.ew_leveldetect0 & wkup_status), + (bank->type_leveldetect0 & wkup_status), (bank->base + bank->regs->fallingdetect)); __raw_writel(bank->context.edge_rising | - (bank->context.ew_leveldetect1 & wkup_status), + (bank->type_leveldetect1 & wkup_status), (bank->base + bank->regs->risingdetect)); __raw_writel(0, bank->base + bank->regs->leveldetect0); __raw_writel(0, bank->base + bank->regs->leveldetect1); @@ -1566,12 +1566,15 @@ int omap2_gpio_prepare_for_idle(int off_mode, bool suspend) struct gpio_bank *bank; list_for_each_entry(bank, &omap_gpio_list, node) { + if (!bank->mod_usage) + continue; + omap2_gpio_set_wakeupenables(bank); if (omap2_gpio_set_edge_wakeup(bank, suspend)) ret = -EBUSY; - if (bank->mod_usage && bank->loses_context && off_mode) + if (bank->loses_context) if (pm_runtime_put_sync_suspend(bank->dev) < 0) dev_err(bank->dev, "%s: GPIO bank %d " "pm_runtime_put_sync failed\n", @@ -1589,7 +1592,10 @@ void omap2_gpio_resume_after_idle(int off_mode) struct gpio_bank *bank; list_for_each_entry(bank, &omap_gpio_list, node) { - if (bank->mod_usage && bank->loses_context && off_mode) + if (!bank->mod_usage) + continue; + + if (bank->loses_context) if (pm_runtime_get_sync(bank->dev) < 0) dev_err(bank->dev, "%s: GPIO bank %d " "pm_runtime_get_sync failed\n", diff --git a/drivers/gpu/pvr/Makefile b/drivers/gpu/pvr/Makefile index 1eb3417..a9c7e44 100644 --- a/drivers/gpu/pvr/Makefile +++ b/drivers/gpu/pvr/Makefile @@ -23,6 +23,7 @@ ccflags-y += \ -DSUPPORT_LARGE_GENERAL_HEAP \ -DPVR_NO_OMAP_TIMER \ -DSYS_SUPPORTS_SGX_IDLE_CALLBACK \ + -DPVRSRV_REFCOUNT_DEBUG \ -Idrivers/gpu/pvr/sgx ccflags-$(CONFIG_PVR_SGXCORE_540) += \ @@ -89,6 +90,7 @@ pvrsrvkm-y := \ bridged_pvr_bridge.o \ perproc.o \ lists.o \ + refcount.o \ omap4/sysconfig.o \ omap4/sysutils.o \ sgx/bridged_sgx_bridge.o \ diff --git a/drivers/gpu/pvr/bridged_pvr_bridge.c b/drivers/gpu/pvr/bridged_pvr_bridge.c index 44f8e05..7a84ee8 100644 --- a/drivers/gpu/pvr/bridged_pvr_bridge.c +++ b/drivers/gpu/pvr/bridged_pvr_bridge.c @@ -46,6 +46,7 @@ #include "perproc.h" #include "device.h" #include "buffer_manager.h" +#include "refcount.h" #include "pdump_km.h" #include "syscommon.h" @@ -899,7 +900,7 @@ PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID, if(psSrcKernelMemInfo->psKernelSyncInfo) { - psSrcKernelMemInfo->psKernelSyncInfo->ui32RefCount++; + PVRSRVKernelSyncInfoIncRef(psSrcKernelMemInfo->psKernelSyncInfo, psSrcKernelMemInfo); } psDstKernelMemInfo->psKernelSyncInfo = psSrcKernelMemInfo->psKernelSyncInfo; diff --git a/drivers/gpu/pvr/buffer_manager.c b/drivers/gpu/pvr/buffer_manager.c index 8907e22..27ed8a1 100644 --- a/drivers/gpu/pvr/buffer_manager.c +++ b/drivers/gpu/pvr/buffer_manager.c @@ -1408,7 +1408,7 @@ BM_Wrap ( IMG_HANDLE hDevMemHeap, "BM_Wrap (Matched previous Wrap! uSize=0x%x, uOffset=0x%x, SysAddr=%08X)", ui32Size, ui32Offset, sHashAddress.uiAddr)); - pBuf->ui32RefCount++; + PVRSRVBMBufIncRef(pBuf); *phBuf = (BM_HANDLE)pBuf; if(pui32Flags) *pui32Flags = uFlags; @@ -1477,7 +1477,7 @@ BM_Export (BM_HANDLE hBuf) { BM_BUF *pBuf = (BM_BUF *)hBuf; - pBuf->ui32ExportCount++; + PVRSRVBMBufIncExport(pBuf); } IMG_VOID @@ -1486,7 +1486,7 @@ BM_FreeExport(BM_HANDLE hBuf, { BM_BUF *pBuf = (BM_BUF *)hBuf; - pBuf->ui32ExportCount--; + PVRSRVBMBufDecExport(pBuf); FreeBuf (pBuf, ui32Flags, IMG_FALSE); } @@ -1509,8 +1509,7 @@ BM_Free (BM_HANDLE hBuf, SysAcquireData(&psSysData); - pBuf->ui32RefCount--; - + PVRSRVBMBufDecRef(pBuf); if(pBuf->ui32RefCount == 0) { if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr) @@ -1757,7 +1756,12 @@ DevMemoryFree (BM_MAPPING *pMapping) #define XPROC_WORKAROUND_BAD_SHAREINDEX 0773407734 +#define XPROC_WORKAROUND_UNKNOWN 0 +#define XPROC_WORKAROUND_ALLOC 1 +#define XPROC_WORKAROUND_MAP 2 + static IMG_UINT32 gXProcWorkaroundShareIndex = XPROC_WORKAROUND_BAD_SHAREINDEX; +static IMG_UINT32 gXProcWorkaroundState = XPROC_WORKAROUND_UNKNOWN; static struct { @@ -1783,6 +1787,7 @@ PVRSRV_ERROR BM_XProcWorkaroundSetShareIndex(IMG_UINT32 ui32Index) } gXProcWorkaroundShareIndex = ui32Index; + gXProcWorkaroundState = XPROC_WORKAROUND_MAP; return PVRSRV_OK; } @@ -1804,6 +1809,7 @@ PVRSRV_ERROR BM_XProcWorkaroundUnsetShareIndex(IMG_UINT32 ui32Index) } gXProcWorkaroundShareIndex = XPROC_WORKAROUND_BAD_SHAREINDEX; + gXProcWorkaroundState = XPROC_WORKAROUND_UNKNOWN; return PVRSRV_OK; } @@ -1823,6 +1829,7 @@ PVRSRV_ERROR BM_XProcWorkaroundFindNewBufferAndSetShareIndex(IMG_UINT32 *pui32In if (gXProcWorkaroundShareData[*pui32Index].ui32RefCount == 0) { gXProcWorkaroundShareIndex = *pui32Index; + gXProcWorkaroundState = XPROC_WORKAROUND_ALLOC; return PVRSRV_OK; } } @@ -1881,12 +1888,20 @@ XProcWorkaroundAllocShareable(RA_ARENA *psArena, *ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr; *phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle; - gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount ++; + gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount++; return PVRSRV_OK; } else { + if (gXProcWorkaroundState != XPROC_WORKAROUND_ALLOC) + { + PVR_DPF((PVR_DBG_ERROR, + "XPROC workaround in bad state! About to allocate memory from non-alloc state! (%d)", + gXProcWorkaroundState)); + } + PVR_ASSERT(gXProcWorkaroundState == XPROC_WORKAROUND_ALLOC); + if (psArena != IMG_NULL) { IMG_CPU_PHYADDR sCpuPAddr; @@ -1954,7 +1969,7 @@ XProcWorkaroundAllocShareable(RA_ARENA *psArena, *ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr; *phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle; - gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount ++; + gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount++; return PVRSRV_OK; } @@ -2006,7 +2021,7 @@ static IMG_VOID XProcWorkaroundFreeShareable(IMG_HANDLE hOSMemHandle) return; } - gXProcWorkaroundShareData[ui32SI].ui32RefCount --; + gXProcWorkaroundShareData[ui32SI].ui32RefCount--; PVR_DPF((PVR_DBG_VERBOSE, "Reduced refcount of SI[%d] from %d to %d", ui32SI, gXProcWorkaroundShareData[ui32SI].ui32RefCount+1, gXProcWorkaroundShareData[ui32SI].ui32RefCount)); diff --git a/drivers/gpu/pvr/deviceclass.c b/drivers/gpu/pvr/deviceclass.c index 2ebd810..2834287 100644 --- a/drivers/gpu/pvr/deviceclass.c +++ b/drivers/gpu/pvr/deviceclass.c @@ -580,7 +580,8 @@ static PVRSRV_ERROR CloseDCDeviceCallBack(IMG_PVOID pvParam, psDCInfo->psFuncTable->pfnCloseDCDevice(psDCInfo->hExtDevice); - if (--psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) + PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); + if (psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) { PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo); } @@ -674,11 +675,24 @@ PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc, return eError; } - psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++; + psDCPerContextInfo->psDCInfo = psDCInfo; + eError = PVRSRVGetDCSystemBufferKM(psDCPerContextInfo, IMG_NULL); + if(eError != PVRSRV_OK) + { + PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to get system buffer")); + psDCInfo->ui32RefCount--; + PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo); + return eError; + } + + PVRSRVKernelSyncInfoIncRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount = 0; } + else + { + psDCPerContextInfo->psDCInfo = psDCInfo; + } - psDCPerContextInfo->psDCInfo = psDCInfo; psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DISPLAYCLASS_DEVICE, psDCPerContextInfo, @@ -742,7 +756,7 @@ PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM, PVRSRV_DISPLAYCLASS_INFO *psDCInfo; IMG_HANDLE hExtBuffer; - if(!hDeviceKM || !phBuffer) + if(!hDeviceKM) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; @@ -767,7 +781,10 @@ PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM, psDCInfo->sSystemBuffer.psDCInfo = psDCInfo; - *phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer); + if (phBuffer) + { + *phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer); + } return PVRSRV_OK; } @@ -872,7 +889,8 @@ static PVRSRV_ERROR DestroyDCSwapChain(PVRSRV_DC_SWAPCHAIN *psSwapChain) { if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) { - if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) + PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); + if (psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) { PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); } @@ -1079,7 +1097,7 @@ PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc, goto ErrorExit; } - psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++; + PVRSRVKernelSyncInfoIncRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr; @@ -1179,7 +1197,8 @@ ErrorExit: { if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) { - if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) + PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); + if (psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) { PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); } @@ -1482,6 +1501,22 @@ PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM, psFlipCmd->ui32SwapInterval = ui32SwapInterval; + SysAcquireData(&psSysData); + + + { + if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH) + { + OSFlushCPUCacheKM(); + } + else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN) + { + OSCleanCPUCacheKM(); + } + + psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE; + } + eError = PVRSRVSubmitCommandKM (psQueue, psCommand); if (eError != PVRSRV_OK) @@ -1492,7 +1527,6 @@ PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM, - SysAcquireData(&psSysData); eError = OSScheduleMISR(psSysData); if (eError != PVRSRV_OK) @@ -2102,7 +2136,8 @@ static PVRSRV_ERROR CloseBCDeviceCallBack(IMG_PVOID pvParam, { if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) { - if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) + PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); + if (psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) { PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); } @@ -2228,7 +2263,7 @@ PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc, goto ErrorExit; } - psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++; + PVRSRVKernelSyncInfoIncRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); @@ -2270,7 +2305,8 @@ ErrorExit: { if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) { - if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) + PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); + if (psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) { PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); } diff --git a/drivers/gpu/pvr/devicemem.c b/drivers/gpu/pvr/devicemem.c index 03b28eb..cd22faa 100644 --- a/drivers/gpu/pvr/devicemem.c +++ b/drivers/gpu/pvr/devicemem.c @@ -597,6 +597,10 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernel } eError = FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM); + + + psKernelSyncInfo->psSyncDataMemInfoKM = IMG_NULL; + psKernelSyncInfo->psSyncData = IMG_NULL; (IMG_VOID)OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL); @@ -737,7 +741,7 @@ PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo, PVR_UNREFERENCED_PARAMETER(ui32Param); - psMemInfo->ui32RefCount--; + PVRSRVKernelMemInfoDecRef(psMemInfo); if (psMemInfo->ui32RefCount == 0) @@ -789,8 +793,7 @@ PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo, case PVRSRV_MEMTYPE_DEVICE: if (psMemInfo->psKernelSyncInfo) { - psMemInfo->psKernelSyncInfo->ui32RefCount--; - + PVRSRVKernelSyncInfoDecRef(psMemInfo->psKernelSyncInfo, psMemInfo); if (psMemInfo->psKernelSyncInfo->ui32RefCount == 0) { eError = PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo); @@ -918,7 +921,8 @@ PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie, { goto free_mainalloc; } - psMemInfo->psKernelSyncInfo->ui32RefCount++; + + PVRSRVKernelSyncInfoIncRef(psMemInfo->psKernelSyncInfo, psMemInfo); } @@ -945,7 +949,7 @@ PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie, } - psMemInfo->ui32RefCount++; + PVRSRVKernelMemInfoIncRef(psMemInfo); psMemInfo->memType = PVRSRV_MEMTYPE_DEVICE; @@ -958,7 +962,6 @@ free_mainalloc: return eError; } - IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE hDevCookie, PVRSRV_KERNEL_MEM_INFO *psMemInfo) @@ -1201,10 +1204,10 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie, goto ErrorExitPhase4; } - psMemInfo->psKernelSyncInfo->ui32RefCount++; + PVRSRVKernelSyncInfoIncRef(psMemInfo->psKernelSyncInfo, psMemInfo); - psMemInfo->ui32RefCount++; + PVRSRVKernelMemInfoIncRef(psMemInfo); psMemInfo->memType = PVRSRV_MEMTYPE_WRAPPED; @@ -1286,7 +1289,7 @@ static PVRSRV_ERROR UnmapDeviceMemoryCallBack(IMG_PVOID pvParam, if( psMapData->psMemInfo->psKernelSyncInfo ) { - psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount--; + PVRSRVKernelSyncInfoDecRef(psMapData->psMemInfo->psKernelSyncInfo, psMapData->psMemInfo); if (psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount == 0) { eError = PVRSRVFreeSyncInfoKM(psMapData->psMemInfo->psKernelSyncInfo); @@ -1446,7 +1449,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPer if(psMemInfo->psKernelSyncInfo) { - psMemInfo->psKernelSyncInfo->ui32RefCount++; + PVRSRVKernelSyncInfoIncRef(psMemInfo->psKernelSyncInfo, psMemInfo); } @@ -1454,10 +1457,10 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPer psMemInfo->pvSysBackupBuffer = IMG_NULL; - psMemInfo->ui32RefCount++; + PVRSRVKernelMemInfoIncRef(psMemInfo); - psSrcMemInfo->ui32RefCount++; + PVRSRVKernelMemInfoIncRef(psSrcMemInfo); BM_Export(psSrcMemInfo->sMemBlk.hBuffer); @@ -1754,7 +1757,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA * &UnmapDeviceClassMemoryCallBack); (psDeviceClassBuffer->ui32MemMapRefCount)++; - psMemInfo->ui32RefCount++; + PVRSRVKernelMemInfoIncRef(psMemInfo); psMemInfo->memType = PVRSRV_MEMTYPE_DEVICECLASS; diff --git a/drivers/gpu/pvr/mmap.c b/drivers/gpu/pvr/mmap.c index d2a09a7..a63223c 100644 --- a/drivers/gpu/pvr/mmap.c +++ b/drivers/gpu/pvr/mmap.c @@ -54,15 +54,12 @@ #include <drm/drmP.h> #endif -#include "img_defs.h" -#include "services.h" -#include "servicesint.h" +#include "services_headers.h" + #include "pvrmmap.h" #include "mutils.h" #include "mmap.h" #include "mm.h" -#include "pvr_debug.h" -#include "osfunc.h" #include "proc.h" #include "mutex.h" #include "handle.h" @@ -327,7 +324,7 @@ PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc, *pui32MMapOffset = psOffsetStruct->ui32MMapOffset; *pui32UserVAddr = psOffsetStruct->ui32UserVAddr; - psOffsetStruct->ui32RefCount++; + PVRSRVOffsetStructIncRef(psOffsetStruct); eError = PVRSRV_OK; goto exit_unlock; @@ -364,7 +361,7 @@ PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc, psOffsetStruct->bOnMMapList = IMG_TRUE; - psOffsetStruct->ui32RefCount++; + PVRSRVOffsetStructIncRef(psOffsetStruct); eError = PVRSRV_OK; @@ -427,7 +424,7 @@ PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc, goto exit_unlock; } - psOffsetStruct->ui32RefCount--; + PVRSRVOffsetStructDecRef(psOffsetStruct); *pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0)); @@ -600,10 +597,12 @@ static IMG_VOID MMapVOpenNoLock(struct vm_area_struct* ps_vma) { PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data; - PVR_ASSERT(psOffsetStruct != IMG_NULL) - psOffsetStruct->ui32Mapped++; + + PVR_ASSERT(psOffsetStruct != IMG_NULL); PVR_ASSERT(!psOffsetStruct->bOnMMapList); + PVRSRVOffsetStructIncMapped(psOffsetStruct); + if (psOffsetStruct->ui32Mapped > 1) { PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %u)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped)); @@ -651,7 +650,7 @@ MMapVCloseNoLock(struct vm_area_struct* ps_vma) #endif PVR_ASSERT(!psOffsetStruct->bOnMMapList); - psOffsetStruct->ui32Mapped--; + PVRSRVOffsetStructDecMapped(psOffsetStruct); if (psOffsetStruct->ui32Mapped == 0) { if (psOffsetStruct->ui32RefCount != 0) @@ -1065,6 +1064,8 @@ PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea) if (psOffsetStruct->ui32Mapped != 0) { PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %u", __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped)); + dump_stack(); + PVRSRVDumpRefCountCCB(); eError = PVRSRV_ERROR_STILL_MAPPED; goto exit_unlock; } diff --git a/drivers/gpu/pvr/omaplfb/omaplfb_displayclass.c b/drivers/gpu/pvr/omaplfb/omaplfb_displayclass.c index 5e0eca4..c888c31 100644 --- a/drivers/gpu/pvr/omaplfb/omaplfb_displayclass.c +++ b/drivers/gpu/pvr/omaplfb/omaplfb_displayclass.c @@ -829,9 +829,6 @@ static IMG_BOOL ProcessFlipV1(IMG_HANDLE hCmdCookie, { psBuffer->hCmdComplete = (OMAPLFB_HANDLE)hCmdCookie; psBuffer->ulSwapInterval = ulSwapInterval; -#if defined(NO_HARDWARE) - psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete((IMG_HANDLE)psBuffer->hCmdComplete, IMG_FALSE); -#else if (is_tiler_addr(psBuffer->sSysAddr.uiAddr)) { IMG_UINT32 w = psBuffer->psDevInfo->sDisplayDim.ui32Width; IMG_UINT32 h = psBuffer->psDevInfo->sDisplayDim.ui32Height; @@ -861,7 +858,6 @@ static IMG_BOOL ProcessFlipV1(IMG_HANDLE hCmdCookie, } else { OMAPLFBQueueBufferForSwap(psSwapChain, psBuffer); } -#endif } OMAPLFBCreateSwapChainUnLock(psDevInfo); diff --git a/drivers/gpu/pvr/osfunc.h b/drivers/gpu/pvr/osfunc.h index 3d76ba8..6e5cbd1 100644 --- a/drivers/gpu/pvr/osfunc.h +++ b/drivers/gpu/pvr/osfunc.h @@ -410,6 +410,7 @@ IMG_BOOL OSMemHandleIsPhysContig(IMG_VOID *hOSMemHandle); #endif static INLINE IMG_BOOL OSMemHandleIsPhysContig(IMG_HANDLE hOSMemHandle) { + PVR_UNREFERENCED_PARAMETER(hOSMemHandle); return IMG_FALSE; } #endif diff --git a/drivers/gpu/pvr/pvr_bridge_k.c b/drivers/gpu/pvr/pvr_bridge_k.c index 91a75a9..6d51200 100644 --- a/drivers/gpu/pvr/pvr_bridge_k.c +++ b/drivers/gpu/pvr/pvr_bridge_k.c @@ -35,6 +35,8 @@ #include "private_data.h" #include "linkage.h" #include "pvr_bridge_km.h" +#include "pvr_uaccess.h" +#include "refcount.h" #if defined(SUPPORT_DRI_DRM) #include <drm/drmP.h> @@ -296,7 +298,11 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig goto unlock_and_return; } - psMapDevMemIN->hKernelMemInfo = psPrivateData->hKernelMemInfo; + if (pvr_put_user(psPrivateData->hKernelMemInfo, &psMapDevMemIN->hKernelMemInfo) != 0) + { + err = -EFAULT; + goto unlock_and_return; + } break; } @@ -390,13 +396,18 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig } - psKernelMemInfo->ui32RefCount++; + PVRSRVKernelMemInfoIncRef(psKernelMemInfo); psPrivateData->hKernelMemInfo = psExportDeviceMemOUT->hMemInfo; #if defined(SUPPORT_MEMINFO_IDS) - psKernelMemInfo->ui64Stamp = - psExportDeviceMemOUT->ui64Stamp = - psPrivateData->ui64Stamp = ++ui64Stamp; + psPrivateData->ui64Stamp = ++ui64Stamp; + + psKernelMemInfo->ui64Stamp = psPrivateData->ui64Stamp; + if (pvr_put_user(psPrivateData->ui64Stamp, &psExportDeviceMemOUT->ui64Stamp) != 0) + { + err = -EFAULT; + goto unlock_and_return; + } #endif break; } @@ -408,7 +419,11 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT = (PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamOut; PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile); - psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp = psPrivateData->ui64Stamp; + if (pvr_put_user(psPrivateData->ui64Stamp, &psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp) != 0) + { + err = -EFAULT; + goto unlock_and_return; + } break; } @@ -416,7 +431,11 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig { PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psDeviceClassMemoryOUT = (PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *)psBridgePackageKM->pvParamOut; - psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp = ++ui64Stamp; + if (pvr_put_user(++ui64Stamp, &psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp) != 0) + { + err = -EFAULT; + goto unlock_and_return; + } break; } #endif diff --git a/drivers/gpu/pvr/pvr_uaccess.h b/drivers/gpu/pvr/pvr_uaccess.h index bacafe9..4b7114e 100644 --- a/drivers/gpu/pvr/pvr_uaccess.h +++ b/drivers/gpu/pvr/pvr_uaccess.h @@ -64,5 +64,7 @@ static inline unsigned long pvr_copy_from_user(void *pvTo, const void __user *pv #endif } +#define pvr_put_user put_user + #endif diff --git a/drivers/gpu/pvr/pvrversion.h b/drivers/gpu/pvr/pvrversion.h index 5a762c1..1065b1c 100644 --- a/drivers/gpu/pvr/pvrversion.h +++ b/drivers/gpu/pvr/pvrversion.h @@ -36,7 +36,7 @@ #define PVRVERSION_FAMILY "sgxddk" #define PVRVERSION_BRANCHNAME "1.8" -#define PVRVERSION_BUILD 778707 +#define PVRVERSION_BUILD 785978 #define PVRVERSION_BSCONTROL "CustomerGoogle_Android_ogles1_ogles2_GPL" #define PVRVERSION_STRING "CustomerGoogle_Android_ogles1_ogles2_GPL sgxddk 18 1.8@" PVR_STR2(PVRVERSION_BUILD) @@ -44,8 +44,8 @@ #define COPYRIGHT_TXT "Copyright (c) Imagination Technologies Ltd. All Rights Reserved." -#define PVRVERSION_BUILD_HI 77 -#define PVRVERSION_BUILD_LO 8707 +#define PVRVERSION_BUILD_HI 78 +#define PVRVERSION_BUILD_LO 5978 #define PVRVERSION_STRING_NUMERIC PVR_STR2(PVRVERSION_MAJ) "." PVR_STR2(PVRVERSION_MIN) "." PVR_STR2(PVRVERSION_BUILD_HI) "." PVR_STR2(PVRVERSION_BUILD_LO) #endif /* _PVRVERSION_H_ */ diff --git a/drivers/gpu/pvr/queue.c b/drivers/gpu/pvr/queue.c index 92a4713..4682094 100644 --- a/drivers/gpu/pvr/queue.c +++ b/drivers/gpu/pvr/queue.c @@ -25,7 +25,6 @@ ******************************************************************************/ #include "services_headers.h" -#include "pvr_bridge_km.h" #include "lists.h" #include "ttrace.h" @@ -626,8 +625,6 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue, psCommand->psDstSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsDstSync[i], IMG_FALSE); psCommand->psDstSync[i].ui32ReadOps2Pending = PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE); - apsDstSync[i]->ui32RefCount++; - PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x", i, psCommand->psDstSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr, psCommand->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr, @@ -645,8 +642,6 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue, psCommand->psSrcSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsSrcSync[i], IMG_TRUE); psCommand->psSrcSync[i].ui32ReadOps2Pending = PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE); - apsSrcSync[i]->ui32RefCount++; - PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x", i, psCommand->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr, psCommand->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr, @@ -1008,11 +1003,6 @@ IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie, { psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete++; - if (--psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->ui32RefCount == 0) - { - PVRSRVFreeSyncInfoKM(psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM); - } - PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_UPDATE_DST, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM, PVRSRV_SYNCOP_COMPLETE); @@ -1029,11 +1019,6 @@ IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie, { psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->ui32ReadOps2Complete++; - if (--psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->ui32RefCount == 0) - { - PVRSRVFreeSyncInfoKM(psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM); - } - PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_UPDATE_SRC, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM, PVRSRV_SYNCOP_COMPLETE); @@ -1200,7 +1185,6 @@ PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex, if (psCmdCompleteData != IMG_NULL) { - PVR_ASSERT(psCmdCompleteData->bInUse == IMG_FALSE); OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, psCmdCompleteData->ui32AllocSize, psCmdCompleteData, IMG_NULL); psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter] = IMG_NULL; diff --git a/drivers/gpu/pvr/refcount.c b/drivers/gpu/pvr/refcount.c new file mode 100644 index 0000000..8b00972 --- /dev/null +++ b/drivers/gpu/pvr/refcount.c @@ -0,0 +1,481 @@ +/*************************************************************************/ /*! +@Title Services reference count debugging +@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved +@License Strictly Confidential. +*/ /**************************************************************************/ + +#if defined(PVRSRV_REFCOUNT_DEBUG) + +#include "services_headers.h" + +#ifndef __linux__ +#warning Reference count debugging is not thread-safe on this platform +#define PVRSRV_LOCK_CCB() +#define PVRSRV_UNLOCK_CCB() +#else /* __linux__ */ +#include <linux/mutex.h> +static DEFINE_MUTEX(gsCCBLock); +#define PVRSRV_LOCK_CCB() mutex_lock(&gsCCBLock) +#define PVRSRV_UNLOCK_CCB() mutex_unlock(&gsCCBLock) +#endif /* __linux__ */ + +#define PVRSRV_REFCOUNT_CCB_MAX 512 +#define PVRSRV_REFCOUNT_CCB_MESG_MAX 80 + +#define PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO (1U << 0) +#define PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO (1U << 1) +#define PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF (1U << 2) +#define PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2 (1U << 3) + +#if defined(__linux__) +#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP (1U << 4) +#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2 (1U << 5) +#else +#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP 0 +#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2 0 +#endif + +#define PVRSRV_REFCOUNT_CCB_DEBUG_ALL ~0U + +/*static const IMG_UINT guiDebugMask = PVRSRV_REFCOUNT_CCB_DEBUG_ALL;*/ +static const IMG_UINT guiDebugMask = + PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO | + PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2; + +typedef struct +{ + const IMG_CHAR *pszFile; + IMG_INT iLine; + IMG_UINT32 ui32PID; + IMG_CHAR pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX]; +} +PVRSRV_REFCOUNT_CCB; + +static PVRSRV_REFCOUNT_CCB gsRefCountCCB[PVRSRV_REFCOUNT_CCB_MAX]; +static IMG_UINT giOffset; + +static const IMG_CHAR gszHeader[] = + /* 10 20 30 40 50 60 70 + * 345678901234567890123456789012345678901234567890123456789012345678901 + */ + "TYPE SYNCINFO MEMINFO MEMHANDLE OTHER REF REF' SIZE PID"; + /* NCINFO deadbeef deadbeef deadbeef deadbeef 1234 1234 deadbeef */ + +#define PVRSRV_REFCOUNT_CCB_FMT_STRING "%8.8s %8p %8p %8p %8p %.4d %.4d %.8x" + +IMG_INTERNAL +void PVRSRVDumpRefCountCCB(void) +{ + int i; + + PVRSRV_LOCK_CCB(); + + PVR_LOG(("%s", gszHeader)); + + for(i = 0; i < PVRSRV_REFCOUNT_CCB_MAX; i++) + { + PVRSRV_REFCOUNT_CCB *psRefCountCCBEntry = + &gsRefCountCCB[(giOffset + i) % PVRSRV_REFCOUNT_CCB_MAX]; + + /* Early on, we won't have MAX_REFCOUNT_CCB_SIZE messages */ + if(!psRefCountCCBEntry->pszFile) + break; + + PVR_LOG(("%s %d %s:%d", psRefCountCCBEntry->pcMesg, + psRefCountCCBEntry->ui32PID, + psRefCountCCBEntry->pszFile, + psRefCountCCBEntry->iLine)); + } + + PVRSRV_UNLOCK_CCB(); +} + +IMG_INTERNAL +void PVRSRVKernelSyncInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, + PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo, + PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo) +{ + if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO)) + goto skip; + + PVRSRV_LOCK_CCB(); + + gsRefCountCCB[giOffset].pszFile = pszFile; + gsRefCountCCB[giOffset].iLine = iLine; + gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); + snprintf(gsRefCountCCB[giOffset].pcMesg, + PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, + PVRSRV_REFCOUNT_CCB_FMT_STRING, + "SYNCINFO", + psKernelSyncInfo, + psKernelMemInfo, + NULL, + (psKernelMemInfo) ? psKernelMemInfo->sMemBlk.hOSMemHandle : NULL, + psKernelSyncInfo->ui32RefCount, + psKernelSyncInfo->ui32RefCount + 1, + (psKernelMemInfo) ? psKernelMemInfo->uAllocSize : 0); + gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; + giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; + + PVRSRV_UNLOCK_CCB(); + +skip: + psKernelSyncInfo->ui32RefCount++; +} + +IMG_INTERNAL +void PVRSRVKernelSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, + PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo, + PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo) +{ + if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO)) + goto skip; + + PVRSRV_LOCK_CCB(); + + gsRefCountCCB[giOffset].pszFile = pszFile; + gsRefCountCCB[giOffset].iLine = iLine; + gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); + snprintf(gsRefCountCCB[giOffset].pcMesg, + PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, + PVRSRV_REFCOUNT_CCB_FMT_STRING, + "SYNCINFO", + psKernelSyncInfo, + psKernelMemInfo, + (psKernelMemInfo) ? psKernelMemInfo->sMemBlk.hOSMemHandle : NULL, + NULL, + psKernelSyncInfo->ui32RefCount, + psKernelSyncInfo->ui32RefCount - 1, + (psKernelMemInfo) ? psKernelMemInfo->uAllocSize : 0); + gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; + giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; + + PVRSRV_UNLOCK_CCB(); + +skip: + psKernelSyncInfo->ui32RefCount--; +} + +IMG_INTERNAL +void PVRSRVKernelMemInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, + PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo) +{ + if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO)) + goto skip; + + PVRSRV_LOCK_CCB(); + + gsRefCountCCB[giOffset].pszFile = pszFile; + gsRefCountCCB[giOffset].iLine = iLine; + gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); + snprintf(gsRefCountCCB[giOffset].pcMesg, + PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, + PVRSRV_REFCOUNT_CCB_FMT_STRING, + "MEMINFO", + psKernelMemInfo->psKernelSyncInfo, + psKernelMemInfo, + psKernelMemInfo->sMemBlk.hOSMemHandle, + NULL, + psKernelMemInfo->ui32RefCount, + psKernelMemInfo->ui32RefCount + 1, + psKernelMemInfo->uAllocSize); + gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; + giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; + + PVRSRV_UNLOCK_CCB(); + +skip: + psKernelMemInfo->ui32RefCount++; +} + +IMG_INTERNAL +void PVRSRVKernelMemInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, + PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo) +{ + if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO)) + goto skip; + + PVRSRV_LOCK_CCB(); + + gsRefCountCCB[giOffset].pszFile = pszFile; + gsRefCountCCB[giOffset].iLine = iLine; + gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); + snprintf(gsRefCountCCB[giOffset].pcMesg, + PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, + PVRSRV_REFCOUNT_CCB_FMT_STRING, + "MEMINFO", + psKernelMemInfo->psKernelSyncInfo, + psKernelMemInfo, + psKernelMemInfo->sMemBlk.hOSMemHandle, + NULL, + psKernelMemInfo->ui32RefCount, + psKernelMemInfo->ui32RefCount - 1, + psKernelMemInfo->uAllocSize); + gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; + giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; + + PVRSRV_UNLOCK_CCB(); + +skip: + psKernelMemInfo->ui32RefCount--; +} + +IMG_INTERNAL +void PVRSRVBMBufIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf) +{ + if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF)) + goto skip; + + PVRSRV_LOCK_CCB(); + + gsRefCountCCB[giOffset].pszFile = pszFile; + gsRefCountCCB[giOffset].iLine = iLine; + gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); + snprintf(gsRefCountCCB[giOffset].pcMesg, + PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, + PVRSRV_REFCOUNT_CCB_FMT_STRING, + "BM_BUF", + NULL, + NULL, + BM_HandleToOSMemHandle(pBuf), + pBuf, + pBuf->ui32RefCount, + pBuf->ui32RefCount + 1, + (pBuf->pMapping) ? pBuf->pMapping->uSize : 0); + gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; + giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; + + PVRSRV_UNLOCK_CCB(); + +skip: + pBuf->ui32RefCount++; +} + +IMG_INTERNAL +void PVRSRVBMBufDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf) +{ + if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF)) + goto skip; + + PVRSRV_LOCK_CCB(); + + gsRefCountCCB[giOffset].pszFile = pszFile; + gsRefCountCCB[giOffset].iLine = iLine; + gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); + snprintf(gsRefCountCCB[giOffset].pcMesg, + PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, + PVRSRV_REFCOUNT_CCB_FMT_STRING, + "BM_BUF", + NULL, + NULL, + BM_HandleToOSMemHandle(pBuf), + pBuf, + pBuf->ui32RefCount, + pBuf->ui32RefCount - 1, + (pBuf->pMapping) ? pBuf->pMapping->uSize : 0); + gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; + giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; + + PVRSRV_UNLOCK_CCB(); + +skip: + pBuf->ui32RefCount--; +} + +IMG_INTERNAL +void PVRSRVBMBufIncExport2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf) +{ + if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2)) + goto skip; + + PVRSRV_LOCK_CCB(); + + gsRefCountCCB[giOffset].pszFile = pszFile; + gsRefCountCCB[giOffset].iLine = iLine; + gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); + snprintf(gsRefCountCCB[giOffset].pcMesg, + PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, + PVRSRV_REFCOUNT_CCB_FMT_STRING, + "BM_BUF2", + NULL, + NULL, + BM_HandleToOSMemHandle(pBuf), + pBuf, + pBuf->ui32ExportCount, + pBuf->ui32ExportCount + 1, + (pBuf->pMapping) ? pBuf->pMapping->uSize : 0); + gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; + giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; + + PVRSRV_UNLOCK_CCB(); + +skip: + pBuf->ui32ExportCount++; +} + +IMG_INTERNAL +void PVRSRVBMBufDecExport2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf) +{ + if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2)) + goto skip; + + PVRSRV_LOCK_CCB(); + + gsRefCountCCB[giOffset].pszFile = pszFile; + gsRefCountCCB[giOffset].iLine = iLine; + gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); + snprintf(gsRefCountCCB[giOffset].pcMesg, + PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, + PVRSRV_REFCOUNT_CCB_FMT_STRING, + "BM_BUF2", + NULL, + NULL, + BM_HandleToOSMemHandle(pBuf), + pBuf, + pBuf->ui32ExportCount, + pBuf->ui32ExportCount - 1, + (pBuf->pMapping) ? pBuf->pMapping->uSize : 0); + gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; + giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; + + PVRSRV_UNLOCK_CCB(); + +skip: + pBuf->ui32ExportCount--; +} + +#if defined(__linux__) + +/* mmap refcounting is Linux specific */ + +IMG_INTERNAL +void PVRSRVOffsetStructIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, + PKV_OFFSET_STRUCT psOffsetStruct) +{ + if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP)) + goto skip; + + PVRSRV_LOCK_CCB(); + + gsRefCountCCB[giOffset].pszFile = pszFile; + gsRefCountCCB[giOffset].iLine = iLine; + gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); + snprintf(gsRefCountCCB[giOffset].pcMesg, + PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, + PVRSRV_REFCOUNT_CCB_FMT_STRING, + "MMAP", + NULL, + NULL, + psOffsetStruct->psLinuxMemArea, + psOffsetStruct, + psOffsetStruct->ui32RefCount, + psOffsetStruct->ui32RefCount + 1, + psOffsetStruct->ui32RealByteSize); + gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; + giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; + + PVRSRV_UNLOCK_CCB(); + +skip: + psOffsetStruct->ui32RefCount++; +} + +IMG_INTERNAL +void PVRSRVOffsetStructDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, + PKV_OFFSET_STRUCT psOffsetStruct) +{ + if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP)) + goto skip; + + PVRSRV_LOCK_CCB(); + + gsRefCountCCB[giOffset].pszFile = pszFile; + gsRefCountCCB[giOffset].iLine = iLine; + gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); + snprintf(gsRefCountCCB[giOffset].pcMesg, + PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, + PVRSRV_REFCOUNT_CCB_FMT_STRING, + "MMAP", + NULL, + NULL, + psOffsetStruct->psLinuxMemArea, + psOffsetStruct, + psOffsetStruct->ui32RefCount, + psOffsetStruct->ui32RefCount - 1, + psOffsetStruct->ui32RealByteSize); + gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; + giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; + + PVRSRV_UNLOCK_CCB(); + +skip: + psOffsetStruct->ui32RefCount--; +} + +IMG_INTERNAL +void PVRSRVOffsetStructIncMapped2(const IMG_CHAR *pszFile, IMG_INT iLine, + PKV_OFFSET_STRUCT psOffsetStruct) +{ + if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2)) + goto skip; + + PVRSRV_LOCK_CCB(); + + gsRefCountCCB[giOffset].pszFile = pszFile; + gsRefCountCCB[giOffset].iLine = iLine; + gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); + snprintf(gsRefCountCCB[giOffset].pcMesg, + PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, + PVRSRV_REFCOUNT_CCB_FMT_STRING, + "MMAP2", + NULL, + NULL, + psOffsetStruct->psLinuxMemArea, + psOffsetStruct, + psOffsetStruct->ui32Mapped, + psOffsetStruct->ui32Mapped + 1, + psOffsetStruct->ui32RealByteSize); + gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; + giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; + + PVRSRV_UNLOCK_CCB(); + +skip: + psOffsetStruct->ui32Mapped++; +} + +IMG_INTERNAL +void PVRSRVOffsetStructDecMapped2(const IMG_CHAR *pszFile, IMG_INT iLine, + PKV_OFFSET_STRUCT psOffsetStruct) +{ + if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2)) + goto skip; + + PVRSRV_LOCK_CCB(); + + gsRefCountCCB[giOffset].pszFile = pszFile; + gsRefCountCCB[giOffset].iLine = iLine; + gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM(); + snprintf(gsRefCountCCB[giOffset].pcMesg, + PVRSRV_REFCOUNT_CCB_MESG_MAX - 1, + PVRSRV_REFCOUNT_CCB_FMT_STRING, + "MMAP2", + NULL, + NULL, + psOffsetStruct->psLinuxMemArea, + psOffsetStruct, + psOffsetStruct->ui32Mapped, + psOffsetStruct->ui32Mapped - 1, + psOffsetStruct->ui32RealByteSize); + gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0; + giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX; + + PVRSRV_UNLOCK_CCB(); + +skip: + psOffsetStruct->ui32Mapped--; +} + +#endif /* defined(__linux__) */ + +#endif /* defined(PVRSRV_REFCOUNT_DEBUG) */ diff --git a/drivers/gpu/pvr/refcount.h b/drivers/gpu/pvr/refcount.h new file mode 100644 index 0000000..d2fd9c7 --- /dev/null +++ b/drivers/gpu/pvr/refcount.h @@ -0,0 +1,152 @@ +/*************************************************************************/ /*! +@Title Services reference count debugging +@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved +@License Strictly Confidential. +*/ /**************************************************************************/ + +#ifndef __REFCOUNT_H__ +#define __REFCOUNT_H__ + +#if defined(PVRSRV_REFCOUNT_DEBUG) + +void PVRSRVDumpRefCountCCB(void); + +#define PVRSRVKernelSyncInfoIncRef(x...) \ + PVRSRVKernelSyncInfoIncRef2(__FILE__, __LINE__, x) +#define PVRSRVKernelSyncInfoDecRef(x...) \ + PVRSRVKernelSyncInfoDecRef2(__FILE__, __LINE__, x) +#define PVRSRVKernelMemInfoIncRef(x...) \ + PVRSRVKernelMemInfoIncRef2(__FILE__, __LINE__, x) +#define PVRSRVKernelMemInfoDecRef(x...) \ + PVRSRVKernelMemInfoDecRef2(__FILE__, __LINE__, x) +#define PVRSRVBMBufIncRef(x...) \ + PVRSRVBMBufIncRef2(__FILE__, __LINE__, x) +#define PVRSRVBMBufDecRef(x...) \ + PVRSRVBMBufDecRef2(__FILE__, __LINE__, x) +#define PVRSRVBMBufIncExport(x...) \ + PVRSRVBMBufIncExport2(__FILE__, __LINE__, x) +#define PVRSRVBMBufDecExport(x...) \ + PVRSRVBMBufDecExport2(__FILE__, __LINE__, x) + +void PVRSRVKernelSyncInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, + PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo, + PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo); +void PVRSRVKernelSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, + PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo, + PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo); +void PVRSRVKernelMemInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, + PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo); +void PVRSRVKernelMemInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, + PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo); +void PVRSRVBMBufIncRef2(const IMG_CHAR *pszFile, + IMG_INT iLine, BM_BUF *pBuf); +void PVRSRVBMBufDecRef2(const IMG_CHAR *pszFile, + IMG_INT iLine, BM_BUF *pBuf); +void PVRSRVBMBufIncExport2(const IMG_CHAR *pszFile, + IMG_INT iLine, BM_BUF *pBuf); +void PVRSRVBMBufDecExport2(const IMG_CHAR *pszFile, + IMG_INT iLine, BM_BUF *pBuf); + +#if defined(__linux__) + +/* mmap refcounting is Linux specific */ +#include "mmap.h" + +#define PVRSRVOffsetStructIncRef(x...) \ + PVRSRVOffsetStructIncRef2(__FILE__, __LINE__, x) +#define PVRSRVOffsetStructDecRef(x...) \ + PVRSRVOffsetStructDecRef2(__FILE__, __LINE__, x) +#define PVRSRVOffsetStructIncMapped(x...) \ + PVRSRVOffsetStructIncMapped2(__FILE__, __LINE__, x) +#define PVRSRVOffsetStructDecMapped(x...) \ + PVRSRVOffsetStructDecMapped2(__FILE__, __LINE__, x) + +void PVRSRVOffsetStructIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, + PKV_OFFSET_STRUCT psOffsetStruct); +void PVRSRVOffsetStructDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, + PKV_OFFSET_STRUCT psOffsetStruct); +void PVRSRVOffsetStructIncMapped2(const IMG_CHAR *pszFile, IMG_INT iLine, + PKV_OFFSET_STRUCT psOffsetStruct); +void PVRSRVOffsetStructDecMapped2(const IMG_CHAR *pszFile, IMG_INT iLine, + PKV_OFFSET_STRUCT psOffsetStruct); + +#endif /* defined(__linux__) */ + +#else /* defined(PVRSRV_REFCOUNT_DEBUG) */ + +static INLINE void PVRSRVDumpRefCountCCB(void) { } + +static INLINE void PVRSRVKernelSyncInfoIncRef(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo, + PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo) +{ + PVR_UNREFERENCED_PARAMETER(psKernelMemInfo); + psKernelSyncInfo->ui32RefCount++; +} + +static INLINE void PVRSRVKernelSyncInfoDecRef(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo, + PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo) +{ + PVR_UNREFERENCED_PARAMETER(psKernelMemInfo); + psKernelSyncInfo->ui32RefCount--; +} + +static INLINE void PVRSRVKernelMemInfoIncRef(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo) +{ + psKernelMemInfo->ui32RefCount++; +} + +static INLINE void PVRSRVKernelMemInfoDecRef(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo) +{ + psKernelMemInfo->ui32RefCount--; +} + +#if defined(__linux__) + +/* mmap refcounting is Linux specific */ +#include "mmap.h" + +static INLINE void PVRSRVOffsetStructIncRef(PKV_OFFSET_STRUCT psOffsetStruct) +{ + psOffsetStruct->ui32RefCount++; +} + +static INLINE void PVRSRVOffsetStructDecRef(PKV_OFFSET_STRUCT psOffsetStruct) +{ + psOffsetStruct->ui32RefCount--; +} + +static INLINE void PVRSRVOffsetStructIncMapped(PKV_OFFSET_STRUCT psOffsetStruct) +{ + psOffsetStruct->ui32Mapped++; +} + +static INLINE void PVRSRVOffsetStructDecMapped(PKV_OFFSET_STRUCT psOffsetStruct) +{ + psOffsetStruct->ui32Mapped--; +} + +static INLINE void PVRSRVBMBufIncRef(BM_BUF *pBuf) +{ + pBuf->ui32RefCount++; +} + +static INLINE void PVRSRVBMBufDecRef(BM_BUF *pBuf) +{ + pBuf->ui32RefCount--; +} + +static INLINE void PVRSRVBMBufIncExport(BM_BUF *pBuf) +{ + pBuf->ui32ExportCount++; +} + +static INLINE void PVRSRVBMBufDecExport(BM_BUF *pBuf) +{ + pBuf->ui32ExportCount--; +} + +#endif /* defined(__linux__) */ + +#endif /* defined(PVRSRV_REFCOUNT_DEBUG) */ + +#endif /* __REFCOUNT_H__ */ diff --git a/drivers/gpu/pvr/services_headers.h b/drivers/gpu/pvr/services_headers.h index 2b5f197..09ed87e 100644 --- a/drivers/gpu/pvr/services_headers.h +++ b/drivers/gpu/pvr/services_headers.h @@ -44,6 +44,7 @@ #include "pvr_debug.h" #include "metrics.h" #include "osfunc.h" +#include "refcount.h" #endif diff --git a/drivers/gpu/pvr/sgx/mmu.c b/drivers/gpu/pvr/sgx/mmu.c index fbda31c..774026d 100644 --- a/drivers/gpu/pvr/sgx/mmu.c +++ b/drivers/gpu/pvr/sgx/mmu.c @@ -197,8 +197,10 @@ MMU_PDumpPageTables (MMU_HEAP *pMMUHeap, static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr); #endif +#define PT_DUMP 1 + #define PT_DEBUG 0 -#if PT_DEBUG +#if (PT_DEBUG || PT_DUMP) && defined(PVRSRV_NEED_PVR_DPF) static IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList) { IMG_UINT32 *p = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr; @@ -207,13 +209,20 @@ static IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList) for(i = 0; i < 1024; i += 8) { - PVR_DPF((PVR_DBG_WARNING, + PVR_DPF((PVR_DBG_ERROR, "%08X %08X %08X %08X %08X %08X %08X %08X\n", p[i + 0], p[i + 1], p[i + 2], p[i + 3], p[i + 4], p[i + 5], p[i + 6], p[i + 7])); } } +#else +static INLINE IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList) +{ + PVR_UNREFERENCED_PARAMETER(psPTInfoList); +} +#endif +#if PT_DEBUG static IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList) { IMG_UINT32 *p = (IMG_UINT32*) psPTInfoList->PTPageCpuVAddr; @@ -226,18 +235,13 @@ static IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList) if(psPTInfoList->ui32ValidPTECount != ui32Count) { - PVR_DPF((PVR_DBG_WARNING, "ui32ValidPTECount: %u ui32Count: %u\n", + PVR_DPF((PVR_DBG_ERROR, "ui32ValidPTECount: %u ui32Count: %u\n", psPTInfoList->ui32ValidPTECount, ui32Count)); DumpPT(psPTInfoList); BUG(); } } #else -static INLINE IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList) -{ - PVR_UNREFERENCED_PARAMETER(psPTInfoList); -} - static INLINE IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList) { PVR_UNREFERENCED_PARAMETER(psPTInfoList); @@ -2754,6 +2758,9 @@ MMU_MapPage (MMU_HEAP *pMMUHeap, ui32Index )); PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page table entry value: 0x%08X", uTmp)); PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Physical page to map: 0x%08X", DevPAddr.uiAddr)); +#if PT_DUMP + DumpPT(ppsPTInfoList[0]); +#endif } #if !defined(FIX_HW_BRN_31620) PVR_ASSERT((uTmp & SGX_MMU_PTE_VALID) == 0); diff --git a/drivers/gpu/pvr/sgx/sgxkick.c b/drivers/gpu/pvr/sgx/sgxkick.c index cbac38e..019a75cb 100644 --- a/drivers/gpu/pvr/sgx/sgxkick.c +++ b/drivers/gpu/pvr/sgx/sgxkick.c @@ -573,6 +573,37 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick) 0, MAKEUNIQUETAG(psCCBMemInfo)); } + + if (psCCBKick->hTASyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo; + + PDUMPCOMMENT("Modify TA/TQ ROpPendingVal\r\n"); + + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, + psCCBMemInfo, + psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, ui32TATQSyncReadOpsPendingVal), + sizeof(IMG_UINT32), + 0, + MAKEUNIQUETAG(psCCBMemInfo)); + psSyncInfo->psSyncData->ui32LastReadOpDumpVal++; + } + + if (psCCBKick->h3DSyncInfo != IMG_NULL) + { + psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo; + + PDUMPCOMMENT("Modify 3D/TQ ROpPendingVal\r\n"); + + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal, + psCCBMemInfo, + psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, ui323DTQSyncReadOpsPendingVal), + sizeof(IMG_UINT32), + 0, + MAKEUNIQUETAG(psCCBMemInfo)); + psSyncInfo->psSyncData->ui32LastReadOpDumpVal++; + } + #endif for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) diff --git a/drivers/gpu/pvr/sgx/sgxreset.c b/drivers/gpu/pvr/sgx/sgxreset.c index 0baa11f..7050371 100644 --- a/drivers/gpu/pvr/sgx/sgxreset.c +++ b/drivers/gpu/pvr/sgx/sgxreset.c @@ -541,6 +541,7 @@ IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo, ui32RegVal = EUR_CR_MASTER_SOFT_RESET_BIF_RESET_MASK | EUR_CR_MASTER_SOFT_RESET_IPF_RESET_MASK | EUR_CR_MASTER_SOFT_RESET_DPM_RESET_MASK | + EUR_CR_MASTER_SOFT_RESET_MCI_RESET_MASK | EUR_CR_MASTER_SOFT_RESET_VDM_RESET_MASK; #if defined(SGX_FEATURE_PTLA) diff --git a/drivers/gpu/pvr/sgx/sgxtransfer.c b/drivers/gpu/pvr/sgx/sgxtransfer.c index 92ee0bc..d40773e 100644 --- a/drivers/gpu/pvr/sgx/sgxtransfer.c +++ b/drivers/gpu/pvr/sgx/sgxtransfer.c @@ -352,7 +352,37 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF } } } - } + + if (psKick->hTASyncInfo != IMG_NULL) + { + psSyncInfo = psKick->hTASyncInfo; + + PDUMPCOMMENT("Tweak TA/TQ surface write op in transfer cmd\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psCCBMemInfo, + psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui32TASyncWriteOpsPendingVal)), + sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal), + psKick->ui32PDumpFlags, + MAKEUNIQUETAG(psCCBMemInfo)); + + psSyncInfo->psSyncData->ui32LastOpDumpVal++; + } + + if (psKick->h3DSyncInfo != IMG_NULL) + { + psSyncInfo = psKick->h3DSyncInfo; + + PDUMPCOMMENT("Tweak 3D/TQ surface write op in transfer cmd\r\n"); + PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal, + psCCBMemInfo, + psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui323DSyncWriteOpsPendingVal)), + sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal), + psKick->ui32PDumpFlags, + MAKEUNIQUETAG(psCCBMemInfo)); + + psSyncInfo->psSyncData->ui32LastOpDumpVal++; + } + } #endif sCommand.ui32Data[1] = psKick->sHWTransferContextDevVAddr.uiAddr; diff --git a/drivers/gpu/pvr/sgx/sgxutils.c b/drivers/gpu/pvr/sgx/sgxutils.c index f362e06..c9a733b 100644 --- a/drivers/gpu/pvr/sgx/sgxutils.c +++ b/drivers/gpu/pvr/sgx/sgxutils.c @@ -365,7 +365,9 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode, goto Exit; } - if ((eCmdType == SGXMKIF_CMD_TA) && bLastInScene) + if (eCmdType == SGXMKIF_CMD_2D || + eCmdType == SGXMKIF_CMD_TRANSFER || + ((eCmdType == SGXMKIF_CMD_TA) && bLastInScene)) { SYS_DATA *psSysData; diff --git a/drivers/gpu/pvr/sgxfeaturedefs.h b/drivers/gpu/pvr/sgxfeaturedefs.h index bdf36fe..2553022 100644 --- a/drivers/gpu/pvr/sgxfeaturedefs.h +++ b/drivers/gpu/pvr/sgxfeaturedefs.h @@ -124,8 +124,6 @@ #define SGX_FEATURE_PDS_DATA_INTERLEAVE_2DWORDS #define SGX_FEATURE_MONOLITHIC_UKERNEL #define SGX_FEATURE_ZLS_EXTERNALZ - #define SGX_FEATURE_VDM_CONTEXT_SWITCH_REV_2 - #define SGX_FEATURE_ISP_CONTEXT_SWITCH_REV_2 #define SGX_FEATURE_NUM_PDS_PIPES (2) #define SGX_FEATURE_NATIVE_BACKWARD_BLIT #define SGX_FEATURE_MAX_TA_RENDER_TARGETS (512) @@ -177,11 +175,6 @@ #define SGX_FEATURE_VDM_CONTEXT_SWITCH #endif -#if defined(SGX_FEATURE_ISP_CONTEXT_SWITCH_REV_2) \ - || defined(SGX_FEATURE_ISP_CONTEXT_SWITCH_REV_3) -#define SGX_FEATURE_ISP_CONTEXT_SWITCH -#endif - #if defined(FIX_HW_BRN_22693) #undef SGX_FEATURE_AUTOCLOCKGATING #endif diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 903b2c7..a2b0862 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2570,8 +2570,8 @@ static int omap_hsmmc_suspend(struct device *dev) if (mmc_slot(host).mmc_data.built_in) host->mmc->pm_flags |= MMC_PM_KEEP_POWER; ret = mmc_suspend_host(host->mmc); - mmc_host_enable(host->mmc); if (ret == 0) { + mmc_host_enable(host->mmc); omap_hsmmc_disable_irq(host); OMAP_HSMMC_WRITE(host->base, HCTL, OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); @@ -2588,13 +2588,6 @@ static int omap_hsmmc_suspend(struct device *dev) dev_dbg(mmc_dev(host->mmc), "Unmask interrupt failed\n"); } - - /* - * Directly call platform_bus suspend. runtime PM - * PM lock is held during system suspend, so will - * not be auto-matically called - */ - mmc_host_disable(host->mmc); } } diff --git a/drivers/remoteproc/remoteproc.c b/drivers/remoteproc/remoteproc.c index 9f46e8b..5d2fa6c 100644 --- a/drivers/remoteproc/remoteproc.c +++ b/drivers/remoteproc/remoteproc.c @@ -1418,7 +1418,7 @@ void rproc_last_busy(struct rproc *rproc) mutex_lock(&rproc->pm_lock); if (pm_runtime_suspended(dev) || - !pm_runtime_autosuspend_expiration(dev)) { + !pm_runtime_autosuspend_expiration(dev)) { pm_runtime_mark_last_busy(dev); mutex_unlock(&rproc->pm_lock); /* diff --git a/drivers/rpmsg/rpmsg_resmgr.c b/drivers/rpmsg/rpmsg_resmgr.c index b3ddc34..a13094d 100644 --- a/drivers/rpmsg/rpmsg_resmgr.c +++ b/drivers/rpmsg/rpmsg_resmgr.c @@ -443,6 +443,10 @@ static int rprm_i2c_request(struct rprm_elem *e, struct rprm_i2c *obj) i2c_put_adapter(adapter); ret = pm_runtime_get_sync(i2c_dev); + /* + * pm_runtime_get_sync can return 1 in case it is already active, + * change it to 0 to indicate success. + */ ret -= ret == 1; if (!ret) e->handle = i2c_dev; diff --git a/drivers/video/omap2/dsscomp/device.c b/drivers/video/omap2/dsscomp/device.c index 57e4257..c92ed3f 100644 --- a/drivers/video/omap2/dsscomp/device.c +++ b/drivers/video/omap2/dsscomp/device.c @@ -235,8 +235,8 @@ static long setup_mgr(struct dsscomp_dev *cdev, /* convert addresses to user space */ if (oi->cfg.color_mode == OMAP_DSS_COLOR_NV12) { - if (oi->uv_addr) - oi->uv = hwc_virt_to_phys((u32) oi->uv_addr); + if (oi->uv_address) + oi->uv = hwc_virt_to_phys((u32) oi->uv_address); else oi->uv = hwc_virt_to_phys(addr + oi->cfg.height * oi->cfg.stride); diff --git a/include/video/dsscomp.h b/include/video/dsscomp.h index 05ec06a..e7216e9 100644 --- a/include/video/dsscomp.h +++ b/include/video/dsscomp.h @@ -334,7 +334,7 @@ struct dss2_ovl_cfg { struct omap_dss_cconv_coefs cconv; struct dss2_vc1_range_map_info vc1; - __u8 ix; /* ovl index same as sysfs/overlay# */ + __u8 ix; /* ovl index same as sysfs/overlay# */ __u8 zorder; /* 0..3 */ __u8 enabled; /* bool */ __u8 zonly; /* only set zorder and enabled bit */ @@ -349,26 +349,36 @@ enum omapdss_buffer_type { OMAP_DSS_BUFTYPE_TILER_PAGE, }; +enum omapdss_buffer_addressing_type { + OMAP_DSS_BUFADDR_DIRECT, /* using direct addresses */ + OMAP_DSS_BUFADDR_BYTYPE, /* using buffer types */ + OMAP_DSS_BUFADDR_ION, /* using ion handle(s) */ + OMAP_DSS_BUFADDR_GRALLOC, /* using gralloc handle */ +}; + struct dss2_ovl_info { struct dss2_ovl_cfg cfg; + enum omapdss_buffer_addressing_type addressing; + union { /* user-space interfaces */ struct { - void *address; /* main buffer address */ - void *uv_addr; /* uv buffer address */ - - /* - * For DSSCIOC_CHECK_OVL we allow specifying just the - * type of each buffer. This is used if we need to - * check whether DSS will be able to display a buffer - * if using a particular memory type before spending - * time to map/copy the buffer into that type of - * memory. Default value of 0 uses the address to - * determine the type. - */ - __u16 ba_type; - __u16 uv_type; + void *address; /* main buffer address */ + void *uv_address; /* uv buffer */ + }; + + /* + * For DSSCIOC_CHECK_OVL we allow specifying just the + * type of each buffer. This is used if we need to + * check whether DSS will be able to display a buffer + * if using a particular memory type before spending + * time to map/copy the buffer into that type of + * memory. + */ + struct { + enum omapdss_buffer_type ba_type; + enum omapdss_buffer_type uv_type; }; /* kernel-space interfaces */ diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 45328d4..62f23b2 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -399,7 +399,9 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, val = __raw_readl(OMAP4430_CM1_ABE_PDM_CLKCTRL); if ((val & CLKCTRL_MODULEMODE_MASK) != CLKCTRL_MODULEMODE_ENABLED) { WARN(1, "Clock not enabled: PDM_CLKCTRL=0x%x\n", val); + mcpdm->active--; pm_runtime_put_sync(mcpdm->dev); + err = -ENODEV; goto out; } diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 6a36196..a2a464f 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -391,7 +391,6 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm) static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd) { struct snd_card *card = rtd->card->snd_card; - struct snd_soc_dai *dai = rtd->cpu_dai; struct snd_pcm *pcm = rtd->pcm; int ret = 0; @@ -400,14 +399,14 @@ static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd) if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = DMA_BIT_MASK(64); - if (dai->driver->playback.channels_min) { + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { ret = omap_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) goto out; } - if (dai->driver->capture.channels_min) { + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { ret = omap_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) diff --git a/sound/soc/soc-dsp.c b/sound/soc/soc-dsp.c index 446266c..40e459a 100644 --- a/sound/soc/soc-dsp.c +++ b/sound/soc/soc-dsp.c @@ -101,6 +101,12 @@ static inline void be_reparent(struct snd_soc_pcm_runtime *fe, list_for_each_entry(dsp_params, &be->dsp[stream].fe_clients, list_fe) { if (dsp_params->fe != fe) { + + dev_dbg(&fe->dev, " reparent %s path %s %s %s\n", + stream ? "capture" : "playback", + dsp_params->fe->dai_link->name, + stream ? "<-" : "->", dsp_params->be->dai_link->name); + fe_substream = snd_soc_dsp_get_substream(dsp_params->fe, stream); be_substream->runtime = fe_substream->runtime; @@ -116,6 +122,10 @@ static inline void be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) list_for_each_entry_safe(dsp_params, d, &fe->dsp[stream].be_clients, list_be) { struct snd_soc_pcm_runtime *be = dsp_params->be; + dev_dbg(&fe->dev, "BE %s disconnect check for %s\n", + stream ? "capture" : "playback", + be->dai_link->name); + if (dsp_params->state == SND_SOC_DSP_LINK_STATE_FREE) { dev_dbg(&fe->dev, " freed DSP %s path %s %s %s\n", stream ? "capture" : "playback", @@ -396,9 +406,12 @@ static int soc_dsp_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) be_substream->runtime = be->dsp[stream].runtime; err = soc_pcm_open(be_substream); - if (err < 0) + if (err < 0) { + dev_err(&be->dev, "BE open failed %d\n", err); + be->dsp[stream].users--; + be->dsp[stream].state = SND_SOC_DSP_STATE_CLOSE; goto unwind; - + } be->dsp[stream].state = SND_SOC_DSP_STATE_OPEN; count++; } @@ -1013,22 +1026,28 @@ static int dsp_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_soc_dsp_link *dsp_link = fe->dai_link->dsp_link; struct snd_pcm_substream *substream = snd_soc_dsp_get_substream(fe, stream); + struct snd_soc_dsp_params *dsp_params; int ret; dev_dbg(&fe->dev, "runtime %s open on FE %s\n", stream ? "capture" : "playback", fe->dai_link->name); ret = soc_dsp_be_dai_startup(fe, stream); - if (ret < 0) + if (ret < 0) { + goto disconnect; return ret; + } ret = soc_dsp_be_dai_hw_params(fe, stream); - if (ret < 0) + if (ret < 0) { + goto close; return ret; - + } ret = soc_dsp_be_dai_prepare(fe, stream); - if (ret < 0) + if (ret < 0) { + goto hw_free; return ret; + } /* run the stream event for each BE */ if (stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -1047,8 +1066,8 @@ static int dsp_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START); if (ret < 0) { - dev_err(&fe->dev,"dsp: trigger FE failed %d\n", ret); - return ret; + dev_err(&fe->dev,"dsp: bespoke trigger FE failed %d\n", ret); + goto stream_stop; } } else { dev_dbg(&fe->dev, "dsp: trigger FE %s cmd start\n", @@ -1056,11 +1075,36 @@ static int dsp_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) ret = soc_dsp_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_START); - if (ret < 0) - return ret; + if (ret < 0) { + dev_err(&fe->dev,"dsp: trigger FE failed %d\n", ret); + goto stream_stop; + } } return 0; + +stream_stop: + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + soc_dsp_dapm_stream_event(fe, stream, + fe->cpu_dai->driver->playback.stream_name, + SNDRV_PCM_TRIGGER_STOP); + else + soc_dsp_dapm_stream_event(fe, stream, + fe->cpu_dai->driver->capture.stream_name, + SNDRV_PCM_TRIGGER_STOP); +hw_free: + soc_dsp_be_dai_hw_free(fe, stream); +close: + soc_dsp_be_dai_shutdown(fe, stream); +disconnect: + /* disconnect any non started BEs */ + list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) { + struct snd_soc_pcm_runtime *be = dsp_params->be; + if (be->dsp[stream].state != SND_SOC_DSP_STATE_START) + dsp_params->state = SND_SOC_DSP_LINK_STATE_FREE; + } + be_disconnect(fe, stream); + return ret; } static int dsp_run_update(struct snd_soc_pcm_runtime *fe, int stream, @@ -1506,7 +1550,9 @@ int soc_dsp_fe_resume(struct snd_soc_pcm_runtime *fe) int soc_dsp_fe_dai_open(struct snd_pcm_substream *fe_substream) { struct snd_soc_pcm_runtime *fe = fe_substream->private_data; - int err; + struct snd_soc_dsp_params *dsp_params; + int err, ret; + int stream = fe_substream->stream; fe->dsp[fe_substream->stream].runtime = fe_substream->runtime; @@ -1517,7 +1563,16 @@ int soc_dsp_fe_dai_open(struct snd_pcm_substream *fe_substream) fe->dai_link->name, fe_substream->stream ? "capture" : "playback"); } - return soc_dsp_fe_dai_startup(fe_substream); + ret = soc_dsp_fe_dai_startup(fe_substream); + if (ret < 0) { + /* clean up all links */ + list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) + dsp_params->state = SND_SOC_DSP_LINK_STATE_FREE; + + be_disconnect(fe, stream); + fe->dsp[stream].runtime = NULL; + } + return ret; } /* called when closing FE stream */ |