From: Dave Airlie Date: Mon, 19 Dec 2011 11:15:29 +0000 (+0000) Subject: drm: move pci bus master enable into driver. X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=466e69b8b03b8c1987367912782bc12988ad8794;p=linux.git drm: move pci bus master enable into driver. The current enabling of bus mastering in the drm midlayer allows a large race condition under kexec. When a kexec'ed kernel re-enables bus mastering for the GPU, previously setup dma blocks may cause writes to random pieces of memory. On radeon the writeback mechanism can cause these sorts of issues. This patch doesn't fix the problem, but it moves the bus master enable under the individual drivers control so they can move enabling it until later in their load cycle and close the race. Fix for radeon kms driver will be in a follow-up patch. Signed-off-by: Dave Airlie --- diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index d4d10b7880cf8..13f3d936472f3 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -324,8 +324,6 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, if (ret) goto err_g1; - pci_set_master(pdev); - dev->pdev = pdev; dev->dev = &pdev->dev; diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index f14768f2b364e..1f57aac2cf808 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -283,6 +283,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->dev = dev; dev->dev_private = (void *) dev_priv; + pci_set_master(dev->pdev); + if (!IS_PSB(dev)) { if (pci_enable_msi(dev->pdev)) dev_warn(dev->dev, "Enabling MSI failed!\n"); diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 7f4b4e10246ec..64a989ed5b8ff 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -1208,6 +1208,8 @@ int i810_driver_load(struct drm_device *dev, unsigned long flags) dev->types[8] = _DRM_STAT_SECONDARY; dev->types[9] = _DRM_STAT_DMA; + pci_set_master(dev->pdev); + return 0; } diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 8919dcc07ed89..a8081f2efaea6 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1933,6 +1933,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto free_priv; } + pci_set_master(dev->pdev); + /* overlay on gen2 is broken and can't address above 1G */ if (IS_GEN2(dev)) dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30)); diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c index 5ccb65deb83c2..507aa3df01689 100644 --- a/drivers/gpu/drm/mga/mga_dma.c +++ b/drivers/gpu/drm/mga/mga_dma.c @@ -403,6 +403,8 @@ int mga_driver_load(struct drm_device *dev, unsigned long flags) dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; dev_priv->chipset = flags; + pci_set_master(dev->pdev); + dev_priv->mmio_base = pci_resource_start(dev->pdev, 1); dev_priv->mmio_size = pci_resource_len(dev->pdev, 1); diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index f80c5e0762ff9..912839c2bc16f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -1002,6 +1002,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) dev->dev_private = dev_priv; dev_priv->dev = dev; + pci_set_master(dev->pdev); + dev_priv->flags = flags & NOUVEAU_FLAGS; NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index 6a5f4395838f7..88718fad5d6db 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c @@ -85,6 +85,7 @@ static struct drm_driver driver = { int r128_driver_load(struct drm_device *dev, unsigned long flags) { + pci_set_master(dev->pdev); return drm_vblank_init(dev, 1); } diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 72ae8266b8e9d..0ebb7d4796faf 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -2115,6 +2115,8 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) break; } + pci_set_master(dev->pdev); + if (drm_pci_device_is_agp(dev)) dev_priv->flags |= RADEON_IS_AGP; else if (pci_is_pcie(dev->pdev)) diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index d3352889a8709..1986ebae1ef2f 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -57,6 +57,8 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) } dev->dev_private = (void *)rdev; + pci_set_master(dev->pdev); + /* update BUS flag */ if (drm_pci_device_is_agp(dev)) { flags |= RADEON_IS_AGP; diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 573220cc5269f..30d98d14b5c58 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -41,6 +41,8 @@ static int sis_driver_load(struct drm_device *dev, unsigned long chipset) { drm_sis_private_t *dev_priv; + pci_set_master(dev->pdev); + dev_priv = kzalloc(sizeof(drm_sis_private_t), GFP_KERNEL); if (dev_priv == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/via/via_map.c b/drivers/gpu/drm/via/via_map.c index a2ab343651518..1f182254e81e8 100644 --- a/drivers/gpu/drm/via/via_map.c +++ b/drivers/gpu/drm/via/via_map.c @@ -106,6 +106,8 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset) idr_init(&dev->object_name_idr); + pci_set_master(dev->pdev); + ret = drm_vblank_init(dev, 1); if (ret) { kfree(dev_priv); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index f076f66b1153c..1760aba9ecef2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -439,6 +439,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) } memset(dev_priv, 0, sizeof(*dev_priv)); + pci_set_master(dev->pdev); + dev_priv->dev = dev; dev_priv->vmw_chipset = chipset; dev_priv->last_read_seqno = (uint32_t) -100;