diff options
author | Dave Airlie <airlied@redhat.com> | 2008-11-27 23:22:24 -0500 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2008-12-29 02:47:22 -0500 |
commit | 7c1c2871a6a3a114853ec6836e9035ac1c0c7f7a (patch) | |
tree | 1b5debcc86ff20bd5e11b42ea5c52da42214e376 /drivers/gpu/drm/drm_ioctl.c | |
parent | e7f7ab45ebcb54fd5f814ea15ea079e079662f67 (diff) |
drm: move to kref per-master structures.
This is step one towards having multiple masters sharing a drm
device in order to get fast-user-switching to work.
It splits out the information associated with the drm master
into a separate kref counted structure, and allocates this when
a master opens the device node. It also allows the current master
to abdicate (say while VT switched), and a new master to take over
the hardware.
It moves the Intel and radeon drivers to using the sarea from
within the new master structures.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_ioctl.c')
-rw-r--r-- | drivers/gpu/drm/drm_ioctl.c | 57 |
1 files changed, 30 insertions, 27 deletions
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 16829fb3089d..e35126a35093 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c | |||
@@ -53,12 +53,13 @@ int drm_getunique(struct drm_device *dev, void *data, | |||
53 | struct drm_file *file_priv) | 53 | struct drm_file *file_priv) |
54 | { | 54 | { |
55 | struct drm_unique *u = data; | 55 | struct drm_unique *u = data; |
56 | struct drm_master *master = file_priv->master; | ||
56 | 57 | ||
57 | if (u->unique_len >= dev->unique_len) { | 58 | if (u->unique_len >= master->unique_len) { |
58 | if (copy_to_user(u->unique, dev->unique, dev->unique_len)) | 59 | if (copy_to_user(u->unique, master->unique, master->unique_len)) |
59 | return -EFAULT; | 60 | return -EFAULT; |
60 | } | 61 | } |
61 | u->unique_len = dev->unique_len; | 62 | u->unique_len = master->unique_len; |
62 | 63 | ||
63 | return 0; | 64 | return 0; |
64 | } | 65 | } |
@@ -81,36 +82,37 @@ int drm_setunique(struct drm_device *dev, void *data, | |||
81 | struct drm_file *file_priv) | 82 | struct drm_file *file_priv) |
82 | { | 83 | { |
83 | struct drm_unique *u = data; | 84 | struct drm_unique *u = data; |
85 | struct drm_master *master = file_priv->master; | ||
84 | int domain, bus, slot, func, ret; | 86 | int domain, bus, slot, func, ret; |
85 | 87 | ||
86 | if (dev->unique_len || dev->unique) | 88 | if (master->unique_len || master->unique) |
87 | return -EBUSY; | 89 | return -EBUSY; |
88 | 90 | ||
89 | if (!u->unique_len || u->unique_len > 1024) | 91 | if (!u->unique_len || u->unique_len > 1024) |
90 | return -EINVAL; | 92 | return -EINVAL; |
91 | 93 | ||
92 | dev->unique_len = u->unique_len; | 94 | master->unique_len = u->unique_len; |
93 | dev->unique = drm_alloc(u->unique_len + 1, DRM_MEM_DRIVER); | 95 | master->unique = drm_alloc(u->unique_len + 1, DRM_MEM_DRIVER); |
94 | if (!dev->unique) | 96 | if (!master->unique) |
95 | return -ENOMEM; | 97 | return -ENOMEM; |
96 | if (copy_from_user(dev->unique, u->unique, dev->unique_len)) | 98 | if (copy_from_user(master->unique, u->unique, master->unique_len)) |
97 | return -EFAULT; | 99 | return -EFAULT; |
98 | 100 | ||
99 | dev->unique[dev->unique_len] = '\0'; | 101 | master->unique[master->unique_len] = '\0'; |
100 | 102 | ||
101 | dev->devname = | 103 | dev->devname = |
102 | drm_alloc(strlen(dev->driver->pci_driver.name) + | 104 | drm_alloc(strlen(dev->driver->pci_driver.name) + |
103 | strlen(dev->unique) + 2, DRM_MEM_DRIVER); | 105 | strlen(master->unique) + 2, DRM_MEM_DRIVER); |
104 | if (!dev->devname) | 106 | if (!dev->devname) |
105 | return -ENOMEM; | 107 | return -ENOMEM; |
106 | 108 | ||
107 | sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, | 109 | sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, |
108 | dev->unique); | 110 | master->unique); |
109 | 111 | ||
110 | /* Return error if the busid submitted doesn't match the device's actual | 112 | /* Return error if the busid submitted doesn't match the device's actual |
111 | * busid. | 113 | * busid. |
112 | */ | 114 | */ |
113 | ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func); | 115 | ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func); |
114 | if (ret != 3) | 116 | if (ret != 3) |
115 | return -EINVAL; | 117 | return -EINVAL; |
116 | domain = bus >> 8; | 118 | domain = bus >> 8; |
@@ -125,34 +127,35 @@ int drm_setunique(struct drm_device *dev, void *data, | |||
125 | return 0; | 127 | return 0; |
126 | } | 128 | } |
127 | 129 | ||
128 | static int drm_set_busid(struct drm_device * dev) | 130 | static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) |
129 | { | 131 | { |
132 | struct drm_master *master = file_priv->master; | ||
130 | int len; | 133 | int len; |
131 | 134 | ||
132 | if (dev->unique != NULL) | 135 | if (master->unique != NULL) |
133 | return 0; | 136 | return -EBUSY; |
134 | 137 | ||
135 | dev->unique_len = 40; | 138 | master->unique_len = 40; |
136 | dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER); | 139 | master->unique = drm_alloc(master->unique_len + 1, DRM_MEM_DRIVER); |
137 | if (dev->unique == NULL) | 140 | if (master->unique == NULL) |
138 | return -ENOMEM; | 141 | return -ENOMEM; |
139 | 142 | ||
140 | len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d", | 143 | len = snprintf(master->unique, master->unique_len, "pci:%04x:%02x:%02x.%d", |
141 | drm_get_pci_domain(dev), dev->pdev->bus->number, | 144 | drm_get_pci_domain(dev), |
145 | dev->pdev->bus->number, | ||
142 | PCI_SLOT(dev->pdev->devfn), | 146 | PCI_SLOT(dev->pdev->devfn), |
143 | PCI_FUNC(dev->pdev->devfn)); | 147 | PCI_FUNC(dev->pdev->devfn)); |
144 | 148 | if (len > master->unique_len) | |
145 | if (len > dev->unique_len) | 149 | DRM_ERROR("buffer overflow"); |
146 | DRM_ERROR("Unique buffer overflowed\n"); | ||
147 | 150 | ||
148 | dev->devname = | 151 | dev->devname = |
149 | drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len + | 152 | drm_alloc(strlen(dev->driver->pci_driver.name) + master->unique_len + |
150 | 2, DRM_MEM_DRIVER); | 153 | 2, DRM_MEM_DRIVER); |
151 | if (dev->devname == NULL) | 154 | if (dev->devname == NULL) |
152 | return -ENOMEM; | 155 | return -ENOMEM; |
153 | 156 | ||
154 | sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, | 157 | sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, |
155 | dev->unique); | 158 | master->unique); |
156 | 159 | ||
157 | return 0; | 160 | return 0; |
158 | } | 161 | } |
@@ -276,7 +279,7 @@ int drm_getstats(struct drm_device *dev, void *data, | |||
276 | for (i = 0; i < dev->counters; i++) { | 279 | for (i = 0; i < dev->counters; i++) { |
277 | if (dev->types[i] == _DRM_STAT_LOCK) | 280 | if (dev->types[i] == _DRM_STAT_LOCK) |
278 | stats->data[i].value = | 281 | stats->data[i].value = |
279 | (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0); | 282 | (file_priv->master->lock.hw_lock ? file_priv->master->lock.hw_lock->lock : 0); |
280 | else | 283 | else |
281 | stats->data[i].value = atomic_read(&dev->counts[i]); | 284 | stats->data[i].value = atomic_read(&dev->counts[i]); |
282 | stats->data[i].type = dev->types[i]; | 285 | stats->data[i].type = dev->types[i]; |
@@ -318,7 +321,7 @@ int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_pri | |||
318 | /* | 321 | /* |
319 | * Version 1.1 includes tying of DRM to specific device | 322 | * Version 1.1 includes tying of DRM to specific device |
320 | */ | 323 | */ |
321 | drm_set_busid(dev); | 324 | drm_set_busid(dev, file_priv); |
322 | } | 325 | } |
323 | } | 326 | } |
324 | 327 | ||