diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/chipidea/otg_fsm.c | 4 | ||||
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 7 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_uvc.c | 40 | ||||
-rw-r--r-- | drivers/usb/gadget/function/uvc.h | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/function/uvc_queue.c | 79 | ||||
-rw-r--r-- | drivers/usb/gadget/function/uvc_queue.h | 4 | ||||
-rw-r--r-- | drivers/usb/gadget/function/uvc_v4l2.c | 8 | ||||
-rw-r--r-- | drivers/usb/gadget/function/uvc_video.c | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/legacy/inode.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/legacy/tcm_usb_gadget.c | 57 | ||||
-rw-r--r-- | drivers/usb/host/ehci-msm.c | 13 | ||||
-rw-r--r-- | drivers/usb/storage/uas-detect.h | 11 | ||||
-rw-r--r-- | drivers/usb/storage/uas.c | 16 | ||||
-rw-r--r-- | drivers/usb/storage/usb.c | 8 |
14 files changed, 94 insertions, 161 deletions
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c index 083acf45ad5a..19d655a743b5 100644 --- a/drivers/usb/chipidea/otg_fsm.c +++ b/drivers/usb/chipidea/otg_fsm.c @@ -520,7 +520,6 @@ static int ci_otg_start_host(struct otg_fsm *fsm, int on) { struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm); - mutex_unlock(&fsm->lock); if (on) { ci_role_stop(ci); ci_role_start(ci, CI_ROLE_HOST); @@ -529,7 +528,6 @@ static int ci_otg_start_host(struct otg_fsm *fsm, int on) hw_device_reset(ci); ci_role_start(ci, CI_ROLE_GADGET); } - mutex_lock(&fsm->lock); return 0; } @@ -537,12 +535,10 @@ static int ci_otg_start_gadget(struct otg_fsm *fsm, int on) { struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm); - mutex_unlock(&fsm->lock); if (on) usb_gadget_vbus_connect(&ci->gadget); else usb_gadget_vbus_disconnect(&ci->gadget); - mutex_lock(&fsm->lock); return 0; } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 3e15add665e2..5c8f58114677 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1142,11 +1142,16 @@ static int acm_probe(struct usb_interface *intf, } while (buflen > 0) { + elength = buffer[0]; + if (!elength) { + dev_err(&intf->dev, "skipping garbage byte\n"); + elength = 1; + goto next_desc; + } if (buffer[1] != USB_DT_CS_INTERFACE) { dev_err(&intf->dev, "skipping garbage\n"); goto next_desc; } - elength = buffer[0]; switch (buffer[2]) { case USB_CDC_UNION_TYPE: /* we've found it */ diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 76891adfba7a..cf0df8fbba89 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -222,7 +222,7 @@ uvc_function_ep0_complete(struct usb_ep *ep, struct usb_request *req) v4l2_event.type = UVC_EVENT_DATA; uvc_event->data.length = req->actual; memcpy(&uvc_event->data.data, req->buf, req->actual); - v4l2_event_queue(uvc->vdev, &v4l2_event); + v4l2_event_queue(&uvc->vdev, &v4l2_event); } } @@ -256,7 +256,7 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_SETUP; memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req)); - v4l2_event_queue(uvc->vdev, &v4l2_event); + v4l2_event_queue(&uvc->vdev, &v4l2_event); return 0; } @@ -315,7 +315,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_CONNECT; uvc_event->speed = cdev->gadget->speed; - v4l2_event_queue(uvc->vdev, &v4l2_event); + v4l2_event_queue(&uvc->vdev, &v4l2_event); uvc->state = UVC_STATE_CONNECTED; } @@ -343,7 +343,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_STREAMOFF; - v4l2_event_queue(uvc->vdev, &v4l2_event); + v4l2_event_queue(&uvc->vdev, &v4l2_event); uvc->state = UVC_STATE_CONNECTED; return 0; @@ -370,7 +370,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_STREAMON; - v4l2_event_queue(uvc->vdev, &v4l2_event); + v4l2_event_queue(&uvc->vdev, &v4l2_event); return USB_GADGET_DELAYED_STATUS; default: @@ -388,7 +388,7 @@ uvc_function_disable(struct usb_function *f) memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_DISCONNECT; - v4l2_event_queue(uvc->vdev, &v4l2_event); + v4l2_event_queue(&uvc->vdev, &v4l2_event); uvc->state = UVC_STATE_DISCONNECTED; @@ -435,24 +435,19 @@ static int uvc_register_video(struct uvc_device *uvc) { struct usb_composite_dev *cdev = uvc->func.config->cdev; - struct video_device *video; /* TODO reference counting. */ - video = video_device_alloc(); - if (video == NULL) - return -ENOMEM; + uvc->vdev.v4l2_dev = &uvc->v4l2_dev; + uvc->vdev.fops = &uvc_v4l2_fops; + uvc->vdev.ioctl_ops = &uvc_v4l2_ioctl_ops; + uvc->vdev.release = video_device_release_empty; + uvc->vdev.vfl_dir = VFL_DIR_TX; + uvc->vdev.lock = &uvc->video.mutex; + strlcpy(uvc->vdev.name, cdev->gadget->name, sizeof(uvc->vdev.name)); - video->v4l2_dev = &uvc->v4l2_dev; - video->fops = &uvc_v4l2_fops; - video->ioctl_ops = &uvc_v4l2_ioctl_ops; - video->release = video_device_release; - video->vfl_dir = VFL_DIR_TX; - strlcpy(video->name, cdev->gadget->name, sizeof(video->name)); + video_set_drvdata(&uvc->vdev, uvc); - uvc->vdev = video; - video_set_drvdata(video, uvc); - - return video_register_device(video, VFL_TYPE_GRABBER, -1); + return video_register_device(&uvc->vdev, VFL_TYPE_GRABBER, -1); } #define UVC_COPY_DESCRIPTOR(mem, dst, desc) \ @@ -765,8 +760,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) error: v4l2_device_unregister(&uvc->v4l2_dev); - if (uvc->vdev) - video_device_release(uvc->vdev); if (uvc->control_ep) uvc->control_ep->driver_data = NULL; @@ -897,7 +890,7 @@ static void uvc_unbind(struct usb_configuration *c, struct usb_function *f) INFO(cdev, "%s\n", __func__); - video_unregister_device(uvc->vdev); + video_unregister_device(&uvc->vdev); v4l2_device_unregister(&uvc->v4l2_dev); uvc->control_ep->driver_data = NULL; uvc->video.ep->driver_data = NULL; @@ -918,6 +911,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi) if (uvc == NULL) return ERR_PTR(-ENOMEM); + mutex_init(&uvc->video.mutex); uvc->state = UVC_STATE_DISCONNECTED; opts = fi_to_f_uvc_opts(fi); diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index f67695cb28f8..ebe409b9e419 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -115,6 +115,7 @@ struct uvc_video unsigned int width; unsigned int height; unsigned int imagesize; + struct mutex mutex; /* protects frame parameters */ /* Requests */ unsigned int req_size; @@ -143,7 +144,7 @@ enum uvc_state struct uvc_device { - struct video_device *vdev; + struct video_device vdev; struct v4l2_device v4l2_dev; enum uvc_state state; struct usb_function func; diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index 8ea8b3b227b4..d617c39a0052 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c @@ -104,29 +104,16 @@ static void uvc_buffer_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&queue->irqlock, flags); } -static void uvc_wait_prepare(struct vb2_queue *vq) -{ - struct uvc_video_queue *queue = vb2_get_drv_priv(vq); - - mutex_unlock(&queue->mutex); -} - -static void uvc_wait_finish(struct vb2_queue *vq) -{ - struct uvc_video_queue *queue = vb2_get_drv_priv(vq); - - mutex_lock(&queue->mutex); -} - static struct vb2_ops uvc_queue_qops = { .queue_setup = uvc_queue_setup, .buf_prepare = uvc_buffer_prepare, .buf_queue = uvc_buffer_queue, - .wait_prepare = uvc_wait_prepare, - .wait_finish = uvc_wait_finish, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; -int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) +int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, + struct mutex *lock) { int ret; @@ -135,6 +122,7 @@ int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) queue->queue.drv_priv = queue; queue->queue.buf_struct_size = sizeof(struct uvc_buffer); queue->queue.ops = &uvc_queue_qops; + queue->queue.lock = lock; queue->queue.mem_ops = &vb2_vmalloc_memops; queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC | V4L2_BUF_FLAG_TSTAMP_SRC_EOF; @@ -142,7 +130,6 @@ int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) if (ret) return ret; - mutex_init(&queue->mutex); spin_lock_init(&queue->irqlock); INIT_LIST_HEAD(&queue->irqqueue); queue->flags = 0; @@ -155,9 +142,7 @@ int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) */ void uvcg_free_buffers(struct uvc_video_queue *queue) { - mutex_lock(&queue->mutex); vb2_queue_release(&queue->queue); - mutex_unlock(&queue->mutex); } /* @@ -168,22 +153,14 @@ int uvcg_alloc_buffers(struct uvc_video_queue *queue, { int ret; - mutex_lock(&queue->mutex); ret = vb2_reqbufs(&queue->queue, rb); - mutex_unlock(&queue->mutex); return ret ? ret : rb->count; } int uvcg_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) { - int ret; - - mutex_lock(&queue->mutex); - ret = vb2_querybuf(&queue->queue, buf); - mutex_unlock(&queue->mutex); - - return ret; + return vb2_querybuf(&queue->queue, buf); } int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) @@ -191,18 +168,14 @@ int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) unsigned long flags; int ret; - mutex_lock(&queue->mutex); ret = vb2_qbuf(&queue->queue, buf); if (ret < 0) - goto done; + return ret; spin_lock_irqsave(&queue->irqlock, flags); ret = (queue->flags & UVC_QUEUE_PAUSED) != 0; queue->flags &= ~UVC_QUEUE_PAUSED; spin_unlock_irqrestore(&queue->irqlock, flags); - -done: - mutex_unlock(&queue->mutex); return ret; } @@ -213,13 +186,7 @@ done: int uvcg_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf, int nonblocking) { - int ret; - - mutex_lock(&queue->mutex); - ret = vb2_dqbuf(&queue->queue, buf, nonblocking); - mutex_unlock(&queue->mutex); - - return ret; + return vb2_dqbuf(&queue->queue, buf, nonblocking); } /* @@ -231,24 +198,12 @@ int uvcg_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf, unsigned int uvcg_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_table *wait) { - unsigned int ret; - - mutex_lock(&queue->mutex); - ret = vb2_poll(&queue->queue, file, wait); - mutex_unlock(&queue->mutex); - - return ret; + return vb2_poll(&queue->queue, file, wait); } int uvcg_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) { - int ret; - - mutex_lock(&queue->mutex); - ret = vb2_mmap(&queue->queue, vma); - mutex_unlock(&queue->mutex); - - return ret; + return vb2_mmap(&queue->queue, vma); } #ifndef CONFIG_MMU @@ -260,12 +215,7 @@ int uvcg_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) unsigned long uvcg_queue_get_unmapped_area(struct uvc_video_queue *queue, unsigned long pgoff) { - unsigned long ret; - - mutex_lock(&queue->mutex); - ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0); - mutex_unlock(&queue->mutex); - return ret; + return vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0); } #endif @@ -327,18 +277,17 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable) unsigned long flags; int ret = 0; - mutex_lock(&queue->mutex); if (enable) { ret = vb2_streamon(&queue->queue, queue->queue.type); if (ret < 0) - goto done; + return ret; queue->sequence = 0; queue->buf_used = 0; } else { ret = vb2_streamoff(&queue->queue, queue->queue.type); if (ret < 0) - goto done; + return ret; spin_lock_irqsave(&queue->irqlock, flags); INIT_LIST_HEAD(&queue->irqqueue); @@ -353,8 +302,6 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable) spin_unlock_irqrestore(&queue->irqlock, flags); } -done: - mutex_unlock(&queue->mutex); return ret; } diff --git a/drivers/usb/gadget/function/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h index 03919c724961..01ca9eab3481 100644 --- a/drivers/usb/gadget/function/uvc_queue.h +++ b/drivers/usb/gadget/function/uvc_queue.h @@ -41,7 +41,6 @@ struct uvc_buffer { struct uvc_video_queue { struct vb2_queue queue; - struct mutex mutex; /* Protects queue */ unsigned int flags; __u32 sequence; @@ -57,7 +56,8 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue) return vb2_is_streaming(&queue->queue); } -int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type); +int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, + struct mutex *lock); void uvcg_free_buffers(struct uvc_video_queue *queue); diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index 8b818fd027b3..f4ccbd56f4d2 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -14,7 +14,6 @@ #include <linux/device.h> #include <linux/errno.h> #include <linux/list.h> -#include <linux/mutex.h> #include <linux/videodev2.h> #include <linux/vmalloc.h> #include <linux/wait.h> @@ -77,7 +76,8 @@ uvc_v4l2_querycap(struct file *file, void *fh, struct v4l2_capability *cap) strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev), sizeof(cap->bus_info)); - cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; + cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -312,8 +312,10 @@ uvc_v4l2_release(struct file *file) uvc_function_disconnect(uvc); + mutex_lock(&video->mutex); uvcg_video_enable(video, 0); uvcg_free_buffers(&video->queue); + mutex_unlock(&video->mutex); file->private_data = NULL; v4l2_fh_del(&handle->vfh); @@ -357,7 +359,7 @@ struct v4l2_file_operations uvc_v4l2_fops = { .owner = THIS_MODULE, .open = uvc_v4l2_open, .release = uvc_v4l2_release, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .mmap = uvc_v4l2_mmap, .poll = uvc_v4l2_poll, #ifndef CONFIG_MMU diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 50a5e637ca35..3d0d5d94a62f 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -391,7 +391,8 @@ int uvcg_video_init(struct uvc_video *video) video->imagesize = 320 * 240 * 2; /* Initialize the video buffers queue. */ - uvcg_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT); + uvcg_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT, + &video->mutex); return 0; } diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 6af58c6dba5e..2030565c6789 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -1505,7 +1505,7 @@ static void destroy_ep_files (struct dev_data *dev) list_del_init (&ep->epfiles); dentry = ep->dentry; ep->dentry = NULL; - parent = dentry->d_parent->d_inode; + parent = d_inode(dentry->d_parent); /* break link to controller */ if (ep->state == STATE_EP_ENABLED) diff --git a/drivers/usb/gadget/legacy/tcm_usb_gadget.c b/drivers/usb/gadget/legacy/tcm_usb_gadget.c index 6e0a019aad54..8b80addc4ce6 100644 --- a/drivers/usb/gadget/legacy/tcm_usb_gadget.c +++ b/drivers/usb/gadget/legacy/tcm_usb_gadget.c @@ -29,7 +29,7 @@ USB_GADGET_COMPOSITE_OPTIONS(); -static struct target_fabric_configfs *usbg_fabric_configfs; +static const struct target_core_fabric_ops usbg_ops; static inline struct f_uas *to_f_uas(struct usb_function *f) { @@ -1572,8 +1572,7 @@ static struct se_portal_group *usbg_make_tpg( tpg->tport = tport; tpg->tport_tpgt = tpgt; - ret = core_tpg_register(&usbg_fabric_configfs->tf_ops, wwn, - &tpg->se_tpg, tpg, + ret = core_tpg_register(&usbg_ops, wwn, &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL); if (ret < 0) { destroy_workqueue(tpg->workqueue); @@ -1864,7 +1863,9 @@ static int usbg_check_stop_free(struct se_cmd *se_cmd) return 1; } -static struct target_core_fabric_ops usbg_ops = { +static const struct target_core_fabric_ops usbg_ops = { + .module = THIS_MODULE, + .name = "usb_gadget", .get_fabric_name = usbg_get_fabric_name, .get_fabric_proto_ident = usbg_get_fabric_proto_ident, .tpg_get_wwn = usbg_get_fabric_wwn, @@ -1906,46 +1907,9 @@ static struct target_core_fabric_ops usbg_ops = { .fabric_drop_np = NULL, .fabric_make_nodeacl = usbg_make_nodeacl, .fabric_drop_nodeacl = usbg_drop_nodeacl, -}; - -static int usbg_register_configfs(void) -{ - struct target_fabric_configfs *fabric; - int ret; - - fabric = target_fabric_configfs_init(THIS_MODULE, "usb_gadget"); - if (IS_ERR(fabric)) { - printk(KERN_ERR "target_fabric_configfs_init() failed\n"); - return PTR_ERR(fabric); - } - - fabric->tf_ops = usbg_ops; - fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = usbg_wwn_attrs; - fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = usbg_base_attrs; - fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL; - fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL; - fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL; - fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL; - fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL; - fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL; - fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL; - ret = target_fabric_configfs_register(fabric); - if (ret < 0) { - printk(KERN_ERR "target_fabric_configfs_register() failed" - " for usb-gadget\n"); - return ret; - } - usbg_fabric_configfs = fabric; - return 0; -}; -static void usbg_deregister_configfs(void) -{ - if (!(usbg_fabric_configfs)) - return; - - target_fabric_configfs_deregister(usbg_fabric_configfs); - usbg_fabric_configfs = NULL; + .tfc_wwn_attrs = usbg_wwn_attrs, + .tfc_tpg_base_attrs = usbg_base_attrs, }; /* Start gadget.c code */ @@ -2454,16 +2418,13 @@ static void usbg_detach(struct usbg_tpg *tpg) static int __init usb_target_gadget_init(void) { - int ret; - - ret = usbg_register_configfs(); - return ret; + return target_register_template(&usbg_ops); } module_init(usb_target_gadget_init); static void __exit usb_target_gadget_exit(void) { - usbg_deregister_configfs(); + target_unregister_template(&usbg_ops); } module_exit(usb_target_gadget_exit); diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 9db74ca7e5b9..275c92e53a59 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -88,13 +88,20 @@ static int ehci_msm_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hcd->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(hcd->regs)) { - ret = PTR_ERR(hcd->regs); + if (!res) { + dev_err(&pdev->dev, "Unable to get memory resource\n"); + ret = -ENODEV; goto put_hcd; } + hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); + hcd->regs = devm_ioremap(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + dev_err(&pdev->dev, "ioremap failed\n"); + ret = -ENOMEM; + goto put_hcd; + } /* * OTG driver takes care of PHY initialization, clock management, diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h index 9893d696fc97..f58caa9e6a27 100644 --- a/drivers/usb/storage/uas-detect.h +++ b/drivers/usb/storage/uas-detect.h @@ -51,7 +51,8 @@ static int uas_find_endpoints(struct usb_host_interface *alt, } static int uas_use_uas_driver(struct usb_interface *intf, - const struct usb_device_id *id) + const struct usb_device_id *id, + unsigned long *flags_ret) { struct usb_host_endpoint *eps[4] = { }; struct usb_device *udev = interface_to_usbdev(intf); @@ -73,7 +74,7 @@ static int uas_use_uas_driver(struct usb_interface *intf, * this writing the following versions exist: * ASM1051 - no uas support version * ASM1051 - with broken (*) uas support - * ASM1053 - with working uas support + * ASM1053 - with working uas support, but problems with large xfers * ASM1153 - with working uas support * * Devices with these chips re-use a number of device-ids over the @@ -103,6 +104,9 @@ static int uas_use_uas_driver(struct usb_interface *intf, } else if (usb_ss_max_streams(&eps[1]->ss_ep_comp) == 32) { /* Possibly an ASM1051, disable uas */ flags |= US_FL_IGNORE_UAS; + } else { + /* ASM1053, these have issues with large transfers */ + flags |= US_FL_MAX_SECTORS_240; } } @@ -132,5 +136,8 @@ static int uas_use_uas_driver(struct usb_interface *intf, return 0; } + if (flags_ret) + *flags_ret = flags; + return 1; } diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 6cdabdc119a7..6d3122afeed3 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -759,7 +759,10 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd) static int uas_slave_alloc(struct scsi_device *sdev) { - sdev->hostdata = (void *)sdev->host->hostdata; + struct uas_dev_info *devinfo = + (struct uas_dev_info *)sdev->host->hostdata; + + sdev->hostdata = devinfo; /* USB has unusual DMA-alignment requirements: Although the * starting address of each scatter-gather element doesn't matter, @@ -778,6 +781,11 @@ static int uas_slave_alloc(struct scsi_device *sdev) */ blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1)); + if (devinfo->flags & US_FL_MAX_SECTORS_64) + blk_queue_max_hw_sectors(sdev->request_queue, 64); + else if (devinfo->flags & US_FL_MAX_SECTORS_240) + blk_queue_max_hw_sectors(sdev->request_queue, 240); + return 0; } @@ -887,8 +895,9 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) struct Scsi_Host *shost = NULL; struct uas_dev_info *devinfo; struct usb_device *udev = interface_to_usbdev(intf); + unsigned long dev_flags; - if (!uas_use_uas_driver(intf, id)) + if (!uas_use_uas_driver(intf, id, &dev_flags)) return -ENODEV; if (uas_switch_interface(udev, intf)) @@ -910,8 +919,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) devinfo->udev = udev; devinfo->resetting = 0; devinfo->shutdown = 0; - devinfo->flags = id->driver_info; - usb_stor_adjust_quirks(udev, &devinfo->flags); + devinfo->flags = dev_flags; init_usb_anchor(&devinfo->cmd_urbs); init_usb_anchor(&devinfo->sense_urbs); init_usb_anchor(&devinfo->data_urbs); diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 5600c33fcadb..6c10c888f35f 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -479,7 +479,8 @@ void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags) US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT | US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 | US_FL_INITIAL_READ10 | US_FL_WRITE_CACHE | - US_FL_NO_ATA_1X | US_FL_NO_REPORT_OPCODES); + US_FL_NO_ATA_1X | US_FL_NO_REPORT_OPCODES | + US_FL_MAX_SECTORS_240); p = quirks; while (*p) { @@ -520,6 +521,9 @@ void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags) case 'f': f |= US_FL_NO_REPORT_OPCODES; break; + case 'g': + f |= US_FL_MAX_SECTORS_240; + break; case 'h': f |= US_FL_CAPACITY_HEURISTICS; break; @@ -1080,7 +1084,7 @@ static int storage_probe(struct usb_interface *intf, /* If uas is enabled and this device can do uas then ignore it. */ #if IS_ENABLED(CONFIG_USB_UAS) - if (uas_use_uas_driver(intf, id)) + if (uas_use_uas_driver(intf, id, NULL)) return -ENXIO; #endif |