1 /* 2 * Copyright © 2015 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 * Authors: 24 * Rafael Antognolli <rafael.antognolli@intel.com> 25 * 26 */ 27 28 #include <linux/device.h> 29 #include <linux/fs.h> 30 #include <drm/drmP.h> 31 #include <linux/slab.h> 32 #include <linux/kernel.h> 33 #include <linux/module.h> 34 #include <linux/uaccess.h> 35 #include <drm/drm_dp_helper.h> 36 #include <drm/drm_crtc.h> 37 38 #include "drm_crtc_helper_internal.h" 39 40 struct drm_dp_aux_dev { 41 unsigned index; 42 struct drm_dp_aux *aux; 43 struct device *dev; 44 struct kref refcount; 45 atomic_t usecount; 46 }; 47 48 #define DRM_AUX_MINORS 256 49 #define AUX_MAX_OFFSET (1 << 20) 50 #if 0 51 static DEFINE_IDR(aux_idr); 52 static DEFINE_MUTEX(aux_idr_mutex); 53 static struct class *drm_dp_aux_dev_class; 54 static int drm_dev_major = -1; 55 56 static struct drm_dp_aux_dev *drm_dp_aux_dev_get_by_minor(unsigned index) 57 { 58 struct drm_dp_aux_dev *aux_dev = NULL; 59 60 mutex_lock(&aux_idr_mutex); 61 aux_dev = idr_find(&aux_idr, index); 62 if (!kref_get_unless_zero(&aux_dev->refcount)) 63 aux_dev = NULL; 64 mutex_unlock(&aux_idr_mutex); 65 66 return aux_dev; 67 } 68 69 static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct drm_dp_aux *aux) 70 { 71 struct drm_dp_aux_dev *aux_dev; 72 int index; 73 74 aux_dev = kzalloc(sizeof(*aux_dev), GFP_KERNEL); 75 if (!aux_dev) 76 return ERR_PTR(-ENOMEM); 77 aux_dev->aux = aux; 78 atomic_set(&aux_dev->usecount, 1); 79 kref_init(&aux_dev->refcount); 80 81 mutex_lock(&aux_idr_mutex); 82 index = idr_alloc_cyclic(&aux_idr, aux_dev, 0, DRM_AUX_MINORS, 83 GFP_KERNEL); 84 mutex_unlock(&aux_idr_mutex); 85 if (index < 0) { 86 kfree(aux_dev); 87 return ERR_PTR(index); 88 } 89 aux_dev->index = index; 90 91 return aux_dev; 92 } 93 94 static void release_drm_dp_aux_dev(struct kref *ref) 95 { 96 struct drm_dp_aux_dev *aux_dev = 97 container_of(ref, struct drm_dp_aux_dev, refcount); 98 99 kfree(aux_dev); 100 } 101 102 static ssize_t name_show(struct device *dev, 103 struct device_attribute *attr, char *buf) 104 { 105 ssize_t res; 106 struct drm_dp_aux_dev *aux_dev = 107 drm_dp_aux_dev_get_by_minor(MINOR(dev->devt)); 108 109 if (!aux_dev) 110 return -ENODEV; 111 112 res = sprintf(buf, "%s\n", aux_dev->aux->name); 113 kref_put(&aux_dev->refcount, release_drm_dp_aux_dev); 114 115 return res; 116 } 117 static DEVICE_ATTR_RO(name); 118 119 static struct attribute *drm_dp_aux_attrs[] = { 120 &dev_attr_name.attr, 121 NULL, 122 }; 123 ATTRIBUTE_GROUPS(drm_dp_aux); 124 125 static int auxdev_open(struct inode *inode, struct file *file) 126 { 127 unsigned int minor = iminor(inode); 128 struct drm_dp_aux_dev *aux_dev; 129 130 aux_dev = drm_dp_aux_dev_get_by_minor(minor); 131 if (!aux_dev) 132 return -ENODEV; 133 134 file->private_data = aux_dev; 135 return 0; 136 } 137 138 static loff_t auxdev_llseek(struct file *file, loff_t offset, int whence) 139 { 140 return fixed_size_llseek(file, offset, whence, AUX_MAX_OFFSET); 141 } 142 143 static ssize_t auxdev_read(struct file *file, char __user *buf, size_t count, 144 loff_t *offset) 145 { 146 size_t bytes_pending, num_bytes_processed = 0; 147 struct drm_dp_aux_dev *aux_dev = file->private_data; 148 ssize_t res = 0; 149 150 if (!atomic_inc_not_zero(&aux_dev->usecount)) 151 return -ENODEV; 152 153 bytes_pending = min((loff_t)count, AUX_MAX_OFFSET - (*offset)); 154 155 if (!access_ok(VERIFY_WRITE, buf, bytes_pending)) { 156 res = -EFAULT; 157 goto out; 158 } 159 160 while (bytes_pending > 0) { 161 uint8_t localbuf[DP_AUX_MAX_PAYLOAD_BYTES]; 162 ssize_t todo = min_t(size_t, bytes_pending, sizeof(localbuf)); 163 164 if (signal_pending(current)) { 165 res = num_bytes_processed ? 166 num_bytes_processed : -ERESTARTSYS; 167 goto out; 168 } 169 170 res = drm_dp_dpcd_read(aux_dev->aux, *offset, localbuf, todo); 171 if (res <= 0) { 172 res = num_bytes_processed ? num_bytes_processed : res; 173 goto out; 174 } 175 if (__copy_to_user(buf + num_bytes_processed, localbuf, res)) { 176 res = num_bytes_processed ? 177 num_bytes_processed : -EFAULT; 178 goto out; 179 } 180 bytes_pending -= res; 181 *offset += res; 182 num_bytes_processed += res; 183 res = num_bytes_processed; 184 } 185 186 out: 187 atomic_dec(&aux_dev->usecount); 188 wake_up_atomic_t(&aux_dev->usecount); 189 return res; 190 } 191 192 static ssize_t auxdev_write(struct file *file, const char __user *buf, 193 size_t count, loff_t *offset) 194 { 195 size_t bytes_pending, num_bytes_processed = 0; 196 struct drm_dp_aux_dev *aux_dev = file->private_data; 197 ssize_t res = 0; 198 199 if (!atomic_inc_not_zero(&aux_dev->usecount)) 200 return -ENODEV; 201 202 bytes_pending = min((loff_t)count, AUX_MAX_OFFSET - *offset); 203 204 if (!access_ok(VERIFY_READ, buf, bytes_pending)) { 205 res = -EFAULT; 206 goto out; 207 } 208 209 while (bytes_pending > 0) { 210 uint8_t localbuf[DP_AUX_MAX_PAYLOAD_BYTES]; 211 ssize_t todo = min_t(size_t, bytes_pending, sizeof(localbuf)); 212 213 if (signal_pending(current)) { 214 res = num_bytes_processed ? 215 num_bytes_processed : -ERESTARTSYS; 216 goto out; 217 } 218 219 if (__copy_from_user(localbuf, 220 buf + num_bytes_processed, todo)) { 221 res = num_bytes_processed ? 222 num_bytes_processed : -EFAULT; 223 goto out; 224 } 225 226 res = drm_dp_dpcd_write(aux_dev->aux, *offset, localbuf, todo); 227 if (res <= 0) { 228 res = num_bytes_processed ? num_bytes_processed : res; 229 goto out; 230 } 231 bytes_pending -= res; 232 *offset += res; 233 num_bytes_processed += res; 234 res = num_bytes_processed; 235 } 236 237 out: 238 atomic_dec(&aux_dev->usecount); 239 wake_up_atomic_t(&aux_dev->usecount); 240 return res; 241 } 242 243 static int auxdev_release(struct inode *inode, struct file *file) 244 { 245 struct drm_dp_aux_dev *aux_dev = file->private_data; 246 247 kref_put(&aux_dev->refcount, release_drm_dp_aux_dev); 248 return 0; 249 } 250 251 static const struct file_operations auxdev_fops = { 252 .owner = THIS_MODULE, 253 .llseek = auxdev_llseek, 254 .read = auxdev_read, 255 .write = auxdev_write, 256 .open = auxdev_open, 257 .release = auxdev_release, 258 }; 259 260 #define to_auxdev(d) container_of(d, struct drm_dp_aux_dev, aux) 261 262 static struct drm_dp_aux_dev *drm_dp_aux_dev_get_by_aux(struct drm_dp_aux *aux) 263 { 264 struct drm_dp_aux_dev *iter, *aux_dev = NULL; 265 int id; 266 267 /* don't increase kref count here because this function should only be 268 * used by drm_dp_aux_unregister_devnode. Thus, it will always have at 269 * least one reference - the one that drm_dp_aux_register_devnode 270 * created 271 */ 272 mutex_lock(&aux_idr_mutex); 273 idr_for_each_entry(&aux_idr, iter, id) { 274 if (iter->aux == aux) { 275 aux_dev = iter; 276 break; 277 } 278 } 279 mutex_unlock(&aux_idr_mutex); 280 return aux_dev; 281 } 282 283 static int auxdev_wait_atomic_t(atomic_t *p) 284 { 285 schedule(); 286 return 0; 287 } 288 289 void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux) 290 { 291 struct drm_dp_aux_dev *aux_dev; 292 unsigned int minor; 293 294 aux_dev = drm_dp_aux_dev_get_by_aux(aux); 295 if (!aux_dev) /* attach must have failed */ 296 return; 297 298 mutex_lock(&aux_idr_mutex); 299 idr_remove(&aux_idr, aux_dev->index); 300 mutex_unlock(&aux_idr_mutex); 301 302 atomic_dec(&aux_dev->usecount); 303 wait_on_atomic_t(&aux_dev->usecount, auxdev_wait_atomic_t, 304 TASK_UNINTERRUPTIBLE); 305 306 minor = aux_dev->index; 307 if (aux_dev->dev) 308 device_destroy(drm_dp_aux_dev_class, 309 MKDEV(drm_dev_major, minor)); 310 311 DRM_DEBUG("drm_dp_aux_dev: aux [%s] unregistering\n", aux->name); 312 kref_put(&aux_dev->refcount, release_drm_dp_aux_dev); 313 } 314 315 int drm_dp_aux_register_devnode(struct drm_dp_aux *aux) 316 { 317 struct drm_dp_aux_dev *aux_dev; 318 int res; 319 320 aux_dev = alloc_drm_dp_aux_dev(aux); 321 if (IS_ERR(aux_dev)) 322 return PTR_ERR(aux_dev); 323 324 aux_dev->dev = device_create(drm_dp_aux_dev_class, aux->dev, 325 MKDEV(drm_dev_major, aux_dev->index), NULL, 326 "drm_dp_aux%d", aux_dev->index); 327 if (IS_ERR(aux_dev->dev)) { 328 res = PTR_ERR(aux_dev->dev); 329 aux_dev->dev = NULL; 330 goto error; 331 } 332 333 DRM_DEBUG("drm_dp_aux_dev: aux [%s] registered as minor %d\n", 334 aux->name, aux_dev->index); 335 return 0; 336 error: 337 drm_dp_aux_unregister_devnode(aux); 338 return res; 339 } 340 341 int drm_dp_aux_dev_init(void) 342 { 343 int res; 344 345 drm_dp_aux_dev_class = class_create(THIS_MODULE, "drm_dp_aux_dev"); 346 if (IS_ERR(drm_dp_aux_dev_class)) { 347 return PTR_ERR(drm_dp_aux_dev_class); 348 } 349 drm_dp_aux_dev_class->dev_groups = drm_dp_aux_groups; 350 351 res = register_chrdev(0, "aux", &auxdev_fops); 352 if (res < 0) 353 goto out; 354 drm_dev_major = res; 355 356 return 0; 357 out: 358 class_destroy(drm_dp_aux_dev_class); 359 return res; 360 } 361 362 void drm_dp_aux_dev_exit(void) 363 { 364 unregister_chrdev(drm_dev_major, "aux"); 365 class_destroy(drm_dp_aux_dev_class); 366 } 367 #endif 368