| .. | .. |
|---|
| 71 | 71 | wait_queue_head_t write_queue; |
|---|
| 72 | 72 | struct usb_request *req; |
|---|
| 73 | 73 | |
|---|
| 74 | | - int minor; |
|---|
| 74 | + struct device dev; |
|---|
| 75 | 75 | struct cdev cdev; |
|---|
| 76 | 76 | struct usb_function func; |
|---|
| 77 | 77 | |
|---|
| .. | .. |
|---|
| 82 | 82 | static inline struct f_hidg *func_to_hidg(struct usb_function *f) |
|---|
| 83 | 83 | { |
|---|
| 84 | 84 | return container_of(f, struct f_hidg, func); |
|---|
| 85 | +} |
|---|
| 86 | + |
|---|
| 87 | +static void hidg_release(struct device *dev) |
|---|
| 88 | +{ |
|---|
| 89 | + struct f_hidg *hidg = container_of(dev, struct f_hidg, dev); |
|---|
| 90 | + |
|---|
| 91 | + kfree(hidg->set_report_buf); |
|---|
| 92 | + kfree(hidg); |
|---|
| 85 | 93 | } |
|---|
| 86 | 94 | |
|---|
| 87 | 95 | /*-------------------------------------------------------------------------*/ |
|---|
| .. | .. |
|---|
| 288 | 296 | if (!count) |
|---|
| 289 | 297 | return 0; |
|---|
| 290 | 298 | |
|---|
| 291 | | - if (!access_ok(VERIFY_WRITE, buffer, count)) |
|---|
| 292 | | - return -EFAULT; |
|---|
| 293 | | - |
|---|
| 294 | 299 | spin_lock_irqsave(&hidg->read_spinlock, flags); |
|---|
| 295 | 300 | |
|---|
| 296 | 301 | #define READ_COND_INTOUT (!list_empty(&hidg->completed_out_req)) |
|---|
| .. | .. |
|---|
| 429 | 434 | unsigned long flags; |
|---|
| 430 | 435 | ssize_t status = -ENOMEM; |
|---|
| 431 | 436 | |
|---|
| 432 | | - if (!access_ok(VERIFY_READ, buffer, count)) |
|---|
| 433 | | - return -EFAULT; |
|---|
| 434 | | - |
|---|
| 435 | 437 | spin_lock_irqsave(&hidg->write_spinlock, flags); |
|---|
| 436 | 438 | |
|---|
| 437 | 439 | if (!hidg->req) { |
|---|
| .. | .. |
|---|
| 487 | 489 | } |
|---|
| 488 | 490 | |
|---|
| 489 | 491 | req->status = 0; |
|---|
| 490 | | - req->zero = ((count % hidg->in_ep->maxpacket) == 0); |
|---|
| 492 | + req->zero = 0; |
|---|
| 491 | 493 | req->length = count; |
|---|
| 492 | 494 | req->complete = f_hidg_req_complete; |
|---|
| 493 | 495 | req->context = hidg; |
|---|
| .. | .. |
|---|
| 593 | 595 | break; |
|---|
| 594 | 596 | default: |
|---|
| 595 | 597 | ERROR(cdev, "Set report failed %d\n", req->status); |
|---|
| 596 | | - /* FALLTHROUGH */ |
|---|
| 598 | + fallthrough; |
|---|
| 597 | 599 | case -ECONNABORTED: /* hardware forced ep reset */ |
|---|
| 598 | 600 | case -ECONNRESET: /* request dequeued */ |
|---|
| 599 | 601 | case -ESHUTDOWN: /* disconnect from host */ |
|---|
| .. | .. |
|---|
| 910 | 912 | struct usb_ep *ep; |
|---|
| 911 | 913 | struct f_hidg *hidg = func_to_hidg(f); |
|---|
| 912 | 914 | struct usb_string *us; |
|---|
| 913 | | - struct device *device; |
|---|
| 914 | 915 | int status; |
|---|
| 915 | | - dev_t dev; |
|---|
| 916 | 916 | |
|---|
| 917 | 917 | /* maybe allocate device-global string IDs, and patch descriptors */ |
|---|
| 918 | 918 | us = usb_gstrings_attach(c->cdev, ct_func_strings, |
|---|
| .. | .. |
|---|
| 1005 | 1005 | |
|---|
| 1006 | 1006 | /* create char device */ |
|---|
| 1007 | 1007 | cdev_init(&hidg->cdev, &f_hidg_fops); |
|---|
| 1008 | | - dev = MKDEV(major, hidg->minor); |
|---|
| 1009 | | - status = cdev_add(&hidg->cdev, dev, 1); |
|---|
| 1008 | + status = cdev_device_add(&hidg->cdev, &hidg->dev); |
|---|
| 1010 | 1009 | if (status) |
|---|
| 1011 | 1010 | goto fail_free_descs; |
|---|
| 1012 | 1011 | |
|---|
| 1013 | | - device = device_create(hidg_class, NULL, dev, NULL, |
|---|
| 1014 | | - "%s%d", "hidg", hidg->minor); |
|---|
| 1015 | | - if (IS_ERR(device)) { |
|---|
| 1016 | | - status = PTR_ERR(device); |
|---|
| 1017 | | - goto del; |
|---|
| 1018 | | - } |
|---|
| 1019 | | - |
|---|
| 1020 | 1012 | return 0; |
|---|
| 1021 | | -del: |
|---|
| 1022 | | - cdev_del(&hidg->cdev); |
|---|
| 1023 | 1013 | fail_free_descs: |
|---|
| 1024 | 1014 | usb_free_all_descriptors(f); |
|---|
| 1025 | 1015 | fail: |
|---|
| .. | .. |
|---|
| 1250 | 1240 | |
|---|
| 1251 | 1241 | hidg = func_to_hidg(f); |
|---|
| 1252 | 1242 | opts = container_of(f->fi, struct f_hid_opts, func_inst); |
|---|
| 1253 | | - kfree(hidg->report_desc); |
|---|
| 1254 | | - kfree(hidg->set_report_buf); |
|---|
| 1255 | | - kfree(hidg); |
|---|
| 1243 | + put_device(&hidg->dev); |
|---|
| 1256 | 1244 | mutex_lock(&opts->lock); |
|---|
| 1257 | 1245 | --opts->refcnt; |
|---|
| 1258 | 1246 | mutex_unlock(&opts->lock); |
|---|
| .. | .. |
|---|
| 1262 | 1250 | { |
|---|
| 1263 | 1251 | struct f_hidg *hidg = func_to_hidg(f); |
|---|
| 1264 | 1252 | |
|---|
| 1265 | | - device_destroy(hidg_class, MKDEV(major, hidg->minor)); |
|---|
| 1266 | | - cdev_del(&hidg->cdev); |
|---|
| 1253 | + cdev_device_del(&hidg->cdev, &hidg->dev); |
|---|
| 1267 | 1254 | |
|---|
| 1268 | 1255 | usb_free_all_descriptors(f); |
|---|
| 1269 | 1256 | } |
|---|
| .. | .. |
|---|
| 1272 | 1259 | { |
|---|
| 1273 | 1260 | struct f_hidg *hidg; |
|---|
| 1274 | 1261 | struct f_hid_opts *opts; |
|---|
| 1262 | + int ret; |
|---|
| 1275 | 1263 | |
|---|
| 1276 | 1264 | /* allocate and initialize one new instance */ |
|---|
| 1277 | 1265 | hidg = kzalloc(sizeof(*hidg), GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 1283 | 1271 | mutex_lock(&opts->lock); |
|---|
| 1284 | 1272 | ++opts->refcnt; |
|---|
| 1285 | 1273 | |
|---|
| 1286 | | - hidg->minor = opts->minor; |
|---|
| 1274 | + device_initialize(&hidg->dev); |
|---|
| 1275 | + hidg->dev.release = hidg_release; |
|---|
| 1276 | + hidg->dev.class = hidg_class; |
|---|
| 1277 | + hidg->dev.devt = MKDEV(major, opts->minor); |
|---|
| 1278 | + ret = dev_set_name(&hidg->dev, "hidg%d", opts->minor); |
|---|
| 1279 | + if (ret) { |
|---|
| 1280 | + --opts->refcnt; |
|---|
| 1281 | + mutex_unlock(&opts->lock); |
|---|
| 1282 | + return ERR_PTR(ret); |
|---|
| 1283 | + } |
|---|
| 1284 | + |
|---|
| 1287 | 1285 | hidg->bInterfaceSubClass = opts->subclass; |
|---|
| 1288 | 1286 | hidg->bInterfaceProtocol = opts->protocol; |
|---|
| 1289 | 1287 | hidg->report_length = opts->report_length; |
|---|
| 1290 | 1288 | hidg->report_desc_length = opts->report_desc_length; |
|---|
| 1291 | 1289 | if (opts->report_desc) { |
|---|
| 1292 | | - hidg->report_desc = kmemdup(opts->report_desc, |
|---|
| 1293 | | - opts->report_desc_length, |
|---|
| 1294 | | - GFP_KERNEL); |
|---|
| 1290 | + hidg->report_desc = devm_kmemdup(&hidg->dev, opts->report_desc, |
|---|
| 1291 | + opts->report_desc_length, |
|---|
| 1292 | + GFP_KERNEL); |
|---|
| 1295 | 1293 | if (!hidg->report_desc) { |
|---|
| 1296 | | - kfree(hidg); |
|---|
| 1294 | + put_device(&hidg->dev); |
|---|
| 1297 | 1295 | mutex_unlock(&opts->lock); |
|---|
| 1298 | 1296 | return ERR_PTR(-ENOMEM); |
|---|
| 1299 | 1297 | } |
|---|