aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_pci.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/gpu/drm/drm_pci.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/gpu/drm/drm_pci.c')
-rw-r--r--drivers/gpu/drm/drm_pci.c206
1 files changed, 200 insertions, 6 deletions
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index f5bd9e590c80..b6a19cb07caf 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -125,6 +125,177 @@ void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
125EXPORT_SYMBOL(drm_pci_free); 125EXPORT_SYMBOL(drm_pci_free);
126 126
127#ifdef CONFIG_PCI 127#ifdef CONFIG_PCI
128
129static int drm_get_pci_domain(struct drm_device *dev)
130{
131#ifndef __alpha__
132 /* For historical reasons, drm_get_pci_domain() is busticated
133 * on most archs and has to remain so for userspace interface
134 * < 1.4, except on alpha which was right from the beginning
135 */
136 if (dev->if_version < 0x10004)
137 return 0;
138#endif /* __alpha__ */
139
140 return pci_domain_nr(dev->pdev->bus);
141}
142
143static int drm_pci_get_irq(struct drm_device *dev)
144{
145 return dev->pdev->irq;
146}
147
148static const char *drm_pci_get_name(struct drm_device *dev)
149{
150 struct pci_driver *pdriver = dev->driver->kdriver.pci;
151 return pdriver->name;
152}
153
154int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master)
155{
156 int len, ret;
157 struct pci_driver *pdriver = dev->driver->kdriver.pci;
158 master->unique_len = 40;
159 master->unique_size = master->unique_len;
160 master->unique = kmalloc(master->unique_size, GFP_KERNEL);
161 if (master->unique == NULL)
162 return -ENOMEM;
163
164
165 len = snprintf(master->unique, master->unique_len,
166 "pci:%04x:%02x:%02x.%d",
167 drm_get_pci_domain(dev),
168 dev->pdev->bus->number,
169 PCI_SLOT(dev->pdev->devfn),
170 PCI_FUNC(dev->pdev->devfn));
171
172 if (len >= master->unique_len) {
173 DRM_ERROR("buffer overflow");
174 ret = -EINVAL;
175 goto err;
176 } else
177 master->unique_len = len;
178
179 dev->devname =
180 kmalloc(strlen(pdriver->name) +
181 master->unique_len + 2, GFP_KERNEL);
182
183 if (dev->devname == NULL) {
184 ret = -ENOMEM;
185 goto err;
186 }
187
188 sprintf(dev->devname, "%s@%s", pdriver->name,
189 master->unique);
190
191 return 0;
192err:
193 return ret;
194}
195
196int drm_pci_set_unique(struct drm_device *dev,
197 struct drm_master *master,
198 struct drm_unique *u)
199{
200 int domain, bus, slot, func, ret;
201 const char *bus_name;
202
203 master->unique_len = u->unique_len;
204 master->unique_size = u->unique_len + 1;
205 master->unique = kmalloc(master->unique_size, GFP_KERNEL);
206 if (!master->unique) {
207 ret = -ENOMEM;
208 goto err;
209 }
210
211 if (copy_from_user(master->unique, u->unique, master->unique_len)) {
212 ret = -EFAULT;
213 goto err;
214 }
215
216 master->unique[master->unique_len] = '\0';
217
218 bus_name = dev->driver->bus->get_name(dev);
219 dev->devname = kmalloc(strlen(bus_name) +
220 strlen(master->unique) + 2, GFP_KERNEL);
221 if (!dev->devname) {
222 ret = -ENOMEM;
223 goto err;
224 }
225
226 sprintf(dev->devname, "%s@%s", bus_name,
227 master->unique);
228
229 /* Return error if the busid submitted doesn't match the device's actual
230 * busid.
231 */
232 ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
233 if (ret != 3) {
234 ret = -EINVAL;
235 goto err;
236 }
237
238 domain = bus >> 8;
239 bus &= 0xff;
240
241 if ((domain != drm_get_pci_domain(dev)) ||
242 (bus != dev->pdev->bus->number) ||
243 (slot != PCI_SLOT(dev->pdev->devfn)) ||
244 (func != PCI_FUNC(dev->pdev->devfn))) {
245 ret = -EINVAL;
246 goto err;
247 }
248 return 0;
249err:
250 return ret;
251}
252
253
254static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
255{
256 if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
257 (p->busnum & 0xff) != dev->pdev->bus->number ||
258 p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
259 return -EINVAL;
260
261 p->irq = dev->pdev->irq;
262
263 DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
264 p->irq);
265 return 0;
266}
267
268int drm_pci_agp_init(struct drm_device *dev)
269{
270 if (drm_core_has_AGP(dev)) {
271 if (drm_pci_device_is_agp(dev))
272 dev->agp = drm_agp_init(dev);
273 if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
274 && (dev->agp == NULL)) {
275 DRM_ERROR("Cannot initialize the agpgart module.\n");
276 return -EINVAL;
277 }
278 if (drm_core_has_MTRR(dev)) {
279 if (dev->agp)
280 dev->agp->agp_mtrr =
281 mtrr_add(dev->agp->agp_info.aper_base,
282 dev->agp->agp_info.aper_size *
283 1024 * 1024, MTRR_TYPE_WRCOMB, 1);
284 }
285 }
286 return 0;
287}
288
289static struct drm_bus drm_pci_bus = {
290 .bus_type = DRIVER_BUS_PCI,
291 .get_irq = drm_pci_get_irq,
292 .get_name = drm_pci_get_name,
293 .set_busid = drm_pci_set_busid,
294 .set_unique = drm_pci_set_unique,
295 .irq_by_busid = drm_pci_irq_by_busid,
296 .agp_init = drm_pci_agp_init,
297};
298
128/** 299/**
129 * Register. 300 * Register.
130 * 301 *
@@ -219,7 +390,7 @@ err_g1:
219EXPORT_SYMBOL(drm_get_pci_dev); 390EXPORT_SYMBOL(drm_get_pci_dev);
220 391
221/** 392/**
222 * PCI device initialization. Called via drm_init at module load time, 393 * PCI device initialization. Called direct from modules at load time.
223 * 394 *
224 * \return zero on success or a negative number on failure. 395 * \return zero on success or a negative number on failure.
225 * 396 *
@@ -229,18 +400,24 @@ EXPORT_SYMBOL(drm_get_pci_dev);
229 * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and 400 * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
230 * after the initialization for driver customization. 401 * after the initialization for driver customization.
231 */ 402 */
232int drm_pci_init(struct drm_driver *driver) 403int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
233{ 404{
234 struct pci_dev *pdev = NULL; 405 struct pci_dev *pdev = NULL;
235 const struct pci_device_id *pid; 406 const struct pci_device_id *pid;
236 int i; 407 int i;
237 408
409 DRM_DEBUG("\n");
410
411 INIT_LIST_HEAD(&driver->device_list);
412 driver->kdriver.pci = pdriver;
413 driver->bus = &drm_pci_bus;
414
238 if (driver->driver_features & DRIVER_MODESET) 415 if (driver->driver_features & DRIVER_MODESET)
239 return pci_register_driver(&driver->pci_driver); 416 return pci_register_driver(pdriver);
240 417
241 /* If not using KMS, fall back to stealth mode manual scanning. */ 418 /* If not using KMS, fall back to stealth mode manual scanning. */
242 for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { 419 for (i = 0; pdriver->id_table[i].vendor != 0; i++) {
243 pid = &driver->pci_driver.id_table[i]; 420 pid = &pdriver->id_table[i];
244 421
245 /* Loop around setting up a DRM device for each PCI device 422 /* Loop around setting up a DRM device for each PCI device
246 * matching our ID and device class. If we had the internal 423 * matching our ID and device class. If we had the internal
@@ -265,10 +442,27 @@ int drm_pci_init(struct drm_driver *driver)
265 442
266#else 443#else
267 444
268int drm_pci_init(struct drm_driver *driver) 445int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
269{ 446{
270 return -1; 447 return -1;
271} 448}
272 449
273#endif 450#endif
451
452EXPORT_SYMBOL(drm_pci_init);
453
274/*@}*/ 454/*@}*/
455void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver)
456{
457 struct drm_device *dev, *tmp;
458 DRM_DEBUG("\n");
459
460 if (driver->driver_features & DRIVER_MODESET) {
461 pci_unregister_driver(pdriver);
462 } else {
463 list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
464 drm_put_dev(dev);
465 }
466 DRM_INFO("Module unloaded\n");
467}
468EXPORT_SYMBOL(drm_pci_exit);