Skip to content

Commit

Permalink
drm: move pci bus master enable into driver.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dave Airlie committed Feb 16, 2012
1 parent 42b923b commit 466e69b
Show file tree
Hide file tree
Showing 12 changed files with 21 additions and 2 deletions.
2 changes: 0 additions & 2 deletions drivers/gpu/drm/drm_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/gma500/psb_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i810/i810_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/mga/mga_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/nouveau/nouveau_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/r128/r128_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/radeon/radeon_cp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/radeon/radeon_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/sis/sis_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/via/via_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 466e69b

Please sign in to comment.