drm: claim PCI device when running in modesetting mode.
Under kernel modesetting, we manage the device at all times, regardless of VT switching and X servers, so the only decent thing to do is to claim the PCI device. In that case, we call the suspend/resume hooks directly from the pci driver hooks instead of the current class device detour. Signed-off-by: Kristian Høgsberg <krh@redhat.com> Signed-off-by: Dave Airlie <airlied@linux.ie>
This commit is contained in:
parent
41c2e75e60
commit
112b715e8e
|
@ -252,15 +252,19 @@ int drm_lastclose(struct drm_device * dev)
|
|||
int drm_init(struct drm_driver *driver)
|
||||
{
|
||||
struct pci_dev *pdev = NULL;
|
||||
struct pci_device_id *pid;
|
||||
const struct pci_device_id *pid;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
INIT_LIST_HEAD(&driver->device_list);
|
||||
|
||||
if (driver->driver_features & DRIVER_MODESET)
|
||||
return pci_register_driver(&driver->pci_driver);
|
||||
|
||||
/* If not using KMS, fall back to stealth mode manual scanning. */
|
||||
for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
|
||||
pid = (struct pci_device_id *)&driver->pci_driver.id_table[i];
|
||||
pid = &driver->pci_driver.id_table[i];
|
||||
|
||||
/* Loop around setting up a DRM device for each PCI device
|
||||
* matching our ID and device class. If we had the internal
|
||||
|
@ -285,68 +289,17 @@ int drm_init(struct drm_driver *driver)
|
|||
|
||||
EXPORT_SYMBOL(drm_init);
|
||||
|
||||
/**
|
||||
* Called via cleanup_module() at module unload time.
|
||||
*
|
||||
* Cleans up all DRM device, calling drm_lastclose().
|
||||
*
|
||||
* \sa drm_init
|
||||
*/
|
||||
static void drm_cleanup(struct drm_device * dev)
|
||||
{
|
||||
struct drm_map_list *r_list, *list_temp;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (!dev) {
|
||||
DRM_ERROR("cleanup called no dev\n");
|
||||
return;
|
||||
}
|
||||
|
||||
drm_vblank_cleanup(dev);
|
||||
|
||||
drm_lastclose(dev);
|
||||
|
||||
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
|
||||
dev->agp && dev->agp->agp_mtrr >= 0) {
|
||||
int retval;
|
||||
retval = mtrr_del(dev->agp->agp_mtrr,
|
||||
dev->agp->agp_info.aper_base,
|
||||
dev->agp->agp_info.aper_size * 1024 * 1024);
|
||||
DRM_DEBUG("mtrr_del=%d\n", retval);
|
||||
}
|
||||
|
||||
if (dev->driver->unload)
|
||||
dev->driver->unload(dev);
|
||||
|
||||
if (drm_core_has_AGP(dev) && dev->agp) {
|
||||
drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
|
||||
dev->agp = NULL;
|
||||
}
|
||||
|
||||
drm_ht_remove(&dev->map_hash);
|
||||
drm_ctxbitmap_cleanup(dev);
|
||||
|
||||
list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
|
||||
drm_rmmap(dev, r_list->map);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_put_minor(&dev->control);
|
||||
|
||||
if (dev->driver->driver_features & DRIVER_GEM)
|
||||
drm_gem_destroy(dev);
|
||||
|
||||
drm_put_minor(&dev->primary);
|
||||
if (drm_put_dev(dev))
|
||||
DRM_ERROR("Cannot unload module\n");
|
||||
}
|
||||
|
||||
void drm_exit(struct drm_driver *driver)
|
||||
{
|
||||
struct drm_device *dev, *tmp;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (driver->driver_features & DRIVER_MODESET) {
|
||||
pci_unregister_driver(&driver->pci_driver);
|
||||
} else {
|
||||
list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
|
||||
drm_cleanup(dev);
|
||||
drm_put_dev(dev);
|
||||
}
|
||||
|
||||
DRM_INFO("Module unloaded\n");
|
||||
}
|
||||
|
|
|
@ -372,6 +372,7 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
|
|||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
pci_set_drvdata(pdev, dev);
|
||||
ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
|
||||
if (ret)
|
||||
goto err_g2;
|
||||
|
@ -409,29 +410,7 @@ err_g1:
|
|||
drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a device minor number.
|
||||
*
|
||||
* \param dev device data structure
|
||||
* \return always zero
|
||||
*
|
||||
* Cleans up the proc resources. If it is the last minor then release the foreign
|
||||
* "drm" data, otherwise unregisters the "drm" data, frees the dev list and
|
||||
* unregisters the character device.
|
||||
*/
|
||||
int drm_put_dev(struct drm_device * dev)
|
||||
{
|
||||
DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
|
||||
|
||||
if (dev->devname) {
|
||||
drm_free(dev->devname, strlen(dev->devname) + 1,
|
||||
DRM_MEM_DRIVER);
|
||||
dev->devname = NULL;
|
||||
}
|
||||
drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_get_dev);
|
||||
|
||||
/**
|
||||
* Put a secondary minor number.
|
||||
|
@ -459,3 +438,67 @@ int drm_put_minor(struct drm_minor **minor_p)
|
|||
*minor_p = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called via drm_exit() at module unload time or when pci device is
|
||||
* unplugged.
|
||||
*
|
||||
* Cleans up all DRM device, calling drm_lastclose().
|
||||
*
|
||||
* \sa drm_init
|
||||
*/
|
||||
void drm_put_dev(struct drm_device *dev)
|
||||
{
|
||||
struct drm_driver *driver = dev->driver;
|
||||
struct drm_map_list *r_list, *list_temp;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (!dev) {
|
||||
DRM_ERROR("cleanup called no dev\n");
|
||||
return;
|
||||
}
|
||||
|
||||
drm_vblank_cleanup(dev);
|
||||
|
||||
drm_lastclose(dev);
|
||||
|
||||
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
|
||||
dev->agp && dev->agp->agp_mtrr >= 0) {
|
||||
int retval;
|
||||
retval = mtrr_del(dev->agp->agp_mtrr,
|
||||
dev->agp->agp_info.aper_base,
|
||||
dev->agp->agp_info.aper_size * 1024 * 1024);
|
||||
DRM_DEBUG("mtrr_del=%d\n", retval);
|
||||
}
|
||||
|
||||
if (dev->driver->unload)
|
||||
dev->driver->unload(dev);
|
||||
|
||||
if (drm_core_has_AGP(dev) && dev->agp) {
|
||||
drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
|
||||
dev->agp = NULL;
|
||||
}
|
||||
|
||||
drm_ht_remove(&dev->map_hash);
|
||||
drm_ctxbitmap_cleanup(dev);
|
||||
|
||||
list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
|
||||
drm_rmmap(dev, r_list->map);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_put_minor(&dev->control);
|
||||
|
||||
if (driver->driver_features & DRIVER_GEM)
|
||||
drm_gem_destroy(dev);
|
||||
|
||||
drm_put_minor(&dev->primary);
|
||||
|
||||
if (dev->devname) {
|
||||
drm_free(dev->devname, strlen(dev->devname) + 1,
|
||||
DRM_MEM_DRIVER);
|
||||
dev->devname = NULL;
|
||||
}
|
||||
drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_put_dev);
|
||||
|
|
|
@ -35,7 +35,9 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
|
|||
struct drm_minor *drm_minor = to_drm_minor(dev);
|
||||
struct drm_device *drm_dev = drm_minor->dev;
|
||||
|
||||
if (drm_minor->type == DRM_MINOR_LEGACY && drm_dev->driver->suspend)
|
||||
if (drm_minor->type == DRM_MINOR_LEGACY &&
|
||||
!drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
|
||||
drm_dev->driver->suspend)
|
||||
return drm_dev->driver->suspend(drm_dev, state);
|
||||
|
||||
return 0;
|
||||
|
@ -53,7 +55,9 @@ static int drm_sysfs_resume(struct device *dev)
|
|||
struct drm_minor *drm_minor = to_drm_minor(dev);
|
||||
struct drm_device *drm_dev = drm_minor->dev;
|
||||
|
||||
if (drm_minor->type == DRM_MINOR_LEGACY && drm_dev->driver->resume)
|
||||
if (drm_minor->type == DRM_MINOR_LEGACY &&
|
||||
!drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
|
||||
drm_dev->driver->resume)
|
||||
return drm_dev->driver->resume(drm_dev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -42,6 +42,8 @@ module_param_named(modeset, i915_modeset, int, 0400);
|
|||
unsigned int i915_fbpercrtc = 0;
|
||||
module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
|
||||
|
||||
static struct drm_driver driver;
|
||||
|
||||
static struct pci_device_id pciidlist[] = {
|
||||
i915_PCI_IDS
|
||||
};
|
||||
|
@ -117,6 +119,36 @@ static int i915_resume(struct drm_device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __devinit
|
||||
i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
return drm_get_dev(pdev, ent, &driver);
|
||||
}
|
||||
|
||||
static void
|
||||
i915_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
|
||||
drm_put_dev(dev);
|
||||
}
|
||||
|
||||
static int
|
||||
i915_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
{
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
|
||||
return i915_suspend(dev, state);
|
||||
}
|
||||
|
||||
static int
|
||||
i915_pci_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
|
||||
return i915_resume(dev);
|
||||
}
|
||||
|
||||
static struct vm_operations_struct i915_gem_vm_ops = {
|
||||
.fault = i915_gem_fault,
|
||||
.open = drm_gem_vm_open,
|
||||
|
@ -172,6 +204,12 @@ static struct drm_driver driver = {
|
|||
.pci_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = pciidlist,
|
||||
.probe = i915_pci_probe,
|
||||
.remove = i915_pci_remove,
|
||||
#ifdef CONFIG_PM
|
||||
.resume = i915_pci_resume,
|
||||
.suspend = i915_pci_suspend,
|
||||
#endif
|
||||
},
|
||||
|
||||
.name = DRIVER_NAME,
|
||||
|
|
|
@ -1265,7 +1265,7 @@ extern struct drm_master *drm_master_get(struct drm_master *master);
|
|||
extern void drm_master_put(struct drm_master **master);
|
||||
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
|
||||
struct drm_driver *driver);
|
||||
extern int drm_put_dev(struct drm_device *dev);
|
||||
extern void drm_put_dev(struct drm_device *dev);
|
||||
extern int drm_put_minor(struct drm_minor **minor);
|
||||
extern unsigned int drm_debug;
|
||||
|
||||
|
|
Loading…
Reference in New Issue