drm: move pci bus master enable into driver.
authorDave Airlie <airlied@redhat.com>
Mon, 19 Dec 2011 11:15:29 +0000 (11:15 +0000)
committerDave Airlie <airlied@redhat.com>
Thu, 16 Feb 2012 18:31:07 +0000 (18:31 +0000)
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 <airlied@redhat.com>
12 files changed:
drivers/gpu/drm/drm_pci.c
drivers/gpu/drm/gma500/psb_drv.c
drivers/gpu/drm/i810/i810_dma.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/mga/mga_dma.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/r128/r128_drv.c
drivers/gpu/drm/radeon/radeon_cp.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/sis/sis_drv.c
drivers/gpu/drm/via/via_map.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c

index d4d10b7880cf8b96303d6c539ff09a08299241f2..13f3d936472f3aadeed78ca465b2cf4feef617ff 100644 (file)
@@ -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;
 
index f14768f2b364e78da7afd88521a108e365c1b7b7..1f57aac2cf80804881a1f3e1845be98b445e2154 100644 (file)
@@ -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");
index 7f4b4e10246ecfbb087ac825c1969b69dc9742c5..64a989ed5b8ff93beddeca17baeda427f9a212ca 100644 (file)
@@ -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;
 }
 
index 8919dcc07ed897b71b6c6b0fdbc9feed605afc39..a8081f2efaea662f1c705db118700853a8d07cb0 100644 (file)
@@ -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));
index 5ccb65deb83c2f956eb67a1adbf505c8d1e8d382..507aa3df0168961a90f751b05caa72164d8474c2 100644 (file)
@@ -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);
 
index f80c5e0762ff90b4c29ec186ee1c5c4017f2fc7d..912839c2bc16fb67fc8408f2c412b162b71a2a57 100644 (file)
@@ -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",
index 6a5f4395838f712bc03bc0c70e9c34777ba37051..88718fad5d6db1093d0a795c6076bb04c5f8cd65 100644 (file)
@@ -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);
 }
 
index 72ae8266b8e9d88edaa7d8369e7512cbde13c734..0ebb7d4796faf4bd105af073b5b2d6bfd4f56ab1 100644 (file)
@@ -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))
index d3352889a8709e79650647bb0dc5b2fd31ebf79f..1986ebae1ef2f55b65f85b5685229ce3cb020666 100644 (file)
@@ -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;
index 573220cc5269fe48d6f0a5fb972c33c5731bb1af..30d98d14b5c586bd6d53a845488c2368a7ab9bc4 100644 (file)
@@ -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;
index a2ab343651518d948d830d237f493b27534bf945..1f182254e81e84beb0c4ed613c02e081ebf38258 100644 (file)
@@ -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);
index f076f66b1153c8509611105c6c94743b44d3458e..1760aba9ecef2314e722e13b698555ffc8dfd9b3 100644 (file)
@@ -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;