aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_ioctl.c')
-rw-r--r--drivers/gpu/drm/drm_ioctl.c140
1 files changed, 106 insertions, 34 deletions
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 9b9ff46c2378..7b03b197fc00 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -64,6 +64,19 @@ int drm_getunique(struct drm_device *dev, void *data,
64 return 0; 64 return 0;
65} 65}
66 66
67static void
68drm_unset_busid(struct drm_device *dev,
69 struct drm_master *master)
70{
71 kfree(dev->devname);
72 dev->devname = NULL;
73
74 kfree(master->unique);
75 master->unique = NULL;
76 master->unique_len = 0;
77 master->unique_size = 0;
78}
79
67/** 80/**
68 * Set the bus id. 81 * Set the bus id.
69 * 82 *
@@ -94,17 +107,24 @@ int drm_setunique(struct drm_device *dev, void *data,
94 master->unique_len = u->unique_len; 107 master->unique_len = u->unique_len;
95 master->unique_size = u->unique_len + 1; 108 master->unique_size = u->unique_len + 1;
96 master->unique = kmalloc(master->unique_size, GFP_KERNEL); 109 master->unique = kmalloc(master->unique_size, GFP_KERNEL);
97 if (!master->unique) 110 if (!master->unique) {
98 return -ENOMEM; 111 ret = -ENOMEM;
99 if (copy_from_user(master->unique, u->unique, master->unique_len)) 112 goto err;
100 return -EFAULT; 113 }
114
115 if (copy_from_user(master->unique, u->unique, master->unique_len)) {
116 ret = -EFAULT;
117 goto err;
118 }
101 119
102 master->unique[master->unique_len] = '\0'; 120 master->unique[master->unique_len] = '\0';
103 121
104 dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) + 122 dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
105 strlen(master->unique) + 2, GFP_KERNEL); 123 strlen(master->unique) + 2, GFP_KERNEL);
106 if (!dev->devname) 124 if (!dev->devname) {
107 return -ENOMEM; 125 ret = -ENOMEM;
126 goto err;
127 }
108 128
109 sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, 129 sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
110 master->unique); 130 master->unique);
@@ -113,53 +133,103 @@ int drm_setunique(struct drm_device *dev, void *data,
113 * busid. 133 * busid.
114 */ 134 */
115 ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func); 135 ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
116 if (ret != 3) 136 if (ret != 3) {
117 return -EINVAL; 137 ret = -EINVAL;
138 goto err;
139 }
140
118 domain = bus >> 8; 141 domain = bus >> 8;
119 bus &= 0xff; 142 bus &= 0xff;
120 143
121 if ((domain != drm_get_pci_domain(dev)) || 144 if ((domain != drm_get_pci_domain(dev)) ||
122 (bus != dev->pdev->bus->number) || 145 (bus != dev->pdev->bus->number) ||
123 (slot != PCI_SLOT(dev->pdev->devfn)) || 146 (slot != PCI_SLOT(dev->pdev->devfn)) ||
124 (func != PCI_FUNC(dev->pdev->devfn))) 147 (func != PCI_FUNC(dev->pdev->devfn))) {
125 return -EINVAL; 148 ret = -EINVAL;
149 goto err;
150 }
126 151
127 return 0; 152 return 0;
153
154err:
155 drm_unset_busid(dev, master);
156 return ret;
128} 157}
129 158
130static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) 159static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
131{ 160{
132 struct drm_master *master = file_priv->master; 161 struct drm_master *master = file_priv->master;
133 int len; 162 int len, ret;
134 163
135 if (master->unique != NULL) 164 if (master->unique != NULL)
136 return -EBUSY; 165 drm_unset_busid(dev, master);
137 166
138 master->unique_len = 40; 167 if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) {
139 master->unique_size = master->unique_len; 168 master->unique_len = 10 + strlen(dev->platformdev->name);
140 master->unique = kmalloc(master->unique_size, GFP_KERNEL); 169 master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
141 if (master->unique == NULL)
142 return -ENOMEM;
143
144 len = snprintf(master->unique, master->unique_len, "pci:%04x:%02x:%02x.%d",
145 drm_get_pci_domain(dev),
146 dev->pdev->bus->number,
147 PCI_SLOT(dev->pdev->devfn),
148 PCI_FUNC(dev->pdev->devfn));
149 if (len >= master->unique_len)
150 DRM_ERROR("buffer overflow");
151 else
152 master->unique_len = len;
153 170
154 dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) + 171 if (master->unique == NULL)
155 master->unique_len + 2, GFP_KERNEL); 172 return -ENOMEM;
156 if (dev->devname == NULL)
157 return -ENOMEM;
158 173
159 sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, 174 len = snprintf(master->unique, master->unique_len,
160 master->unique); 175 "platform:%s", dev->platformdev->name);
176
177 if (len > master->unique_len) {
178 DRM_ERROR("Unique buffer overflowed\n");
179 ret = -EINVAL;
180 goto err;
181 }
182
183 dev->devname =
184 kmalloc(strlen(dev->platformdev->name) +
185 master->unique_len + 2, GFP_KERNEL);
186
187 if (dev->devname == NULL) {
188 ret = -ENOMEM;
189 goto err;
190 }
191
192 sprintf(dev->devname, "%s@%s", dev->platformdev->name,
193 master->unique);
194
195 } else {
196 master->unique_len = 40;
197 master->unique_size = master->unique_len;
198 master->unique = kmalloc(master->unique_size, GFP_KERNEL);
199 if (master->unique == NULL)
200 return -ENOMEM;
201
202 len = snprintf(master->unique, master->unique_len,
203 "pci:%04x:%02x:%02x.%d",
204 drm_get_pci_domain(dev),
205 dev->pdev->bus->number,
206 PCI_SLOT(dev->pdev->devfn),
207 PCI_FUNC(dev->pdev->devfn));
208 if (len >= master->unique_len) {
209 DRM_ERROR("buffer overflow");
210 ret = -EINVAL;
211 goto err;
212 } else
213 master->unique_len = len;
214
215 dev->devname =
216 kmalloc(strlen(dev->driver->pci_driver.name) +
217 master->unique_len + 2, GFP_KERNEL);
218
219 if (dev->devname == NULL) {
220 ret = -ENOMEM;
221 goto err;
222 }
223
224 sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
225 master->unique);
226 }
161 227
162 return 0; 228 return 0;
229
230err:
231 drm_unset_busid(dev, master);
232 return ret;
163} 233}
164 234
165/** 235/**
@@ -323,7 +393,9 @@ int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_pri
323 /* 393 /*
324 * Version 1.1 includes tying of DRM to specific device 394 * Version 1.1 includes tying of DRM to specific device
325 */ 395 */
326 drm_set_busid(dev, file_priv); 396 retcode = drm_set_busid(dev, file_priv);
397 if (retcode)
398 goto done;
327 } 399 }
328 } 400 }
329 401