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)
|
int drm_init(struct drm_driver *driver)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = NULL;
|
struct pci_dev *pdev = NULL;
|
||||||
struct pci_device_id *pid;
|
const struct pci_device_id *pid;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
DRM_DEBUG("\n");
|
DRM_DEBUG("\n");
|
||||||
|
|
||||||
INIT_LIST_HEAD(&driver->device_list);
|
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++) {
|
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
|
/* Loop around setting up a DRM device for each PCI device
|
||||||
* matching our ID and device class. If we had the internal
|
* 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);
|
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)
|
void drm_exit(struct drm_driver *driver)
|
||||||
{
|
{
|
||||||
struct drm_device *dev, *tmp;
|
struct drm_device *dev, *tmp;
|
||||||
DRM_DEBUG("\n");
|
DRM_DEBUG("\n");
|
||||||
|
|
||||||
list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
|
if (driver->driver_features & DRIVER_MODESET) {
|
||||||
drm_cleanup(dev);
|
pci_unregister_driver(&driver->pci_driver);
|
||||||
|
} else {
|
||||||
|
list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
|
||||||
|
drm_put_dev(dev);
|
||||||
|
}
|
||||||
|
|
||||||
DRM_INFO("Module unloaded\n");
|
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)) {
|
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||||
|
pci_set_drvdata(pdev, dev);
|
||||||
ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
|
ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_g2;
|
goto err_g2;
|
||||||
|
@ -409,29 +410,7 @@ err_g1:
|
||||||
drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
|
drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(drm_get_dev);
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Put a secondary minor number.
|
* Put a secondary minor number.
|
||||||
|
@ -459,3 +438,67 @@ int drm_put_minor(struct drm_minor **minor_p)
|
||||||
*minor_p = NULL;
|
*minor_p = NULL;
|
||||||
return 0;
|
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_minor *drm_minor = to_drm_minor(dev);
|
||||||
struct drm_device *drm_dev = 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 drm_dev->driver->suspend(drm_dev, state);
|
||||||
|
|
||||||
return 0;
|
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_minor *drm_minor = to_drm_minor(dev);
|
||||||
struct drm_device *drm_dev = 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 drm_dev->driver->resume(drm_dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -42,6 +42,8 @@ module_param_named(modeset, i915_modeset, int, 0400);
|
||||||
unsigned int i915_fbpercrtc = 0;
|
unsigned int i915_fbpercrtc = 0;
|
||||||
module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
|
module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
|
||||||
|
|
||||||
|
static struct drm_driver driver;
|
||||||
|
|
||||||
static struct pci_device_id pciidlist[] = {
|
static struct pci_device_id pciidlist[] = {
|
||||||
i915_PCI_IDS
|
i915_PCI_IDS
|
||||||
};
|
};
|
||||||
|
@ -117,6 +119,36 @@ static int i915_resume(struct drm_device *dev)
|
||||||
return ret;
|
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 = {
|
static struct vm_operations_struct i915_gem_vm_ops = {
|
||||||
.fault = i915_gem_fault,
|
.fault = i915_gem_fault,
|
||||||
.open = drm_gem_vm_open,
|
.open = drm_gem_vm_open,
|
||||||
|
@ -172,6 +204,12 @@ static struct drm_driver driver = {
|
||||||
.pci_driver = {
|
.pci_driver = {
|
||||||
.name = DRIVER_NAME,
|
.name = DRIVER_NAME,
|
||||||
.id_table = pciidlist,
|
.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,
|
.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 void drm_master_put(struct drm_master **master);
|
||||||
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
|
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
|
||||||
struct drm_driver *driver);
|
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 int drm_put_minor(struct drm_minor **minor);
|
||||||
extern unsigned int drm_debug;
|
extern unsigned int drm_debug;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue