aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_pci.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@gmail.com>2010-12-14 12:16:38 -0500
committerDave Airlie <airlied@redhat.com>2011-02-06 22:09:36 -0500
commit8410ea3b95d105a5be5db501656f44bbb91197c1 (patch)
tree6cd27f207e50c13ba2f4a78d6323bc23f751e380 /drivers/gpu/drm/drm_pci.c
parentff72145badb834e8051719ea66e024784d000cb4 (diff)
drm: rework PCI/platform driver interface.
This abstracts the pci/platform interface out a step further, we can go further but this is far enough for now to allow USB to be plugged in. The drivers now just call the init code directly for their device type. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_pci.c')
-rw-r--r--drivers/gpu/drm/drm_pci.c205
1 files changed, 199 insertions, 6 deletions
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index f5bd9e590c80..e1aee4f6a7c6 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -125,6 +125,176 @@ 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
254int 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 .agp_init = drm_pci_agp_init,
296};
297
128/** 298/**
129 * Register. 299 * Register.
130 * 300 *
@@ -219,7 +389,7 @@ err_g1:
219EXPORT_SYMBOL(drm_get_pci_dev); 389EXPORT_SYMBOL(drm_get_pci_dev);
220 390
221/** 391/**
222 * PCI device initialization. Called via drm_init at module load time, 392 * PCI device initialization. Called direct from modules at load time.
223 * 393 *
224 * \return zero on success or a negative number on failure. 394 * \return zero on success or a negative number on failure.
225 * 395 *
@@ -229,18 +399,24 @@ EXPORT_SYMBOL(drm_get_pci_dev);
229 * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and 399 * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
230 * after the initialization for driver customization. 400 * after the initialization for driver customization.
231 */ 401 */
232int drm_pci_init(struct drm_driver *driver) 402int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
233{ 403{
234 struct pci_dev *pdev = NULL; 404 struct pci_dev *pdev = NULL;
235 const struct pci_device_id *pid; 405 const struct pci_device_id *pid;
236 int i; 406 int i;
237 407
408 DRM_DEBUG("\n");
409
410 INIT_LIST_HEAD(&driver->device_list);
411 driver->kdriver.pci = pdriver;
412 driver->bus = &drm_pci_bus;
413
238 if (driver->driver_features & DRIVER_MODESET) 414 if (driver->driver_features & DRIVER_MODESET)
239 return pci_register_driver(&driver->pci_driver); 415 return pci_register_driver(pdriver);
240 416
241 /* If not using KMS, fall back to stealth mode manual scanning. */ 417 /* If not using KMS, fall back to stealth mode manual scanning. */
242 for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { 418 for (i = 0; pdriver->id_table[i].vendor != 0; i++) {
243 pid = &driver->pci_driver.id_table[i]; 419 pid = &pdriver->id_table[i];
244 420
245 /* Loop around setting up a DRM device for each PCI device 421 /* Loop around setting up a DRM device for each PCI device
246 * matching our ID and device class. If we had the internal 422 * matching our ID and device class. If we had the internal
@@ -265,10 +441,27 @@ int drm_pci_init(struct drm_driver *driver)
265 441
266#else 442#else
267 443
268int drm_pci_init(struct drm_driver *driver) 444int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
269{ 445{
270 return -1; 446 return -1;
271} 447}
272 448
273#endif 449#endif
450
451EXPORT_SYMBOL(drm_pci_init);
452
274/*@}*/ 453/*@}*/
454void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver)
455{
456 struct drm_device *dev, *tmp;
457 DRM_DEBUG("\n");
458
459 if (driver->driver_features & DRIVER_MODESET) {
460 pci_unregister_driver(pdriver);
461 } else {
462 list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
463 drm_put_dev(dev);
464 }
465 DRM_INFO("Module unloaded\n");
466}
467EXPORT_SYMBOL(drm_pci_exit);