From ea9da1c79eb9a28176550d0b8ba9166e6e5f42b8 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 2 Dec 2011 11:55:44 -0800 Subject: [PATCH 001/269] UAS: Re-add workqueue items if submission fails. If the original submission (or allocation) of the URBs for a SCSI command fails, the UAS driver sticks the command structure in a workqueue and schedules uas_do_work() to run. That function removes the entire queue before walking across it and attempting to resubmit. Unfortunately, if the second submission fails, we will leak memory (because an allocated URB was not submitted) and possibly leave the SCSI command partially enqueued on some of the stream rings. Fix this by checking whether the second submission failed and re-queueing the command to the UAS workqueue and scheduling it. Signed-off-by: Sarah Sharp Cc: Matthew Wilcox Signed-off-by: Sebastian Andrzej Siewior --- drivers/usb/storage/uas.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 1d10d5b8204c..4bbaf6e150e4 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -125,29 +125,38 @@ struct uas_cmd_info { /* I hate forward declarations, but I actually have a loop */ static int uas_submit_urbs(struct scsi_cmnd *cmnd, struct uas_dev_info *devinfo, gfp_t gfp); +static void uas_do_work(struct work_struct *work); +static DECLARE_WORK(uas_work, uas_do_work); static DEFINE_SPINLOCK(uas_work_lock); static LIST_HEAD(uas_work_list); static void uas_do_work(struct work_struct *work) { struct uas_cmd_info *cmdinfo; + struct uas_cmd_info *temp; struct list_head list; + int err; spin_lock_irq(&uas_work_lock); list_replace_init(&uas_work_list, &list); spin_unlock_irq(&uas_work_lock); - list_for_each_entry(cmdinfo, &list, list) { + list_for_each_entry_safe(cmdinfo, temp, &list, list) { struct scsi_pointer *scp = (void *)cmdinfo; struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp); - uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); + err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); + if (err) { + list_del(&cmdinfo->list); + spin_lock_irq(&uas_work_lock); + list_add_tail(&cmdinfo->list, &uas_work_list); + spin_unlock_irq(&uas_work_lock); + schedule_work(&uas_work); + } } } -static DECLARE_WORK(uas_work, uas_do_work); - static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) { struct sense_iu *sense_iu = urb->transfer_buffer; From 9eb445410db99e5f5f660e97a2165a0567bd909e Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 2 Dec 2011 11:55:46 -0800 Subject: [PATCH 002/269] UAS: Use unique tags on non-streams devices. UAS can work with either USB 3.0 devices that support bulk streams, or USB 2.0 devices that do not support bulk streams. When we're working with a non-streams device, we need to be able to uniquely identify a SCSI command with a tag in the IU. Devices will barf and abort all queued commands if they find a duplicate tag. uas_queuecommand_lck() sets cmdinfo->stream to zero if the device doesn't support streams, which is later passed into uas_alloc_cmd_urb() as the variable stream. This means the UAS driver was setting the tag in all commands to zero for non-stream devices. So the UAS driver won't currently work with USB 2.0 devices. Use the SCSI command tag instead of the stream ID for the command IU tag. We have to add one to the SCSI command tag because SCSI tags are zero-based, but stream IDs are one-based, and the command tag must match the stream ID that we're queueing the data IUs for. Untagged SCSI commands use stream ID 1. Signed-off-by: Sarah Sharp Cc: Matthew Wilcox Signed-off-by: Sebastian Andrzej Siewior --- drivers/usb/storage/uas.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 4bbaf6e150e4..28d9b1909389 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -343,7 +343,10 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp, goto free; iu->iu_id = IU_ID_COMMAND; - iu->tag = cpu_to_be16(stream_id); + if (blk_rq_tagged(cmnd->request)) + iu->tag = cpu_to_be16(cmnd->request->tag + 1); + else + iu->tag = cpu_to_be16(1); iu->prio_attr = UAS_SIMPLE_TAG; iu->len = len; int_to_scsilun(sdev->lun, &iu->lun); From 96c1eb9873caffc507a1951c36b43fdcf3ddeff3 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 2 Dec 2011 11:55:48 -0800 Subject: [PATCH 003/269] UAS: Free status URB when we can't find the SCSI tag. In the UAS status URB completion handler, we need to free the URB, no matter what happens. Fix a bug where we would leak the URB (and its buffer) if we couldn't find a SCSI command that is associated with this status phase. Signed-off-by: Sarah Sharp Cc: Matthew Wilcox Signed-off-by: Sebastian Andrzej Siewior --- drivers/usb/storage/uas.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 28d9b1909389..9dd4aaee85cc 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -246,8 +246,10 @@ static void uas_stat_cmplt(struct urb *urb) cmnd = sdev->current_cmnd; else cmnd = scsi_find_tag(sdev, tag); - if (!cmnd) + if (!cmnd) { + usb_free_urb(urb); return; + } switch (iu->iu_id) { case IU_ID_STATUS: From dae51546b6564b06cbae4191d4f2dee7136be3c1 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 19 Dec 2011 17:06:08 +0100 Subject: [PATCH 004/269] usb/uas: use unique tags for all LUNs I observed that on a device with multiple LUNs UAS was re-using the same tag number for requests which were issued at the same time to both LUNs. This patch uses scsi_init_shared_tag_map() to use unique tags for all LUNs. With this patch I haven't seen the same tag number during the init sequence anymore. Tag 1 is used for devices which do not adverise command queueing. This patch initilizes the queue before adding the scsi host like the other two user in tree. Signed-off-by: Sebastian Andrzej Siewior --- drivers/usb/storage/uas.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 9dd4aaee85cc..6974f4bed2fd 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -684,6 +684,17 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo) } } +static void uas_free_streams(struct uas_dev_info *devinfo) +{ + struct usb_device *udev = devinfo->udev; + struct usb_host_endpoint *eps[3]; + + eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); + eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); + eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); + usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL); +} + /* * XXX: What I'd like to do here is register a SCSI host for each USB host in * the system. Follow usb-storage's design of registering a SCSI host for @@ -713,18 +724,26 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) shost->max_id = 1; shost->sg_tablesize = udev->bus->sg_tablesize; - result = scsi_add_host(shost, &intf->dev); - if (result) - goto free; - shost->hostdata[0] = (unsigned long)devinfo; - devinfo->intf = intf; devinfo->udev = udev; uas_configure_endpoints(devinfo); + result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 1); + if (result) + goto free; + + result = scsi_add_host(shost, &intf->dev); + if (result) + goto deconfig_eps; + + shost->hostdata[0] = (unsigned long)devinfo; + scsi_scan_host(shost); usb_set_intfdata(intf, shost); return result; + +deconfig_eps: + uas_free_streams(devinfo); free: kfree(devinfo); if (shost) @@ -746,18 +765,11 @@ static int uas_post_reset(struct usb_interface *intf) static void uas_disconnect(struct usb_interface *intf) { - struct usb_device *udev = interface_to_usbdev(intf); - struct usb_host_endpoint *eps[3]; struct Scsi_Host *shost = usb_get_intfdata(intf); struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; scsi_remove_host(shost); - - eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); - eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); - eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); - usb_free_streams(intf, eps, 3, GFP_KERNEL); - + uas_free_streams(devinfo); kfree(devinfo); } From 22188f4a933c6e86ac67f52028895c795896492e Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 19 Dec 2011 20:22:39 +0100 Subject: [PATCH 005/269] usb/uas: use scsi_host_find_tag() to find command from a tag In "usb/uas: use unique tags for all LUNs" we make sure to create unique tags across all LUNs. This patch uses scsi_host_find_tag() to obtain the correct command which is associated with the tag. The following changes are required: - don't use sdev->current_cmnd anymore Since we can have devices which don't support command queueing we must ensure that we can tell the two commands apart. Even if a device supports comand queuing we send the INQUIRY command "untagged" for LUN1 while we can send a tagged command to LUN0 at the same time. devinfo->cmnd is used for stashing the one "untagged" command. - tag number is altered. If stream support is used then the tag number must match the stream number. Therefore we can't use tag 0 and must start at tag 1. In case we have untagged commands (at least the first command) we must be able to distinguish between command tag 0 (which becomes 1) and untagged command (which becomes curently also 1). The following tag numbers are used: 0: never 1: for untagged commands (devinfo->cmnd) 2+: tagged commands. Signed-off-by: Sebastian Andrzej Siewior --- drivers/usb/storage/uas.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 6974f4bed2fd..e2386e8c7678 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -98,6 +98,7 @@ struct uas_dev_info { unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe; unsigned use_streams:1; unsigned uas_sense_old:1; + struct scsi_cmnd *cmnd; }; enum { @@ -178,8 +179,6 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) } cmnd->result = sense_iu->status; - if (sdev->current_cmnd) - sdev->current_cmnd = NULL; cmnd->scsi_done(cmnd); usb_free_urb(urb); } @@ -205,8 +204,6 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) } cmnd->result = sense_iu->status; - if (sdev->current_cmnd) - sdev->current_cmnd = NULL; cmnd->scsi_done(cmnd); usb_free_urb(urb); } @@ -230,8 +227,8 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, static void uas_stat_cmplt(struct urb *urb) { struct iu *iu = urb->transfer_buffer; - struct scsi_device *sdev = urb->context; - struct uas_dev_info *devinfo = sdev->hostdata; + struct Scsi_Host *shost = urb->context; + struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; struct scsi_cmnd *cmnd; u16 tag; @@ -242,10 +239,10 @@ static void uas_stat_cmplt(struct urb *urb) } tag = be16_to_cpup(&iu->tag) - 1; - if (sdev->current_cmnd) - cmnd = sdev->current_cmnd; + if (tag == 0) + cmnd = devinfo->cmnd; else - cmnd = scsi_find_tag(sdev, tag); + cmnd = scsi_host_find_tag(shost, tag - 1); if (!cmnd) { usb_free_urb(urb); return; @@ -253,6 +250,9 @@ static void uas_stat_cmplt(struct urb *urb) switch (iu->iu_id) { case IU_ID_STATUS: + if (devinfo->cmnd == cmnd) + devinfo->cmnd = NULL; + if (urb->actual_length < 16) devinfo->uas_sense_old = 1; if (devinfo->uas_sense_old) @@ -314,7 +314,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, goto free; usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu), - uas_stat_cmplt, cmnd->device); + uas_stat_cmplt, cmnd->device->host); urb->stream_id = stream_id; urb->transfer_flags |= URB_FREE_BUFFER; out: @@ -346,7 +346,7 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp, iu->iu_id = IU_ID_COMMAND; if (blk_rq_tagged(cmnd->request)) - iu->tag = cpu_to_be16(cmnd->request->tag + 1); + iu->tag = cpu_to_be16(cmnd->request->tag + 2); else iu->tag = cpu_to_be16(1); iu->prio_attr = UAS_SIMPLE_TAG; @@ -458,13 +458,13 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer)); - if (!cmdinfo->status_urb && sdev->current_cmnd) + if (devinfo->cmnd) return SCSI_MLQUEUE_DEVICE_BUSY; if (blk_rq_tagged(cmnd->request)) { - cmdinfo->stream = cmnd->request->tag + 1; + cmdinfo->stream = cmnd->request->tag + 2; } else { - sdev->current_cmnd = cmnd; + devinfo->cmnd = cmnd; cmdinfo->stream = 1; } @@ -565,7 +565,7 @@ static int uas_slave_configure(struct scsi_device *sdev) { struct uas_dev_info *devinfo = sdev->hostdata; scsi_set_tag_type(sdev, MSG_ORDERED_TAG); - scsi_activate_tcq(sdev, devinfo->qdepth - 1); + scsi_activate_tcq(sdev, devinfo->qdepth - 2); return 0; } @@ -633,6 +633,7 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo) unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints; devinfo->uas_sense_old = 0; + devinfo->cmnd = NULL; for (i = 0; i < n_endpoints; i++) { unsigned char *extra = endpoint[i].extra; @@ -728,7 +729,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) devinfo->udev = udev; uas_configure_endpoints(devinfo); - result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 1); + result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2); if (result) goto free; From ceb3f91fd53c9fbd7b292fc2754ba4efffeeeedb Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 20 Dec 2011 14:50:26 +0100 Subject: [PATCH 006/269] usb/uas: one only one status URB/host on stream-less connection The status/sense URB is allocated on per-command basis. A read/write looks the following way on a stream-less connection: - send cmd tag X, queue status - receive status, oh it is a read for tag X. queue status & read - receive read - receive status, oh I'm done for tag X. Cool call complete and free status urb. This block repeats itself 1:1 for further commands and looks great so far. Lets take a look now what happens if we do allow multiple commands: - send cmd tag X, queue statusX (belongs to the command with the X tag) - send cmd tag Y, queue statusY (belongs to the command with the Y tag) - receive statusX, oh it is a read for tag X. queue statusX & a read - receive read - receive statusY, oh I'm done for tag X. Cool call complete and free statusY. - receive statusX, oh it is a read for tag Y. queue statusY & before we queue the read the the following message can be observed: |sd 0:0:0:0: [sda] sense urb submission failure followed by a second attempt with the same result. In order to address this problem we will use only one status URB for each scsi host in case we don't have stream support (as suggested by Matthew). This URB is requeued until the device removed. Nothing changes on stream based endpoints. Signed-off-by: Sebastian Andrzej Siewior --- drivers/usb/storage/uas.c | 70 +++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index e2386e8c7678..036e96900956 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -99,6 +99,7 @@ struct uas_dev_info { unsigned use_streams:1; unsigned uas_sense_old:1; struct scsi_cmnd *cmnd; + struct urb *status_urb; /* used only if stream support is available */ }; enum { @@ -117,6 +118,7 @@ struct uas_cmd_info { unsigned int state; unsigned int stream; struct urb *cmd_urb; + /* status_urb is used only if stream support isn't available */ struct urb *status_urb; struct urb *data_in_urb; struct urb *data_out_urb; @@ -180,7 +182,6 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) cmnd->result = sense_iu->status; cmnd->scsi_done(cmnd); - usb_free_urb(urb); } static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) @@ -205,7 +206,6 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) cmnd->result = sense_iu->status; cmnd->scsi_done(cmnd); - usb_free_urb(urb); } static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, @@ -214,7 +214,7 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; int err; - cmdinfo->state = direction | SUBMIT_STATUS_URB; + cmdinfo->state = direction; err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); if (err) { spin_lock(&uas_work_lock); @@ -231,10 +231,12 @@ static void uas_stat_cmplt(struct urb *urb) struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; struct scsi_cmnd *cmnd; u16 tag; + int ret; if (urb->status) { dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status); - usb_free_urb(urb); + if (devinfo->use_streams) + usb_free_urb(urb); return; } @@ -244,7 +246,13 @@ static void uas_stat_cmplt(struct urb *urb) else cmnd = scsi_host_find_tag(shost, tag - 1); if (!cmnd) { - usb_free_urb(urb); + if (devinfo->use_streams) { + usb_free_urb(urb); + return; + } + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) + dev_err(&urb->dev->dev, "failed submit status urb\n"); return; } @@ -270,6 +278,15 @@ static void uas_stat_cmplt(struct urb *urb) scmd_printk(KERN_ERR, cmnd, "Bogus IU (%d) received on status pipe\n", iu->iu_id); } + + if (devinfo->use_streams) { + usb_free_urb(urb); + return; + } + + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) + dev_err(&urb->dev->dev, "failed submit status urb\n"); } static void uas_data_cmplt(struct urb *urb) @@ -300,7 +317,7 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp, } static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, - struct scsi_cmnd *cmnd, u16 stream_id) + struct Scsi_Host *shost, u16 stream_id) { struct usb_device *udev = devinfo->udev; struct urb *urb = usb_alloc_urb(0, gfp); @@ -314,7 +331,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, goto free; usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu), - uas_stat_cmplt, cmnd->device->host); + uas_stat_cmplt, shost); urb->stream_id = stream_id; urb->transfer_flags |= URB_FREE_BUFFER; out: @@ -376,8 +393,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; if (cmdinfo->state & ALLOC_STATUS_URB) { - cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd, - cmdinfo->stream); + cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, + cmnd->device->host, cmdinfo->stream); if (!cmdinfo->status_urb) return SCSI_MLQUEUE_DEVICE_BUSY; cmdinfo->state &= ~ALLOC_STATUS_URB; @@ -486,7 +503,8 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, } if (!devinfo->use_streams) { - cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB); + cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB | + ALLOC_STATUS_URB | SUBMIT_STATUS_URB); cmdinfo->stream = 0; } @@ -685,6 +703,29 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo) } } +static int uas_alloc_status_urb(struct uas_dev_info *devinfo, + struct Scsi_Host *shost) +{ + if (devinfo->use_streams) { + devinfo->status_urb = NULL; + return 0; + } + + devinfo->status_urb = uas_alloc_sense_urb(devinfo, GFP_KERNEL, + shost, 0); + if (!devinfo->status_urb) + goto err_s_urb; + + if (usb_submit_urb(devinfo->status_urb, GFP_KERNEL)) + goto err_submit_urb; + + return 0; +err_submit_urb: + usb_free_urb(devinfo->status_urb); +err_s_urb: + return -ENOMEM; +} + static void uas_free_streams(struct uas_dev_info *devinfo) { struct usb_device *udev = devinfo->udev; @@ -739,10 +780,17 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) shost->hostdata[0] = (unsigned long)devinfo; + result = uas_alloc_status_urb(devinfo, shost); + if (result) + goto err_alloc_status; + scsi_scan_host(shost); usb_set_intfdata(intf, shost); return result; +err_alloc_status: + scsi_remove_host(shost); + shost = NULL; deconfig_eps: uas_free_streams(devinfo); free: @@ -770,6 +818,8 @@ static void uas_disconnect(struct usb_interface *intf) struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; scsi_remove_host(shost); + usb_kill_urb(devinfo->status_urb); + usb_free_urb(devinfo->status_urb); uas_free_streams(devinfo); kfree(devinfo); } From c688419141ad6134d7973fcf182e3719e98d7491 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 9 Jan 2012 13:14:56 +0100 Subject: [PATCH 007/269] usb: gadget: dummy_hcd: initialize max_streams early While playing with uasp I noticed that it does not work with dummy_hcd. The problem is that uasp requires a stream capable endpoint which it is requesting at bind time like every other gadget. dummy_hcd however initializes the max_stream value after connect once it knows if it runs at SS or not. I don't think that it is might be wrong to initialize the stream capability even at HS speed. The gadget may not use this descriptor at HS speed so it should not cause any damage. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index db815c2da7ed..5a21bf5c7650 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -800,17 +800,10 @@ static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value) static void dummy_udc_udpate_ep0(struct dummy *dum) { - u32 i; - - if (dum->gadget.speed == USB_SPEED_SUPER) { - for (i = 0; i < DUMMY_ENDPOINTS; i++) - dum->ep[i].ep.max_streams = 0x10; + if (dum->gadget.speed == USB_SPEED_SUPER) dum->ep[0].ep.maxpacket = 9; - } else { - for (i = 0; i < DUMMY_ENDPOINTS; i++) - dum->ep[i].ep.max_streams = 0; + else dum->ep[0].ep.maxpacket = 64; - } } static int dummy_pullup (struct usb_gadget *_gadget, int value) @@ -954,6 +947,7 @@ static void init_dummy_udc_hw(struct dummy *dum) ep->halted = ep->wedged = ep->already_seen = ep->setup_stage = 0; ep->ep.maxpacket = ~0; + ep->ep.max_streams = 16; ep->last_io = jiffies; ep->gadget = &dum->gadget; ep->desc = NULL; From a04ce20d9f5e9484ed3879e1290bd05933cbbe2a Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 9 Jan 2012 13:14:57 +0100 Subject: [PATCH 008/269] usb: gadget: dummy_hcd: move the transfer part into its own function This patch moves the part of the code which does the bare transfer into its function. It is a preparion for the implementation of sg support. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 5a21bf5c7650..61e893ac2545 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1133,6 +1133,23 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) return rc; } +static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req, + u32 len) +{ + void *ubuf, *rbuf; + int to_host; + + to_host = usb_pipein(urb->pipe); + rbuf = req->req.buf + req->req.actual; + ubuf = urb->transfer_buffer + urb->actual_length; + + if (to_host) + memcpy(ubuf, rbuf, len); + else + memcpy(rbuf, ubuf, len); + return len; +} + /* transfer up to a frame's worth; caller must own lock */ static int transfer(struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit, @@ -1164,8 +1181,6 @@ top: if (unlikely (len == 0)) is_short = 1; else { - char *ubuf, *rbuf; - /* not enough bandwidth left? */ if (limit < ep->ep.maxpacket && limit < len) break; @@ -1180,13 +1195,8 @@ top: } is_short = (len % ep->ep.maxpacket) != 0; - /* else transfer packet(s) */ - ubuf = urb->transfer_buffer + urb->actual_length; - rbuf = req->req.buf + req->req.actual; - if (to_host) - memcpy (ubuf, rbuf, len); - else - memcpy (rbuf, ubuf, len); + len = dummy_perform_transfer(urb, req, len); + ep->last_io = jiffies; limit -= len; From 14fce33a960afbcf91ef97135903092c33f6d076 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 9 Jan 2012 19:30:50 +0100 Subject: [PATCH 009/269] usb: gadget: dummy_hcd: add sg support This patch adds sg support to dummy_hcd. It seems that uas is not able to work with a hcd which does not support sg only based transfers. Signed-off-by: Sebastian Andrzej Siewior Acked-by: Alan Stern Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 80 ++++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 13 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 61e893ac2545..4973778b7785 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -147,6 +148,8 @@ static const char *const ep_name [] = { struct urbp { struct urb *urb; struct list_head urbp_list; + struct sg_mapping_iter miter; + u32 miter_started; }; @@ -1077,13 +1080,11 @@ static int dummy_urb_enqueue ( unsigned long flags; int rc; - if (!urb->transfer_buffer && urb->transfer_buffer_length) - return -EINVAL; - urbp = kmalloc (sizeof *urbp, mem_flags); if (!urbp) return -ENOMEM; urbp->urb = urb; + urbp->miter_started = 0; dum_hcd = hcd_to_dummy_hcd(hcd); spin_lock_irqsave(&dum_hcd->dum->lock, flags); @@ -1137,17 +1138,66 @@ static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req, u32 len) { void *ubuf, *rbuf; + struct urbp *urbp = urb->hcpriv; int to_host; + struct sg_mapping_iter *miter = &urbp->miter; + u32 trans = 0; + u32 this_sg; + bool next_sg; to_host = usb_pipein(urb->pipe); rbuf = req->req.buf + req->req.actual; - ubuf = urb->transfer_buffer + urb->actual_length; - if (to_host) - memcpy(ubuf, rbuf, len); - else - memcpy(rbuf, ubuf, len); - return len; + if (!urb->num_sgs) { + ubuf = urb->transfer_buffer + urb->actual_length; + if (to_host) + memcpy(ubuf, rbuf, len); + else + memcpy(rbuf, ubuf, len); + return len; + } + + if (!urbp->miter_started) { + u32 flags = SG_MITER_ATOMIC; + + if (to_host) + flags |= SG_MITER_TO_SG; + else + flags |= SG_MITER_FROM_SG; + + sg_miter_start(miter, urb->sg, urb->num_sgs, flags); + urbp->miter_started = 1; + } + next_sg = sg_miter_next(miter); + if (next_sg == false) { + WARN_ON_ONCE(1); + return -EINVAL; + } + do { + ubuf = miter->addr; + this_sg = min_t(u32, len, miter->length); + miter->consumed = this_sg; + trans += this_sg; + + if (to_host) + memcpy(ubuf, rbuf, this_sg); + else + memcpy(rbuf, ubuf, this_sg); + len -= this_sg; + + if (!len) + break; + next_sg = sg_miter_next(miter); + if (next_sg == false) { + WARN_ON_ONCE(1); + return -EINVAL; + } + + rbuf += this_sg; + } while (1); + + sg_miter_stop(miter); + return trans; } /* transfer up to a frame's worth; caller must own lock */ @@ -1198,10 +1248,13 @@ top: len = dummy_perform_transfer(urb, req, len); ep->last_io = jiffies; - - limit -= len; - urb->actual_length += len; - req->req.actual += len; + if (len < 0) { + req->req.status = len; + } else { + limit -= len; + urb->actual_length += len; + req->req.actual += len; + } } /* short packets terminate, maybe with overflow/underflow. @@ -2212,6 +2265,7 @@ static int dummy_h_get_frame (struct usb_hcd *hcd) static int dummy_setup(struct usb_hcd *hcd) { + hcd->self.sg_tablesize = ~0; if (usb_hcd_is_primary_hcd(hcd)) { the_controller.hs_hcd = hcd_to_dummy_hcd(hcd); the_controller.hs_hcd->dum = &the_controller; From d262127c330b852ce4b210a0b1b06e69d4d87704 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 9 Jan 2012 13:14:59 +0100 Subject: [PATCH 010/269] usb: gadget: dummy_hcd: rename dummy_udc_udpate_ep0() to dummy_udc_update_ep0() This renames a function so "update" is spelled properly. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 4973778b7785..a40dc6a4c9eb 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -801,7 +801,7 @@ static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value) return 0; } -static void dummy_udc_udpate_ep0(struct dummy *dum) +static void dummy_udc_update_ep0(struct dummy *dum) { if (dum->gadget.speed == USB_SPEED_SUPER) dum->ep[0].ep.maxpacket = 9; @@ -825,7 +825,7 @@ static int dummy_pullup (struct usb_gadget *_gadget, int value) dum->driver->max_speed); else dum->gadget.speed = USB_SPEED_FULL; - dummy_udc_udpate_ep0(dum); + dummy_udc_update_ep0(dum); if (dum->gadget.speed < dum->driver->max_speed) dev_dbg(udc_dev(dum), "This device can perform faster" From d81f3e4f5792acab5929ef99aad6ca5e21a31a0e Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 9 Jan 2012 13:15:00 +0100 Subject: [PATCH 011/269] usb: gadget: dummy_hcd: make alloc/free streams static There is no reason why dummy_alloc_streams() and dummy_free_streams() are global. Make them static instead. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index a40dc6a4c9eb..626473238b3c 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -2286,7 +2286,7 @@ static int dummy_setup(struct usb_hcd *hcd) } /* Change a group of bulk endpoints to support multiple stream IDs */ -int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, +static int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint **eps, unsigned int num_eps, unsigned int num_streams, gfp_t mem_flags) { @@ -2298,7 +2298,7 @@ int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, } /* Reverts a group of bulk endpoints back to not using stream IDs. */ -int dummy_free_streams(struct usb_hcd *hcd, struct usb_device *udev, +static int dummy_free_streams(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint **eps, unsigned int num_eps, gfp_t mem_flags) { From 10800f2ca1a78e24cf92dc5e16a68a9b78f91bbe Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 4 Jan 2012 10:20:09 +0300 Subject: [PATCH 012/269] usb: gadget: mv_udc: remove unneeded NULL check We've dereferenced req already, and we checked for bogus parameters at the start of the function. Signed-off-by: Dan Carpenter Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_udc_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index f97e737d26f7..8dd398b99e2f 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -771,8 +771,7 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) udc->ep0_state = DATA_STATE_XMIT; /* irq handler advances the queue */ - if (req != NULL) - list_add_tail(&req->queue, &ep->queue); + list_add_tail(&req->queue, &ep->queue); spin_unlock_irqrestore(&udc->lock, flags); return 0; From 53069af3fa8ba2849cd4785160690873995d4f39 Mon Sep 17 00:00:00 2001 From: "Shimoda, Yoshihiro" Date: Thu, 5 Jan 2012 15:37:18 +0900 Subject: [PATCH 013/269] usb: renesas_usbhs: add IRQ resource decoding for IRQF_SHARED In case of the SH7757, the irq number of USB module and SUDMAC are the same. So, we have to set the IRQF_SHARED in such a case. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/common.c | 11 ++++++----- drivers/usb/renesas_usbhs/common.h | 1 + drivers/usb/renesas_usbhs/mod.c | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index e9a5b1d2615e..a165490bae48 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -413,8 +413,7 @@ static int usbhs_probe(struct platform_device *pdev) struct renesas_usbhs_platform_info *info = pdev->dev.platform_data; struct renesas_usbhs_driver_callback *dfunc; struct usbhs_priv *priv; - struct resource *res; - unsigned int irq; + struct resource *res, *irq_res; int ret; /* check platform information */ @@ -426,8 +425,8 @@ static int usbhs_probe(struct platform_device *pdev) /* platform data */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irq = platform_get_irq(pdev, 0); - if (!res || (int)irq <= 0) { + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res || !irq_res) { dev_err(&pdev->dev, "Not enough Renesas USB platform resources.\n"); return -ENODEV; } @@ -476,7 +475,9 @@ static int usbhs_probe(struct platform_device *pdev) /* * priv settings */ - priv->irq = irq; + priv->irq = irq_res->start; + if (irq_res->flags & IORESOURCE_IRQ_SHAREABLE) + priv->irqflags = IRQF_SHARED; priv->pdev = pdev; INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug); spin_lock_init(usbhs_priv_to_lock(priv)); diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h index d79b3e27db95..3f3ccd358753 100644 --- a/drivers/usb/renesas_usbhs/common.h +++ b/drivers/usb/renesas_usbhs/common.h @@ -242,6 +242,7 @@ struct usbhs_priv { void __iomem *base; unsigned int irq; + unsigned long irqflags; struct renesas_usbhs_platform_callback pfunc; struct renesas_usbhs_driver_param dparam; diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 1b97fb12694b..0871e816df45 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c @@ -152,7 +152,7 @@ int usbhs_mod_probe(struct usbhs_priv *priv) /* irq settings */ ret = request_irq(priv->irq, usbhs_interrupt, - 0, dev_name(dev), priv); + priv->irqflags, dev_name(dev), priv); if (ret) { dev_err(dev, "irq request err\n"); goto mod_init_gadget_err; From 5ea4399457f730b4614d0632ceefd3e8f53fb1e6 Mon Sep 17 00:00:00 2001 From: "Shimoda, Yoshihiro" Date: Thu, 5 Jan 2012 15:37:22 +0900 Subject: [PATCH 014/269] usb: renesas_usbhs: add support for SUDMAC The SUDMAC uses 8-bit width only. So, when the driver uses SUDMAC, we have to clear the MBW_32. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 6 +++++- include/linux/usb/renesas_usbhs.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 72339bd6fcab..03a9cc529c82 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -23,6 +23,7 @@ #define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo)) #define usbhsf_get_d0fifo(p) (&((p)->fifo_info.d0fifo)) #define usbhsf_get_d1fifo(p) (&((p)->fifo_info.d1fifo)) +#define usbhsf_is_cfifo(p, f) (usbhsf_get_cfifo(p) == f) #define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */ @@ -305,7 +306,10 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe, } /* "base" will be used below */ - usbhs_write(priv, fifo->sel, base | MBW_32); + if (usbhs_get_dparam(priv, has_sudmac) && !usbhsf_is_cfifo(priv, fifo)) + usbhs_write(priv, fifo->sel, base); + else + usbhs_write(priv, fifo->sel, base | MBW_32); /* check ISEL and CURPIPE value */ while (timeout--) { diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h index 0d3f98879256..547e59cc00ea 100644 --- a/include/linux/usb/renesas_usbhs.h +++ b/include/linux/usb/renesas_usbhs.h @@ -149,6 +149,7 @@ struct renesas_usbhs_driver_param { * option: */ u32 has_otg:1; /* for controlling PWEN/EXTLP */ + u32 has_sudmac:1; /* for SUDMAC */ }; /* From 2d4172c938745cfa51c4a91406efb584549c1024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Sun, 8 Jan 2012 21:57:55 +0100 Subject: [PATCH 015/269] usb: s3c-hsudc: Use helper functions instead of generic container_of The helper functions were definied but never used until now. Signed-off-by: Heiko Stuebner Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsudc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index df8661d266cb..41b3a583c1a7 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -759,7 +759,7 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep, unsigned long flags; u32 ecr = 0; - hsep = container_of(_ep, struct s3c_hsudc_ep, ep); + hsep = our_ep(_ep); if (!_ep || !desc || hsep->desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || hsep->bEndpointAddress != desc->bEndpointAddress @@ -853,7 +853,7 @@ static void s3c_hsudc_free_request(struct usb_ep *ep, struct usb_request *_req) { struct s3c_hsudc_req *hsreq; - hsreq = container_of(_req, struct s3c_hsudc_req, req); + hsreq = our_req(_req); WARN_ON(!list_empty(&hsreq->queue)); kfree(hsreq); } @@ -876,12 +876,12 @@ static int s3c_hsudc_queue(struct usb_ep *_ep, struct usb_request *_req, u32 offset; u32 csr; - hsreq = container_of(_req, struct s3c_hsudc_req, req); + hsreq = our_req(_req); if ((!_req || !_req->complete || !_req->buf || !list_empty(&hsreq->queue))) return -EINVAL; - hsep = container_of(_ep, struct s3c_hsudc_ep, ep); + hsep = our_ep(_ep); hsudc = hsep->dev; if (!hsudc->driver || hsudc->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; @@ -935,7 +935,7 @@ static int s3c_hsudc_dequeue(struct usb_ep *_ep, struct usb_request *_req) struct s3c_hsudc_req *hsreq; unsigned long flags; - hsep = container_of(_ep, struct s3c_hsudc_ep, ep); + hsep = our_ep(_ep); if (!_ep || hsep->ep.name == ep0name) return -EINVAL; From 294f78ec493e69b55bcba566d4fe264d041aba8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Sun, 8 Jan 2012 21:58:28 +0100 Subject: [PATCH 016/269] usb: s3c-hsudc: add basic runtime_pm calls This will enable the system to check for activity of the usb gadget and also in a later patch to control the usbphy power-domain. When handling the power domain there, it will be possible to remove another reference to architecture code. Signed-off-by: Heiko Stuebner Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsudc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index 41b3a583c1a7..5e8729374fba 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -1178,6 +1179,9 @@ static int s3c_hsudc_start(struct usb_gadget *gadget, dev_info(hsudc->dev, "bound driver %s\n", driver->driver.name); s3c_hsudc_reconfig(hsudc); + + pm_runtime_get_sync(hsudc->dev); + s3c_hsudc_init_phy(); if (hsudc->pd->gpio_init) hsudc->pd->gpio_init(); @@ -1208,6 +1212,9 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget, hsudc->gadget.dev.driver = NULL; hsudc->gadget.speed = USB_SPEED_UNKNOWN; s3c_hsudc_uninit_phy(); + + pm_runtime_put(hsudc->dev); + if (hsudc->pd->gpio_uninit) hsudc->pd->gpio_uninit(); s3c_hsudc_stop_activity(hsudc); @@ -1362,6 +1369,8 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev) if (ret) goto err_add_udc; + pm_runtime_enable(dev); + return 0; err_add_udc: device_unregister(&hsudc->gadget.dev); From c50a3bff0edb0acd49d8033a12ea4668e09a31ad Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 12 Jan 2012 11:27:05 +0900 Subject: [PATCH 017/269] usb: gadget: pch_udc: Fix disconnect issue ISSUE: When the driver notifies a gadget of a disconnect event, a system rarely freezes. CAUSE: When the driver calls dev->driver->disconnect(), it is not calling spin_unlock(). Signed-off-by: Tomoya MORINAGA Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index a3fcaae4bc2a..6a44c921d13c 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -2335,8 +2335,11 @@ static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev) /* Complete request queue */ empty_req_queue(ep); } - if (dev->driver && dev->driver->disconnect) + if (dev->driver && dev->driver->disconnect) { + spin_unlock(&dev->lock); dev->driver->disconnect(&dev->gadget); + spin_lock(&dev->lock); + } } /** From c802672cd36cd063bfd54d54c8c34825ab5b2357 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 12 Jan 2012 11:27:06 +0900 Subject: [PATCH 018/269] usb: gadget: pch_udc: Fix wrong return value ISSUE: If the return value of pch_udc_pcd_init() is False, the return value of this function is unsettled. Since pch_udc_pcd_init() always returns 0, there is not actually the issue. CAUSE: If pch_udc_pcd_init() is True, the variable, retval, is not set for an appropriate value. Signed-off-by: Tomoya MORINAGA Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 6a44c921d13c..96606b6cff45 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -2915,8 +2915,10 @@ static int pch_udc_probe(struct pci_dev *pdev, } pch_udc = dev; /* initialize the hardware */ - if (pch_udc_pcd_init(dev)) + if (pch_udc_pcd_init(dev)) { + retval = -ENODEV; goto finished; + } if (request_irq(pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME, dev)) { dev_err(&pdev->dev, "%s: request_irq(%d) fail\n", __func__, From 84566abba058b2aae8d603dfa90b5a3778a6714f Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 12 Jan 2012 11:27:07 +0900 Subject: [PATCH 019/269] usb: gadget: pch_udc: Fix USB suspend issue ISSUE: After USB Suspend, a system rarely freezes. CAUSE: When USB Suspend occurred, the driver is not notifying a gadget of the event. Signed-off-by: Tomoya MORINAGA Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 96606b6cff45..842ca6349a90 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -2475,8 +2475,15 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr) if (dev_intr & UDC_DEVINT_SC) pch_udc_svc_cfg_interrupt(dev); /* USB Suspend interrupt */ - if (dev_intr & UDC_DEVINT_US) + if (dev_intr & UDC_DEVINT_US) { + if (dev->driver + && dev->driver->suspend) { + spin_unlock(&dev->lock); + dev->driver->suspend(&dev->gadget); + spin_lock(&dev->lock); + } dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n"); + } /* Clear the SOF interrupt, if enabled */ if (dev_intr & UDC_DEVINT_SOF) dev_dbg(&dev->pdev->dev, "SOF\n"); From 1c575d2d2e3ff2a7cb3c2e2165064199cfd8ad32 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 12 Jan 2012 11:27:08 +0900 Subject: [PATCH 020/269] usb: gadget: pch_udc: Fix usb/gadget/pch_udc: Fix ether gadget connect/disconnect issue ISSUE: After a USB cable is connect/disconnected, the system rarely freezes. CAUSE: Since the USB device controller cannot know to disconnect the USB cable, when it is used without detecting VBUS by GPIO, the UDC driver does not notify to USB Gadget. Since USB Gadget cannot know to disconnect, a false setting occurred when the USB cable is connected/disconnect repeatedly. Signed-off-by: Tomoya MORINAGA Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 70 +++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 842ca6349a90..c2f19752c074 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -311,6 +311,7 @@ struct pch_udc_ep { * @registered: driver regsitered with system * @suspended: driver in suspended state * @connected: gadget driver associated + * @vbus_session: required vbus_session state * @set_cfg_not_acked: pending acknowledgement 4 setup * @waiting_zlp_ack: pending acknowledgement 4 ZLP * @data_requests: DMA pool for data requests @@ -337,6 +338,7 @@ struct pch_udc_dev { registered:1, suspended:1, connected:1, + vbus_session:1, set_cfg_not_acked:1, waiting_zlp_ack:1; struct pci_pool *data_requests; @@ -553,6 +555,31 @@ static void pch_udc_clear_disconnect(struct pch_udc_dev *dev) pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES); } +/** + * pch_udc_reconnect() - This API initializes usb device controller, + * and clear the disconnect status. + * @dev: Reference to pch_udc_regs structure + */ +static void pch_udc_init(struct pch_udc_dev *dev); +static void pch_udc_reconnect(struct pch_udc_dev *dev) +{ + pch_udc_init(dev); + + /* enable device interrupts */ + /* pch_udc_enable_interrupts() */ + pch_udc_bit_clr(dev, UDC_DEVIRQMSK_ADDR, + UDC_DEVINT_UR | UDC_DEVINT_US | + UDC_DEVINT_ENUM | + UDC_DEVINT_SI | UDC_DEVINT_SC); + + /* Clear the disconnect */ + pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES); + pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD); + mdelay(1); + /* Resume USB signalling */ + pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES); +} + /** * pch_udc_vbus_session() - set or clearr the disconnect status. * @dev: Reference to pch_udc_regs structure @@ -563,10 +590,18 @@ static void pch_udc_clear_disconnect(struct pch_udc_dev *dev) static inline void pch_udc_vbus_session(struct pch_udc_dev *dev, int is_active) { - if (is_active) - pch_udc_clear_disconnect(dev); - else + if (is_active) { + pch_udc_reconnect(dev); + dev->vbus_session = 1; + } else { + if (dev->driver && dev->driver->disconnect) { + spin_unlock(&dev->lock); + dev->driver->disconnect(&dev->gadget); + spin_lock(&dev->lock); + } pch_udc_set_disconnect(dev); + dev->vbus_session = 0; + } } /** @@ -1126,7 +1161,17 @@ static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on) if (!gadget) return -EINVAL; dev = container_of(gadget, struct pch_udc_dev, gadget); - pch_udc_vbus_session(dev, is_on); + if (is_on) { + pch_udc_reconnect(dev); + } else { + if (dev->driver && dev->driver->disconnect) { + spin_unlock(&dev->lock); + dev->driver->disconnect(&dev->gadget); + spin_lock(&dev->lock); + } + pch_udc_set_disconnect(dev); + } + return 0; } @@ -2482,6 +2527,15 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr) dev->driver->suspend(&dev->gadget); spin_lock(&dev->lock); } + + if (dev->vbus_session == 0) { + if (dev->driver && dev->driver->disconnect) { + spin_unlock(&dev->lock); + dev->driver->disconnect(&dev->gadget); + spin_lock(&dev->lock); + } + pch_udc_reconnect(dev); + } dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n"); } /* Clear the SOF interrupt, if enabled */ @@ -2509,6 +2563,14 @@ static irqreturn_t pch_udc_isr(int irq, void *pdev) dev_intr = pch_udc_read_device_interrupts(dev); ep_intr = pch_udc_read_ep_interrupts(dev); + /* For a hot plug, this find that the controller is hung up. */ + if (dev_intr == ep_intr) + if (dev_intr == pch_udc_readl(dev, UDC_DEVCFG_ADDR)) { + dev_dbg(&dev->pdev->dev, "UDC: Hung up\n"); + /* The controller is reset */ + pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR); + return IRQ_HANDLED; + } if (dev_intr) /* Clear device interrupts */ pch_udc_write_device_interrupts(dev, dev_intr); From 833310402c54ad9b676b465fc53ad276b13d36be Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 12 Jan 2012 11:27:09 +0900 Subject: [PATCH 021/269] usb: gadget: pch_udc: Reduce redundant interrupt ISSUE: USB Suspend interrupts occur frequently. CAUSE: When it is called pch_udc_reconnect() in USB Suspend, it repeats reset and Suspend. SOLUTION: pch_udc_reconnect() does not enable all interrupts. When an enumeration event occurred the driver enables all interrupts. Signed-off-by: Tomoya MORINAGA Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index c2f19752c074..4da98141e058 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -568,9 +568,7 @@ static void pch_udc_reconnect(struct pch_udc_dev *dev) /* enable device interrupts */ /* pch_udc_enable_interrupts() */ pch_udc_bit_clr(dev, UDC_DEVIRQMSK_ADDR, - UDC_DEVINT_UR | UDC_DEVINT_US | - UDC_DEVINT_ENUM | - UDC_DEVINT_SI | UDC_DEVINT_SC); + UDC_DEVINT_UR | UDC_DEVINT_ENUM); /* Clear the disconnect */ pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES); @@ -2419,6 +2417,11 @@ static void pch_udc_svc_enum_interrupt(struct pch_udc_dev *dev) pch_udc_set_dma(dev, DMA_DIR_TX); pch_udc_set_dma(dev, DMA_DIR_RX); pch_udc_ep_set_rrdy(&(dev->ep[UDC_EP0OUT_IDX])); + + /* enable device interrupts */ + pch_udc_enable_interrupts(dev, UDC_DEVINT_UR | UDC_DEVINT_US | + UDC_DEVINT_ES | UDC_DEVINT_ENUM | + UDC_DEVINT_SI | UDC_DEVINT_SC); } /** From 9645f7d3dab346a9d442dca1688740551b8c55f2 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 12 Jan 2012 11:27:10 +0900 Subject: [PATCH 022/269] usb: gadget: pch_udc: Add debug message ISSUE: Adding debugging messages. CAUSE: The debugging messages are added to make sure of that major interrupt events are occurring. Signed-off-by: Tomoya MORINAGA Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 4da98141e058..82416aae816f 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -2511,11 +2511,15 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev) static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr) { /* USB Reset Interrupt */ - if (dev_intr & UDC_DEVINT_UR) + if (dev_intr & UDC_DEVINT_UR) { pch_udc_svc_ur_interrupt(dev); + dev_dbg(&dev->pdev->dev, "USB_RESET\n"); + } /* Enumeration Done Interrupt */ - if (dev_intr & UDC_DEVINT_ENUM) + if (dev_intr & UDC_DEVINT_ENUM) { pch_udc_svc_enum_interrupt(dev); + dev_dbg(&dev->pdev->dev, "USB_ENUM\n"); + } /* Set Interface Interrupt */ if (dev_intr & UDC_DEVINT_SI) pch_udc_svc_intf_interrupt(dev); From a54c979fed31b4230b2e63132f7167206e4e5d69 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 13 Jan 2012 21:51:47 +0100 Subject: [PATCH 023/269] usb: gadget: dummy_hcd: complete stream support dummy_hcd provides (alloc|free)_stream() callbacks but there are not doing anything. The transfer side also lacks matching of streams. This patch changes this and implements stream allocation / de-allocation support and proper urb <=> req matching. The UDC side exposes a limit of 16 streams. DWC3, the only USB3 UDC has no limitations in this regard except that it _needs_ to know that streams will be used at the ep_enable time. At the host side, there is no real limit either: XHCI can allocate any number of streams as long as it does not run out of memory. The UAS gadget currently requests 16 streams and the UAS host side fallbacks from the requested 256 down to 16 which is fine. From the UASP point of view (the only specified user), the number of used streams does not really matter. The only limitation is that the host may not use a higher stream than the gadget requested and can deal with. The dummy stream support has been modelled after current UAS + XHCI + DWC3 + UASP usage which helps me testing: - the device announces that each ep supports 16 streams (even it could more than that). - the device side looks into Companion descriptor at ep_enable time and enables them according to it. - the host side tries to enable the requested number of streams but the upper limit is the Comanion descriptor. None (zero streams) is an error condition, less is okay. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 197 ++++++++++++++++++++++++++++++--- 1 file changed, 181 insertions(+), 16 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 626473238b3c..e57989ccc0e5 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -88,6 +88,7 @@ struct dummy_ep { unsigned wedged : 1; unsigned already_seen : 1; unsigned setup_stage : 1; + unsigned stream_en:1; }; struct dummy_request { @@ -169,6 +170,8 @@ struct dummy_hcd { struct usb_device *udev; struct list_head urbp_list; + u32 stream_en_ep; + u8 num_stream[30 / 2]; unsigned active:1; unsigned old_active:1; @@ -514,8 +517,16 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) _ep->maxpacket = max; ep->desc = desc; + if (usb_ss_max_streams(_ep->comp_desc)) { + if (!usb_endpoint_xfer_bulk(desc)) { + dev_err(udc_dev(dum), "Can't enable stream support on " + "non-bulk ep %s\n", _ep->name); + return -EINVAL; + } + ep->stream_en = 1; + } - dev_dbg (udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d\n", + dev_dbg(udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d stream %s\n", _ep->name, desc->bEndpointAddress & 0x0f, (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out", @@ -534,7 +545,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) val = "ctrl"; break; }; val; }), - max); + max, ep->stream_en ? "enabled" : "disabled"); /* at this point real hardware should be NAKing transfers * to that endpoint, until a buffer is queued to it. @@ -559,6 +570,7 @@ static int dummy_disable (struct usb_ep *_ep) spin_lock_irqsave (&dum->lock, flags); ep->desc = NULL; + ep->stream_en = 0; retval = 0; nuke (dum, ep); spin_unlock_irqrestore (&dum->lock, flags); @@ -1058,6 +1070,16 @@ static struct platform_driver dummy_udc_driver = { /*-------------------------------------------------------------------------*/ +static unsigned int dummy_get_ep_idx(const struct usb_endpoint_descriptor *desc) +{ + unsigned int index; + + index = usb_endpoint_num(desc) << 1; + if (usb_endpoint_dir_in(desc)) + index |= 1; + return index; +} + /* MASTER/HOST SIDE DRIVER * * this uses the hcd framework to hook up to host side drivers. @@ -1070,6 +1092,81 @@ static struct platform_driver dummy_udc_driver = { * usb 2.0 rules. */ +static int dummy_ep_stream_en(struct dummy_hcd *dum_hcd, struct urb *urb) +{ + const struct usb_endpoint_descriptor *desc = &urb->ep->desc; + u32 index; + + if (!usb_endpoint_xfer_bulk(desc)) + return 0; + + index = dummy_get_ep_idx(desc); + return (1 << index) & dum_hcd->stream_en_ep; +} + +/* + * The max stream number is saved as a nibble so for the 30 possible endpoints + * we only 15 bytes of memory. Therefore we are limited to max 16 streams (0 + * means we use only 1 stream). The maximum according to the spec is 16bit so + * if the 16 stream limit is about to go, the array size should be incremented + * to 30 elements of type u16. + */ +static int get_max_streams_for_pipe(struct dummy_hcd *dum_hcd, + unsigned int pipe) +{ + int max_streams; + + max_streams = dum_hcd->num_stream[usb_pipeendpoint(pipe)]; + if (usb_pipeout(pipe)) + max_streams >>= 4; + else + max_streams &= 0xf; + max_streams++; + return max_streams; +} + +static void set_max_streams_for_pipe(struct dummy_hcd *dum_hcd, + unsigned int pipe, unsigned int streams) +{ + int max_streams; + + streams--; + max_streams = dum_hcd->num_stream[usb_pipeendpoint(pipe)]; + if (usb_pipeout(pipe)) { + streams <<= 4; + max_streams &= 0xf; + } else { + max_streams &= 0xf0; + } + max_streams |= streams; + dum_hcd->num_stream[usb_pipeendpoint(pipe)] = max_streams; +} + +static int dummy_validate_stream(struct dummy_hcd *dum_hcd, struct urb *urb) +{ + unsigned int max_streams; + int enabled; + + enabled = dummy_ep_stream_en(dum_hcd, urb); + if (!urb->stream_id) { + if (enabled) + return -EINVAL; + return 0; + } + if (!enabled) + return -EINVAL; + + max_streams = get_max_streams_for_pipe(dum_hcd, + usb_pipeendpoint(urb->pipe)); + if (urb->stream_id > max_streams) { + dev_err(dummy_dev(dum_hcd), "Stream id %d is out of range.\n", + urb->stream_id); + BUG(); + return -EINVAL; + } + return 0; +} + static int dummy_urb_enqueue ( struct usb_hcd *hcd, struct urb *urb, @@ -1088,6 +1185,13 @@ static int dummy_urb_enqueue ( dum_hcd = hcd_to_dummy_hcd(hcd); spin_lock_irqsave(&dum_hcd->dum->lock, flags); + + rc = dummy_validate_stream(dum_hcd, urb); + if (rc) { + kfree(urbp); + goto done; + } + rc = usb_hcd_link_urb_to_ep(hcd, urb); if (rc) { kfree(urbp); @@ -1201,10 +1305,10 @@ static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req, } /* transfer up to a frame's worth; caller must own lock */ -static int -transfer(struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit, - int *status) +static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb, + struct dummy_ep *ep, int limit, int *status) { + struct dummy *dum = dum_hcd->dum; struct dummy_request *req; top: @@ -1214,6 +1318,11 @@ top: int is_short, to_host; int rescan = 0; + if (dummy_ep_stream_en(dum_hcd, urb)) { + if ((urb->stream_id != req->req.stream_id)) + continue; + } + /* 1..N packets of ep->ep.maxpacket each ... the last one * may be short (including zero length). * @@ -1744,7 +1853,7 @@ restart: default: treat_control_like_bulk: ep->last_io = jiffies; - total = transfer(dum, urb, ep, limit, &status); + total = transfer(dum_hcd, urb, ep, limit, &status); break; } @@ -2201,6 +2310,7 @@ static int dummy_start_ss(struct dummy_hcd *dum_hcd) dum_hcd->timer.function = dummy_timer; dum_hcd->timer.data = (unsigned long)dum_hcd; dum_hcd->rh_state = DUMMY_RH_RUNNING; + dum_hcd->stream_en_ep = 0; INIT_LIST_HEAD(&dum_hcd->urbp_list); dummy_hcd_to_hcd(dum_hcd)->power_budget = POWER_BUDGET; dummy_hcd_to_hcd(dum_hcd)->state = HC_STATE_RUNNING; @@ -2290,11 +2400,46 @@ static int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint **eps, unsigned int num_eps, unsigned int num_streams, gfp_t mem_flags) { - if (hcd->speed != HCD_USB3) - dev_dbg(dummy_dev(hcd_to_dummy_hcd(hcd)), - "%s() - ERROR! Not supported for USB2.0 roothub\n", - __func__); - return 0; + struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd); + unsigned long flags; + int max_stream; + int ret_streams = num_streams; + unsigned int index; + unsigned int i; + + if (!num_eps) + return -EINVAL; + + spin_lock_irqsave(&dum_hcd->dum->lock, flags); + for (i = 0; i < num_eps; i++) { + index = dummy_get_ep_idx(&eps[i]->desc); + if ((1 << index) & dum_hcd->stream_en_ep) { + ret_streams = -EINVAL; + goto out; + } + max_stream = usb_ss_max_streams(&eps[i]->ss_ep_comp); + if (!max_stream) { + ret_streams = -EINVAL; + goto out; + } + if (max_stream < ret_streams) { + dev_dbg(dummy_dev(dum_hcd), "Ep 0x%x only supports %u " + "stream IDs.\n", + eps[i]->desc.bEndpointAddress, + max_stream); + ret_streams = max_stream; + } + } + + for (i = 0; i < num_eps; i++) { + index = dummy_get_ep_idx(&eps[i]->desc); + dum_hcd->stream_en_ep |= 1 << index; + set_max_streams_for_pipe(dum_hcd, + usb_endpoint_num(&eps[i]->desc), ret_streams); + } +out: + spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); + return ret_streams; } /* Reverts a group of bulk endpoints back to not using stream IDs. */ @@ -2302,11 +2447,31 @@ static int dummy_free_streams(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint **eps, unsigned int num_eps, gfp_t mem_flags) { - if (hcd->speed != HCD_USB3) - dev_dbg(dummy_dev(hcd_to_dummy_hcd(hcd)), - "%s() - ERROR! Not supported for USB2.0 roothub\n", - __func__); - return 0; + struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd); + unsigned long flags; + int ret; + unsigned int index; + unsigned int i; + + spin_lock_irqsave(&dum_hcd->dum->lock, flags); + for (i = 0; i < num_eps; i++) { + index = dummy_get_ep_idx(&eps[i]->desc); + if (!((1 << index) & dum_hcd->stream_en_ep)) { + ret = -EINVAL; + goto out; + } + } + + for (i = 0; i < num_eps; i++) { + index = dummy_get_ep_idx(&eps[i]->desc); + dum_hcd->stream_en_ep &= ~(1 << index); + set_max_streams_for_pipe(dum_hcd, + usb_endpoint_num(&eps[i]->desc), 0); + } + ret = 0; +out: + spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); + return ret; } static struct hc_driver dummy_hcd = { From 59f08e6d2015a16fb4856f910ef0660d13a0c767 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 12 Jan 2012 12:53:14 +0100 Subject: [PATCH 024/269] usb: dummy_hcd: use usb_endpoint_type() This patch makes use of usb_endpoint_type() instead of the open coding. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index e57989ccc0e5..fd4d86a57142 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -447,7 +447,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) * especially for "ep9out" style fixed function ones.) */ retval = -EINVAL; - switch (desc->bmAttributes & 0x03) { + switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_BULK: if (strstr (ep->ep.name, "-iso") || strstr (ep->ep.name, "-int")) { @@ -531,7 +531,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) desc->bEndpointAddress & 0x0f, (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out", ({ char *val; - switch (desc->bmAttributes & 0x03) { + switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_BULK: val = "bulk"; break; @@ -1439,7 +1439,7 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep) limit += limit * tmp; } if (dum->gadget.speed == USB_SPEED_SUPER) { - switch (ep->desc->bmAttributes & 0x03) { + switch (usb_endpoint_type(ep->desc)) { case USB_ENDPOINT_XFER_ISOC: /* Sec. 4.4.8.2 USB3.0 Spec */ limit = 3 * 16 * 1024 * 8; From 18f2cbaa2b9617eed20789ce40878920a8ea6beb Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 12 Jan 2012 12:53:15 +0100 Subject: [PATCH 025/269] usb: gadget: dummy_hcd: clean up checkpatch This patch converts checkpatch output of |./scripts/checkpatch.pl drivers/usb/gadget/dummy_hcd.c -file from |total: 22 errors, 174 warnings, 2642 lines checked to |total: 0 errors, 0 warnings, 2632 lines checked Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 432 ++++++++++++++++----------------- 1 file changed, 211 insertions(+), 221 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index fd4d86a57142..67573e5f2a18 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -42,25 +42,24 @@ #include #include -#include +#include #include #include #include - #define DRIVER_DESC "USB Host+Gadget Emulator" #define DRIVER_VERSION "02 May 2005" #define POWER_BUDGET 500 /* in mA; use 8 for low-power port testing */ -static const char driver_name [] = "dummy_hcd"; -static const char driver_desc [] = "USB Host+Gadget Emulator"; +static const char driver_name[] = "dummy_hcd"; +static const char driver_desc[] = "USB Host+Gadget Emulator"; -static const char gadget_name [] = "dummy_udc"; +static const char gadget_name[] = "dummy_udc"; -MODULE_DESCRIPTION (DRIVER_DESC); -MODULE_AUTHOR ("David Brownell"); -MODULE_LICENSE ("GPL"); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("David Brownell"); +MODULE_LICENSE("GPL"); struct dummy_hcd_module_parameters { bool is_super_speed; @@ -84,10 +83,10 @@ struct dummy_ep { struct usb_gadget *gadget; const struct usb_endpoint_descriptor *desc; struct usb_ep ep; - unsigned halted : 1; - unsigned wedged : 1; - unsigned already_seen : 1; - unsigned setup_stage : 1; + unsigned halted:1; + unsigned wedged:1; + unsigned already_seen:1; + unsigned setup_stage:1; unsigned stream_en:1; }; @@ -96,15 +95,15 @@ struct dummy_request { struct usb_request req; }; -static inline struct dummy_ep *usb_ep_to_dummy_ep (struct usb_ep *_ep) +static inline struct dummy_ep *usb_ep_to_dummy_ep(struct usb_ep *_ep) { - return container_of (_ep, struct dummy_ep, ep); + return container_of(_ep, struct dummy_ep, ep); } static inline struct dummy_request *usb_request_to_dummy_request (struct usb_request *_req) { - return container_of (_req, struct dummy_request, req); + return container_of(_req, struct dummy_request, req); } /*-------------------------------------------------------------------------*/ @@ -123,9 +122,9 @@ static inline struct dummy_request *usb_request_to_dummy_request * configurations, illegal or unsupported packet lengths, and so on. */ -static const char ep0name [] = "ep0"; +static const char ep0name[] = "ep0"; -static const char *const ep_name [] = { +static const char *const ep_name[] = { ep0name, /* everyone has ep0 */ /* act like a net2280: high speed, six configurable endpoints */ @@ -184,12 +183,12 @@ struct dummy { /* * SLAVE/GADGET side support */ - struct dummy_ep ep [DUMMY_ENDPOINTS]; + struct dummy_ep ep[DUMMY_ENDPOINTS]; int address; struct usb_gadget gadget; struct usb_gadget_driver *driver; struct dummy_request fifo_req; - u8 fifo_buf [FIFO_SIZE]; + u8 fifo_buf[FIFO_SIZE]; u16 devstatus; unsigned udc_suspended:1; unsigned pullup:1; @@ -216,14 +215,14 @@ static inline struct device *dummy_dev(struct dummy_hcd *dum) return dummy_hcd_to_hcd(dum)->self.controller; } -static inline struct device *udc_dev (struct dummy *dum) +static inline struct device *udc_dev(struct dummy *dum) { return dum->gadget.dev.parent; } -static inline struct dummy *ep_to_dummy (struct dummy_ep *ep) +static inline struct dummy *ep_to_dummy(struct dummy_ep *ep) { - return container_of (ep->gadget, struct dummy, gadget); + return container_of(ep->gadget, struct dummy, gadget); } static inline struct dummy_hcd *gadget_to_dummy_hcd(struct usb_gadget *gadget) @@ -235,9 +234,9 @@ static inline struct dummy_hcd *gadget_to_dummy_hcd(struct usb_gadget *gadget) return dum->hs_hcd; } -static inline struct dummy *gadget_dev_to_dummy (struct device *dev) +static inline struct dummy *gadget_dev_to_dummy(struct device *dev) { - return container_of (dev, struct dummy, gadget.dev); + return container_of(dev, struct dummy, gadget.dev); } static struct dummy the_controller; @@ -247,24 +246,23 @@ static struct dummy the_controller; /* SLAVE/GADGET SIDE UTILITY ROUTINES */ /* called with spinlock held */ -static void nuke (struct dummy *dum, struct dummy_ep *ep) +static void nuke(struct dummy *dum, struct dummy_ep *ep) { - while (!list_empty (&ep->queue)) { + while (!list_empty(&ep->queue)) { struct dummy_request *req; - req = list_entry (ep->queue.next, struct dummy_request, queue); - list_del_init (&req->queue); + req = list_entry(ep->queue.next, struct dummy_request, queue); + list_del_init(&req->queue); req->req.status = -ESHUTDOWN; - spin_unlock (&dum->lock); - req->req.complete (&ep->ep, &req->req); - spin_lock (&dum->lock); + spin_unlock(&dum->lock); + req->req.complete(&ep->ep, &req->req); + spin_lock(&dum->lock); } } /* caller must hold lock */ -static void -stop_activity (struct dummy *dum) +static void stop_activity(struct dummy *dum) { struct dummy_ep *ep; @@ -274,8 +272,8 @@ stop_activity (struct dummy *dum) /* The timer is left running so that outstanding URBs can fail */ /* nuke any pending requests first, so driver i/o is quiesced */ - list_for_each_entry (ep, &dum->gadget.ep_list, ep.ep_list) - nuke (dum, ep); + list_for_each_entry(ep, &dum->gadget.ep_list, ep.ep_list) + nuke(dum, ep); /* driver now does any non-usb quiescing necessary */ } @@ -410,8 +408,8 @@ static void set_link_state(struct dummy_hcd *dum_hcd) #define is_enabled(dum) \ (dum->port_status & USB_PORT_STAT_ENABLE) -static int -dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) +static int dummy_enable(struct usb_ep *_ep, + const struct usb_endpoint_descriptor *desc) { struct dummy *dum; struct dummy_hcd *dum_hcd; @@ -419,11 +417,11 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) unsigned max; int retval; - ep = usb_ep_to_dummy_ep (_ep); + ep = usb_ep_to_dummy_ep(_ep); if (!_ep || !desc || ep->desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT) return -EINVAL; - dum = ep_to_dummy (ep); + dum = ep_to_dummy(ep); if (!dum->driver) return -ESHUTDOWN; @@ -449,8 +447,8 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) retval = -EINVAL; switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_BULK: - if (strstr (ep->ep.name, "-iso") - || strstr (ep->ep.name, "-int")) { + if (strstr(ep->ep.name, "-iso") + || strstr(ep->ep.name, "-int")) { goto done; } switch (dum->gadget.speed) { @@ -472,7 +470,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) } break; case USB_ENDPOINT_XFER_INT: - if (strstr (ep->ep.name, "-iso")) /* bulk is ok */ + if (strstr(ep->ep.name, "-iso")) /* bulk is ok */ goto done; /* real hardware might not handle all packet sizes */ switch (dum->gadget.speed) { @@ -492,8 +490,8 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) } break; case USB_ENDPOINT_XFER_ISOC: - if (strstr (ep->ep.name, "-bulk") - || strstr (ep->ep.name, "-int")) + if (strstr(ep->ep.name, "-bulk") + || strstr(ep->ep.name, "-int")) goto done; /* real hardware might not handle all packet sizes */ switch (dum->gadget.speed) { @@ -556,68 +554,65 @@ done: return retval; } -static int dummy_disable (struct usb_ep *_ep) +static int dummy_disable(struct usb_ep *_ep) { struct dummy_ep *ep; struct dummy *dum; unsigned long flags; int retval; - ep = usb_ep_to_dummy_ep (_ep); + ep = usb_ep_to_dummy_ep(_ep); if (!_ep || !ep->desc || _ep->name == ep0name) return -EINVAL; - dum = ep_to_dummy (ep); + dum = ep_to_dummy(ep); - spin_lock_irqsave (&dum->lock, flags); + spin_lock_irqsave(&dum->lock, flags); ep->desc = NULL; ep->stream_en = 0; retval = 0; - nuke (dum, ep); - spin_unlock_irqrestore (&dum->lock, flags); + nuke(dum, ep); + spin_unlock_irqrestore(&dum->lock, flags); - dev_dbg (udc_dev(dum), "disabled %s\n", _ep->name); + dev_dbg(udc_dev(dum), "disabled %s\n", _ep->name); return retval; } -static struct usb_request * -dummy_alloc_request (struct usb_ep *_ep, gfp_t mem_flags) +static struct usb_request *dummy_alloc_request(struct usb_ep *_ep, + gfp_t mem_flags) { struct dummy_ep *ep; struct dummy_request *req; if (!_ep) return NULL; - ep = usb_ep_to_dummy_ep (_ep); + ep = usb_ep_to_dummy_ep(_ep); req = kzalloc(sizeof(*req), mem_flags); if (!req) return NULL; - INIT_LIST_HEAD (&req->queue); + INIT_LIST_HEAD(&req->queue); return &req->req; } -static void -dummy_free_request (struct usb_ep *_ep, struct usb_request *_req) +static void dummy_free_request(struct usb_ep *_ep, struct usb_request *_req) { struct dummy_ep *ep; struct dummy_request *req; - ep = usb_ep_to_dummy_ep (_ep); + ep = usb_ep_to_dummy_ep(_ep); if (!ep || !_req || (!ep->desc && _ep->name != ep0name)) return; - req = usb_request_to_dummy_request (_req); - WARN_ON (!list_empty (&req->queue)); - kfree (req); + req = usb_request_to_dummy_request(_req); + WARN_ON(!list_empty(&req->queue)); + kfree(req); } -static void -fifo_complete (struct usb_ep *ep, struct usb_request *req) +static void fifo_complete(struct usb_ep *ep, struct usb_request *req) { } -static int -dummy_queue (struct usb_ep *_ep, struct usb_request *_req, +static int dummy_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t mem_flags) { struct dummy_ep *ep; @@ -626,49 +621,48 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req, struct dummy_hcd *dum_hcd; unsigned long flags; - req = usb_request_to_dummy_request (_req); - if (!_req || !list_empty (&req->queue) || !_req->complete) + req = usb_request_to_dummy_request(_req); + if (!_req || !list_empty(&req->queue) || !_req->complete) return -EINVAL; - ep = usb_ep_to_dummy_ep (_ep); + ep = usb_ep_to_dummy_ep(_ep); if (!_ep || (!ep->desc && _ep->name != ep0name)) return -EINVAL; - dum = ep_to_dummy (ep); + dum = ep_to_dummy(ep); dum_hcd = gadget_to_dummy_hcd(&dum->gadget); if (!dum->driver || !is_enabled(dum_hcd)) return -ESHUTDOWN; #if 0 - dev_dbg (udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n", + dev_dbg(udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n", ep, _req, _ep->name, _req->length, _req->buf); #endif - _req->status = -EINPROGRESS; _req->actual = 0; - spin_lock_irqsave (&dum->lock, flags); + spin_lock_irqsave(&dum->lock, flags); /* implement an emulated single-request FIFO */ if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) && - list_empty (&dum->fifo_req.queue) && - list_empty (&ep->queue) && + list_empty(&dum->fifo_req.queue) && + list_empty(&ep->queue) && _req->length <= FIFO_SIZE) { req = &dum->fifo_req; req->req = *_req; req->req.buf = dum->fifo_buf; - memcpy (dum->fifo_buf, _req->buf, _req->length); + memcpy(dum->fifo_buf, _req->buf, _req->length); req->req.context = dum; req->req.complete = fifo_complete; list_add_tail(&req->queue, &ep->queue); - spin_unlock (&dum->lock); + spin_unlock(&dum->lock); _req->actual = _req->length; _req->status = 0; - _req->complete (_ep, _req); - spin_lock (&dum->lock); + _req->complete(_ep, _req); + spin_lock(&dum->lock); } else list_add_tail(&req->queue, &ep->queue); - spin_unlock_irqrestore (&dum->lock, flags); + spin_unlock_irqrestore(&dum->lock, flags); /* real hardware would likely enable transfers here, in case * it'd been left NAKing. @@ -676,7 +670,7 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req, return 0; } -static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) +static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req) { struct dummy_ep *ep; struct dummy *dum; @@ -686,31 +680,31 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) if (!_ep || !_req) return retval; - ep = usb_ep_to_dummy_ep (_ep); - dum = ep_to_dummy (ep); + ep = usb_ep_to_dummy_ep(_ep); + dum = ep_to_dummy(ep); if (!dum->driver) return -ESHUTDOWN; - local_irq_save (flags); - spin_lock (&dum->lock); - list_for_each_entry (req, &ep->queue, queue) { + local_irq_save(flags); + spin_lock(&dum->lock); + list_for_each_entry(req, &ep->queue, queue) { if (&req->req == _req) { - list_del_init (&req->queue); + list_del_init(&req->queue); _req->status = -ECONNRESET; retval = 0; break; } } - spin_unlock (&dum->lock); + spin_unlock(&dum->lock); if (retval == 0) { - dev_dbg (udc_dev(dum), + dev_dbg(udc_dev(dum), "dequeued req %p from %s, len %d buf %p\n", req, _ep->name, _req->length, _req->buf); - _req->complete (_ep, _req); + _req->complete(_ep, _req); } - local_irq_restore (flags); + local_irq_restore(flags); return retval; } @@ -722,14 +716,14 @@ dummy_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged) if (!_ep) return -EINVAL; - ep = usb_ep_to_dummy_ep (_ep); - dum = ep_to_dummy (ep); + ep = usb_ep_to_dummy_ep(_ep); + dum = ep_to_dummy(ep); if (!dum->driver) return -ESHUTDOWN; if (!value) ep->halted = ep->wedged = 0; else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) && - !list_empty (&ep->queue)) + !list_empty(&ep->queue)) return -EAGAIN; else { ep->halted = 1; @@ -770,15 +764,15 @@ static const struct usb_ep_ops dummy_ep_ops = { /*-------------------------------------------------------------------------*/ /* there are both host and device side versions of this call ... */ -static int dummy_g_get_frame (struct usb_gadget *_gadget) +static int dummy_g_get_frame(struct usb_gadget *_gadget) { struct timeval tv; - do_gettimeofday (&tv); + do_gettimeofday(&tv); return tv.tv_usec / 1000; } -static int dummy_wakeup (struct usb_gadget *_gadget) +static int dummy_wakeup(struct usb_gadget *_gadget) { struct dummy_hcd *dum_hcd; @@ -801,11 +795,11 @@ static int dummy_wakeup (struct usb_gadget *_gadget) return 0; } -static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value) +static int dummy_set_selfpowered(struct usb_gadget *_gadget, int value) { struct dummy *dum; - dum = (gadget_to_dummy_hcd(_gadget))->dum; + dum = gadget_to_dummy_hcd(_gadget)->dum; if (value) dum->devstatus |= (1 << USB_DEVICE_SELF_POWERED); else @@ -821,7 +815,7 @@ static void dummy_udc_update_ep0(struct dummy *dum) dum->ep[0].ep.maxpacket = 64; } -static int dummy_pullup (struct usb_gadget *_gadget, int value) +static int dummy_pullup(struct usb_gadget *_gadget, int value) { struct dummy_hcd *dum_hcd; struct dummy *dum; @@ -846,10 +840,10 @@ static int dummy_pullup (struct usb_gadget *_gadget, int value) } dum_hcd = gadget_to_dummy_hcd(_gadget); - spin_lock_irqsave (&dum->lock, flags); + spin_lock_irqsave(&dum->lock, flags); dum->pullup = (value != 0); set_link_state(dum_hcd); - spin_unlock_irqrestore (&dum->lock, flags); + spin_unlock_irqrestore(&dum->lock, flags); usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd)); return 0; @@ -872,16 +866,16 @@ static const struct usb_gadget_ops dummy_ops = { /*-------------------------------------------------------------------------*/ /* "function" sysfs attribute */ -static ssize_t -show_function (struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_function(struct device *dev, struct device_attribute *attr, + char *buf) { - struct dummy *dum = gadget_dev_to_dummy (dev); + struct dummy *dum = gadget_dev_to_dummy(dev); if (!dum->driver || !dum->driver->function) return 0; - return scnprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function); + return scnprintf(buf, PAGE_SIZE, "%s\n", dum->driver->function); } -static DEVICE_ATTR (function, S_IRUGO, show_function, NULL); +static DEVICE_ATTR(function, S_IRUGO, show_function, NULL); /*-------------------------------------------------------------------------*/ @@ -916,7 +910,7 @@ static int dummy_udc_start(struct usb_gadget *g, dum->devstatus = 0; dum->driver = driver; - dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n", + dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n", driver->driver.name); return 0; } @@ -927,7 +921,7 @@ static int dummy_udc_stop(struct usb_gadget *g, struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(g); struct dummy *dum = dum_hcd->dum; - dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n", + dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n", driver->driver.name); dum->driver = NULL; @@ -940,8 +934,7 @@ static int dummy_udc_stop(struct usb_gadget *g, /* The gadget structure is stored inside the hcd structure and will be * released along with it. */ -static void -dummy_gadget_release (struct device *dev) +static void dummy_gadget_release(struct device *dev) { return; } @@ -978,7 +971,7 @@ static void init_dummy_udc_hw(struct dummy *dum) #endif } -static int dummy_udc_probe (struct platform_device *pdev) +static int dummy_udc_probe(struct platform_device *pdev) { struct dummy *dum = &the_controller; int rc; @@ -990,7 +983,7 @@ static int dummy_udc_probe (struct platform_device *pdev) dev_set_name(&dum->gadget.dev, "gadget"); dum->gadget.dev.parent = &pdev->dev; dum->gadget.dev.release = dummy_gadget_release; - rc = device_register (&dum->gadget.dev); + rc = device_register(&dum->gadget.dev); if (rc < 0) { put_device(&dum->gadget.dev); return rc; @@ -1002,7 +995,7 @@ static int dummy_udc_probe (struct platform_device *pdev) if (rc < 0) goto err_udc; - rc = device_create_file (&dum->gadget.dev, &dev_attr_function); + rc = device_create_file(&dum->gadget.dev, &dev_attr_function); if (rc < 0) goto err_dev; platform_set_drvdata(pdev, dum); @@ -1015,14 +1008,14 @@ err_udc: return rc; } -static int dummy_udc_remove (struct platform_device *pdev) +static int dummy_udc_remove(struct platform_device *pdev) { - struct dummy *dum = platform_get_drvdata (pdev); + struct dummy *dum = platform_get_drvdata(pdev); usb_del_gadget_udc(&dum->gadget); - platform_set_drvdata (pdev, NULL); - device_remove_file (&dum->gadget.dev, &dev_attr_function); - device_unregister (&dum->gadget.dev); + platform_set_drvdata(pdev, NULL); + device_remove_file(&dum->gadget.dev, &dev_attr_function); + device_unregister(&dum->gadget.dev); return 0; } @@ -1167,7 +1160,7 @@ static int dummy_validate_stream(struct dummy_hcd *dum_hcd, struct urb *urb) return 0; } -static int dummy_urb_enqueue ( +static int dummy_urb_enqueue( struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags @@ -1177,7 +1170,7 @@ static int dummy_urb_enqueue ( unsigned long flags; int rc; - urbp = kmalloc (sizeof *urbp, mem_flags); + urbp = kmalloc(sizeof *urbp, mem_flags); if (!urbp) return -ENOMEM; urbp->urb = urb; @@ -1206,7 +1199,7 @@ static int dummy_urb_enqueue ( list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list); urb->hcpriv = urbp; - if (usb_pipetype (urb->pipe) == PIPE_CONTROL) + if (usb_pipetype(urb->pipe) == PIPE_CONTROL) urb->error_count = 1; /* mark as a new urb */ /* kick the scheduler, it'll do the rest */ @@ -1313,7 +1306,7 @@ static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb, top: /* if there's no request queued, the device is NAKing; return */ - list_for_each_entry (req, &ep->queue, queue) { + list_for_each_entry(req, &ep->queue, queue) { unsigned host_len, dev_len, len; int is_short, to_host; int rescan = 0; @@ -1332,18 +1325,18 @@ top: */ host_len = urb->transfer_buffer_length - urb->actual_length; dev_len = req->req.length - req->req.actual; - len = min (host_len, dev_len); + len = min(host_len, dev_len); /* FIXME update emulated data toggle too */ - to_host = usb_pipein (urb->pipe); - if (unlikely (len == 0)) + to_host = usb_pipein(urb->pipe); + if (unlikely(len == 0)) is_short = 1; else { /* not enough bandwidth left? */ if (limit < ep->ep.maxpacket && limit < len) break; - len = min (len, (unsigned) limit); + len = min_t(unsigned, len, limit); if (len == 0) break; @@ -1404,11 +1397,11 @@ top: /* device side completion --> continuable */ if (req->req.status != -EINPROGRESS) { - list_del_init (&req->queue); + list_del_init(&req->queue); - spin_unlock (&dum->lock); - req->req.complete (&ep->ep, &req->req); - spin_lock (&dum->lock); + spin_unlock(&dum->lock); + req->req.complete(&ep->ep, &req->req); + spin_lock(&dum->lock); /* requests might have been unlinked... */ rescan = 1; @@ -1425,7 +1418,7 @@ top: return limit; } -static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep) +static int periodic_bytes(struct dummy *dum, struct dummy_ep *ep) { int limit = ep->ep.maxpacket; @@ -1461,7 +1454,7 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep) USB_PORT_STAT_SUSPEND)) \ == (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) -static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address) +static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address) { int i; @@ -1469,9 +1462,9 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address) dum->ss_hcd : dum->hs_hcd))) return NULL; if ((address & ~USB_DIR_IN) == 0) - return &dum->ep [0]; + return &dum->ep[0]; for (i = 1; i < DUMMY_ENDPOINTS; i++) { - struct dummy_ep *ep = &dum->ep [i]; + struct dummy_ep *ep = &dum->ep[i]; if (!ep->desc) continue; @@ -1701,19 +1694,19 @@ static void dummy_timer(unsigned long _dum_hcd) /* FIXME if HZ != 1000 this will probably misbehave ... */ /* look at each urb queued by the host side driver */ - spin_lock_irqsave (&dum->lock, flags); + spin_lock_irqsave(&dum->lock, flags); if (!dum_hcd->udev) { dev_err(dummy_dev(dum_hcd), "timer fired with no URBs pending?\n"); - spin_unlock_irqrestore (&dum->lock, flags); + spin_unlock_irqrestore(&dum->lock, flags); return; } for (i = 0; i < DUMMY_ENDPOINTS; i++) { - if (!ep_name [i]) + if (!ep_name[i]) break; - dum->ep [i].already_seen = 0; + dum->ep[i].already_seen = 0; } restart: @@ -1730,7 +1723,7 @@ restart: goto return_urb; else if (dum_hcd->rh_state != DUMMY_RH_RUNNING) continue; - type = usb_pipetype (urb->pipe); + type = usb_pipetype(urb->pipe); /* used up this frame's non-periodic bandwidth? * FIXME there's infinite bandwidth for control and @@ -1741,7 +1734,7 @@ restart: /* find the gadget's ep for this request (if configured) */ address = usb_pipeendpoint (urb->pipe); - if (usb_pipein (urb->pipe)) + if (usb_pipein(urb->pipe)) address |= USB_DIR_IN; ep = find_endpoint(dum, address); if (!ep) { @@ -1756,7 +1749,7 @@ restart: if (ep->already_seen) continue; ep->already_seen = 1; - if (ep == &dum->ep [0] && urb->error_count) { + if (ep == &dum->ep[0] && urb->error_count) { ep->setup_stage = 1; /* a new urb */ urb->error_count = 0; } @@ -1770,21 +1763,21 @@ restart: /* FIXME make sure both ends agree on maxpacket */ /* handle control requests */ - if (ep == &dum->ep [0] && ep->setup_stage) { + if (ep == &dum->ep[0] && ep->setup_stage) { struct usb_ctrlrequest setup; int value = 1; - setup = *(struct usb_ctrlrequest*) urb->setup_packet; + setup = *(struct usb_ctrlrequest *) urb->setup_packet; /* paranoia, in case of stale queued data */ - list_for_each_entry (req, &ep->queue, queue) { - list_del_init (&req->queue); + list_for_each_entry(req, &ep->queue, queue) { + list_del_init(&req->queue); req->req.status = -EOVERFLOW; - dev_dbg (udc_dev(dum), "stale req = %p\n", + dev_dbg(udc_dev(dum), "stale req = %p\n", req); - spin_unlock (&dum->lock); - req->req.complete (&ep->ep, &req->req); - spin_lock (&dum->lock); + spin_unlock(&dum->lock); + req->req.complete(&ep->ep, &req->req); + spin_lock(&dum->lock); ep->already_seen = 0; goto restart; } @@ -1804,10 +1797,10 @@ restart: * until setup() returns; no reentrancy issues etc. */ if (value > 0) { - spin_unlock (&dum->lock); - value = dum->driver->setup (&dum->gadget, + spin_unlock(&dum->lock); + value = dum->driver->setup(&dum->gadget, &setup); - spin_lock (&dum->lock); + spin_lock(&dum->lock); if (value >= 0) { /* no delays (max 64KB data stage) */ @@ -1819,7 +1812,7 @@ restart: if (value < 0) { if (value != -EOPNOTSUPP) - dev_dbg (udc_dev(dum), + dev_dbg(udc_dev(dum), "setup --> %d\n", value); status = -EPIPE; @@ -1831,14 +1824,14 @@ restart: /* non-control requests */ limit = total; - switch (usb_pipetype (urb->pipe)) { + switch (usb_pipetype(urb->pipe)) { case PIPE_ISOCHRONOUS: /* FIXME is it urb->interval since the last xfer? * use urb->iso_frame_desc[i]. * complete whether or not ep has requests queued. * report random errors, to debug drivers. */ - limit = max (limit, periodic_bytes (dum, ep)); + limit = max(limit, periodic_bytes(dum, ep)); status = -ENOSYS; break; @@ -1846,12 +1839,11 @@ restart: /* FIXME is it urb->interval since the last xfer? * this almost certainly polls too fast. */ - limit = max (limit, periodic_bytes (dum, ep)); + limit = max(limit, periodic_bytes(dum, ep)); /* FALLTHROUGH */ - // case PIPE_BULK: case PIPE_CONTROL: default: - treat_control_like_bulk: +treat_control_like_bulk: ep->last_io = jiffies; total = transfer(dum_hcd, urb, ep, limit, &status); break; @@ -1862,15 +1854,15 @@ restart: continue; return_urb: - list_del (&urbp->urbp_list); - kfree (urbp); + list_del(&urbp->urbp_list); + kfree(urbp); if (ep) ep->already_seen = ep->setup_stage = 0; usb_hcd_unlink_urb_from_ep(dummy_hcd_to_hcd(dum_hcd), urb); - spin_unlock (&dum->lock); + spin_unlock(&dum->lock); usb_hcd_giveback_urb(dummy_hcd_to_hcd(dum_hcd), urb, status); - spin_lock (&dum->lock); + spin_lock(&dum->lock); goto restart; } @@ -1883,7 +1875,7 @@ return_urb: mod_timer(&dum_hcd->timer, jiffies + msecs_to_jiffies(1)); } - spin_unlock_irqrestore (&dum->lock, flags); + spin_unlock_irqrestore(&dum->lock, flags); } /*-------------------------------------------------------------------------*/ @@ -1895,7 +1887,7 @@ return_urb: | USB_PORT_STAT_C_OVERCURRENT \ | USB_PORT_STAT_C_RESET) << 16) -static int dummy_hub_status (struct usb_hcd *hcd, char *buf) +static int dummy_hub_status(struct usb_hcd *hcd, char *buf) { struct dummy_hcd *dum_hcd; unsigned long flags; @@ -1919,7 +1911,7 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf) dum_hcd->port_status); retval = 1; if (dum_hcd->rh_state == DUMMY_RH_SUSPENDED) - usb_hcd_resume_root_hub (hcd); + usb_hcd_resume_root_hub(hcd); } done: spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); @@ -1938,10 +1930,9 @@ ss_hub_descriptor(struct usb_hub_descriptor *desc) desc->u.ss.DeviceRemovable = 0xffff; } -static inline void -hub_descriptor (struct usb_hub_descriptor *desc) +static inline void hub_descriptor(struct usb_hub_descriptor *desc) { - memset (desc, 0, sizeof *desc); + memset(desc, 0, sizeof *desc); desc->bDescriptorType = 0x29; desc->bDescLength = 9; desc->wHubCharacteristics = cpu_to_le16(0x0001); @@ -1950,7 +1941,7 @@ hub_descriptor (struct usb_hub_descriptor *desc) desc->u.hs.DeviceRemovable[1] = 0xff; } -static int dummy_hub_control ( +static int dummy_hub_control( struct usb_hcd *hcd, u16 typeReq, u16 wValue, @@ -2018,7 +2009,7 @@ static int dummy_hub_control ( hub_descriptor((struct usb_hub_descriptor *) buf); break; case GetHubStatus: - *(__le32 *) buf = cpu_to_le32 (0); + *(__le32 *) buf = cpu_to_le32(0); break; case GetPortStatus: if (wIndex != 1) @@ -2060,8 +2051,8 @@ static int dummy_hub_control ( } } set_link_state(dum_hcd); - ((__le16 *) buf)[0] = cpu_to_le16 (dum_hcd->port_status); - ((__le16 *) buf)[1] = cpu_to_le16 (dum_hcd->port_status >> 16); + ((__le16 *) buf)[0] = cpu_to_le16(dum_hcd->port_status); + ((__le16 *) buf)[1] = cpu_to_le16(dum_hcd->port_status >> 16); break; case SetHubFeature: retval = -EPIPE; @@ -2195,15 +2186,15 @@ error: spin_unlock_irqrestore(&dum_hcd->dum->lock, flags); if ((dum_hcd->port_status & PORT_C_MASK) != 0) - usb_hcd_poll_rh_status (hcd); + usb_hcd_poll_rh_status(hcd); return retval; } -static int dummy_bus_suspend (struct usb_hcd *hcd) +static int dummy_bus_suspend(struct usb_hcd *hcd) { struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd); - dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__); + dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__); spin_lock_irq(&dum_hcd->dum->lock); dum_hcd->rh_state = DUMMY_RH_SUSPENDED; @@ -2213,12 +2204,12 @@ static int dummy_bus_suspend (struct usb_hcd *hcd) return 0; } -static int dummy_bus_resume (struct usb_hcd *hcd) +static int dummy_bus_resume(struct usb_hcd *hcd) { struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd); int rc = 0; - dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__); + dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__); spin_lock_irq(&dum_hcd->dum->lock); if (!HCD_HW_ACCESSIBLE(hcd)) { @@ -2236,55 +2227,54 @@ static int dummy_bus_resume (struct usb_hcd *hcd) /*-------------------------------------------------------------------------*/ -static inline ssize_t -show_urb (char *buf, size_t size, struct urb *urb) +static inline ssize_t show_urb(char *buf, size_t size, struct urb *urb) { - int ep = usb_pipeendpoint (urb->pipe); + int ep = usb_pipeendpoint(urb->pipe); - return snprintf (buf, size, + return snprintf(buf, size, "urb/%p %s ep%d%s%s len %d/%d\n", urb, ({ char *s; - switch (urb->dev->speed) { - case USB_SPEED_LOW: + switch (urb->dev->speed) { + case USB_SPEED_LOW: s = "ls"; break; - case USB_SPEED_FULL: + case USB_SPEED_FULL: s = "fs"; break; - case USB_SPEED_HIGH: + case USB_SPEED_HIGH: s = "hs"; break; - case USB_SPEED_SUPER: + case USB_SPEED_SUPER: s = "ss"; break; - default: + default: s = "?"; break; }; s; }), - ep, ep ? (usb_pipein (urb->pipe) ? "in" : "out") : "", + ep, ep ? (usb_pipein(urb->pipe) ? "in" : "out") : "", ({ char *s; \ - switch (usb_pipetype (urb->pipe)) { \ - case PIPE_CONTROL: \ + switch (usb_pipetype(urb->pipe)) { \ + case PIPE_CONTROL: \ s = ""; \ break; \ - case PIPE_BULK: \ + case PIPE_BULK: \ s = "-bulk"; \ break; \ - case PIPE_INTERRUPT: \ + case PIPE_INTERRUPT: \ s = "-int"; \ break; \ - default: \ + default: \ s = "-iso"; \ break; \ - }; s;}), + }; s; }), urb->actual_length, urb->transfer_buffer_length); } -static ssize_t -show_urbs (struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_urbs(struct device *dev, struct device_attribute *attr, + char *buf) { - struct usb_hcd *hcd = dev_get_drvdata (dev); + struct usb_hcd *hcd = dev_get_drvdata(dev); struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd); struct urbp *urbp; size_t size = 0; @@ -2294,7 +2284,7 @@ show_urbs (struct device *dev, struct device_attribute *attr, char *buf) list_for_each_entry(urbp, &dum_hcd->urbp_list, urbp_list) { size_t temp; - temp = show_urb (buf, PAGE_SIZE - size, urbp->urb); + temp = show_urb(buf, PAGE_SIZE - size, urbp->urb); buf += temp; size += temp; } @@ -2302,7 +2292,7 @@ show_urbs (struct device *dev, struct device_attribute *attr, char *buf) return size; } -static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL); +static DEVICE_ATTR(urbs, S_IRUGO, show_urbs, NULL); static int dummy_start_ss(struct dummy_hcd *dum_hcd) { @@ -2356,11 +2346,11 @@ static int dummy_start(struct usb_hcd *hcd) return device_create_file(dummy_dev(dum_hcd), &dev_attr_urbs); } -static void dummy_stop (struct usb_hcd *hcd) +static void dummy_stop(struct usb_hcd *hcd) { struct dummy *dum; - dum = (hcd_to_dummy_hcd(hcd))->dum; + dum = hcd_to_dummy_hcd(hcd)->dum; device_remove_file(dummy_dev(hcd_to_dummy_hcd(hcd)), &dev_attr_urbs); usb_gadget_unregister_driver(dum->driver); dev_info(dummy_dev(hcd_to_dummy_hcd(hcd)), "stopped\n"); @@ -2368,9 +2358,9 @@ static void dummy_stop (struct usb_hcd *hcd) /*-------------------------------------------------------------------------*/ -static int dummy_h_get_frame (struct usb_hcd *hcd) +static int dummy_h_get_frame(struct usb_hcd *hcd) { - return dummy_g_get_frame (NULL); + return dummy_g_get_frame(NULL); } static int dummy_setup(struct usb_hcd *hcd) @@ -2485,13 +2475,13 @@ static struct hc_driver dummy_hcd = { .start = dummy_start, .stop = dummy_stop, - .urb_enqueue = dummy_urb_enqueue, - .urb_dequeue = dummy_urb_dequeue, + .urb_enqueue = dummy_urb_enqueue, + .urb_dequeue = dummy_urb_dequeue, - .get_frame_number = dummy_h_get_frame, + .get_frame_number = dummy_h_get_frame, - .hub_status_data = dummy_hub_status, - .hub_control = dummy_hub_control, + .hub_status_data = dummy_hub_status, + .hub_control = dummy_hub_control, .bus_suspend = dummy_bus_suspend, .bus_resume = dummy_bus_resume, @@ -2546,7 +2536,7 @@ static int dummy_hcd_remove(struct platform_device *pdev) { struct dummy *dum; - dum = (hcd_to_dummy_hcd(platform_get_drvdata(pdev)))->dum; + dum = hcd_to_dummy_hcd(platform_get_drvdata(pdev))->dum; if (dum->ss_hcd) { usb_remove_hcd(dummy_hcd_to_hcd(dum->ss_hcd)); @@ -2562,15 +2552,15 @@ static int dummy_hcd_remove(struct platform_device *pdev) return 0; } -static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state) +static int dummy_hcd_suspend(struct platform_device *pdev, pm_message_t state) { struct usb_hcd *hcd; struct dummy_hcd *dum_hcd; int rc = 0; - dev_dbg (&pdev->dev, "%s\n", __func__); + dev_dbg(&pdev->dev, "%s\n", __func__); - hcd = platform_get_drvdata (pdev); + hcd = platform_get_drvdata(pdev); dum_hcd = hcd_to_dummy_hcd(hcd); if (dum_hcd->rh_state == DUMMY_RH_RUNNING) { dev_warn(&pdev->dev, "Root hub isn't suspended!\n"); @@ -2580,15 +2570,15 @@ static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state) return rc; } -static int dummy_hcd_resume (struct platform_device *pdev) +static int dummy_hcd_resume(struct platform_device *pdev) { struct usb_hcd *hcd; - dev_dbg (&pdev->dev, "%s\n", __func__); + dev_dbg(&pdev->dev, "%s\n", __func__); - hcd = platform_get_drvdata (pdev); + hcd = platform_get_drvdata(pdev); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - usb_hcd_poll_rh_status (hcd); + usb_hcd_poll_rh_status(hcd); return 0; } @@ -2608,11 +2598,11 @@ static struct platform_driver dummy_hcd_driver = { static struct platform_device *the_udc_pdev; static struct platform_device *the_hcd_pdev; -static int __init init (void) +static int __init init(void) { int retval = -ENOMEM; - if (usb_disabled ()) + if (usb_disabled()) return -ENODEV; if (!mod_data.is_high_speed && mod_data.is_super_speed) @@ -2671,13 +2661,13 @@ err_alloc_udc: platform_device_put(the_hcd_pdev); return retval; } -module_init (init); +module_init(init); -static void __exit cleanup (void) +static void __exit cleanup(void) { platform_device_unregister(the_udc_pdev); platform_device_unregister(the_hcd_pdev); platform_driver_unregister(&dummy_udc_driver); platform_driver_unregister(&dummy_hcd_driver); } -module_exit (cleanup); +module_exit(cleanup); From 54b8360ffd4c8b2c128ca25233b8c6876fb92d30 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Fri, 13 Jan 2012 15:05:16 +0100 Subject: [PATCH 026/269] usb: gadget: update Michal Nazarewicz's email address The m.nazarewicz@samsung.com email address is no longer valid, so this commit replaces it with mina86@mina86.com which is employer-agnostic and thus should be valid for foreseeable feature. Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_acm.c | 2 +- drivers/usb/gadget/f_fs.c | 2 +- drivers/usb/gadget/f_mass_storage.c | 2 +- drivers/usb/gadget/f_rndis.c | 2 +- drivers/usb/gadget/g_ffs.c | 2 +- drivers/usb/gadget/mass_storage.c | 2 +- drivers/usb/gadget/multi.c | 2 +- drivers/usb/gadget/storage_common.c | 2 +- tools/usb/ffs-test.c | 2 +- tools/usb/testusb.c | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index 3f8849339ade..e48212195466 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -5,7 +5,7 @@ * Copyright (C) 2008 by David Brownell * Copyright (C) 2008 by Nokia Corporation * Copyright (C) 2009 by Samsung Electronics - * Author: Michal Nazarewicz (m.nazarewicz@samsung.com) + * Author: Michal Nazarewicz (mina86@mina86.com) * * This software is distributed under the terms of the GNU General * Public License ("GPL") as published by the Free Software Foundation, diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index f63dc6c150d2..7e2216f1bbe6 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -2,7 +2,7 @@ * f_fs.c -- user mode file system API for USB composite function controllers * * Copyright (C) 2010 Samsung Electronics - * Author: Michal Nazarewicz + * Author: Michal Nazarewicz * * Based on inode.c (GadgetFS) which was: * Copyright (C) 2003-2004 David Brownell diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 6353eca1e852..6cde0217a8da 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -3,7 +3,7 @@ * * Copyright (C) 2003-2008 Alan Stern * Copyright (C) 2009 Samsung Electronics - * Author: Michal Nazarewicz + * Author: Michal Nazarewicz * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 704d1d94f72a..7b1cf18df5e3 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -5,7 +5,7 @@ * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger * Copyright (C) 2008 Nokia Corporation * Copyright (C) 2009 Samsung Electronics - * Author: Michal Nazarewicz (m.nazarewicz@samsung.com) + * Author: Michal Nazarewicz (mina86@mina86.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 0519d77915ec..331cd6729d3c 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -2,7 +2,7 @@ * g_ffs.c -- user mode file system API for USB composite function controllers * * Copyright (C) 2010 Samsung Electronics - * Author: Michal Nazarewicz + * Author: Michal Nazarewicz * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index e24f72f82a47..1f376eba31f6 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -3,7 +3,7 @@ * * Copyright (C) 2003-2008 Alan Stern * Copyright (C) 2009 Samsung Electronics - * Author: Michal Nazarewicz + * Author: Michal Nazarewicz * All rights reserved. * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 7e7f515b8b19..c37fb33a3d1b 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -4,7 +4,7 @@ * Copyright (C) 2008 David Brownell * Copyright (C) 2008 Nokia Corporation * Copyright (C) 2009 Samsung Electronics - * Author: Michal Nazarewicz (m.nazarewicz@samsung.com) + * Author: Michal Nazarewicz (mina86@mina86.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index c7f291a331df..9d450feaaeab 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -3,7 +3,7 @@ * * Copyright (C) 2003-2008 Alan Stern * Copyeight (C) 2009 Samsung Electronics - * Author: Michal Nazarewicz (m.nazarewicz@samsung.com) + * Author: Michal Nazarewicz (mina86@mina86.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/tools/usb/ffs-test.c b/tools/usb/ffs-test.c index b9c798631699..53452c35d5e1 100644 --- a/tools/usb/ffs-test.c +++ b/tools/usb/ffs-test.c @@ -2,7 +2,7 @@ * ffs-test.c.c -- user mode filesystem api for usb composite function * * Copyright (C) 2010 Samsung Electronics - * Author: Michal Nazarewicz + * Author: Michal Nazarewicz * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c index f08e89463842..6e0f56701e44 100644 --- a/tools/usb/testusb.c +++ b/tools/usb/testusb.c @@ -3,7 +3,7 @@ /* * Copyright (c) 2002 by David Brownell * Copyright (c) 2010 by Samsung Electronics - * Author: Michal Nazarewicz + * Author: Michal Nazarewicz * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the From fcc0bb5ace11e6d0a27bdbdbf2e5e6d361a4e701 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 13 Jan 2012 21:54:46 +0100 Subject: [PATCH 027/269] usb: gadget: f_mass_storage: remove one FSG_NO_INTR_EP Remove one define of FSG_NO_INTR_EP and we still have that we can use. Signed-off-by: Sebastian Andrzej Siewior Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_mass_storage.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 6cde0217a8da..82462714582d 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -304,7 +304,6 @@ static const char fsg_string_interface[] = "Mass Storage"; -#define FSG_NO_INTR_EP 1 #define FSG_NO_DEVICE_STRINGS 1 #define FSG_NO_OTG 1 #define FSG_NO_INTR_EP 1 From f557978745bbea2e7305588d33aac60f4dd42447 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Thu, 12 Jan 2012 15:21:38 +0200 Subject: [PATCH 028/269] usb: musb: drop superfluous pm_runtime calls around musb_shutdown Since commit 4f9edd2d7e8d "usb: musb: Fix the crash issue during reboot" musb_shutdown() does pm_runtime_get_sync/pm_runtime_put by itself, so this no longer needs to be done by the caller. Also, musb_exit_debugfs() doesn't access the device, so just drop those runtime_pm calls. Signed-off-by: Grazvydas Ignotas Reviewed-by: Shubhrajyoti D Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 56cf0243979e..6a929859b55a 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2111,11 +2111,9 @@ static int __exit musb_remove(struct platform_device *pdev) * - Peripheral mode: peripheral is deactivated (or never-activated) * - OTG mode: both roles are deactivated (or never-activated) */ - pm_runtime_get_sync(musb->controller); musb_exit_debugfs(musb); musb_shutdown(pdev); - pm_runtime_put(musb->controller); musb_free(musb); iounmap(ctrl_base); device_init_wakeup(&pdev->dev, 0); From 1493138af1463112e42eebcdab5db61452821e97 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 5 Jan 2012 15:39:57 +0100 Subject: [PATCH 029/269] USB: code cleanup in suspend/resume path (3rd try) Do the cleanup to avoid behaviorial parameters Linus requested. Signed-off-by: Oliver Neukum Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 93 ++++++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 30 deletions(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index d40ff9568813..b7dfdecc7fda 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -958,13 +958,8 @@ void usb_rebind_intf(struct usb_interface *intf) int rc; /* Delayed unbind of an existing driver */ - if (intf->dev.driver) { - struct usb_driver *driver = - to_usb_driver(intf->dev.driver); - - dev_dbg(&intf->dev, "forced unbind\n"); - usb_driver_release_interface(driver, intf); - } + if (intf->dev.driver) + usb_forced_unbind_intf(intf); /* Try to rebind the interface */ if (!intf->dev.power.is_prepared) { @@ -977,15 +972,13 @@ void usb_rebind_intf(struct usb_interface *intf) #ifdef CONFIG_PM -#define DO_UNBIND 0 -#define DO_REBIND 1 - -/* Unbind drivers for @udev's interfaces that don't support suspend/resume, - * or rebind interfaces that have been unbound, according to @action. +/* Unbind drivers for @udev's interfaces that don't support suspend/resume + * There is no check for reset_resume here because it can be determined + * only during resume whether reset_resume is needed. * * The caller must hold @udev's device lock. */ -static void do_unbind_rebind(struct usb_device *udev, int action) +static void unbind_no_pm_drivers_interfaces(struct usb_device *udev) { struct usb_host_config *config; int i; @@ -996,23 +989,53 @@ static void do_unbind_rebind(struct usb_device *udev, int action) if (config) { for (i = 0; i < config->desc.bNumInterfaces; ++i) { intf = config->interface[i]; - switch (action) { - case DO_UNBIND: - if (intf->dev.driver) { - drv = to_usb_driver(intf->dev.driver); - if (!drv->suspend || !drv->resume) - usb_forced_unbind_intf(intf); - } - break; - case DO_REBIND: - if (intf->needs_binding) - usb_rebind_intf(intf); - break; + + if (intf->dev.driver) { + drv = to_usb_driver(intf->dev.driver); + if (!drv->suspend || !drv->resume) + usb_forced_unbind_intf(intf); } } } } +/* Unbind drivers for @udev's interfaces that failed to support reset-resume. + * These interfaces have the needs_binding flag set by usb_resume_interface(). + * + * The caller must hold @udev's device lock. + */ +static void unbind_no_reset_resume_drivers_interfaces(struct usb_device *udev) +{ + struct usb_host_config *config; + int i; + struct usb_interface *intf; + + config = udev->actconfig; + if (config) { + for (i = 0; i < config->desc.bNumInterfaces; ++i) { + intf = config->interface[i]; + if (intf->dev.driver && intf->needs_binding) + usb_forced_unbind_intf(intf); + } + } +} + +static void do_rebind_interfaces(struct usb_device *udev) +{ + struct usb_host_config *config; + int i; + struct usb_interface *intf; + + config = udev->actconfig; + if (config) { + for (i = 0; i < config->desc.bNumInterfaces; ++i) { + intf = config->interface[i]; + if (intf->needs_binding) + usb_rebind_intf(intf); + } + } +} + static int usb_suspend_device(struct usb_device *udev, pm_message_t msg) { struct usb_device_driver *udriver; @@ -1302,7 +1325,12 @@ int usb_suspend(struct device *dev, pm_message_t msg) { struct usb_device *udev = to_usb_device(dev); - do_unbind_rebind(udev, DO_UNBIND); + unbind_no_pm_drivers_interfaces(udev); + + /* From now on we are sure all drivers support suspend/resume + * but not necessarily reset_resume() + * so we may still need to unbind and rebind upon resume + */ choose_wakeup(udev, msg); return usb_suspend_both(udev, msg); } @@ -1313,15 +1341,20 @@ int usb_resume(struct device *dev, pm_message_t msg) struct usb_device *udev = to_usb_device(dev); int status; - /* For PM complete calls, all we do is rebind interfaces */ + /* For PM complete calls, all we do is rebind interfaces + * whose needs_binding flag is set + */ if (msg.event == PM_EVENT_ON) { if (udev->state != USB_STATE_NOTATTACHED) - do_unbind_rebind(udev, DO_REBIND); + do_rebind_interfaces(udev); status = 0; /* For all other calls, take the device back to full power and * tell the PM core in case it was autosuspended previously. - * Unbind the interfaces that will need rebinding later. + * Unbind the interfaces that will need rebinding later, + * because they fail to support reset_resume. + * (This can't be done in usb_resume_interface() + * above because it doesn't own the right set of locks.) */ } else { status = usb_resume_both(udev, msg); @@ -1329,7 +1362,7 @@ int usb_resume(struct device *dev, pm_message_t msg) pm_runtime_disable(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); - do_unbind_rebind(udev, DO_REBIND); + unbind_no_reset_resume_drivers_interfaces(udev); } } From 98d9a82e5f753a2483d7b4638802d60e94e5d2e4 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 11 Jan 2012 08:38:35 +0100 Subject: [PATCH 030/269] USB: cleanup the handling of the PM complete call This eliminates the last instance of a function's behavior controlled by a parameter as Linus hates such things. Signed-off-by: Oliver Neukum Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 39 +++++++++++++++++++++------------------ drivers/usb/core/usb.c | 2 +- drivers/usb/core/usb.h | 1 + 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index b7dfdecc7fda..d77daf3683da 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1335,35 +1335,38 @@ int usb_suspend(struct device *dev, pm_message_t msg) return usb_suspend_both(udev, msg); } +/* The device lock is held by the PM core */ +int usb_resume_complete(struct device *dev) +{ + struct usb_device *udev = to_usb_device(dev); + + /* For PM complete calls, all we do is rebind interfaces + * whose needs_binding flag is set + */ + if (udev->state != USB_STATE_NOTATTACHED) + do_rebind_interfaces(udev); + return 0; +} + /* The device lock is held by the PM core */ int usb_resume(struct device *dev, pm_message_t msg) { struct usb_device *udev = to_usb_device(dev); int status; - /* For PM complete calls, all we do is rebind interfaces - * whose needs_binding flag is set - */ - if (msg.event == PM_EVENT_ON) { - if (udev->state != USB_STATE_NOTATTACHED) - do_rebind_interfaces(udev); - status = 0; - - /* For all other calls, take the device back to full power and + /* For all calls, take the device back to full power and * tell the PM core in case it was autosuspended previously. * Unbind the interfaces that will need rebinding later, * because they fail to support reset_resume. * (This can't be done in usb_resume_interface() - * above because it doesn't own the right set of locks.) + * above because it doesn't own the right set of locks.) */ - } else { - status = usb_resume_both(udev, msg); - if (status == 0) { - pm_runtime_disable(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - unbind_no_reset_resume_drivers_interfaces(udev); - } + status = usb_resume_both(udev, msg); + if (status == 0) { + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + unbind_no_reset_resume_drivers_interfaces(udev); } /* Avoid PM error messages for devices disconnected while suspended diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 8ca9f994a280..c74ba7bbc748 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -274,7 +274,7 @@ static int usb_dev_prepare(struct device *dev) static void usb_dev_complete(struct device *dev) { /* Currently used only for rebinding interfaces */ - usb_resume(dev, PMSG_ON); /* FIXME: change to PMSG_COMPLETE */ + usb_resume_complete(dev); } static int usb_dev_suspend(struct device *dev) diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 45e8479c377d..71648dcbe438 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -56,6 +56,7 @@ extern void usb_major_cleanup(void); extern int usb_suspend(struct device *dev, pm_message_t msg); extern int usb_resume(struct device *dev, pm_message_t msg); +extern int usb_resume_complete(struct device *dev); extern int usb_port_suspend(struct usb_device *dev, pm_message_t msg); extern int usb_port_resume(struct usb_device *dev, pm_message_t msg); From 2851784f4d820bc697a8cc608509f9e3975c80e5 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 13 Jan 2012 19:04:17 +0100 Subject: [PATCH 031/269] usb/uhci: initialize sg_table properly Commit 689d6eac ("USB: UHCI: add native scatter-gather support(v1)) added sg support to uhci but forgot to set the sg_table so this feature remained unused. Cc: Ming Lei Signed-off-by: Sebastian Andrzej Siewior Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-hcd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 6b5eb1017e2c..e37dea87bb56 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -565,6 +565,9 @@ static int uhci_start(struct usb_hcd *hcd) struct dentry __maybe_unused *dentry; hcd->uses_new_polling = 1; + /* Accept arbitrarily long scatter-gather lists */ + if (!(hcd->driver->flags & HCD_LOCAL_MEM)) + hcd->self.sg_tablesize = ~0; spin_lock_init(&uhci->lock); setup_timer(&uhci->fsbr_timer, uhci_fsbr_timeout, From e73b2db6c9bc5bd9a3c080f286964e594351991a Mon Sep 17 00:00:00 2001 From: Huajun Li Date: Sat, 14 Jan 2012 10:15:21 +0800 Subject: [PATCH 032/269] usb: Disable dynamic id of USB storage subdrivers Storage subdrivers, like alauda, datafab and others, don't support dynamic id currently, and it needs lots of work but with very little gain to enable the feature, so disable them in the patch. Signed-off-by: Huajun Li Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/alauda.c | 1 + drivers/usb/storage/cypress_atacb.c | 1 + drivers/usb/storage/datafab.c | 1 + drivers/usb/storage/ene_ub6250.c | 1 + drivers/usb/storage/freecom.c | 1 + drivers/usb/storage/isd200.c | 1 + drivers/usb/storage/jumpshot.c | 1 + drivers/usb/storage/karma.c | 1 + drivers/usb/storage/onetouch.c | 1 + drivers/usb/storage/realtek_cr.c | 1 + drivers/usb/storage/sddr09.c | 1 + drivers/usb/storage/sddr55.c | 1 + drivers/usb/storage/shuttle_usbat.c | 1 + 13 files changed, 13 insertions(+) diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index 51af2fee2efd..bab8c8fe8290 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -1276,6 +1276,7 @@ static struct usb_driver alauda_driver = { .post_reset = usb_stor_post_reset, .id_table = alauda_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(alauda_driver); diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 387cbd47acc9..5fe451d16e68 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -272,6 +272,7 @@ static struct usb_driver cypress_driver = { .post_reset = usb_stor_post_reset, .id_table = cypress_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(cypress_driver); diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 15d41f2b3d6f..35e9c51e6696 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -751,6 +751,7 @@ static struct usb_driver datafab_driver = { .post_reset = usb_stor_post_reset, .id_table = datafab_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(datafab_driver); diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index a6ade4071a9a..30532d93eecc 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -2407,6 +2407,7 @@ static struct usb_driver ene_ub6250_driver = { .post_reset = usb_stor_post_reset, .id_table = ene_ub6250_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(ene_ub6250_driver); diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index fa1615748475..042cf9ef3153 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -553,6 +553,7 @@ static struct usb_driver freecom_driver = { .post_reset = usb_stor_post_reset, .id_table = freecom_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(freecom_driver); diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index bd5502700831..31fa24e7e68a 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -1566,6 +1566,7 @@ static struct usb_driver isd200_driver = { .post_reset = usb_stor_post_reset, .id_table = isd200_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(isd200_driver); diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index a19211b5c265..e3b97383186a 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -677,6 +677,7 @@ static struct usb_driver jumpshot_driver = { .post_reset = usb_stor_post_reset, .id_table = jumpshot_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(jumpshot_driver); diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c index e720f8ebdf9f..a8708eae9788 100644 --- a/drivers/usb/storage/karma.c +++ b/drivers/usb/storage/karma.c @@ -230,6 +230,7 @@ static struct usb_driver karma_driver = { .post_reset = usb_stor_post_reset, .id_table = karma_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(karma_driver); diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index d75155c38200..886567a3806d 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -312,6 +312,7 @@ static struct usb_driver onetouch_driver = { .post_reset = usb_stor_post_reset, .id_table = onetouch_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(onetouch_driver); diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index 1f62723ef1a8..ccf271d2f670 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -1100,6 +1100,7 @@ static struct usb_driver realtek_cr_driver = { .id_table = realtek_cr_ids, .soft_unbind = 1, .supports_autosuspend = 1, + .no_dynamic_id = 1, }; module_usb_driver(realtek_cr_driver); diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 425df7df2e56..3252a62b31bc 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -1787,6 +1787,7 @@ static struct usb_driver sddr09_driver = { .post_reset = usb_stor_post_reset, .id_table = sddr09_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(sddr09_driver); diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index e4ca5fcb7cc3..c144078065a7 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -1006,6 +1006,7 @@ static struct usb_driver sddr55_driver = { .post_reset = usb_stor_post_reset, .id_table = sddr55_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(sddr55_driver); diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index 1369d2590616..fa1ceebc465c 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -1863,6 +1863,7 @@ static struct usb_driver usbat_driver = { .post_reset = usb_stor_post_reset, .id_table = usbat_usb_ids, .soft_unbind = 1, + .no_dynamic_id = 1, }; module_usb_driver(usbat_driver); From fd7ff36d6a3f6413f838a2037b957b0e33ba9056 Mon Sep 17 00:00:00 2001 From: Huajun Li Date: Sat, 14 Jan 2012 10:16:40 +0800 Subject: [PATCH 033/269] usb: Re-enable usb-storage support dynamic id Enable usb-storage support dynamic id again by using a fixed id entry that describes a device using the Bulk-Only transport with the Transparent SCSI protocol. Signed-off-by: Huajun Li Reviewed-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/usb.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 3dd7da9fd504..58f56775ecde 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -125,6 +125,9 @@ static struct us_unusual_dev us_unusual_dev_list[] = { { } /* Terminating entry */ }; +static struct us_unusual_dev for_dynamic_ids = + USUAL_DEV(USB_SC_SCSI, USB_PR_BULK, 0); + #undef UNUSUAL_DEV #undef COMPLIANT_DEV #undef USUAL_DEV @@ -1027,8 +1030,10 @@ EXPORT_SYMBOL_GPL(usb_stor_disconnect); static int storage_probe(struct usb_interface *intf, const struct usb_device_id *id) { + struct us_unusual_dev *unusual_dev; struct us_data *us; int result; + int size; /* * If libusual is configured, let it decide whether a standard @@ -1047,8 +1052,19 @@ static int storage_probe(struct usb_interface *intf, * table, so we use the index of the id entry to find the * corresponding unusual_devs entry. */ - result = usb_stor_probe1(&us, intf, id, - (id - usb_storage_usb_ids) + us_unusual_dev_list); + + size = ARRAY_SIZE(us_unusual_dev_list); + if (id >= usb_storage_usb_ids && id < usb_storage_usb_ids + size) { + unusual_dev = (id - usb_storage_usb_ids) + us_unusual_dev_list; + } else { + unusual_dev = &for_dynamic_ids; + + US_DEBUGP("%s %s 0x%04x 0x%04x\n", "Use Bulk-Only transport", + "with the Transparent SCSI protocol for dynamic id:", + id->idVendor, id->idProduct); + } + + result = usb_stor_probe1(&us, intf, id, unusual_dev); if (result) return result; @@ -1074,7 +1090,6 @@ static struct usb_driver usb_storage_driver = { .id_table = usb_storage_usb_ids, .supports_autosuspend = 1, .soft_unbind = 1, - .no_dynamic_id = 1, }; static int __init usb_stor_init(void) From 0b238583ac8db66762bba021de1b7c60b6bc29ad Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 16 Jan 2012 00:36:47 +0100 Subject: [PATCH 034/269] USB: cp210x: fix debug output Remove superfluous newlines from debug statements. Remove unnecessary line breaks. Signed-off-by: Johan Hovold Cc: Preston Fick Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index fba1147ed916..92aadd889a6d 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -279,7 +279,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, if (result != size) { dbg("%s - Unable to send config request, " - "request=0x%x size=%d result=%d\n", + "request=0x%x size=%d result=%d", __func__, request, size, result); if (result > 0) result = -EPROTO; @@ -333,7 +333,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, if ((size > 2 && result != size) || result < 0) { dbg("%s - Unable to send request, " - "request=0x%x size=%d result=%d\n", + "request=0x%x size=%d result=%d", __func__, request, size, result); if (result > 0) result = -EPROTO; @@ -636,13 +636,13 @@ static void cp210x_set_termios(struct tty_struct *tty, default: dbg("cp210x driver does not " "support the number of bits requested," - " using 8 bit mode\n"); + " using 8 bit mode"); bits |= BITS_DATA_8; break; } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) dbg("Number of data bits requested " - "not supported by device\n"); + "not supported by device"); } if ((cflag & (PARENB|PARODD|CMSPAR)) != @@ -669,8 +669,7 @@ static void cp210x_set_termios(struct tty_struct *tty, } } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) - dbg("Parity mode not supported " - "by device\n"); + dbg("Parity mode not supported by device"); } if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) { @@ -685,7 +684,7 @@ static void cp210x_set_termios(struct tty_struct *tty, } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) dbg("Number of stop bits requested " - "not supported by device\n"); + "not supported by device"); } if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { From 19b85b3b87fd1388df1f4a35969823521d35d243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 16 Jan 2012 15:11:58 +0100 Subject: [PATCH 035/269] USB: cdc-wdm: no need to fill the in request URB every time it's submitted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Filling the same URB with the exact same data is pointless. It can be filled once and resubmitted. And not doing buffer allocation and URB filling at the same place only serves to hide size mismatch bugs Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 39 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 1c50baff7725..9734863a3a49 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -159,11 +159,9 @@ static void wdm_int_callback(struct urb *urb) int rv = 0; int status = urb->status; struct wdm_device *desc; - struct usb_ctrlrequest *req; struct usb_cdc_notification *dr; desc = urb->context; - req = desc->irq; dr = (struct usb_cdc_notification *)desc->sbuf; if (status) { @@ -210,24 +208,6 @@ static void wdm_int_callback(struct urb *urb) goto exit; } - req->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE); - req->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE; - req->wValue = 0; - req->wIndex = desc->inum; - req->wLength = cpu_to_le16(desc->wMaxCommand); - - usb_fill_control_urb( - desc->response, - interface_to_usbdev(desc->intf), - /* using common endpoint 0 */ - usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0), - (unsigned char *)req, - desc->inbuf, - desc->wMaxCommand, - wdm_in_callback, - desc - ); - desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; spin_lock(&desc->iuspin); clear_bit(WDM_READ, &desc->flags); set_bit(WDM_RESPONDING, &desc->flags); @@ -734,6 +714,25 @@ next_desc: ); desc->validity->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + desc->irq->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE); + desc->irq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE; + desc->irq->wValue = 0; + desc->irq->wIndex = desc->inum; + desc->irq->wLength = cpu_to_le16(desc->wMaxCommand); + + usb_fill_control_urb( + desc->response, + interface_to_usbdev(desc->intf), + /* using common endpoint 0 */ + usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0), + (unsigned char *)desc->irq, + desc->inbuf, + desc->wMaxCommand, + wdm_in_callback, + desc + ); + desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + usb_set_intfdata(intf, desc); rv = usb_register_dev(intf, &wdm_class); if (rv < 0) From cafbe85fb0d00d32988905c4978df433ca9b6512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 16 Jan 2012 15:11:59 +0100 Subject: [PATCH 036/269] USB: cdc-wdm: better allocate a buffer that is at least as big as we tell the USB core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As it turns out, there was a mismatch between the allocated inbuf size (desc->bMaxPacketSize0, typically something like 64) and the length we specified in the URB (desc->wMaxCommand, typically something like 2048) Signed-off-by: Bjørn Mork Cc: Oliver Neukum Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 9734863a3a49..846dfa603447 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -696,7 +696,7 @@ next_desc: goto err; desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf), - desc->bMaxPacketSize0, + desc->wMaxCommand, GFP_KERNEL, &desc->response->transfer_dma); if (!desc->inbuf) From 8457d99cab81e91724b43363f7fccd851d766187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 16 Jan 2012 15:12:00 +0100 Subject: [PATCH 037/269] USB: cdc-wdm: no need to use usb_alloc_coherent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As Documentation/usb/dma.txt states: Most drivers should *NOT* be using these primitives; they don't need to use this type of memory (dma-coherent), and memory returned from kmalloc() will work just fine. This driver handle only very low bandwith transfers. It is not an obvious candidate for usb_alloc_coherent(). Using these calls only serves to complicate the code for no gain, as has been shown by multiple bugs related to this allocation path. Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 39 +++++++++---------------------------- 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 846dfa603447..8909058b1bb1 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -256,14 +256,8 @@ static void free_urbs(struct wdm_device *desc) static void cleanup(struct wdm_device *desc) { - usb_free_coherent(interface_to_usbdev(desc->intf), - desc->wMaxPacketSize, - desc->sbuf, - desc->validity->transfer_dma); - usb_free_coherent(interface_to_usbdev(desc->intf), - desc->bMaxPacketSize0, - desc->inbuf, - desc->response->transfer_dma); + kfree(desc->sbuf); + kfree(desc->inbuf); kfree(desc->orq); kfree(desc->irq); kfree(desc->ubuf); @@ -688,19 +682,13 @@ next_desc: if (!desc->ubuf) goto err; - desc->sbuf = usb_alloc_coherent(interface_to_usbdev(intf), - desc->wMaxPacketSize, - GFP_KERNEL, - &desc->validity->transfer_dma); + desc->sbuf = kmalloc(desc->wMaxPacketSize, GFP_KERNEL); if (!desc->sbuf) goto err; - desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf), - desc->wMaxCommand, - GFP_KERNEL, - &desc->response->transfer_dma); + desc->inbuf = kmalloc(desc->wMaxCommand, GFP_KERNEL); if (!desc->inbuf) - goto err2; + goto err; usb_fill_int_urb( desc->validity, @@ -712,7 +700,6 @@ next_desc: desc, ep->bInterval ); - desc->validity->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; desc->irq->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE); desc->irq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE; @@ -731,30 +718,22 @@ next_desc: wdm_in_callback, desc ); - desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_set_intfdata(intf, desc); rv = usb_register_dev(intf, &wdm_class); if (rv < 0) - goto err3; + goto err2; else dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n", intf->minor - WDM_MINOR_BASE); out: return rv; -err3: - usb_set_intfdata(intf, NULL); - usb_free_coherent(interface_to_usbdev(desc->intf), - desc->bMaxPacketSize0, - desc->inbuf, - desc->response->transfer_dma); err2: - usb_free_coherent(interface_to_usbdev(desc->intf), - desc->wMaxPacketSize, - desc->sbuf, - desc->validity->transfer_dma); + usb_set_intfdata(intf, NULL); err: free_urbs(desc); + kfree(desc->inbuf); + kfree(desc->sbuf); kfree(desc->ubuf); kfree(desc->orq); kfree(desc->irq); From 8143a8963c374116f84aba15dcaeaf02370c8098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Mon, 16 Jan 2012 15:12:01 +0100 Subject: [PATCH 038/269] USB: cdc-wdm: kill the now unnecessary bMaxPacketSize0 field and udev variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't need bMaxPacketSize0, and keeping all these different size fields around will only cause us to use the wrong one. Seems the udev variable was only used for getting bMaxPacketSize0. We could have used it for the usb_fill_*_urb() calls, but as it wasn't before - why start now? Instead make the interface_to_usbdev() calls consistent. Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 8909058b1bb1..bb8208a13a53 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -80,7 +80,6 @@ struct wdm_device { u16 bufsize; u16 wMaxCommand; u16 wMaxPacketSize; - u16 bMaxPacketSize0; __le16 inum; int reslength; int length; @@ -597,7 +596,6 @@ static void wdm_rxwork(struct work_struct *work) static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) { int rv = -EINVAL; - struct usb_device *udev = interface_to_usbdev(intf); struct wdm_device *desc; struct usb_host_interface *iface; struct usb_endpoint_descriptor *ep; @@ -657,7 +655,6 @@ next_desc: goto err; desc->wMaxPacketSize = usb_endpoint_maxp(ep); - desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0; desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); if (!desc->orq) @@ -709,7 +706,7 @@ next_desc: usb_fill_control_urb( desc->response, - interface_to_usbdev(desc->intf), + interface_to_usbdev(intf), /* using common endpoint 0 */ usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0), (unsigned char *)desc->irq, From 7e3054a005537f28544ab2870c375458362f7473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 20 Jan 2012 01:49:57 +0100 Subject: [PATCH 039/269] USB: cdc-wdm: Avoid hanging on interface with no USB_CDC_DMM_TYPE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe does not strictly require the USB_CDC_DMM_TYPE descriptor, which is a good thing as it makes the driver usable on non-conforming interfaces. A user could e.g. bind to it to a CDC ECM interface by using the new_id and bind sysfs files. But this would fail with a 0 buffer length due to the missing descriptor. Fix by defining a reasonable fallback size: The minimum device receive buffer size required by the CDC WMC standard, revision 1.1 Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index bb8208a13a53..c0197af22fd8 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -57,6 +57,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); #define WDM_MAX 16 +/* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */ +#define WDM_DEFAULT_BUFSIZE 256 static DEFINE_MUTEX(wdm_mutex); @@ -602,7 +604,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) struct usb_cdc_dmm_desc *dmhd; u8 *buffer = intf->altsetting->extra; int buflen = intf->altsetting->extralen; - u16 maxcom = 0; + u16 maxcom = WDM_DEFAULT_BUFSIZE; if (!buffer) goto out; From 820c629a595ad8d8f2694641e494738b18d29e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 20 Jan 2012 04:17:25 +0100 Subject: [PATCH 040/269] USB: cdc-wdm: avoid printing odd-looking "cdc-wdm-176" names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit usb_register_dev() will change our .minor_base to 0 if CONFIG_USB_DYNAMIC_MINORS is set. And it usually is, of course. Use dev_name() to print the proper interface name instead Signed-off-by: Bjørn Mork Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index c0197af22fd8..c154d4f1d674 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -723,8 +723,7 @@ next_desc: if (rv < 0) goto err2; else - dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n", - intf->minor - WDM_MINOR_BASE); + dev_info(&intf->dev, "%s: USB WDM device\n", dev_name(intf->usb_dev)); out: return rv; err2: From 761bbcb74e4611414937ea480ba60bb970648755 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Tue, 24 Jan 2012 22:17:38 +0100 Subject: [PATCH 041/269] usb: ehci-fsl: set INCR8 mode for system bus interface on MPC512x Use INCR8 mode for system bus interface of the USB controller on MPC512x. This is a work-around for the AHB bus lock up problem observed on MPC512x when there is heavy simultaneous PATA write or network (FEC) activity. See also "12.4 The USB controller can issue transactions that lock up the AHB bus under certain conditions" in MPC5121e (M36P) Errata. Signed-off-by: Anatolij Gustschin Tested-by: Matthias Fuchs Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-fsl.c | 14 ++++++++++++++ drivers/usb/host/ehci-fsl.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index e90344a17631..42414cd73571 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -316,7 +316,9 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; struct fsl_usb2_platform_data *pdata; + struct device *dev; + dev = hcd->self.controller; pdata = hcd->self.controller->platform_data; ehci->big_endian_desc = pdata->big_endian_desc; ehci->big_endian_mmio = pdata->big_endian_mmio; @@ -346,6 +348,16 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) ehci_reset(ehci); + if (of_device_is_compatible(dev->parent->of_node, + "fsl,mpc5121-usb2-dr")) { + /* + * set SBUSCFG:AHBBRST so that control msgs don't + * fail when doing heavy PATA writes. + */ + ehci_writel(ehci, SBUSCFG_INCR8, + hcd->regs + FSL_SOC_USB_SBUSCFG); + } + retval = ehci_fsl_reinit(ehci); return retval; } @@ -469,6 +481,8 @@ static int ehci_fsl_mpc512x_drv_resume(struct device *dev) ehci_writel(ehci, ISIPHYCTRL_PXE | ISIPHYCTRL_PHYE, hcd->regs + FSL_SOC_USB_ISIPHYCTRL); + ehci_writel(ehci, SBUSCFG_INCR8, hcd->regs + FSL_SOC_USB_SBUSCFG); + /* restore EHCI registers */ ehci_writel(ehci, pdata->pm_command, &ehci->regs->command); ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable); diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index 491806221165..0855be8b5b47 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -19,6 +19,8 @@ #define _EHCI_FSL_H /* offsets for the non-ehci registers in the FSL SOC USB controller */ +#define FSL_SOC_USB_SBUSCFG 0x90 +#define SBUSCFG_INCR8 0x02 /* INCR8, specified */ #define FSL_SOC_USB_ULPIVP 0x170 #define FSL_SOC_USB_PORTSC1 0x184 #define PORT_PTS_MSK (3<<30) From f30cdbcb2e6a7b9cdebe2117a7b623a5b3832a75 Mon Sep 17 00:00:00 2001 From: Kelvin Cheung Date: Wed, 18 Jan 2012 14:41:16 +0800 Subject: [PATCH 042/269] USB: Add EHCI bus glue for Loongson1x SoCs (UPDATED) Use ehci_setup() in ehci_ls1x_reset(). The Loongson1x SoCs have a built-in EHCI controller. This patch adds the necessary glue code to make the generic EHCI driver usable for them. Signed-off-by: Kelvin Cheung Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Kconfig | 1 + drivers/usb/host/ehci-hcd.c | 5 ++ drivers/usb/host/ehci-ls1x.c | 159 +++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 drivers/usb/host/ehci-ls1x.c diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 75823a1abeb6..0b0afc81a542 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -76,6 +76,7 @@ config USB_ARCH_HAS_EHCI default y if MICROBLAZE default y if SPARC_LEON default y if ARCH_MMP + default y if MACH_LOONGSON1 default PCI # some non-PCI HCDs implement xHCI diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a007a9fe0f87..4918b0c59af9 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1376,6 +1376,11 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_mv_driver #endif +#ifdef CONFIG_MACH_LOONGSON1 +#include "ehci-ls1x.c" +#define PLATFORM_DRIVER ehci_ls1x_driver +#endif + #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ !defined(XILINX_OF_PLATFORM_DRIVER) diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c new file mode 100644 index 000000000000..a283e59709d6 --- /dev/null +++ b/drivers/usb/host/ehci-ls1x.c @@ -0,0 +1,159 @@ +/* + * Bus Glue for Loongson LS1X built-in EHCI controller. + * + * Copyright (c) 2012 Zhang, Keguang + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + + +#include + +static int ehci_ls1x_reset(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int ret; + + ehci->caps = hcd->regs; + + ret = ehci_setup(hcd); + if (ret) + return ret; + + ehci_port_power(ehci, 0); + + return 0; +} + +static const struct hc_driver ehci_ls1x_hc_driver = { + .description = hcd_name, + .product_desc = "LOONGSON1 EHCI", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + */ + .reset = ehci_ls1x_reset, + .start = ehci_run, + .stop = ehci_stop, + .shutdown = ehci_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, + .endpoint_reset = ehci_endpoint_reset, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, + .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, + + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, +}; + +static int ehci_hcd_ls1x_probe(struct platform_device *pdev) +{ + struct usb_hcd *hcd; + struct resource *res; + int irq; + int ret; + + pr_debug("initializing loongson1 ehci USB Controller\n"); + + if (usb_disabled()) + return -ENODEV; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, + "Found HC with no IRQ. Check %s setup!\n", + dev_name(&pdev->dev)); + return -ENODEV; + } + irq = res->start; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, + "Found HC with no register addr. Check %s setup!\n", + dev_name(&pdev->dev)); + return -ENODEV; + } + + hcd = usb_create_hcd(&ehci_ls1x_hc_driver, &pdev->dev, + dev_name(&pdev->dev)); + if (!hcd) + return -ENOMEM; + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + dev_dbg(&pdev->dev, "controller already in use\n"); + ret = -EBUSY; + goto err_put_hcd; + } + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (hcd->regs == NULL) { + dev_dbg(&pdev->dev, "error mapping memory\n"); + ret = -EFAULT; + goto err_release_region; + } + + ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); + if (ret) + goto err_iounmap; + + return ret; + +err_iounmap: + iounmap(hcd->regs); +err_release_region: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +err_put_hcd: + usb_put_hcd(hcd); + return ret; +} + +static int ehci_hcd_ls1x_remove(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + + usb_remove_hcd(hcd); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); + + return 0; +} + +static struct platform_driver ehci_ls1x_driver = { + .probe = ehci_hcd_ls1x_probe, + .remove = ehci_hcd_ls1x_remove, + .shutdown = usb_hcd_platform_shutdown, + .driver = { + .name = "ls1x-ehci", + .owner = THIS_MODULE, + }, +}; + +MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ls1x-ehci"); From fec67b45bf045582c3172101970090d640cd56d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 25 Jan 2012 13:03:29 +0100 Subject: [PATCH 043/269] usb: cdc-wdm: Add device-id for Huawei 3G/LTE modems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [v2: Editorial changes suggested by Sergei Shtylyov] These modems use the Qualcomm MSM Interface (QMI) protocol for management of their CDC ECM like wwan interface. This driver is perfect for exporting the protocol to userspace. The created character device will be indistinguishable from a common AT command based Device Management interface, so userspace applications must do some intelligent matching on the USB device. Cc: Sergei Shtylyov Signed-off-by: Bjørn Mork Acked-by: Oliver Neukum Acked-by: Marcel Holtmann Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index c154d4f1d674..23cf9d38eb54 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -31,6 +31,8 @@ #define DRIVER_AUTHOR "Oliver Neukum" #define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management" +#define HUAWEI_VENDOR_ID 0x12D1 + static const struct usb_device_id wdm_ids[] = { { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | @@ -38,6 +40,20 @@ static const struct usb_device_id wdm_ids[] = { .bInterfaceClass = USB_CLASS_COMM, .bInterfaceSubClass = USB_CDC_SUBCLASS_DMM }, + { + /* + * Huawei E392, E398 and possibly other Qualcomm based modems + * embed the Qualcomm QMI protocol inside CDC on CDC ECM like + * control interfaces. Userspace access to this is required + * to configure the accompanying data interface + */ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | + USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = HUAWEI_VENDOR_ID, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 9, /* NOTE: CDC ECM control interface! */ + }, { } }; From d11519adc214c243ec606f186316f2667b677694 Mon Sep 17 00:00:00 2001 From: Praveena Nadahally Date: Wed, 25 Jan 2012 11:02:03 +0100 Subject: [PATCH 044/269] usb: gadget: Add Interface Association Descriptor to ECM Add IAD to bind the two interfaces of ECM so that it works properly in composite gadget mode. Signed-off-by: Thirupathi Signed-off-by: Praveena Nadahally Signed-off-by: Linus Walleij Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_ecm.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index 11c07cb7d337..30b908f2a53d 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -97,6 +97,20 @@ static inline unsigned ecm_bitrate(struct usb_gadget *g) /* interface descriptor: */ +static struct usb_interface_assoc_descriptor +ecm_iad_descriptor = { + .bLength = sizeof ecm_iad_descriptor, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + + /* .bFirstInterface = DYNAMIC, */ + .bInterfaceCount = 2, /* control + data */ + .bFunctionClass = USB_CLASS_COMM, + .bFunctionSubClass = USB_CDC_SUBCLASS_ETHERNET, + .bFunctionProtocol = USB_CDC_PROTO_NONE, + /* .iFunction = DYNAMIC */ +}; + + static struct usb_interface_descriptor ecm_control_intf = { .bLength = sizeof ecm_control_intf, .bDescriptorType = USB_DT_INTERFACE, @@ -199,6 +213,7 @@ static struct usb_endpoint_descriptor fs_ecm_out_desc = { static struct usb_descriptor_header *ecm_fs_function[] = { /* CDC ECM control descriptors */ + (struct usb_descriptor_header *) &ecm_iad_descriptor, (struct usb_descriptor_header *) &ecm_control_intf, (struct usb_descriptor_header *) &ecm_header_desc, (struct usb_descriptor_header *) &ecm_union_desc, @@ -247,6 +262,7 @@ static struct usb_endpoint_descriptor hs_ecm_out_desc = { static struct usb_descriptor_header *ecm_hs_function[] = { /* CDC ECM control descriptors */ + (struct usb_descriptor_header *) &ecm_iad_descriptor, (struct usb_descriptor_header *) &ecm_control_intf, (struct usb_descriptor_header *) &ecm_header_desc, (struct usb_descriptor_header *) &ecm_union_desc, @@ -339,6 +355,7 @@ static struct usb_string ecm_string_defs[] = { [0].s = "CDC Ethernet Control Model (ECM)", [1].s = NULL /* DYNAMIC */, [2].s = "CDC Ethernet Data", + [3].s = "CDC ECM", { } /* end of list */ }; @@ -674,6 +691,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) if (status < 0) goto fail; ecm->ctrl_id = status; + ecm_iad_descriptor.bFirstInterface = status; ecm_control_intf.bInterfaceNumber = status; ecm_union_desc.bMasterInterface0 = status; @@ -864,6 +882,13 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) return status; ecm_string_defs[1].id = status; ecm_desc.iMACAddress = status; + + /* IAD label */ + status = usb_string_id(c->cdev); + if (status < 0) + return status; + ecm_string_defs[3].id = status; + ecm_iad_descriptor.iFunction = status; } /* allocate and initialize one new instance */ From e9e8c85e69310141d78daaecd6a56138700ac317 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 26 Jan 2012 12:40:23 +0200 Subject: [PATCH 045/269] usb: musb: make modules behave better There's really no point in doing all that initcall trickery when we can safely let udev handle module probing for us. Remove all of that trickery, by moving everybody to module_init() and making proper use of platform_device_register() rather than platform_device_probe(). Tested-by: Rajashekhara, Sudhakar Tested-by: Tasslehoff Kjappfot Signed-off-by: Felipe Balbi --- drivers/usb/musb/am35x.c | 11 ++++---- drivers/usb/musb/blackfin.c | 9 +++--- drivers/usb/musb/da8xx.c | 11 ++++---- drivers/usb/musb/davinci.c | 11 ++++---- drivers/usb/musb/musb_core.c | 49 ++++++++++++++++----------------- drivers/usb/musb/musb_debugfs.c | 2 +- drivers/usb/musb/musb_gadget.c | 6 ++-- drivers/usb/musb/omap2430.c | 11 ++++---- drivers/usb/musb/tusb6010.c | 11 ++++---- drivers/usb/musb/ux500.c | 11 ++++---- 10 files changed, 68 insertions(+), 64 deletions(-) diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index e233d2b7d335..5285bda1dc4e 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -456,7 +456,7 @@ static const struct musb_platform_ops am35x_ops = { static u64 am35x_dmamask = DMA_BIT_MASK(32); -static int __init am35x_probe(struct platform_device *pdev) +static int __devinit am35x_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; @@ -561,7 +561,7 @@ err0: return ret; } -static int __exit am35x_remove(struct platform_device *pdev) +static int __devexit am35x_remove(struct platform_device *pdev) { struct am35x_glue *glue = platform_get_drvdata(pdev); @@ -630,7 +630,8 @@ static struct dev_pm_ops am35x_pm_ops = { #endif static struct platform_driver am35x_driver = { - .remove = __exit_p(am35x_remove), + .probe = am35x_probe, + .remove = __devexit_p(am35x_remove), .driver = { .name = "musb-am35x", .pm = DEV_PM_OPS, @@ -643,9 +644,9 @@ MODULE_LICENSE("GPL v2"); static int __init am35x_init(void) { - return platform_driver_probe(&am35x_driver, am35x_probe); + return platform_driver_register(&am35x_driver); } -subsys_initcall(am35x_init); +module_init(am35x_init); static void __exit am35x_exit(void) { diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index 5e7cfba5b079..261af3487b5e 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -463,7 +463,7 @@ static const struct musb_platform_ops bfin_ops = { static u64 bfin_dmamask = DMA_BIT_MASK(32); -static int __init bfin_probe(struct platform_device *pdev) +static int __devinit bfin_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; @@ -525,7 +525,7 @@ err0: return ret; } -static int __exit bfin_remove(struct platform_device *pdev) +static int __devexit bfin_remove(struct platform_device *pdev) { struct bfin_glue *glue = platform_get_drvdata(pdev); @@ -575,6 +575,7 @@ static struct dev_pm_ops bfin_pm_ops = { #endif static struct platform_driver bfin_driver = { + .probe = bfin_probe, .remove = __exit_p(bfin_remove), .driver = { .name = "musb-blackfin", @@ -588,9 +589,9 @@ MODULE_LICENSE("GPL v2"); static int __init bfin_init(void) { - return platform_driver_probe(&bfin_driver, bfin_probe); + return platform_driver_register(&bfin_driver); } -subsys_initcall(bfin_init); +module_init(bfin_init); static void __exit bfin_exit(void) { diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 2613bfdb09b6..01c8f2ece084 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -478,7 +478,7 @@ static const struct musb_platform_ops da8xx_ops = { static u64 da8xx_dmamask = DMA_BIT_MASK(32); -static int __init da8xx_probe(struct platform_device *pdev) +static int __devinit da8xx_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; @@ -562,7 +562,7 @@ err0: return ret; } -static int __exit da8xx_remove(struct platform_device *pdev) +static int __devexit da8xx_remove(struct platform_device *pdev) { struct da8xx_glue *glue = platform_get_drvdata(pdev); @@ -576,7 +576,8 @@ static int __exit da8xx_remove(struct platform_device *pdev) } static struct platform_driver da8xx_driver = { - .remove = __exit_p(da8xx_remove), + .probe = da8xx_probe, + .remove = __devexit_p(da8xx_remove), .driver = { .name = "musb-da8xx", }, @@ -588,9 +589,9 @@ MODULE_LICENSE("GPL v2"); static int __init da8xx_init(void) { - return platform_driver_probe(&da8xx_driver, da8xx_probe); + return platform_driver_register(&da8xx_driver); } -subsys_initcall(da8xx_init); +module_init(da8xx_init); static void __exit da8xx_exit(void) { diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index f9a3f62a83b5..7802c7ec43f9 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -514,7 +514,7 @@ static const struct musb_platform_ops davinci_ops = { static u64 davinci_dmamask = DMA_BIT_MASK(32); -static int __init davinci_probe(struct platform_device *pdev) +static int __devinit davinci_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; @@ -597,7 +597,7 @@ err0: return ret; } -static int __exit davinci_remove(struct platform_device *pdev) +static int __devexit davinci_remove(struct platform_device *pdev) { struct davinci_glue *glue = platform_get_drvdata(pdev); @@ -611,7 +611,8 @@ static int __exit davinci_remove(struct platform_device *pdev) } static struct platform_driver davinci_driver = { - .remove = __exit_p(davinci_remove), + .probe = davinci_probe, + .remove = __devexit_p(davinci_remove), .driver = { .name = "musb-davinci", }, @@ -623,9 +624,9 @@ MODULE_LICENSE("GPL v2"); static int __init davinci_init(void) { - return platform_driver_probe(&davinci_driver, davinci_probe); + return platform_driver_register(&davinci_driver); } -subsys_initcall(davinci_init); +module_init(davinci_init); static void __exit davinci_exit(void) { diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 6a929859b55a..d6134b39e8fc 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1014,12 +1014,12 @@ static void musb_shutdown(struct platform_device *pdev) || defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE) \ || defined(CONFIG_USB_MUSB_AM35X) \ || defined(CONFIG_USB_MUSB_AM35X_MODULE) -static ushort __initdata fifo_mode = 4; +static ushort __devinitdata fifo_mode = 4; #elif defined(CONFIG_USB_MUSB_UX500) \ || defined(CONFIG_USB_MUSB_UX500_MODULE) -static ushort __initdata fifo_mode = 5; +static ushort __devinitdata fifo_mode = 5; #else -static ushort __initdata fifo_mode = 2; +static ushort __devinitdata fifo_mode = 2; #endif /* "modprobe ... fifo_mode=1" etc */ @@ -1032,7 +1032,7 @@ MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration"); */ /* mode 0 - fits in 2KB */ -static struct musb_fifo_cfg __initdata mode_0_cfg[] = { +static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, }, @@ -1041,7 +1041,7 @@ static struct musb_fifo_cfg __initdata mode_0_cfg[] = { }; /* mode 1 - fits in 4KB */ -static struct musb_fifo_cfg __initdata mode_1_cfg[] = { +static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, }, { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, }, @@ -1050,7 +1050,7 @@ static struct musb_fifo_cfg __initdata mode_1_cfg[] = { }; /* mode 2 - fits in 4KB */ -static struct musb_fifo_cfg __initdata mode_2_cfg[] = { +static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, @@ -1060,7 +1060,7 @@ static struct musb_fifo_cfg __initdata mode_2_cfg[] = { }; /* mode 3 - fits in 4KB */ -static struct musb_fifo_cfg __initdata mode_3_cfg[] = { +static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, @@ -1070,7 +1070,7 @@ static struct musb_fifo_cfg __initdata mode_3_cfg[] = { }; /* mode 4 - fits in 16KB */ -static struct musb_fifo_cfg __initdata mode_4_cfg[] = { +static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, @@ -1101,7 +1101,7 @@ static struct musb_fifo_cfg __initdata mode_4_cfg[] = { }; /* mode 5 - fits in 8KB */ -static struct musb_fifo_cfg __initdata mode_5_cfg[] = { +static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, @@ -1137,7 +1137,7 @@ static struct musb_fifo_cfg __initdata mode_5_cfg[] = { * * returns negative errno or offset for next fifo. */ -static int __init +static int __devinit fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep, const struct musb_fifo_cfg *cfg, u16 offset) { @@ -1208,11 +1208,11 @@ fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep, return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0)); } -static struct musb_fifo_cfg __initdata ep0_cfg = { +static struct musb_fifo_cfg __devinitdata ep0_cfg = { .style = FIFO_RXTX, .maxpacket = 64, }; -static int __init ep_config_from_table(struct musb *musb) +static int __devinit ep_config_from_table(struct musb *musb) { const struct musb_fifo_cfg *cfg; unsigned i, n; @@ -1303,7 +1303,7 @@ done: * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false * @param musb the controller */ -static int __init ep_config_from_hw(struct musb *musb) +static int __devinit ep_config_from_hw(struct musb *musb) { u8 epnum = 0; struct musb_hw_ep *hw_ep; @@ -1350,7 +1350,7 @@ enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, }; /* Initialize MUSB (M)HDRC part of the USB hardware subsystem; * configure endpoints, or take their config from silicon */ -static int __init musb_core_init(u16 musb_type, struct musb *musb) +static int __devinit musb_core_init(u16 musb_type, struct musb *musb) { u8 reg; char *type; @@ -1586,7 +1586,7 @@ irqreturn_t musb_interrupt(struct musb *musb) EXPORT_SYMBOL_GPL(musb_interrupt); #ifndef CONFIG_MUSB_PIO_ONLY -static bool __initdata use_dma = 1; +static bool __devinitdata use_dma = 1; /* "modprobe ... use_dma=0" etc */ module_param(use_dma, bool, 0); @@ -1774,7 +1774,7 @@ static void musb_irq_work(struct work_struct *data) * Init support */ -static struct musb *__init +static struct musb *__devinit allocate_instance(struct device *dev, struct musb_hdrc_config *config, void __iomem *mbase) { @@ -1852,7 +1852,7 @@ static void musb_free(struct musb *musb) * @mregs: virtual address of controller registers, * not yet corrected for platform-specific offsets */ -static int __init +static int __devinit musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) { int status; @@ -2072,7 +2072,7 @@ fail0: static u64 *orig_dma_mask; #endif -static int __init musb_probe(struct platform_device *pdev) +static int __devinit musb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; int irq = platform_get_irq_byname(pdev, "mc"); @@ -2101,7 +2101,7 @@ static int __init musb_probe(struct platform_device *pdev) return status; } -static int __exit musb_remove(struct platform_device *pdev) +static int __devexit musb_remove(struct platform_device *pdev) { struct musb *musb = dev_to_musb(&pdev->dev); void __iomem *ctrl_base = musb->ctrl_base; @@ -2361,7 +2361,8 @@ static struct platform_driver musb_driver = { .owner = THIS_MODULE, .pm = MUSB_DEV_PM_OPS, }, - .remove = __exit_p(musb_remove), + .probe = musb_probe, + .remove = __devexit_p(musb_remove), .shutdown = musb_shutdown, }; @@ -2377,13 +2378,9 @@ static int __init musb_init(void) ", " "otg (peripheral+host)", musb_driver_name); - return platform_driver_probe(&musb_driver, musb_probe); + return platform_driver_register(&musb_driver); } - -/* make us init after usbcore and i2c (transceivers, regulators, etc) - * and before usb gadget and host-side drivers start to register - */ -fs_initcall(musb_init); +module_init(musb_init); static void __exit musb_cleanup(void) { diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index 13d9af9bf920..219d0fba584e 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c @@ -235,7 +235,7 @@ static const struct file_operations musb_test_mode_fops = { .release = single_release, }; -int __init musb_init_debugfs(struct musb *musb) +int __devinit musb_init_debugfs(struct musb *musb) { struct dentry *root; struct dentry *file; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index ac3d2eec20fe..59ab98f08e9e 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1762,7 +1762,7 @@ static void musb_gadget_release(struct device *dev) } -static void __init +static void __devinit init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in) { struct musb_hw_ep *hw_ep = musb->endpoints + epnum; @@ -1799,7 +1799,7 @@ init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in) * Initialize the endpoints exposed to peripheral drivers, with backlinks * to the rest of the driver state. */ -static inline void __init musb_g_init_endpoints(struct musb *musb) +static inline void __devinit musb_g_init_endpoints(struct musb *musb) { u8 epnum; struct musb_hw_ep *hw_ep; @@ -1832,7 +1832,7 @@ static inline void __init musb_g_init_endpoints(struct musb *musb) /* called once during driver setup to initialize and link into * the driver model; memory is zeroed. */ -int __init musb_gadget_setup(struct musb *musb) +int __devinit musb_gadget_setup(struct musb *musb) { int status; diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index c27bbbf32b52..b254173e7e85 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -408,7 +408,7 @@ static const struct musb_platform_ops omap2430_ops = { static u64 omap2430_dmamask = DMA_BIT_MASK(32); -static int __init omap2430_probe(struct platform_device *pdev) +static int __devinit omap2430_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; @@ -471,7 +471,7 @@ err0: return ret; } -static int __exit omap2430_remove(struct platform_device *pdev) +static int __devexit omap2430_remove(struct platform_device *pdev) { struct omap2430_glue *glue = platform_get_drvdata(pdev); @@ -524,7 +524,8 @@ static struct dev_pm_ops omap2430_pm_ops = { #endif static struct platform_driver omap2430_driver = { - .remove = __exit_p(omap2430_remove), + .probe = omap2430_probe, + .remove = __devexit_p(omap2430_remove), .driver = { .name = "musb-omap2430", .pm = DEV_PM_OPS, @@ -537,9 +538,9 @@ MODULE_LICENSE("GPL v2"); static int __init omap2430_init(void) { - return platform_driver_probe(&omap2430_driver, omap2430_probe); + return platform_driver_register(&omap2430_driver); } -subsys_initcall(omap2430_init); +module_init(omap2430_init); static void __exit omap2430_exit(void) { diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 1f405616e6cd..b387f12d05b8 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -1165,7 +1165,7 @@ static const struct musb_platform_ops tusb_ops = { static u64 tusb_dmamask = DMA_BIT_MASK(32); -static int __init tusb_probe(struct platform_device *pdev) +static int __devinit tusb_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; @@ -1227,7 +1227,7 @@ err0: return ret; } -static int __exit tusb_remove(struct platform_device *pdev) +static int __devexit tusb_remove(struct platform_device *pdev) { struct tusb6010_glue *glue = platform_get_drvdata(pdev); @@ -1239,7 +1239,8 @@ static int __exit tusb_remove(struct platform_device *pdev) } static struct platform_driver tusb_driver = { - .remove = __exit_p(tusb_remove), + .probe = tusb_probe, + .remove = __devexit_p(tusb_remove), .driver = { .name = "musb-tusb", }, @@ -1251,9 +1252,9 @@ MODULE_LICENSE("GPL v2"); static int __init tusb_init(void) { - return platform_driver_probe(&tusb_driver, tusb_probe); + return platform_driver_register(&tusb_driver); } -subsys_initcall(tusb_init); +module_init(tusb_init); static void __exit tusb_exit(void) { diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index f7e04bf34a13..bcfc48f4854a 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -58,7 +58,7 @@ static const struct musb_platform_ops ux500_ops = { .exit = ux500_musb_exit, }; -static int __init ux500_probe(struct platform_device *pdev) +static int __devinit ux500_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; @@ -141,7 +141,7 @@ err0: return ret; } -static int __exit ux500_remove(struct platform_device *pdev) +static int __devexit ux500_remove(struct platform_device *pdev) { struct ux500_glue *glue = platform_get_drvdata(pdev); @@ -194,7 +194,8 @@ static const struct dev_pm_ops ux500_pm_ops = { #endif static struct platform_driver ux500_driver = { - .remove = __exit_p(ux500_remove), + .probe = ux500_probe, + .remove = __devexit_p(ux500_remove), .driver = { .name = "musb-ux500", .pm = DEV_PM_OPS, @@ -207,9 +208,9 @@ MODULE_LICENSE("GPL v2"); static int __init ux500_init(void) { - return platform_driver_probe(&ux500_driver, ux500_probe); + return platform_driver_register(&ux500_driver); } -subsys_initcall(ux500_init); +module_init(ux500_init); static void __exit ux500_exit(void) { From 6c2abcdd4f8e21ce686a26697de0ce198a16eaed Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 31 Jan 2012 14:19:00 +0200 Subject: [PATCH 046/269] usb: musb: debugfs: fix error check debugfs will return NULL on failure, so we must check for !ptr instead of IS_ERR(ptr). Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_debugfs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index 219d0fba584e..40a37c91cc10 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c @@ -242,22 +242,22 @@ int __devinit musb_init_debugfs(struct musb *musb) int ret; root = debugfs_create_dir("musb", NULL); - if (IS_ERR(root)) { - ret = PTR_ERR(root); + if (!root) { + ret = -ENOMEM; goto err0; } file = debugfs_create_file("regdump", S_IRUGO, root, musb, &musb_regdump_fops); - if (IS_ERR(file)) { - ret = PTR_ERR(file); + if (!file) { + ret = -ENOMEM; goto err1; } file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, musb, &musb_test_mode_fops); - if (IS_ERR(file)) { - ret = PTR_ERR(file); + if (!file) { + ret = -ENOMEM; goto err1; } From c898add51c7b5b99fcecdeaf4df2ca30949cacb6 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 11 Jan 2012 12:42:32 +0100 Subject: [PATCH 047/269] usb/uas: only bind if the hcd supports SG The UAS driver requires SG support by the HCD operating the device. This patch stops UAS from operating on a HCD without sg support and prints a message to let him know. The spec says: |For [USB2] backward compatibility, the device shall present [BOT] as |alternate interface zero (primary) and [UAS] as alternate interface one |(secondary). A device which does not need backward compatibility with |[BOT] shall present [UAS] as alternate interface zero. In [USB2] |systems, the [BOT] driver or an associated filter driver may need to |issue a SET INTERFACE request for alternate interface one and then allow |the [UAS] driver to load. If the user used usb_modeswitch to switch to UAS then he can go back to BOT or use a different HCD. In case UAS is the only interface then there is currently no way out. In future usb_sg_wait() should be extended to provide a non-blocking interface so it can work with the UAS driver. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Sarah Sharp --- drivers/usb/storage/uas.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index e0133c9ab0bf..e34c75970ed1 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -621,22 +622,34 @@ static int uas_is_interface(struct usb_host_interface *intf) intf->desc.bInterfaceProtocol == USB_PR_UAS); } +static int uas_isnt_supported(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + dev_warn(&udev->dev, "The driver for the USB controller %s does not " + "support scatter-gather which is\n", + hcd->driver->description); + dev_warn(&udev->dev, "required by the UAS driver. Please try an" + "alternative USB controller if you wish to use UAS.\n"); + return -ENODEV; +} + static int uas_switch_interface(struct usb_device *udev, struct usb_interface *intf) { int i; - - if (uas_is_interface(intf->cur_altsetting)) - return 0; + int sg_supported = udev->bus->sg_tablesize != 0; for (i = 0; i < intf->num_altsetting; i++) { struct usb_host_interface *alt = &intf->altsetting[i]; - if (alt == intf->cur_altsetting) - continue; - if (uas_is_interface(alt)) + + if (uas_is_interface(alt)) { + if (!sg_supported) + return uas_isnt_supported(udev); return usb_set_interface(udev, alt->desc.bInterfaceNumber, alt->desc.bAlternateSetting); + } } return -ENODEV; From 348748b0e8cccc675e2f3a1456460ffcd540e1a1 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 11 Jan 2012 12:45:56 +0100 Subject: [PATCH 048/269] usb/uas: move UAS structs / defines into a header file The protocol specific structures and defines which are used by UAS are moved into a header files by this patch so it can be accessed by the UAS gadget as well. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Sarah Sharp --- drivers/usb/storage/uas.c | 56 +---------------------------------- include/linux/usb/uas.h | 61 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 55 deletions(-) create mode 100644 include/linux/usb/uas.h diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index e34c75970ed1..f98ba40352c1 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -23,49 +24,6 @@ #include #include -/* Common header for all IUs */ -struct iu { - __u8 iu_id; - __u8 rsvd1; - __be16 tag; -}; - -enum { - IU_ID_COMMAND = 0x01, - IU_ID_STATUS = 0x03, - IU_ID_RESPONSE = 0x04, - IU_ID_TASK_MGMT = 0x05, - IU_ID_READ_READY = 0x06, - IU_ID_WRITE_READY = 0x07, -}; - -struct command_iu { - __u8 iu_id; - __u8 rsvd1; - __be16 tag; - __u8 prio_attr; - __u8 rsvd5; - __u8 len; - __u8 rsvd7; - struct scsi_lun lun; - __u8 cdb[16]; /* XXX: Overflow-checking tools may misunderstand */ -}; - -/* - * Also used for the Read Ready and Write Ready IUs since they have the - * same first four bytes - */ -struct sense_iu { - __u8 iu_id; - __u8 rsvd1; - __be16 tag; - __be16 status_qual; - __u8 status; - __u8 rsvd7[7]; - __be16 len; - __u8 sense[SCSI_SENSE_BUFFERSIZE]; -}; - /* * The r00-r01c specs define this version of the SENSE IU data structure. * It's still in use by several different firmware releases. @@ -80,18 +38,6 @@ struct sense_iu_old { __u8 sense[SCSI_SENSE_BUFFERSIZE]; }; -enum { - CMD_PIPE_ID = 1, - STATUS_PIPE_ID = 2, - DATA_IN_PIPE_ID = 3, - DATA_OUT_PIPE_ID = 4, - - UAS_SIMPLE_TAG = 0, - UAS_HEAD_TAG = 1, - UAS_ORDERED_TAG = 2, - UAS_ACA = 4, -}; - struct uas_dev_info { struct usb_interface *intf; struct usb_device *udev; diff --git a/include/linux/usb/uas.h b/include/linux/usb/uas.h new file mode 100644 index 000000000000..856be7fcbbd8 --- /dev/null +++ b/include/linux/usb/uas.h @@ -0,0 +1,61 @@ +#ifndef __USB_UAS_H__ +#define __USB_UAS_H__ + +#include +#include + +/* Common header for all IUs */ +struct iu { + __u8 iu_id; + __u8 rsvd1; + __be16 tag; +}; + +enum { + IU_ID_COMMAND = 0x01, + IU_ID_STATUS = 0x03, + IU_ID_RESPONSE = 0x04, + IU_ID_TASK_MGMT = 0x05, + IU_ID_READ_READY = 0x06, + IU_ID_WRITE_READY = 0x07, +}; + +struct command_iu { + __u8 iu_id; + __u8 rsvd1; + __be16 tag; + __u8 prio_attr; + __u8 rsvd5; + __u8 len; + __u8 rsvd7; + struct scsi_lun lun; + __u8 cdb[16]; /* XXX: Overflow-checking tools may misunderstand */ +}; + +/* + * Also used for the Read Ready and Write Ready IUs since they have the + * same first four bytes + */ +struct sense_iu { + __u8 iu_id; + __u8 rsvd1; + __be16 tag; + __be16 status_qual; + __u8 status; + __u8 rsvd7[7]; + __be16 len; + __u8 sense[SCSI_SENSE_BUFFERSIZE]; +}; + +enum { + CMD_PIPE_ID = 1, + STATUS_PIPE_ID = 2, + DATA_IN_PIPE_ID = 3, + DATA_OUT_PIPE_ID = 4, + + UAS_SIMPLE_TAG = 0, + UAS_HEAD_TAG = 1, + UAS_ORDERED_TAG = 2, + UAS_ACA = 4, +}; +#endif From ee398b59ec1dc3ce1d60518f4ea644907893414b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 11 Jan 2012 12:45:57 +0100 Subject: [PATCH 049/269] usb/uas: add usb_pipe_usage_descriptor usb_pipe_usage_descriptor defines the struct which is used to describe the type of the endpoint in UAS (status/command/data in+out). It will be used by the UAS gadget, the host code is using a char array for the access. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Sarah Sharp --- include/linux/usb/uas.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/linux/usb/uas.h b/include/linux/usb/uas.h index 856be7fcbbd8..9a988e413694 100644 --- a/include/linux/usb/uas.h +++ b/include/linux/usb/uas.h @@ -47,6 +47,14 @@ struct sense_iu { __u8 sense[SCSI_SENSE_BUFFERSIZE]; }; +struct usb_pipe_usage_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bPipeID; + __u8 Reserved; +} __attribute__((__packed__)); + enum { CMD_PIPE_ID = 1, STATUS_PIPE_ID = 2, From e4d8318a85779b25b880187b1b1c44e797bd7d4b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 25 Jan 2012 11:48:40 +0100 Subject: [PATCH 050/269] usb/uas: make sure data urb is gone if we receive status before that Just run into the following: - new disk arrived in the system - udev couldn't wait to get its hands on to to run ata_id /dev/sda - this sent the cdb 0xa1 to the device. - my UAS-gadget recevied the cdb and had no idea what to do with it. It decided to send a status URB back with sense set to invalid opcode. - the host side received it status and completed the scsi command. - the host sent another scsi with 4kib data buffer - Now I was confused why the data transfer is only 512 bytes instead of 4kib since the host is always allocating the complete transfer in one go. - Finally the system crashed while walking through the sg list. This patch adds three new flags in order to distinguish between DATA URB completed and outstanding. If we receive status before data, we cancel data and let data complete the command. This solves the problem for IN and OUT transfers but does not work for BIDI. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Sarah Sharp --- drivers/usb/storage/uas.c | 90 ++++++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 15 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index f98ba40352c1..8ec8a6e66f50 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -58,6 +58,9 @@ enum { SUBMIT_DATA_OUT_URB = (1 << 5), ALLOC_CMD_URB = (1 << 6), SUBMIT_CMD_URB = (1 << 7), + COMPLETED_DATA_IN = (1 << 8), + COMPLETED_DATA_OUT = (1 << 9), + DATA_COMPLETES_CMD = (1 << 10), }; /* Overrides scsi_pointer */ @@ -111,6 +114,7 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) { struct sense_iu *sense_iu = urb->transfer_buffer; struct scsi_device *sdev = cmnd->device; + struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; if (urb->actual_length > 16) { unsigned len = be16_to_cpup(&sense_iu->len); @@ -128,13 +132,15 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) } cmnd->result = sense_iu->status; - cmnd->scsi_done(cmnd); + if (!(cmdinfo->state & DATA_COMPLETES_CMD)) + cmnd->scsi_done(cmnd); } static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) { struct sense_iu_old *sense_iu = urb->transfer_buffer; struct scsi_device *sdev = cmnd->device; + struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; if (urb->actual_length > 8) { unsigned len = be16_to_cpup(&sense_iu->len) - 2; @@ -152,7 +158,8 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) } cmnd->result = sense_iu->status; - cmnd->scsi_done(cmnd); + if (!(cmdinfo->state & DATA_COMPLETES_CMD)) + cmnd->scsi_done(cmnd); } static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, @@ -177,6 +184,7 @@ static void uas_stat_cmplt(struct urb *urb) struct Scsi_Host *shost = urb->context; struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; struct scsi_cmnd *cmnd; + struct uas_cmd_info *cmdinfo; u16 tag; int ret; @@ -202,12 +210,32 @@ static void uas_stat_cmplt(struct urb *urb) dev_err(&urb->dev->dev, "failed submit status urb\n"); return; } + cmdinfo = (void *)&cmnd->SCp; switch (iu->iu_id) { case IU_ID_STATUS: if (devinfo->cmnd == cmnd) devinfo->cmnd = NULL; + if (!(cmdinfo->state & COMPLETED_DATA_IN) && + cmdinfo->data_in_urb) { + if (devinfo->use_streams) { + cmdinfo->state |= DATA_COMPLETES_CMD; + usb_unlink_urb(cmdinfo->data_in_urb); + } else { + usb_free_urb(cmdinfo->data_in_urb); + } + } + if (!(cmdinfo->state & COMPLETED_DATA_OUT) && + cmdinfo->data_out_urb) { + if (devinfo->use_streams) { + cmdinfo->state |= DATA_COMPLETES_CMD; + usb_unlink_urb(cmdinfo->data_in_urb); + } else { + usb_free_urb(cmdinfo->data_out_urb); + } + } + if (urb->actual_length < 16) devinfo->uas_sense_old = 1; if (devinfo->uas_sense_old) @@ -236,27 +264,59 @@ static void uas_stat_cmplt(struct urb *urb) dev_err(&urb->dev->dev, "failed submit status urb\n"); } -static void uas_data_cmplt(struct urb *urb) +static void uas_data_out_cmplt(struct urb *urb) { - struct scsi_data_buffer *sdb = urb->context; + struct scsi_cmnd *cmnd = urb->context; + struct scsi_data_buffer *sdb = scsi_out(cmnd); + struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + + cmdinfo->state |= COMPLETED_DATA_OUT; + sdb->resid = sdb->length - urb->actual_length; usb_free_urb(urb); + + if (cmdinfo->state & DATA_COMPLETES_CMD) + cmnd->scsi_done(cmnd); +} + +static void uas_data_in_cmplt(struct urb *urb) +{ + struct scsi_cmnd *cmnd = urb->context; + struct scsi_data_buffer *sdb = scsi_in(cmnd); + struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + + cmdinfo->state |= COMPLETED_DATA_IN; + + sdb->resid = sdb->length - urb->actual_length; + usb_free_urb(urb); + + if (cmdinfo->state & DATA_COMPLETES_CMD) + cmnd->scsi_done(cmnd); } static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp, - unsigned int pipe, u16 stream_id, - struct scsi_data_buffer *sdb, - enum dma_data_direction dir) + unsigned int pipe, struct scsi_cmnd *cmnd, + enum dma_data_direction dir) { + struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; struct usb_device *udev = devinfo->udev; struct urb *urb = usb_alloc_urb(0, gfp); + struct scsi_data_buffer *sdb; + usb_complete_t complete_fn; + u16 stream_id = cmdinfo->stream; if (!urb) goto out; - usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, uas_data_cmplt, - sdb); - if (devinfo->use_streams) - urb->stream_id = stream_id; + if (dir == DMA_FROM_DEVICE) { + sdb = scsi_in(cmnd); + complete_fn = uas_data_in_cmplt; + } else { + sdb = scsi_out(cmnd); + complete_fn = uas_data_out_cmplt; + } + usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, + complete_fn, cmnd); + urb->stream_id = stream_id; urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0; urb->sg = sdb->table.sgl; out: @@ -358,8 +418,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, if (cmdinfo->state & ALLOC_DATA_IN_URB) { cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp, - devinfo->data_in_pipe, cmdinfo->stream, - scsi_in(cmnd), DMA_FROM_DEVICE); + devinfo->data_in_pipe, cmnd, + DMA_FROM_DEVICE); if (!cmdinfo->data_in_urb) return SCSI_MLQUEUE_DEVICE_BUSY; cmdinfo->state &= ~ALLOC_DATA_IN_URB; @@ -376,8 +436,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, if (cmdinfo->state & ALLOC_DATA_OUT_URB) { cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp, - devinfo->data_out_pipe, cmdinfo->stream, - scsi_out(cmnd), DMA_TO_DEVICE); + devinfo->data_out_pipe, cmnd, + DMA_TO_DEVICE); if (!cmdinfo->data_out_urb) return SCSI_MLQUEUE_DEVICE_BUSY; cmdinfo->state &= ~ALLOC_DATA_OUT_URB; From 0cb54a3e47cb4baf0bc7463f0a64cfeae5e35697 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 2 Feb 2012 15:38:14 -0500 Subject: [PATCH 051/269] USB: debugging code shouldn't alter control flow People have complained that debugging code shouldn't alter the flow of control; it should restrict itself to printing out warnings and error messages. Bowing to popular opinion, this patch (as1518) changes the debugging checks in usb_submit_urb() to follow this guideline. Signed-off-by: Alan Stern Reported-by: Keith Packard CC: Pavel Machek Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/urb.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 909625b91eb3..f4f20c7b7765 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -403,20 +403,17 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) * cause problems in HCDs if they get it wrong. */ { - unsigned int orig_flags = urb->transfer_flags; unsigned int allowed; static int pipetypes[4] = { PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT }; /* Check that the pipe's type matches the endpoint's type */ - if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) { - dev_err(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", + if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) + dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", usb_pipetype(urb->pipe), pipetypes[xfertype]); - return -EPIPE; /* The most suitable error code :-) */ - } - /* enforce simple/standard policy */ + /* Check against a simple/standard policy */ allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK | URB_FREE_BUFFER); switch (xfertype) { @@ -435,14 +432,12 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) allowed |= URB_ISO_ASAP; break; } - urb->transfer_flags &= allowed; + allowed &= urb->transfer_flags; - /* fail if submitter gave bogus flags */ - if (urb->transfer_flags != orig_flags) { - dev_err(&dev->dev, "BOGUS urb flags, %x --> %x\n", - orig_flags, urb->transfer_flags); - return -EINVAL; - } + /* warn if submitter gave bogus flags */ + if (allowed != urb->transfer_flags) + dev_WARN(&dev->dev, "BOGUS urb flags, %x --> %x\n", + urb->transfer_flags, allowed); } #endif /* From 04a9bfcd50dd568a8f1a10194a7f336f6b3ad81c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 2 Jan 2012 18:25:43 +0200 Subject: [PATCH 052/269] usb: dwc3: gadget: re-factor USB2 test mode to a function There are some situations were we might need to enable USB Test Modes without having access to a Host stack. In such situations we cannot rely solely on USB Control Messages to enable test features. For those cases, we will also allow test mode to be enabled via debugfs and this patch is a preparation for that. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 23 +++++------------------ drivers/usb/dwc3/gadget.c | 33 +++++++++++++++++++++++++++++++++ drivers/usb/dwc3/gadget.h | 2 ++ 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index c8df1dd967ef..5eb7095e4005 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -315,7 +315,6 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, u32 recip; u32 wValue; u32 wIndex; - u32 reg; int ret; u32 mode; @@ -357,24 +356,12 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, return -EINVAL; mode = wIndex >> 8; - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - reg &= ~DWC3_DCTL_TSTCTRL_MASK; - - switch (mode) { - case TEST_J: - case TEST_K: - case TEST_SE0_NAK: - case TEST_PACKET: - case TEST_FORCE_EN: - reg |= mode << 1; - break; - default: - return -EINVAL; + ret = dwc3_gadget_set_test_mode(dwc, mode); + if (ret < 0) { + dev_dbg(dwc->dev, "Invalid Test #%d\n", + mode); + return ret; } - dwc3_writel(dwc->regs, DWC3_DCTL, reg); - break; - default: - return -EINVAL; } break; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 064b6e2cd411..1dee17e7b778 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -56,6 +56,39 @@ #define DMA_ADDR_INVALID (~(dma_addr_t)0) +/** + * dwc3_gadget_set_test_mode - Enables USB2 Test Modes + * @dwc: pointer to our context structure + * @mode: the mode to set (J, K SE0 NAK, Force Enable) + * + * Caller should take care of locking. This function will + * return 0 on success or -EINVAL if wrong Test Selector + * is passed + */ +int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode) +{ + u32 reg; + + reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg &= ~DWC3_DCTL_TSTCTRL_MASK; + + switch (mode) { + case TEST_J: + case TEST_K: + case TEST_SE0_NAK: + case TEST_PACKET: + case TEST_FORCE_EN: + reg |= mode << 1; + break; + default: + return -EINVAL; + } + + dwc3_writel(dwc->regs, DWC3_DCTL, reg); + + return 0; +} + void dwc3_map_buffer_to_dma(struct dwc3_request *req) { struct dwc3 *dwc = req->dep->dwc; diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index d97f467d41cc..2cf6f2989f73 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -100,6 +100,8 @@ static inline void dwc3_gadget_move_request_queued(struct dwc3_request *req) void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, int status); +int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode); + void dwc3_ep0_interrupt(struct dwc3 *dwc, const struct dwc3_event_depevt *event); void dwc3_ep0_out_start(struct dwc3 *dwc); From 080d921fe7a8d27c07eba7723fe53a3bea100327 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 2 Jan 2012 18:38:30 +0200 Subject: [PATCH 053/269] usb: dwc3: gadget: allow testmodes changes via debugfs This is very useful for low level Link Testing where we might not have a USB Host stack, only a scope to verify signal integrity. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debugfs.c | 92 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 433c97c15fc5..c7e85024fda8 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -46,6 +46,8 @@ #include #include +#include + #include "core.h" #include "gadget.h" #include "io.h" @@ -464,6 +466,89 @@ static const struct file_operations dwc3_mode_fops = { .release = single_release, }; +static int dwc3_testmode_show(struct seq_file *s, void *unused) +{ + struct dwc3 *dwc = s->private; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&dwc->lock, flags); + reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg &= DWC3_DCTL_TSTCTRL_MASK; + reg >>= 1; + spin_unlock_irqrestore(&dwc->lock, flags); + + switch (reg) { + case 0: + seq_printf(s, "no test\n"); + break; + case TEST_J: + seq_printf(s, "test_j\n"); + break; + case TEST_K: + seq_printf(s, "test_k\n"); + break; + case TEST_SE0_NAK: + seq_printf(s, "test_se0_nak\n"); + break; + case TEST_PACKET: + seq_printf(s, "test_packet\n"); + break; + case TEST_FORCE_EN: + seq_printf(s, "test_force_enable\n"); + break; + default: + seq_printf(s, "UNKNOWN %d\n", reg); + } + + return 0; +} + +static int dwc3_testmode_open(struct inode *inode, struct file *file) +{ + return single_open(file, dwc3_testmode_show, inode->i_private); +} + +static ssize_t dwc3_testmode_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + struct seq_file *s = file->private_data; + struct dwc3 *dwc = s->private; + unsigned long flags; + u32 testmode = 0; + char buf[32]; + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return -EFAULT; + + if (!strncmp(buf, "test_j", 6)) + testmode = TEST_J; + else if (!strncmp(buf, "test_k", 6)) + testmode = TEST_K; + else if (!strncmp(buf, "test_se0_nak", 13)) + testmode = TEST_SE0_NAK; + else if (!strncmp(buf, "test_packet", 12)) + testmode = TEST_PACKET; + else if (!strncmp(buf, "test_force_enable", 18)) + testmode = TEST_FORCE_EN; + else + testmode = 0; + + spin_lock_irqsave(&dwc->lock, flags); + dwc3_gadget_set_test_mode(dwc, testmode); + spin_unlock_irqrestore(&dwc->lock, flags); + + return count; +} + +static const struct file_operations dwc3_testmode_fops = { + .open = dwc3_testmode_open, + .write = dwc3_testmode_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + int __devinit dwc3_debugfs_init(struct dwc3 *dwc) { struct dentry *root; @@ -492,6 +577,13 @@ int __devinit dwc3_debugfs_init(struct dwc3 *dwc) goto err1; } + file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, + dwc, &dwc3_testmode_fops); + if (IS_ERR(file)) { + ret = PTR_ERR(file); + goto err1; + } + return 0; err1: From 8598bde7fa125e85bc97decd6513d37dcf1e7bd9 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 2 Jan 2012 18:55:57 +0200 Subject: [PATCH 054/269] usb: dwc3: gadget: re-factor Link state change to a function Most link changes will, of course, happen with the help of a matching host HW, but in some cases we might want to debug very low level details about the link and exposing this to debugfs sounds like a good plan. This is a preparation for such setup. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 52 ++++++++++++++++++++++++++++++--------- drivers/usb/dwc3/gadget.h | 1 + 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 1dee17e7b778..80003952547e 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -89,6 +89,42 @@ int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode) return 0; } +/** + * dwc3_gadget_set_link_state - Sets USB Link to a particular State + * @dwc: pointer to our context structure + * @state: the state to put link into + * + * Caller should take care of locking. This function will + * return 0 on success or -EINVAL. + */ +int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) +{ + int retries = 100; + u32 reg; + + reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; + + /* set requested state */ + reg |= DWC3_DCTL_ULSTCHNGREQ(state); + dwc3_writel(dwc->regs, DWC3_DCTL, reg); + + /* wait for a change in DSTS */ + while (--retries) { + reg = dwc3_readl(dwc->regs, DWC3_DSTS); + + /* in HS, means ON */ + if (DWC3_DSTS_USBLNKST(reg) == state) + return 0; + + usleep_range(500, 1500); + } + + dev_vdbg(dwc->dev, "link state change request timed out\n"); + + return -ETIMEDOUT; +} + void dwc3_map_buffer_to_dma(struct dwc3_request *req) { struct dwc3 *dwc = req->dep->dwc; @@ -1155,17 +1191,11 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g) goto out; } - reg = dwc3_readl(dwc->regs, DWC3_DCTL); - - /* - * Switch link state to Recovery. In HS/FS/LS this means - * RemoteWakeup Request - */ - reg |= DWC3_DCTL_ULSTCHNG_RECOVERY; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); - - /* wait for at least 2000us */ - usleep_range(2000, 2500); + ret = dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RECOV); + if (ret < 0) { + dev_err(dwc->dev, "failed to put link in Recovery\n"); + goto out; + } /* write zeroes to Link Change Request */ reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 2cf6f2989f73..152b6de0649d 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -101,6 +101,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, int status); int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode); +int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state); void dwc3_ep0_interrupt(struct dwc3 *dwc, const struct dwc3_event_depevt *event); From 138801aaa566ecb5a5739a85909b9ec7285efd70 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 2 Jan 2012 19:25:16 +0200 Subject: [PATCH 055/269] usb: dwc3: gadget: allow Link state changes via debugfs This is very useful for low level link testing where we might not have a USB Host stack, only a scope to verify signal integrity. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debugfs.c | 110 +++++++++++++++++++++++++++++++++++++ drivers/usb/dwc3/gadget.c | 2 +- 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index c7e85024fda8..a2c1cc64b48d 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -549,6 +549,109 @@ static const struct file_operations dwc3_testmode_fops = { .release = single_release, }; +static int dwc3_link_state_show(struct seq_file *s, void *unused) +{ + struct dwc3 *dwc = s->private; + unsigned long flags; + enum dwc3_link_state state; + u32 reg; + + spin_lock_irqsave(&dwc->lock, flags); + reg = dwc3_readl(dwc->regs, DWC3_DSTS); + state = DWC3_DSTS_USBLNKST(reg); + spin_unlock_irqrestore(&dwc->lock, flags); + + switch (state) { + case DWC3_LINK_STATE_U0: + seq_printf(s, "U0\n"); + break; + case DWC3_LINK_STATE_U1: + seq_printf(s, "U1\n"); + break; + case DWC3_LINK_STATE_U2: + seq_printf(s, "U2\n"); + break; + case DWC3_LINK_STATE_U3: + seq_printf(s, "U3\n"); + break; + case DWC3_LINK_STATE_SS_DIS: + seq_printf(s, "SS.Disabled\n"); + break; + case DWC3_LINK_STATE_RX_DET: + seq_printf(s, "Rx.Detect\n"); + break; + case DWC3_LINK_STATE_SS_INACT: + seq_printf(s, "SS.Inactive\n"); + break; + case DWC3_LINK_STATE_POLL: + seq_printf(s, "Poll\n"); + break; + case DWC3_LINK_STATE_RECOV: + seq_printf(s, "Recovery\n"); + break; + case DWC3_LINK_STATE_HRESET: + seq_printf(s, "HRESET\n"); + break; + case DWC3_LINK_STATE_CMPLY: + seq_printf(s, "Compliance\n"); + break; + case DWC3_LINK_STATE_LPBK: + seq_printf(s, "Loopback\n"); + break; + default: + seq_printf(s, "UNKNOWN %d\n", reg); + } + + return 0; +} + +static int dwc3_link_state_open(struct inode *inode, struct file *file) +{ + return single_open(file, dwc3_link_state_show, inode->i_private); +} + +static ssize_t dwc3_link_state_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) +{ + struct seq_file *s = file->private_data; + struct dwc3 *dwc = s->private; + unsigned long flags; + enum dwc3_link_state state = 0; + char buf[32]; + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return -EFAULT; + + if (!strncmp(buf, "SS.Disabled", 11)) + state = DWC3_LINK_STATE_SS_DIS; + else if (!strncmp(buf, "Rx.Detect", 9)) + state = DWC3_LINK_STATE_RX_DET; + else if (!strncmp(buf, "SS.Inactive", 11)) + state = DWC3_LINK_STATE_SS_INACT; + else if (!strncmp(buf, "Recovery", 8)) + state = DWC3_LINK_STATE_RECOV; + else if (!strncmp(buf, "Compliance", 10)) + state = DWC3_LINK_STATE_CMPLY; + else if (!strncmp(buf, "Loopback", 8)) + state = DWC3_LINK_STATE_LPBK; + else + return -EINVAL; + + spin_lock_irqsave(&dwc->lock, flags); + dwc3_gadget_set_link_state(dwc, state); + spin_unlock_irqrestore(&dwc->lock, flags); + + return count; +} + +static const struct file_operations dwc3_link_state_fops = { + .open = dwc3_link_state_open, + .write = dwc3_link_state_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + int __devinit dwc3_debugfs_init(struct dwc3 *dwc) { struct dentry *root; @@ -584,6 +687,13 @@ int __devinit dwc3_debugfs_init(struct dwc3 *dwc) goto err1; } + file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root, + dwc, &dwc3_link_state_fops); + if (IS_ERR(file)) { + ret = PTR_ERR(file); + goto err1; + } + return 0; err1: diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 80003952547e..e0e2337dad13 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -117,7 +117,7 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) if (DWC3_DSTS_USBLNKST(reg) == state) return 0; - usleep_range(500, 1500); + udelay(500); } dev_vdbg(dwc->dev, "link state change request timed out\n"); From 40aa41fba348bc5bd19ff5bcf2b03d67bb01d1ce Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 18 Jan 2012 17:06:03 +0200 Subject: [PATCH 056/269] usb: dwc3: gadget: fix XferNotReady debug print Only bit 3 of the event status bitfield is valid and the others should not be considered. Make sure SW matches documentation on that case to avoid bogus debugging prints which would confuse an engineer. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 5 +++++ drivers/usb/dwc3/gadget.c | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 9e57f8e9bf17..f4878c4dec0f 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -719,6 +719,11 @@ struct dwc3_event_depevt { u32 endpoint_event:4; u32 reserved11_10:2; u32 status:4; + +/* Within XferNotReady */ +#define DEPEVT_STATUS_TRANSFER_ACTIVE (1 << 3) + +/* Within XferComplete */ #define DEPEVT_STATUS_BUSERR (1 << 0) #define DEPEVT_STATUS_SHORT (1 << 1) #define DEPEVT_STATUS_IOC (1 << 2) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index e0e2337dad13..4b64dc0bfa27 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1657,7 +1657,8 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, int ret; dev_vdbg(dwc->dev, "%s: reason %s\n", - dep->name, event->status + dep->name, event->status & + DEPEVT_STATUS_TRANSFER_ACTIVE ? "Transfer Active" : "Transfer Not Active"); From 7b7dd0253cd50fdc413b4ec199f1f3af08b7ba0d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 18 Jan 2012 17:09:17 +0200 Subject: [PATCH 057/269] usb: dwc3: gadget: use the descriptor pointer we hold We hold that pointer for one reason. It just looks nicer to use it. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 4b64dc0bfa27..d406a75456a0 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -943,7 +943,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) int start_trans; start_trans = 1; - if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && + if (usb_endpoint_xfer_isoc(dep->desc) && dep->flags & DWC3_EP_BUSY) start_trans = 0; From bb5cfd6811c63c47403e98028bde7e98bd7a1751 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 18 Jan 2012 20:18:45 +0200 Subject: [PATCH 058/269] usb: dwc3: ep0: move to CONFIGURED also on delayed status Mass Storage gadget will take some time to handle the SetConfiguration request, but even on those cases we should move to CONFIGURED state. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 5eb7095e4005..e90ebb9dd3e8 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -457,7 +457,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) case DWC3_ADDRESS_STATE: ret = dwc3_ep0_delegate_req(dwc, ctrl); /* if the cfg matches and the cfg is non zero */ - if (!ret && cfg) + if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) dwc->dev_state = DWC3_CONFIGURED_STATE; break; From 457e84b6624b4d97e6ffae437887ea51a22d54a0 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 18 Jan 2012 18:04:09 +0200 Subject: [PATCH 059/269] usb: dwc3: gadget: dynamically re-size TxFifos We need to dynamically re-size TxFifos for the cases where default values will not do. While at that, we create a simple function which, for now, will just allocate one full packet fifo space for each of the enabled endpoints. This can be improved later in order to allow for better throughput by allocating more space for endpoints which could make good use of that like isochronous and bulk. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 5 +++ drivers/usb/dwc3/core.h | 16 ++++++++- drivers/usb/dwc3/ep0.c | 11 +++++- drivers/usb/dwc3/gadget.c | 74 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 7c9df630dbe4..d119a1fbf946 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -404,6 +405,7 @@ static void dwc3_core_exit(struct dwc3 *dwc) static int __devinit dwc3_probe(struct platform_device *pdev) { + struct device_node *node = pdev->dev.of_node; struct resource *res; struct dwc3 *dwc; @@ -469,6 +471,9 @@ static int __devinit dwc3_probe(struct platform_device *pdev) else dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; + if (of_get_property(node, "tx-fifo-resize", NULL)) + dwc->needs_fifo_resize = true; + pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); pm_runtime_forbid(&pdev->dev); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index f4878c4dec0f..123c3aa47128 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -172,6 +172,10 @@ #define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) #define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17) +/* Global TX Fifo Size Register */ +#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff) +#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000) + /* Global HWPARAMS1 Register */ #define DWC3_GHWPARAMS1_EN_PWROPT(n) ((n & (3 << 24)) >> 24) #define DWC3_GHWPARAMS1_EN_PWROPT_NO 0 @@ -546,8 +550,13 @@ struct dwc3_hwparams { #define DWC3_MODE_DRD 2 #define DWC3_MODE_HUB 3 +#define DWC3_MDWIDTH(n) (((n) & 0xff00) >> 8) + /* HWPARAMS1 */ -#define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15) +#define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15) + +/* HWPARAMS7 */ +#define DWC3_RAM1_DEPTH(n) ((n) & 0xffff) struct dwc3_request { struct usb_request request; @@ -594,6 +603,8 @@ struct dwc3_request { * @ep0_expect_in: true when we expect a DATA IN transfer * @start_config_issued: true when StartConfig command has been issued * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround + * @needs_fifo_resize: not all users might want fifo resizing, flag it + * @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes. * @ep0_next_event: hold the next expected event * @ep0state: state of endpoint zero * @link_state: link state @@ -651,6 +662,8 @@ struct dwc3 { unsigned start_config_issued:1; unsigned setup_packet_pending:1; unsigned delayed_status:1; + unsigned needs_fifo_resize:1; + unsigned resize_fifos:1; enum dwc3_ep0_next ep0_next_event; enum dwc3_ep0_state ep0state; @@ -812,6 +825,7 @@ union dwc3_event { /* prototypes */ void dwc3_set_mode(struct dwc3 *dwc, u32 mode); +int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc); int dwc3_host_init(struct dwc3 *dwc); void dwc3_host_exit(struct dwc3 *dwc); diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index e90ebb9dd3e8..5104dbf46680 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -457,8 +457,11 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) case DWC3_ADDRESS_STATE: ret = dwc3_ep0_delegate_req(dwc, ctrl); /* if the cfg matches and the cfg is non zero */ - if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) + if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { dwc->dev_state = DWC3_CONFIGURED_STATE; + dwc->resize_fifos = true; + dev_dbg(dwc->dev, "resize fifos flag SET\n"); + } break; case DWC3_CONFIGURED_STATE: @@ -707,6 +710,12 @@ static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum) { struct dwc3_ep *dep = dwc->eps[epnum]; + if (dwc->resize_fifos) { + dev_dbg(dwc->dev, "starting to resize fifos\n"); + dwc3_gadget_resize_tx_fifos(dwc); + dwc->resize_fifos = 0; + } + WARN_ON(dwc3_ep0_start_control_status(dep)); } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index d406a75456a0..7913d1b50e38 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -125,6 +125,80 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) return -ETIMEDOUT; } +/** + * dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for current use-case + * @dwc: pointer to our context structure + * + * This function will a best effort FIFO allocation in order + * to improve FIFO usage and throughput, while still allowing + * us to enable as many endpoints as possible. + * + * Keep in mind that this operation will be highly dependent + * on the configured size for RAM1 - which contains TxFifo -, + * the amount of endpoints enabled on coreConsultant tool, and + * the width of the Master Bus. + * + * In the ideal world, we would always be able to satisfy the + * following equation: + * + * ((512 + 2 * MDWIDTH-Bytes) + (Number of IN Endpoints - 1) * \ + * (3 * (1024 + MDWIDTH-Bytes) + MDWIDTH-Bytes)) / MDWIDTH-Bytes + * + * Unfortunately, due to many variables that's not always the case. + */ +int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc) +{ + int last_fifo_depth = 0; + int ram1_depth; + int fifo_size; + int mdwidth; + int num; + + if (!dwc->needs_fifo_resize) + return 0; + + ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7); + mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0); + + /* MDWIDTH is represented in bits, we need it in bytes */ + mdwidth >>= 3; + + /* + * FIXME For now we will only allocate 1 wMaxPacketSize space + * for each enabled endpoint, later patches will come to + * improve this algorithm so that we better use the internal + * FIFO space + */ + for (num = 0; num < DWC3_ENDPOINTS_NUM; num++) { + struct dwc3_ep *dep = dwc->eps[num]; + int fifo_number = dep->number >> 1; + int tmp; + + if (!(dep->number & 1)) + continue; + + if (!(dep->flags & DWC3_EP_ENABLED)) + continue; + + tmp = dep->endpoint.maxpacket; + tmp += mdwidth; + tmp += mdwidth; + + fifo_size = DIV_ROUND_UP(tmp, mdwidth); + fifo_size |= (last_fifo_depth << 16); + + dev_vdbg(dwc->dev, "%s: Fifo Addr %04x Size %d\n", + dep->name, last_fifo_depth, fifo_size & 0xffff); + + dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(fifo_number), + fifo_size); + + last_fifo_depth += (fifo_size & 0xffff); + } + + return 0; +} + void dwc3_map_buffer_to_dma(struct dwc3_request *req) { struct dwc3 *dwc = req->dep->dwc; From 8db7ed15f2557e26371e4b2d98fee290d992b715 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 18 Jan 2012 18:32:29 +0200 Subject: [PATCH 060/269] usb: dwc3: gadget: start core on Rx.Detect When we set Run/Stop bit, we also move the core to Rx.Detect state so that USB3 handshake can start from a known location. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 9 +++++++++ drivers/usb/dwc3/gadget.c | 9 ++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 123c3aa47128..71d958af2393 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -202,6 +202,15 @@ #define DWC3_DCTL_APPL1RES (1 << 23) +#define DWC3_DCTL_TRGTULST_MASK (0x0f << 17) +#define DWC3_DCTL_TRGTULST(n) ((n) << 17) + +#define DWC3_DCTL_TRGTULST_U2 (DWC3_DCTL_TRGTULST(2)) +#define DWC3_DCTL_TRGTULST_U3 (DWC3_DCTL_TRGTULST(3)) +#define DWC3_DCTL_TRGTULST_SS_DIS (DWC3_DCTL_TRGTULST(4)) +#define DWC3_DCTL_TRGTULST_RX_DET (DWC3_DCTL_TRGTULST(5)) +#define DWC3_DCTL_TRGTULST_SS_INACT (DWC3_DCTL_TRGTULST(6)) + #define DWC3_DCTL_INITU2ENA (1 << 12) #define DWC3_DCTL_ACCEPTU2ENA (1 << 11) #define DWC3_DCTL_INITU1ENA (1 << 10) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 7913d1b50e38..2c4482f13a12 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1313,10 +1313,13 @@ static void dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) u32 timeout = 500; reg = dwc3_readl(dwc->regs, DWC3_DCTL); - if (is_on) - reg |= DWC3_DCTL_RUN_STOP; - else + if (is_on) { + reg &= ~DWC3_DCTL_TRGTULST_MASK; + reg |= (DWC3_DCTL_RUN_STOP + | DWC3_DCTL_TRGTULST_RX_DET); + } else { reg &= ~DWC3_DCTL_RUN_STOP; + } dwc3_writel(dwc->regs, DWC3_DCTL, reg); From 45b3cd4ad79b31289aa7da7a6448ec5afb7780a4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 25 Jan 2012 11:07:03 +0200 Subject: [PATCH 061/269] usb: dwc3: omap: convert pdata to of property Convert our platform_data usage to OF property, keep the legacy pdata for a while until the complete conversion is done. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 3274ac8f1200..64e29c31df22 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include "core.h" @@ -197,14 +198,18 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) static int __devinit dwc3_omap_probe(struct platform_device *pdev) { struct dwc3_omap_data *pdata = pdev->dev.platform_data; + struct device_node *node = pdev->dev.of_node; + struct platform_device *dwc3; struct dwc3_omap *omap; struct resource *res; int devid; + int size; int ret = -ENOMEM; int irq; + const u32 *utmi_mode; u32 reg; void __iomem *base; @@ -269,19 +274,24 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) reg = dwc3_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS); - if (!pdata) { - dev_dbg(&pdev->dev, "missing platform data\n"); + utmi_mode = of_get_property(node, "utmi-mode", &size); + if (utmi_mode && size == sizeof(*utmi_mode)) { + reg |= *utmi_mode; } else { - switch (pdata->utmi_mode) { - case DWC3_OMAP_UTMI_MODE_SW: - reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; - break; - case DWC3_OMAP_UTMI_MODE_HW: - reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; - break; - default: - dev_dbg(&pdev->dev, "UNKNOWN utmi mode %d\n", - pdata->utmi_mode); + if (!pdata) { + dev_dbg(&pdev->dev, "missing platform data\n"); + } else { + switch (pdata->utmi_mode) { + case DWC3_OMAP_UTMI_MODE_SW: + reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; + break; + case DWC3_OMAP_UTMI_MODE_HW: + reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; + break; + default: + dev_dbg(&pdev->dev, "UNKNOWN utmi mode %d\n", + pdata->utmi_mode); + } } } From 3d4c0d4ffb418800b2d1af111f9e1d5b204ee55c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 31 Jan 2012 13:33:32 +0200 Subject: [PATCH 062/269] usb: dwc3: debugfs: fix error check debugfs APIs will return NULL if it fails to create the file/directory we ask it to create. Instead of checking for IS_ERR(ptr) we must check for !ptr. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debugfs.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index a2c1cc64b48d..78ec092db5eb 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -659,8 +659,8 @@ int __devinit dwc3_debugfs_init(struct dwc3 *dwc) int ret; root = debugfs_create_dir(dev_name(dwc->dev), NULL); - if (IS_ERR(root)) { - ret = PTR_ERR(root); + if (!root) { + ret = -ENOMEM; goto err0; } @@ -668,29 +668,29 @@ int __devinit dwc3_debugfs_init(struct dwc3 *dwc) file = debugfs_create_file("regdump", S_IRUGO, root, dwc, &dwc3_regdump_fops); - if (IS_ERR(file)) { - ret = PTR_ERR(file); + if (!file) { + ret = -ENOMEM; goto err1; } file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, dwc, &dwc3_mode_fops); - if (IS_ERR(file)) { - ret = PTR_ERR(file); + if (!file) { + ret = -ENOMEM; goto err1; } file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, dwc, &dwc3_testmode_fops); - if (IS_ERR(file)) { - ret = PTR_ERR(file); + if (!file) { + ret = -ENOMEM; goto err1; } file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root, dwc, &dwc3_link_state_fops); - if (IS_ERR(file)) { - ret = PTR_ERR(file); + if (!file) { + ret = -ENOMEM; goto err1; } From 8b5d6b0a4353d0e3517947f894be215750d681bb Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 3 Feb 2012 15:04:46 +0200 Subject: [PATCH 063/269] usb: dwc3: host: align on host device name PCI uses xhci-hcd, so let's use the same device name to avoid confusion. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index 7cfe211b6c37..b108d18fd40d 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -53,7 +53,7 @@ int dwc3_host_init(struct dwc3 *dwc) struct platform_device *xhci; int ret; - xhci = platform_device_alloc("xhci", -1); + xhci = platform_device_alloc("xhci-hcd", -1); if (!xhci) { dev_err(dwc->dev, "couldn't allocate xHCI device\n"); ret = -ENOMEM; From d70d84423cbc5d6d929640189cf204e693024309 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 6 Feb 2012 13:40:17 +0200 Subject: [PATCH 064/269] usb: dwc3: gadget: avoid memcpy()ing event buffer We're only using the 4 byte events and memcpy() will make us slower. We can easily avoid that. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2c4482f13a12..1f64e7c1c34f 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2223,7 +2223,8 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) while (left > 0) { union dwc3_event event; - memcpy(&event.raw, (evt->buf + evt->lpos), sizeof(event.raw)); + event.raw = *(u32 *) (evt->buf + evt->lpos); + dwc3_process_event_entry(dwc, &event); /* * XXX we wrap around correctly to the next entry as almost all From 2e81c36a00d0eb8ce72faaaec1a1d865617374ae Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 2 Feb 2012 13:01:12 +0200 Subject: [PATCH 065/269] usb: dwc3: gadget: allocate 3 packets for bulk and isoc endpoints Those transfer types are generally high bandwidth, so we want to optimize transfers with those endpoints. For that, databook suggests allocating 3 * wMaxPacketSize of FIFO. Let's do that. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 1f64e7c1c34f..c30ab6da3d0e 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -172,6 +172,7 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc) for (num = 0; num < DWC3_ENDPOINTS_NUM; num++) { struct dwc3_ep *dep = dwc->eps[num]; int fifo_number = dep->number >> 1; + int mult = 1; int tmp; if (!(dep->number & 1)) @@ -180,11 +181,26 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc) if (!(dep->flags & DWC3_EP_ENABLED)) continue; - tmp = dep->endpoint.maxpacket; - tmp += mdwidth; + if (usb_endpoint_xfer_bulk(dep->desc) + || usb_endpoint_xfer_isoc(dep->desc)) + mult = 3; + + /* + * REVISIT: the following assumes we will always have enough + * space available on the FIFO RAM for all possible use cases. + * Make sure that's true somehow and change FIFO allocation + * accordingly. + * + * If we have Bulk or Isochronous endpoints, we want + * them to be able to be very, very fast. So we're giving + * those endpoints a fifo_size which is enough for 3 full + * packets + */ + tmp = mult * (dep->endpoint.maxpacket + mdwidth); tmp += mdwidth; fifo_size = DIV_ROUND_UP(tmp, mdwidth); + fifo_size |= (last_fifo_depth << 16); dev_vdbg(dwc->dev, "%s: Fifo Addr %04x Size %d\n", From de8c46bfc032fbdf490cfb67f534d2a0188ebeb0 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 10 Jan 2012 13:43:04 -0500 Subject: [PATCH 066/269] SCSI: fix typo in definition of struct scsi_target This patch (as1506) corrects a typo in the definition of the scsi_target structure. pdt_1f_for_no_lun is supposed to be a single-bit flag, not a full-sized integer. Signed-off-by: Alan Stern Cc: James Bottomley Signed-off-by: Greg Kroah-Hartman --- include/scsi/scsi_device.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 77273f2fdd80..01cb3c4cb74d 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -246,8 +246,8 @@ struct scsi_target { unsigned int single_lun:1; /* Indicates we should only * allow I/O to one of the luns * for the device at a time. */ - unsigned int pdt_1f_for_no_lun; /* PDT = 0x1f */ - /* means no lun present */ + unsigned int pdt_1f_for_no_lun:1; /* PDT = 0x1f + * means no lun present. */ /* commands actually active on LLD. protected by host lock. */ unsigned int target_busy; /* From 09b6b51b0b6c1b9bb61815baf205e4d74c89ff04 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 10 Jan 2012 13:43:30 -0500 Subject: [PATCH 067/269] SCSI & usb-storage: add flags for VPD pages and REPORT LUNS This patch (as1507) adds a skip_vpd_pages flag to struct scsi_device and a no_report_luns flag to struct scsi_target. The first is used to control whether sd will look at VPD pages for information on block provisioning, limits, and characteristics. The second prevents scsi_report_lun_scan() from issuing a REPORT LUNS command. The patch also modifies usb-storage to set the new flag bits for all USB devices and targets, and to stop adjusting the scsi_level value. Historically we have seen that USB mass-storage devices often don't support VPD pages or REPORT LUNS properly. Until now we have avoided these things by setting the scsi_level to SCSI_2 for all USB devices. But this has the side effect of storing the LUN bits into the second byte of each CDB, and now we have a report of a device which doesn't like that. The best solution is to stop abusing scsi_level and instead have separate flags for VPD pages and REPORT LUNS. Signed-off-by: Alan Stern Reported-by: Perry Wagle CC: Matthew Dharm Cc: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_scan.c | 4 ++++ drivers/scsi/sd.c | 2 +- drivers/usb/storage/scsiglue.c | 26 ++++++++++++++++---------- include/scsi/scsi_device.h | 3 +++ 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 89da43f73c00..fd37bfbfbcdb 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1295,6 +1295,7 @@ EXPORT_SYMBOL(int_to_scsilun); * LUNs even if it's older than SCSI-3. * If BLIST_NOREPORTLUN is set, return 1 always. * If BLIST_NOLUN is set, return 0 always. + * If starget->no_report_luns is set, return 1 always. * * Return: * 0: scan completed (or no memory, so further scanning is futile) @@ -1321,6 +1322,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set. * Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does * support more than 8 LUNs. + * Don't attempt if the target doesn't support REPORT LUNS. */ if (bflags & BLIST_NOREPORTLUN) return 1; @@ -1332,6 +1334,8 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, return 1; if (bflags & BLIST_NOLUN) return 0; + if (starget->no_report_luns) + return 1; if (!(sdev = scsi_device_lookup_by_target(starget, 0))) { sdev = scsi_alloc_sdev(starget, 0, NULL); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c691fb50e6cb..d173b90b25e9 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2349,7 +2349,7 @@ static int sd_try_extended_inquiry(struct scsi_device *sdp) * some USB ones crash on receiving them, and the pages * we currently ask for are for SPC-3 and beyond */ - if (sdp->scsi_level > SCSI_SPC_2) + if (sdp->scsi_level > SCSI_SPC_2 && !sdp->skip_vpd_pages) return 1; return 0; } diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 13b8bcdf3dba..dc68cc9fef5d 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -197,6 +197,9 @@ static int slave_configure(struct scsi_device *sdev) * page x08, so we will skip it. */ sdev->skip_ms_page_8 = 1; + /* Some devices don't handle VPD pages correctly */ + sdev->skip_vpd_pages = 1; + /* Some disks return the total number of blocks in response * to READ CAPACITY rather than the highest block number. * If this device makes that mistake, tell the sd driver. */ @@ -217,16 +220,6 @@ static int slave_configure(struct scsi_device *sdev) if (sdev->scsi_level > SCSI_SPC_2) us->fflags |= US_FL_SANE_SENSE; - /* Some devices report a SCSI revision level above 2 but are - * unable to handle the REPORT LUNS command (for which - * support is mandatory at level 3). Since we already have - * a Get-Max-LUN request, we won't lose much by setting the - * revision level down to 2. The only devices that would be - * affected are those with sparse LUNs. */ - if (sdev->scsi_level > SCSI_2) - sdev->sdev_target->scsi_level = - sdev->scsi_level = SCSI_2; - /* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable * Hardware Error) when any low-level error occurs, * recoverable or not. Setting this flag tells the SCSI @@ -283,6 +276,18 @@ static int slave_configure(struct scsi_device *sdev) return 0; } +static int target_alloc(struct scsi_target *starget) +{ + /* + * Some USB drives don't support REPORT LUNS, even though they + * report a SCSI revision level above 2. Tell the SCSI layer + * not to issue that command; it will perform a normal sequential + * scan instead. + */ + starget->no_report_luns = 1; + return 0; +} + /* queue a command */ /* This is always called with scsi_lock(host) held */ static int queuecommand_lck(struct scsi_cmnd *srb, @@ -546,6 +551,7 @@ struct scsi_host_template usb_stor_host_template = { .slave_alloc = slave_alloc, .slave_configure = slave_configure, + .target_alloc = target_alloc, /* lots of sg segments can be handled */ .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 01cb3c4cb74d..b3a1c2daf6cc 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -136,6 +136,7 @@ struct scsi_device { unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */ unsigned skip_ms_page_8:1; /* do not use MODE SENSE page 0x08 */ unsigned skip_ms_page_3f:1; /* do not use MODE SENSE page 0x3f */ + unsigned skip_vpd_pages:1; /* do not read VPD pages */ unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */ unsigned no_start_on_add:1; /* do not issue start on add */ unsigned allow_restart:1; /* issue START_UNIT in error handler */ @@ -248,6 +249,8 @@ struct scsi_target { * for the device at a time. */ unsigned int pdt_1f_for_no_lun:1; /* PDT = 0x1f * means no lun present. */ + unsigned int no_report_luns:1; /* Don't use + * REPORT LUNS for scanning. */ /* commands actually active on LLD. protected by host lock. */ unsigned int target_busy; /* From af74d2dae8f85a0e90a30594beb507f5d954fa3f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 10 Jan 2012 13:43:40 -0500 Subject: [PATCH 068/269] usb-storage: reorganize target-specific code Now that usb-storage has a target_alloc() routine, this patch (as1508) moves some existing target-specific code out of the slave_alloc() routine to where it really belongs. Signed-off-by: Alan Stern CC: Matthew Dharm Cc: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/scsiglue.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index dc68cc9fef5d..a324a5d21e99 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -78,8 +78,6 @@ static const char* host_info(struct Scsi_Host *host) static int slave_alloc (struct scsi_device *sdev) { - struct us_data *us = host_to_us(sdev->host); - /* * Set the INQUIRY transfer length to 36. We don't use any of * the extra data and many devices choke if asked for more or @@ -104,18 +102,6 @@ static int slave_alloc (struct scsi_device *sdev) */ blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1)); - /* - * The UFI spec treates the Peripheral Qualifier bits in an - * INQUIRY result as reserved and requires devices to set them - * to 0. However the SCSI spec requires these bits to be set - * to 3 to indicate when a LUN is not present. - * - * Let the scanning code know if this target merely sets - * Peripheral Device Type to 0x1f to indicate no LUN. - */ - if (us->subclass == USB_SC_UFI) - sdev->sdev_target->pdt_1f_for_no_lun = 1; - return 0; } @@ -278,6 +264,8 @@ static int slave_configure(struct scsi_device *sdev) static int target_alloc(struct scsi_target *starget) { + struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent)); + /* * Some USB drives don't support REPORT LUNS, even though they * report a SCSI revision level above 2. Tell the SCSI layer @@ -285,6 +273,19 @@ static int target_alloc(struct scsi_target *starget) * scan instead. */ starget->no_report_luns = 1; + + /* + * The UFI spec treats the Peripheral Qualifier bits in an + * INQUIRY result as reserved and requires devices to set them + * to 0. However the SCSI spec requires these bits to be set + * to 3 to indicate when a LUN is not present. + * + * Let the scanning code know if this target merely sets + * Peripheral Device Type to 0x1f to indicate no LUN. + */ + if (us->subclass == USB_SC_UFI) + starget->pdt_1f_for_no_lun = 1; + return 0; } From 3cf0ad02e42a91e85ffe9bd67422dd266531d3ec Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 25 Jan 2012 11:51:19 +0100 Subject: [PATCH 069/269] usb: gadget: dummy_hcd: don't assign ->desc on error case If the stream check fails then we leave ep->desc assigend but we return with an error code. The caller assumes the endpoint is not enabled (which is the case) but it can not enable it again due to this assigment. Signed-off-by: Sebastian Andrzej Siewior Acked-by: Alan Stern Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 67573e5f2a18..9170a4c7ced4 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -514,7 +514,6 @@ static int dummy_enable(struct usb_ep *_ep, } _ep->maxpacket = max; - ep->desc = desc; if (usb_ss_max_streams(_ep->comp_desc)) { if (!usb_endpoint_xfer_bulk(desc)) { dev_err(udc_dev(dum), "Can't enable stream support on " @@ -523,6 +522,7 @@ static int dummy_enable(struct usb_ep *_ep, } ep->stream_en = 1; } + ep->desc = desc; dev_dbg(udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d stream %s\n", _ep->name, From 20edfbb6a17f3007c1905e9849d8d306e318883b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 25 Jan 2012 15:18:58 +0100 Subject: [PATCH 070/269] usb: gadget: dummy_hcd: fix null-deref free req _ep to ep is a pointer substraction so ep won't be zero unless _ep was 8. This was not intendent by the author, it was probably a typo while checking for NULL of the argument. Signed-off-by: Sebastian Andrzej Siewior Acked-by: Alan Stern Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 9170a4c7ced4..8cc1a88d21e7 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -599,8 +599,10 @@ static void dummy_free_request(struct usb_ep *_ep, struct usb_request *_req) struct dummy_ep *ep; struct dummy_request *req; + if (!_ep || !_req) + return; ep = usb_ep_to_dummy_ep(_ep); - if (!ep || !_req || (!ep->desc && _ep->name != ep0name)) + if (!ep->desc && _ep->name != ep0name) return; req = usb_request_to_dummy_request(_req); From dd63180b758d5972fc90621af0741d5bfae1a684 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Fri, 3 Feb 2012 16:35:26 +0900 Subject: [PATCH 071/269] usb: gadget: pch_udc: Detecting VBUS through GPIO Problem: In USB Suspend, pch_udc handles 'disconnect'. Root cause: The current pch_udc is not monitoring VBUS. When USB cable is disconnected, USB Device Controller generates an interrupt of USB Suspend. pch_udc cannot distinguish it is USB Suspend or disconnect. Therefore, pch_udc handles 'disconnect' after an interrupt of USB Suspend happend. Solution: VBUS is detected through GPIO. After an interrupt produced USB Suspend, if VBUS is Low, pch_udc handles 'disconnect'. If VBUS is High, pch_udc handles 'suspend'. Signed-off-by: Tomoya MORINAGA Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 145 ++++++++++++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 82416aae816f..9c5ae2c10147 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -15,6 +15,13 @@ #include #include #include +#include + +/* GPIO port for VBUS detecting */ +static int vbus_gpio_port = -1; /* GPIO port number (-1:Not used) */ + +#define PCH_VBUS_PERIOD 3000 /* VBUS polling period (msec) */ +#define PCH_VBUS_INTERVAL 10 /* VBUS polling interval (msec) */ /* Address offset of Registers */ #define UDC_EP_REG_SHIFT 0x20 /* Offset to next EP */ @@ -295,6 +302,17 @@ struct pch_udc_ep { unsigned long epsts; }; +/** + * struct pch_vbus_gpio_data - Structure holding GPIO informaton + * for detecting VBUS + * @port: gpio port number + * @irq_work_fall Structure for WorkQueue + */ +struct pch_vbus_gpio_data { + int port; + struct work_struct irq_work_fall; +}; + /** * struct pch_udc_dev - Structure holding complete information * of the PCH USB device @@ -323,6 +341,7 @@ struct pch_udc_ep { * @base_addr: for mapped device memory * @irq: IRQ line for the device * @cfg_data: current cfg, intf, and alt in use + * @vbus_gpio: GPIO informaton for detecting VBUS */ struct pch_udc_dev { struct usb_gadget gadget; @@ -349,7 +368,8 @@ struct pch_udc_dev { unsigned long phys_addr; void __iomem *base_addr; unsigned irq; - struct pch_udc_cfg_data cfg_data; + struct pch_udc_cfg_data cfg_data; + struct pch_vbus_gpio_data vbus_gpio; }; #define PCH_UDC_PCI_BAR 1 @@ -1225,6 +1245,115 @@ static const struct usb_gadget_ops pch_udc_ops = { .stop = pch_udc_stop, }; +/** + * pch_vbus_gpio_get_value() - This API gets value of GPIO port as VBUS status. + * @dev: Reference to the driver structure + * + * Return value: + * 1: VBUS is high + * 0: VBUS is low + * -1: It is not enable to detect VBUS using GPIO + */ +static int pch_vbus_gpio_get_value(struct pch_udc_dev *dev) +{ + int vbus = 0; + + if (dev->vbus_gpio.port) + vbus = gpio_get_value(dev->vbus_gpio.port) ? 1 : 0; + else + vbus = -1; + + return vbus; +} + +/** + * pch_vbus_gpio_work_fall() - This API keeps watch on VBUS becoming Low. + * If VBUS is Low, disconnect is processed + * @irq_work: Structure for WorkQueue + * + */ +static void pch_vbus_gpio_work_fall(struct work_struct *irq_work) +{ + struct pch_vbus_gpio_data *vbus_gpio = container_of(irq_work, + struct pch_vbus_gpio_data, irq_work_fall); + struct pch_udc_dev *dev = + container_of(vbus_gpio, struct pch_udc_dev, vbus_gpio); + int vbus_saved = -1; + int vbus; + int count; + + if (!dev->vbus_gpio.port) + return; + + for (count = 0; count < (PCH_VBUS_PERIOD / PCH_VBUS_INTERVAL); + count++) { + vbus = pch_vbus_gpio_get_value(dev); + + if ((vbus_saved == vbus) && (vbus == 0)) { + dev_dbg(&dev->pdev->dev, "VBUS fell"); + if (dev->driver + && dev->driver->disconnect) { + dev->driver->disconnect( + &dev->gadget); + } + pch_udc_reconnect(dev); + dev_dbg(&dev->pdev->dev, "VBUS fell"); + return; + } + vbus_saved = vbus; + mdelay(PCH_VBUS_INTERVAL); + } +} + +/** + * pch_vbus_gpio_init() - This API initializes GPIO port detecting VBUS. + * @dev: Reference to the driver structure + * @vbus_gpio Number of GPIO port to detect gpio + * + * Return codes: + * 0: Success + * -EINVAL: GPIO port is invalid or can't be initialized. + */ +static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port) +{ + int err; + + dev->vbus_gpio.port = 0; + + if (vbus_gpio_port <= -1) + return -EINVAL; + + err = gpio_is_valid(vbus_gpio_port); + if (!err) { + pr_err("%s: gpio port %d is invalid\n", + __func__, vbus_gpio_port); + return -EINVAL; + } + + err = gpio_request(vbus_gpio_port, "pch_vbus"); + if (err) { + pr_err("%s: can't request gpio port %d, err: %d\n", + __func__, vbus_gpio_port, err); + return -EINVAL; + } + + dev->vbus_gpio.port = vbus_gpio_port; + gpio_direction_input(vbus_gpio_port); + INIT_WORK(&dev->vbus_gpio.irq_work_fall, pch_vbus_gpio_work_fall); + + return 0; +} + +/** + * pch_vbus_gpio_free() - This API frees resources of GPIO port + * @dev: Reference to the driver structure + */ +static void pch_vbus_gpio_free(struct pch_udc_dev *dev) +{ + if (dev->vbus_gpio.port) + gpio_free(dev->vbus_gpio.port); +} + /** * complete_req() - This API is invoked from the driver when processing * of a request is complete @@ -2510,6 +2639,8 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev) */ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr) { + int vbus; + /* USB Reset Interrupt */ if (dev_intr & UDC_DEVINT_UR) { pch_udc_svc_ur_interrupt(dev); @@ -2535,14 +2666,19 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr) spin_lock(&dev->lock); } - if (dev->vbus_session == 0) { + vbus = pch_vbus_gpio_get_value(dev); + if ((dev->vbus_session == 0) + && (vbus != 1)) { if (dev->driver && dev->driver->disconnect) { spin_unlock(&dev->lock); dev->driver->disconnect(&dev->gadget); spin_lock(&dev->lock); } pch_udc_reconnect(dev); - } + } else if ((dev->vbus_session == 0) + && (vbus == 1)) + schedule_work(&dev->vbus_gpio.irq_work_fall); + dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n"); } /* Clear the SOF interrupt, if enabled */ @@ -2704,6 +2840,7 @@ static int pch_udc_pcd_init(struct pch_udc_dev *dev) { pch_udc_init(dev); pch_udc_pcd_reinit(dev); + pch_vbus_gpio_init(dev, vbus_gpio_port); return 0; } @@ -2882,6 +3019,8 @@ static void pch_udc_remove(struct pci_dev *pdev) UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE); kfree(dev->ep0out_buf); + pch_vbus_gpio_free(dev); + pch_udc_exit(dev); if (dev->irq_registered) From 637b78eb31e0b167ed913f1750bb645dfeda38f0 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Fri, 3 Feb 2012 16:14:18 +0900 Subject: [PATCH 072/269] usb: gadget: pch_udc: Detecting VBUS through GPIO with interrupt Problem: pch_udc continues operation even if VBUS becomes Low. pch_udc performs D+ pulling up before VBUS becomes High. USB device should be controlled according to VBUS state. Root cause: The current pch_udc is not always monitoring VBUS. Solution: The change of VBUS is detected using an interrupt of GPIO. If VBUS became Low, pch_udc handles 'disconnect'. After VBUS became High, a pull improves D+, and pch_udc handles 'connect'. [ balbi@ti.com : make it actually compile ] Signed-off-by: Tomoya MORINAGA Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 87 ++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 9c5ae2c10147..a992084d3890 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -306,11 +306,15 @@ struct pch_udc_ep { * struct pch_vbus_gpio_data - Structure holding GPIO informaton * for detecting VBUS * @port: gpio port number + * @intr: gpio interrupt number * @irq_work_fall Structure for WorkQueue + * @irq_work_rise Structure for WorkQueue */ struct pch_vbus_gpio_data { int port; + int intr; struct work_struct irq_work_fall; + struct work_struct irq_work_rise; }; /** @@ -1296,8 +1300,10 @@ static void pch_vbus_gpio_work_fall(struct work_struct *irq_work) dev->driver->disconnect( &dev->gadget); } - pch_udc_reconnect(dev); - dev_dbg(&dev->pdev->dev, "VBUS fell"); + if (dev->vbus_gpio.intr) + pch_udc_init(dev); + else + pch_udc_reconnect(dev); return; } vbus_saved = vbus; @@ -1305,6 +1311,57 @@ static void pch_vbus_gpio_work_fall(struct work_struct *irq_work) } } +/** + * pch_vbus_gpio_work_rise() - This API checks VBUS is High. + * If VBUS is High, connect is processed + * @irq_work: Structure for WorkQueue + * + */ +static void pch_vbus_gpio_work_rise(struct work_struct *irq_work) +{ + struct pch_vbus_gpio_data *vbus_gpio = container_of(irq_work, + struct pch_vbus_gpio_data, irq_work_rise); + struct pch_udc_dev *dev = + container_of(vbus_gpio, struct pch_udc_dev, vbus_gpio); + int vbus; + + if (!dev->vbus_gpio.port) + return; + + mdelay(PCH_VBUS_INTERVAL); + vbus = pch_vbus_gpio_get_value(dev); + + if (vbus == 1) { + dev_dbg(&dev->pdev->dev, "VBUS rose"); + pch_udc_reconnect(dev); + return; + } +} + +/** + * pch_vbus_gpio_irq() - IRQ handler for GPIO intrerrupt for changing VBUS + * @irq: Interrupt request number + * @dev: Reference to the device structure + * + * Return codes: + * 0: Success + * -EINVAL: GPIO port is invalid or can't be initialized. + */ +static irqreturn_t pch_vbus_gpio_irq(int irq, void *data) +{ + struct pch_udc_dev *dev = (struct pch_udc_dev *)data; + + if (!dev->vbus_gpio.port || !dev->vbus_gpio.intr) + return IRQ_NONE; + + if (pch_vbus_gpio_get_value(dev)) + schedule_work(&dev->vbus_gpio.irq_work_rise); + else + schedule_work(&dev->vbus_gpio.irq_work_fall); + + return IRQ_HANDLED; +} + /** * pch_vbus_gpio_init() - This API initializes GPIO port detecting VBUS. * @dev: Reference to the driver structure @@ -1317,8 +1374,10 @@ static void pch_vbus_gpio_work_fall(struct work_struct *irq_work) static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port) { int err; + int irq_num = 0; dev->vbus_gpio.port = 0; + dev->vbus_gpio.intr = 0; if (vbus_gpio_port <= -1) return -EINVAL; @@ -1341,6 +1400,21 @@ static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port) gpio_direction_input(vbus_gpio_port); INIT_WORK(&dev->vbus_gpio.irq_work_fall, pch_vbus_gpio_work_fall); + irq_num = gpio_to_irq(vbus_gpio_port); + if (irq_num > 0) { + irq_set_irq_type(irq_num, IRQ_TYPE_EDGE_BOTH); + err = request_irq(irq_num, pch_vbus_gpio_irq, 0, + "vbus_detect", dev); + if (!err) { + dev->vbus_gpio.intr = irq_num; + INIT_WORK(&dev->vbus_gpio.irq_work_rise, + pch_vbus_gpio_work_rise); + } else { + pr_err("%s: can't request irq %d, err: %d\n", + __func__, irq_num, err); + } + } + return 0; } @@ -1350,6 +1424,9 @@ static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port) */ static void pch_vbus_gpio_free(struct pch_udc_dev *dev) { + if (dev->vbus_gpio.intr) + free_irq(dev->vbus_gpio.intr, dev); + if (dev->vbus_gpio.port) gpio_free(dev->vbus_gpio.port); } @@ -2676,7 +2753,8 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr) } pch_udc_reconnect(dev); } else if ((dev->vbus_session == 0) - && (vbus == 1)) + && (vbus == 1) + && !dev->vbus_gpio.intr) schedule_work(&dev->vbus_gpio.irq_work_fall); dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n"); @@ -2941,7 +3019,8 @@ static int pch_udc_start(struct usb_gadget_driver *driver, pch_udc_setup_ep0(dev); /* clear SD */ - pch_udc_clear_disconnect(dev); + if ((pch_vbus_gpio_get_value(dev) != 0) || !dev->vbus_gpio.intr) + pch_udc_clear_disconnect(dev); dev->connected = 1; return 0; From 609ca228073ae06c5513474d2cdf0af7ee5766ec Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 6 Feb 2012 18:46:35 +0100 Subject: [PATCH 073/269] usb: gadget: clean the ep in autoconf before returning it. Since commit 72c973dd aka ("usb: gadget: add usb_endpoint_descriptor to struct usb_ep) the descriptor is part of the ep. Most gadgets like g_zero or masstorage call config_ep_by_speed() to grab an available endpoint which may be used for FS/HS/SS bulk/iso/intr and in a second they assign the proper descriptor by calling config_ep_by_speed(). This is good so far. A few of them like ncm call config_ep_by_speed() only if ep->desc not assigned earlier. That means ep->desc is never assigned if the endpoint was used by another gadget before it was removed. Some of those gadgets also assign ep->driver_data to NULL on reset or ep_disable part _but_ keep a reference to this endpoint. At ep_enable time they assign driver_data to their private data. This probably needs a clean up of its own. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 753aa0683ac1..f59f7e367b5a 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -275,24 +275,24 @@ struct usb_ep *usb_ep_autoconfig_ss( /* ep-e, ep-f are PIO with only 64 byte fifos */ ep = find_ep (gadget, "ep-e"); if (ep && ep_matches(gadget, ep, desc, ep_comp)) - return ep; + goto found_ep; ep = find_ep (gadget, "ep-f"); if (ep && ep_matches(gadget, ep, desc, ep_comp)) - return ep; + goto found_ep; } else if (gadget_is_goku (gadget)) { if (USB_ENDPOINT_XFER_INT == type) { /* single buffering is enough */ ep = find_ep(gadget, "ep3-bulk"); if (ep && ep_matches(gadget, ep, desc, ep_comp)) - return ep; + goto found_ep; } else if (USB_ENDPOINT_XFER_BULK == type && (USB_DIR_IN & desc->bEndpointAddress)) { /* DMA may be available */ ep = find_ep(gadget, "ep2-bulk"); if (ep && ep_matches(gadget, ep, desc, ep_comp)) - return ep; + goto found_ep; } #ifdef CONFIG_BLACKFIN @@ -311,18 +311,22 @@ struct usb_ep *usb_ep_autoconfig_ss( } else ep = NULL; if (ep && ep_matches(gadget, ep, desc, ep_comp)) - return ep; + goto found_ep; #endif } /* Second, look at endpoints until an unclaimed one looks usable */ list_for_each_entry (ep, &gadget->ep_list, ep_list) { if (ep_matches(gadget, ep, desc, ep_comp)) - return ep; + goto found_ep; } /* Fail */ return NULL; +found_ep: + ep->desc = NULL; + ep->comp_desc = NULL; + return ep; } /** From 6fecfb05c077586ba85aa6f52f10abf30a4bfb40 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 6 Feb 2012 18:46:36 +0100 Subject: [PATCH 074/269] usb: gadget: add usb3.0 descriptors to serial gadgets This patch adds SS descriptors to the ACM & generic serial gadget. The ACM part was tested with minicom + dummy + send / receive files over ttyACM <=> ttyGS0. The generic serial part (f_serial) was not tested (haven't found a driver on the host side). The nokia & multi gadget use HS at most. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_acm.c | 50 +++++++++++++++++++++++++++++++++++ drivers/usb/gadget/f_serial.c | 42 +++++++++++++++++++++++++++++ drivers/usb/gadget/serial.c | 2 +- 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index e48212195466..d672250a61fa 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -237,6 +237,42 @@ static struct usb_descriptor_header *acm_hs_function[] = { NULL, }; +static struct usb_endpoint_descriptor acm_ss_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_endpoint_descriptor acm_ss_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor acm_ss_bulk_comp_desc = { + .bLength = sizeof acm_ss_bulk_comp_desc, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, +}; + +static struct usb_descriptor_header *acm_ss_function[] = { + (struct usb_descriptor_header *) &acm_iad_descriptor, + (struct usb_descriptor_header *) &acm_control_interface_desc, + (struct usb_descriptor_header *) &acm_header_desc, + (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, + (struct usb_descriptor_header *) &acm_descriptor, + (struct usb_descriptor_header *) &acm_union_desc, + (struct usb_descriptor_header *) &acm_hs_notify_desc, + (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc, + (struct usb_descriptor_header *) &acm_data_interface_desc, + (struct usb_descriptor_header *) &acm_ss_in_desc, + (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc, + (struct usb_descriptor_header *) &acm_ss_out_desc, + (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc, + NULL, +}; + /* string descriptors: */ #define ACM_CTRL_IDX 0 @@ -643,9 +679,21 @@ acm_bind(struct usb_configuration *c, struct usb_function *f) /* copy descriptors */ f->hs_descriptors = usb_copy_descriptors(acm_hs_function); } + if (gadget_is_superspeed(c->cdev->gadget)) { + acm_ss_in_desc.bEndpointAddress = + acm_fs_in_desc.bEndpointAddress; + acm_ss_out_desc.bEndpointAddress = + acm_fs_out_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->ss_descriptors = usb_copy_descriptors(acm_ss_function); + if (!f->ss_descriptors) + goto fail; + } DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n", acm->port_num, + gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", acm->port.in->name, acm->port.out->name, acm->notify->name); @@ -675,6 +723,8 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f) if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_descriptors(f->hs_descriptors); + if (gadget_is_superspeed(c->cdev->gadget)) + usb_free_descriptors(f->ss_descriptors); usb_free_descriptors(f->descriptors); gs_free_req(acm->notify, acm->notify_req); kfree(acm); diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index cf33a8d0fd5d..07197d63d9b1 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -99,6 +99,34 @@ static struct usb_descriptor_header *gser_hs_function[] __initdata = { NULL, }; +static struct usb_endpoint_descriptor gser_ss_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_endpoint_descriptor gser_ss_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc __initdata = { + .bLength = sizeof gser_ss_bulk_comp_desc, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, +}; + +static struct usb_descriptor_header *gser_ss_function[] __initdata = { + (struct usb_descriptor_header *) &gser_interface_desc, + (struct usb_descriptor_header *) &gser_ss_in_desc, + (struct usb_descriptor_header *) &gser_ss_bulk_comp_desc, + (struct usb_descriptor_header *) &gser_ss_out_desc, + (struct usb_descriptor_header *) &gser_ss_bulk_comp_desc, + NULL, +}; + /* string descriptors: */ static struct usb_string gser_string_defs[] = { @@ -201,9 +229,21 @@ gser_bind(struct usb_configuration *c, struct usb_function *f) /* copy descriptors, and track endpoint copies */ f->hs_descriptors = usb_copy_descriptors(gser_hs_function); } + if (gadget_is_superspeed(c->cdev->gadget)) { + gser_ss_in_desc.bEndpointAddress = + gser_fs_in_desc.bEndpointAddress; + gser_ss_out_desc.bEndpointAddress = + gser_fs_out_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->ss_descriptors = usb_copy_descriptors(gser_ss_function); + if (!f->ss_descriptors) + goto fail; + } DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n", gser->port_num, + gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", gser->port.in->name, gser->port.out->name); return 0; @@ -225,6 +265,8 @@ gser_unbind(struct usb_configuration *c, struct usb_function *f) { if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_descriptors(f->hs_descriptors); + if (gadget_is_superspeed(c->cdev->gadget)) + usb_free_descriptors(f->ss_descriptors); usb_free_descriptors(f->descriptors); kfree(func_to_gser(f)); } diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index ad9e5b2df642..665c07422c26 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -242,7 +242,7 @@ static struct usb_composite_driver gserial_driver = { .name = "g_serial", .dev = &device_desc, .strings = dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, }; static int __init init(void) From 0846e7e9856c0928223447d9349a877202a63f24 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Fri, 3 Feb 2012 17:11:54 -0500 Subject: [PATCH 075/269] usb: Add support for indicating whether a port is removable Userspace may want to make policy decisions based on whether or not a given USB device is removable. Add a per-device member and support for exposing it in sysfs. Information sources to populate it will be added later. Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-bus-usb | 11 +++++++++++ drivers/usb/core/sysfs.c | 23 +++++++++++++++++++++++ include/linux/usb.h | 8 ++++++++ 3 files changed, 42 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index b4f548792e32..7c22a532fdfb 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -182,3 +182,14 @@ Description: USB2 hardware LPM is enabled for the device. Developer can write y/Y/1 or n/N/0 to the file to enable/disable the feature. + +What: /sys/bus/usb/devices/.../removable +Date: February 2012 +Contact: Matthew Garrett +Description: + Some information about whether a given USB device is + physically fixed to the platform can be inferred from a + combination of hub decriptor bits and platform-specific data + such as ACPI. This file will read either "removable" or + "fixed" if the information is available, and "unknown" + otherwise. \ No newline at end of file diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 9e491ca2e5c4..566d9f94f735 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -230,6 +230,28 @@ show_urbnum(struct device *dev, struct device_attribute *attr, char *buf) } static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL); +static ssize_t +show_removable(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct usb_device *udev; + char *state; + + udev = to_usb_device(dev); + + switch (udev->removable) { + case USB_DEVICE_REMOVABLE: + state = "removable"; + break; + case USB_DEVICE_FIXED: + state = "fixed"; + break; + default: + state = "unknown"; + } + + return sprintf(buf, "%s\n", state); +} +static DEVICE_ATTR(removable, S_IRUGO, show_removable, NULL); #ifdef CONFIG_PM @@ -626,6 +648,7 @@ static struct attribute *dev_attrs[] = { &dev_attr_avoid_reset_quirk.attr, &dev_attr_authorized.attr, &dev_attr_remove.attr, + &dev_attr_removable.attr, NULL, }; static struct attribute_group dev_attr_grp = { diff --git a/include/linux/usb.h b/include/linux/usb.h index 27a4e16d2bf1..b2eb3a47caf5 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -376,6 +376,12 @@ struct usb_bus { struct usb_tt; +enum usb_device_removable { + USB_DEVICE_REMOVABLE_UNKNOWN = 0, + USB_DEVICE_REMOVABLE, + USB_DEVICE_FIXED, +}; + /** * struct usb_device - kernel's representation of a USB device * @devnum: device number; address on a USB bus @@ -432,6 +438,7 @@ struct usb_tt; * @wusb_dev: if this is a Wireless USB device, link to the WUSB * specific data for the device. * @slot_id: Slot ID assigned by xHCI + * @removable: Device can be physically removed from this port * * Notes: * Usbcore drivers should not set usbdev->state directly. Instead use @@ -509,6 +516,7 @@ struct usb_device { #endif struct wusb_dev *wusb_dev; int slot_id; + enum usb_device_removable removable; }; #define to_usb_device(d) container_of(d, struct usb_device, dev) From d35e70d50a0641ebc1502fd343bef9b4011ada27 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Fri, 3 Feb 2012 17:11:55 -0500 Subject: [PATCH 076/269] usb: Use hub port data to determine whether a port is removable Hubs have a flag to indicate whether a given port carries removable devices or not. This is not strictly accurate in that some built-in devices will be flagged as removable, but followup patches will make use of platform data to make this more reliable. Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a0613d8f9be7..2d773cbe191c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1838,6 +1838,37 @@ fail: return err; } +static void set_usb_port_removable(struct usb_device *udev) +{ + struct usb_device *hdev = udev->parent; + struct usb_hub *hub; + u8 port = udev->portnum; + u16 wHubCharacteristics; + bool removable = true; + + if (!hdev) + return; + + hub = hdev_to_hub(udev->parent); + + wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); + + if (!(wHubCharacteristics & HUB_CHAR_COMPOUND)) + return; + + if (hub_is_superspeed(hdev)) { + if (hub->descriptor->u.ss.DeviceRemovable & (1 << port)) + removable = false; + } else { + if (hub->descriptor->u.hs.DeviceRemovable[port / 8] & (1 << (port % 8))) + removable = false; + } + + if (removable) + udev->removable = USB_DEVICE_REMOVABLE; + else + udev->removable = USB_DEVICE_FIXED; +} /** * usb_new_device - perform initial device setup (usbcore-internal) @@ -1896,6 +1927,15 @@ int usb_new_device(struct usb_device *udev) announce_device(udev); device_enable_async_suspend(&udev->dev); + + /* + * check whether the hub marks this port as non-removable. Do it + * now so that platform-specific data can override it in + * device_add() + */ + if (udev->parent) + set_usb_port_removable(udev); + /* Register the device. The device driver is responsible * for configuring the device and invoking the add-device * notifier chain (used by usbfs and possibly others). From e688355bfeadf17ef522b1e62cc12f8e88e69667 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Feb 2012 19:22:19 +0100 Subject: [PATCH 077/269] USB: serial: add macro for console error reporting Add macro which prints an error message only once if port is used a console. Reporting errors in a write path when port is used as a console could otherwise result in an infinite loop. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/serial.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 4267a9c717ba..10cb74d2ad1d 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -389,5 +389,20 @@ do { \ printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \ } while (0) +/* + * Macro for reporting errors in write path to avoid inifinite loop + * when port is used as a console. + */ +#define dev_err_console(usport, fmt, ...) \ +do { \ + static bool __print_once; \ + struct usb_serial_port *__port = (usport); \ + \ + if (!__port->port.console || !__print_once) { \ + __print_once = true; \ + dev_err(&__port->dev, fmt, ##__VA_ARGS__); \ + } \ +} while (0) + #endif /* __LINUX_USB_SERIAL_H */ From 090725431b9636a0a59516ff0fe94933cf09a82b Mon Sep 17 00:00:00 2001 From: Gerard Cauvy Date: Fri, 10 Feb 2012 12:14:53 +0200 Subject: [PATCH 078/269] usb: dwc3: debugfs: fix off by one when entering testmode When implementing the USB2 testmode support via debugfs, Felipe has committed a mistake when counting the number of letters of some of the strings, resulting on an off by one error which prevented some of the Test modes to be entered properly. This patch, fixes that mistake. Signed-off-by: Gerard Cauvy Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debugfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 78ec092db5eb..d4a30f118724 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -525,11 +525,11 @@ static ssize_t dwc3_testmode_write(struct file *file, testmode = TEST_J; else if (!strncmp(buf, "test_k", 6)) testmode = TEST_K; - else if (!strncmp(buf, "test_se0_nak", 13)) + else if (!strncmp(buf, "test_se0_nak", 12)) testmode = TEST_SE0_NAK; - else if (!strncmp(buf, "test_packet", 12)) + else if (!strncmp(buf, "test_packet", 11)) testmode = TEST_PACKET; - else if (!strncmp(buf, "test_force_enable", 18)) + else if (!strncmp(buf, "test_force_enable", 17)) testmode = TEST_FORCE_EN; else testmode = 0; From 3b637367ae40b6d3c20e30cb0cdd059e67bbf848 Mon Sep 17 00:00:00 2001 From: Gerard Cauvy Date: Fri, 10 Feb 2012 12:21:18 +0200 Subject: [PATCH 079/269] usb: dwc3: ep0: fix SetFeature(TEST) When host requests us to enter a test mode, we cannot directly enter the test mode before Status Phase is completed, otherwise the core will never be able to deliver the Status ZLP to host, because it has already entered the requested Test Mode. In order to fix the error, we move the actual start of Test Mode right after we receive Transfer Complete event of the status phase. Signed-off-by: Gerard Cauvy Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 3 +++ drivers/usb/dwc3/ep0.c | 21 +++++++++++++-------- drivers/usb/dwc3/gadget.c | 1 + 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 71d958af2393..4dac9828577e 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -684,6 +684,9 @@ struct dwc3 { struct dwc3_hwparams hwparams; struct dentry *root; + + u8 test_mode; + u8 test_mode_nr; }; /* -------------------------------------------------------------------------- */ diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 5104dbf46680..c20e30c8b695 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -316,7 +316,6 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, u32 wValue; u32 wIndex; int ret; - u32 mode; wValue = le16_to_cpu(ctrl->wValue); wIndex = le16_to_cpu(ctrl->wIndex); @@ -355,13 +354,8 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, if (!set) return -EINVAL; - mode = wIndex >> 8; - ret = dwc3_gadget_set_test_mode(dwc, mode); - if (ret < 0) { - dev_dbg(dwc->dev, "Invalid Test #%d\n", - mode); - return ret; - } + dwc->test_mode_nr = wIndex >> 8; + dwc->test_mode = true; } break; @@ -604,6 +598,17 @@ static void dwc3_ep0_complete_req(struct dwc3 *dwc, dwc3_gadget_giveback(dep, r, 0); } + if (dwc->test_mode) { + int ret; + + ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr); + if (ret < 0) { + dev_dbg(dwc->dev, "Invalid Test #%d\n", + dwc->test_mode_nr); + dwc3_ep0_stall_and_restart(dwc); + } + } + dwc->ep0state = EP0_SETUP_PHASE; dwc3_ep0_out_start(dwc); } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c30ab6da3d0e..76327005d54c 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1962,6 +1962,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg &= ~DWC3_DCTL_TSTCTRL_MASK; dwc3_writel(dwc->regs, DWC3_DCTL, reg); + dwc->test_mode = false; dwc3_stop_active_transfers(dwc); dwc3_clear_stall_all_ep(dwc); From 548dd4b6da8a8e428453d55f7fa7b8a46498d147 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Feb 2012 13:20:49 +0100 Subject: [PATCH 080/269] USB: serial: fix console error reporting Do not report errors in write path if port is used as a console as this may trigger the same error (and error report) resulting in a loop. Reported-by: Stephen Hemminger Cc: stable Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index f7403576f99f..e129fcd69fd9 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -217,8 +217,10 @@ retry: clear_bit(i, &port->write_urbs_free); result = usb_submit_urb(urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, "%s - error submitting urb: %d\n", + if (!port->port.console) { + dev_err(&port->dev, "%s - error submitting urb: %d\n", __func__, result); + } set_bit(i, &port->write_urbs_free); spin_lock_irqsave(&port->lock, flags); port->tx_bytes -= count; From f1475a00a11b07e6ac7f97971466c1bfbf491957 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Feb 2012 13:20:50 +0100 Subject: [PATCH 081/269] USB: serial: use dev_err_console in generic write Use dev_err_console in write path so that an error at least gets reported once. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index e129fcd69fd9..2a2fa2d0489d 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -217,10 +217,8 @@ retry: clear_bit(i, &port->write_urbs_free); result = usb_submit_urb(urb, GFP_ATOMIC); if (result) { - if (!port->port.console) { - dev_err(&port->dev, "%s - error submitting urb: %d\n", + dev_err_console(port, "%s - error submitting urb: %d\n", __func__, result); - } set_bit(i, &port->write_urbs_free); spin_lock_irqsave(&port->lock, flags); port->tx_bytes -= count; From 22a416c4e0f2179b57028e084ac0ed2c110333bd Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 10 Feb 2012 13:20:51 +0100 Subject: [PATCH 082/269] USB: serial: use dev_err_console in custom write paths Use dev_err_console in write paths for devices which can be used as a console but do not use the generic write implementation. Compile-only tested. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cypress_m8.c | 2 +- drivers/usb/serial/digi_acceleport.c | 4 ++-- drivers/usb/serial/io_edgeport.c | 4 ++-- drivers/usb/serial/io_ti.c | 4 ++-- drivers/usb/serial/mos7720.c | 4 ++-- drivers/usb/serial/mos7840.c | 4 ++-- drivers/usb/serial/omninet.c | 2 +- drivers/usb/serial/oti6858.c | 6 +++--- drivers/usb/serial/ti_usb_3410_5052.c | 5 ++--- drivers/usb/serial/whiteheat.c | 2 +- 10 files changed, 18 insertions(+), 19 deletions(-) diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 3bdeafa29c24..5ae86b349cad 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -800,7 +800,7 @@ send: cypress_write_int_callback, port, priv->write_urb_interval); result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, + dev_err_console(port, "%s - failed submitting write urb, error %d\n", __func__, result); priv->write_urb_in_use = 0; diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index b23bebd721a1..2b1da0cc071a 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -995,7 +995,7 @@ static int digi_write(struct tty_struct *tty, struct usb_serial_port *port, /* return length of new data written, or error */ spin_unlock_irqrestore(&priv->dp_port_lock, flags); if (ret < 0) - dev_err(&port->dev, + dev_err_console(port, "%s: usb_submit_urb failed, ret=%d, port=%d\n", __func__, ret, priv->dp_port_num); dbg("digi_write: returning %d", ret); @@ -1065,7 +1065,7 @@ static void digi_write_bulk_callback(struct urb *urb) spin_unlock(&priv->dp_port_lock); if (ret && ret != -EPERM) - dev_err(&port->dev, + dev_err_console(port, "%s: usb_submit_urb failed, ret=%d, port=%d\n", __func__, ret, priv->dp_port_num); } diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 0497575e4799..616b07862771 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -1286,7 +1286,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, count = fifo->count; buffer = kmalloc(count+2, GFP_ATOMIC); if (buffer == NULL) { - dev_err(&edge_port->port->dev, + dev_err_console(edge_port->port, "%s - no more kernel memory...\n", __func__); edge_port->write_in_progress = false; goto exit_send; @@ -1331,7 +1331,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { /* something went wrong */ - dev_err(&edge_port->port->dev, + dev_err_console(edge_port->port, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __func__, status); edge_port->write_in_progress = false; diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 65bf06aa591a..311e4bf46dee 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -1817,7 +1817,7 @@ static void edge_bulk_out_callback(struct urb *urb) __func__, status); return; default: - dev_err(&urb->dev->dev, "%s - nonzero write bulk status " + dev_err_console(port, "%s - nonzero write bulk status " "received: %d\n", __func__, status); } @@ -2111,7 +2111,7 @@ static void edge_send(struct tty_struct *tty) /* send the data out the bulk port */ result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, + dev_err_console(port, "%s - failed submitting write urb, error %d\n", __func__, result); edge_port->ep_write_urb_in_use = 0; diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 4554ee49e635..4fb29b4aaad6 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1294,7 +1294,7 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port, urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); if (urb->transfer_buffer == NULL) { - dev_err(&port->dev, "%s no more kernel memory...\n", + dev_err_console(port, "%s no more kernel memory...\n", __func__); goto exit; } @@ -1315,7 +1315,7 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port, /* send it down the pipe */ status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { - dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " + dev_err_console(port, "%s - usb_submit_urb(write bulk) failed " "with status = %d\n", __func__, status); bytes_sent = status; goto exit; diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 03b5e249e95e..19b11cece6ba 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1509,7 +1509,7 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); if (urb->transfer_buffer == NULL) { - dev_err(&port->dev, "%s no more kernel memory...\n", + dev_err_console(port, "%s no more kernel memory...\n", __func__); goto exit; } @@ -1535,7 +1535,7 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, if (status) { mos7840_port->busy[i] = 0; - dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " + dev_err_console(port, "%s - usb_submit_urb(write bulk) failed " "with status = %d\n", __func__, status); bytes_sent = status; goto exit; diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 8b8d58a2ac12..033e8afa6c77 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -254,7 +254,7 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, result = usb_submit_urb(wport->write_urb, GFP_ATOMIC); if (result) { set_bit(0, &wport->write_urbs_free); - dev_err(&port->dev, + dev_err_console(port, "%s - failed submitting write urb, error %d\n", __func__, result); } else diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index e287fd32682c..343e626a06f8 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -302,7 +302,7 @@ static void send_data(struct work_struct *work) if (count != 0) { allow = kmalloc(1, GFP_KERNEL); if (!allow) { - dev_err(&port->dev, "%s(): kmalloc failed\n", + dev_err_console(port, "%s(): kmalloc failed\n", __func__); return; } @@ -334,7 +334,7 @@ static void send_data(struct work_struct *work) port->write_urb->transfer_buffer_length = count; result = usb_submit_urb(port->write_urb, GFP_NOIO); if (result != 0) { - dev_err(&port->dev, "%s(): usb_submit_urb() failed" + dev_err_console(port, "%s(): usb_submit_urb() failed" " with error %d\n", __func__, result); priv->flags.write_urb_in_use = 0; } @@ -938,7 +938,7 @@ static void oti6858_write_bulk_callback(struct urb *urb) port->write_urb->transfer_buffer_length = 1; result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, "%s(): usb_submit_urb() failed," + dev_err_console(port, "%s(): usb_submit_urb() failed," " error %d\n", __func__, result); } else { return; diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 8468eb769a29..91d0dc640360 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -1248,7 +1248,6 @@ static void ti_bulk_out_callback(struct urb *urb) { struct ti_port *tport = urb->context; struct usb_serial_port *port = tport->tp_port; - struct device *dev = &urb->dev->dev; int status = urb->status; dbg("%s - port %d", __func__, port->number); @@ -1266,7 +1265,7 @@ static void ti_bulk_out_callback(struct urb *urb) wake_up_interruptible(&tport->tp_write_wait); return; default: - dev_err(dev, "%s - nonzero urb status, %d\n", + dev_err_console(port, "%s - nonzero urb status, %d\n", __func__, status); tport->tp_tdev->td_urb_error = 1; wake_up_interruptible(&tport->tp_write_wait); @@ -1335,7 +1334,7 @@ static void ti_send(struct ti_port *tport) result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, "%s - submit write urb failed, %d\n", + dev_err_console(port, "%s - submit write urb failed, %d\n", __func__, result); tport->tp_write_urb_in_use = 0; /* TODO: reschedule ti_send */ diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 7e0acf5c8e38..007cf3a2481a 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -740,7 +740,7 @@ static int whiteheat_write(struct tty_struct *tty, urb->transfer_buffer_length = bytes; result = usb_submit_urb(urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, + dev_err_console(port, "%s - failed submitting write urb, error %d\n", __func__, result); sent = result; From 88044202756925ad47c51c2f634a4f2c17afe068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 10 Feb 2012 09:44:08 +0100 Subject: [PATCH 083/269] usb: cdc-wdm: make reset work with blocking IO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a flag to tell wdm_read/wdm_write that a reset is in progress, and wake any blocking read/write before taking the mutexes. This allows the device to reset without waiting for blocking IO to finish. Signed-off-by: Bjørn Mork Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index f63601a2054c..b27bbb957e16 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -70,6 +70,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); #define WDM_POLL_RUNNING 6 #define WDM_RESPONDING 7 #define WDM_SUSPENDING 8 +#define WDM_RESETTING 9 #define WDM_MAX 16 @@ -340,6 +341,10 @@ static ssize_t wdm_write else if (test_bit(WDM_IN_USE, &desc->flags)) r = -EAGAIN; + + if (test_bit(WDM_RESETTING, &desc->flags)) + r = -EIO; + if (r < 0) { kfree(buf); goto out; @@ -419,6 +424,10 @@ retry: rv = -ENODEV; goto err; } + if (test_bit(WDM_RESETTING, &desc->flags)) { + rv = -EIO; + goto err; + } usb_mark_last_busy(interface_to_usbdev(desc->intf)); if (rv < 0) { rv = -ERESTARTSYS; @@ -859,10 +868,6 @@ static int wdm_pre_reset(struct usb_interface *intf) { struct wdm_device *desc = usb_get_intfdata(intf); - mutex_lock(&desc->rlock); - mutex_lock(&desc->wlock); - kill_urbs(desc); - /* * we notify everybody using poll of * an exceptional situation @@ -870,9 +875,16 @@ static int wdm_pre_reset(struct usb_interface *intf) * message from the device is lost */ spin_lock_irq(&desc->iuspin); + set_bit(WDM_RESETTING, &desc->flags); /* inform read/write */ + set_bit(WDM_READ, &desc->flags); /* unblock read */ + clear_bit(WDM_IN_USE, &desc->flags); /* unblock write */ desc->rerr = -EINTR; spin_unlock_irq(&desc->iuspin); wake_up_all(&desc->wait); + mutex_lock(&desc->rlock); + mutex_lock(&desc->wlock); + kill_urbs(desc); + cancel_work_sync(&desc->rxwork); return 0; } @@ -881,6 +893,7 @@ static int wdm_post_reset(struct usb_interface *intf) struct wdm_device *desc = usb_get_intfdata(intf); int rv; + clear_bit(WDM_RESETTING, &desc->flags); rv = recover_from_urb_loss(desc); mutex_unlock(&desc->wlock); mutex_unlock(&desc->rlock); From 8675381109b0eb1c948a423c2b35e3f4509cb25e Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:02 +0200 Subject: [PATCH 084/269] usb: otg: Rename otg_transceiver to usb_phy This is the first step in separating USB transceivers from USB OTG utilities. Includes fixes to IMX code from Sascha Hauer. Signed-off-by: Heikki Krogerus Acked-by: Sascha Hauer Acked-by: Pavankumar Kondeti Acked-by: Li Yang Acked-by: Alan Stern Acked-by: Igor Grinberg Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- arch/arm/mach-imx/mx31moboard-devboard.c | 6 +- arch/arm/mach-imx/mx31moboard-marxbot.c | 6 +- arch/arm/mach-pxa/pxa3xx-ulpi.c | 6 +- arch/arm/mach-tegra/include/mach/usb_phy.h | 2 +- arch/arm/plat-mxc/include/mach/mxc_ehci.h | 2 +- arch/arm/plat-mxc/include/mach/ulpi.h | 4 +- arch/arm/plat-mxc/ulpi.c | 6 +- drivers/power/isp1704_charger.c | 2 +- drivers/power/pda_power.c | 2 +- drivers/power/twl4030_charger.c | 2 +- drivers/usb/gadget/ci13xxx_udc.h | 2 +- drivers/usb/gadget/fsl_usb2_udc.h | 2 +- drivers/usb/gadget/langwell_udc.h | 2 +- drivers/usb/gadget/mv_udc.h | 2 +- drivers/usb/gadget/omap_udc.c | 4 +- drivers/usb/gadget/omap_udc.h | 2 +- drivers/usb/gadget/pxa25x_udc.h | 2 +- drivers/usb/gadget/pxa27x_udc.h | 2 +- drivers/usb/gadget/s3c-hsudc.c | 2 +- drivers/usb/host/ehci-msm.c | 2 +- drivers/usb/host/ehci-mv.c | 2 +- drivers/usb/host/ehci-tegra.c | 2 +- drivers/usb/host/ehci.h | 2 +- drivers/usb/host/ohci.h | 2 +- drivers/usb/musb/blackfin.c | 2 +- drivers/usb/musb/musb_core.c | 4 +- drivers/usb/musb/musb_core.h | 2 +- drivers/usb/musb/tusb6010.c | 2 +- drivers/usb/otg/Kconfig | 2 +- drivers/usb/otg/ab8500-usb.c | 12 +-- drivers/usb/otg/fsl_otg.c | 18 ++-- drivers/usb/otg/fsl_otg.h | 2 +- drivers/usb/otg/gpio_vbus.c | 8 +- drivers/usb/otg/isp1301_omap.c | 12 +-- drivers/usb/otg/msm_otg.c | 54 ++++++------ drivers/usb/otg/mv_otg.c | 14 ++-- drivers/usb/otg/mv_otg.h | 2 +- drivers/usb/otg/nop-usb-xceiv.c | 10 +-- drivers/usb/otg/otg.c | 8 +- drivers/usb/otg/otg_fsm.h | 2 +- drivers/usb/otg/twl4030-usb.c | 8 +- drivers/usb/otg/twl6030-usb.c | 18 ++-- drivers/usb/otg/ulpi.c | 20 ++--- drivers/usb/otg/ulpi_viewport.c | 4 +- include/linux/usb/intel_mid_otg.h | 6 +- include/linux/usb/msm_hsusb.h | 2 +- include/linux/usb/otg.h | 98 +++++++++++----------- include/linux/usb/ulpi.h | 2 +- 48 files changed, 190 insertions(+), 190 deletions(-) diff --git a/arch/arm/mach-imx/mx31moboard-devboard.c b/arch/arm/mach-imx/mx31moboard-devboard.c index 0aa25364360d..9cd4a97efa52 100644 --- a/arch/arm/mach-imx/mx31moboard-devboard.c +++ b/arch/arm/mach-imx/mx31moboard-devboard.c @@ -158,7 +158,7 @@ static int devboard_usbh1_hw_init(struct platform_device *pdev) #define USBH1_VBUSEN_B IOMUX_TO_GPIO(MX31_PIN_NFRE_B) #define USBH1_MODE IOMUX_TO_GPIO(MX31_PIN_NFALE) -static int devboard_isp1105_init(struct otg_transceiver *otg) +static int devboard_isp1105_init(struct usb_phy *otg) { int ret = gpio_request(USBH1_MODE, "usbh1-mode"); if (ret) @@ -177,7 +177,7 @@ static int devboard_isp1105_init(struct otg_transceiver *otg) } -static int devboard_isp1105_set_vbus(struct otg_transceiver *otg, bool on) +static int devboard_isp1105_set_vbus(struct usb_phy *otg, bool on) { if (on) gpio_set_value(USBH1_VBUSEN_B, 0); @@ -194,7 +194,7 @@ static struct mxc_usbh_platform_data usbh1_pdata __initdata = { static int __init devboard_usbh1_init(void) { - struct otg_transceiver *otg; + struct usb_phy *otg; struct platform_device *pdev; otg = kzalloc(sizeof(*otg), GFP_KERNEL); diff --git a/arch/arm/mach-imx/mx31moboard-marxbot.c b/arch/arm/mach-imx/mx31moboard-marxbot.c index bb639cbda4e5..2be769bbe05e 100644 --- a/arch/arm/mach-imx/mx31moboard-marxbot.c +++ b/arch/arm/mach-imx/mx31moboard-marxbot.c @@ -272,7 +272,7 @@ static int marxbot_usbh1_hw_init(struct platform_device *pdev) #define USBH1_VBUSEN_B IOMUX_TO_GPIO(MX31_PIN_NFRE_B) #define USBH1_MODE IOMUX_TO_GPIO(MX31_PIN_NFALE) -static int marxbot_isp1105_init(struct otg_transceiver *otg) +static int marxbot_isp1105_init(struct usb_phy *otg) { int ret = gpio_request(USBH1_MODE, "usbh1-mode"); if (ret) @@ -291,7 +291,7 @@ static int marxbot_isp1105_init(struct otg_transceiver *otg) } -static int marxbot_isp1105_set_vbus(struct otg_transceiver *otg, bool on) +static int marxbot_isp1105_set_vbus(struct usb_phy *otg, bool on) { if (on) gpio_set_value(USBH1_VBUSEN_B, 0); @@ -308,7 +308,7 @@ static struct mxc_usbh_platform_data usbh1_pdata __initdata = { static int __init marxbot_usbh1_init(void) { - struct otg_transceiver *otg; + struct usb_phy *otg; struct platform_device *pdev; otg = kzalloc(sizeof(*otg), GFP_KERNEL); diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c index e28dfb88827f..960d0ac50418 100644 --- a/arch/arm/mach-pxa/pxa3xx-ulpi.c +++ b/arch/arm/mach-pxa/pxa3xx-ulpi.c @@ -33,7 +33,7 @@ struct pxa3xx_u2d_ulpi { struct clk *clk; void __iomem *mmio_base; - struct otg_transceiver *otg; + struct usb_phy *otg; unsigned int ulpi_mode; }; @@ -79,7 +79,7 @@ static int pxa310_ulpi_poll(void) return -ETIMEDOUT; } -static int pxa310_ulpi_read(struct otg_transceiver *otg, u32 reg) +static int pxa310_ulpi_read(struct usb_phy *otg, u32 reg) { int err; @@ -98,7 +98,7 @@ static int pxa310_ulpi_read(struct otg_transceiver *otg, u32 reg) return u2d_readl(U2DOTGUCR) & U2DOTGUCR_RDATA; } -static int pxa310_ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg) +static int pxa310_ulpi_write(struct usb_phy *otg, u32 val, u32 reg) { if (pxa310_ulpi_get_phymode() != SYNCH) { pr_warning("%s: PHY is not in SYNCH mode!\n", __func__); diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h index d4b8f9e298a8..de1a0f602b28 100644 --- a/arch/arm/mach-tegra/include/mach/usb_phy.h +++ b/arch/arm/mach-tegra/include/mach/usb_phy.h @@ -58,7 +58,7 @@ struct tegra_usb_phy { struct clk *pad_clk; enum tegra_usb_phy_mode mode; void *config; - struct otg_transceiver *ulpi; + struct usb_phy *ulpi; }; struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs, diff --git a/arch/arm/plat-mxc/include/mach/mxc_ehci.h b/arch/arm/plat-mxc/include/mach/mxc_ehci.h index 2c159dc2398b..9ffd1bbe615f 100644 --- a/arch/arm/plat-mxc/include/mach/mxc_ehci.h +++ b/arch/arm/plat-mxc/include/mach/mxc_ehci.h @@ -44,7 +44,7 @@ struct mxc_usbh_platform_data { int (*exit)(struct platform_device *pdev); unsigned int portsc; - struct otg_transceiver *otg; + struct usb_phy *otg; }; int mx51_initialize_usb_hw(int port, unsigned int flags); diff --git a/arch/arm/plat-mxc/include/mach/ulpi.h b/arch/arm/plat-mxc/include/mach/ulpi.h index f9161c96d7bd..d39d94a170e7 100644 --- a/arch/arm/plat-mxc/include/mach/ulpi.h +++ b/arch/arm/plat-mxc/include/mach/ulpi.h @@ -2,9 +2,9 @@ #define __MACH_ULPI_H #ifdef CONFIG_USB_ULPI -struct otg_transceiver *imx_otg_ulpi_create(unsigned int flags); +struct usb_phy *imx_otg_ulpi_create(unsigned int flags); #else -static inline struct otg_transceiver *imx_otg_ulpi_create(unsigned int flags) +static inline struct usb_phy *imx_otg_ulpi_create(unsigned int flags) { return NULL; } diff --git a/arch/arm/plat-mxc/ulpi.c b/arch/arm/plat-mxc/ulpi.c index 477e45bea1be..8eeeb6b979c4 100644 --- a/arch/arm/plat-mxc/ulpi.c +++ b/arch/arm/plat-mxc/ulpi.c @@ -58,7 +58,7 @@ static int ulpi_poll(void __iomem *view, u32 bit) return -ETIMEDOUT; } -static int ulpi_read(struct otg_transceiver *otg, u32 reg) +static int ulpi_read(struct usb_phy *otg, u32 reg) { int ret; void __iomem *view = otg->io_priv; @@ -84,7 +84,7 @@ static int ulpi_read(struct otg_transceiver *otg, u32 reg) return (__raw_readl(view) >> ULPIVW_RDATA_SHIFT) & ULPIVW_RDATA_MASK; } -static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg) +static int ulpi_write(struct usb_phy *otg, u32 val, u32 reg) { int ret; void __iomem *view = otg->io_priv; @@ -112,7 +112,7 @@ struct otg_io_access_ops mxc_ulpi_access_ops = { }; EXPORT_SYMBOL_GPL(mxc_ulpi_access_ops); -struct otg_transceiver *imx_otg_ulpi_create(unsigned int flags) +struct usb_phy *imx_otg_ulpi_create(unsigned int flags) { return otg_ulpi_create(&mxc_ulpi_access_ops, flags); } diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c index b806667b59ae..51cdea4fc034 100644 --- a/drivers/power/isp1704_charger.c +++ b/drivers/power/isp1704_charger.c @@ -56,7 +56,7 @@ static u16 isp170x_id[] = { struct isp1704_charger { struct device *dev; struct power_supply psy; - struct otg_transceiver *otg; + struct usb_phy *otg; struct notifier_block nb; struct work_struct work; diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c index fd49689738af..dcf07f55eb04 100644 --- a/drivers/power/pda_power.c +++ b/drivers/power/pda_power.c @@ -40,7 +40,7 @@ static struct timer_list polling_timer; static int polling; #ifdef CONFIG_USB_OTG_UTILS -static struct otg_transceiver *transceiver; +static struct usb_phy *transceiver; static struct notifier_block otg_nb; #endif diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index 54b9198fa576..b3ead2305b4c 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -69,7 +69,7 @@ struct twl4030_bci { struct device *dev; struct power_supply ac; struct power_supply usb; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; struct notifier_block otg_nb; struct work_struct work; int irq_chg; diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h index f4871e1fac59..0d31af56c989 100644 --- a/drivers/usb/gadget/ci13xxx_udc.h +++ b/drivers/usb/gadget/ci13xxx_udc.h @@ -136,7 +136,7 @@ struct ci13xxx { struct usb_gadget_driver *driver; /* 3rd party gadget driver */ struct ci13xxx_udc_driver *udc_driver; /* device controller driver */ int vbus_active; /* is VBUS active */ - struct otg_transceiver *transceiver; /* Transceiver struct */ + struct usb_phy *transceiver; /* Transceiver struct */ }; /****************************************************************************** diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index f781f5dec417..e651469fd39b 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -471,7 +471,7 @@ struct fsl_udc { struct usb_ctrlrequest local_setup_buff; spinlock_t lock; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; unsigned softconnect:1; unsigned vbus_active:1; unsigned stopped:1; diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h index d6e78accaffe..8c8087abb481 100644 --- a/drivers/usb/gadget/langwell_udc.h +++ b/drivers/usb/gadget/langwell_udc.h @@ -162,7 +162,7 @@ struct langwell_udc { spinlock_t lock; /* device lock */ struct langwell_ep *ep; struct usb_gadget_driver *driver; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; u8 dev_addr; u32 usb_state; u32 resume_state; diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h index 34aadfae723d..e2be9519abbe 100644 --- a/drivers/usb/gadget/mv_udc.h +++ b/drivers/usb/gadget/mv_udc.h @@ -217,7 +217,7 @@ struct mv_udc { struct work_struct vbus_work; struct workqueue_struct *qwork; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; struct mv_usb_platform_data *pdata; diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 576cd8578b45..d3529787351d 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2650,7 +2650,7 @@ static void omap_udc_release(struct device *dev) } static int __init -omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv) +omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) { unsigned tmp, buf; @@ -2790,7 +2790,7 @@ static int __init omap_udc_probe(struct platform_device *pdev) { int status = -ENODEV; int hmc; - struct otg_transceiver *xceiv = NULL; + struct usb_phy *xceiv = NULL; const char *type = NULL; struct omap_usb_config *config = pdev->dev.platform_data; struct clk *dc_clk; diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h index 29edc51b6b22..59d3b2213cb1 100644 --- a/drivers/usb/gadget/omap_udc.h +++ b/drivers/usb/gadget/omap_udc.h @@ -164,7 +164,7 @@ struct omap_udc { struct omap_ep ep[32]; u16 devstat; u16 clr_halt; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; struct list_head iso; unsigned softconnect:1; unsigned vbus_active:1; diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h index 8eaf4e43726b..893e917f048e 100644 --- a/drivers/usb/gadget/pxa25x_udc.h +++ b/drivers/usb/gadget/pxa25x_udc.h @@ -119,7 +119,7 @@ struct pxa25x_udc { struct device *dev; struct clk *clk; struct pxa2xx_udc_mach_info *mach; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; u64 dma_mask; struct pxa25x_ep ep [PXA_UDC_NUM_ENDPOINTS]; diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index 7f4e8f424e80..a1d268c6f2cc 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -447,7 +447,7 @@ struct pxa_udc { struct usb_gadget_driver *driver; struct device *dev; struct pxa2xx_udc_mach_info *mach; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; enum ep0_state ep0state; struct udc_stats stats; diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index df8661d266cb..dea475a61fd3 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -145,7 +145,7 @@ struct s3c_hsudc { struct usb_gadget_driver *driver; struct device *dev; struct s3c24xx_hsudc_platdata *pd; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsudc_supply_names)]; spinlock_t lock; void __iomem *regs; diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 592d5f76803e..ef7c4319c6e4 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -32,7 +32,7 @@ #define MSM_USB_BASE (hcd->regs) -static struct otg_transceiver *otg; +static struct usb_phy *otg; static int ehci_msm_reset(struct usb_hcd *hcd) { diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 52a604fb9321..39ca79e008d9 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -28,7 +28,7 @@ struct ehci_hcd_mv { void __iomem *cap_regs; void __iomem *op_regs; - struct otg_transceiver *otg; + struct usb_phy *otg; struct mv_usb_platform_data *pdata; diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index dbc7fe8ca9e7..2e157144dcf6 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -35,7 +35,7 @@ struct tegra_ehci_hcd { struct tegra_usb_phy *phy; struct clk *clk; struct clk *emc_clk; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; int host_resumed; int bus_suspended; int port_resuming; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 0a5fda73b3f2..8f9acbc96fde 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -176,7 +176,7 @@ struct ehci_hcd { /* one per controller */ /* * OTG controllers and transceivers need software interaction */ - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 8ff6f7ea96fd..1b19aea25a2b 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -376,7 +376,7 @@ struct ohci_hcd { * OTG controllers and transceivers need software interaction; * other external transceivers should be software-transparent */ - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; void (*start_hnp)(struct ohci_hcd *ohci); /* diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index 5e7cfba5b079..fc8e9edbcb82 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -317,7 +317,7 @@ static void bfin_musb_set_vbus(struct musb *musb, int is_on) musb_readb(musb->mregs, MUSB_DEVCTL)); } -static int bfin_musb_set_power(struct otg_transceiver *x, unsigned mA) +static int bfin_musb_set_power(struct usb_phy *x, unsigned mA) { return 0; } diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 3d11cf64ebd1..7b7ecf6c65b7 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -131,7 +131,7 @@ static inline struct musb *dev_to_musb(struct device *dev) /*-------------------------------------------------------------------------*/ #ifndef CONFIG_BLACKFIN -static int musb_ulpi_read(struct otg_transceiver *otg, u32 offset) +static int musb_ulpi_read(struct usb_phy *otg, u32 offset) { void __iomem *addr = otg->io_priv; int i = 0; @@ -165,7 +165,7 @@ static int musb_ulpi_read(struct otg_transceiver *otg, u32 offset) return musb_readb(addr, MUSB_ULPI_REG_DATA); } -static int musb_ulpi_write(struct otg_transceiver *otg, +static int musb_ulpi_write(struct usb_phy *otg, u32 offset, u32 data) { void __iomem *addr = otg->io_priv; diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 3d28fb8a2dc9..93de517a32a0 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -372,7 +372,7 @@ struct musb { u16 int_rx; u16 int_tx; - struct otg_transceiver *xceiv; + struct usb_phy *xceiv; u8 xceiv_event; int nIrq; diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 1f405616e6cd..5ce01bdb1951 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -277,7 +277,7 @@ static struct musb *the_musb; * mode), or low power Default-B sessions, something else supplies power. * Caller must take care of locking. */ -static int tusb_draw_power(struct otg_transceiver *x, unsigned mA) +static int tusb_draw_power(struct usb_phy *x, unsigned mA) { struct musb *musb = the_musb; void __iomem *tbase = musb->ctrl_base; diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 76d629345418..b353b393448a 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -23,7 +23,7 @@ config USB_GPIO_VBUS select USB_OTG_UTILS help Provides simple GPIO VBUS sensing for controllers with an - internal transceiver via the otg_transceiver interface, and + internal transceiver via the usb_phy interface, and optionally control of a D+ pullup GPIO as well as a VBUS current limit regulator. diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c index 74fe6e62e0f7..5f06dda7db61 100644 --- a/drivers/usb/otg/ab8500-usb.c +++ b/drivers/usb/otg/ab8500-usb.c @@ -68,7 +68,7 @@ enum ab8500_usb_link_status { }; struct ab8500_usb { - struct otg_transceiver otg; + struct usb_phy otg; struct device *dev; int irq_num_id_rise; int irq_num_id_fall; @@ -82,7 +82,7 @@ struct ab8500_usb { int rev; }; -static inline struct ab8500_usb *xceiv_to_ab(struct otg_transceiver *x) +static inline struct ab8500_usb *xceiv_to_ab(struct usb_phy *x) { return container_of(x, struct ab8500_usb, otg); } @@ -269,7 +269,7 @@ static void ab8500_usb_phy_disable_work(struct work_struct *work) ab8500_usb_peri_phy_dis(ab); } -static int ab8500_usb_set_power(struct otg_transceiver *otg, unsigned mA) +static int ab8500_usb_set_power(struct usb_phy *otg, unsigned mA) { struct ab8500_usb *ab; @@ -290,13 +290,13 @@ static int ab8500_usb_set_power(struct otg_transceiver *otg, unsigned mA) * ab->vbus_draw. */ -static int ab8500_usb_set_suspend(struct otg_transceiver *x, int suspend) +static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend) { /* TODO */ return 0; } -static int ab8500_usb_set_peripheral(struct otg_transceiver *otg, +static int ab8500_usb_set_peripheral(struct usb_phy *otg, struct usb_gadget *gadget) { struct ab8500_usb *ab; @@ -329,7 +329,7 @@ static int ab8500_usb_set_peripheral(struct otg_transceiver *otg, return 0; } -static int ab8500_usb_set_host(struct otg_transceiver *otg, +static int ab8500_usb_set_host(struct usb_phy *otg, struct usb_bus *host) { struct ab8500_usb *ab; diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c index a190850d2d3b..66db2a117444 100644 --- a/drivers/usb/otg/fsl_otg.c +++ b/drivers/usb/otg/fsl_otg.c @@ -452,7 +452,7 @@ void otg_reset_controller(void) /* Call suspend/resume routines in host driver */ int fsl_otg_start_host(struct otg_fsm *fsm, int on) { - struct otg_transceiver *xceiv = fsm->transceiver; + struct usb_phy *xceiv = fsm->transceiver; struct device *dev; struct fsl_otg *otg_dev = container_of(xceiv, struct fsl_otg, otg); u32 retval = 0; @@ -518,7 +518,7 @@ end: */ int fsl_otg_start_gadget(struct otg_fsm *fsm, int on) { - struct otg_transceiver *xceiv = fsm->transceiver; + struct usb_phy *xceiv = fsm->transceiver; struct device *dev; if (!xceiv->gadget || !xceiv->gadget->dev.parent) @@ -542,7 +542,7 @@ int fsl_otg_start_gadget(struct otg_fsm *fsm, int on) * Called by initialization code of host driver. Register host controller * to the OTG. Suspend host for OTG role detection. */ -static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host) +static int fsl_otg_set_host(struct usb_phy *otg_p, struct usb_bus *host) { struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); @@ -587,7 +587,7 @@ static int fsl_otg_set_host(struct otg_transceiver *otg_p, struct usb_bus *host) } /* Called by initialization code of udc. Register udc to OTG. */ -static int fsl_otg_set_peripheral(struct otg_transceiver *otg_p, +static int fsl_otg_set_peripheral(struct usb_phy *otg_p, struct usb_gadget *gadget) { struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); @@ -625,7 +625,7 @@ static int fsl_otg_set_peripheral(struct otg_transceiver *otg_p, } /* Set OTG port power, only for B-device */ -static int fsl_otg_set_power(struct otg_transceiver *otg_p, unsigned mA) +static int fsl_otg_set_power(struct usb_phy *otg_p, unsigned mA) { if (!fsl_otg_dev) return -ENODEV; @@ -658,7 +658,7 @@ static void fsl_otg_event(struct work_struct *work) } /* B-device start SRP */ -static int fsl_otg_start_srp(struct otg_transceiver *otg_p) +static int fsl_otg_start_srp(struct usb_phy *otg_p) { struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); @@ -673,7 +673,7 @@ static int fsl_otg_start_srp(struct otg_transceiver *otg_p) } /* A_host suspend will call this function to start hnp */ -static int fsl_otg_start_hnp(struct otg_transceiver *otg_p) +static int fsl_otg_start_hnp(struct usb_phy *otg_p) { struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); @@ -698,7 +698,7 @@ static int fsl_otg_start_hnp(struct otg_transceiver *otg_p) irqreturn_t fsl_otg_isr(int irq, void *dev_id) { struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm; - struct otg_transceiver *otg = &((struct fsl_otg *)dev_id)->otg; + struct usb_phy *otg = &((struct fsl_otg *)dev_id)->otg; u32 otg_int_src, otg_sc; otg_sc = fsl_readl(&usb_dr_regs->otgsc); @@ -815,7 +815,7 @@ err: int usb_otg_start(struct platform_device *pdev) { struct fsl_otg *p_otg; - struct otg_transceiver *otg_trans = otg_get_transceiver(); + struct usb_phy *otg_trans = otg_get_transceiver(); struct otg_fsm *fsm; int status; struct resource *res; diff --git a/drivers/usb/otg/fsl_otg.h b/drivers/usb/otg/fsl_otg.h index 3f8ef731aac9..caec254ad819 100644 --- a/drivers/usb/otg/fsl_otg.h +++ b/drivers/usb/otg/fsl_otg.h @@ -369,7 +369,7 @@ inline struct fsl_otg_timer *otg_timer_initializer } struct fsl_otg { - struct otg_transceiver otg; + struct usb_phy otg; struct otg_fsm fsm; struct usb_dr_mmap *dr_mem_map; struct delayed_work otg_event; diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c index fb644c107ded..4e1b1384dc89 100644 --- a/drivers/usb/otg/gpio_vbus.c +++ b/drivers/usb/otg/gpio_vbus.c @@ -32,7 +32,7 @@ * Needs to be loaded before the UDC driver that will use it. */ struct gpio_vbus_data { - struct otg_transceiver otg; + struct usb_phy otg; struct device *dev; struct regulator *vbus_draw; int vbus_draw_enabled; @@ -149,7 +149,7 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data) /* OTG transceiver interface */ /* bind/unbind the peripheral controller */ -static int gpio_vbus_set_peripheral(struct otg_transceiver *otg, +static int gpio_vbus_set_peripheral(struct usb_phy *otg, struct usb_gadget *gadget) { struct gpio_vbus_data *gpio_vbus; @@ -189,7 +189,7 @@ static int gpio_vbus_set_peripheral(struct otg_transceiver *otg, } /* effective for B devices, ignored for A-peripheral */ -static int gpio_vbus_set_power(struct otg_transceiver *otg, unsigned mA) +static int gpio_vbus_set_power(struct usb_phy *otg, unsigned mA) { struct gpio_vbus_data *gpio_vbus; @@ -201,7 +201,7 @@ static int gpio_vbus_set_power(struct otg_transceiver *otg, unsigned mA) } /* for non-OTG B devices: set/clear transceiver suspend mode */ -static int gpio_vbus_set_suspend(struct otg_transceiver *otg, int suspend) +static int gpio_vbus_set_suspend(struct usb_phy *otg, int suspend) { struct gpio_vbus_data *gpio_vbus; diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c index 8c86787c2f09..1bc27948ac22 100644 --- a/drivers/usb/otg/isp1301_omap.c +++ b/drivers/usb/otg/isp1301_omap.c @@ -52,7 +52,7 @@ MODULE_DESCRIPTION("ISP1301 USB OTG Transceiver Driver"); MODULE_LICENSE("GPL"); struct isp1301 { - struct otg_transceiver otg; + struct usb_phy otg; struct i2c_client *client; void (*i2c_release)(struct device *dev); @@ -1274,7 +1274,7 @@ static int isp1301_otg_enable(struct isp1301 *isp) /* add or disable the host device+driver */ static int -isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) +isp1301_set_host(struct usb_phy *otg, struct usb_bus *host) { struct isp1301 *isp = container_of(otg, struct isp1301, otg); @@ -1330,7 +1330,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) } static int -isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) +isp1301_set_peripheral(struct usb_phy *otg, struct usb_gadget *gadget) { struct isp1301 *isp = container_of(otg, struct isp1301, otg); #ifndef CONFIG_USB_OTG @@ -1399,7 +1399,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) /*-------------------------------------------------------------------------*/ static int -isp1301_set_power(struct otg_transceiver *dev, unsigned mA) +isp1301_set_power(struct usb_phy *dev, unsigned mA) { if (!the_transceiver) return -ENODEV; @@ -1409,7 +1409,7 @@ isp1301_set_power(struct otg_transceiver *dev, unsigned mA) } static int -isp1301_start_srp(struct otg_transceiver *dev) +isp1301_start_srp(struct usb_phy *dev) { struct isp1301 *isp = container_of(dev, struct isp1301, otg); u32 otg_ctrl; @@ -1436,7 +1436,7 @@ isp1301_start_srp(struct otg_transceiver *dev) } static int -isp1301_start_hnp(struct otg_transceiver *dev) +isp1301_start_hnp(struct usb_phy *dev) { #ifdef CONFIG_USB_OTG struct isp1301 *isp = container_of(dev, struct isp1301, otg); diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c index b276f8fcdeba..cba4737a04f4 100644 --- a/drivers/usb/otg/msm_otg.c +++ b/drivers/usb/otg/msm_otg.c @@ -235,7 +235,7 @@ static int msm_hsusb_ldo_set_mode(int on) return ret < 0 ? ret : 0; } -static int ulpi_read(struct otg_transceiver *otg, u32 reg) +static int ulpi_read(struct usb_phy *otg, u32 reg) { struct msm_otg *motg = container_of(otg, struct msm_otg, otg); int cnt = 0; @@ -260,7 +260,7 @@ static int ulpi_read(struct otg_transceiver *otg, u32 reg) return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT)); } -static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg) +static int ulpi_write(struct usb_phy *otg, u32 val, u32 reg) { struct msm_otg *motg = container_of(otg, struct msm_otg, otg); int cnt = 0; @@ -390,7 +390,7 @@ static int msm_otg_phy_reset(struct msm_otg *motg) } #define LINK_RESET_TIMEOUT_USEC (250 * 1000) -static int msm_otg_reset(struct otg_transceiver *otg) +static int msm_otg_reset(struct usb_phy *otg) { struct msm_otg *motg = container_of(otg, struct msm_otg, otg); struct msm_otg_platform_data *pdata = motg->pdata; @@ -448,7 +448,7 @@ static int msm_otg_reset(struct otg_transceiver *otg) #ifdef CONFIG_PM_SLEEP static int msm_otg_suspend(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; struct usb_bus *bus = otg->host; struct msm_otg_platform_data *pdata = motg->pdata; int cnt = 0; @@ -543,7 +543,7 @@ static int msm_otg_suspend(struct msm_otg *motg) static int msm_otg_resume(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; struct usb_bus *bus = otg->host; int cnt = 0; unsigned temp; @@ -627,7 +627,7 @@ static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA) motg->cur_power = mA; } -static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA) +static int msm_otg_set_power(struct usb_phy *otg, unsigned mA) { struct msm_otg *motg = container_of(otg, struct msm_otg, otg); @@ -644,7 +644,7 @@ static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA) return 0; } -static void msm_otg_start_host(struct otg_transceiver *otg, int on) +static void msm_otg_start_host(struct usb_phy *otg, int on) { struct msm_otg *motg = container_of(otg, struct msm_otg, otg); struct msm_otg_platform_data *pdata = motg->pdata; @@ -683,7 +683,7 @@ static void msm_otg_start_host(struct otg_transceiver *otg, int on) } } -static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host) +static int msm_otg_set_host(struct usb_phy *otg, struct usb_bus *host) { struct msm_otg *motg = container_of(otg, struct msm_otg, otg); struct usb_hcd *hcd; @@ -729,7 +729,7 @@ static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host) return 0; } -static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on) +static void msm_otg_start_peripheral(struct usb_phy *otg, int on) { struct msm_otg *motg = container_of(otg, struct msm_otg, otg); struct msm_otg_platform_data *pdata = motg->pdata; @@ -756,7 +756,7 @@ static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on) } -static int msm_otg_set_peripheral(struct otg_transceiver *otg, +static int msm_otg_set_peripheral(struct usb_phy *otg, struct usb_gadget *gadget) { struct msm_otg *motg = container_of(otg, struct msm_otg, otg); @@ -800,7 +800,7 @@ static int msm_otg_set_peripheral(struct otg_transceiver *otg, static bool msm_chg_check_secondary_det(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; u32 chg_det; bool ret = false; @@ -821,7 +821,7 @@ static bool msm_chg_check_secondary_det(struct msm_otg *motg) static void msm_chg_enable_secondary_det(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; u32 chg_det; switch (motg->pdata->phy_type) { @@ -861,7 +861,7 @@ static void msm_chg_enable_secondary_det(struct msm_otg *motg) static bool msm_chg_check_primary_det(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; u32 chg_det; bool ret = false; @@ -882,7 +882,7 @@ static bool msm_chg_check_primary_det(struct msm_otg *motg) static void msm_chg_enable_primary_det(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; u32 chg_det; switch (motg->pdata->phy_type) { @@ -907,7 +907,7 @@ static void msm_chg_enable_primary_det(struct msm_otg *motg) static bool msm_chg_check_dcd(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; u32 line_state; bool ret = false; @@ -928,7 +928,7 @@ static bool msm_chg_check_dcd(struct msm_otg *motg) static void msm_chg_disable_dcd(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; u32 chg_det; switch (motg->pdata->phy_type) { @@ -947,7 +947,7 @@ static void msm_chg_disable_dcd(struct msm_otg *motg) static void msm_chg_enable_dcd(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; u32 chg_det; switch (motg->pdata->phy_type) { @@ -968,7 +968,7 @@ static void msm_chg_enable_dcd(struct msm_otg *motg) static void msm_chg_block_on(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; u32 func_ctrl, chg_det; /* put the controller in non-driving mode */ @@ -1003,7 +1003,7 @@ static void msm_chg_block_on(struct msm_otg *motg) static void msm_chg_block_off(struct msm_otg *motg) { - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; u32 func_ctrl, chg_det; switch (motg->pdata->phy_type) { @@ -1038,7 +1038,7 @@ static void msm_chg_block_off(struct msm_otg *motg) static void msm_chg_detect_work(struct work_struct *w) { struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work); - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; bool is_dcd, tmout, vout; unsigned long delay; @@ -1152,7 +1152,7 @@ static void msm_otg_init_sm(struct msm_otg *motg) static void msm_otg_sm_work(struct work_struct *w) { struct msm_otg *motg = container_of(w, struct msm_otg, sm_work); - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; switch (otg->state) { case OTG_STATE_UNDEFINED: @@ -1243,7 +1243,7 @@ static void msm_otg_sm_work(struct work_struct *w) static irqreturn_t msm_otg_irq(int irq, void *data) { struct msm_otg *motg = data; - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; u32 otgsc = 0; if (atomic_read(&motg->in_lpm)) { @@ -1281,7 +1281,7 @@ static irqreturn_t msm_otg_irq(int irq, void *data) static int msm_otg_mode_show(struct seq_file *s, void *unused) { struct msm_otg *motg = s->private; - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; switch (otg->state) { case OTG_STATE_A_HOST: @@ -1309,7 +1309,7 @@ static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, struct seq_file *s = file->private_data; struct msm_otg *motg = s->private; char buf[16]; - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; int status = count; enum usb_mode_type req_mode; @@ -1414,7 +1414,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) int ret = 0; struct resource *res; struct msm_otg *motg; - struct otg_transceiver *otg; + struct usb_phy *otg; dev_info(&pdev->dev, "msm_otg probe\n"); if (!pdev->dev.platform_data) { @@ -1598,7 +1598,7 @@ free_motg: static int __devexit msm_otg_remove(struct platform_device *pdev) { struct msm_otg *motg = platform_get_drvdata(pdev); - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; int cnt = 0; if (otg->host || otg->gadget) @@ -1660,7 +1660,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) static int msm_otg_runtime_idle(struct device *dev) { struct msm_otg *motg = dev_get_drvdata(dev); - struct otg_transceiver *otg = &motg->otg; + struct usb_phy *otg = &motg->otg; dev_dbg(dev, "OTG runtime idle\n"); diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c index b5fbe1452ab0..6e05d58effe1 100644 --- a/drivers/usb/otg/mv_otg.c +++ b/drivers/usb/otg/mv_otg.c @@ -55,7 +55,7 @@ static char *state_string[] = { "a_vbus_err" }; -static int mv_otg_set_vbus(struct otg_transceiver *otg, bool on) +static int mv_otg_set_vbus(struct usb_phy *otg, bool on) { struct mv_otg *mvotg = container_of(otg, struct mv_otg, otg); if (mvotg->pdata->set_vbus == NULL) @@ -64,7 +64,7 @@ static int mv_otg_set_vbus(struct otg_transceiver *otg, bool on) return mvotg->pdata->set_vbus(on); } -static int mv_otg_set_host(struct otg_transceiver *otg, +static int mv_otg_set_host(struct usb_phy *otg, struct usb_bus *host) { otg->host = host; @@ -72,7 +72,7 @@ static int mv_otg_set_host(struct otg_transceiver *otg, return 0; } -static int mv_otg_set_peripheral(struct otg_transceiver *otg, +static int mv_otg_set_peripheral(struct usb_phy *otg, struct usb_gadget *gadget) { otg->gadget = gadget; @@ -203,7 +203,7 @@ static void mv_otg_init_irq(struct mv_otg *mvotg) static void mv_otg_start_host(struct mv_otg *mvotg, int on) { #ifdef CONFIG_USB - struct otg_transceiver *otg = &mvotg->otg; + struct usb_phy *otg = &mvotg->otg; struct usb_hcd *hcd; if (!otg->host) @@ -222,7 +222,7 @@ static void mv_otg_start_host(struct mv_otg *mvotg, int on) static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on) { - struct otg_transceiver *otg = &mvotg->otg; + struct usb_phy *otg = &mvotg->otg; if (!otg->gadget) return; @@ -343,7 +343,7 @@ static void mv_otg_update_inputs(struct mv_otg *mvotg) static void mv_otg_update_state(struct mv_otg *mvotg) { struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl; - struct otg_transceiver *otg = &mvotg->otg; + struct usb_phy *otg = &mvotg->otg; int old_state = otg->state; switch (old_state) { @@ -416,7 +416,7 @@ static void mv_otg_update_state(struct mv_otg *mvotg) static void mv_otg_work(struct work_struct *work) { struct mv_otg *mvotg; - struct otg_transceiver *otg; + struct usb_phy *otg; int old_state; mvotg = container_of((struct delayed_work *)work, struct mv_otg, work); diff --git a/drivers/usb/otg/mv_otg.h b/drivers/usb/otg/mv_otg.h index be6ca1437645..a74ee07a2727 100644 --- a/drivers/usb/otg/mv_otg.h +++ b/drivers/usb/otg/mv_otg.h @@ -136,7 +136,7 @@ struct mv_otg_regs { }; struct mv_otg { - struct otg_transceiver otg; + struct usb_phy otg; struct mv_otg_ctrl otg_ctrl; /* base address */ diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index c1e360046435..2ab027997060 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -33,7 +33,7 @@ #include struct nop_usb_xceiv { - struct otg_transceiver otg; + struct usb_phy otg; struct device *dev; }; @@ -58,17 +58,17 @@ void usb_nop_xceiv_unregister(void) } EXPORT_SYMBOL(usb_nop_xceiv_unregister); -static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x) +static inline struct nop_usb_xceiv *xceiv_to_nop(struct usb_phy *x) { return container_of(x, struct nop_usb_xceiv, otg); } -static int nop_set_suspend(struct otg_transceiver *x, int suspend) +static int nop_set_suspend(struct usb_phy *x, int suspend) { return 0; } -static int nop_set_peripheral(struct otg_transceiver *x, +static int nop_set_peripheral(struct usb_phy *x, struct usb_gadget *gadget) { struct nop_usb_xceiv *nop; @@ -88,7 +88,7 @@ static int nop_set_peripheral(struct otg_transceiver *x, return 0; } -static int nop_set_host(struct otg_transceiver *x, struct usb_bus *host) +static int nop_set_host(struct usb_phy *x, struct usb_bus *host) { struct nop_usb_xceiv *nop; diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c index 307c27bc51eb..56c0f1781d8c 100644 --- a/drivers/usb/otg/otg.c +++ b/drivers/usb/otg/otg.c @@ -15,7 +15,7 @@ #include -static struct otg_transceiver *xceiv; +static struct usb_phy *xceiv; /** * otg_get_transceiver - find the (single) OTG transceiver @@ -26,7 +26,7 @@ static struct otg_transceiver *xceiv; * * For use by USB host and peripheral drivers. */ -struct otg_transceiver *otg_get_transceiver(void) +struct usb_phy *otg_get_transceiver(void) { if (xceiv) get_device(xceiv->dev); @@ -42,7 +42,7 @@ EXPORT_SYMBOL(otg_get_transceiver); * * For use by USB host and peripheral drivers. */ -void otg_put_transceiver(struct otg_transceiver *x) +void otg_put_transceiver(struct usb_phy *x) { if (x) put_device(x->dev); @@ -57,7 +57,7 @@ EXPORT_SYMBOL(otg_put_transceiver); * coordinate the activities of drivers for host and peripheral * controllers, and in some cases for VBUS current regulation. */ -int otg_set_transceiver(struct otg_transceiver *x) +int otg_set_transceiver(struct usb_phy *x) { if (xceiv && x) return -EBUSY; diff --git a/drivers/usb/otg/otg_fsm.h b/drivers/usb/otg/otg_fsm.h index 0cecf1d593a0..5e589ae9a199 100644 --- a/drivers/usb/otg/otg_fsm.h +++ b/drivers/usb/otg/otg_fsm.h @@ -82,7 +82,7 @@ struct otg_fsm { int loc_sof; struct otg_fsm_ops *ops; - struct otg_transceiver *transceiver; + struct usb_phy *transceiver; /* Current usb protocol used: 0:undefine; 1:host; 2:client */ int protocol; diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 14f66c358629..beeecc239d18 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -144,7 +144,7 @@ #define GPIO_USB_4PIN_ULPI_2430C (3 << 0) struct twl4030_usb { - struct otg_transceiver otg; + struct usb_phy otg; struct device *dev; /* TWL4030 internal USB regulator supplies */ @@ -548,7 +548,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl) sysfs_notify(&twl->dev->kobj, NULL, "vbus"); } -static int twl4030_set_suspend(struct otg_transceiver *x, int suspend) +static int twl4030_set_suspend(struct usb_phy *x, int suspend) { struct twl4030_usb *twl = xceiv_to_twl(x); @@ -560,7 +560,7 @@ static int twl4030_set_suspend(struct otg_transceiver *x, int suspend) return 0; } -static int twl4030_set_peripheral(struct otg_transceiver *x, +static int twl4030_set_peripheral(struct usb_phy *x, struct usb_gadget *gadget) { struct twl4030_usb *twl; @@ -576,7 +576,7 @@ static int twl4030_set_peripheral(struct otg_transceiver *x, return 0; } -static int twl4030_set_host(struct otg_transceiver *x, struct usb_bus *host) +static int twl4030_set_host(struct usb_phy *x, struct usb_bus *host) { struct twl4030_usb *twl; diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index ed2b26cfe814..56c4d3d50ebe 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c @@ -87,7 +87,7 @@ #define VBUS_DET BIT(2) struct twl6030_usb { - struct otg_transceiver otg; + struct usb_phy otg; struct device *dev; /* for vbus reporting with irqs disabled */ @@ -137,7 +137,7 @@ static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address) return ret; } -static int twl6030_phy_init(struct otg_transceiver *x) +static int twl6030_phy_init(struct usb_phy *x) { struct twl6030_usb *twl; struct device *dev; @@ -155,7 +155,7 @@ static int twl6030_phy_init(struct otg_transceiver *x) return 0; } -static void twl6030_phy_shutdown(struct otg_transceiver *x) +static void twl6030_phy_shutdown(struct usb_phy *x) { struct twl6030_usb *twl; struct device *dev; @@ -167,7 +167,7 @@ static void twl6030_phy_shutdown(struct otg_transceiver *x) pdata->phy_power(twl->dev, 0, 0); } -static int twl6030_phy_suspend(struct otg_transceiver *x, int suspend) +static int twl6030_phy_suspend(struct usb_phy *x, int suspend) { struct twl6030_usb *twl = xceiv_to_twl(x); struct device *dev = twl->dev; @@ -178,7 +178,7 @@ static int twl6030_phy_suspend(struct otg_transceiver *x, int suspend) return 0; } -static int twl6030_start_srp(struct otg_transceiver *x) +static int twl6030_start_srp(struct usb_phy *x) { struct twl6030_usb *twl = xceiv_to_twl(x); @@ -324,7 +324,7 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) return IRQ_HANDLED; } -static int twl6030_set_peripheral(struct otg_transceiver *x, +static int twl6030_set_peripheral(struct usb_phy *x, struct usb_gadget *gadget) { struct twl6030_usb *twl; @@ -340,7 +340,7 @@ static int twl6030_set_peripheral(struct otg_transceiver *x, return 0; } -static int twl6030_enable_irq(struct otg_transceiver *x) +static int twl6030_enable_irq(struct usb_phy *x) { struct twl6030_usb *twl = xceiv_to_twl(x); @@ -376,7 +376,7 @@ static void otg_set_vbus_work(struct work_struct *data) CHARGERUSB_CTRL1); } -static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled) +static int twl6030_set_vbus(struct usb_phy *x, bool enabled) { struct twl6030_usb *twl = xceiv_to_twl(x); @@ -386,7 +386,7 @@ static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled) return 0; } -static int twl6030_set_host(struct otg_transceiver *x, struct usb_bus *host) +static int twl6030_set_host(struct usb_phy *x, struct usb_bus *host) { struct twl6030_usb *twl; diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index 0b0466728fdc..51841ed829ab 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/otg/ulpi.c @@ -49,7 +49,7 @@ static struct ulpi_info ulpi_ids[] = { ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"), }; -static int ulpi_set_otg_flags(struct otg_transceiver *otg) +static int ulpi_set_otg_flags(struct usb_phy *otg) { unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN | ULPI_OTG_CTRL_DM_PULLDOWN; @@ -73,7 +73,7 @@ static int ulpi_set_otg_flags(struct otg_transceiver *otg) return otg_io_write(otg, flags, ULPI_OTG_CTRL); } -static int ulpi_set_fc_flags(struct otg_transceiver *otg) +static int ulpi_set_fc_flags(struct usb_phy *otg) { unsigned int flags = 0; @@ -115,7 +115,7 @@ static int ulpi_set_fc_flags(struct otg_transceiver *otg) return otg_io_write(otg, flags, ULPI_FUNC_CTRL); } -static int ulpi_set_ic_flags(struct otg_transceiver *otg) +static int ulpi_set_ic_flags(struct usb_phy *otg) { unsigned int flags = 0; @@ -134,7 +134,7 @@ static int ulpi_set_ic_flags(struct otg_transceiver *otg) return otg_io_write(otg, flags, ULPI_IFC_CTRL); } -static int ulpi_set_flags(struct otg_transceiver *otg) +static int ulpi_set_flags(struct usb_phy *otg) { int ret; @@ -149,7 +149,7 @@ static int ulpi_set_flags(struct otg_transceiver *otg) return ulpi_set_fc_flags(otg); } -static int ulpi_check_integrity(struct otg_transceiver *otg) +static int ulpi_check_integrity(struct usb_phy *otg) { int ret, i; unsigned int val = 0x55; @@ -175,7 +175,7 @@ static int ulpi_check_integrity(struct otg_transceiver *otg) return 0; } -static int ulpi_init(struct otg_transceiver *otg) +static int ulpi_init(struct usb_phy *otg) { int i, vid, pid, ret; u32 ulpi_id = 0; @@ -206,7 +206,7 @@ static int ulpi_init(struct otg_transceiver *otg) return ulpi_set_flags(otg); } -static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host) +static int ulpi_set_host(struct usb_phy *otg, struct usb_bus *host) { unsigned int flags = otg_io_read(otg, ULPI_IFC_CTRL); @@ -231,7 +231,7 @@ static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host) return otg_io_write(otg, flags, ULPI_IFC_CTRL); } -static int ulpi_set_vbus(struct otg_transceiver *otg, bool on) +static int ulpi_set_vbus(struct usb_phy *otg, bool on) { unsigned int flags = otg_io_read(otg, ULPI_OTG_CTRL); @@ -248,11 +248,11 @@ static int ulpi_set_vbus(struct otg_transceiver *otg, bool on) return otg_io_write(otg, flags, ULPI_OTG_CTRL); } -struct otg_transceiver * +struct usb_phy * otg_ulpi_create(struct otg_io_access_ops *ops, unsigned int flags) { - struct otg_transceiver *otg; + struct usb_phy *otg; otg = kzalloc(sizeof(*otg), GFP_KERNEL); if (!otg) diff --git a/drivers/usb/otg/ulpi_viewport.c b/drivers/usb/otg/ulpi_viewport.c index e9a37f90994f..e7b311b960bd 100644 --- a/drivers/usb/otg/ulpi_viewport.c +++ b/drivers/usb/otg/ulpi_viewport.c @@ -40,7 +40,7 @@ static int ulpi_viewport_wait(void __iomem *view, u32 mask) return -ETIMEDOUT; } -static int ulpi_viewport_read(struct otg_transceiver *otg, u32 reg) +static int ulpi_viewport_read(struct usb_phy *otg, u32 reg) { int ret; void __iomem *view = otg->io_priv; @@ -58,7 +58,7 @@ static int ulpi_viewport_read(struct otg_transceiver *otg, u32 reg) return ULPI_VIEW_DATA_READ(readl(view)); } -static int ulpi_viewport_write(struct otg_transceiver *otg, u32 val, u32 reg) +static int ulpi_viewport_write(struct usb_phy *otg, u32 val, u32 reg) { int ret; void __iomem *view = otg->io_priv; diff --git a/include/linux/usb/intel_mid_otg.h b/include/linux/usb/intel_mid_otg.h index a0ccf795f362..756cf5543ffd 100644 --- a/include/linux/usb/intel_mid_otg.h +++ b/include/linux/usb/intel_mid_otg.h @@ -104,11 +104,11 @@ struct iotg_ulpi_access_ops { /* * the Intel MID (Langwell/Penwell) otg transceiver driver needs to interact * with device and host drivers to implement the USB OTG related feature. More - * function members are added based on otg_transceiver data structure for this + * function members are added based on usb_phy data structure for this * purpose. */ struct intel_mid_otg_xceiv { - struct otg_transceiver otg; + struct usb_phy otg; struct otg_hsm hsm; /* base address */ @@ -147,7 +147,7 @@ struct intel_mid_otg_xceiv { }; static inline -struct intel_mid_otg_xceiv *otg_to_mid_xceiv(struct otg_transceiver *otg) +struct intel_mid_otg_xceiv *otg_to_mid_xceiv(struct usb_phy *otg) { return container_of(otg, struct intel_mid_otg_xceiv, otg); } diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index 00311fe9d0df..2d3547ae9562 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h @@ -160,7 +160,7 @@ struct msm_otg_platform_data { * detection process. */ struct msm_otg { - struct otg_transceiver otg; + struct usb_phy otg; struct msm_otg_platform_data *pdata; int irq; struct clk *clk; diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index d87f44f5b04e..e0bc55702a89 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -43,14 +43,14 @@ enum usb_xceiv_events { USB_EVENT_ENUMERATED, /* gadget driver enumerated */ }; -struct otg_transceiver; +struct usb_phy; /* for transceivers connected thru an ULPI interface, the user must * provide access ops */ struct otg_io_access_ops { - int (*read)(struct otg_transceiver *otg, u32 reg); - int (*write)(struct otg_transceiver *otg, u32 val, u32 reg); + int (*read)(struct usb_phy *x, u32 reg); + int (*write)(struct usb_phy *x, u32 val, u32 reg); }; /* @@ -59,7 +59,7 @@ struct otg_io_access_ops { * moment, using the transceiver, ID signal, HNP and sometimes static * configuration information (including "board isn't wired for otg"). */ -struct otg_transceiver { +struct usb_phy { struct device *dev; const char *label; unsigned int flags; @@ -82,40 +82,40 @@ struct otg_transceiver { u16 port_change; /* initialize/shutdown the OTG controller */ - int (*init)(struct otg_transceiver *otg); - void (*shutdown)(struct otg_transceiver *otg); + int (*init)(struct usb_phy *x); + void (*shutdown)(struct usb_phy *x); /* bind/unbind the host controller */ - int (*set_host)(struct otg_transceiver *otg, + int (*set_host)(struct usb_phy *x, struct usb_bus *host); /* bind/unbind the peripheral controller */ - int (*set_peripheral)(struct otg_transceiver *otg, + int (*set_peripheral)(struct usb_phy *x, struct usb_gadget *gadget); /* effective for B devices, ignored for A-peripheral */ - int (*set_power)(struct otg_transceiver *otg, + int (*set_power)(struct usb_phy *x, unsigned mA); /* effective for A-peripheral, ignored for B devices */ - int (*set_vbus)(struct otg_transceiver *otg, + int (*set_vbus)(struct usb_phy *x, bool enabled); /* for non-OTG B devices: set transceiver into suspend mode */ - int (*set_suspend)(struct otg_transceiver *otg, + int (*set_suspend)(struct usb_phy *x, int suspend); /* for B devices only: start session with A-Host */ - int (*start_srp)(struct otg_transceiver *otg); + int (*start_srp)(struct usb_phy *x); /* start or continue HNP role switch */ - int (*start_hnp)(struct otg_transceiver *otg); + int (*start_hnp)(struct usb_phy *x); }; /* for board-specific init logic */ -extern int otg_set_transceiver(struct otg_transceiver *); +extern int otg_set_transceiver(struct usb_phy *); #if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE)) /* sometimes transceivers are accessed only through e.g. ULPI */ @@ -132,50 +132,50 @@ static inline void usb_nop_xceiv_unregister(void) #endif /* helpers for direct access thru low-level io interface */ -static inline int otg_io_read(struct otg_transceiver *otg, u32 reg) +static inline int otg_io_read(struct usb_phy *x, u32 reg) { - if (otg->io_ops && otg->io_ops->read) - return otg->io_ops->read(otg, reg); + if (x->io_ops && x->io_ops->read) + return x->io_ops->read(x, reg); return -EINVAL; } -static inline int otg_io_write(struct otg_transceiver *otg, u32 val, u32 reg) +static inline int otg_io_write(struct usb_phy *x, u32 val, u32 reg) { - if (otg->io_ops && otg->io_ops->write) - return otg->io_ops->write(otg, val, reg); + if (x->io_ops && x->io_ops->write) + return x->io_ops->write(x, val, reg); return -EINVAL; } static inline int -otg_init(struct otg_transceiver *otg) +otg_init(struct usb_phy *x) { - if (otg->init) - return otg->init(otg); + if (x->init) + return x->init(x); return 0; } static inline void -otg_shutdown(struct otg_transceiver *otg) +otg_shutdown(struct usb_phy *x) { - if (otg->shutdown) - otg->shutdown(otg); + if (x->shutdown) + x->shutdown(x); } /* for usb host and peripheral controller drivers */ #ifdef CONFIG_USB_OTG_UTILS -extern struct otg_transceiver *otg_get_transceiver(void); -extern void otg_put_transceiver(struct otg_transceiver *); +extern struct usb_phy *otg_get_transceiver(void); +extern void otg_put_transceiver(struct usb_phy *); extern const char *otg_state_string(enum usb_otg_state state); #else -static inline struct otg_transceiver *otg_get_transceiver(void) +static inline struct usb_phy *otg_get_transceiver(void) { return NULL; } -static inline void otg_put_transceiver(struct otg_transceiver *x) +static inline void otg_put_transceiver(struct usb_phy *x) { } @@ -187,67 +187,67 @@ static inline const char *otg_state_string(enum usb_otg_state state) /* Context: can sleep */ static inline int -otg_start_hnp(struct otg_transceiver *otg) +otg_start_hnp(struct usb_phy *x) { - return otg->start_hnp(otg); + return x->start_hnp(x); } /* Context: can sleep */ static inline int -otg_set_vbus(struct otg_transceiver *otg, bool enabled) +otg_set_vbus(struct usb_phy *x, bool enabled) { - return otg->set_vbus(otg, enabled); + return x->set_vbus(x, enabled); } /* for HCDs */ static inline int -otg_set_host(struct otg_transceiver *otg, struct usb_bus *host) +otg_set_host(struct usb_phy *x, struct usb_bus *host) { - return otg->set_host(otg, host); + return x->set_host(x, host); } /* for usb peripheral controller drivers */ /* Context: can sleep */ static inline int -otg_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *periph) +otg_set_peripheral(struct usb_phy *x, struct usb_gadget *periph) { - return otg->set_peripheral(otg, periph); + return x->set_peripheral(x, periph); } static inline int -otg_set_power(struct otg_transceiver *otg, unsigned mA) +otg_set_power(struct usb_phy *x, unsigned mA) { - return otg->set_power(otg, mA); + return x->set_power(x, mA); } /* Context: can sleep */ static inline int -otg_set_suspend(struct otg_transceiver *otg, int suspend) +otg_set_suspend(struct usb_phy *x, int suspend) { - if (otg->set_suspend != NULL) - return otg->set_suspend(otg, suspend); + if (x->set_suspend != NULL) + return x->set_suspend(x, suspend); else return 0; } static inline int -otg_start_srp(struct otg_transceiver *otg) +otg_start_srp(struct usb_phy *x) { - return otg->start_srp(otg); + return x->start_srp(x); } /* notifiers */ static inline int -otg_register_notifier(struct otg_transceiver *otg, struct notifier_block *nb) +otg_register_notifier(struct usb_phy *x, struct notifier_block *nb) { - return atomic_notifier_chain_register(&otg->notifier, nb); + return atomic_notifier_chain_register(&x->notifier, nb); } static inline void -otg_unregister_notifier(struct otg_transceiver *otg, struct notifier_block *nb) +otg_unregister_notifier(struct usb_phy *x, struct notifier_block *nb) { - atomic_notifier_chain_unregister(&otg->notifier, nb); + atomic_notifier_chain_unregister(&x->notifier, nb); } /* for OTG controller drivers (and maybe other stuff) */ diff --git a/include/linux/usb/ulpi.h b/include/linux/usb/ulpi.h index 9595796d62ed..51ebf72bc449 100644 --- a/include/linux/usb/ulpi.h +++ b/include/linux/usb/ulpi.h @@ -181,7 +181,7 @@ /*-------------------------------------------------------------------------*/ -struct otg_transceiver *otg_ulpi_create(struct otg_io_access_ops *ops, +struct usb_phy *otg_ulpi_create(struct otg_io_access_ops *ops, unsigned int flags); #ifdef CONFIG_USB_ULPI_VIEWPORT From de07e18c00c403d5076a5a697d83fe3ced73bc30 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:03 +0200 Subject: [PATCH 085/269] usb: otg: Rename usb_xceiv_event to usb_phy_event Convert all users. Signed-off-by: Heikki Krogerus Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- drivers/usb/otg/ab8500-usb.c | 2 +- drivers/usb/otg/twl4030-usb.c | 2 +- include/linux/usb/otg.h | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c index 5f06dda7db61..b46a5fe178ef 100644 --- a/drivers/usb/otg/ab8500-usb.c +++ b/drivers/usb/otg/ab8500-usb.c @@ -153,7 +153,7 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab) u8 reg; enum ab8500_usb_link_status lsts; void *v = NULL; - enum usb_xceiv_events event; + enum usb_phy_events event; abx500_get_register_interruptible(ab->dev, AB8500_USB, diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index beeecc239d18..906d524b94bb 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -246,7 +246,7 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits) /*-------------------------------------------------------------------------*/ -static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl) +static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl) { int status; int linkstat = USB_EVENT_NONE; diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index e0bc55702a89..723a000146f8 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -35,7 +35,7 @@ enum usb_otg_state { OTG_STATE_A_VBUS_ERR, }; -enum usb_xceiv_events { +enum usb_phy_events { USB_EVENT_NONE, /* no events or cable disconnected */ USB_EVENT_VBUS, /* vbus valid event */ USB_EVENT_ID, /* id was grounded */ @@ -66,7 +66,7 @@ struct usb_phy { u8 default_a; enum usb_otg_state state; - enum usb_xceiv_events last_event; + enum usb_phy_events last_event; struct usb_bus *host; struct usb_gadget *gadget; @@ -74,7 +74,7 @@ struct usb_phy { struct otg_io_access_ops *io_ops; void __iomem *io_priv; - /* for notification of usb_xceiv_events */ + /* for notification of usb_phy_events */ struct atomic_notifier_head notifier; /* to pass extra port status to the root hub */ From 7a8a3a9bec7432eedcb32b54a3940d0593246060 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:04 +0200 Subject: [PATCH 086/269] usb: otg: Separate otg members from usb_phy Introducing struct otg and collecting otg specific members to it from struct usb_phy. There are no changes to struct usb_phy at this stage. This also renames transceiver specific functions, and offers aliases for the old otg ones. Signed-off-by: Heikki Krogerus Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- drivers/usb/otg/otg.c | 38 ++++++++-------- include/linux/usb/otg.h | 96 +++++++++++++++++++++++++++++++++-------- 2 files changed, 98 insertions(+), 36 deletions(-) diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c index 56c0f1781d8c..801e597a1541 100644 --- a/drivers/usb/otg/otg.c +++ b/drivers/usb/otg/otg.c @@ -15,56 +15,56 @@ #include -static struct usb_phy *xceiv; +static struct usb_phy *phy; /** - * otg_get_transceiver - find the (single) OTG transceiver + * usb_get_transceiver - find the (single) USB transceiver * * Returns the transceiver driver, after getting a refcount to it; or * null if there is no such transceiver. The caller is responsible for - * calling otg_put_transceiver() to release that count. + * calling usb_put_transceiver() to release that count. * * For use by USB host and peripheral drivers. */ -struct usb_phy *otg_get_transceiver(void) +struct usb_phy *usb_get_transceiver(void) { - if (xceiv) - get_device(xceiv->dev); - return xceiv; + if (phy) + get_device(phy->dev); + return phy; } -EXPORT_SYMBOL(otg_get_transceiver); +EXPORT_SYMBOL(usb_get_transceiver); /** - * otg_put_transceiver - release the (single) OTG transceiver - * @x: the transceiver returned by otg_get_transceiver() + * usb_put_transceiver - release the (single) USB transceiver + * @x: the transceiver returned by usb_get_transceiver() * - * Releases a refcount the caller received from otg_get_transceiver(). + * Releases a refcount the caller received from usb_get_transceiver(). * * For use by USB host and peripheral drivers. */ -void otg_put_transceiver(struct usb_phy *x) +void usb_put_transceiver(struct usb_phy *x) { if (x) put_device(x->dev); } -EXPORT_SYMBOL(otg_put_transceiver); +EXPORT_SYMBOL(usb_put_transceiver); /** - * otg_set_transceiver - declare the (single) OTG transceiver - * @x: the USB OTG transceiver to be used; or NULL + * usb_set_transceiver - declare the (single) USB transceiver + * @x: the USB transceiver to be used; or NULL * * This call is exclusively for use by transceiver drivers, which * coordinate the activities of drivers for host and peripheral * controllers, and in some cases for VBUS current regulation. */ -int otg_set_transceiver(struct usb_phy *x) +int usb_set_transceiver(struct usb_phy *x) { - if (xceiv && x) + if (phy && x) return -EBUSY; - xceiv = x; + phy = x; return 0; } -EXPORT_SYMBOL(otg_set_transceiver); +EXPORT_SYMBOL(usb_set_transceiver); const char *otg_state_string(enum usb_otg_state state) { diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 723a000146f8..5c1cfbc73555 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -48,11 +48,36 @@ struct usb_phy; /* for transceivers connected thru an ULPI interface, the user must * provide access ops */ -struct otg_io_access_ops { +struct usb_phy_io_ops { int (*read)(struct usb_phy *x, u32 reg); int (*write)(struct usb_phy *x, u32 val, u32 reg); }; +struct usb_otg { + u8 default_a; + + struct usb_phy *phy; + struct usb_bus *host; + struct usb_gadget *gadget; + + /* bind/unbind the host controller */ + int (*set_host)(struct usb_otg *otg, struct usb_bus *host); + + /* bind/unbind the peripheral controller */ + int (*set_peripheral)(struct usb_otg *otg, + struct usb_gadget *gadget); + + /* effective for A-peripheral, ignored for B devices */ + int (*set_vbus)(struct usb_otg *otg, bool enabled); + + /* for B devices only: start session with A-Host */ + int (*start_srp)(struct usb_otg *otg); + + /* start or continue HNP role switch */ + int (*start_hnp)(struct usb_otg *otg); + +}; + /* * the otg driver needs to interact with both device side and host side * usb controllers. it decides which controller is active at a given @@ -68,11 +93,13 @@ struct usb_phy { enum usb_otg_state state; enum usb_phy_events last_event; + struct usb_otg *otg; + struct usb_bus *host; struct usb_gadget *gadget; - struct otg_io_access_ops *io_ops; - void __iomem *io_priv; + struct usb_phy_io_ops *io_ops; + void __iomem *io_priv; /* for notification of usb_phy_events */ struct atomic_notifier_head notifier; @@ -115,7 +142,7 @@ struct usb_phy { /* for board-specific init logic */ -extern int otg_set_transceiver(struct usb_phy *); +extern int usb_set_transceiver(struct usb_phy *); #if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE)) /* sometimes transceivers are accessed only through e.g. ULPI */ @@ -132,7 +159,7 @@ static inline void usb_nop_xceiv_unregister(void) #endif /* helpers for direct access thru low-level io interface */ -static inline int otg_io_read(struct usb_phy *x, u32 reg) +static inline int usb_phy_io_read(struct usb_phy *x, u32 reg) { if (x->io_ops && x->io_ops->read) return x->io_ops->read(x, reg); @@ -140,7 +167,7 @@ static inline int otg_io_read(struct usb_phy *x, u32 reg) return -EINVAL; } -static inline int otg_io_write(struct usb_phy *x, u32 val, u32 reg) +static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg) { if (x->io_ops && x->io_ops->write) return x->io_ops->write(x, val, reg); @@ -149,7 +176,7 @@ static inline int otg_io_write(struct usb_phy *x, u32 val, u32 reg) } static inline int -otg_init(struct usb_phy *x) +usb_phy_init(struct usb_phy *x) { if (x->init) return x->init(x); @@ -158,7 +185,7 @@ otg_init(struct usb_phy *x) } static inline void -otg_shutdown(struct usb_phy *x) +usb_phy_shutdown(struct usb_phy *x) { if (x->shutdown) x->shutdown(x); @@ -166,16 +193,16 @@ otg_shutdown(struct usb_phy *x) /* for usb host and peripheral controller drivers */ #ifdef CONFIG_USB_OTG_UTILS -extern struct usb_phy *otg_get_transceiver(void); -extern void otg_put_transceiver(struct usb_phy *); +extern struct usb_phy *usb_get_transceiver(void); +extern void usb_put_transceiver(struct usb_phy *); extern const char *otg_state_string(enum usb_otg_state state); #else -static inline struct usb_phy *otg_get_transceiver(void) +static inline struct usb_phy *usb_get_transceiver(void) { return NULL; } -static inline void otg_put_transceiver(struct usb_phy *x) +static inline void usb_put_transceiver(struct usb_phy *x) { } @@ -189,6 +216,9 @@ static inline const char *otg_state_string(enum usb_otg_state state) static inline int otg_start_hnp(struct usb_phy *x) { + if (x->otg && x->otg->start_hnp) + return x->otg->start_hnp(x->otg); + return x->start_hnp(x); } @@ -196,6 +226,9 @@ otg_start_hnp(struct usb_phy *x) static inline int otg_set_vbus(struct usb_phy *x, bool enabled) { + if (x->otg && x->otg->set_vbus) + return x->otg->set_vbus(x->otg, enabled); + return x->set_vbus(x, enabled); } @@ -203,6 +236,9 @@ otg_set_vbus(struct usb_phy *x, bool enabled) static inline int otg_set_host(struct usb_phy *x, struct usb_bus *host) { + if (x->otg && x->otg->set_host) + return x->otg->set_host(x->otg, host); + return x->set_host(x, host); } @@ -212,18 +248,23 @@ otg_set_host(struct usb_phy *x, struct usb_bus *host) static inline int otg_set_peripheral(struct usb_phy *x, struct usb_gadget *periph) { + if (x->otg && x->otg->set_peripheral) + return x->otg->set_peripheral(x->otg, periph); + return x->set_peripheral(x, periph); } static inline int -otg_set_power(struct usb_phy *x, unsigned mA) +usb_phy_set_power(struct usb_phy *x, unsigned mA) { - return x->set_power(x, mA); + if (x && x->set_power) + return x->set_power(x, mA); + return 0; } /* Context: can sleep */ static inline int -otg_set_suspend(struct usb_phy *x, int suspend) +usb_phy_set_suspend(struct usb_phy *x, int suspend) { if (x->set_suspend != NULL) return x->set_suspend(x, suspend); @@ -234,18 +275,21 @@ otg_set_suspend(struct usb_phy *x, int suspend) static inline int otg_start_srp(struct usb_phy *x) { + if (x->otg && x->otg->start_srp) + return x->otg->start_srp(x->otg); + return x->start_srp(x); } /* notifiers */ static inline int -otg_register_notifier(struct usb_phy *x, struct notifier_block *nb) +usb_register_notifier(struct usb_phy *x, struct notifier_block *nb) { return atomic_notifier_chain_register(&x->notifier, nb); } static inline void -otg_unregister_notifier(struct usb_phy *x, struct notifier_block *nb) +usb_unregister_notifier(struct usb_phy *x, struct notifier_block *nb) { atomic_notifier_chain_unregister(&x->notifier, nb); } @@ -253,4 +297,22 @@ otg_unregister_notifier(struct usb_phy *x, struct notifier_block *nb) /* for OTG controller drivers (and maybe other stuff) */ extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num); +/* Temporary aliases for transceiver functions */ +#define otg_set_transceiver(x) usb_set_transceiver(x) +#define otg_get_transceiver() usb_get_transceiver() +#define otg_put_transceiver(x) usb_put_transceiver(x) + +#define otg_io_read(x, a) usb_phy_io_read(x, a) +#define otg_io_write(x, a, b) usb_phy_io_write(x, a, b) + +#define otg_init(x) usb_phy_init(x) +#define otg_shutdown(x) usb_phy_shutdown(x) +#define otg_set_power(x, a) usb_phy_set_power(x, a) +#define otg_set_suspend(x, a) usb_phy_set_suspend(x, a) + +#define otg_register_notifier(x, a) usb_register_notifier(x, a) +#define otg_unregister_notifier(x, a) usb_unregiser_notifier(x, a) + +#define otg_io_access_ops usb_phy_io_ops + #endif /* __LINUX_USB_OTG_H */ From 144713f34727801d55d8858e0f549118b9f691c4 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:05 +0200 Subject: [PATCH 087/269] usb: otg: ab8500: Start using struct usb_otg Use struct usb_otg members with OTG specific functions instead of usb_phy members. Signed-off-by: Heikki Krogerus Acked-by: Mian Yousaf Kaukab Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- drivers/usb/otg/ab8500-usb.c | 91 ++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c index b46a5fe178ef..e6371ff5f583 100644 --- a/drivers/usb/otg/ab8500-usb.c +++ b/drivers/usb/otg/ab8500-usb.c @@ -68,7 +68,7 @@ enum ab8500_usb_link_status { }; struct ab8500_usb { - struct usb_phy otg; + struct usb_phy phy; struct device *dev; int irq_num_id_rise; int irq_num_id_fall; @@ -82,9 +82,9 @@ struct ab8500_usb { int rev; }; -static inline struct ab8500_usb *xceiv_to_ab(struct usb_phy *x) +static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x) { - return container_of(x, struct ab8500_usb, otg); + return container_of(x, struct ab8500_usb, phy); } static void ab8500_usb_wd_workaround(struct ab8500_usb *ab) @@ -169,8 +169,8 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab) /* TODO: Disable regulators. */ ab8500_usb_host_phy_dis(ab); ab8500_usb_peri_phy_dis(ab); - ab->otg.state = OTG_STATE_B_IDLE; - ab->otg.default_a = false; + ab->phy.state = OTG_STATE_B_IDLE; + ab->phy.otg->default_a = false; ab->vbus_draw = 0; event = USB_EVENT_NONE; break; @@ -181,22 +181,22 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab) case USB_LINK_HOST_CHG_NM: case USB_LINK_HOST_CHG_HS: case USB_LINK_HOST_CHG_HS_CHIRP: - if (ab->otg.gadget) { + if (ab->phy.otg->gadget) { /* TODO: Enable regulators. */ ab8500_usb_peri_phy_en(ab); - v = ab->otg.gadget; + v = ab->phy.otg->gadget; } event = USB_EVENT_VBUS; break; case USB_LINK_HM_IDGND: - if (ab->otg.host) { + if (ab->phy.otg->host) { /* TODO: Enable regulators. */ ab8500_usb_host_phy_en(ab); - v = ab->otg.host; + v = ab->phy.otg->host; } - ab->otg.state = OTG_STATE_A_IDLE; - ab->otg.default_a = true; + ab->phy.state = OTG_STATE_A_IDLE; + ab->phy.otg->default_a = true; event = USB_EVENT_ID; break; @@ -212,7 +212,7 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab) break; } - atomic_notifier_call_chain(&ab->otg.notifier, event, v); + atomic_notifier_call_chain(&ab->phy.notifier, event, v); return 0; } @@ -262,27 +262,27 @@ static void ab8500_usb_phy_disable_work(struct work_struct *work) struct ab8500_usb *ab = container_of(work, struct ab8500_usb, phy_dis_work); - if (!ab->otg.host) + if (!ab->phy.otg->host) ab8500_usb_host_phy_dis(ab); - if (!ab->otg.gadget) + if (!ab->phy.otg->gadget) ab8500_usb_peri_phy_dis(ab); } -static int ab8500_usb_set_power(struct usb_phy *otg, unsigned mA) +static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA) { struct ab8500_usb *ab; - if (!otg) + if (!phy) return -ENODEV; - ab = xceiv_to_ab(otg); + ab = phy_to_ab(phy); ab->vbus_draw = mA; if (mA) - atomic_notifier_call_chain(&ab->otg.notifier, - USB_EVENT_ENUMERATED, ab->otg.gadget); + atomic_notifier_call_chain(&ab->phy.notifier, + USB_EVENT_ENUMERATED, ab->phy.otg->gadget); return 0; } @@ -296,15 +296,15 @@ static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend) return 0; } -static int ab8500_usb_set_peripheral(struct usb_phy *otg, - struct usb_gadget *gadget) +static int ab8500_usb_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) { struct ab8500_usb *ab; if (!otg) return -ENODEV; - ab = xceiv_to_ab(otg); + ab = phy_to_ab(otg->phy); /* Some drivers call this function in atomic context. * Do not update ab8500 registers directly till this @@ -313,11 +313,11 @@ static int ab8500_usb_set_peripheral(struct usb_phy *otg, if (!gadget) { /* TODO: Disable regulators. */ - ab->otg.gadget = NULL; + otg->gadget = NULL; schedule_work(&ab->phy_dis_work); } else { - ab->otg.gadget = gadget; - ab->otg.state = OTG_STATE_B_IDLE; + otg->gadget = gadget; + otg->phy->state = OTG_STATE_B_IDLE; /* Phy will not be enabled if cable is already * plugged-in. Schedule to enable phy. @@ -329,15 +329,14 @@ static int ab8500_usb_set_peripheral(struct usb_phy *otg, return 0; } -static int ab8500_usb_set_host(struct usb_phy *otg, - struct usb_bus *host) +static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host) { struct ab8500_usb *ab; if (!otg) return -ENODEV; - ab = xceiv_to_ab(otg); + ab = phy_to_ab(otg->phy); /* Some drivers call this function in atomic context. * Do not update ab8500 registers directly till this @@ -346,10 +345,10 @@ static int ab8500_usb_set_host(struct usb_phy *otg, if (!host) { /* TODO: Disable regulators. */ - ab->otg.host = NULL; + otg->host = NULL; schedule_work(&ab->phy_dis_work); } else { - ab->otg.host = host; + otg->host = host; /* Phy will not be enabled if cable is already * plugged-in. Schedule to enable phy. * Use same delay to avoid any race condition. @@ -472,6 +471,7 @@ static int ab8500_usb_v2_res_setup(struct platform_device *pdev, static int __devinit ab8500_usb_probe(struct platform_device *pdev) { struct ab8500_usb *ab; + struct usb_otg *otg; int err; int rev; @@ -488,19 +488,28 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) if (!ab) return -ENOMEM; + otg = kzalloc(sizeof *otg, GFP_KERNEL); + if (!ab->phy.otg) { + kfree(ab); + return -ENOMEM; + } + ab->dev = &pdev->dev; ab->rev = rev; - ab->otg.dev = ab->dev; - ab->otg.label = "ab8500"; - ab->otg.state = OTG_STATE_UNDEFINED; - ab->otg.set_host = ab8500_usb_set_host; - ab->otg.set_peripheral = ab8500_usb_set_peripheral; - ab->otg.set_suspend = ab8500_usb_set_suspend; - ab->otg.set_power = ab8500_usb_set_power; + ab->phy.dev = ab->dev; + ab->phy.otg = otg; + ab->phy.label = "ab8500"; + ab->phy.set_suspend = ab8500_usb_set_suspend; + ab->phy.set_power = ab8500_usb_set_power; + ab->phy.state = OTG_STATE_UNDEFINED; + + otg->phy = &ab->phy; + otg->set_host = ab8500_usb_set_host; + otg->set_peripheral = ab8500_usb_set_peripheral; platform_set_drvdata(pdev, ab); - ATOMIC_INIT_NOTIFIER_HEAD(&ab->otg.notifier); + ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier); /* v1: Wait for link status to become stable. * all: Updates form set_host and set_peripheral as they are atomic. @@ -520,7 +529,7 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) if (err < 0) goto fail0; - err = otg_set_transceiver(&ab->otg); + err = usb_set_transceiver(&ab->phy); if (err) { dev_err(&pdev->dev, "Can't register transceiver\n"); goto fail1; @@ -532,6 +541,7 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) fail1: ab8500_usb_irq_free(ab); fail0: + kfree(otg); kfree(ab); return err; } @@ -546,13 +556,14 @@ static int __devexit ab8500_usb_remove(struct platform_device *pdev) cancel_work_sync(&ab->phy_dis_work); - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); ab8500_usb_host_phy_dis(ab); ab8500_usb_peri_phy_dis(ab); platform_set_drvdata(pdev, NULL); + kfree(ab->phy.otg); kfree(ab); return 0; From 7e062c0f8888001d28cf74da0c3d16a651bd7489 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:06 +0200 Subject: [PATCH 088/269] usb: otg: fsl: Start using struct usb_otg Use struct usb_otg members with OTG specific functions instead of usb_phy members. Signed-off-by: Heikki Krogerus Acked-by: Li Yang Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- drivers/usb/otg/fsl_otg.c | 113 +++++++++++++++++++++----------------- drivers/usb/otg/fsl_otg.h | 2 +- drivers/usb/otg/otg_fsm.c | 22 ++++---- drivers/usb/otg/otg_fsm.h | 2 +- 4 files changed, 75 insertions(+), 64 deletions(-) diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c index 66db2a117444..be4a63e8302f 100644 --- a/drivers/usb/otg/fsl_otg.c +++ b/drivers/usb/otg/fsl_otg.c @@ -275,7 +275,7 @@ void b_srp_end(unsigned long foo) fsl_otg_dischrg_vbus(0); srp_wait_done = 1; - if ((fsl_otg_dev->otg.state == OTG_STATE_B_SRP_INIT) && + if ((fsl_otg_dev->phy.state == OTG_STATE_B_SRP_INIT) && fsl_otg_dev->fsm.b_sess_vld) fsl_otg_dev->fsm.b_srp_done = 1; } @@ -288,7 +288,7 @@ void b_srp_end(unsigned long foo) void a_wait_enum(unsigned long foo) { VDBG("a_wait_enum timeout\n"); - if (!fsl_otg_dev->otg.host->b_hnp_enable) + if (!fsl_otg_dev->phy.otg->host->b_hnp_enable) fsl_otg_add_timer(a_wait_enum_tmr); else otg_statemachine(&fsl_otg_dev->fsm); @@ -452,14 +452,14 @@ void otg_reset_controller(void) /* Call suspend/resume routines in host driver */ int fsl_otg_start_host(struct otg_fsm *fsm, int on) { - struct usb_phy *xceiv = fsm->transceiver; + struct usb_otg *otg = fsm->otg; struct device *dev; - struct fsl_otg *otg_dev = container_of(xceiv, struct fsl_otg, otg); + struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy); u32 retval = 0; - if (!xceiv->host) + if (!otg->host) return -ENODEV; - dev = xceiv->host->controller; + dev = otg->host->controller; /* * Update a_vbus_vld state as a_vbus_vld int is disabled @@ -518,14 +518,14 @@ end: */ int fsl_otg_start_gadget(struct otg_fsm *fsm, int on) { - struct usb_phy *xceiv = fsm->transceiver; + struct usb_otg *otg = fsm->otg; struct device *dev; - if (!xceiv->gadget || !xceiv->gadget->dev.parent) + if (!otg->gadget || !otg->gadget->dev.parent) return -ENODEV; VDBG("gadget %s\n", on ? "on" : "off"); - dev = xceiv->gadget->dev.parent; + dev = otg->gadget->dev.parent; if (on) { if (dev->driver->resume) @@ -542,14 +542,14 @@ int fsl_otg_start_gadget(struct otg_fsm *fsm, int on) * Called by initialization code of host driver. Register host controller * to the OTG. Suspend host for OTG role detection. */ -static int fsl_otg_set_host(struct usb_phy *otg_p, struct usb_bus *host) +static int fsl_otg_set_host(struct usb_otg *otg, struct usb_bus *host) { - struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); + struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy); - if (!otg_p || otg_dev != fsl_otg_dev) + if (!otg || otg_dev != fsl_otg_dev) return -ENODEV; - otg_p->host = host; + otg->host = host; otg_dev->fsm.a_bus_drop = 0; otg_dev->fsm.a_bus_req = 1; @@ -557,8 +557,8 @@ static int fsl_otg_set_host(struct usb_phy *otg_p, struct usb_bus *host) if (host) { VDBG("host off......\n"); - otg_p->host->otg_port = fsl_otg_initdata.otg_port; - otg_p->host->is_b_host = otg_dev->fsm.id; + otg->host->otg_port = fsl_otg_initdata.otg_port; + otg->host->is_b_host = otg_dev->fsm.id; /* * must leave time for khubd to finish its thing * before yanking the host driver out from under it, @@ -574,7 +574,7 @@ static int fsl_otg_set_host(struct usb_phy *otg_p, struct usb_bus *host) /* Mini-A cable connected */ struct otg_fsm *fsm = &otg_dev->fsm; - otg_p->state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; fsm->protocol = PROTO_UNDEF; } } @@ -587,29 +587,29 @@ static int fsl_otg_set_host(struct usb_phy *otg_p, struct usb_bus *host) } /* Called by initialization code of udc. Register udc to OTG. */ -static int fsl_otg_set_peripheral(struct usb_phy *otg_p, - struct usb_gadget *gadget) +static int fsl_otg_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) { - struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); + struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy); VDBG("otg_dev 0x%x\n", (int)otg_dev); VDBG("fsl_otg_dev 0x%x\n", (int)fsl_otg_dev); - if (!otg_p || otg_dev != fsl_otg_dev) + if (!otg || otg_dev != fsl_otg_dev) return -ENODEV; if (!gadget) { - if (!otg_dev->otg.default_a) - otg_p->gadget->ops->vbus_draw(otg_p->gadget, 0); - usb_gadget_vbus_disconnect(otg_dev->otg.gadget); - otg_dev->otg.gadget = 0; + if (!otg->default_a) + otg->gadget->ops->vbus_draw(otg->gadget, 0); + usb_gadget_vbus_disconnect(otg->gadget); + otg->gadget = 0; otg_dev->fsm.b_bus_req = 0; otg_statemachine(&otg_dev->fsm); return 0; } - otg_p->gadget = gadget; - otg_p->gadget->is_a_peripheral = !otg_dev->fsm.id; + otg->gadget = gadget; + otg->gadget->is_a_peripheral = !otg_dev->fsm.id; otg_dev->fsm.b_bus_req = 1; @@ -625,11 +625,11 @@ static int fsl_otg_set_peripheral(struct usb_phy *otg_p, } /* Set OTG port power, only for B-device */ -static int fsl_otg_set_power(struct usb_phy *otg_p, unsigned mA) +static int fsl_otg_set_power(struct usb_phy *phy, unsigned mA) { if (!fsl_otg_dev) return -ENODEV; - if (otg_p->state == OTG_STATE_B_PERIPHERAL) + if (phy->state == OTG_STATE_B_PERIPHERAL) pr_info("FSL OTG: Draw %d mA\n", mA); return 0; @@ -658,12 +658,12 @@ static void fsl_otg_event(struct work_struct *work) } /* B-device start SRP */ -static int fsl_otg_start_srp(struct usb_phy *otg_p) +static int fsl_otg_start_srp(struct usb_otg *otg) { - struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); + struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy); - if (!otg_p || otg_dev != fsl_otg_dev - || otg_p->state != OTG_STATE_B_IDLE) + if (!otg || otg_dev != fsl_otg_dev + || otg->phy->state != OTG_STATE_B_IDLE) return -ENODEV; otg_dev->fsm.b_bus_req = 1; @@ -673,11 +673,11 @@ static int fsl_otg_start_srp(struct usb_phy *otg_p) } /* A_host suspend will call this function to start hnp */ -static int fsl_otg_start_hnp(struct usb_phy *otg_p) +static int fsl_otg_start_hnp(struct usb_otg *otg) { - struct fsl_otg *otg_dev = container_of(otg_p, struct fsl_otg, otg); + struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy); - if (!otg_p || otg_dev != fsl_otg_dev) + if (!otg || otg_dev != fsl_otg_dev) return -ENODEV; DBG("start_hnp...n"); @@ -698,7 +698,7 @@ static int fsl_otg_start_hnp(struct usb_phy *otg_p) irqreturn_t fsl_otg_isr(int irq, void *dev_id) { struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm; - struct usb_phy *otg = &((struct fsl_otg *)dev_id)->otg; + struct usb_otg *otg = ((struct fsl_otg *)dev_id)->phy.otg; u32 otg_int_src, otg_sc; otg_sc = fsl_readl(&usb_dr_regs->otgsc); @@ -774,6 +774,12 @@ static int fsl_otg_conf(struct platform_device *pdev) if (!fsl_otg_tc) return -ENOMEM; + fsl_otg_tc->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL); + if (!fsl_otg_tc->phy.otg) { + kfree(fsl_otg_tc); + return -ENOMEM; + } + INIT_DELAYED_WORK(&fsl_otg_tc->otg_event, fsl_otg_event); INIT_LIST_HEAD(&active_timers); @@ -788,17 +794,19 @@ static int fsl_otg_conf(struct platform_device *pdev) fsl_otg_tc->fsm.ops = &fsl_otg_ops; /* initialize the otg structure */ - fsl_otg_tc->otg.label = DRIVER_DESC; - fsl_otg_tc->otg.set_host = fsl_otg_set_host; - fsl_otg_tc->otg.set_peripheral = fsl_otg_set_peripheral; - fsl_otg_tc->otg.set_power = fsl_otg_set_power; - fsl_otg_tc->otg.start_hnp = fsl_otg_start_hnp; - fsl_otg_tc->otg.start_srp = fsl_otg_start_srp; + fsl_otg_tc->phy.label = DRIVER_DESC; + fsl_otg_tc->phy.set_power = fsl_otg_set_power; + + fsl_otg_tc->phy.otg->phy = &fsl_otg_tc->phy; + fsl_otg_tc->phy.otg->set_host = fsl_otg_set_host; + fsl_otg_tc->phy.otg->set_peripheral = fsl_otg_set_peripheral; + fsl_otg_tc->phy.otg->start_hnp = fsl_otg_start_hnp; + fsl_otg_tc->phy.otg->start_srp = fsl_otg_start_srp; fsl_otg_dev = fsl_otg_tc; /* Store the otg transceiver */ - status = otg_set_transceiver(&fsl_otg_tc->otg); + status = usb_set_transceiver(&fsl_otg_tc->phy); if (status) { pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n"); goto err; @@ -807,6 +815,7 @@ static int fsl_otg_conf(struct platform_device *pdev) return 0; err: fsl_otg_uninit_timers(); + kfree(fsl_otg_tc->phy.otg); kfree(fsl_otg_tc); return status; } @@ -815,19 +824,19 @@ err: int usb_otg_start(struct platform_device *pdev) { struct fsl_otg *p_otg; - struct usb_phy *otg_trans = otg_get_transceiver(); + struct usb_phy *otg_trans = usb_get_transceiver(); struct otg_fsm *fsm; int status; struct resource *res; u32 temp; struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; - p_otg = container_of(otg_trans, struct fsl_otg, otg); + p_otg = container_of(otg_trans, struct fsl_otg, phy); fsm = &p_otg->fsm; /* Initialize the state machine structure with default values */ SET_OTG_STATE(otg_trans, OTG_STATE_UNDEFINED); - fsm->transceiver = &p_otg->otg; + fsm->otg = p_otg->phy.otg; /* We don't require predefined MEM/IRQ resource index */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -857,9 +866,10 @@ int usb_otg_start(struct platform_device *pdev) status = request_irq(p_otg->irq, fsl_otg_isr, IRQF_SHARED, driver_name, p_otg); if (status) { - dev_dbg(p_otg->otg.dev, "can't get IRQ %d, error %d\n", + dev_dbg(p_otg->phy.dev, "can't get IRQ %d, error %d\n", p_otg->irq, status); iounmap(p_otg->dr_mem_map); + kfree(p_otg->phy.otg); kfree(p_otg); return status; } @@ -919,10 +929,10 @@ int usb_otg_start(struct platform_device *pdev) * Also: record initial state of ID pin */ if (fsl_readl(&p_otg->dr_mem_map->otgsc) & OTGSC_STS_USB_ID) { - p_otg->otg.state = OTG_STATE_UNDEFINED; + p_otg->phy.state = OTG_STATE_UNDEFINED; p_otg->fsm.id = 1; } else { - p_otg->otg.state = OTG_STATE_A_IDLE; + p_otg->phy.state = OTG_STATE_A_IDLE; p_otg->fsm.id = 0; } @@ -978,7 +988,7 @@ static int show_fsl_usb2_otg_state(struct device *dev, /* State */ t = scnprintf(next, size, "OTG state: %s\n\n", - otg_state_string(fsl_otg_dev->otg.state)); + otg_state_string(fsl_otg_dev->phy.state)); size -= t; next += t; @@ -1124,12 +1134,13 @@ static int __devexit fsl_otg_remove(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); free_irq(fsl_otg_dev->irq, fsl_otg_dev); iounmap((void *)usb_dr_regs); fsl_otg_uninit_timers(); + kfree(fsl_otg_dev->phy.otg); kfree(fsl_otg_dev); device_remove_file(&pdev->dev, &dev_attr_fsl_usb2_otg_state); diff --git a/drivers/usb/otg/fsl_otg.h b/drivers/usb/otg/fsl_otg.h index caec254ad819..ca266280895d 100644 --- a/drivers/usb/otg/fsl_otg.h +++ b/drivers/usb/otg/fsl_otg.h @@ -369,7 +369,7 @@ inline struct fsl_otg_timer *otg_timer_initializer } struct fsl_otg { - struct usb_phy otg; + struct usb_phy phy; struct otg_fsm fsm; struct usb_dr_mmap *dr_mem_map; struct delayed_work otg_event; diff --git a/drivers/usb/otg/otg_fsm.c b/drivers/usb/otg/otg_fsm.c index 09117387d2a4..ade131a8ae5e 100644 --- a/drivers/usb/otg/otg_fsm.c +++ b/drivers/usb/otg/otg_fsm.c @@ -117,10 +117,10 @@ void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state) int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state) { state_changed = 1; - if (fsm->transceiver->state == new_state) + if (fsm->otg->phy->state == new_state) return 0; VDBG("Set state: %s\n", otg_state_string(new_state)); - otg_leave_state(fsm, fsm->transceiver->state); + otg_leave_state(fsm, fsm->otg->phy->state); switch (new_state) { case OTG_STATE_B_IDLE: otg_drv_vbus(fsm, 0); @@ -155,8 +155,8 @@ int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state) otg_loc_conn(fsm, 0); otg_loc_sof(fsm, 1); otg_set_protocol(fsm, PROTO_HOST); - usb_bus_start_enum(fsm->transceiver->host, - fsm->transceiver->host->otg_port); + usb_bus_start_enum(fsm->otg->host, + fsm->otg->host->otg_port); break; case OTG_STATE_A_IDLE: otg_drv_vbus(fsm, 0); @@ -221,7 +221,7 @@ int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state) break; } - fsm->transceiver->state = new_state; + fsm->otg->phy->state = new_state; return 0; } @@ -233,7 +233,7 @@ int otg_statemachine(struct otg_fsm *fsm) spin_lock_irqsave(&fsm->lock, flags); - state = fsm->transceiver->state; + state = fsm->otg->phy->state; state_changed = 0; /* State machine state change judgement */ @@ -248,7 +248,7 @@ int otg_statemachine(struct otg_fsm *fsm) case OTG_STATE_B_IDLE: if (!fsm->id) otg_set_state(fsm, OTG_STATE_A_IDLE); - else if (fsm->b_sess_vld && fsm->transceiver->gadget) + else if (fsm->b_sess_vld && fsm->otg->gadget) otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); else if (fsm->b_bus_req && fsm->b_sess_end && fsm->b_se0_srp) otg_set_state(fsm, OTG_STATE_B_SRP_INIT); @@ -260,7 +260,7 @@ int otg_statemachine(struct otg_fsm *fsm) case OTG_STATE_B_PERIPHERAL: if (!fsm->id || !fsm->b_sess_vld) otg_set_state(fsm, OTG_STATE_B_IDLE); - else if (fsm->b_bus_req && fsm->transceiver-> + else if (fsm->b_bus_req && fsm->otg-> gadget->b_hnp_enable && fsm->a_bus_suspend) otg_set_state(fsm, OTG_STATE_B_WAIT_ACON); break; @@ -302,7 +302,7 @@ int otg_statemachine(struct otg_fsm *fsm) break; case OTG_STATE_A_HOST: if ((!fsm->a_bus_req || fsm->a_suspend_req) && - fsm->transceiver->host->b_hnp_enable) + fsm->otg->host->b_hnp_enable) otg_set_state(fsm, OTG_STATE_A_SUSPEND); else if (fsm->id || !fsm->b_conn || fsm->a_bus_drop) otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); @@ -310,9 +310,9 @@ int otg_statemachine(struct otg_fsm *fsm) otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); break; case OTG_STATE_A_SUSPEND: - if (!fsm->b_conn && fsm->transceiver->host->b_hnp_enable) + if (!fsm->b_conn && fsm->otg->host->b_hnp_enable) otg_set_state(fsm, OTG_STATE_A_PERIPHERAL); - else if (!fsm->b_conn && !fsm->transceiver->host->b_hnp_enable) + else if (!fsm->b_conn && !fsm->otg->host->b_hnp_enable) otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); else if (fsm->a_bus_req || fsm->b_bus_resume) otg_set_state(fsm, OTG_STATE_A_HOST); diff --git a/drivers/usb/otg/otg_fsm.h b/drivers/usb/otg/otg_fsm.h index 5e589ae9a199..c30a2e1d9e46 100644 --- a/drivers/usb/otg/otg_fsm.h +++ b/drivers/usb/otg/otg_fsm.h @@ -82,7 +82,7 @@ struct otg_fsm { int loc_sof; struct otg_fsm_ops *ops; - struct usb_phy *transceiver; + struct usb_otg *otg; /* Current usb protocol used: 0:undefine; 1:host; 2:client */ int protocol; From 16bc1bb2d87feabe7a69c68c4795b54273ed80f1 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:07 +0200 Subject: [PATCH 089/269] usb: otg: gpio_vbus: Start using struct usb_otg Use struct usb_otg members with OTG specific functions instead of usb_phy members. Signed-off-by: Heikki Krogerus Reviewed-by: Marek Vasut Cc: Philipp Zabel Signed-off-by: Felipe Balbi --- drivers/usb/otg/gpio_vbus.c | 61 ++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c index 4e1b1384dc89..3ece43a2e4c1 100644 --- a/drivers/usb/otg/gpio_vbus.c +++ b/drivers/usb/otg/gpio_vbus.c @@ -32,7 +32,7 @@ * Needs to be loaded before the UDC driver that will use it. */ struct gpio_vbus_data { - struct usb_phy otg; + struct usb_phy phy; struct device *dev; struct regulator *vbus_draw; int vbus_draw_enabled; @@ -98,7 +98,7 @@ static void gpio_vbus_work(struct work_struct *work) struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data; int gpio; - if (!gpio_vbus->otg.gadget) + if (!gpio_vbus->phy.otg->gadget) return; /* Peripheral controllers which manage the pullup themselves won't have @@ -108,8 +108,8 @@ static void gpio_vbus_work(struct work_struct *work) */ gpio = pdata->gpio_pullup; if (is_vbus_powered(pdata)) { - gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL; - usb_gadget_vbus_connect(gpio_vbus->otg.gadget); + gpio_vbus->phy.state = OTG_STATE_B_PERIPHERAL; + usb_gadget_vbus_connect(gpio_vbus->phy.otg->gadget); /* drawing a "unit load" is *always* OK, except for OTG */ set_vbus_draw(gpio_vbus, 100); @@ -124,8 +124,8 @@ static void gpio_vbus_work(struct work_struct *work) set_vbus_draw(gpio_vbus, 0); - usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget); - gpio_vbus->otg.state = OTG_STATE_B_IDLE; + usb_gadget_vbus_disconnect(gpio_vbus->phy.otg->gadget); + gpio_vbus->phy.state = OTG_STATE_B_IDLE; } } @@ -135,12 +135,13 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data) struct platform_device *pdev = data; struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data; struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev); + struct usb_otg *otg = gpio_vbus->phy.otg; dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n", is_vbus_powered(pdata) ? "supplied" : "inactive", - gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none"); + otg->gadget ? otg->gadget->name : "none"); - if (gpio_vbus->otg.gadget) + if (otg->gadget) schedule_work(&gpio_vbus->work); return IRQ_HANDLED; @@ -149,15 +150,15 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data) /* OTG transceiver interface */ /* bind/unbind the peripheral controller */ -static int gpio_vbus_set_peripheral(struct usb_phy *otg, - struct usb_gadget *gadget) +static int gpio_vbus_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) { struct gpio_vbus_data *gpio_vbus; struct gpio_vbus_mach_info *pdata; struct platform_device *pdev; int gpio, irq; - gpio_vbus = container_of(otg, struct gpio_vbus_data, otg); + gpio_vbus = container_of(otg->phy, struct gpio_vbus_data, phy); pdev = to_platform_device(gpio_vbus->dev); pdata = gpio_vbus->dev->platform_data; irq = gpio_to_irq(pdata->gpio_vbus); @@ -174,7 +175,7 @@ static int gpio_vbus_set_peripheral(struct usb_phy *otg, set_vbus_draw(gpio_vbus, 0); usb_gadget_vbus_disconnect(otg->gadget); - otg->state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; otg->gadget = NULL; return 0; @@ -189,23 +190,23 @@ static int gpio_vbus_set_peripheral(struct usb_phy *otg, } /* effective for B devices, ignored for A-peripheral */ -static int gpio_vbus_set_power(struct usb_phy *otg, unsigned mA) +static int gpio_vbus_set_power(struct usb_phy *phy, unsigned mA) { struct gpio_vbus_data *gpio_vbus; - gpio_vbus = container_of(otg, struct gpio_vbus_data, otg); + gpio_vbus = container_of(phy, struct gpio_vbus_data, phy); - if (otg->state == OTG_STATE_B_PERIPHERAL) + if (phy->state == OTG_STATE_B_PERIPHERAL) set_vbus_draw(gpio_vbus, mA); return 0; } /* for non-OTG B devices: set/clear transceiver suspend mode */ -static int gpio_vbus_set_suspend(struct usb_phy *otg, int suspend) +static int gpio_vbus_set_suspend(struct usb_phy *phy, int suspend) { struct gpio_vbus_data *gpio_vbus; - gpio_vbus = container_of(otg, struct gpio_vbus_data, otg); + gpio_vbus = container_of(phy, struct gpio_vbus_data, phy); /* draw max 0 mA from vbus in suspend mode; or the previously * recorded amount of current if not suspended @@ -213,7 +214,7 @@ static int gpio_vbus_set_suspend(struct usb_phy *otg, int suspend) * NOTE: high powered configs (mA > 100) may draw up to 2.5 mA * if they're wake-enabled ... we don't handle that yet. */ - return gpio_vbus_set_power(otg, suspend ? 0 : gpio_vbus->mA); + return gpio_vbus_set_power(phy, suspend ? 0 : gpio_vbus->mA); } /* platform driver interface */ @@ -233,13 +234,21 @@ static int __init gpio_vbus_probe(struct platform_device *pdev) if (!gpio_vbus) return -ENOMEM; + gpio_vbus->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL); + if (!gpio_vbus->phy.otg) { + kfree(gpio_vbus); + return -ENOMEM; + } + platform_set_drvdata(pdev, gpio_vbus); gpio_vbus->dev = &pdev->dev; - gpio_vbus->otg.label = "gpio-vbus"; - gpio_vbus->otg.state = OTG_STATE_UNDEFINED; - gpio_vbus->otg.set_peripheral = gpio_vbus_set_peripheral; - gpio_vbus->otg.set_power = gpio_vbus_set_power; - gpio_vbus->otg.set_suspend = gpio_vbus_set_suspend; + gpio_vbus->phy.label = "gpio-vbus"; + gpio_vbus->phy.set_power = gpio_vbus_set_power; + gpio_vbus->phy.set_suspend = gpio_vbus_set_suspend; + gpio_vbus->phy.state = OTG_STATE_UNDEFINED; + + gpio_vbus->phy.otg->phy = &gpio_vbus->phy; + gpio_vbus->phy.otg->set_peripheral = gpio_vbus_set_peripheral; err = gpio_request(gpio, "vbus_detect"); if (err) { @@ -288,7 +297,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev) } /* only active when a gadget is registered */ - err = otg_set_transceiver(&gpio_vbus->otg); + err = usb_set_transceiver(&gpio_vbus->phy); if (err) { dev_err(&pdev->dev, "can't register transceiver, err: %d\n", err); @@ -304,6 +313,7 @@ err_irq: gpio_free(pdata->gpio_vbus); err_gpio: platform_set_drvdata(pdev, NULL); + kfree(gpio_vbus->phy.otg); kfree(gpio_vbus); return err; } @@ -316,13 +326,14 @@ static int __exit gpio_vbus_remove(struct platform_device *pdev) regulator_put(gpio_vbus->vbus_draw); - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); free_irq(gpio_to_irq(gpio), &pdev->dev); if (gpio_is_valid(pdata->gpio_pullup)) gpio_free(pdata->gpio_pullup); gpio_free(gpio); platform_set_drvdata(pdev, NULL); + kfree(gpio_vbus->phy.otg); kfree(gpio_vbus); return 0; From 819d1c742b408bd6cdab77d4308940600811cf20 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:08 +0200 Subject: [PATCH 090/269] usb: otg: isp1301_omap: Start using struct usb_otg Use struct usb_otg members with OTG specific functions instead of usb_phy members. Signed-off-by: Heikki Krogerus Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- drivers/usb/otg/isp1301_omap.c | 232 +++++++++++++++++---------------- 1 file changed, 121 insertions(+), 111 deletions(-) diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c index 1bc27948ac22..70cf5d7bca48 100644 --- a/drivers/usb/otg/isp1301_omap.c +++ b/drivers/usb/otg/isp1301_omap.c @@ -52,7 +52,7 @@ MODULE_DESCRIPTION("ISP1301 USB OTG Transceiver Driver"); MODULE_LICENSE("GPL"); struct isp1301 { - struct usb_phy otg; + struct usb_phy phy; struct i2c_client *client; void (*i2c_release)(struct device *dev); @@ -236,7 +236,7 @@ isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits) static inline const char *state_name(struct isp1301 *isp) { - return otg_state_string(isp->otg.state); + return otg_state_string(isp->phy.state); } /*-------------------------------------------------------------------------*/ @@ -251,7 +251,7 @@ static inline const char *state_name(struct isp1301 *isp) static void power_down(struct isp1301 *isp) { - isp->otg.state = OTG_STATE_UNDEFINED; + isp->phy.state = OTG_STATE_UNDEFINED; // isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN); isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND); @@ -280,13 +280,13 @@ static int host_suspend(struct isp1301 *isp) #else struct device *dev; - if (!isp->otg.host) + if (!isp->phy.otg->host) return -ENODEV; /* Currently ASSUMES only the OTG port matters; * other ports could be active... */ - dev = isp->otg.host->controller; + dev = isp->phy.otg->host->controller; return dev->driver->suspend(dev, 3, 0); #endif } @@ -298,20 +298,20 @@ static int host_resume(struct isp1301 *isp) #else struct device *dev; - if (!isp->otg.host) + if (!isp->phy.otg->host) return -ENODEV; - dev = isp->otg.host->controller; + dev = isp->phy.otg->host->controller; return dev->driver->resume(dev, 0); #endif } static int gadget_suspend(struct isp1301 *isp) { - isp->otg.gadget->b_hnp_enable = 0; - isp->otg.gadget->a_hnp_support = 0; - isp->otg.gadget->a_alt_hnp_support = 0; - return usb_gadget_vbus_disconnect(isp->otg.gadget); + isp->phy.otg->gadget->b_hnp_enable = 0; + isp->phy.otg->gadget->a_hnp_support = 0; + isp->phy.otg->gadget->a_alt_hnp_support = 0; + return usb_gadget_vbus_disconnect(isp->phy.otg->gadget); } /*-------------------------------------------------------------------------*/ @@ -341,19 +341,19 @@ static void a_idle(struct isp1301 *isp, const char *tag) { u32 l; - if (isp->otg.state == OTG_STATE_A_IDLE) + if (isp->phy.state == OTG_STATE_A_IDLE) return; - isp->otg.default_a = 1; - if (isp->otg.host) { - isp->otg.host->is_b_host = 0; + isp->phy.otg->default_a = 1; + if (isp->phy.otg->host) { + isp->phy.otg->host->is_b_host = 0; host_suspend(isp); } - if (isp->otg.gadget) { - isp->otg.gadget->is_a_peripheral = 1; + if (isp->phy.otg->gadget) { + isp->phy.otg->gadget->is_a_peripheral = 1; gadget_suspend(isp); } - isp->otg.state = OTG_STATE_A_IDLE; + isp->phy.state = OTG_STATE_A_IDLE; l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS; omap_writel(l, OTG_CTRL); isp->last_otg_ctrl = l; @@ -365,19 +365,19 @@ static void b_idle(struct isp1301 *isp, const char *tag) { u32 l; - if (isp->otg.state == OTG_STATE_B_IDLE) + if (isp->phy.state == OTG_STATE_B_IDLE) return; - isp->otg.default_a = 0; - if (isp->otg.host) { - isp->otg.host->is_b_host = 1; + isp->phy.otg->default_a = 0; + if (isp->phy.otg->host) { + isp->phy.otg->host->is_b_host = 1; host_suspend(isp); } - if (isp->otg.gadget) { - isp->otg.gadget->is_a_peripheral = 0; + if (isp->phy.otg->gadget) { + isp->phy.otg->gadget->is_a_peripheral = 0; gadget_suspend(isp); } - isp->otg.state = OTG_STATE_B_IDLE; + isp->phy.state = OTG_STATE_B_IDLE; l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS; omap_writel(l, OTG_CTRL); isp->last_otg_ctrl = l; @@ -478,7 +478,7 @@ static void check_state(struct isp1301 *isp, const char *tag) default: break; } - if (isp->otg.state == state && !extra) + if (isp->phy.state == state && !extra) return; pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag, otg_state_string(state), fsm, state_name(isp), @@ -502,22 +502,23 @@ static void update_otg1(struct isp1301 *isp, u8 int_src) if (int_src & INTR_SESS_VLD) otg_ctrl |= OTG_ASESSVLD; - else if (isp->otg.state == OTG_STATE_A_WAIT_VFALL) { + else if (isp->phy.state == OTG_STATE_A_WAIT_VFALL) { a_idle(isp, "vfall"); otg_ctrl &= ~OTG_CTRL_BITS; } if (int_src & INTR_VBUS_VLD) otg_ctrl |= OTG_VBUSVLD; if (int_src & INTR_ID_GND) { /* default-A */ - if (isp->otg.state == OTG_STATE_B_IDLE - || isp->otg.state == OTG_STATE_UNDEFINED) { + if (isp->phy.state == OTG_STATE_B_IDLE + || isp->phy.state + == OTG_STATE_UNDEFINED) { a_idle(isp, "init"); return; } } else { /* default-B */ otg_ctrl |= OTG_ID; - if (isp->otg.state == OTG_STATE_A_IDLE - || isp->otg.state == OTG_STATE_UNDEFINED) { + if (isp->phy.state == OTG_STATE_A_IDLE + || isp->phy.state == OTG_STATE_UNDEFINED) { b_idle(isp, "init"); return; } @@ -551,14 +552,14 @@ static void otg_update_isp(struct isp1301 *isp) isp->last_otg_ctrl = otg_ctrl; otg_ctrl = otg_ctrl & OTG_XCEIV_INPUTS; - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_B_IDLE: case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_SRP_INIT: if (!(otg_ctrl & OTG_PULLUP)) { // if (otg_ctrl & OTG_B_HNPEN) { - if (isp->otg.gadget->b_hnp_enable) { - isp->otg.state = OTG_STATE_B_WAIT_ACON; + if (isp->phy.otg->gadget->b_hnp_enable) { + isp->phy.state = OTG_STATE_B_WAIT_ACON; pr_debug(" --> b_wait_acon\n"); } goto pulldown; @@ -585,10 +586,10 @@ pulldown: else clr |= ISP; \ } while (0) - if (!(isp->otg.host)) + if (!(isp->phy.otg->host)) otg_ctrl &= ~OTG_DRV_VBUS; - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_A_SUSPEND: if (otg_ctrl & OTG_DRV_VBUS) { set |= OTG1_VBUS_DRV; @@ -599,7 +600,7 @@ pulldown: /* FALLTHROUGH */ case OTG_STATE_A_VBUS_ERR: - isp->otg.state = OTG_STATE_A_WAIT_VFALL; + isp->phy.state = OTG_STATE_A_WAIT_VFALL; pr_debug(" --> a_wait_vfall\n"); /* FALLTHROUGH */ case OTG_STATE_A_WAIT_VFALL: @@ -608,7 +609,7 @@ pulldown: break; case OTG_STATE_A_IDLE: if (otg_ctrl & OTG_DRV_VBUS) { - isp->otg.state = OTG_STATE_A_WAIT_VRISE; + isp->phy.state = OTG_STATE_A_WAIT_VRISE; pr_debug(" --> a_wait_vrise\n"); } /* FALLTHROUGH */ @@ -628,17 +629,17 @@ pulldown: if (otg_change & OTG_PULLUP) { u32 l; - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_B_IDLE: if (clr & OTG1_DP_PULLUP) break; - isp->otg.state = OTG_STATE_B_PERIPHERAL; + isp->phy.state = OTG_STATE_B_PERIPHERAL; pr_debug(" --> b_peripheral\n"); break; case OTG_STATE_A_SUSPEND: if (clr & OTG1_DP_PULLUP) break; - isp->otg.state = OTG_STATE_A_PERIPHERAL; + isp->phy.state = OTG_STATE_A_PERIPHERAL; pr_debug(" --> a_peripheral\n"); break; default: @@ -659,6 +660,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) u32 otg_ctrl; int ret = IRQ_NONE; struct isp1301 *isp = _isp; + struct usb_otg *otg = isp->phy.otg; /* update ISP1301 transceiver from OTG controller */ if (otg_irq & OPRT_CHG) { @@ -675,7 +677,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) * remote wakeup (SRP, normal) using their own timer * to give "check cable and A-device" messages. */ - if (isp->otg.state == OTG_STATE_B_SRP_INIT) + if (isp->phy.state == OTG_STATE_B_SRP_INIT) b_idle(isp, "srp_timeout"); omap_writew(B_SRP_TMROUT, OTG_IRQ_SRC); @@ -693,7 +695,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) omap_writel(otg_ctrl, OTG_CTRL); /* subset of b_peripheral()... */ - isp->otg.state = OTG_STATE_B_PERIPHERAL; + isp->phy.state = OTG_STATE_B_PERIPHERAL; pr_debug(" --> b_peripheral\n"); omap_writew(B_HNP_FAIL, OTG_IRQ_SRC); @@ -705,9 +707,9 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) state_name(isp), omap_readl(OTG_CTRL)); isp1301_defer_work(isp, WORK_UPDATE_OTG); - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_A_IDLE: - if (!isp->otg.host) + if (!otg->host) break; isp1301_defer_work(isp, WORK_HOST_RESUME); otg_ctrl = omap_readl(OTG_CTRL); @@ -736,7 +738,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) otg_ctrl |= OTG_BUSDROP; otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS; omap_writel(otg_ctrl, OTG_CTRL); - isp->otg.state = OTG_STATE_A_WAIT_VFALL; + isp->phy.state = OTG_STATE_A_WAIT_VFALL; omap_writew(A_REQ_TMROUT, OTG_IRQ_SRC); ret = IRQ_HANDLED; @@ -750,7 +752,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) otg_ctrl |= OTG_BUSDROP; otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS; omap_writel(otg_ctrl, OTG_CTRL); - isp->otg.state = OTG_STATE_A_VBUS_ERR; + isp->phy.state = OTG_STATE_A_VBUS_ERR; omap_writew(A_VBUS_ERR, OTG_IRQ_SRC); ret = IRQ_HANDLED; @@ -771,7 +773,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) /* role is peripheral */ if (otg_ctrl & OTG_DRIVER_SEL) { - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_A_IDLE: b_idle(isp, __func__); break; @@ -787,19 +789,19 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) omap_writel(otg_ctrl | OTG_A_BUSREQ, OTG_CTRL); } - if (isp->otg.host) { - switch (isp->otg.state) { + if (otg->host) { + switch (isp->phy.state) { case OTG_STATE_B_WAIT_ACON: - isp->otg.state = OTG_STATE_B_HOST; + isp->phy.state = OTG_STATE_B_HOST; pr_debug(" --> b_host\n"); kick = 1; break; case OTG_STATE_A_WAIT_BCON: - isp->otg.state = OTG_STATE_A_HOST; + isp->phy.state = OTG_STATE_A_HOST; pr_debug(" --> a_host\n"); break; case OTG_STATE_A_PERIPHERAL: - isp->otg.state = OTG_STATE_A_WAIT_BCON; + isp->phy.state = OTG_STATE_A_WAIT_BCON; pr_debug(" --> a_wait_bcon\n"); break; default: @@ -813,8 +815,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) ret = IRQ_HANDLED; if (kick) - usb_bus_start_enum(isp->otg.host, - isp->otg.host->otg_port); + usb_bus_start_enum(otg->host, otg->host->otg_port); } check_state(isp, __func__); @@ -930,7 +931,7 @@ static void b_peripheral(struct isp1301 *isp) l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS; omap_writel(l, OTG_CTRL); - usb_gadget_vbus_connect(isp->otg.gadget); + usb_gadget_vbus_connect(isp->phy.otg->gadget); #ifdef CONFIG_USB_OTG enable_vbus_draw(isp, 8); @@ -940,7 +941,7 @@ static void b_peripheral(struct isp1301 *isp) /* UDC driver just set OTG_BSESSVLD */ isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP); isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN); - isp->otg.state = OTG_STATE_B_PERIPHERAL; + isp->phy.state = OTG_STATE_B_PERIPHERAL; pr_debug(" --> b_peripheral\n"); dump_regs(isp, "2periph"); #endif @@ -948,8 +949,9 @@ static void b_peripheral(struct isp1301 *isp) static void isp_update_otg(struct isp1301 *isp, u8 stat) { + struct usb_otg *otg = isp->phy.otg; u8 isp_stat, isp_bstat; - enum usb_otg_state state = isp->otg.state; + enum usb_otg_state state = isp->phy.state; if (stat & INTR_BDIS_ACON) pr_debug("OTG: BDIS_ACON, %s\n", state_name(isp)); @@ -957,7 +959,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) /* start certain state transitions right away */ isp_stat = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE); if (isp_stat & INTR_ID_GND) { - if (isp->otg.default_a) { + if (otg->default_a) { switch (state) { case OTG_STATE_B_IDLE: a_idle(isp, "idle"); @@ -972,7 +974,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) * when HNP is used. */ if (isp_stat & INTR_VBUS_VLD) - isp->otg.state = OTG_STATE_A_HOST; + isp->phy.state = OTG_STATE_A_HOST; break; case OTG_STATE_A_WAIT_VFALL: if (!(isp_stat & INTR_SESS_VLD)) @@ -980,7 +982,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) break; default: if (!(isp_stat & INTR_VBUS_VLD)) - isp->otg.state = OTG_STATE_A_VBUS_ERR; + isp->phy.state = OTG_STATE_A_VBUS_ERR; break; } isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS); @@ -989,14 +991,14 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_HOST: case OTG_STATE_B_WAIT_ACON: - usb_gadget_vbus_disconnect(isp->otg.gadget); + usb_gadget_vbus_disconnect(otg->gadget); break; default: break; } if (state != OTG_STATE_A_IDLE) a_idle(isp, "id"); - if (isp->otg.host && state == OTG_STATE_A_IDLE) + if (otg->host && state == OTG_STATE_A_IDLE) isp1301_defer_work(isp, WORK_HOST_RESUME); isp_bstat = 0; } @@ -1006,10 +1008,10 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) /* if user unplugged mini-A end of cable, * don't bypass A_WAIT_VFALL. */ - if (isp->otg.default_a) { + if (otg->default_a) { switch (state) { default: - isp->otg.state = OTG_STATE_A_WAIT_VFALL; + isp->phy.state = OTG_STATE_A_WAIT_VFALL; break; case OTG_STATE_A_WAIT_VFALL: state = OTG_STATE_A_IDLE; @@ -1022,7 +1024,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) host_suspend(isp); isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_BDIS_ACON_EN); - isp->otg.state = OTG_STATE_B_IDLE; + isp->phy.state = OTG_STATE_B_IDLE; l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; l &= ~OTG_CTRL_BITS; omap_writel(l, OTG_CTRL); @@ -1033,7 +1035,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) } isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS); - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_WAIT_ACON: case OTG_STATE_B_HOST: @@ -1055,7 +1057,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) omap_writel(l, OTG_CTRL); /* FALLTHROUGH */ case OTG_STATE_B_IDLE: - if (isp->otg.gadget && (isp_bstat & OTG_B_SESS_VLD)) { + if (otg->gadget && (isp_bstat & OTG_B_SESS_VLD)) { #ifdef CONFIG_USB_OTG update_otg1(isp, isp_stat); update_otg2(isp, isp_bstat); @@ -1073,7 +1075,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) } } - if (state != isp->otg.state) + if (state != isp->phy.state) pr_debug(" isp, %s -> %s\n", otg_state_string(state), state_name(isp)); @@ -1131,10 +1133,10 @@ isp1301_work(struct work_struct *work) * skip A_WAIT_VRISE; hc transitions invisibly * skip A_WAIT_BCON; same. */ - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_A_WAIT_BCON: case OTG_STATE_A_WAIT_VRISE: - isp->otg.state = OTG_STATE_A_HOST; + isp->phy.state = OTG_STATE_A_HOST; pr_debug(" --> a_host\n"); otg_ctrl = omap_readl(OTG_CTRL); otg_ctrl |= OTG_A_BUSREQ; @@ -1143,7 +1145,7 @@ isp1301_work(struct work_struct *work) omap_writel(otg_ctrl, OTG_CTRL); break; case OTG_STATE_B_WAIT_ACON: - isp->otg.state = OTG_STATE_B_HOST; + isp->phy.state = OTG_STATE_B_HOST; pr_debug(" --> b_host (acon)\n"); break; case OTG_STATE_B_HOST: @@ -1204,6 +1206,7 @@ static void isp1301_release(struct device *dev) /* ugly -- i2c hijacks our memory hook to wait_for_completion() */ if (isp->i2c_release) isp->i2c_release(dev); + kfree(isp->phy.otg); kfree (isp); } @@ -1274,9 +1277,9 @@ static int isp1301_otg_enable(struct isp1301 *isp) /* add or disable the host device+driver */ static int -isp1301_set_host(struct usb_phy *otg, struct usb_bus *host) +isp1301_set_host(struct usb_otg *otg, struct usb_bus *host) { - struct isp1301 *isp = container_of(otg, struct isp1301, otg); + struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy); if (!otg || isp != the_transceiver) return -ENODEV; @@ -1284,21 +1287,21 @@ isp1301_set_host(struct usb_phy *otg, struct usb_bus *host) if (!host) { omap_writew(0, OTG_IRQ_EN); power_down(isp); - isp->otg.host = NULL; + otg->host = NULL; return 0; } #ifdef CONFIG_USB_OTG - isp->otg.host = host; + otg->host = host; dev_dbg(&isp->client->dev, "registered host\n"); host_suspend(isp); - if (isp->otg.gadget) + if (otg->gadget) return isp1301_otg_enable(isp); return 0; #elif !defined(CONFIG_USB_GADGET_OMAP) // FIXME update its refcount - isp->otg.host = host; + otg->host = host; power_up(isp); @@ -1330,9 +1333,9 @@ isp1301_set_host(struct usb_phy *otg, struct usb_bus *host) } static int -isp1301_set_peripheral(struct usb_phy *otg, struct usb_gadget *gadget) +isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) { - struct isp1301 *isp = container_of(otg, struct isp1301, otg); + struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy); #ifndef CONFIG_USB_OTG u32 l; #endif @@ -1342,24 +1345,24 @@ isp1301_set_peripheral(struct usb_phy *otg, struct usb_gadget *gadget) if (!gadget) { omap_writew(0, OTG_IRQ_EN); - if (!isp->otg.default_a) + if (!otg->default_a) enable_vbus_draw(isp, 0); - usb_gadget_vbus_disconnect(isp->otg.gadget); - isp->otg.gadget = NULL; + usb_gadget_vbus_disconnect(otg->gadget); + otg->gadget = NULL; power_down(isp); return 0; } #ifdef CONFIG_USB_OTG - isp->otg.gadget = gadget; + otg->gadget = gadget; dev_dbg(&isp->client->dev, "registered gadget\n"); /* gadget driver may be suspended until vbus_connect () */ - if (isp->otg.host) + if (otg->host) return isp1301_otg_enable(isp); return 0; #elif !defined(CONFIG_USB_OHCI_HCD) && !defined(CONFIG_USB_OHCI_HCD_MODULE) - isp->otg.gadget = gadget; + otg->gadget = gadget; // FIXME update its refcount l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; @@ -1368,7 +1371,7 @@ isp1301_set_peripheral(struct usb_phy *otg, struct usb_gadget *gadget) omap_writel(l, OTG_CTRL); power_up(isp); - isp->otg.state = OTG_STATE_B_IDLE; + isp->phy.state = OTG_STATE_B_IDLE; if (machine_is_omap_h2() || machine_is_omap_h3()) isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); @@ -1409,13 +1412,13 @@ isp1301_set_power(struct usb_phy *dev, unsigned mA) } static int -isp1301_start_srp(struct usb_phy *dev) +isp1301_start_srp(struct usb_otg *otg) { - struct isp1301 *isp = container_of(dev, struct isp1301, otg); + struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy); u32 otg_ctrl; - if (!dev || isp != the_transceiver - || isp->otg.state != OTG_STATE_B_IDLE) + if (!otg || isp != the_transceiver + || isp->phy.state != OTG_STATE_B_IDLE) return -ENODEV; otg_ctrl = omap_readl(OTG_CTRL); @@ -1425,7 +1428,7 @@ isp1301_start_srp(struct usb_phy *dev) otg_ctrl |= OTG_B_BUSREQ; otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK; omap_writel(otg_ctrl, OTG_CTRL); - isp->otg.state = OTG_STATE_B_SRP_INIT; + isp->phy.state = OTG_STATE_B_SRP_INIT; pr_debug("otg: SRP, %s ... %06x\n", state_name(isp), omap_readl(OTG_CTRL)); @@ -1436,27 +1439,26 @@ isp1301_start_srp(struct usb_phy *dev) } static int -isp1301_start_hnp(struct usb_phy *dev) +isp1301_start_hnp(struct usb_otg *otg) { #ifdef CONFIG_USB_OTG - struct isp1301 *isp = container_of(dev, struct isp1301, otg); + struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy); u32 l; - if (!dev || isp != the_transceiver) + if (!otg || isp != the_transceiver) return -ENODEV; - if (isp->otg.default_a && (isp->otg.host == NULL - || !isp->otg.host->b_hnp_enable)) + if (otg->default_a && (otg->host == NULL || !otg->host->b_hnp_enable)) return -ENOTCONN; - if (!isp->otg.default_a && (isp->otg.gadget == NULL - || !isp->otg.gadget->b_hnp_enable)) + if (!otg->default_a && (otg->gadget == NULL + || !otg->gadget->b_hnp_enable)) return -ENOTCONN; /* We want hardware to manage most HNP protocol timings. * So do this part as early as possible... */ - switch (isp->otg.state) { + switch (isp->phy.state) { case OTG_STATE_B_HOST: - isp->otg.state = OTG_STATE_B_PERIPHERAL; + isp->phy.state = OTG_STATE_B_PERIPHERAL; /* caller will suspend next */ break; case OTG_STATE_A_HOST: @@ -1466,7 +1468,7 @@ isp1301_start_hnp(struct usb_phy *dev) MC1_BDIS_ACON_EN); #endif /* caller must suspend then clear A_BUSREQ */ - usb_gadget_vbus_connect(isp->otg.gadget); + usb_gadget_vbus_connect(otg->gadget); l = omap_readl(OTG_CTRL); l |= OTG_A_SETB_HNPEN; omap_writel(l, OTG_CTRL); @@ -1503,6 +1505,12 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) if (!isp) return 0; + isp->phy.otg = kzalloc(sizeof *isp->phy.otg, GFP_KERNEL); + if (!isp->phy.otg) { + kfree(isp); + return 0; + } + INIT_WORK(&isp->work, isp1301_work); init_timer(&isp->timer); isp->timer.function = isp1301_timer; @@ -1576,14 +1584,15 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) goto fail; } - isp->otg.dev = &i2c->dev; - isp->otg.label = DRIVER_NAME; + isp->phy.dev = &i2c->dev; + isp->phy.label = DRIVER_NAME; + isp->phy.set_power = isp1301_set_power, - isp->otg.set_host = isp1301_set_host, - isp->otg.set_peripheral = isp1301_set_peripheral, - isp->otg.set_power = isp1301_set_power, - isp->otg.start_srp = isp1301_start_srp, - isp->otg.start_hnp = isp1301_start_hnp, + isp->phy.otg->phy = &isp->phy; + isp->phy.otg->set_host = isp1301_set_host, + isp->phy.otg->set_peripheral = isp1301_set_peripheral, + isp->phy.otg->start_srp = isp1301_start_srp, + isp->phy.otg->start_hnp = isp1301_start_hnp, enable_vbus_draw(isp, 0); power_down(isp); @@ -1601,7 +1610,7 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES); #endif - status = otg_set_transceiver(&isp->otg); + status = usb_set_transceiver(&isp->phy); if (status < 0) dev_err(&i2c->dev, "can't register transceiver, %d\n", status); @@ -1609,6 +1618,7 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) return 0; fail: + kfree(isp->phy.otg); kfree(isp); return -ENODEV; } @@ -1639,7 +1649,7 @@ subsys_initcall(isp_init); static void __exit isp_exit(void) { if (the_transceiver) - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); i2c_del_driver(&isp1301_driver); } module_exit(isp_exit); From 1d4c9293ae3555f2dcf9f394d1e2a14fd9421c4f Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:09 +0200 Subject: [PATCH 091/269] usb: otg: msm: Start using struct usb_otg Use struct usb_otg members with OTG specific functions instead of usb_phy members. Signed-off-by: Heikki Krogerus Acked-by: Pavankumar Kondeti Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- drivers/usb/otg/msm_otg.c | 398 +++++++++++++++++----------------- include/linux/usb/msm_hsusb.h | 2 +- 2 files changed, 206 insertions(+), 194 deletions(-) diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c index cba4737a04f4..1d0347c247d1 100644 --- a/drivers/usb/otg/msm_otg.c +++ b/drivers/usb/otg/msm_otg.c @@ -69,9 +69,9 @@ static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) int ret = 0; if (init) { - hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX"); + hsusb_vddcx = regulator_get(motg->phy.dev, "HSUSB_VDDCX"); if (IS_ERR(hsusb_vddcx)) { - dev_err(motg->otg.dev, "unable to get hsusb vddcx\n"); + dev_err(motg->phy.dev, "unable to get hsusb vddcx\n"); return PTR_ERR(hsusb_vddcx); } @@ -79,7 +79,7 @@ static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) USB_PHY_VDD_DIG_VOL_MIN, USB_PHY_VDD_DIG_VOL_MAX); if (ret) { - dev_err(motg->otg.dev, "unable to set the voltage " + dev_err(motg->phy.dev, "unable to set the voltage " "for hsusb vddcx\n"); regulator_put(hsusb_vddcx); return ret; @@ -87,18 +87,18 @@ static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) ret = regulator_enable(hsusb_vddcx); if (ret) { - dev_err(motg->otg.dev, "unable to enable hsusb vddcx\n"); + dev_err(motg->phy.dev, "unable to enable hsusb vddcx\n"); regulator_put(hsusb_vddcx); } } else { ret = regulator_set_voltage(hsusb_vddcx, 0, USB_PHY_VDD_DIG_VOL_MAX); if (ret) - dev_err(motg->otg.dev, "unable to set the voltage " + dev_err(motg->phy.dev, "unable to set the voltage " "for hsusb vddcx\n"); ret = regulator_disable(hsusb_vddcx); if (ret) - dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n"); + dev_err(motg->phy.dev, "unable to disable hsusb vddcx\n"); regulator_put(hsusb_vddcx); } @@ -111,40 +111,40 @@ static int msm_hsusb_ldo_init(struct msm_otg *motg, int init) int rc = 0; if (init) { - hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3"); + hsusb_3p3 = regulator_get(motg->phy.dev, "HSUSB_3p3"); if (IS_ERR(hsusb_3p3)) { - dev_err(motg->otg.dev, "unable to get hsusb 3p3\n"); + dev_err(motg->phy.dev, "unable to get hsusb 3p3\n"); return PTR_ERR(hsusb_3p3); } rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN, USB_PHY_3P3_VOL_MAX); if (rc) { - dev_err(motg->otg.dev, "unable to set voltage level " + dev_err(motg->phy.dev, "unable to set voltage level " "for hsusb 3p3\n"); goto put_3p3; } rc = regulator_enable(hsusb_3p3); if (rc) { - dev_err(motg->otg.dev, "unable to enable the hsusb 3p3\n"); + dev_err(motg->phy.dev, "unable to enable the hsusb 3p3\n"); goto put_3p3; } - hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8"); + hsusb_1p8 = regulator_get(motg->phy.dev, "HSUSB_1p8"); if (IS_ERR(hsusb_1p8)) { - dev_err(motg->otg.dev, "unable to get hsusb 1p8\n"); + dev_err(motg->phy.dev, "unable to get hsusb 1p8\n"); rc = PTR_ERR(hsusb_1p8); goto disable_3p3; } rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN, USB_PHY_1P8_VOL_MAX); if (rc) { - dev_err(motg->otg.dev, "unable to set voltage level " + dev_err(motg->phy.dev, "unable to set voltage level " "for hsusb 1p8\n"); goto put_1p8; } rc = regulator_enable(hsusb_1p8); if (rc) { - dev_err(motg->otg.dev, "unable to enable the hsusb 1p8\n"); + dev_err(motg->phy.dev, "unable to enable the hsusb 1p8\n"); goto put_1p8; } @@ -235,9 +235,9 @@ static int msm_hsusb_ldo_set_mode(int on) return ret < 0 ? ret : 0; } -static int ulpi_read(struct usb_phy *otg, u32 reg) +static int ulpi_read(struct usb_phy *phy, u32 reg) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(phy, struct msm_otg, phy); int cnt = 0; /* initiate read operation */ @@ -253,16 +253,16 @@ static int ulpi_read(struct usb_phy *otg, u32 reg) } if (cnt >= ULPI_IO_TIMEOUT_USEC) { - dev_err(otg->dev, "ulpi_read: timeout %08x\n", + dev_err(phy->dev, "ulpi_read: timeout %08x\n", readl(USB_ULPI_VIEWPORT)); return -ETIMEDOUT; } return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT)); } -static int ulpi_write(struct usb_phy *otg, u32 val, u32 reg) +static int ulpi_write(struct usb_phy *phy, u32 val, u32 reg) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(phy, struct msm_otg, phy); int cnt = 0; /* initiate write operation */ @@ -279,13 +279,13 @@ static int ulpi_write(struct usb_phy *otg, u32 val, u32 reg) } if (cnt >= ULPI_IO_TIMEOUT_USEC) { - dev_err(otg->dev, "ulpi_write: timeout\n"); + dev_err(phy->dev, "ulpi_write: timeout\n"); return -ETIMEDOUT; } return 0; } -static struct otg_io_access_ops msm_otg_io_ops = { +static struct usb_phy_io_ops msm_otg_io_ops = { .read = ulpi_read, .write = ulpi_write, }; @@ -299,9 +299,9 @@ static void ulpi_init(struct msm_otg *motg) return; while (seq[0] >= 0) { - dev_vdbg(motg->otg.dev, "ulpi: write 0x%02x to 0x%02x\n", + dev_vdbg(motg->phy.dev, "ulpi: write 0x%02x to 0x%02x\n", seq[0], seq[1]); - ulpi_write(&motg->otg, seq[0], seq[1]); + ulpi_write(&motg->phy, seq[0], seq[1]); seq += 2; } } @@ -313,11 +313,11 @@ static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert) if (assert) { ret = clk_reset(motg->clk, CLK_RESET_ASSERT); if (ret) - dev_err(motg->otg.dev, "usb hs_clk assert failed\n"); + dev_err(motg->phy.dev, "usb hs_clk assert failed\n"); } else { ret = clk_reset(motg->clk, CLK_RESET_DEASSERT); if (ret) - dev_err(motg->otg.dev, "usb hs_clk deassert failed\n"); + dev_err(motg->phy.dev, "usb hs_clk deassert failed\n"); } return ret; } @@ -328,13 +328,13 @@ static int msm_otg_phy_clk_reset(struct msm_otg *motg) ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT); if (ret) { - dev_err(motg->otg.dev, "usb phy clk assert failed\n"); + dev_err(motg->phy.dev, "usb phy clk assert failed\n"); return ret; } usleep_range(10000, 12000); ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT); if (ret) - dev_err(motg->otg.dev, "usb phy clk deassert failed\n"); + dev_err(motg->phy.dev, "usb phy clk deassert failed\n"); return ret; } @@ -358,7 +358,7 @@ static int msm_otg_phy_reset(struct msm_otg *motg) writel(val | PORTSC_PTS_ULPI, USB_PORTSC); for (retries = 3; retries > 0; retries--) { - ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM, + ret = ulpi_write(&motg->phy, ULPI_FUNC_CTRL_SUSPENDM, ULPI_CLR(ULPI_FUNC_CTRL)); if (!ret) break; @@ -375,7 +375,7 @@ static int msm_otg_phy_reset(struct msm_otg *motg) return ret; for (retries = 3; retries > 0; retries--) { - ret = ulpi_read(&motg->otg, ULPI_DEBUG); + ret = ulpi_read(&motg->phy, ULPI_DEBUG); if (ret != -ETIMEDOUT) break; ret = msm_otg_phy_clk_reset(motg); @@ -385,14 +385,14 @@ static int msm_otg_phy_reset(struct msm_otg *motg) if (!retries) return -ETIMEDOUT; - dev_info(motg->otg.dev, "phy_reset: success\n"); + dev_info(motg->phy.dev, "phy_reset: success\n"); return 0; } #define LINK_RESET_TIMEOUT_USEC (250 * 1000) -static int msm_otg_reset(struct usb_phy *otg) +static int msm_otg_reset(struct usb_phy *phy) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(phy, struct msm_otg, phy); struct msm_otg_platform_data *pdata = motg->pdata; int cnt = 0; int ret; @@ -401,7 +401,7 @@ static int msm_otg_reset(struct usb_phy *otg) ret = msm_otg_phy_reset(motg); if (ret) { - dev_err(otg->dev, "phy_reset failed\n"); + dev_err(phy->dev, "phy_reset failed\n"); return ret; } @@ -435,8 +435,8 @@ static int msm_otg_reset(struct usb_phy *otg) val |= OTGSC_BSVIE; } writel(val, USB_OTGSC); - ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE); - ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL); + ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_RISE); + ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_FALL); } return 0; @@ -448,8 +448,8 @@ static int msm_otg_reset(struct usb_phy *otg) #ifdef CONFIG_PM_SLEEP static int msm_otg_suspend(struct msm_otg *motg) { - struct usb_phy *otg = &motg->otg; - struct usb_bus *bus = otg->host; + struct usb_phy *phy = &motg->phy; + struct usb_bus *bus = phy->otg->host; struct msm_otg_platform_data *pdata = motg->pdata; int cnt = 0; @@ -475,10 +475,10 @@ static int msm_otg_suspend(struct msm_otg *motg) */ if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) { - ulpi_read(otg, 0x14); + ulpi_read(phy, 0x14); if (pdata->otg_control == OTG_PHY_CONTROL) - ulpi_write(otg, 0x01, 0x30); - ulpi_write(otg, 0x08, 0x09); + ulpi_write(phy, 0x01, 0x30); + ulpi_write(phy, 0x08, 0x09); } /* @@ -495,8 +495,8 @@ static int msm_otg_suspend(struct msm_otg *motg) } if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) { - dev_err(otg->dev, "Unable to suspend PHY\n"); - msm_otg_reset(otg); + dev_err(phy->dev, "Unable to suspend PHY\n"); + msm_otg_reset(phy); enable_irq(motg->irq); return -ETIMEDOUT; } @@ -528,7 +528,7 @@ static int msm_otg_suspend(struct msm_otg *motg) msm_hsusb_config_vddcx(0); } - if (device_may_wakeup(otg->dev)) + if (device_may_wakeup(phy->dev)) enable_irq_wake(motg->irq); if (bus) clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags); @@ -536,15 +536,15 @@ static int msm_otg_suspend(struct msm_otg *motg) atomic_set(&motg->in_lpm, 1); enable_irq(motg->irq); - dev_info(otg->dev, "USB in low power mode\n"); + dev_info(phy->dev, "USB in low power mode\n"); return 0; } static int msm_otg_resume(struct msm_otg *motg) { - struct usb_phy *otg = &motg->otg; - struct usb_bus *bus = otg->host; + struct usb_phy *phy = &motg->phy; + struct usb_bus *bus = phy->otg->host; int cnt = 0; unsigned temp; @@ -592,13 +592,13 @@ static int msm_otg_resume(struct msm_otg *motg) * PHY. USB state can not be restored. Re-insertion * of USB cable is the only way to get USB working. */ - dev_err(otg->dev, "Unable to resume USB." + dev_err(phy->dev, "Unable to resume USB." "Re-plugin the cable\n"); - msm_otg_reset(otg); + msm_otg_reset(phy); } skip_phy_resume: - if (device_may_wakeup(otg->dev)) + if (device_may_wakeup(phy->dev)) disable_irq_wake(motg->irq); if (bus) set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags); @@ -607,11 +607,11 @@ skip_phy_resume: if (motg->async_int) { motg->async_int = 0; - pm_runtime_put(otg->dev); + pm_runtime_put(phy->dev); enable_irq(motg->irq); } - dev_info(otg->dev, "USB exited from low power mode\n"); + dev_info(phy->dev, "USB exited from low power mode\n"); return 0; } @@ -623,13 +623,13 @@ static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA) return; /* TODO: Notify PMIC about available current */ - dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA); + dev_info(motg->phy.dev, "Avail curr from USB = %u\n", mA); motg->cur_power = mA; } -static int msm_otg_set_power(struct usb_phy *otg, unsigned mA) +static int msm_otg_set_power(struct usb_phy *phy, unsigned mA) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(phy, struct msm_otg, phy); /* * Gadget driver uses set_power method to notify about the @@ -644,19 +644,19 @@ static int msm_otg_set_power(struct usb_phy *otg, unsigned mA) return 0; } -static void msm_otg_start_host(struct usb_phy *otg, int on) +static void msm_otg_start_host(struct usb_phy *phy, int on) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(phy, struct msm_otg, phy); struct msm_otg_platform_data *pdata = motg->pdata; struct usb_hcd *hcd; - if (!otg->host) + if (!phy->otg->host) return; - hcd = bus_to_hcd(otg->host); + hcd = bus_to_hcd(phy->otg->host); if (on) { - dev_dbg(otg->dev, "host on\n"); + dev_dbg(phy->dev, "host on\n"); if (pdata->vbus_power) pdata->vbus_power(1); @@ -671,7 +671,7 @@ static void msm_otg_start_host(struct usb_phy *otg, int on) usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); #endif } else { - dev_dbg(otg->dev, "host off\n"); + dev_dbg(phy->dev, "host off\n"); #ifdef CONFIG_USB usb_remove_hcd(hcd); @@ -683,9 +683,9 @@ static void msm_otg_start_host(struct usb_phy *otg, int on) } } -static int msm_otg_set_host(struct usb_phy *otg, struct usb_bus *host) +static int msm_otg_set_host(struct usb_otg *otg, struct usb_bus *host) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy); struct usb_hcd *hcd; /* @@ -693,16 +693,16 @@ static int msm_otg_set_host(struct usb_phy *otg, struct usb_bus *host) * only peripheral configuration. */ if (motg->pdata->mode == USB_PERIPHERAL) { - dev_info(otg->dev, "Host mode is not supported\n"); + dev_info(otg->phy->dev, "Host mode is not supported\n"); return -ENODEV; } if (!host) { - if (otg->state == OTG_STATE_A_HOST) { - pm_runtime_get_sync(otg->dev); - msm_otg_start_host(otg, 0); + if (otg->phy->state == OTG_STATE_A_HOST) { + pm_runtime_get_sync(otg->phy->dev); + msm_otg_start_host(otg->phy, 0); otg->host = NULL; - otg->state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; schedule_work(&motg->sm_work); } else { otg->host = NULL; @@ -715,30 +715,30 @@ static int msm_otg_set_host(struct usb_phy *otg, struct usb_bus *host) hcd->power_budget = motg->pdata->power_budget; otg->host = host; - dev_dbg(otg->dev, "host driver registered w/ tranceiver\n"); + dev_dbg(otg->phy->dev, "host driver registered w/ tranceiver\n"); /* * Kick the state machine work, if peripheral is not supported * or peripheral is already registered with us. */ if (motg->pdata->mode == USB_HOST || otg->gadget) { - pm_runtime_get_sync(otg->dev); + pm_runtime_get_sync(otg->phy->dev); schedule_work(&motg->sm_work); } return 0; } -static void msm_otg_start_peripheral(struct usb_phy *otg, int on) +static void msm_otg_start_peripheral(struct usb_phy *phy, int on) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(phy, struct msm_otg, phy); struct msm_otg_platform_data *pdata = motg->pdata; - if (!otg->gadget) + if (!phy->otg->gadget) return; if (on) { - dev_dbg(otg->dev, "gadget on\n"); + dev_dbg(phy->dev, "gadget on\n"); /* * Some boards have a switch cotrolled by gpio * to enable/disable internal HUB. Disable internal @@ -746,36 +746,36 @@ static void msm_otg_start_peripheral(struct usb_phy *otg, int on) */ if (pdata->setup_gpio) pdata->setup_gpio(OTG_STATE_B_PERIPHERAL); - usb_gadget_vbus_connect(otg->gadget); + usb_gadget_vbus_connect(phy->otg->gadget); } else { - dev_dbg(otg->dev, "gadget off\n"); - usb_gadget_vbus_disconnect(otg->gadget); + dev_dbg(phy->dev, "gadget off\n"); + usb_gadget_vbus_disconnect(phy->otg->gadget); if (pdata->setup_gpio) pdata->setup_gpio(OTG_STATE_UNDEFINED); } } -static int msm_otg_set_peripheral(struct usb_phy *otg, - struct usb_gadget *gadget) +static int msm_otg_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) { - struct msm_otg *motg = container_of(otg, struct msm_otg, otg); + struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy); /* * Fail peripheral registration if this board can support * only host configuration. */ if (motg->pdata->mode == USB_HOST) { - dev_info(otg->dev, "Peripheral mode is not supported\n"); + dev_info(otg->phy->dev, "Peripheral mode is not supported\n"); return -ENODEV; } if (!gadget) { - if (otg->state == OTG_STATE_B_PERIPHERAL) { - pm_runtime_get_sync(otg->dev); - msm_otg_start_peripheral(otg, 0); + if (otg->phy->state == OTG_STATE_B_PERIPHERAL) { + pm_runtime_get_sync(otg->phy->dev); + msm_otg_start_peripheral(otg->phy, 0); otg->gadget = NULL; - otg->state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; schedule_work(&motg->sm_work); } else { otg->gadget = NULL; @@ -784,14 +784,14 @@ static int msm_otg_set_peripheral(struct usb_phy *otg, return 0; } otg->gadget = gadget; - dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n"); + dev_dbg(otg->phy->dev, "peripheral driver registered w/ tranceiver\n"); /* * Kick the state machine work, if host is not supported * or host is already registered with us. */ if (motg->pdata->mode == USB_PERIPHERAL || otg->host) { - pm_runtime_get_sync(otg->dev); + pm_runtime_get_sync(otg->phy->dev); schedule_work(&motg->sm_work); } @@ -800,17 +800,17 @@ static int msm_otg_set_peripheral(struct usb_phy *otg, static bool msm_chg_check_secondary_det(struct msm_otg *motg) { - struct usb_phy *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 chg_det; bool ret = false; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); ret = chg_det & (1 << 4); break; case SNPS_28NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x87); + chg_det = ulpi_read(phy, 0x87); ret = chg_det & 1; break; default: @@ -821,38 +821,38 @@ static bool msm_chg_check_secondary_det(struct msm_otg *motg) static void msm_chg_enable_secondary_det(struct msm_otg *motg) { - struct usb_phy *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 chg_det; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); /* Turn off charger block */ chg_det |= ~(1 << 1); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); udelay(20); /* control chg block via ULPI */ chg_det &= ~(1 << 3); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); /* put it in host mode for enabling D- source */ chg_det &= ~(1 << 2); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); /* Turn on chg detect block */ chg_det &= ~(1 << 1); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); udelay(20); /* enable chg detection */ chg_det &= ~(1 << 0); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); break; case SNPS_28NM_INTEGRATED_PHY: /* * Configure DM as current source, DP as current sink * and enable battery charging comparators. */ - ulpi_write(otg, 0x8, 0x85); - ulpi_write(otg, 0x2, 0x85); - ulpi_write(otg, 0x1, 0x85); + ulpi_write(phy, 0x8, 0x85); + ulpi_write(phy, 0x2, 0x85); + ulpi_write(phy, 0x1, 0x85); break; default: break; @@ -861,17 +861,17 @@ static void msm_chg_enable_secondary_det(struct msm_otg *motg) static bool msm_chg_check_primary_det(struct msm_otg *motg) { - struct usb_phy *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 chg_det; bool ret = false; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); ret = chg_det & (1 << 4); break; case SNPS_28NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x87); + chg_det = ulpi_read(phy, 0x87); ret = chg_det & 1; break; default: @@ -882,23 +882,23 @@ static bool msm_chg_check_primary_det(struct msm_otg *motg) static void msm_chg_enable_primary_det(struct msm_otg *motg) { - struct usb_phy *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 chg_det; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); /* enable chg detection */ chg_det &= ~(1 << 0); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); break; case SNPS_28NM_INTEGRATED_PHY: /* * Configure DP as current source, DM as current sink * and enable battery charging comparators. */ - ulpi_write(otg, 0x2, 0x85); - ulpi_write(otg, 0x1, 0x85); + ulpi_write(phy, 0x2, 0x85); + ulpi_write(phy, 0x1, 0x85); break; default: break; @@ -907,17 +907,17 @@ static void msm_chg_enable_primary_det(struct msm_otg *motg) static bool msm_chg_check_dcd(struct msm_otg *motg) { - struct usb_phy *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 line_state; bool ret = false; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - line_state = ulpi_read(otg, 0x15); + line_state = ulpi_read(phy, 0x15); ret = !(line_state & 1); break; case SNPS_28NM_INTEGRATED_PHY: - line_state = ulpi_read(otg, 0x87); + line_state = ulpi_read(phy, 0x87); ret = line_state & 2; break; default: @@ -928,17 +928,17 @@ static bool msm_chg_check_dcd(struct msm_otg *motg) static void msm_chg_disable_dcd(struct msm_otg *motg) { - struct usb_phy *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 chg_det; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); chg_det &= ~(1 << 5); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); break; case SNPS_28NM_INTEGRATED_PHY: - ulpi_write(otg, 0x10, 0x86); + ulpi_write(phy, 0x10, 0x86); break; default: break; @@ -947,19 +947,19 @@ static void msm_chg_disable_dcd(struct msm_otg *motg) static void msm_chg_enable_dcd(struct msm_otg *motg) { - struct usb_phy *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 chg_det; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); /* Turn on D+ current source */ chg_det |= (1 << 5); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); break; case SNPS_28NM_INTEGRATED_PHY: /* Data contact detection enable */ - ulpi_write(otg, 0x10, 0x85); + ulpi_write(phy, 0x10, 0x85); break; default: break; @@ -968,32 +968,32 @@ static void msm_chg_enable_dcd(struct msm_otg *motg) static void msm_chg_block_on(struct msm_otg *motg) { - struct usb_phy *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 func_ctrl, chg_det; /* put the controller in non-driving mode */ - func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL); + func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL); func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK; func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; - ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL); + ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL); switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); /* control chg block via ULPI */ chg_det &= ~(1 << 3); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); /* Turn on chg detect block */ chg_det &= ~(1 << 1); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); udelay(20); break; case SNPS_28NM_INTEGRATED_PHY: /* Clear charger detecting control bits */ - ulpi_write(otg, 0x3F, 0x86); + ulpi_write(phy, 0x3F, 0x86); /* Clear alt interrupt latch and enable bits */ - ulpi_write(otg, 0x1F, 0x92); - ulpi_write(otg, 0x1F, 0x95); + ulpi_write(phy, 0x1F, 0x92); + ulpi_write(phy, 0x1F, 0x95); udelay(100); break; default: @@ -1003,32 +1003,32 @@ static void msm_chg_block_on(struct msm_otg *motg) static void msm_chg_block_off(struct msm_otg *motg) { - struct usb_phy *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 func_ctrl, chg_det; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: - chg_det = ulpi_read(otg, 0x34); + chg_det = ulpi_read(phy, 0x34); /* Turn off charger block */ chg_det |= ~(1 << 1); - ulpi_write(otg, chg_det, 0x34); + ulpi_write(phy, chg_det, 0x34); break; case SNPS_28NM_INTEGRATED_PHY: /* Clear charger detecting control bits */ - ulpi_write(otg, 0x3F, 0x86); + ulpi_write(phy, 0x3F, 0x86); /* Clear alt interrupt latch and enable bits */ - ulpi_write(otg, 0x1F, 0x92); - ulpi_write(otg, 0x1F, 0x95); + ulpi_write(phy, 0x1F, 0x92); + ulpi_write(phy, 0x1F, 0x95); break; default: break; } /* put the controller in normal mode */ - func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL); + func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL); func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK; func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL; - ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL); + ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL); } #define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */ @@ -1038,14 +1038,14 @@ static void msm_chg_block_off(struct msm_otg *motg) static void msm_chg_detect_work(struct work_struct *w) { struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work); - struct usb_phy *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; bool is_dcd, tmout, vout; unsigned long delay; - dev_dbg(otg->dev, "chg detection work\n"); + dev_dbg(phy->dev, "chg detection work\n"); switch (motg->chg_state) { case USB_CHG_STATE_UNDEFINED: - pm_runtime_get_sync(otg->dev); + pm_runtime_get_sync(phy->dev); msm_chg_block_on(motg); msm_chg_enable_dcd(motg); motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; @@ -1088,7 +1088,7 @@ static void msm_chg_detect_work(struct work_struct *w) motg->chg_state = USB_CHG_STATE_DETECTED; case USB_CHG_STATE_DETECTED: msm_chg_block_off(motg); - dev_dbg(otg->dev, "charger = %d\n", motg->chg_type); + dev_dbg(phy->dev, "charger = %d\n", motg->chg_type); schedule_work(&motg->sm_work); return; default: @@ -1152,22 +1152,22 @@ static void msm_otg_init_sm(struct msm_otg *motg) static void msm_otg_sm_work(struct work_struct *w) { struct msm_otg *motg = container_of(w, struct msm_otg, sm_work); - struct usb_phy *otg = &motg->otg; + struct usb_otg *otg = motg->phy.otg; - switch (otg->state) { + switch (otg->phy->state) { case OTG_STATE_UNDEFINED: - dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n"); - msm_otg_reset(otg); + dev_dbg(otg->phy->dev, "OTG_STATE_UNDEFINED state\n"); + msm_otg_reset(otg->phy); msm_otg_init_sm(motg); - otg->state = OTG_STATE_B_IDLE; + otg->phy->state = OTG_STATE_B_IDLE; /* FALL THROUGH */ case OTG_STATE_B_IDLE: - dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n"); + dev_dbg(otg->phy->dev, "OTG_STATE_B_IDLE state\n"); if (!test_bit(ID, &motg->inputs) && otg->host) { /* disable BSV bit */ writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC); - msm_otg_start_host(otg, 1); - otg->state = OTG_STATE_A_HOST; + msm_otg_start_host(otg->phy, 1); + otg->phy->state = OTG_STATE_A_HOST; } else if (test_bit(B_SESS_VLD, &motg->inputs)) { switch (motg->chg_state) { case USB_CHG_STATE_UNDEFINED: @@ -1182,13 +1182,15 @@ static void msm_otg_sm_work(struct work_struct *w) case USB_CDP_CHARGER: msm_otg_notify_charger(motg, IDEV_CHG_MAX); - msm_otg_start_peripheral(otg, 1); - otg->state = OTG_STATE_B_PERIPHERAL; + msm_otg_start_peripheral(otg->phy, 1); + otg->phy->state + = OTG_STATE_B_PERIPHERAL; break; case USB_SDP_CHARGER: msm_otg_notify_charger(motg, IUNIT); - msm_otg_start_peripheral(otg, 1); - otg->state = OTG_STATE_B_PERIPHERAL; + msm_otg_start_peripheral(otg->phy, 1); + otg->phy->state + = OTG_STATE_B_PERIPHERAL; break; default: break; @@ -1204,34 +1206,34 @@ static void msm_otg_sm_work(struct work_struct *w) * is incremented in charger detection work. */ if (cancel_delayed_work_sync(&motg->chg_work)) { - pm_runtime_put_sync(otg->dev); - msm_otg_reset(otg); + pm_runtime_put_sync(otg->phy->dev); + msm_otg_reset(otg->phy); } msm_otg_notify_charger(motg, 0); motg->chg_state = USB_CHG_STATE_UNDEFINED; motg->chg_type = USB_INVALID_CHARGER; } - pm_runtime_put_sync(otg->dev); + pm_runtime_put_sync(otg->phy->dev); break; case OTG_STATE_B_PERIPHERAL: - dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n"); + dev_dbg(otg->phy->dev, "OTG_STATE_B_PERIPHERAL state\n"); if (!test_bit(B_SESS_VLD, &motg->inputs) || !test_bit(ID, &motg->inputs)) { msm_otg_notify_charger(motg, 0); - msm_otg_start_peripheral(otg, 0); + msm_otg_start_peripheral(otg->phy, 0); motg->chg_state = USB_CHG_STATE_UNDEFINED; motg->chg_type = USB_INVALID_CHARGER; - otg->state = OTG_STATE_B_IDLE; - msm_otg_reset(otg); + otg->phy->state = OTG_STATE_B_IDLE; + msm_otg_reset(otg->phy); schedule_work(w); } break; case OTG_STATE_A_HOST: - dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n"); + dev_dbg(otg->phy->dev, "OTG_STATE_A_HOST state\n"); if (test_bit(ID, &motg->inputs)) { - msm_otg_start_host(otg, 0); - otg->state = OTG_STATE_B_IDLE; - msm_otg_reset(otg); + msm_otg_start_host(otg->phy, 0); + otg->phy->state = OTG_STATE_B_IDLE; + msm_otg_reset(otg->phy); schedule_work(w); } break; @@ -1243,13 +1245,13 @@ static void msm_otg_sm_work(struct work_struct *w) static irqreturn_t msm_otg_irq(int irq, void *data) { struct msm_otg *motg = data; - struct usb_phy *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; u32 otgsc = 0; if (atomic_read(&motg->in_lpm)) { disable_irq_nosync(irq); motg->async_int = 1; - pm_runtime_get(otg->dev); + pm_runtime_get(phy->dev); return IRQ_HANDLED; } @@ -1262,15 +1264,15 @@ static irqreturn_t msm_otg_irq(int irq, void *data) set_bit(ID, &motg->inputs); else clear_bit(ID, &motg->inputs); - dev_dbg(otg->dev, "ID set/clear\n"); - pm_runtime_get_noresume(otg->dev); + dev_dbg(phy->dev, "ID set/clear\n"); + pm_runtime_get_noresume(phy->dev); } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) { if (otgsc & OTGSC_BSV) set_bit(B_SESS_VLD, &motg->inputs); else clear_bit(B_SESS_VLD, &motg->inputs); - dev_dbg(otg->dev, "BSV set/clear\n"); - pm_runtime_get_noresume(otg->dev); + dev_dbg(phy->dev, "BSV set/clear\n"); + pm_runtime_get_noresume(phy->dev); } writel(otgsc, USB_OTGSC); @@ -1281,9 +1283,9 @@ static irqreturn_t msm_otg_irq(int irq, void *data) static int msm_otg_mode_show(struct seq_file *s, void *unused) { struct msm_otg *motg = s->private; - struct usb_phy *otg = &motg->otg; + struct usb_otg *otg = motg->phy.otg; - switch (otg->state) { + switch (otg->phy->state) { case OTG_STATE_A_HOST: seq_printf(s, "host\n"); break; @@ -1309,7 +1311,7 @@ static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, struct seq_file *s = file->private_data; struct msm_otg *motg = s->private; char buf[16]; - struct usb_phy *otg = &motg->otg; + struct usb_otg *otg = motg->phy.otg; int status = count; enum usb_mode_type req_mode; @@ -1333,7 +1335,7 @@ static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, switch (req_mode) { case USB_NONE: - switch (otg->state) { + switch (otg->phy->state) { case OTG_STATE_A_HOST: case OTG_STATE_B_PERIPHERAL: set_bit(ID, &motg->inputs); @@ -1344,7 +1346,7 @@ static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, } break; case USB_PERIPHERAL: - switch (otg->state) { + switch (otg->phy->state) { case OTG_STATE_B_IDLE: case OTG_STATE_A_HOST: set_bit(ID, &motg->inputs); @@ -1355,7 +1357,7 @@ static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, } break; case USB_HOST: - switch (otg->state) { + switch (otg->phy->state) { case OTG_STATE_B_IDLE: case OTG_STATE_B_PERIPHERAL: clear_bit(ID, &motg->inputs); @@ -1368,7 +1370,7 @@ static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, goto out; } - pm_runtime_get_sync(otg->dev); + pm_runtime_get_sync(otg->phy->dev); schedule_work(&motg->sm_work); out: return status; @@ -1414,7 +1416,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) int ret = 0; struct resource *res; struct msm_otg *motg; - struct usb_phy *otg; + struct usb_phy *phy; dev_info(&pdev->dev, "msm_otg probe\n"); if (!pdev->dev.platform_data) { @@ -1428,9 +1430,15 @@ static int __init msm_otg_probe(struct platform_device *pdev) return -ENOMEM; } + motg->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL); + if (!motg->phy.otg) { + dev_err(&pdev->dev, "unable to allocate msm_otg\n"); + return -ENOMEM; + } + motg->pdata = pdev->dev.platform_data; - otg = &motg->otg; - otg->dev = &pdev->dev; + phy = &motg->phy; + phy->dev = &pdev->dev; motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk"); if (IS_ERR(motg->phy_reset_clk)) { @@ -1538,16 +1546,18 @@ static int __init msm_otg_probe(struct platform_device *pdev) goto disable_clks; } - otg->init = msm_otg_reset; - otg->set_host = msm_otg_set_host; - otg->set_peripheral = msm_otg_set_peripheral; - otg->set_power = msm_otg_set_power; + phy->init = msm_otg_reset; + phy->set_power = msm_otg_set_power; - otg->io_ops = &msm_otg_io_ops; + phy->io_ops = &msm_otg_io_ops; - ret = otg_set_transceiver(&motg->otg); + phy->otg->phy = &motg->phy; + phy->otg->set_host = msm_otg_set_host; + phy->otg->set_peripheral = msm_otg_set_peripheral; + + ret = usb_set_transceiver(&motg->phy); if (ret) { - dev_err(&pdev->dev, "otg_set_transceiver failed\n"); + dev_err(&pdev->dev, "usb_set_transceiver failed\n"); goto free_irq; } @@ -1591,6 +1601,7 @@ put_clk: put_phy_reset_clk: clk_put(motg->phy_reset_clk); free_motg: + kfree(motg->phy.otg); kfree(motg); return ret; } @@ -1598,10 +1609,10 @@ free_motg: static int __devexit msm_otg_remove(struct platform_device *pdev) { struct msm_otg *motg = platform_get_drvdata(pdev); - struct usb_phy *otg = &motg->otg; + struct usb_phy *phy = &motg->phy; int cnt = 0; - if (otg->host || otg->gadget) + if (phy->otg->host || phy->otg->gadget) return -EBUSY; msm_otg_debugfs_cleanup(); @@ -1613,14 +1624,14 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); pm_runtime_disable(&pdev->dev); - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); free_irq(motg->irq, motg); /* * Put PHY in low power mode. */ - ulpi_read(otg, 0x14); - ulpi_write(otg, 0x08, 0x09); + ulpi_read(phy, 0x14); + ulpi_write(phy, 0x08, 0x09); writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC); while (cnt < PHY_SUSPEND_TIMEOUT_USEC) { @@ -1630,7 +1641,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) cnt++; } if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) - dev_err(otg->dev, "Unable to suspend PHY\n"); + dev_err(phy->dev, "Unable to suspend PHY\n"); clk_disable(motg->pclk); clk_disable(motg->clk); @@ -1651,6 +1662,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) if (motg->core_clk) clk_put(motg->core_clk); + kfree(motg->phy.otg); kfree(motg); return 0; @@ -1660,7 +1672,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) static int msm_otg_runtime_idle(struct device *dev) { struct msm_otg *motg = dev_get_drvdata(dev); - struct usb_phy *otg = &motg->otg; + struct usb_otg *otg = motg->phy.otg; dev_dbg(dev, "OTG runtime idle\n"); @@ -1670,7 +1682,7 @@ static int msm_otg_runtime_idle(struct device *dev) * This 1 sec delay also prevents entering into LPM immediately * after asynchronous interrupt. */ - if (otg->state != OTG_STATE_UNDEFINED) + if (otg->phy->state != OTG_STATE_UNDEFINED) pm_schedule_suspend(dev, 1000); return -EAGAIN; diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index 2d3547ae9562..22a396c13f3a 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h @@ -160,7 +160,7 @@ struct msm_otg_platform_data { * detection process. */ struct msm_otg { - struct usb_phy otg; + struct usb_phy phy; struct msm_otg_platform_data *pdata; int irq; struct clk *clk; From 41adf109334650c35d0eb94e68082436bd3dd683 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:10 +0200 Subject: [PATCH 092/269] usb: otg: nop: Start using struct usb_otg Use struct usb_otg members with OTG specific functions instead of usb_phy members. Signed-off-by: Heikki Krogerus Reviewed-by: Marek Vasut Cc: Ajay Kumar Gupta Signed-off-by: Felipe Balbi --- drivers/usb/otg/nop-usb-xceiv.c | 64 ++++++++++++++++----------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index 2ab027997060..58b26df6afd1 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -33,7 +33,7 @@ #include struct nop_usb_xceiv { - struct usb_phy otg; + struct usb_phy phy; struct device *dev; }; @@ -58,51 +58,37 @@ void usb_nop_xceiv_unregister(void) } EXPORT_SYMBOL(usb_nop_xceiv_unregister); -static inline struct nop_usb_xceiv *xceiv_to_nop(struct usb_phy *x) -{ - return container_of(x, struct nop_usb_xceiv, otg); -} - static int nop_set_suspend(struct usb_phy *x, int suspend) { return 0; } -static int nop_set_peripheral(struct usb_phy *x, - struct usb_gadget *gadget) +static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) { - struct nop_usb_xceiv *nop; - - if (!x) + if (!otg) return -ENODEV; - nop = xceiv_to_nop(x); - if (!gadget) { - nop->otg.gadget = NULL; + otg->gadget = NULL; return -ENODEV; } - nop->otg.gadget = gadget; - nop->otg.state = OTG_STATE_B_IDLE; + otg->gadget = gadget; + otg->phy->state = OTG_STATE_B_IDLE; return 0; } -static int nop_set_host(struct usb_phy *x, struct usb_bus *host) +static int nop_set_host(struct usb_otg *otg, struct usb_bus *host) { - struct nop_usb_xceiv *nop; - - if (!x) + if (!otg) return -ENODEV; - nop = xceiv_to_nop(x); - if (!host) { - nop->otg.host = NULL; + otg->host = NULL; return -ENODEV; } - nop->otg.host = host; + otg->host = host; return 0; } @@ -115,15 +101,23 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) if (!nop) return -ENOMEM; - nop->dev = &pdev->dev; - nop->otg.dev = nop->dev; - nop->otg.label = "nop-xceiv"; - nop->otg.state = OTG_STATE_UNDEFINED; - nop->otg.set_host = nop_set_host; - nop->otg.set_peripheral = nop_set_peripheral; - nop->otg.set_suspend = nop_set_suspend; + nop->phy.otg = kzalloc(sizeof *nop->phy.otg, GFP_KERNEL); + if (!nop->phy.otg) { + kfree(nop); + return -ENOMEM; + } - err = otg_set_transceiver(&nop->otg); + nop->dev = &pdev->dev; + nop->phy.dev = nop->dev; + nop->phy.label = "nop-xceiv"; + nop->phy.set_suspend = nop_set_suspend; + nop->phy.state = OTG_STATE_UNDEFINED; + + nop->phy.otg->phy = &nop->phy; + nop->phy.otg->set_host = nop_set_host; + nop->phy.otg->set_peripheral = nop_set_peripheral; + + err = usb_set_transceiver(&nop->phy); if (err) { dev_err(&pdev->dev, "can't register transceiver, err: %d\n", err); @@ -132,10 +126,11 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, nop); - ATOMIC_INIT_NOTIFIER_HEAD(&nop->otg.notifier); + ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier); return 0; exit: + kfree(nop->phy.otg); kfree(nop); return err; } @@ -144,9 +139,10 @@ static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev) { struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); platform_set_drvdata(pdev, NULL); + kfree(nop->phy.otg); kfree(nop); return 0; From 74d4aa4419f9ec91d2dc1703923a0e59d4664ac3 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:11 +0200 Subject: [PATCH 093/269] usb: otg: twl4030: Start using struct usb_otg Use struct usb_otg members with OTG specific functions instead of usb_phy members. Signed-off-by: Heikki Krogerus Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- drivers/usb/otg/twl4030-usb.c | 79 +++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 906d524b94bb..c4a86da858e2 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -144,7 +144,7 @@ #define GPIO_USB_4PIN_ULPI_2430C (3 << 0) struct twl4030_usb { - struct usb_phy otg; + struct usb_phy phy; struct device *dev; /* TWL4030 internal USB regulator supplies */ @@ -166,7 +166,7 @@ struct twl4030_usb { }; /* internal define on top of container_of */ -#define xceiv_to_twl(x) container_of((x), struct twl4030_usb, otg) +#define phy_to_twl(x) container_of((x), struct twl4030_usb, phy) /*-------------------------------------------------------------------------*/ @@ -250,6 +250,7 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl) { int status; int linkstat = USB_EVENT_NONE; + struct usb_otg *otg = twl->phy.otg; twl->vbus_supplied = false; @@ -281,7 +282,7 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl) dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", status, status, linkstat); - twl->otg.last_event = linkstat; + twl->phy.last_event = linkstat; /* REVISIT this assumes host and peripheral controllers * are registered, and that both are active... @@ -290,11 +291,11 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl) spin_lock_irq(&twl->lock); twl->linkstat = linkstat; if (linkstat == USB_EVENT_ID) { - twl->otg.default_a = true; - twl->otg.state = OTG_STATE_A_IDLE; + otg->default_a = true; + twl->phy.state = OTG_STATE_A_IDLE; } else { - twl->otg.default_a = false; - twl->otg.state = OTG_STATE_B_IDLE; + otg->default_a = false; + twl->phy.state = OTG_STATE_B_IDLE; } spin_unlock_irq(&twl->lock); @@ -520,8 +521,8 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) else twl4030_phy_resume(twl); - atomic_notifier_call_chain(&twl->otg.notifier, status, - twl->otg.gadget); + atomic_notifier_call_chain(&twl->phy.notifier, status, + twl->phy.otg->gadget); } sysfs_notify(&twl->dev->kobj, NULL, "vbus"); @@ -542,15 +543,15 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl) twl->asleep = 0; } - atomic_notifier_call_chain(&twl->otg.notifier, status, - twl->otg.gadget); + atomic_notifier_call_chain(&twl->phy.notifier, status, + twl->phy.otg->gadget); } sysfs_notify(&twl->dev->kobj, NULL, "vbus"); } static int twl4030_set_suspend(struct usb_phy *x, int suspend) { - struct twl4030_usb *twl = xceiv_to_twl(x); + struct twl4030_usb *twl = phy_to_twl(x); if (suspend) twl4030_phy_suspend(twl, 1); @@ -560,33 +561,27 @@ static int twl4030_set_suspend(struct usb_phy *x, int suspend) return 0; } -static int twl4030_set_peripheral(struct usb_phy *x, - struct usb_gadget *gadget) +static int twl4030_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) { - struct twl4030_usb *twl; - - if (!x) + if (!otg) return -ENODEV; - twl = xceiv_to_twl(x); - twl->otg.gadget = gadget; + otg->gadget = gadget; if (!gadget) - twl->otg.state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; return 0; } -static int twl4030_set_host(struct usb_phy *x, struct usb_bus *host) +static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host) { - struct twl4030_usb *twl; - - if (!x) + if (!otg) return -ENODEV; - twl = xceiv_to_twl(x); - twl->otg.host = host; + otg->host = host; if (!host) - twl->otg.state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; return 0; } @@ -596,6 +591,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) struct twl4030_usb_data *pdata = pdev->dev.platform_data; struct twl4030_usb *twl; int status, err; + struct usb_otg *otg; if (!pdata) { dev_dbg(&pdev->dev, "platform_data not available\n"); @@ -606,16 +602,26 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) if (!twl) return -ENOMEM; + otg = kzalloc(sizeof *otg, GFP_KERNEL); + if (!otg) { + kfree(twl); + return -ENOMEM; + } + twl->dev = &pdev->dev; twl->irq = platform_get_irq(pdev, 0); - twl->otg.dev = twl->dev; - twl->otg.label = "twl4030"; - twl->otg.set_host = twl4030_set_host; - twl->otg.set_peripheral = twl4030_set_peripheral; - twl->otg.set_suspend = twl4030_set_suspend; twl->usb_mode = pdata->usb_mode; twl->vbus_supplied = false; - twl->asleep = 1; + twl->asleep = 1; + + twl->phy.dev = twl->dev; + twl->phy.label = "twl4030"; + twl->phy.otg = otg; + twl->phy.set_suspend = twl4030_set_suspend; + + otg->phy = &twl->phy; + otg->set_host = twl4030_set_host; + otg->set_peripheral = twl4030_set_peripheral; /* init spinlock for workqueue */ spin_lock_init(&twl->lock); @@ -623,16 +629,17 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) err = twl4030_usb_ldo_init(twl); if (err) { dev_err(&pdev->dev, "ldo init failed\n"); + kfree(otg); kfree(twl); return err; } - otg_set_transceiver(&twl->otg); + usb_set_transceiver(&twl->phy); platform_set_drvdata(pdev, twl); if (device_create_file(&pdev->dev, &dev_attr_vbus)) dev_warn(&pdev->dev, "could not create sysfs file\n"); - ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier); + ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); /* Our job is to use irqs and status from the power module * to keep the transceiver disabled when nothing's connected. @@ -649,6 +656,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) if (status < 0) { dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n", twl->irq, status); + kfree(otg); kfree(twl); return status; } @@ -693,6 +701,7 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) regulator_put(twl->usb1v8); regulator_put(twl->usb3v1); + kfree(twl->phy.otg); kfree(twl); return 0; From 46b8f6b0eb9a9df137c76ea04564c3648fdc63d4 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:12 +0200 Subject: [PATCH 094/269] usb: otg: twl6030: Start using struct usb_otg Use struct usb_otg members with OTG specific functions instead of usb_phy members. Signed-off-by: Heikki Krogerus Tested-by: Kishon Vijay Abraham I Reviewed-by: Marek Vasut Cc: Hema HK Signed-off-by: Felipe Balbi --- drivers/usb/otg/twl6030-usb.c | 111 +++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 50 deletions(-) diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index 56c4d3d50ebe..e3fa387ca81e 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c @@ -87,7 +87,7 @@ #define VBUS_DET BIT(2) struct twl6030_usb { - struct usb_phy otg; + struct usb_phy phy; struct device *dev; /* for vbus reporting with irqs disabled */ @@ -107,7 +107,7 @@ struct twl6030_usb { unsigned long features; }; -#define xceiv_to_twl(x) container_of((x), struct twl6030_usb, otg) +#define phy_to_twl(x) container_of((x), struct twl6030_usb, phy) /*-------------------------------------------------------------------------*/ @@ -143,7 +143,7 @@ static int twl6030_phy_init(struct usb_phy *x) struct device *dev; struct twl4030_usb_data *pdata; - twl = xceiv_to_twl(x); + twl = phy_to_twl(x); dev = twl->dev; pdata = dev->platform_data; @@ -161,7 +161,7 @@ static void twl6030_phy_shutdown(struct usb_phy *x) struct device *dev; struct twl4030_usb_data *pdata; - twl = xceiv_to_twl(x); + twl = phy_to_twl(x); dev = twl->dev; pdata = dev->platform_data; pdata->phy_power(twl->dev, 0, 0); @@ -169,7 +169,7 @@ static void twl6030_phy_shutdown(struct usb_phy *x) static int twl6030_phy_suspend(struct usb_phy *x, int suspend) { - struct twl6030_usb *twl = xceiv_to_twl(x); + struct twl6030_usb *twl = phy_to_twl(x); struct device *dev = twl->dev; struct twl4030_usb_data *pdata = dev->platform_data; @@ -178,9 +178,9 @@ static int twl6030_phy_suspend(struct usb_phy *x, int suspend) return 0; } -static int twl6030_start_srp(struct usb_phy *x) +static int twl6030_start_srp(struct usb_otg *otg) { - struct twl6030_usb *twl = xceiv_to_twl(x); + struct twl6030_usb *twl = phy_to_twl(otg->phy); twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET); twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET); @@ -256,6 +256,7 @@ static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL); static irqreturn_t twl6030_usb_irq(int irq, void *_twl) { struct twl6030_usb *twl = _twl; + struct usb_otg *otg = twl->phy.otg; int status; u8 vbus_state, hw_state; @@ -268,18 +269,18 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) regulator_enable(twl->usb3v3); twl->asleep = 1; status = USB_EVENT_VBUS; - twl->otg.default_a = false; - twl->otg.state = OTG_STATE_B_IDLE; + otg->default_a = false; + twl->phy.state = OTG_STATE_B_IDLE; twl->linkstat = status; - twl->otg.last_event = status; - atomic_notifier_call_chain(&twl->otg.notifier, - status, twl->otg.gadget); + twl->phy.last_event = status; + atomic_notifier_call_chain(&twl->phy.notifier, + status, otg->gadget); } else { status = USB_EVENT_NONE; twl->linkstat = status; - twl->otg.last_event = status; - atomic_notifier_call_chain(&twl->otg.notifier, - status, twl->otg.gadget); + twl->phy.last_event = status; + atomic_notifier_call_chain(&twl->phy.notifier, + status, otg->gadget); if (twl->asleep) { regulator_disable(twl->usb3v3); twl->asleep = 0; @@ -294,6 +295,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) { struct twl6030_usb *twl = _twl; + struct usb_otg *otg = twl->phy.otg; int status = USB_EVENT_NONE; u8 hw_state; @@ -307,12 +309,12 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x10); status = USB_EVENT_ID; - twl->otg.default_a = true; - twl->otg.state = OTG_STATE_A_IDLE; + otg->default_a = true; + twl->phy.state = OTG_STATE_A_IDLE; twl->linkstat = status; - twl->otg.last_event = status; - atomic_notifier_call_chain(&twl->otg.notifier, status, - twl->otg.gadget); + twl->phy.last_event = status; + atomic_notifier_call_chain(&twl->phy.notifier, status, + otg->gadget); } else { twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x10); @@ -324,25 +326,22 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) return IRQ_HANDLED; } -static int twl6030_set_peripheral(struct usb_phy *x, +static int twl6030_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) { - struct twl6030_usb *twl; - - if (!x) + if (!otg) return -ENODEV; - twl = xceiv_to_twl(x); - twl->otg.gadget = gadget; + otg->gadget = gadget; if (!gadget) - twl->otg.state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; return 0; } static int twl6030_enable_irq(struct usb_phy *x) { - struct twl6030_usb *twl = xceiv_to_twl(x); + struct twl6030_usb *twl = phy_to_twl(x); twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1); twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C); @@ -376,9 +375,9 @@ static void otg_set_vbus_work(struct work_struct *data) CHARGERUSB_CTRL1); } -static int twl6030_set_vbus(struct usb_phy *x, bool enabled) +static int twl6030_set_vbus(struct usb_otg *otg, bool enabled) { - struct twl6030_usb *twl = xceiv_to_twl(x); + struct twl6030_usb *twl = phy_to_twl(otg->phy); twl->vbus_enable = enabled; schedule_work(&twl->set_vbus_work); @@ -386,17 +385,14 @@ static int twl6030_set_vbus(struct usb_phy *x, bool enabled) return 0; } -static int twl6030_set_host(struct usb_phy *x, struct usb_bus *host) +static int twl6030_set_host(struct usb_otg *otg, struct usb_bus *host) { - struct twl6030_usb *twl; - - if (!x) + if (!otg) return -ENODEV; - twl = xceiv_to_twl(x); - twl->otg.host = host; + otg->host = host; if (!host) - twl->otg.state = OTG_STATE_UNDEFINED; + otg->phy->state = OTG_STATE_UNDEFINED; return 0; } @@ -405,6 +401,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) struct twl6030_usb *twl; int status, err; struct twl4030_usb_data *pdata; + struct usb_otg *otg; struct device *dev = &pdev->dev; pdata = dev->platform_data; @@ -412,19 +409,29 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) if (!twl) return -ENOMEM; + otg = kzalloc(sizeof *otg, GFP_KERNEL); + if (!otg) { + kfree(twl); + return -ENOMEM; + } + twl->dev = &pdev->dev; twl->irq1 = platform_get_irq(pdev, 0); twl->irq2 = platform_get_irq(pdev, 1); twl->features = pdata->features; - twl->otg.dev = twl->dev; - twl->otg.label = "twl6030"; - twl->otg.set_host = twl6030_set_host; - twl->otg.set_peripheral = twl6030_set_peripheral; - twl->otg.set_vbus = twl6030_set_vbus; - twl->otg.init = twl6030_phy_init; - twl->otg.shutdown = twl6030_phy_shutdown; - twl->otg.set_suspend = twl6030_phy_suspend; - twl->otg.start_srp = twl6030_start_srp; + + twl->phy.dev = twl->dev; + twl->phy.label = "twl6030"; + twl->phy.otg = otg; + twl->phy.init = twl6030_phy_init; + twl->phy.shutdown = twl6030_phy_shutdown; + twl->phy.set_suspend = twl6030_phy_suspend; + + otg->phy = &twl->phy; + otg->set_host = twl6030_set_host; + otg->set_peripheral = twl6030_set_peripheral; + otg->set_vbus = twl6030_set_vbus; + otg->start_srp = twl6030_start_srp; /* init spinlock for workqueue */ spin_lock_init(&twl->lock); @@ -432,16 +439,17 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) err = twl6030_usb_ldo_init(twl); if (err) { dev_err(&pdev->dev, "ldo init failed\n"); + kfree(otg); kfree(twl); return err; } - otg_set_transceiver(&twl->otg); + usb_set_transceiver(&twl->phy); platform_set_drvdata(pdev, twl); if (device_create_file(&pdev->dev, &dev_attr_vbus)) dev_warn(&pdev->dev, "could not create sysfs file\n"); - ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier); + ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); @@ -453,6 +461,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", twl->irq1, status); device_remove_file(twl->dev, &dev_attr_vbus); + kfree(otg); kfree(twl); return status; } @@ -465,14 +474,15 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) twl->irq2, status); free_irq(twl->irq1, twl); device_remove_file(twl->dev, &dev_attr_vbus); + kfree(otg); kfree(twl); return status; } twl->asleep = 0; pdata->phy_init(dev); - twl6030_phy_suspend(&twl->otg, 0); - twl6030_enable_irq(&twl->otg); + twl6030_phy_suspend(&twl->phy, 0); + twl6030_enable_irq(&twl->phy); dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); return 0; @@ -496,6 +506,7 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) pdata->phy_exit(twl->dev); device_remove_file(twl->dev, &dev_attr_vbus); cancel_work_sync(&twl->set_vbus_work); + kfree(twl->phy.otg); kfree(twl); return 0; From 298b083cf9dd2efd9bb7020107ab0077135051e0 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:13 +0200 Subject: [PATCH 095/269] usb: otg: ulpi: Start using struct usb_otg Use struct usb_otg members with OTG specific functions instead of usb_phy members. Signed-off-by: Heikki Krogerus Acked-by: Igor Grinberg Acked-by: Sascha Hauer Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- arch/arm/mach-pxa/pxa3xx-ulpi.c | 6 +- arch/arm/plat-mxc/include/mach/ulpi.h | 2 +- arch/arm/plat-mxc/ulpi.c | 2 +- drivers/usb/otg/ulpi.c | 116 ++++++++++++++------------ drivers/usb/otg/ulpi_viewport.c | 2 +- include/linux/usb/ulpi.h | 4 +- 6 files changed, 72 insertions(+), 60 deletions(-) diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c index 960d0ac50418..a13f33565623 100644 --- a/arch/arm/mach-pxa/pxa3xx-ulpi.c +++ b/arch/arm/mach-pxa/pxa3xx-ulpi.c @@ -111,7 +111,7 @@ static int pxa310_ulpi_write(struct usb_phy *otg, u32 val, u32 reg) return pxa310_ulpi_poll(); } -struct otg_io_access_ops pxa310_ulpi_access_ops = { +struct usb_phy_io_ops pxa310_ulpi_access_ops = { .read = pxa310_ulpi_read, .write = pxa310_ulpi_write, }; @@ -139,7 +139,7 @@ static int pxa310_start_otg_host_transcvr(struct usb_bus *host) pxa310_otg_transceiver_rtsm(); - err = otg_init(u2d->otg); + err = usb_phy_init(u2d->otg); if (err) { pr_err("OTG transceiver init failed"); return err; @@ -191,7 +191,7 @@ static void pxa310_stop_otg_hc(void) otg_set_host(u2d->otg, NULL); otg_set_vbus(u2d->otg, 0); - otg_shutdown(u2d->otg); + usb_phy_shutdown(u2d->otg); } static void pxa310_u2d_setup_otg_hc(void) diff --git a/arch/arm/plat-mxc/include/mach/ulpi.h b/arch/arm/plat-mxc/include/mach/ulpi.h index d39d94a170e7..42bdaca6d7d9 100644 --- a/arch/arm/plat-mxc/include/mach/ulpi.h +++ b/arch/arm/plat-mxc/include/mach/ulpi.h @@ -10,7 +10,7 @@ static inline struct usb_phy *imx_otg_ulpi_create(unsigned int flags) } #endif -extern struct otg_io_access_ops mxc_ulpi_access_ops; +extern struct usb_phy_io_ops mxc_ulpi_access_ops; #endif /* __MACH_ULPI_H */ diff --git a/arch/arm/plat-mxc/ulpi.c b/arch/arm/plat-mxc/ulpi.c index 8eeeb6b979c4..d2963427184f 100644 --- a/arch/arm/plat-mxc/ulpi.c +++ b/arch/arm/plat-mxc/ulpi.c @@ -106,7 +106,7 @@ static int ulpi_write(struct usb_phy *otg, u32 val, u32 reg) return ulpi_poll(view, ULPIVW_RUN); } -struct otg_io_access_ops mxc_ulpi_access_ops = { +struct usb_phy_io_ops mxc_ulpi_access_ops = { .read = ulpi_read, .write = ulpi_write, }; diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index 51841ed829ab..217339dd7a90 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/otg/ulpi.c @@ -49,31 +49,31 @@ static struct ulpi_info ulpi_ids[] = { ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"), }; -static int ulpi_set_otg_flags(struct usb_phy *otg) +static int ulpi_set_otg_flags(struct usb_phy *phy) { unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN | ULPI_OTG_CTRL_DM_PULLDOWN; - if (otg->flags & ULPI_OTG_ID_PULLUP) + if (phy->flags & ULPI_OTG_ID_PULLUP) flags |= ULPI_OTG_CTRL_ID_PULLUP; /* * ULPI Specification rev.1.1 default * for Dp/DmPulldown is enabled. */ - if (otg->flags & ULPI_OTG_DP_PULLDOWN_DIS) + if (phy->flags & ULPI_OTG_DP_PULLDOWN_DIS) flags &= ~ULPI_OTG_CTRL_DP_PULLDOWN; - if (otg->flags & ULPI_OTG_DM_PULLDOWN_DIS) + if (phy->flags & ULPI_OTG_DM_PULLDOWN_DIS) flags &= ~ULPI_OTG_CTRL_DM_PULLDOWN; - if (otg->flags & ULPI_OTG_EXTVBUSIND) + if (phy->flags & ULPI_OTG_EXTVBUSIND) flags |= ULPI_OTG_CTRL_EXTVBUSIND; - return otg_io_write(otg, flags, ULPI_OTG_CTRL); + return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL); } -static int ulpi_set_fc_flags(struct usb_phy *otg) +static int ulpi_set_fc_flags(struct usb_phy *phy) { unsigned int flags = 0; @@ -81,27 +81,27 @@ static int ulpi_set_fc_flags(struct usb_phy *otg) * ULPI Specification rev.1.1 default * for XcvrSelect is Full Speed. */ - if (otg->flags & ULPI_FC_HS) + if (phy->flags & ULPI_FC_HS) flags |= ULPI_FUNC_CTRL_HIGH_SPEED; - else if (otg->flags & ULPI_FC_LS) + else if (phy->flags & ULPI_FC_LS) flags |= ULPI_FUNC_CTRL_LOW_SPEED; - else if (otg->flags & ULPI_FC_FS4LS) + else if (phy->flags & ULPI_FC_FS4LS) flags |= ULPI_FUNC_CTRL_FS4LS; else flags |= ULPI_FUNC_CTRL_FULL_SPEED; - if (otg->flags & ULPI_FC_TERMSEL) + if (phy->flags & ULPI_FC_TERMSEL) flags |= ULPI_FUNC_CTRL_TERMSELECT; /* * ULPI Specification rev.1.1 default * for OpMode is Normal Operation. */ - if (otg->flags & ULPI_FC_OP_NODRV) + if (phy->flags & ULPI_FC_OP_NODRV) flags |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; - else if (otg->flags & ULPI_FC_OP_DIS_NRZI) + else if (phy->flags & ULPI_FC_OP_DIS_NRZI) flags |= ULPI_FUNC_CTRL_OPMODE_DISABLE_NRZI; - else if (otg->flags & ULPI_FC_OP_NSYNC_NEOP) + else if (phy->flags & ULPI_FC_OP_NSYNC_NEOP) flags |= ULPI_FUNC_CTRL_OPMODE_NOSYNC_NOEOP; else flags |= ULPI_FUNC_CTRL_OPMODE_NORMAL; @@ -112,54 +112,54 @@ static int ulpi_set_fc_flags(struct usb_phy *otg) */ flags |= ULPI_FUNC_CTRL_SUSPENDM; - return otg_io_write(otg, flags, ULPI_FUNC_CTRL); + return usb_phy_io_write(phy, flags, ULPI_FUNC_CTRL); } -static int ulpi_set_ic_flags(struct usb_phy *otg) +static int ulpi_set_ic_flags(struct usb_phy *phy) { unsigned int flags = 0; - if (otg->flags & ULPI_IC_AUTORESUME) + if (phy->flags & ULPI_IC_AUTORESUME) flags |= ULPI_IFC_CTRL_AUTORESUME; - if (otg->flags & ULPI_IC_EXTVBUS_INDINV) + if (phy->flags & ULPI_IC_EXTVBUS_INDINV) flags |= ULPI_IFC_CTRL_EXTERNAL_VBUS; - if (otg->flags & ULPI_IC_IND_PASSTHRU) + if (phy->flags & ULPI_IC_IND_PASSTHRU) flags |= ULPI_IFC_CTRL_PASSTHRU; - if (otg->flags & ULPI_IC_PROTECT_DIS) + if (phy->flags & ULPI_IC_PROTECT_DIS) flags |= ULPI_IFC_CTRL_PROTECT_IFC_DISABLE; - return otg_io_write(otg, flags, ULPI_IFC_CTRL); + return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL); } -static int ulpi_set_flags(struct usb_phy *otg) +static int ulpi_set_flags(struct usb_phy *phy) { int ret; - ret = ulpi_set_otg_flags(otg); + ret = ulpi_set_otg_flags(phy); if (ret) return ret; - ret = ulpi_set_ic_flags(otg); + ret = ulpi_set_ic_flags(phy); if (ret) return ret; - return ulpi_set_fc_flags(otg); + return ulpi_set_fc_flags(phy); } -static int ulpi_check_integrity(struct usb_phy *otg) +static int ulpi_check_integrity(struct usb_phy *phy) { int ret, i; unsigned int val = 0x55; for (i = 0; i < 2; i++) { - ret = otg_io_write(otg, val, ULPI_SCRATCH); + ret = usb_phy_io_write(phy, val, ULPI_SCRATCH); if (ret < 0) return ret; - ret = otg_io_read(otg, ULPI_SCRATCH); + ret = usb_phy_io_read(phy, ULPI_SCRATCH); if (ret < 0) return ret; @@ -175,13 +175,13 @@ static int ulpi_check_integrity(struct usb_phy *otg) return 0; } -static int ulpi_init(struct usb_phy *otg) +static int ulpi_init(struct usb_phy *phy) { int i, vid, pid, ret; u32 ulpi_id = 0; for (i = 0; i < 4; i++) { - ret = otg_io_read(otg, ULPI_PRODUCT_ID_HIGH - i); + ret = usb_phy_io_read(phy, ULPI_PRODUCT_ID_HIGH - i); if (ret < 0) return ret; ulpi_id = (ulpi_id << 8) | ret; @@ -199,16 +199,17 @@ static int ulpi_init(struct usb_phy *otg) } } - ret = ulpi_check_integrity(otg); + ret = ulpi_check_integrity(phy); if (ret) return ret; - return ulpi_set_flags(otg); + return ulpi_set_flags(phy); } -static int ulpi_set_host(struct usb_phy *otg, struct usb_bus *host) +static int ulpi_set_host(struct usb_otg *otg, struct usb_bus *host) { - unsigned int flags = otg_io_read(otg, ULPI_IFC_CTRL); + struct usb_phy *phy = otg->phy; + unsigned int flags = usb_phy_io_read(phy, ULPI_IFC_CTRL); if (!host) { otg->host = NULL; @@ -221,51 +222,62 @@ static int ulpi_set_host(struct usb_phy *otg, struct usb_bus *host) ULPI_IFC_CTRL_3_PIN_SERIAL_MODE | ULPI_IFC_CTRL_CARKITMODE); - if (otg->flags & ULPI_IC_6PIN_SERIAL) + if (phy->flags & ULPI_IC_6PIN_SERIAL) flags |= ULPI_IFC_CTRL_6_PIN_SERIAL_MODE; - else if (otg->flags & ULPI_IC_3PIN_SERIAL) + else if (phy->flags & ULPI_IC_3PIN_SERIAL) flags |= ULPI_IFC_CTRL_3_PIN_SERIAL_MODE; - else if (otg->flags & ULPI_IC_CARKIT) + else if (phy->flags & ULPI_IC_CARKIT) flags |= ULPI_IFC_CTRL_CARKITMODE; - return otg_io_write(otg, flags, ULPI_IFC_CTRL); + return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL); } -static int ulpi_set_vbus(struct usb_phy *otg, bool on) +static int ulpi_set_vbus(struct usb_otg *otg, bool on) { - unsigned int flags = otg_io_read(otg, ULPI_OTG_CTRL); + struct usb_phy *phy = otg->phy; + unsigned int flags = usb_phy_io_read(phy, ULPI_OTG_CTRL); flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT); if (on) { - if (otg->flags & ULPI_OTG_DRVVBUS) + if (phy->flags & ULPI_OTG_DRVVBUS) flags |= ULPI_OTG_CTRL_DRVVBUS; - if (otg->flags & ULPI_OTG_DRVVBUS_EXT) + if (phy->flags & ULPI_OTG_DRVVBUS_EXT) flags |= ULPI_OTG_CTRL_DRVVBUS_EXT; } - return otg_io_write(otg, flags, ULPI_OTG_CTRL); + return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL); } struct usb_phy * -otg_ulpi_create(struct otg_io_access_ops *ops, +otg_ulpi_create(struct usb_phy_io_ops *ops, unsigned int flags) { - struct usb_phy *otg; + struct usb_phy *phy; + struct usb_otg *otg; - otg = kzalloc(sizeof(*otg), GFP_KERNEL); - if (!otg) + phy = kzalloc(sizeof(*phy), GFP_KERNEL); + if (!phy) return NULL; - otg->label = "ULPI"; - otg->flags = flags; - otg->io_ops = ops; - otg->init = ulpi_init; + otg = kzalloc(sizeof(*otg), GFP_KERNEL); + if (!otg) { + kfree(phy); + return NULL; + } + + phy->label = "ULPI"; + phy->flags = flags; + phy->io_ops = ops; + phy->otg = otg; + phy->init = ulpi_init; + + otg->phy = phy; otg->set_host = ulpi_set_host; otg->set_vbus = ulpi_set_vbus; - return otg; + return phy; } EXPORT_SYMBOL_GPL(otg_ulpi_create); diff --git a/drivers/usb/otg/ulpi_viewport.c b/drivers/usb/otg/ulpi_viewport.c index e7b311b960bd..c5ba7e5423fc 100644 --- a/drivers/usb/otg/ulpi_viewport.c +++ b/drivers/usb/otg/ulpi_viewport.c @@ -74,7 +74,7 @@ static int ulpi_viewport_write(struct usb_phy *otg, u32 val, u32 reg) return ulpi_viewport_wait(view, ULPI_VIEW_RUN); } -struct otg_io_access_ops ulpi_viewport_access_ops = { +struct usb_phy_io_ops ulpi_viewport_access_ops = { .read = ulpi_viewport_read, .write = ulpi_viewport_write, }; diff --git a/include/linux/usb/ulpi.h b/include/linux/usb/ulpi.h index 51ebf72bc449..6f033a415ecb 100644 --- a/include/linux/usb/ulpi.h +++ b/include/linux/usb/ulpi.h @@ -181,12 +181,12 @@ /*-------------------------------------------------------------------------*/ -struct usb_phy *otg_ulpi_create(struct otg_io_access_ops *ops, +struct usb_phy *otg_ulpi_create(struct usb_phy_io_ops *ops, unsigned int flags); #ifdef CONFIG_USB_ULPI_VIEWPORT /* access ops for controllers with a viewport register */ -extern struct otg_io_access_ops ulpi_viewport_access_ops; +extern struct usb_phy_io_ops ulpi_viewport_access_ops; #endif #endif /* __LINUX_USB_ULPI_H */ From 76eb57ec1bf3201d2f417cafa5c974e7c0b6aaf9 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:14 +0200 Subject: [PATCH 096/269] arm: imx: Start using struct usb_otg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use struct usb_otg members with OTG specific functions instead of usb_phy members. Includes fixes from Sascha Hauer. Signed-off-by: Heikki Krogerus Acked-by: Igor Grinberg Tested-by: Philippe Rétornaz Tested-by: Sascha Hauer Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- arch/arm/mach-imx/mx31moboard-devboard.c | 22 ++++++++++++++-------- arch/arm/mach-imx/mx31moboard-marxbot.c | 22 ++++++++++++++-------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-imx/mx31moboard-devboard.c b/arch/arm/mach-imx/mx31moboard-devboard.c index 9cd4a97efa52..cc285e507286 100644 --- a/arch/arm/mach-imx/mx31moboard-devboard.c +++ b/arch/arm/mach-imx/mx31moboard-devboard.c @@ -177,7 +177,7 @@ static int devboard_isp1105_init(struct usb_phy *otg) } -static int devboard_isp1105_set_vbus(struct usb_phy *otg, bool on) +static int devboard_isp1105_set_vbus(struct usb_otg *otg, bool on) { if (on) gpio_set_value(USBH1_VBUSEN_B, 0); @@ -194,18 +194,24 @@ static struct mxc_usbh_platform_data usbh1_pdata __initdata = { static int __init devboard_usbh1_init(void) { - struct usb_phy *otg; + struct usb_phy *phy; struct platform_device *pdev; - otg = kzalloc(sizeof(*otg), GFP_KERNEL); - if (!otg) + phy = kzalloc(sizeof(*phy), GFP_KERNEL); + if (!phy) return -ENOMEM; - otg->label = "ISP1105"; - otg->init = devboard_isp1105_init; - otg->set_vbus = devboard_isp1105_set_vbus; + phy->otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL); + if (!phy->otg) { + kfree(phy); + return -ENOMEM; + } - usbh1_pdata.otg = otg; + phy->label = "ISP1105"; + phy->init = devboard_isp1105_init; + phy->otg->set_vbus = devboard_isp1105_set_vbus; + + usbh1_pdata.otg = phy; pdev = imx31_add_mxc_ehci_hs(1, &usbh1_pdata); if (IS_ERR(pdev)) diff --git a/arch/arm/mach-imx/mx31moboard-marxbot.c b/arch/arm/mach-imx/mx31moboard-marxbot.c index 2be769bbe05e..135c90e3a45f 100644 --- a/arch/arm/mach-imx/mx31moboard-marxbot.c +++ b/arch/arm/mach-imx/mx31moboard-marxbot.c @@ -291,7 +291,7 @@ static int marxbot_isp1105_init(struct usb_phy *otg) } -static int marxbot_isp1105_set_vbus(struct usb_phy *otg, bool on) +static int marxbot_isp1105_set_vbus(struct usb_otg *otg, bool on) { if (on) gpio_set_value(USBH1_VBUSEN_B, 0); @@ -308,18 +308,24 @@ static struct mxc_usbh_platform_data usbh1_pdata __initdata = { static int __init marxbot_usbh1_init(void) { - struct usb_phy *otg; + struct usb_phy *phy; struct platform_device *pdev; - otg = kzalloc(sizeof(*otg), GFP_KERNEL); - if (!otg) + phy = kzalloc(sizeof(*phy), GFP_KERNEL); + if (!phy) return -ENOMEM; - otg->label = "ISP1105"; - otg->init = marxbot_isp1105_init; - otg->set_vbus = marxbot_isp1105_set_vbus; + phy->otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL); + if (!phy->otg) { + kfree(phy); + return -ENOMEM; + } - usbh1_pdata.otg = otg; + phy->label = "ISP1105"; + phy->init = marxbot_isp1105_init; + phy->otg->set_vbus = marxbot_isp1105_set_vbus; + + usbh1_pdata.otg = phy; pdev = imx31_add_mxc_ehci_hs(1, &usbh1_pdata); if (IS_ERR(pdev)) From d445b6da8da491e025eb60576ce959f6a3a56a4f Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:15 +0200 Subject: [PATCH 097/269] usb: musb: Start using struct usb_otg Use struct usb_otg members with OTG specific functions instead of usb_phy members. [ balbi@ti.com: added a missing change on musb_gadget.c to avoid a compile error on a later patch ] Signed-off-by: Heikki Krogerus Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- drivers/usb/musb/am35x.c | 5 +++-- drivers/usb/musb/da8xx.c | 5 +++-- drivers/usb/musb/davinci.c | 7 ++++--- drivers/usb/musb/musb_core.c | 11 ++++++----- drivers/usb/musb/musb_gadget.c | 3 ++- drivers/usb/musb/musb_virthub.c | 9 ++++++--- drivers/usb/musb/omap2430.c | 5 +++-- drivers/usb/musb/tusb6010.c | 14 ++++++++------ 8 files changed, 35 insertions(+), 24 deletions(-) diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index e233d2b7d335..cb942b6cfe2b 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -226,6 +226,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) struct device *dev = musb->controller; struct musb_hdrc_platform_data *plat = dev->platform_data; struct omap_musb_board_data *data = plat->board_data; + struct usb_otg *otg = musb->xceiv->otg; unsigned long flags; irqreturn_t ret = IRQ_NONE; u32 epintr, usbintr; @@ -289,14 +290,14 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) WARNING("VBUS error workaround (delay coming)\n"); } else if (is_host_enabled(musb) && drvvbus) { MUSB_HST_MODE(musb); - musb->xceiv->default_a = 1; + otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; portstate(musb->port1_status |= USB_PORT_STAT_POWER); del_timer(&otg_workaround); } else { musb->is_active = 0; MUSB_DEV_MODE(musb); - musb->xceiv->default_a = 0; + otg->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); } diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 2613bfdb09b6..f0cb7767fa6a 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -294,6 +294,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) { struct musb *musb = hci; void __iomem *reg_base = musb->ctrl_base; + struct usb_otg *otg = musb->xceiv->otg; unsigned long flags; irqreturn_t ret = IRQ_NONE; u32 status; @@ -351,14 +352,14 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) WARNING("VBUS error workaround (delay coming)\n"); } else if (is_host_enabled(musb) && drvvbus) { MUSB_HST_MODE(musb); - musb->xceiv->default_a = 1; + otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; portstate(musb->port1_status |= USB_PORT_STAT_POWER); del_timer(&otg_workaround); } else { musb->is_active = 0; MUSB_DEV_MODE(musb); - musb->xceiv->default_a = 0; + otg->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); } diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 7c569f51212a..f2a63dd0dfce 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -265,6 +265,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) unsigned long flags; irqreturn_t retval = IRQ_NONE; struct musb *musb = __hci; + struct usb_otg *otg = musb->xceiv->otg; void __iomem *tibase = musb->ctrl_base; struct cppi *cppi; u32 tmp; @@ -331,14 +332,14 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) WARNING("VBUS error workaround (delay coming)\n"); } else if (is_host_enabled(musb) && drvvbus) { MUSB_HST_MODE(musb); - musb->xceiv->default_a = 1; + otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; portstate(musb->port1_status |= USB_PORT_STAT_POWER); del_timer(&otg_workaround); } else { musb->is_active = 0; MUSB_DEV_MODE(musb); - musb->xceiv->default_a = 0; + otg->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); } @@ -464,7 +465,7 @@ static int davinci_musb_exit(struct musb *musb) davinci_musb_source_power(musb, 0 /*off*/, 1); /* delay, to avoid problems with module reload */ - if (is_host_enabled(musb) && musb->xceiv->default_a) { + if (is_host_enabled(musb) && musb->xceiv->otg->default_a) { int maxdelay = 30; u8 devctl, warn = 0; diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 7b7ecf6c65b7..f9ecd5ebf267 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -414,6 +414,7 @@ void musb_hnp_stop(struct musb *musb) static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, u8 devctl, u8 power) { + struct usb_otg *otg = musb->xceiv->otg; irqreturn_t handled = IRQ_NONE; dev_dbg(musb->controller, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl, @@ -626,7 +627,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, case OTG_STATE_B_PERIPHERAL: musb_g_suspend(musb); musb->is_active = is_otg_enabled(musb) - && musb->xceiv->gadget->b_hnp_enable; + && otg->gadget->b_hnp_enable; if (musb->is_active) { musb->xceiv->state = OTG_STATE_B_WAIT_ACON; dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n"); @@ -643,7 +644,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, case OTG_STATE_A_HOST: musb->xceiv->state = OTG_STATE_A_SUSPEND; musb->is_active = is_otg_enabled(musb) - && musb->xceiv->host->b_hnp_enable; + && otg->host->b_hnp_enable; break; case OTG_STATE_B_HOST: /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ @@ -1965,7 +1966,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) if (is_otg_enabled(musb)) hcd->self.otg_port = 1; - musb->xceiv->host = &hcd->self; + musb->xceiv->otg->host = &hcd->self; hcd->power_budget = 2 * (plat->power ? : 250); /* program PHY to use external vBus if required */ @@ -1984,7 +1985,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) struct usb_hcd *hcd = musb_to_hcd(musb); MUSB_HST_MODE(musb); - musb->xceiv->default_a = 1; + musb->xceiv->otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_IDLE; status = usb_add_hcd(musb_to_hcd(musb), -1, 0); @@ -1999,7 +2000,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) } else /* peripheral is enabled */ { MUSB_DEV_MODE(musb); - musb->xceiv->default_a = 0; + musb->xceiv->otg->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; status = musb_gadget_setup(musb); diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index ac3d2eec20fe..0524a34be3c7 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1898,6 +1898,7 @@ static int musb_gadget_start(struct usb_gadget *g, struct usb_gadget_driver *driver) { struct musb *musb = gadget_to_musb(g); + struct usb_otg *otg = musb->xceiv->otg; unsigned long flags; int retval = -EINVAL; @@ -1945,7 +1946,7 @@ static int musb_gadget_start(struct usb_gadget *g, } if ((musb->xceiv->last_event == USB_EVENT_ID) - && musb->xceiv->set_vbus) + && otg->set_vbus) otg_set_vbus(musb->xceiv, 1); hcd->self.uses_pio_for_control = 1; diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index e9f80adc45a4..22ec3e379980 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -47,6 +47,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) { + struct usb_otg *otg = musb->xceiv->otg; u8 power; void __iomem *mbase = musb->mregs; @@ -81,7 +82,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) case OTG_STATE_A_HOST: musb->xceiv->state = OTG_STATE_A_SUSPEND; musb->is_active = is_otg_enabled(musb) - && musb->xceiv->host->b_hnp_enable; + && otg->host->b_hnp_enable; if (musb->is_active) mod_timer(&musb->otg_timer, jiffies + msecs_to_jiffies( @@ -91,7 +92,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) case OTG_STATE_B_HOST: musb->xceiv->state = OTG_STATE_B_WAIT_ACON; musb->is_active = is_otg_enabled(musb) - && musb->xceiv->host->b_hnp_enable; + && otg->host->b_hnp_enable; musb_platform_try_idle(musb, 0); break; default: @@ -179,6 +180,8 @@ static void musb_port_reset(struct musb *musb, bool do_reset) void musb_root_disconnect(struct musb *musb) { + struct usb_otg *otg = musb->xceiv->otg; + musb->port1_status = USB_PORT_STAT_POWER | (USB_PORT_STAT_C_CONNECTION << 16); @@ -188,7 +191,7 @@ void musb_root_disconnect(struct musb *musb) switch (musb->xceiv->state) { case OTG_STATE_A_SUSPEND: if (is_otg_enabled(musb) - && musb->xceiv->host->b_hnp_enable) { + && otg->host->b_hnp_enable) { musb->xceiv->state = OTG_STATE_A_PERIPHERAL; musb->g.is_a_peripheral = 1; break; diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index df719eae3b03..a427fcb13430 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -132,6 +132,7 @@ static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout) static void omap2430_musb_set_vbus(struct musb *musb, int is_on) { + struct usb_otg *otg = musb->xceiv->otg; u8 devctl; unsigned long timeout = jiffies + msecs_to_jiffies(1000); int ret = 1; @@ -167,7 +168,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) otg_set_vbus(musb->xceiv, 1); } else { musb->is_active = 1; - musb->xceiv->default_a = 1; + otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; devctl |= MUSB_DEVCTL_SESSION; MUSB_HST_MODE(musb); @@ -179,7 +180,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) * jumping right to B_IDLE... */ - musb->xceiv->default_a = 0; + otg->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; devctl &= ~MUSB_DEVCTL_SESSION; diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 5ce01bdb1951..0665c14cc540 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -293,7 +293,7 @@ static int tusb_draw_power(struct usb_phy *x, unsigned mA) * The actual current usage would be very board-specific. For now, * it's simpler to just use an aggregate (also board-specific). */ - if (x->default_a || mA < (musb->min_power << 1)) + if (x->otg->default_a || mA < (musb->min_power << 1)) mA = 0; reg = musb_readl(tbase, TUSB_PRCM_MNGMT); @@ -510,6 +510,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on) void __iomem *tbase = musb->ctrl_base; u32 conf, prcm, timer; u8 devctl; + struct usb_otg *otg = musb->xceiv->otg; /* HDRC controls CPEN, but beware current surges during device * connect. They can trigger transient overcurrent conditions @@ -522,7 +523,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on) if (is_on) { timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE); - musb->xceiv->default_a = 1; + otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; devctl |= MUSB_DEVCTL_SESSION; @@ -548,11 +549,11 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on) musb->xceiv->state = OTG_STATE_A_IDLE; } musb->is_active = 0; - musb->xceiv->default_a = 1; + otg->default_a = 1; MUSB_HST_MODE(musb); } else { musb->is_active = 0; - musb->xceiv->default_a = 0; + otg->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; MUSB_DEV_MODE(musb); } @@ -644,6 +645,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) { u32 otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); unsigned long idle_timeout = 0; + struct usb_otg *otg = musb->xceiv->otg; /* ID pin */ if ((int_src & TUSB_INT_SRC_ID_STATUS_CHNG)) { @@ -654,7 +656,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) else default_a = is_host_enabled(musb); dev_dbg(musb->controller, "Default-%c\n", default_a ? 'A' : 'B'); - musb->xceiv->default_a = default_a; + otg->default_a = default_a; tusb_musb_set_vbus(musb, default_a); /* Don't allow idling immediately */ @@ -666,7 +668,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) { /* B-dev state machine: no vbus ~= disconnect */ - if ((is_otg_enabled(musb) && !musb->xceiv->default_a) + if ((is_otg_enabled(musb) && !otg->default_a) || !is_host_enabled(musb)) { /* ? musb_root_disconnect(musb); */ musb->port1_status &= From fcc8ebc99034bae4020a3cec030553d469e265db Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:16 +0200 Subject: [PATCH 098/269] power_supply: Convert all users to new usb_phy Use the new usb_phy_* functions instead of the old otg_* ones. Signed-off-by: Heikki Krogerus Acked-by: Anton Vorontsov Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- drivers/power/isp1704_charger.c | 106 +++++++++++++++++--------------- drivers/power/pda_power.c | 8 +-- drivers/power/twl4030_charger.c | 18 +++--- 3 files changed, 71 insertions(+), 61 deletions(-) diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c index 51cdea4fc034..58ad6e998ca0 100644 --- a/drivers/power/isp1704_charger.c +++ b/drivers/power/isp1704_charger.c @@ -56,7 +56,7 @@ static u16 isp170x_id[] = { struct isp1704_charger { struct device *dev; struct power_supply psy; - struct usb_phy *otg; + struct usb_phy *phy; struct notifier_block nb; struct work_struct work; @@ -71,6 +71,16 @@ struct isp1704_charger { unsigned max_power; }; +static inline int isp1704_read(struct isp1704_charger *isp, u32 reg) +{ + return usb_phy_io_read(isp->phy, reg); +} + +static inline int isp1704_write(struct isp1704_charger *isp, u32 val, u32 reg) +{ + return usb_phy_io_write(isp->phy, val, reg); +} + /* * Disable/enable the power from the isp1704 if a function for it * has been provided with platform data. @@ -97,31 +107,31 @@ static inline int isp1704_charger_type(struct isp1704_charger *isp) u8 otg_ctrl; int type = POWER_SUPPLY_TYPE_USB_DCP; - func_ctrl = otg_io_read(isp->otg, ULPI_FUNC_CTRL); - otg_ctrl = otg_io_read(isp->otg, ULPI_OTG_CTRL); + func_ctrl = isp1704_read(isp, ULPI_FUNC_CTRL); + otg_ctrl = isp1704_read(isp, ULPI_OTG_CTRL); /* disable pulldowns */ reg = ULPI_OTG_CTRL_DM_PULLDOWN | ULPI_OTG_CTRL_DP_PULLDOWN; - otg_io_write(isp->otg, ULPI_CLR(ULPI_OTG_CTRL), reg); + isp1704_write(isp, ULPI_CLR(ULPI_OTG_CTRL), reg); /* full speed */ - otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL), + isp1704_write(isp, ULPI_CLR(ULPI_FUNC_CTRL), ULPI_FUNC_CTRL_XCVRSEL_MASK); - otg_io_write(isp->otg, ULPI_SET(ULPI_FUNC_CTRL), + isp1704_write(isp, ULPI_SET(ULPI_FUNC_CTRL), ULPI_FUNC_CTRL_FULL_SPEED); /* Enable strong pull-up on DP (1.5K) and reset */ reg = ULPI_FUNC_CTRL_TERMSELECT | ULPI_FUNC_CTRL_RESET; - otg_io_write(isp->otg, ULPI_SET(ULPI_FUNC_CTRL), reg); + isp1704_write(isp, ULPI_SET(ULPI_FUNC_CTRL), reg); usleep_range(1000, 2000); - reg = otg_io_read(isp->otg, ULPI_DEBUG); + reg = isp1704_read(isp, ULPI_DEBUG); if ((reg & 3) != 3) type = POWER_SUPPLY_TYPE_USB_CDP; /* recover original state */ - otg_io_write(isp->otg, ULPI_FUNC_CTRL, func_ctrl); - otg_io_write(isp->otg, ULPI_OTG_CTRL, otg_ctrl); + isp1704_write(isp, ULPI_FUNC_CTRL, func_ctrl); + isp1704_write(isp, ULPI_OTG_CTRL, otg_ctrl); return type; } @@ -136,28 +146,28 @@ static inline int isp1704_charger_verify(struct isp1704_charger *isp) u8 r; /* Reset the transceiver */ - r = otg_io_read(isp->otg, ULPI_FUNC_CTRL); + r = isp1704_read(isp, ULPI_FUNC_CTRL); r |= ULPI_FUNC_CTRL_RESET; - otg_io_write(isp->otg, ULPI_FUNC_CTRL, r); + isp1704_write(isp, ULPI_FUNC_CTRL, r); usleep_range(1000, 2000); /* Set normal mode */ r &= ~(ULPI_FUNC_CTRL_RESET | ULPI_FUNC_CTRL_OPMODE_MASK); - otg_io_write(isp->otg, ULPI_FUNC_CTRL, r); + isp1704_write(isp, ULPI_FUNC_CTRL, r); /* Clear the DP and DM pull-down bits */ r = ULPI_OTG_CTRL_DP_PULLDOWN | ULPI_OTG_CTRL_DM_PULLDOWN; - otg_io_write(isp->otg, ULPI_CLR(ULPI_OTG_CTRL), r); + isp1704_write(isp, ULPI_CLR(ULPI_OTG_CTRL), r); /* Enable strong pull-up on DP (1.5K) and reset */ r = ULPI_FUNC_CTRL_TERMSELECT | ULPI_FUNC_CTRL_RESET; - otg_io_write(isp->otg, ULPI_SET(ULPI_FUNC_CTRL), r); + isp1704_write(isp, ULPI_SET(ULPI_FUNC_CTRL), r); usleep_range(1000, 2000); /* Read the line state */ - if (!otg_io_read(isp->otg, ULPI_DEBUG)) { + if (!isp1704_read(isp, ULPI_DEBUG)) { /* Disable strong pull-up on DP (1.5K) */ - otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL), + isp1704_write(isp, ULPI_CLR(ULPI_FUNC_CTRL), ULPI_FUNC_CTRL_TERMSELECT); return 1; } @@ -165,23 +175,23 @@ static inline int isp1704_charger_verify(struct isp1704_charger *isp) /* Is it a charger or PS/2 connection */ /* Enable weak pull-up resistor on DP */ - otg_io_write(isp->otg, ULPI_SET(ISP1704_PWR_CTRL), + isp1704_write(isp, ULPI_SET(ISP1704_PWR_CTRL), ISP1704_PWR_CTRL_DP_WKPU_EN); /* Disable strong pull-up on DP (1.5K) */ - otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL), + isp1704_write(isp, ULPI_CLR(ULPI_FUNC_CTRL), ULPI_FUNC_CTRL_TERMSELECT); /* Enable weak pull-down resistor on DM */ - otg_io_write(isp->otg, ULPI_SET(ULPI_OTG_CTRL), + isp1704_write(isp, ULPI_SET(ULPI_OTG_CTRL), ULPI_OTG_CTRL_DM_PULLDOWN); /* It's a charger if the line states are clear */ - if (!(otg_io_read(isp->otg, ULPI_DEBUG))) + if (!(isp1704_read(isp, ULPI_DEBUG))) ret = 1; /* Disable weak pull-up resistor on DP */ - otg_io_write(isp->otg, ULPI_CLR(ISP1704_PWR_CTRL), + isp1704_write(isp, ULPI_CLR(ISP1704_PWR_CTRL), ISP1704_PWR_CTRL_DP_WKPU_EN); return ret; @@ -193,14 +203,14 @@ static inline int isp1704_charger_detect(struct isp1704_charger *isp) u8 pwr_ctrl; int ret = 0; - pwr_ctrl = otg_io_read(isp->otg, ISP1704_PWR_CTRL); + pwr_ctrl = isp1704_read(isp, ISP1704_PWR_CTRL); /* set SW control bit in PWR_CTRL register */ - otg_io_write(isp->otg, ISP1704_PWR_CTRL, + isp1704_write(isp, ISP1704_PWR_CTRL, ISP1704_PWR_CTRL_SWCTRL); /* enable manual charger detection */ - otg_io_write(isp->otg, ULPI_SET(ISP1704_PWR_CTRL), + isp1704_write(isp, ULPI_SET(ISP1704_PWR_CTRL), ISP1704_PWR_CTRL_SWCTRL | ISP1704_PWR_CTRL_DPVSRC_EN); usleep_range(1000, 2000); @@ -208,7 +218,7 @@ static inline int isp1704_charger_detect(struct isp1704_charger *isp) timeout = jiffies + msecs_to_jiffies(300); do { /* Check if there is a charger */ - if (otg_io_read(isp->otg, ISP1704_PWR_CTRL) + if (isp1704_read(isp, ISP1704_PWR_CTRL) & ISP1704_PWR_CTRL_VDAT_DET) { ret = isp1704_charger_verify(isp); break; @@ -216,7 +226,7 @@ static inline int isp1704_charger_detect(struct isp1704_charger *isp) } while (!time_after(jiffies, timeout) && isp->online); /* recover original state */ - otg_io_write(isp->otg, ISP1704_PWR_CTRL, pwr_ctrl); + isp1704_write(isp, ISP1704_PWR_CTRL, pwr_ctrl); return ret; } @@ -264,8 +274,8 @@ static void isp1704_charger_work(struct work_struct *data) case POWER_SUPPLY_TYPE_USB: default: /* enable data pullups */ - if (isp->otg->gadget) - usb_gadget_connect(isp->otg->gadget); + if (isp->phy->gadget) + usb_gadget_connect(isp->phy->gadget); } break; case USB_EVENT_NONE: @@ -283,8 +293,8 @@ static void isp1704_charger_work(struct work_struct *data) * chargers. The pullups may be enabled elsewhere, so this can * not be the final solution. */ - if (isp->otg->gadget) - usb_gadget_disconnect(isp->otg->gadget); + if (isp->phy->gadget) + usb_gadget_disconnect(isp->phy->gadget); isp1704_charger_set_power(isp, 0); break; @@ -364,11 +374,11 @@ static inline int isp1704_test_ulpi(struct isp1704_charger *isp) int ret = -ENODEV; /* Test ULPI interface */ - ret = otg_io_write(isp->otg, ULPI_SCRATCH, 0xaa); + ret = isp1704_write(isp, ULPI_SCRATCH, 0xaa); if (ret < 0) return ret; - ret = otg_io_read(isp->otg, ULPI_SCRATCH); + ret = isp1704_read(isp, ULPI_SCRATCH); if (ret < 0) return ret; @@ -376,13 +386,13 @@ static inline int isp1704_test_ulpi(struct isp1704_charger *isp) return -ENODEV; /* Verify the product and vendor id matches */ - vendor = otg_io_read(isp->otg, ULPI_VENDOR_ID_LOW); - vendor |= otg_io_read(isp->otg, ULPI_VENDOR_ID_HIGH) << 8; + vendor = isp1704_read(isp, ULPI_VENDOR_ID_LOW); + vendor |= isp1704_read(isp, ULPI_VENDOR_ID_HIGH) << 8; if (vendor != NXP_VENDOR_ID) return -ENODEV; - product = otg_io_read(isp->otg, ULPI_PRODUCT_ID_LOW); - product |= otg_io_read(isp->otg, ULPI_PRODUCT_ID_HIGH) << 8; + product = isp1704_read(isp, ULPI_PRODUCT_ID_LOW); + product |= isp1704_read(isp, ULPI_PRODUCT_ID_HIGH) << 8; for (i = 0; i < ARRAY_SIZE(isp170x_id); i++) { if (product == isp170x_id[i]) { @@ -405,8 +415,8 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) if (!isp) return -ENOMEM; - isp->otg = otg_get_transceiver(); - if (!isp->otg) + isp->phy = usb_get_transceiver(); + if (!isp->phy) goto fail0; isp->dev = &pdev->dev; @@ -429,14 +439,14 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) goto fail1; /* - * REVISIT: using work in order to allow the otg notifications to be + * REVISIT: using work in order to allow the usb notifications to be * made atomically in the future. */ INIT_WORK(&isp->work, isp1704_charger_work); isp->nb.notifier_call = isp1704_notifier_call; - ret = otg_register_notifier(isp->otg, &isp->nb); + ret = usb_register_notifier(isp->phy, &isp->nb); if (ret) goto fail2; @@ -449,13 +459,13 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) * enumerated. The charger driver should be always loaded before any * gadget is loaded. */ - if (isp->otg->gadget) - usb_gadget_disconnect(isp->otg->gadget); + if (isp->phy->gadget) + usb_gadget_disconnect(isp->phy->gadget); /* Detect charger if VBUS is valid (the cable was already plugged). */ - ret = otg_io_read(isp->otg, ULPI_USB_INT_STS); + ret = isp1704_read(isp, ULPI_USB_INT_STS); isp1704_charger_set_power(isp, 0); - if ((ret & ULPI_INT_VBUS_VALID) && !isp->otg->default_a) { + if ((ret & ULPI_INT_VBUS_VALID) && !isp->phy->otg->default_a) { isp->event = USB_EVENT_VBUS; schedule_work(&isp->work); } @@ -464,7 +474,7 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) fail2: power_supply_unregister(&isp->psy); fail1: - otg_put_transceiver(isp->otg); + usb_put_transceiver(isp->phy); fail0: kfree(isp); @@ -477,9 +487,9 @@ static int __devexit isp1704_charger_remove(struct platform_device *pdev) { struct isp1704_charger *isp = platform_get_drvdata(pdev); - otg_unregister_notifier(isp->otg, &isp->nb); + usb_unregister_notifier(isp->phy, &isp->nb); power_supply_unregister(&isp->psy); - otg_put_transceiver(isp->otg); + usb_put_transceiver(isp->phy); isp1704_charger_set_power(isp, 0); kfree(isp); diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c index dcf07f55eb04..214468f4444a 100644 --- a/drivers/power/pda_power.c +++ b/drivers/power/pda_power.c @@ -321,7 +321,7 @@ static int pda_power_probe(struct platform_device *pdev) } #ifdef CONFIG_USB_OTG_UTILS - transceiver = otg_get_transceiver(); + transceiver = usb_get_transceiver(); if (transceiver && !pdata->is_usb_online) { pdata->is_usb_online = otg_is_usb_online; } @@ -375,7 +375,7 @@ static int pda_power_probe(struct platform_device *pdev) #ifdef CONFIG_USB_OTG_UTILS if (transceiver && pdata->use_otg_notifier) { otg_nb.notifier_call = otg_handle_notification; - ret = otg_register_notifier(transceiver, &otg_nb); + ret = usb_register_notifier(transceiver, &otg_nb); if (ret) { dev_err(dev, "failure to register otg notifier\n"); goto otg_reg_notifier_failed; @@ -409,7 +409,7 @@ usb_supply_failed: free_irq(ac_irq->start, &pda_psy_ac); #ifdef CONFIG_USB_OTG_UTILS if (transceiver) - otg_put_transceiver(transceiver); + usb_put_transceiver(transceiver); #endif ac_irq_failed: if (pdata->is_ac_online) @@ -444,7 +444,7 @@ static int pda_power_remove(struct platform_device *pdev) power_supply_unregister(&pda_psy_ac); #ifdef CONFIG_USB_OTG_UTILS if (transceiver) - otg_put_transceiver(transceiver); + usb_put_transceiver(transceiver); #endif if (ac_draw) { regulator_put(ac_draw); diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index b3ead2305b4c..fdad850c77d3 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -70,7 +70,7 @@ struct twl4030_bci { struct power_supply ac; struct power_supply usb; struct usb_phy *transceiver; - struct notifier_block otg_nb; + struct notifier_block usb_nb; struct work_struct work; int irq_chg; int irq_bci; @@ -279,7 +279,7 @@ static void twl4030_bci_usb_work(struct work_struct *data) static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val, void *priv) { - struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, otg_nb); + struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, usb_nb); dev_dbg(bci->dev, "OTG notify %lu\n", val); @@ -479,10 +479,10 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) INIT_WORK(&bci->work, twl4030_bci_usb_work); - bci->transceiver = otg_get_transceiver(); + bci->transceiver = usb_get_transceiver(); if (bci->transceiver != NULL) { - bci->otg_nb.notifier_call = twl4030_bci_usb_ncb; - otg_register_notifier(bci->transceiver, &bci->otg_nb); + bci->usb_nb.notifier_call = twl4030_bci_usb_ncb; + usb_register_notifier(bci->transceiver, &bci->usb_nb); } /* Enable interrupts now. */ @@ -508,8 +508,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) fail_unmask_interrupts: if (bci->transceiver != NULL) { - otg_unregister_notifier(bci->transceiver, &bci->otg_nb); - otg_put_transceiver(bci->transceiver); + usb_unregister_notifier(bci->transceiver, &bci->usb_nb); + usb_put_transceiver(bci->transceiver); } free_irq(bci->irq_bci, bci); fail_bci_irq: @@ -539,8 +539,8 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev) TWL4030_INTERRUPTS_BCIIMR2A); if (bci->transceiver != NULL) { - otg_unregister_notifier(bci->transceiver, &bci->otg_nb); - otg_put_transceiver(bci->transceiver); + usb_unregister_notifier(bci->transceiver, &bci->usb_nb); + usb_put_transceiver(bci->transceiver); } free_irq(bci->irq_bci, bci); free_irq(bci->irq_chg, bci); From f6bafc6a1c9d58f0c234ac5052b9c09b0747348c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 6 Feb 2012 11:04:53 +0200 Subject: [PATCH 099/269] usb: dwc3: convert TRBs into bitshifts this will get rid of a useless memcpy on IRQ handling, thus improving driver performance. Tested with OMAP5430 running g_mass_storage on SuperSpeed and HighSpeed. Note that we are removing the little endian access of the TRB and all accesses will be in System endianness, if there happens to be a system in BE, bit 12 of GSBUSCFG0 should be set so that HW does byte invariant BE accesses when fetching TRBs. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 138 ++++++++++---------------------------- drivers/usb/dwc3/ep0.c | 34 +++++----- drivers/usb/dwc3/gadget.c | 83 ++++++++++++----------- 3 files changed, 95 insertions(+), 160 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 4dac9828577e..696b20a8b1fa 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -301,7 +301,7 @@ /* Structures */ -struct dwc3_trb_hw; +struct dwc3_trb; /** * struct dwc3_event_buffer - Software event buffer representation @@ -356,7 +356,7 @@ struct dwc3_ep { struct list_head request_list; struct list_head req_queued; - struct dwc3_trb_hw *trb_pool; + struct dwc3_trb *trb_pool; dma_addr_t trb_pool_dma; u32 free_slot; u32 busy_slot; @@ -431,102 +431,49 @@ enum dwc3_device_state { DWC3_CONFIGURED_STATE, }; -/** - * struct dwc3_trb - transfer request block - * @bpl: lower 32bit of the buffer - * @bph: higher 32bit of the buffer - * @length: buffer size (up to 16mb - 1) - * @pcm1: packet count m1 - * @trbsts: trb status - * 0 = ok - * 1 = missed isoc - * 2 = setup pending - * @hwo: hardware owner of descriptor - * @lst: last trb - * @chn: chain buffers - * @csp: continue on short packets (only supported on isoc eps) - * @trbctl: trb control - * 1 = normal - * 2 = control-setup - * 3 = control-status-2 - * 4 = control-status-3 - * 5 = control-data (first trb of data stage) - * 6 = isochronous-first (first trb of service interval) - * 7 = isochronous - * 8 = link trb - * others = reserved - * @isp_imi: interrupt on short packet / interrupt on missed isoc - * @ioc: interrupt on complete - * @sid_sofn: Stream ID / SOF Number - */ -struct dwc3_trb { - u64 bplh; +/* TRB Length, PCM and Status */ +#define DWC3_TRB_SIZE_MASK (0x00ffffff) +#define DWC3_TRB_SIZE_LENGTH(n) ((n) & DWC3_TRB_SIZE_MASK) +#define DWC3_TRB_SIZE_PCM1(n) (((n) & 0x03) << 24) +#define DWC3_TRB_SIZE_TRBSTS(n) (((n) & (0x0f << 28) >> 28)) - union { - struct { - u32 length:24; - u32 pcm1:2; - u32 reserved27_26:2; - u32 trbsts:4; -#define DWC3_TRB_STS_OKAY 0 -#define DWC3_TRB_STS_MISSED_ISOC 1 -#define DWC3_TRB_STS_SETUP_PENDING 2 - }; - u32 len_pcm; - }; +#define DWC3_TRBSTS_OK 0 +#define DWC3_TRBSTS_MISSED_ISOC 1 +#define DWC3_TRBSTS_SETUP_PENDING 2 - union { - struct { - u32 hwo:1; - u32 lst:1; - u32 chn:1; - u32 csp:1; - u32 trbctl:6; - u32 isp_imi:1; - u32 ioc:1; - u32 reserved13_12:2; - u32 sid_sofn:16; - u32 reserved31_30:2; - }; - u32 control; - }; -} __packed; +/* TRB Control */ +#define DWC3_TRB_CTRL_HWO (1 << 0) +#define DWC3_TRB_CTRL_LST (1 << 1) +#define DWC3_TRB_CTRL_CHN (1 << 2) +#define DWC3_TRB_CTRL_CSP (1 << 3) +#define DWC3_TRB_CTRL_TRBCTL(n) (((n) & 0x3f) << 4) +#define DWC3_TRB_CTRL_ISP_IMI (1 << 10) +#define DWC3_TRB_CTRL_IOC (1 << 11) +#define DWC3_TRB_CTRL_SID_SOFN(n) (((n) & 0xffff) << 14) + +#define DWC3_TRBCTL_NORMAL DWC3_TRB_CTRL_TRBCTL(1) +#define DWC3_TRBCTL_CONTROL_SETUP DWC3_TRB_CTRL_TRBCTL(2) +#define DWC3_TRBCTL_CONTROL_STATUS2 DWC3_TRB_CTRL_TRBCTL(3) +#define DWC3_TRBCTL_CONTROL_STATUS3 DWC3_TRB_CTRL_TRBCTL(4) +#define DWC3_TRBCTL_CONTROL_DATA DWC3_TRB_CTRL_TRBCTL(5) +#define DWC3_TRBCTL_ISOCHRONOUS_FIRST DWC3_TRB_CTRL_TRBCTL(6) +#define DWC3_TRBCTL_ISOCHRONOUS DWC3_TRB_CTRL_TRBCTL(7) +#define DWC3_TRBCTL_LINK_TRB DWC3_TRB_CTRL_TRBCTL(8) /** - * struct dwc3_trb_hw - transfer request block (hw format) + * struct dwc3_trb - transfer request block (hw format) * @bpl: DW0-3 * @bph: DW4-7 * @size: DW8-B * @trl: DWC-F */ -struct dwc3_trb_hw { - __le32 bpl; - __le32 bph; - __le32 size; - __le32 ctrl; +struct dwc3_trb { + u32 bpl; + u32 bph; + u32 size; + u32 ctrl; } __packed; -static inline void dwc3_trb_to_hw(struct dwc3_trb *nat, struct dwc3_trb_hw *hw) -{ - hw->bpl = cpu_to_le32(lower_32_bits(nat->bplh)); - hw->bph = cpu_to_le32(upper_32_bits(nat->bplh)); - hw->size = cpu_to_le32p(&nat->len_pcm); - /* HWO is written last */ - hw->ctrl = cpu_to_le32p(&nat->control); -} - -static inline void dwc3_trb_to_nat(struct dwc3_trb_hw *hw, struct dwc3_trb *nat) -{ - u64 bplh; - - bplh = le32_to_cpup(&hw->bpl); - bplh |= (u64) le32_to_cpup(&hw->bph) << 32; - nat->bplh = bplh; - - nat->len_pcm = le32_to_cpup(&hw->size); - nat->control = le32_to_cpup(&hw->ctrl); -} - /** * dwc3_hwparams - copy of HWPARAMS registers * @hwparams0 - GHWPARAMS0 @@ -573,7 +520,7 @@ struct dwc3_request { struct dwc3_ep *dep; u8 epnum; - struct dwc3_trb_hw *trb; + struct dwc3_trb *trb; dma_addr_t trb_dma; unsigned direction:1; @@ -624,7 +571,7 @@ struct dwc3_request { */ struct dwc3 { struct usb_ctrlrequest *ctrl_req; - struct dwc3_trb_hw *ep0_trb; + struct dwc3_trb *ep0_trb; void *ep0_bounce; u8 *setup_buf; dma_addr_t ctrl_req_addr; @@ -691,19 +638,6 @@ struct dwc3 { /* -------------------------------------------------------------------------- */ -#define DWC3_TRBSTS_OK 0 -#define DWC3_TRBSTS_MISSED_ISOC 1 -#define DWC3_TRBSTS_SETUP_PENDING 2 - -#define DWC3_TRBCTL_NORMAL 1 -#define DWC3_TRBCTL_CONTROL_SETUP 2 -#define DWC3_TRBCTL_CONTROL_STATUS2 3 -#define DWC3_TRBCTL_CONTROL_STATUS3 4 -#define DWC3_TRBCTL_CONTROL_DATA 5 -#define DWC3_TRBCTL_ISOCHRONOUS_FIRST 6 -#define DWC3_TRBCTL_ISOCHRONOUS 7 -#define DWC3_TRBCTL_LINK_TRB 8 - /* -------------------------------------------------------------------------- */ struct dwc3_event_type { diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index c20e30c8b695..5a067090f27e 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -76,8 +76,7 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, u32 len, u32 type) { struct dwc3_gadget_ep_cmd_params params; - struct dwc3_trb_hw *trb_hw; - struct dwc3_trb trb; + struct dwc3_trb *trb; struct dwc3_ep *dep; int ret; @@ -88,19 +87,17 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, return 0; } - trb_hw = dwc->ep0_trb; - memset(&trb, 0, sizeof(trb)); + trb = dwc->ep0_trb; - trb.trbctl = type; - trb.bplh = buf_dma; - trb.length = len; + trb->bpl = lower_32_bits(buf_dma); + trb->bph = upper_32_bits(buf_dma); + trb->size = len; + trb->ctrl = type; - trb.hwo = 1; - trb.lst = 1; - trb.ioc = 1; - trb.isp_imi = 1; - - dwc3_trb_to_hw(&trb, trb_hw); + trb->ctrl |= (DWC3_TRB_CTRL_HWO + | DWC3_TRB_CTRL_LST + | DWC3_TRB_CTRL_IOC + | DWC3_TRB_CTRL_ISP_IMI); memset(¶ms, 0, sizeof(params)); params.param0 = upper_32_bits(dwc->ep0_trb_addr); @@ -544,9 +541,10 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, { struct dwc3_request *r = NULL; struct usb_request *ur; - struct dwc3_trb trb; + struct dwc3_trb *trb; struct dwc3_ep *ep0; u32 transferred; + u32 length; u8 epnum; epnum = event->endpoint_number; @@ -557,16 +555,16 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, r = next_request(&ep0->request_list); ur = &r->request; - dwc3_trb_to_nat(dwc->ep0_trb, &trb); + trb = dwc->ep0_trb; + length = trb->size & DWC3_TRB_SIZE_MASK; if (dwc->ep0_bounced) { - transferred = min_t(u32, ur->length, - ep0->endpoint.maxpacket - trb.length); + ep0->endpoint.maxpacket - length); memcpy(ur->buf, dwc->ep0_bounce, transferred); dwc->ep0_bounced = false; } else { - transferred = ur->length - trb.length; + transferred = ur->length - length; ur->actual += transferred; } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 76327005d54c..eeba2227c28f 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -378,7 +378,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, } static dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep, - struct dwc3_trb_hw *trb) + struct dwc3_trb *trb) { u32 offset = (char *) trb - (char *) dep->trb_pool; @@ -527,9 +527,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, return ret; if (!(dep->flags & DWC3_EP_ENABLED)) { - struct dwc3_trb_hw *trb_st_hw; - struct dwc3_trb_hw *trb_link_hw; - struct dwc3_trb trb_link; + struct dwc3_trb *trb_st_hw; + struct dwc3_trb *trb_link; ret = dwc3_gadget_set_xfer_resource(dwc, dep); if (ret) @@ -552,12 +551,12 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, /* Link TRB for ISOC. The HWO but is never reset */ trb_st_hw = &dep->trb_pool[0]; - trb_link.bplh = dwc3_trb_dma_offset(dep, trb_st_hw); - trb_link.trbctl = DWC3_TRBCTL_LINK_TRB; - trb_link.hwo = true; + trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1]; - trb_link_hw = &dep->trb_pool[DWC3_TRB_NUM - 1]; - dwc3_trb_to_hw(&trb_link, trb_link_hw); + trb_link->bpl = lower_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw)); + trb_link->bph = upper_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw)); + trb_link->ctrl |= DWC3_TRBCTL_LINK_TRB; + trb_link->ctrl |= DWC3_TRB_CTRL_HWO; } return 0; @@ -744,8 +743,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, unsigned length, unsigned last, unsigned chain) { struct dwc3 *dwc = dep->dwc; - struct dwc3_trb_hw *trb_hw; - struct dwc3_trb trb; + struct dwc3_trb *trb; unsigned int cur_slot; @@ -754,7 +752,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, length, last ? " last" : "", chain ? " chain" : ""); - trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; + trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; cur_slot = dep->free_slot; dep->free_slot++; @@ -763,40 +761,32 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, usb_endpoint_xfer_isoc(dep->desc)) return; - memset(&trb, 0, sizeof(trb)); if (!req->trb) { dwc3_gadget_move_request_queued(req); - req->trb = trb_hw; - req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw); + req->trb = trb; + req->trb_dma = dwc3_trb_dma_offset(dep, trb); } - if (usb_endpoint_xfer_isoc(dep->desc)) { - trb.isp_imi = true; - trb.csp = true; - } else { - trb.chn = chain; - trb.lst = last; - } - - if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) - trb.sid_sofn = req->request.stream_id; + trb->size = DWC3_TRB_SIZE_LENGTH(length); + trb->bpl = lower_32_bits(dma); + trb->bph = upper_32_bits(dma); switch (usb_endpoint_type(dep->desc)) { case USB_ENDPOINT_XFER_CONTROL: - trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; + trb->ctrl = DWC3_TRBCTL_CONTROL_SETUP; break; case USB_ENDPOINT_XFER_ISOC: - trb.trbctl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; + trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; /* IOC every DWC3_TRB_NUM / 4 so we can refill */ if (!(cur_slot % (DWC3_TRB_NUM / 4))) - trb.ioc = last; + trb->ctrl |= DWC3_TRB_CTRL_IOC; break; case USB_ENDPOINT_XFER_BULK: case USB_ENDPOINT_XFER_INT: - trb.trbctl = DWC3_TRBCTL_NORMAL; + trb->ctrl = DWC3_TRBCTL_NORMAL; break; default: /* @@ -806,11 +796,21 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, BUG(); } - trb.length = length; - trb.bplh = dma; - trb.hwo = true; + if (usb_endpoint_xfer_isoc(dep->desc)) { + trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; + trb->ctrl |= DWC3_TRB_CTRL_CSP; + } else { + if (chain) + trb->ctrl |= DWC3_TRB_CTRL_CHN; - dwc3_trb_to_hw(&trb, trb_hw); + if (last) + trb->ctrl |= DWC3_TRB_CTRL_LST; + } + + if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) + trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id); + + trb->ctrl |= DWC3_TRB_CTRL_HWO; } /* @@ -1542,7 +1542,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, const struct dwc3_event_depevt *event, int status) { struct dwc3_request *req; - struct dwc3_trb trb; + struct dwc3_trb *trb; unsigned int count; unsigned int s_pkt = 0; @@ -1553,9 +1553,9 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, return 1; } - dwc3_trb_to_nat(req->trb, &trb); + trb = req->trb; - if (trb.hwo && status != -ESHUTDOWN) + if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) /* * We continue despite the error. There is not much we * can do. If we don't clean in up we loop for ever. If @@ -1566,7 +1566,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, */ dev_err(dwc->dev, "%s's TRB (%p) still owned by HW\n", dep->name, req->trb); - count = trb.length; + count = trb->size & DWC3_TRB_SIZE_MASK; if (dep->direction) { if (count) { @@ -1590,13 +1590,16 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, dwc3_gadget_giveback(dep, req, status); if (s_pkt) break; - if ((event->status & DEPEVT_STATUS_LST) && trb.lst) + if ((event->status & DEPEVT_STATUS_LST) && + (trb->ctrl & DWC3_TRB_CTRL_LST)) break; - if ((event->status & DEPEVT_STATUS_IOC) && trb.ioc) + if ((event->status & DEPEVT_STATUS_IOC) && + (trb->ctrl & DWC3_TRB_CTRL_IOC)) break; } while (1); - if ((event->status & DEPEVT_STATUS_IOC) && trb.ioc) + if ((event->status & DEPEVT_STATUS_IOC) && + (trb->ctrl & DWC3_TRB_CTRL_IOC)) return 0; return 1; } From 5ee71cf3bef66ad9683c681e48628fae057f8e18 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Sat, 11 Feb 2012 21:19:10 +0900 Subject: [PATCH 100/269] usb: Fix typo in imx21-dbg.c Correct spelling "alocate" to "allocate" in drivers/usb/host/imx21-dbg.c Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/imx21-dbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/imx21-dbg.c b/drivers/usb/host/imx21-dbg.c index 6d7533427163..ec98ecee3517 100644 --- a/drivers/usb/host/imx21-dbg.c +++ b/drivers/usb/host/imx21-dbg.c @@ -239,7 +239,7 @@ static int debug_status_show(struct seq_file *s, void *v) "ETDs allocated: %d/%d (max=%d)\n" "ETDs in use sw: %d\n" "ETDs in use hw: %d\n" - "DMEM alocated: %d/%d (max=%d)\n" + "DMEM allocated: %d/%d (max=%d)\n" "DMEM blocks: %d\n" "Queued waiting for ETD: %d\n" "Queued waiting for DMEM: %d\n", From d5261286949fc9ada701c7e30bf89e08a6dbf4de Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 14 Feb 2012 11:37:17 +0100 Subject: [PATCH 101/269] usb: renesas_usbhs: (cosmetic) simplify list operations list.h already provide helpers to find the first entry and to move list nodes to the tail of another list. This patch simply uses those helpers, no functional changes. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 03a9cc529c82..fb2a88c5c210 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -76,8 +76,7 @@ void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, pipe->handler = &usbhsf_null_handler; } - list_del_init(&pkt->node); - list_add_tail(&pkt->node, &pipe->list); + list_move_tail(&pkt->node, &pipe->list); /* * each pkt must hold own handler. @@ -107,7 +106,7 @@ static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) if (list_empty(&pipe->list)) return NULL; - return list_entry(pipe->list.next, struct usbhs_pkt, node); + return list_first_entry(&pipe->list, struct usbhs_pkt, node); } struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) From 6e4b74e4690dd03b5664fa4895c3db0607d64742 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 14 Feb 2012 11:37:21 +0100 Subject: [PATCH 102/269] usb: renesas: fix scheduling in atomic context bug The current renesas_usbhs driver triggers BUG: scheduling while atomic: ksoftirqd/0/3/0x00000102 with enabled CONFIG_DEBUG_ATOMIC_SLEEP, by submitting DMA transfers from an atomic (tasklet) context, which is not supported by the shdma dmaengine driver. Fix it by switching to a work. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 18 ++++++------------ drivers/usb/renesas_usbhs/fifo.h | 3 ++- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index fb2a88c5c210..3648c82a17fe 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -765,9 +765,9 @@ static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map) } static void usbhsf_dma_complete(void *arg); -static void usbhsf_dma_prepare_tasklet(unsigned long data) +static void xfer_work(struct work_struct *work) { - struct usbhs_pkt *pkt = (struct usbhs_pkt *)data; + struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work); struct usbhs_pipe *pipe = pkt->pipe; struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe); struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); @@ -847,11 +847,8 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) pkt->trans = len; - tasklet_init(&fifo->tasklet, - usbhsf_dma_prepare_tasklet, - (unsigned long)pkt); - - tasklet_schedule(&fifo->tasklet); + INIT_WORK(&pkt->work, xfer_work); + schedule_work(&pkt->work); return 0; @@ -941,11 +938,8 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) pkt->trans = len; - tasklet_init(&fifo->tasklet, - usbhsf_dma_prepare_tasklet, - (unsigned long)pkt); - - tasklet_schedule(&fifo->tasklet); + INIT_WORK(&pkt->work, xfer_work); + schedule_work(&pkt->work); return 0; diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h index f68609c0f489..c31731a843d1 100644 --- a/drivers/usb/renesas_usbhs/fifo.h +++ b/drivers/usb/renesas_usbhs/fifo.h @@ -19,6 +19,7 @@ #include #include +#include #include #include "pipe.h" @@ -31,7 +32,6 @@ struct usbhs_fifo { u32 ctr; /* xFIFOCTR */ struct usbhs_pipe *pipe; - struct tasklet_struct tasklet; struct dma_chan *tx_chan; struct dma_chan *rx_chan; @@ -53,6 +53,7 @@ struct usbhs_pkt { struct usbhs_pkt_handle *handler; void (*done)(struct usbhs_priv *priv, struct usbhs_pkt *pkt); + struct work_struct work; dma_addr_t dma; void *buf; int length; From d93814cfadb131fb219359d4b7008c728421c552 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 24 Jan 2012 16:39:02 -0800 Subject: [PATCH 103/269] xHCI: Kick khubd when USB3 resume really completes. xHCI roothubs go through slightly different port state machines when either a device initiates a remote wakeup and signals resume, or when the host initiates a resume. According to section 4.19.1.2.13 of the xHCI 1.0 spec, on host-initiated resume, the xHC port state machine automatically goes through the U3Exit state into the U0 state, setting the port link state change (PLC) bit in the process. When a device initiates resume, the xHCI port state machine goes into the "Resume" state and sets the PLC bit. Then the xHCI driver writes U0 into the port link state register to transition the port to U0 from the Resume state. We can't be sure the device is actually in the U0 state until we receive the next port status change event with the PLC bit set. We really don't want khubd to be polling the roothub port status bits until the device is really in U0. Signed-off-by: Sarah Sharp Acked-by: Andiry Xu --- drivers/usb/host/xhci-ring.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b62037bff688..ca38483c9f56 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1321,20 +1321,16 @@ static void handle_port_status(struct xhci_hcd *xhci, } if (DEV_SUPERSPEED(temp)) { - xhci_dbg(xhci, "resume SS port %d\n", port_id); + xhci_dbg(xhci, "remote wake SS port %d\n", port_id); + xhci_test_and_clear_bit(xhci, port_array, + faked_port_index, PORT_PLC); xhci_set_link_state(xhci, port_array, faked_port_index, XDEV_U0); - slot_id = xhci_find_slot_id_by_port(hcd, xhci, - faked_port_index + 1); - if (!slot_id) { - xhci_dbg(xhci, "slot_id is zero\n"); - goto cleanup; - } - xhci_ring_device(xhci, slot_id); - xhci_dbg(xhci, "resume SS port %d finished\n", port_id); - /* Clear PORT_PLC */ - xhci_test_and_clear_bit(xhci, port_array, - faked_port_index, PORT_PLC); + /* Need to wait until the next link state change + * indicates the device is actually in U0. + */ + bogus_port_status = true; + goto cleanup; } else { xhci_dbg(xhci, "resume HS port %d\n", port_id); bus_state->resume_done[faked_port_index] = jiffies + @@ -1345,6 +1341,15 @@ static void handle_port_status(struct xhci_hcd *xhci, } } + if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_U0 && + DEV_SUPERSPEED(temp)) { + xhci_dbg(xhci, "resume SS port %d finished\n", port_id); + slot_id = xhci_find_slot_id_by_port(hcd, xhci, + faked_port_index + 1); + if (slot_id && xhci->devs[slot_id]) + xhci_ring_device(xhci, slot_id); + } + if (hcd->speed != HCD_USB3) xhci_test_and_clear_bit(xhci, port_array, faked_port_index, PORT_PLC); From 623bef9e03a60adc623b09673297ca7a1cdfb367 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 11 Nov 2011 14:57:33 -0800 Subject: [PATCH 104/269] USB/xhci: Enable remote wakeup for USB3 devices. When the USB 3.0 hub support went in, I disabled selective suspend for all external USB 3.0 hubs because they used a different mechanism to enable remote wakeup. In fact, other USB 3.0 devices that could signal remote wakeup would have been prevented from going into suspend because they would have stalled the SetFeature Device Remote Wakeup request. This patch adds support for the USB 3.0 way of enabling remote wake up (with a SetFeature Function Suspend request), and enables selective suspend for all hubs during hub_probe. It assumes that all USB 3.0 have only one "function" as defined by the interface association descriptor, which is true of all the USB 3.0 devices I've seen so far. FIXME if that turns out to change later. After a device signals a remote wakeup, it is supposed to send a Device Notification packet to the host controller, signaling which function sent the remote wakeup. The host can then put any other functions back into function suspend. Since we don't have support for function suspend (and no devices currently support it), we'll just assume the hub function will resume the device properly when it received the port status change notification, and simply ignore any device notification events from the xHCI host controller. Signed-off-by: Sarah Sharp --- drivers/usb/core/hub.c | 25 ++++++++++++++++++++----- drivers/usb/host/xhci-mem.c | 11 ++++++++++- drivers/usb/host/xhci-ring.c | 21 +++++++++++++++++++++ 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 2d773cbe191c..50411cd0ac48 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2421,11 +2421,26 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) * we don't explicitly enable it here. */ if (udev->do_remote_wakeup) { - status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); + if (!hub_is_superspeed(hub->hdev)) { + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + /* Assume there's only one function on the USB 3.0 + * device and enable remote wake for the first + * interface. FIXME if the interface association + * descriptor shows there's more than one function. + */ + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, + USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, + USB_INTRF_FUNC_SUSPEND_RW, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } if (status) { dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", status); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 36cbe2226a44..6b70e7fb484c 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2141,7 +2141,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) unsigned int val, val2; u64 val_64; struct xhci_segment *seg; - u32 page_size; + u32 page_size, temp; int i; page_size = xhci_readl(xhci, &xhci->op_regs->page_size); @@ -2324,6 +2324,15 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) INIT_LIST_HEAD(&xhci->lpm_failed_devs); + /* Enable USB 3.0 device notifications for function remote wake, which + * is necessary for allowing USB 3.0 devices to do remote wakeup from + * U3 (device suspend). + */ + temp = xhci_readl(xhci, &xhci->op_regs->dev_notification); + temp &= ~DEV_NOTE_MASK; + temp |= DEV_NOTE_FWAKE; + xhci_writel(xhci, temp, &xhci->op_regs->dev_notification); + return 0; fail: diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index ca38483c9f56..ffe549338cec 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1237,6 +1237,24 @@ static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd, return num_similar_speed_ports; } +static void handle_device_notification(struct xhci_hcd *xhci, + union xhci_trb *event) +{ + u32 slot_id; + + slot_id = TRB_TO_SLOT_ID(event->generic.field[3]); + if (!xhci->devs[slot_id]) + xhci_warn(xhci, "Device Notification event for " + "unused slot %u\n", slot_id); + else + xhci_dbg(xhci, "Device Notification event for slot ID %u\n", + slot_id); + /* XXX should we kick khubd for the parent hub? It should have send an + * interrupt transfer when the port started signaling resume, so there's + * probably no need to do so. + */ +} + static void handle_port_status(struct xhci_hcd *xhci, union xhci_trb *event) { @@ -2282,6 +2300,9 @@ static int xhci_handle_event(struct xhci_hcd *xhci) else update_ptrs = 0; break; + case TRB_TYPE(TRB_DEV_NOTE): + handle_device_notification(xhci, event); + break; default: if ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK) >= TRB_TYPE(48)) From 3b9b6acd4798aafe9b9f64ccb7e8eb76f27f904a Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 6 Jan 2012 15:48:30 -0800 Subject: [PATCH 105/269] USB: Suspend functions before putting dev into U3. The USB 3.0 bus specification introduces a new type of power management called function suspend. The idea is to be able to suspend different functions (i.e. a scanner or an SD card reader on a USB printer) independently. A device can be in U0, but have one or more functions suspended. Thus, signaling a function resume with the standard device remote wake signaling was not possible. Instead, a device will (without prompt from the host) send a "device notification" for the function remote wake. A new Set Feature Function Remote Wake was developed to turn remote wake up on and off for each function. USB 3.0 devices can still go into device suspend (U3), and signal a remote wakeup to bring the link back into U1. However, they now use the function remote wake device notification to allow the host to know which function woke the device from U3. The spec is a bit ambiguous about whether a function is allowed to signal a remote wakeup if the function has been enabled for remote wakeup, but not placed in function suspend before the device is placed into U3. Section 9.2.5.1 says "Suspending a device with more than one function effectively suspends all the functions within the device." I interpret that to mean that putting a device in U3 suspends all functions, and thus if the host has previously enabled remote wake for those functions, it should be able to signal a remote wake up on port status changes. However, hub vendors may have a different interpretation, and it can't hurt to put the function into suspend before putting the device into U3. I cannot get an answer out of the USB 3.0 spec architects about this ambiguity, so I'm erring on the safe side and always suspending the first function before placing the device in U3. Note, this code should be fixed if we ever find any USB 3.0 devices that have more than one function. Signed-off-by: Sarah Sharp --- drivers/usb/core/hub.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 50411cd0ac48..70622d633fda 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2437,7 +2437,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) USB_REQ_SET_FEATURE, USB_RECIP_INTERFACE, USB_INTRF_FUNC_SUSPEND, - USB_INTRF_FUNC_SUSPEND_RW, + USB_INTRF_FUNC_SUSPEND_RW | + USB_INTRF_FUNC_SUSPEND_LP, NULL, 0, USB_CTRL_SET_TIMEOUT); } From 4296c70a5ec316903ef037ed15f154dd3d354ad7 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 6 Jan 2012 10:34:31 -0800 Subject: [PATCH 106/269] USB/xHCI: Enable USB 3.0 hub remote wakeup. USB 3.0 hubs have a different remote wakeup policy than USB 2.0 hubs. USB 2.0 hubs, once they have remote wakeup enabled, will always send remote wakes when anything changes on a port. However, USB 3.0 hubs have a per-port remote wake up policy that is off by default. The Set Feature remote wake mask can be changed for any port, enabling remote wakeup for a connect, disconnect, or overcurrent event, much like EHCI and xHCI host controller "wake on" port status bits. The bits are cleared to zero on the initial hub power on, or after the hub has been reset. Without this patch, when a USB 3.0 hub gets suspended, it will not send a remote wakeup on device connect or disconnect. This would show up to the user as "dead ports" unless they ran lsusb -v (since newer versions of lsusb use the sysfs files, rather than sending control transfers). Change the hub driver's suspend method to enable remote wake up for disconnect, connect, and overcurrent for all ports on the hub. Modify the xHCI driver's roothub code to handle that request, and set the "wake on" bits in the port status registers accordingly. Signed-off-by: Sarah Sharp --- drivers/usb/core/hub.c | 12 +++++++++++ drivers/usb/host/xhci-hub.c | 41 +++++++++++++++++++++++++++++++++++++ include/linux/usb/ch11.h | 5 +++++ 3 files changed, 58 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 70622d633fda..b3137fa65f2a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2731,6 +2731,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) struct usb_hub *hub = usb_get_intfdata (intf); struct usb_device *hdev = hub->hdev; unsigned port1; + int status; /* Warn if children aren't already suspended */ for (port1 = 1; port1 <= hdev->maxchild; port1++) { @@ -2743,6 +2744,17 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) return -EBUSY; } } + if (hub_is_superspeed(hdev) && hdev->do_remote_wakeup) { + /* Enable hub to send remote wakeup for all ports. */ + for (port1 = 1; port1 <= hdev->maxchild; port1++) { + status = set_port_feature(hdev, + port1 | + USB_PORT_FEAT_REMOTE_WAKE_CONNECT | + USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT | + USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT, + USB_PORT_FEAT_REMOTE_WAKE_MASK); + } + } dev_dbg(&intf->dev, "%s\n", __func__); diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 557b6f32db86..673ad120c43e 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -422,6 +422,32 @@ void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, xhci_writel(xhci, temp, port_array[port_id]); } +void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, + __le32 __iomem **port_array, int port_id, u16 wake_mask) +{ + u32 temp; + + temp = xhci_readl(xhci, port_array[port_id]); + temp = xhci_port_state_to_neutral(temp); + + if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_CONNECT) + temp |= PORT_WKCONN_E; + else + temp &= ~PORT_WKCONN_E; + + if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT) + temp |= PORT_WKDISC_E; + else + temp &= ~PORT_WKDISC_E; + + if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT) + temp |= PORT_WKOC_E; + else + temp &= ~PORT_WKOC_E; + + xhci_writel(xhci, temp, port_array[port_id]); +} + /* Test and clear port RWC bit */ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, int port_id, u32 port_bit) @@ -448,6 +474,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, int slot_id; struct xhci_bus_state *bus_state; u16 link_state = 0; + u16 wake_mask = 0; max_ports = xhci_get_ports(hcd, &port_array); bus_state = &xhci->bus_state[hcd_index(hcd)]; @@ -593,6 +620,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, case SetPortFeature: if (wValue == USB_PORT_FEAT_LINK_STATE) link_state = (wIndex & 0xff00) >> 3; + if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK) + wake_mask = wIndex & 0xff00; wIndex &= 0xff; if (!wIndex || wIndex > max_ports) goto error; @@ -703,6 +732,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = xhci_readl(xhci, port_array[wIndex]); xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp); break; + case USB_PORT_FEAT_REMOTE_WAKE_MASK: + xhci_set_remote_wake_mask(xhci, port_array, + wIndex, wake_mask); + temp = xhci_readl(xhci, port_array[wIndex]); + xhci_dbg(xhci, "set port remote wake mask, " + "actual port %d status = 0x%x\n", + wIndex, temp); + break; case USB_PORT_FEAT_BH_PORT_RESET: temp |= PORT_WR; xhci_writel(xhci, temp, port_array[wIndex]); @@ -883,6 +920,10 @@ int xhci_bus_suspend(struct usb_hcd *hcd) t2 |= PORT_LINK_STROBE | XDEV_U3; set_bit(port_index, &bus_state->bus_suspended); } + /* USB core sets remote wake mask for USB 3.0 hubs, + * including the USB 3.0 roothub, but only if CONFIG_USB_SUSPEND + * is enabled, so also enable remote wake here. + */ if (hcd->self.root_hub->do_remote_wakeup) { if (t1 & PORT_CONNECT) { t2 |= PORT_WKOC_E | PORT_WKDISC_E; diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h index 0b83acd3360a..f1d26b6067f1 100644 --- a/include/linux/usb/ch11.h +++ b/include/linux/usb/ch11.h @@ -76,6 +76,11 @@ #define USB_PORT_FEAT_C_BH_PORT_RESET 29 #define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30 +/* USB 3.0 hub remote wake mask bits, see table 10-14 */ +#define USB_PORT_FEAT_REMOTE_WAKE_CONNECT (1 << 8) +#define USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT (1 << 9) +#define USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT (1 << 10) + /* * Hub Status and Hub Change results * See USB 2.0 spec Table 11-19 and Table 11-20 From 714b07be3bbf94d2dc9838723d63fc827fdbef12 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 24 Jan 2012 13:53:18 -0800 Subject: [PATCH 107/269] USB: Refactor hub remote wake handling. Refactor the code to check for a remote wakeup on a port into its own function. Keep the behavior the same, and set connect_change in hub_events if the device disconnected on resume. Cleanup references to hdev->children[i-1] to use a common variable. Signed-off-by: Sarah Sharp --- drivers/usb/core/hub.c | 59 +++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b3137fa65f2a..ba9509454ed5 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3488,6 +3488,39 @@ done: hcd->driver->relinquish_port(hcd, port1); } +/* Returns 1 if there was a remote wakeup and a connect status change. */ +static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, + u16 portchange) +{ + struct usb_device *hdev; + struct usb_device *udev; + int connect_change = 0; + int ret; + + hdev = hub->hdev; + if (!(portchange & USB_PORT_STAT_C_SUSPEND)) + return 0; + clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND); + + udev = hdev->children[port-1]; + if (udev) { + /* TRSMRCY = 10 msec */ + msleep(10); + + usb_lock_device(udev); + ret = usb_remote_wakeup(udev); + usb_unlock_device(udev); + if (ret < 0) + connect_change = 1; + } else { + ret = -ENODEV; + hub_port_disable(hub, port, 1); + } + dev_dbg(hub->intfdev, "resume on port %d, status %d\n", + port, ret); + return connect_change; +} + static void hub_events(void) { struct list_head *tmp; @@ -3621,31 +3654,9 @@ static void hub_events(void) } } - if (portchange & USB_PORT_STAT_C_SUSPEND) { - struct usb_device *udev; + if (hub_handle_remote_wakeup(hub, i, portchange)) + connect_change = 1; - clear_port_feature(hdev, i, - USB_PORT_FEAT_C_SUSPEND); - udev = hdev->children[i-1]; - if (udev) { - /* TRSMRCY = 10 msec */ - msleep(10); - - usb_lock_device(udev); - ret = usb_remote_wakeup(hdev-> - children[i-1]); - usb_unlock_device(udev); - if (ret < 0) - connect_change = 1; - } else { - ret = -ENODEV; - hub_port_disable(hub, i, 1); - } - dev_dbg (hub_dev, - "resume on port %d, status %d\n", - i, ret); - } - if (portchange & USB_PORT_STAT_C_OVERCURRENT) { u16 status = 0; u16 unused; From 4ee823b83bc9851743fab756c76b27d6a1e2472b Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 14 Nov 2011 18:00:01 -0800 Subject: [PATCH 108/269] USB/xHCI: Support device-initiated USB 3.0 resume. USB 3.0 hubs don't have a port suspend change bit (that bit is now reserved). Instead, when a host-initiated resume finishes, the hub sets the port link state change bit. When a USB 3.0 device initiates remote wakeup, the parent hubs with their upstream links in U3 will pass the LFPS up the chain. The first hub that has an upstream link in U0 (which may be the roothub) will reflect that LFPS back down the path to the device. However, the parent hubs in the resumed path will not set their link state change bit. Instead, the device that initiated the resume has to send an asynchronous "Function Wake" Device Notification up to the host controller. Therefore, we need a way to notify the USB core of a device resume without going through the normal hub URB completion method. First, make the xHCI roothub act like an external USB 3.0 hub and not pass up the port link state change bit when a device-initiated resume finishes. Introduce a new xHCI bit field, port_remote_wakeup, so that we can tell the difference between a port coming out of the U3Exit state (host-initiated resume) and the RExit state (ending state of device-initiated resume). Since the USB core can't tell whether a port on a hub has resumed by looking at the Hub Status buffer, we need to introduce a bitfield, wakeup_bits, that indicates which ports have resumed. When the xHCI driver notices a port finishing a device-initiated resume, we call into a new USB core function, usb_wakeup_notification(), that will set the right bit in wakeup_bits, and kick khubd for that hub. We also call usb_wakeup_notification() when the Function Wake Device Notification is received by the xHCI driver. This covers the case where the link between the roothub and the first-tier hub is in U0, and the hub reflects the resume signaling back to the device without giving any indication it has done so until the device sends the Function Wake notification. Change the code in khubd that handles the remote wakeup to look at the state the USB core thinks the device is in, and handle the remote wakeup if the port's wakeup bit is set. This patch only takes care of the case where the device is attached directly to the roothub, or the USB 3.0 hub that is attached to the root hub is the device sending the Function Wake Device Notification (e.g. because a new USB device was attached). The other cases will be covered in a second patch. Signed-off-by: Sarah Sharp --- drivers/usb/core/hub.c | 51 +++++++++++++++++++++++++++--------- drivers/usb/host/xhci-ring.c | 40 ++++++++++++++++++++++------ drivers/usb/host/xhci.h | 1 + include/linux/usb/hcd.h | 2 ++ 4 files changed, 74 insertions(+), 20 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index ba9509454ed5..1c32bbac9862 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -62,6 +62,8 @@ struct usb_hub { resumed */ unsigned long removed_bits[1]; /* ports with a "removed" device present */ + unsigned long wakeup_bits[1]; /* ports that have signaled + remote wakeup */ #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ #error event_bits[] is too short! #endif @@ -411,6 +413,29 @@ void usb_kick_khubd(struct usb_device *hdev) kick_khubd(hub); } +/* + * Let the USB core know that a USB 3.0 device has sent a Function Wake Device + * Notification, which indicates it had initiated remote wakeup. + * + * USB 3.0 hubs do not report the port link state change from U3 to U0 when the + * device initiates resume, so the USB core will not receive notice of the + * resume through the normal hub interrupt URB. + */ +void usb_wakeup_notification(struct usb_device *hdev, + unsigned int portnum) +{ + struct usb_hub *hub; + + if (!hdev) + return; + + hub = hdev_to_hub(hdev); + if (hub) { + set_bit(portnum, hub->wakeup_bits); + kick_khubd(hub); + } +} +EXPORT_SYMBOL_GPL(usb_wakeup_notification); /* completion function, fires on port status changes and various faults */ static void hub_irq(struct urb *urb) @@ -807,12 +832,6 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_ENABLE); } - if (portchange & USB_PORT_STAT_C_LINK_STATE) { - need_debounce_delay = true; - clear_port_feature(hub->hdev, port1, - USB_PORT_FEAT_C_PORT_LINK_STATE); - } - if ((portchange & USB_PORT_STAT_C_BH_RESET) && hub_is_superspeed(hub->hdev)) { need_debounce_delay = true; @@ -3498,11 +3517,18 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, int ret; hdev = hub->hdev; - if (!(portchange & USB_PORT_STAT_C_SUSPEND)) - return 0; - clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND); - udev = hdev->children[port-1]; + if (!hub_is_superspeed(hdev)) { + if (!(portchange & USB_PORT_STAT_C_SUSPEND)) + return 0; + clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND); + } else { + if (!udev || udev->state != USB_STATE_SUSPENDED || + !test_and_clear_bit(udev->portnum, + hub->wakeup_bits)) + return 0; + } + if (udev) { /* TRSMRCY = 10 msec */ msleep(10); @@ -3533,7 +3559,7 @@ static void hub_events(void) u16 portstatus; u16 portchange; int i, ret; - int connect_change; + int connect_change, wakeup_change; /* * We restart the list every time to avoid a deadlock with @@ -3612,8 +3638,9 @@ static void hub_events(void) if (test_bit(i, hub->busy_bits)) continue; connect_change = test_bit(i, hub->change_bits); + wakeup_change = test_bit(i, hub->wakeup_bits); if (!test_and_clear_bit(i, hub->event_bits) && - !connect_change) + !connect_change && !wakeup_change) continue; ret = hub_port_status(hub, i, diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index ffe549338cec..3a033240ec64 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1241,18 +1241,20 @@ static void handle_device_notification(struct xhci_hcd *xhci, union xhci_trb *event) { u32 slot_id; + struct usb_device *udev; slot_id = TRB_TO_SLOT_ID(event->generic.field[3]); - if (!xhci->devs[slot_id]) + if (!xhci->devs[slot_id]) { xhci_warn(xhci, "Device Notification event for " "unused slot %u\n", slot_id); - else - xhci_dbg(xhci, "Device Notification event for slot ID %u\n", - slot_id); - /* XXX should we kick khubd for the parent hub? It should have send an - * interrupt transfer when the port started signaling resume, so there's - * probably no need to do so. - */ + return; + } + + xhci_dbg(xhci, "Device Wake Notification event for slot ID %u\n", + slot_id); + udev = xhci->devs[slot_id]->udev; + if (udev && udev->parent) + usb_wakeup_notification(udev->parent, udev->portnum); } static void handle_port_status(struct xhci_hcd *xhci, @@ -1340,6 +1342,11 @@ static void handle_port_status(struct xhci_hcd *xhci, if (DEV_SUPERSPEED(temp)) { xhci_dbg(xhci, "remote wake SS port %d\n", port_id); + /* Set a flag to say the port signaled remote wakeup, + * so we can tell the difference between the end of + * device and host initiated resume. + */ + bus_state->port_remote_wakeup |= 1 << faked_port_index; xhci_test_and_clear_bit(xhci, port_array, faked_port_index, PORT_PLC); xhci_set_link_state(xhci, port_array, faked_port_index, @@ -1362,10 +1369,27 @@ static void handle_port_status(struct xhci_hcd *xhci, if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_U0 && DEV_SUPERSPEED(temp)) { xhci_dbg(xhci, "resume SS port %d finished\n", port_id); + /* We've just brought the device into U0 through either the + * Resume state after a device remote wakeup, or through the + * U3Exit state after a host-initiated resume. If it's a device + * initiated remote wake, don't pass up the link state change, + * so the roothub behavior is consistent with external + * USB 3.0 hub behavior. + */ slot_id = xhci_find_slot_id_by_port(hcd, xhci, faked_port_index + 1); if (slot_id && xhci->devs[slot_id]) xhci_ring_device(xhci, slot_id); + if (bus_state->port_remote_wakeup && (1 << faked_port_index)) { + bus_state->port_remote_wakeup &= + ~(1 << faked_port_index); + xhci_test_and_clear_bit(xhci, port_array, + faked_port_index, PORT_PLC); + usb_wakeup_notification(hcd->self.root_hub, + faked_port_index + 1); + bogus_port_status = true; + goto cleanup; + } } if (hcd->speed != HCD_USB3) diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index fb99c8379142..0f4936956103 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1344,6 +1344,7 @@ struct xhci_bus_state { /* ports suspend status arrays - max 31 ports for USB2, 15 for USB3 */ u32 port_c_suspend; u32 suspended_ports; + u32 port_remote_wakeup; unsigned long resume_done[USB_MAXCHILDREN]; }; diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index b2f62f3a32af..2e6071efbfb7 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -412,6 +412,8 @@ extern irqreturn_t usb_hcd_irq(int irq, void *__hcd); extern void usb_hc_died(struct usb_hcd *hcd); extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd); +extern void usb_wakeup_notification(struct usb_device *hdev, + unsigned int portnum); /* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */ #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1) From 72937e1e342f5631d08df4ef0629e55bdcf74c76 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 24 Jan 2012 11:46:50 -0800 Subject: [PATCH 109/269] USB: Set wakeup bits for all children hubs. This patch takes care of the race condition between the Function Wake Device Notification and the auto-suspend timeout for this situation: Roothub | (U3) hub A | (U3) hub B | (U3) device C When device C signals a resume, the xHCI driver will set the wakeup_bits for the roothub port that hub A is attached to. However, since USB 3.0 hubs do not set a link state change bit on device-initiated resume, hub A will not indicate a port event when polled. Without this patch, khubd will notice the wakeup-bits are set for the roothub port, it will resume hub A, and then it will poll the events bits for hub A and notice that nothing has changed. Then it will be suspended after 2 seconds. Change hub_activate() to look at the port link state for each USB 3.0 hub port, and set hub->change_bits if the link state is U0, indicating the device has finished resume. Change the resume function called by hub_events(), hub_handle_remote_wakeup(), to check the link status for resume instead of just the port's wakeup_bits. Signed-off-by: Sarah Sharp --- drivers/usb/core/hub.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 1c32bbac9862..994aa8853bac 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -853,12 +853,19 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) set_bit(port1, hub->change_bits); } else if (portstatus & USB_PORT_STAT_ENABLE) { + bool port_resumed = (portstatus & + USB_PORT_STAT_LINK_STATE) == + USB_SS_PORT_LS_U0; /* The power session apparently survived the resume. * If there was an overcurrent or suspend change * (i.e., remote wakeup request), have khubd - * take care of it. + * take care of it. Look at the port link state + * for USB 3.0 hubs, since they don't have a suspend + * change bit, and they don't set the port link change + * bit on device-initiated resume. */ - if (portchange) + if (portchange || (hub_is_superspeed(hub->hdev) && + port_resumed)) set_bit(port1, hub->change_bits); } else if (udev->persist_enabled) { @@ -3509,7 +3516,7 @@ done: /* Returns 1 if there was a remote wakeup and a connect status change. */ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, - u16 portchange) + u16 portstatus, u16 portchange) { struct usb_device *hdev; struct usb_device *udev; @@ -3524,8 +3531,8 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND); } else { if (!udev || udev->state != USB_STATE_SUSPENDED || - !test_and_clear_bit(udev->portnum, - hub->wakeup_bits)) + (portstatus & USB_PORT_STAT_LINK_STATE) != + USB_SS_PORT_LS_U0) return 0; } @@ -3638,7 +3645,7 @@ static void hub_events(void) if (test_bit(i, hub->busy_bits)) continue; connect_change = test_bit(i, hub->change_bits); - wakeup_change = test_bit(i, hub->wakeup_bits); + wakeup_change = test_and_clear_bit(i, hub->wakeup_bits); if (!test_and_clear_bit(i, hub->event_bits) && !connect_change && !wakeup_change) continue; @@ -3681,7 +3688,8 @@ static void hub_events(void) } } - if (hub_handle_remote_wakeup(hub, i, portchange)) + if (hub_handle_remote_wakeup(hub, i, + portstatus, portchange)) connect_change = 1; if (portchange & USB_PORT_STAT_C_OVERCURRENT) { From 2839f5bcfcfc61f69a36c262107e3cfd6eee9f53 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 6 Jan 2012 16:27:25 -0800 Subject: [PATCH 110/269] USB: Turn on auto-suspend for USB 3.0 hubs. Now that USB 3.0 hub remote wakeup on port status changes is enabled, and USB 3.0 device remote wakeup is handled in the USB core properly, let's turn on auto-suspend for all USB 3.0 hubs. Signed-off-by: Sarah Sharp --- drivers/usb/core/hub.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 994aa8853bac..d4f062472796 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1315,14 +1315,8 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) desc = intf->cur_altsetting; hdev = interface_to_usbdev(intf); - /* Hubs have proper suspend/resume support. USB 3.0 device suspend is - * different from USB 2.0/1.1 device suspend, and unfortunately we - * don't support it yet. So leave autosuspend disabled for USB 3.0 - * external hubs for now. Enable autosuspend for USB 3.0 roothubs, - * since that isn't a "real" hub. - */ - if (!hub_is_superspeed(hdev) || !hdev->parent) - usb_enable_autosuspend(hdev); + /* Hubs have proper suspend/resume support. */ + usb_enable_autosuspend(hdev); if (hdev->level == MAX_TOPO_LEVEL) { dev_err(&intf->dev, From 18b5b3b55f44c28a0380f3559d1db3c467f94b4a Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Thu, 2 Feb 2012 21:59:53 +0530 Subject: [PATCH 111/269] usb: gadget: Rename audio function to uac1 The extant USB-Audio function driver complies to UAC_1 spec. So name the files accordingly, paving way for inclusion of a new UAC_2 specified driver. Signed-off-by: Yadi Brar Signed-off-by: Jassi Brar Signed-off-by: Felipe Balbi --- drivers/usb/gadget/audio.c | 6 +++--- drivers/usb/gadget/{f_audio.c => f_uac1.c} | 2 +- drivers/usb/gadget/{u_audio.c => u_uac1.c} | 4 ++-- drivers/usb/gadget/{u_audio.h => u_uac1.h} | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) rename drivers/usb/gadget/{f_audio.c => f_uac1.c} (99%) rename drivers/usb/gadget/{u_audio.c => u_uac1.c} (99%) rename drivers/usb/gadget/{u_audio.h => u_uac1.h} (94%) diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 9d89ae4765a9..056a2d936d7f 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -14,7 +14,7 @@ #include #include -#include "u_audio.h" +#include "u_uac1.h" #define DRIVER_DESC "Linux USB Audio Gadget" #define DRIVER_VERSION "Dec 18, 2008" @@ -33,8 +33,8 @@ #include "config.c" #include "epautoconf.c" -#include "u_audio.c" -#include "f_audio.c" +#include "u_uac1.c" +#include "f_uac1.c" /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/f_audio.c b/drivers/usb/gadget/f_uac1.c similarity index 99% rename from drivers/usb/gadget/f_audio.c rename to drivers/usb/gadget/f_uac1.c index ec7ffcd0d0cd..e4c060fd81e4 100644 --- a/drivers/usb/gadget/f_audio.c +++ b/drivers/usb/gadget/f_uac1.c @@ -14,7 +14,7 @@ #include #include -#include "u_audio.h" +#include "u_uac1.h" #define OUT_EP_MAX_PACKET_SIZE 200 static int req_buf_size = OUT_EP_MAX_PACKET_SIZE; diff --git a/drivers/usb/gadget/u_audio.c b/drivers/usb/gadget/u_uac1.c similarity index 99% rename from drivers/usb/gadget/u_audio.c rename to drivers/usb/gadget/u_uac1.c index 59ffe1ecf1c9..af9898982059 100644 --- a/drivers/usb/gadget/u_audio.c +++ b/drivers/usb/gadget/u_uac1.c @@ -1,5 +1,5 @@ /* - * u_audio.c -- ALSA audio utilities for Gadget stack + * u_uac1.c -- ALSA audio utilities for Gadget stack * * Copyright (C) 2008 Bryan Wu * Copyright (C) 2008 Analog Devices, Inc @@ -17,7 +17,7 @@ #include #include -#include "u_audio.h" +#include "u_uac1.h" /* * This component encapsulates the ALSA devices for USB audio gadget diff --git a/drivers/usb/gadget/u_audio.h b/drivers/usb/gadget/u_uac1.h similarity index 94% rename from drivers/usb/gadget/u_audio.h rename to drivers/usb/gadget/u_uac1.h index 08ffce3298e6..18c2e729faf6 100644 --- a/drivers/usb/gadget/u_audio.h +++ b/drivers/usb/gadget/u_uac1.h @@ -1,5 +1,5 @@ /* - * u_audio.h -- interface to USB gadget "ALSA AUDIO" utilities + * u_uac1.h -- interface to USB gadget "ALSA AUDIO" utilities * * Copyright (C) 2008 Bryan Wu * Copyright (C) 2008 Analog Devices, Inc From 0d4e1b2a7eb7f4db8b3dc1c7ef4b507040f87ded Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Thu, 2 Feb 2012 22:00:48 +0530 Subject: [PATCH 112/269] usb: uac2: Add ACHeader and FormatType descriptor Add missing, but needed, ACHeader and FormatType descriptor definitions. Signed-off-by: Yadi Brar Signed-off-by: Jassi Brar Signed-off-by: Felipe Balbi --- include/linux/usb/audio-v2.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/linux/usb/audio-v2.h b/include/linux/usb/audio-v2.h index 964cb603f7c7..ed13053153f4 100644 --- a/include/linux/usb/audio-v2.h +++ b/include/linux/usb/audio-v2.h @@ -43,6 +43,27 @@ static inline bool uac2_control_is_writeable(u32 bmControls, u8 control) return (bmControls >> (control * 2)) & 0x2; } +/* 4.7.2 Class-Specific AC Interface Descriptor */ +struct uac2_ac_header_descriptor { + __u8 bLength; /* 9 */ + __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ + __u8 bDescriptorSubtype; /* UAC_MS_HEADER */ + __le16 bcdADC; /* 0x0200 */ + __u8 bCategory; + __le16 wTotalLength; /* includes Unit and Terminal desc. */ + __u8 bmControls; +} __packed; + +/* 2.3.1.6 Type I Format Type Descriptor (Frmts20 final.pdf)*/ +struct uac2_format_type_i_descriptor { + __u8 bLength; /* in bytes: 6 */ + __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ + __u8 bDescriptorSubtype; /* FORMAT_TYPE */ + __u8 bFormatType; /* FORMAT_TYPE_1 */ + __u8 bSubslotSize; /* {1,2,3,4} */ + __u8 bBitResolution; +} __packed; + /* 4.7.2.1 Clock Source Descriptor */ struct uac_clock_source_descriptor { From d747a916872241daef68c864ef09f8bef0c35bf8 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Thu, 2 Feb 2012 22:01:12 +0530 Subject: [PATCH 113/269] usb: gadget: audio: Move string IDs to audio.c Move manufacturer and product string ids into audio.c so as to be reusable by the new uac2 version of gadget driver. Signed-off-by: Yadi Brar Signed-off-by: Jassi Brar Signed-off-by: Felipe Balbi --- drivers/usb/gadget/audio.c | 23 +++++++++++++++++++++++ drivers/usb/gadget/f_uac1.c | 23 ----------------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 056a2d936d7f..33e9327d6639 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -33,6 +33,29 @@ #include "config.c" #include "epautoconf.c" +/* string IDs are assigned dynamically */ + +#define STRING_MANUFACTURER_IDX 0 +#define STRING_PRODUCT_IDX 1 + +static char manufacturer[50]; + +static struct usb_string strings_dev[] = { + [STRING_MANUFACTURER_IDX].s = manufacturer, + [STRING_PRODUCT_IDX].s = DRIVER_DESC, + { } /* end of list */ +}; + +static struct usb_gadget_strings stringtab_dev = { + .language = 0x0409, /* en-us */ + .strings = strings_dev, +}; + +static struct usb_gadget_strings *audio_strings[] = { + &stringtab_dev, + NULL, +}; + #include "u_uac1.c" #include "f_uac1.c" diff --git a/drivers/usb/gadget/f_uac1.c b/drivers/usb/gadget/f_uac1.c index e4c060fd81e4..1a5dcd5565e3 100644 --- a/drivers/usb/gadget/f_uac1.c +++ b/drivers/usb/gadget/f_uac1.c @@ -216,29 +216,6 @@ static struct usb_descriptor_header *f_audio_desc[] __initdata = { NULL, }; -/* string IDs are assigned dynamically */ - -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 - -static char manufacturer[50]; - -static struct usb_string strings_dev[] = { - [STRING_MANUFACTURER_IDX].s = manufacturer, - [STRING_PRODUCT_IDX].s = DRIVER_DESC, - { } /* end of list */ -}; - -static struct usb_gadget_strings stringtab_dev = { - .language = 0x0409, /* en-us */ - .strings = strings_dev, -}; - -static struct usb_gadget_strings *audio_strings[] = { - &stringtab_dev, - NULL, -}; - /* * This function is an ALSA sound card following USB Audio Class Spec 1.0. */ From 132fcb460839a876f5bc8b71bede60f8d0875757 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Thu, 2 Feb 2012 22:01:34 +0530 Subject: [PATCH 114/269] usb: gadget: Add Audio Class 2.0 Driver This is a flexible USB Audio Class 2.0 compliant gadget driver that implements a simple topology with a virtual sound card exposed at the function side. The driver doesn't expect any real audio codec to be present on the function - the audio streams are simply sinked to and sourced from a virtual ALSA sound card created. The user-space application may choose to do whatever it wants with the data received from the USB Host and choose to provide whatever it wants as audio data to the USB Host. Capture(USB-Out) and Playback(USB-In) can be run at independent configurations specified via module parameters while loading the driver. Make this new version as the default selection by a new Kconfig choice. Signed-off-by: Yadi Brar Signed-off-by: Jassi Brar Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 25 +- drivers/usb/gadget/audio.c | 20 +- drivers/usb/gadget/f_uac2.c | 1449 +++++++++++++++++++++++++++++++++++ 3 files changed, 1485 insertions(+), 9 deletions(-) create mode 100644 drivers/usb/gadget/f_uac2.c diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 7ecb68a67411..1623b5204da4 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -599,16 +599,29 @@ config USB_AUDIO depends on SND select SND_PCM help - Gadget Audio is compatible with USB Audio Class specification 1.0. - It will include at least one AudioControl interface, zero or more - AudioStream interface and zero or more MIDIStream interface. - - Gadget Audio will use on-board ALSA (CONFIG_SND) audio card to - playback or capture audio stream. + This Gadget Audio driver is compatible with USB Audio Class + specification 2.0. It implements 1 AudioControl interface, + 1 AudioStreaming Interface each for USB-OUT and USB-IN. + Number of channels, sample rate and sample size can be + specified as module parameters. + This driver doesn't expect any real Audio codec to be present + on the device - the audio streams are simply sinked to and + sourced from a virtual ALSA sound card created. The user-space + application may choose to do whatever it wants with the data + received from the USB Host and choose to provide whatever it + wants as audio data to the USB Host. Say "y" to link the driver statically, or "m" to build a dynamically linked module called "g_audio". +config GADGET_UAC1 + bool "UAC 1.0 (Legacy)" + depends on USB_AUDIO + help + If you instead want older UAC Spec-1.0 driver that also has audio + paths hardwired to the Audio codec chip on-board and doesn't work + without one. + config USB_ETH tristate "Ethernet Gadget (with CDC Ethernet support)" depends on NET diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 33e9327d6639..98899244860e 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -14,10 +14,8 @@ #include #include -#include "u_uac1.h" - #define DRIVER_DESC "Linux USB Audio Gadget" -#define DRIVER_VERSION "Dec 18, 2008" +#define DRIVER_VERSION "Feb 2, 2012" /*-------------------------------------------------------------------------*/ @@ -56,8 +54,13 @@ static struct usb_gadget_strings *audio_strings[] = { NULL, }; +#ifdef CONFIG_GADGET_UAC1 +#include "u_uac1.h" #include "u_uac1.c" #include "f_uac1.c" +#else +#include "f_uac2.c" +#endif /*-------------------------------------------------------------------------*/ @@ -77,9 +80,15 @@ static struct usb_device_descriptor device_desc = { .bcdUSB = __constant_cpu_to_le16(0x200), +#ifdef CONFIG_GADGET_UAC1 .bDeviceClass = USB_CLASS_PER_INTERFACE, .bDeviceSubClass = 0, .bDeviceProtocol = 0, +#else + .bDeviceClass = USB_CLASS_MISC, + .bDeviceSubClass = 0x02, + .bDeviceProtocol = 0x01, +#endif /* .bMaxPacketSize0 = f(hardware) */ /* Vendor and product id defaults change according to what configs @@ -131,6 +140,9 @@ static struct usb_configuration audio_config_driver = { .bConfigurationValue = 1, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, +#ifndef CONFIG_GADGET_UAC1 + .unbind = uac2_unbind_config, +#endif }; /*-------------------------------------------------------------------------*/ @@ -180,7 +192,9 @@ fail: static int __exit audio_unbind(struct usb_composite_dev *cdev) { +#ifdef CONFIG_GADGET_UAC1 gaudio_cleanup(); +#endif return 0; } diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c new file mode 100644 index 000000000000..e7cc4de93e33 --- /dev/null +++ b/drivers/usb/gadget/f_uac2.c @@ -0,0 +1,1449 @@ +/* + * f_uac2.c -- USB Audio Class 2.0 Function + * + * Copyright (C) 2011 + * Yadwinder Singh (yadi.brar01@gmail.com) + * Jaswinder Singh (jaswinder.singh@linaro.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include + +#include +#include +#include + +/* Playback(USB-IN) Default Stereo - Fl/Fr */ +static int p_chmask = 0x3; +module_param(p_chmask, uint, S_IRUGO); +MODULE_PARM_DESC(p_chmask, "Playback Channel Mask"); + +/* Playback Default 48 KHz */ +static int p_srate = 48000; +module_param(p_srate, uint, S_IRUGO); +MODULE_PARM_DESC(p_srate, "Playback Sampling Rate"); + +/* Playback Default 16bits/sample */ +static int p_ssize = 2; +module_param(p_ssize, uint, S_IRUGO); +MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)"); + +/* Capture(USB-OUT) Default Stereo - Fl/Fr */ +static int c_chmask = 0x3; +module_param(c_chmask, uint, S_IRUGO); +MODULE_PARM_DESC(c_chmask, "Capture Channel Mask"); + +/* Capture Default 64 KHz */ +static int c_srate = 64000; +module_param(c_srate, uint, S_IRUGO); +MODULE_PARM_DESC(c_srate, "Capture Sampling Rate"); + +/* Capture Default 16bits/sample */ +static int c_ssize = 2; +module_param(c_ssize, uint, S_IRUGO); +MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); + +#define DMA_ADDR_INVALID (~(dma_addr_t)0) + +#define ALT_SET(x, a) do {(x) &= ~0xff; (x) |= (a); } while (0) +#define ALT_GET(x) ((x) & 0xff) +#define INTF_SET(x, i) do {(x) &= 0xff; (x) |= ((i) << 8); } while (0) +#define INTF_GET(x) ((x >> 8) & 0xff) + +/* Keep everyone on toes */ +#define USB_XFERS 2 + +/* + * The driver implements a simple UAC_2 topology. + * USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture + * ALSA_Playback -> IT_2 -> OT_4 -> USB-IN + * Capture and Playback sampling rates are independently + * controlled by two clock sources : + * CLK_5 := c_srate, and CLK_6 := p_srate + */ +#define USB_OUT_IT_ID 1 +#define IO_IN_IT_ID 2 +#define IO_OUT_OT_ID 3 +#define USB_IN_OT_ID 4 +#define USB_OUT_CLK_ID 5 +#define USB_IN_CLK_ID 6 + +#define CONTROL_ABSENT 0 +#define CONTROL_RDONLY 1 +#define CONTROL_RDWR 3 + +#define CLK_FREQ_CTRL 0 +#define CLK_VLD_CTRL 2 + +#define COPY_CTRL 0 +#define CONN_CTRL 2 +#define OVRLD_CTRL 4 +#define CLSTR_CTRL 6 +#define UNFLW_CTRL 8 +#define OVFLW_CTRL 10 + +const char *uac2_name = "snd_uac2"; + +struct uac2_req { + struct uac2_rtd_params *pp; /* parent param */ + struct usb_request *req; +}; + +struct uac2_rtd_params { + bool ep_enabled; /* if the ep is enabled */ + /* Size of the ring buffer */ + size_t dma_bytes; + unsigned char *dma_area; + + struct snd_pcm_substream *ss; + + /* Ring buffer */ + ssize_t hw_ptr; + + void *rbuf; + + size_t period_size; + + unsigned max_psize; + struct uac2_req ureq[USB_XFERS]; + + spinlock_t lock; +}; + +struct snd_uac2_chip { + struct platform_device pdev; + struct platform_driver pdrv; + + struct uac2_rtd_params p_prm; + struct uac2_rtd_params c_prm; + + struct snd_card *card; + struct snd_pcm *pcm; +}; + +#define BUFF_SIZE_MAX (PAGE_SIZE * 16) +#define PRD_SIZE_MAX PAGE_SIZE +#define MIN_PERIODS 4 + +static struct snd_pcm_hardware uac2_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER + | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID + | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .periods_max = BUFF_SIZE_MAX / PRD_SIZE_MAX, + .buffer_bytes_max = BUFF_SIZE_MAX, + .period_bytes_max = PRD_SIZE_MAX, + .periods_min = MIN_PERIODS, +}; + +struct audio_dev { + /* Currently active {Interface[15:8] | AltSettings[7:0]} */ + __u16 ac_alt, as_out_alt, as_in_alt; + + struct usb_ep *in_ep, *out_ep; + struct usb_function func; + + /* The ALSA Sound Card it represents on the USB-Client side */ + struct snd_uac2_chip uac2; +}; + +static struct audio_dev *agdev_g; + +static inline +struct audio_dev *func_to_agdev(struct usb_function *f) +{ + return container_of(f, struct audio_dev, func); +} + +static inline +struct audio_dev *uac2_to_agdev(struct snd_uac2_chip *u) +{ + return container_of(u, struct audio_dev, uac2); +} + +static inline +struct snd_uac2_chip *pdev_to_uac2(struct platform_device *p) +{ + return container_of(p, struct snd_uac2_chip, pdev); +} + +static inline +struct snd_uac2_chip *prm_to_uac2(struct uac2_rtd_params *r) +{ + struct snd_uac2_chip *uac2 = container_of(r, + struct snd_uac2_chip, c_prm); + + if (&uac2->c_prm != r) + uac2 = container_of(r, struct snd_uac2_chip, p_prm); + + return uac2; +} + +static inline +uint num_channels(uint chanmask) +{ + uint num = 0; + + while (chanmask) { + num += (chanmask & 1); + chanmask >>= 1; + } + + return num; +} + +static void +agdev_iso_complete(struct usb_ep *ep, struct usb_request *req) +{ + unsigned pending; + unsigned long flags; + bool update_alsa = false; + unsigned char *src, *dst; + int status = req->status; + struct uac2_req *ur = req->context; + struct snd_pcm_substream *substream; + struct uac2_rtd_params *prm = ur->pp; + struct snd_uac2_chip *uac2 = prm_to_uac2(prm); + + /* i/f shutting down */ + if (!prm->ep_enabled) + return; + + /* + * We can't really do much about bad xfers. + * Afterall, the ISOCH xfers could fail legitimately. + */ + if (status) + pr_debug("%s: iso_complete status(%d) %d/%d\n", + __func__, status, req->actual, req->length); + + substream = prm->ss; + + /* Do nothing if ALSA isn't active */ + if (!substream) + goto exit; + + spin_lock_irqsave(&prm->lock, flags); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + src = prm->dma_area + prm->hw_ptr; + req->actual = req->length; + dst = req->buf; + } else { + dst = prm->dma_area + prm->hw_ptr; + src = req->buf; + } + + pending = prm->hw_ptr % prm->period_size; + pending += req->actual; + if (pending >= prm->period_size) + update_alsa = true; + + prm->hw_ptr = (prm->hw_ptr + req->actual) % prm->dma_bytes; + + spin_unlock_irqrestore(&prm->lock, flags); + + /* Pack USB load in ALSA ring buffer */ + memcpy(dst, src, req->actual); +exit: + if (usb_ep_queue(ep, req, GFP_ATOMIC)) + dev_err(&uac2->pdev.dev, "%d Error!\n", __LINE__); + + if (update_alsa) + snd_pcm_period_elapsed(substream); + + return; +} + +static int +uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); + struct audio_dev *agdev = uac2_to_agdev(uac2); + struct uac2_rtd_params *prm; + unsigned long flags; + struct usb_ep *ep; + int err = 0; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ep = agdev->in_ep; + prm = &uac2->p_prm; + } else { + ep = agdev->out_ep; + prm = &uac2->c_prm; + } + + spin_lock_irqsave(&prm->lock, flags); + + /* Reset */ + prm->hw_ptr = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + prm->ss = substream; + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + prm->ss = NULL; + break; + default: + err = -EINVAL; + } + + spin_unlock_irqrestore(&prm->lock, flags); + + /* Clear buffer after Play stops */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !prm->ss) + memset(prm->rbuf, 0, prm->max_psize * USB_XFERS); + + return err; +} + +static snd_pcm_uframes_t uac2_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); + struct uac2_rtd_params *prm; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + prm = &uac2->p_prm; + else + prm = &uac2->c_prm; + + return bytes_to_frames(substream->runtime, prm->hw_ptr); +} + +static int uac2_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); + struct uac2_rtd_params *prm; + int err; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + prm = &uac2->p_prm; + else + prm = &uac2->c_prm; + + err = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + if (err >= 0) { + prm->dma_bytes = substream->runtime->dma_bytes; + prm->dma_area = substream->runtime->dma_area; + prm->period_size = params_period_bytes(hw_params); + } + + return err; +} + +static int uac2_pcm_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); + struct uac2_rtd_params *prm; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + prm = &uac2->p_prm; + else + prm = &uac2->c_prm; + + prm->dma_area = NULL; + prm->dma_bytes = 0; + prm->period_size = 0; + + return snd_pcm_lib_free_pages(substream); +} + +static int uac2_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + + runtime->hw = uac2_pcm_hardware; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + spin_lock_init(&uac2->p_prm.lock); + runtime->hw.rate_min = p_srate; + runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! p_ssize ! */ + runtime->hw.channels_min = num_channels(p_chmask); + runtime->hw.period_bytes_min = 2 * uac2->p_prm.max_psize + / runtime->hw.periods_min; + } else { + spin_lock_init(&uac2->c_prm.lock); + runtime->hw.rate_min = c_srate; + runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! c_ssize ! */ + runtime->hw.channels_min = num_channels(c_chmask); + runtime->hw.period_bytes_min = 2 * uac2->c_prm.max_psize + / runtime->hw.periods_min; + } + + runtime->hw.rate_max = runtime->hw.rate_min; + runtime->hw.channels_max = runtime->hw.channels_min; + + snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + + return 0; +} + +/* ALSA cries without these function pointers */ +static int uac2_pcm_null(struct snd_pcm_substream *substream) +{ + return 0; +} + +static struct snd_pcm_ops uac2_pcm_ops = { + .open = uac2_pcm_open, + .close = uac2_pcm_null, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = uac2_pcm_hw_params, + .hw_free = uac2_pcm_hw_free, + .trigger = uac2_pcm_trigger, + .pointer = uac2_pcm_pointer, + .prepare = uac2_pcm_null, +}; + +static int __devinit snd_uac2_probe(struct platform_device *pdev) +{ + struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev); + struct snd_card *card; + struct snd_pcm *pcm; + int err; + + /* Choose any slot, with no id */ + err = snd_card_create(-1, NULL, THIS_MODULE, 0, &card); + if (err < 0) + return err; + + uac2->card = card; + + /* + * Create first PCM device + * Create a substream only for non-zero channel streams + */ + err = snd_pcm_new(uac2->card, "UAC2 PCM", 0, + p_chmask ? 1 : 0, c_chmask ? 1 : 0, &pcm); + if (err < 0) + goto snd_fail; + + strcpy(pcm->name, "UAC2 PCM"); + pcm->private_data = uac2; + + uac2->pcm = pcm; + + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac2_pcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac2_pcm_ops); + + strcpy(card->driver, "UAC2_Gadget"); + strcpy(card->shortname, "UAC2_Gadget"); + sprintf(card->longname, "UAC2_Gadget %i", pdev->id); + + snd_card_set_dev(card, &pdev->dev); + + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, + snd_dma_continuous_data(GFP_KERNEL), 0, BUFF_SIZE_MAX); + + err = snd_card_register(card); + if (!err) { + platform_set_drvdata(pdev, card); + return 0; + } + +snd_fail: + snd_card_free(card); + + uac2->pcm = NULL; + uac2->card = NULL; + + return err; +} + +static int __devexit snd_uac2_remove(struct platform_device *pdev) +{ + struct snd_card *card = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + + if (card) + return snd_card_free(card); + + return 0; +} + +static int alsa_uac2_init(struct audio_dev *agdev) +{ + struct snd_uac2_chip *uac2 = &agdev->uac2; + int err; + + uac2->pdrv.probe = snd_uac2_probe; + uac2->pdrv.remove = snd_uac2_remove; + uac2->pdrv.driver.name = uac2_name; + + uac2->pdev.id = 0; + uac2->pdev.name = uac2_name; + + /* Register snd_uac2 driver */ + err = platform_driver_register(&uac2->pdrv); + if (err) + return err; + + /* Register snd_uac2 device */ + err = platform_device_register(&uac2->pdev); + if (err) + platform_driver_unregister(&uac2->pdrv); + + return err; +} + +static void alsa_uac2_exit(struct audio_dev *agdev) +{ + struct snd_uac2_chip *uac2 = &agdev->uac2; + + platform_driver_unregister(&uac2->pdrv); + platform_device_unregister(&uac2->pdev); +} + + +/* --------- USB Function Interface ------------- */ + +enum { + STR_ASSOC, + STR_IF_CTRL, + STR_CLKSRC_IN, + STR_CLKSRC_OUT, + STR_USB_IT, + STR_IO_IT, + STR_USB_OT, + STR_IO_OT, + STR_AS_OUT_ALT0, + STR_AS_OUT_ALT1, + STR_AS_IN_ALT0, + STR_AS_IN_ALT1, +}; + +static const char ifassoc[] = "Source/Sink"; +static const char ifctrl[] = "Topology Control"; +static char clksrc_in[8]; +static char clksrc_out[8]; +static const char usb_it[] = "USBH Out"; +static const char io_it[] = "USBD Out"; +static const char usb_ot[] = "USBH In"; +static const char io_ot[] = "USBD In"; +static const char out_alt0[] = "Playback Inactive"; +static const char out_alt1[] = "Playback Active"; +static const char in_alt0[] = "Capture Inactive"; +static const char in_alt1[] = "Capture Active"; + +static struct usb_string strings_fn[] = { + [STR_ASSOC].s = ifassoc, + [STR_IF_CTRL].s = ifctrl, + [STR_CLKSRC_IN].s = clksrc_in, + [STR_CLKSRC_OUT].s = clksrc_out, + [STR_USB_IT].s = usb_it, + [STR_IO_IT].s = io_it, + [STR_USB_OT].s = usb_ot, + [STR_IO_OT].s = io_ot, + [STR_AS_OUT_ALT0].s = out_alt0, + [STR_AS_OUT_ALT1].s = out_alt1, + [STR_AS_IN_ALT0].s = in_alt0, + [STR_AS_IN_ALT1].s = in_alt1, + { }, +}; + +static struct usb_gadget_strings str_fn = { + .language = 0x0409, /* en-us */ + .strings = strings_fn, +}; + +static struct usb_gadget_strings *fn_strings[] = { + &str_fn, + NULL, +}; + +static struct usb_qualifier_descriptor devqual_desc = { + .bLength = sizeof devqual_desc, + .bDescriptorType = USB_DT_DEVICE_QUALIFIER, + + .bcdUSB = cpu_to_le16(0x200), + .bDeviceClass = USB_CLASS_MISC, + .bDeviceSubClass = 0x02, + .bDeviceProtocol = 0x01, + .bNumConfigurations = 1, + .bRESERVED = 0, +}; + +static struct usb_interface_assoc_descriptor iad_desc = { + .bLength = sizeof iad_desc, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + + .bFirstInterface = 0, + .bInterfaceCount = 3, + .bFunctionClass = USB_CLASS_AUDIO, + .bFunctionSubClass = UAC2_FUNCTION_SUBCLASS_UNDEFINED, + .bFunctionProtocol = UAC_VERSION_2, +}; + +/* Audio Control Interface */ +static struct usb_interface_descriptor std_ac_if_desc = { + .bLength = sizeof std_ac_if_desc, + .bDescriptorType = USB_DT_INTERFACE, + + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, + .bInterfaceProtocol = UAC_VERSION_2, +}; + +/* Clock source for IN traffic */ +struct uac_clock_source_descriptor in_clk_src_desc = { + .bLength = sizeof in_clk_src_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + + .bDescriptorSubtype = UAC2_CLOCK_SOURCE, + .bClockID = USB_IN_CLK_ID, + .bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED, + .bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL), + .bAssocTerminal = 0, +}; + +/* Clock source for OUT traffic */ +struct uac_clock_source_descriptor out_clk_src_desc = { + .bLength = sizeof out_clk_src_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + + .bDescriptorSubtype = UAC2_CLOCK_SOURCE, + .bClockID = USB_OUT_CLK_ID, + .bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED, + .bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL), + .bAssocTerminal = 0, +}; + +/* Input Terminal for USB_OUT */ +struct uac2_input_terminal_descriptor usb_out_it_desc = { + .bLength = sizeof usb_out_it_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + + .bDescriptorSubtype = UAC_INPUT_TERMINAL, + .bTerminalID = USB_OUT_IT_ID, + .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING), + .bAssocTerminal = 0, + .bCSourceID = USB_OUT_CLK_ID, + .iChannelNames = 0, + .bmControls = (CONTROL_RDWR << COPY_CTRL), +}; + +/* Input Terminal for I/O-In */ +struct uac2_input_terminal_descriptor io_in_it_desc = { + .bLength = sizeof io_in_it_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + + .bDescriptorSubtype = UAC_INPUT_TERMINAL, + .bTerminalID = IO_IN_IT_ID, + .wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_UNDEFINED), + .bAssocTerminal = 0, + .bCSourceID = USB_IN_CLK_ID, + .iChannelNames = 0, + .bmControls = (CONTROL_RDWR << COPY_CTRL), +}; + +/* Ouput Terminal for USB_IN */ +struct uac2_output_terminal_descriptor usb_in_ot_desc = { + .bLength = sizeof usb_in_ot_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + + .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, + .bTerminalID = USB_IN_OT_ID, + .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING), + .bAssocTerminal = 0, + .bSourceID = IO_IN_IT_ID, + .bCSourceID = USB_IN_CLK_ID, + .bmControls = (CONTROL_RDWR << COPY_CTRL), +}; + +/* Ouput Terminal for I/O-Out */ +struct uac2_output_terminal_descriptor io_out_ot_desc = { + .bLength = sizeof io_out_ot_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + + .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, + .bTerminalID = IO_OUT_OT_ID, + .wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_UNDEFINED), + .bAssocTerminal = 0, + .bSourceID = USB_OUT_IT_ID, + .bCSourceID = USB_OUT_CLK_ID, + .bmControls = (CONTROL_RDWR << COPY_CTRL), +}; + +struct uac2_ac_header_descriptor ac_hdr_desc = { + .bLength = sizeof ac_hdr_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + + .bDescriptorSubtype = UAC_MS_HEADER, + .bcdADC = cpu_to_le16(0x200), + .bCategory = UAC2_FUNCTION_IO_BOX, + .wTotalLength = sizeof in_clk_src_desc + sizeof out_clk_src_desc + + sizeof usb_out_it_desc + sizeof io_in_it_desc + + sizeof usb_in_ot_desc + sizeof io_out_ot_desc, + .bmControls = 0, +}; + +/* Audio Streaming OUT Interface - Alt0 */ +static struct usb_interface_descriptor std_as_out_if0_desc = { + .bLength = sizeof std_as_out_if0_desc, + .bDescriptorType = USB_DT_INTERFACE, + + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = UAC_VERSION_2, +}; + +/* Audio Streaming OUT Interface - Alt1 */ +static struct usb_interface_descriptor std_as_out_if1_desc = { + .bLength = sizeof std_as_out_if1_desc, + .bDescriptorType = USB_DT_INTERFACE, + + .bAlternateSetting = 1, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = UAC_VERSION_2, +}; + +/* Audio Stream OUT Intface Desc */ +struct uac2_as_header_descriptor as_out_hdr_desc = { + .bLength = sizeof as_out_hdr_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + + .bDescriptorSubtype = UAC_AS_GENERAL, + .bTerminalLink = USB_OUT_IT_ID, + .bmControls = 0, + .bFormatType = UAC_FORMAT_TYPE_I, + .bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM), + .iChannelNames = 0, +}; + +/* Audio USB_OUT Format */ +struct uac2_format_type_i_descriptor as_out_fmt1_desc = { + .bLength = sizeof as_out_fmt1_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubtype = UAC_FORMAT_TYPE, + .bFormatType = UAC_FORMAT_TYPE_I, +}; + +/* STD AS ISO OUT Endpoint */ +struct usb_endpoint_descriptor fs_epout_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, + .bInterval = 1, +}; + +struct usb_endpoint_descriptor hs_epout_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, + .bInterval = 4, +}; + +/* CS AS ISO OUT Endpoint */ +static struct uac2_iso_endpoint_descriptor as_iso_out_desc = { + .bLength = sizeof as_iso_out_desc, + .bDescriptorType = USB_DT_CS_ENDPOINT, + + .bDescriptorSubtype = UAC_EP_GENERAL, + .bmAttributes = 0, + .bmControls = 0, + .bLockDelayUnits = 0, + .wLockDelay = 0, +}; + +/* Audio Streaming IN Interface - Alt0 */ +static struct usb_interface_descriptor std_as_in_if0_desc = { + .bLength = sizeof std_as_in_if0_desc, + .bDescriptorType = USB_DT_INTERFACE, + + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = UAC_VERSION_2, +}; + +/* Audio Streaming IN Interface - Alt1 */ +static struct usb_interface_descriptor std_as_in_if1_desc = { + .bLength = sizeof std_as_in_if1_desc, + .bDescriptorType = USB_DT_INTERFACE, + + .bAlternateSetting = 1, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = UAC_VERSION_2, +}; + +/* Audio Stream IN Intface Desc */ +struct uac2_as_header_descriptor as_in_hdr_desc = { + .bLength = sizeof as_in_hdr_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + + .bDescriptorSubtype = UAC_AS_GENERAL, + .bTerminalLink = USB_IN_OT_ID, + .bmControls = 0, + .bFormatType = UAC_FORMAT_TYPE_I, + .bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM), + .iChannelNames = 0, +}; + +/* Audio USB_IN Format */ +struct uac2_format_type_i_descriptor as_in_fmt1_desc = { + .bLength = sizeof as_in_fmt1_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubtype = UAC_FORMAT_TYPE, + .bFormatType = UAC_FORMAT_TYPE_I, +}; + +/* STD AS ISO IN Endpoint */ +struct usb_endpoint_descriptor fs_epin_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, + .bInterval = 1, +}; + +struct usb_endpoint_descriptor hs_epin_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, + .bInterval = 4, +}; + +/* CS AS ISO IN Endpoint */ +static struct uac2_iso_endpoint_descriptor as_iso_in_desc = { + .bLength = sizeof as_iso_in_desc, + .bDescriptorType = USB_DT_CS_ENDPOINT, + + .bDescriptorSubtype = UAC_EP_GENERAL, + .bmAttributes = 0, + .bmControls = 0, + .bLockDelayUnits = 0, + .wLockDelay = 0, +}; + +static struct usb_descriptor_header *fs_audio_desc[] = { + (struct usb_descriptor_header *)&iad_desc, + (struct usb_descriptor_header *)&std_ac_if_desc, + + (struct usb_descriptor_header *)&ac_hdr_desc, + (struct usb_descriptor_header *)&in_clk_src_desc, + (struct usb_descriptor_header *)&out_clk_src_desc, + (struct usb_descriptor_header *)&usb_out_it_desc, + (struct usb_descriptor_header *)&io_in_it_desc, + (struct usb_descriptor_header *)&usb_in_ot_desc, + (struct usb_descriptor_header *)&io_out_ot_desc, + + (struct usb_descriptor_header *)&std_as_out_if0_desc, + (struct usb_descriptor_header *)&std_as_out_if1_desc, + + (struct usb_descriptor_header *)&as_out_hdr_desc, + (struct usb_descriptor_header *)&as_out_fmt1_desc, + (struct usb_descriptor_header *)&fs_epout_desc, + (struct usb_descriptor_header *)&as_iso_out_desc, + + (struct usb_descriptor_header *)&std_as_in_if0_desc, + (struct usb_descriptor_header *)&std_as_in_if1_desc, + + (struct usb_descriptor_header *)&as_in_hdr_desc, + (struct usb_descriptor_header *)&as_in_fmt1_desc, + (struct usb_descriptor_header *)&fs_epin_desc, + (struct usb_descriptor_header *)&as_iso_in_desc, + NULL, +}; + +static struct usb_descriptor_header *hs_audio_desc[] = { + (struct usb_descriptor_header *)&iad_desc, + (struct usb_descriptor_header *)&std_ac_if_desc, + + (struct usb_descriptor_header *)&ac_hdr_desc, + (struct usb_descriptor_header *)&in_clk_src_desc, + (struct usb_descriptor_header *)&out_clk_src_desc, + (struct usb_descriptor_header *)&usb_out_it_desc, + (struct usb_descriptor_header *)&io_in_it_desc, + (struct usb_descriptor_header *)&usb_in_ot_desc, + (struct usb_descriptor_header *)&io_out_ot_desc, + + (struct usb_descriptor_header *)&std_as_out_if0_desc, + (struct usb_descriptor_header *)&std_as_out_if1_desc, + + (struct usb_descriptor_header *)&as_out_hdr_desc, + (struct usb_descriptor_header *)&as_out_fmt1_desc, + (struct usb_descriptor_header *)&hs_epout_desc, + (struct usb_descriptor_header *)&as_iso_out_desc, + + (struct usb_descriptor_header *)&std_as_in_if0_desc, + (struct usb_descriptor_header *)&std_as_in_if1_desc, + + (struct usb_descriptor_header *)&as_in_hdr_desc, + (struct usb_descriptor_header *)&as_in_fmt1_desc, + (struct usb_descriptor_header *)&hs_epin_desc, + (struct usb_descriptor_header *)&as_iso_in_desc, + NULL, +}; + +struct cntrl_cur_lay3 { + __u32 dCUR; +}; + +struct cntrl_range_lay3 { + __u16 wNumSubRanges; + __u32 dMIN; + __u32 dMAX; + __u32 dRES; +} __packed; + +static inline void +free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep) +{ + struct snd_uac2_chip *uac2 = prm_to_uac2(prm); + int i; + + prm->ep_enabled = false; + + for (i = 0; i < USB_XFERS; i++) { + if (prm->ureq[i].req) { + usb_ep_dequeue(ep, prm->ureq[i].req); + usb_ep_free_request(ep, prm->ureq[i].req); + prm->ureq[i].req = NULL; + } + } + + if (usb_ep_disable(ep)) + dev_err(&uac2->pdev.dev, + "%s:%d Error!\n", __func__, __LINE__); +} + +static int __init +afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) +{ + struct audio_dev *agdev = func_to_agdev(fn); + struct snd_uac2_chip *uac2 = &agdev->uac2; + struct usb_composite_dev *cdev = cfg->cdev; + struct usb_gadget *gadget = cdev->gadget; + struct uac2_rtd_params *prm; + int ret; + + ret = usb_interface_id(cfg, fn); + if (ret < 0) { + dev_err(&uac2->pdev.dev, + "%s:%d Error!\n", __func__, __LINE__); + return ret; + } + std_ac_if_desc.bInterfaceNumber = ret; + ALT_SET(agdev->ac_alt, 0); + INTF_SET(agdev->ac_alt, ret); + + ret = usb_interface_id(cfg, fn); + if (ret < 0) { + dev_err(&uac2->pdev.dev, + "%s:%d Error!\n", __func__, __LINE__); + return ret; + } + std_as_out_if0_desc.bInterfaceNumber = ret; + std_as_out_if1_desc.bInterfaceNumber = ret; + ALT_SET(agdev->as_out_alt, 0); + INTF_SET(agdev->as_out_alt, ret); + + ret = usb_interface_id(cfg, fn); + if (ret < 0) { + dev_err(&uac2->pdev.dev, + "%s:%d Error!\n", __func__, __LINE__); + return ret; + } + std_as_in_if0_desc.bInterfaceNumber = ret; + std_as_in_if1_desc.bInterfaceNumber = ret; + ALT_SET(agdev->as_in_alt, 0); + INTF_SET(agdev->as_in_alt, ret); + + agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc); + if (!agdev->out_ep) + dev_err(&uac2->pdev.dev, + "%s:%d Error!\n", __func__, __LINE__); + agdev->out_ep->driver_data = agdev; + + agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc); + if (!agdev->in_ep) + dev_err(&uac2->pdev.dev, + "%s:%d Error!\n", __func__, __LINE__); + agdev->in_ep->driver_data = agdev; + + hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; + hs_epout_desc.wMaxPacketSize = fs_epout_desc.wMaxPacketSize; + hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; + hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize; + + fn->descriptors = usb_copy_descriptors(fs_audio_desc); + if (gadget_is_dualspeed(gadget)) + fn->hs_descriptors = usb_copy_descriptors(hs_audio_desc); + + prm = &agdev->uac2.c_prm; + prm->max_psize = hs_epout_desc.wMaxPacketSize; + prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); + if (!prm->rbuf) { + prm->max_psize = 0; + dev_err(&uac2->pdev.dev, + "%s:%d Error!\n", __func__, __LINE__); + } + + prm = &agdev->uac2.p_prm; + prm->max_psize = hs_epin_desc.wMaxPacketSize; + prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); + if (!prm->rbuf) { + prm->max_psize = 0; + dev_err(&uac2->pdev.dev, + "%s:%d Error!\n", __func__, __LINE__); + } + + return alsa_uac2_init(agdev); +} + +static void +afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn) +{ + struct audio_dev *agdev = func_to_agdev(fn); + struct usb_composite_dev *cdev = cfg->cdev; + struct usb_gadget *gadget = cdev->gadget; + struct uac2_rtd_params *prm; + + alsa_uac2_exit(agdev); + + prm = &agdev->uac2.p_prm; + kfree(prm->rbuf); + + prm = &agdev->uac2.c_prm; + kfree(prm->rbuf); + + if (gadget_is_dualspeed(gadget)) + usb_free_descriptors(fn->hs_descriptors); + usb_free_descriptors(fn->descriptors); + + if (agdev->in_ep) + agdev->in_ep->driver_data = NULL; + if (agdev->out_ep) + agdev->out_ep->driver_data = NULL; +} + +static int +afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) +{ + struct usb_composite_dev *cdev = fn->config->cdev; + struct audio_dev *agdev = func_to_agdev(fn); + struct snd_uac2_chip *uac2 = &agdev->uac2; + struct usb_gadget *gadget = cdev->gadget; + struct usb_request *req; + struct usb_ep *ep; + struct uac2_rtd_params *prm; + int i; + + /* No i/f has more than 2 alt settings */ + if (alt > 1) { + dev_err(&uac2->pdev.dev, + "%s:%d Error!\n", __func__, __LINE__); + return -EINVAL; + } + + if (intf == INTF_GET(agdev->ac_alt)) { + /* Control I/f has only 1 AltSetting - 0 */ + if (alt) { + dev_err(&uac2->pdev.dev, + "%s:%d Error!\n", __func__, __LINE__); + return -EINVAL; + } + return 0; + } + + if (intf == INTF_GET(agdev->as_out_alt)) { + ep = agdev->out_ep; + prm = &uac2->c_prm; + config_ep_by_speed(gadget, fn, ep); + ALT_SET(agdev->as_out_alt, alt); + } else if (intf == INTF_GET(agdev->as_in_alt)) { + ep = agdev->in_ep; + prm = &uac2->p_prm; + config_ep_by_speed(gadget, fn, ep); + ALT_SET(agdev->as_in_alt, alt); + } else { + dev_err(&uac2->pdev.dev, + "%s:%d Error!\n", __func__, __LINE__); + return -EINVAL; + } + + if (alt == 0) { + free_ep(prm, ep); + return 0; + } + + prm->ep_enabled = true; + usb_ep_enable(ep); + + for (i = 0; i < USB_XFERS; i++) { + if (prm->ureq[i].req) { + if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC)) + dev_err(&uac2->pdev.dev, "%d Error!\n", + __LINE__); + continue; + } + + req = usb_ep_alloc_request(ep, GFP_ATOMIC); + if (req == NULL) { + dev_err(&uac2->pdev.dev, + "%s:%d Error!\n", __func__, __LINE__); + return -EINVAL; + } + + prm->ureq[i].req = req; + prm->ureq[i].pp = prm; + + req->zero = 0; + req->dma = DMA_ADDR_INVALID; + req->context = &prm->ureq[i]; + req->length = prm->max_psize; + req->complete = agdev_iso_complete; + req->buf = prm->rbuf + i * req->length; + + if (usb_ep_queue(ep, req, GFP_ATOMIC)) + dev_err(&uac2->pdev.dev, "%d Error!\n", __LINE__); + } + + return 0; +} + +static int +afunc_get_alt(struct usb_function *fn, unsigned intf) +{ + struct audio_dev *agdev = func_to_agdev(fn); + struct snd_uac2_chip *uac2 = &agdev->uac2; + + if (intf == INTF_GET(agdev->ac_alt)) + return ALT_GET(agdev->ac_alt); + else if (intf == INTF_GET(agdev->as_out_alt)) + return ALT_GET(agdev->as_out_alt); + else if (intf == INTF_GET(agdev->as_in_alt)) + return ALT_GET(agdev->as_in_alt); + else + dev_err(&uac2->pdev.dev, + "%s:%d Invalid Interface %d!\n", + __func__, __LINE__, intf); + + return -EINVAL; +} + +static void +afunc_disable(struct usb_function *fn) +{ + struct audio_dev *agdev = func_to_agdev(fn); + struct snd_uac2_chip *uac2 = &agdev->uac2; + + free_ep(&uac2->p_prm, agdev->in_ep); + ALT_SET(agdev->as_in_alt, 0); + + free_ep(&uac2->c_prm, agdev->out_ep); + ALT_SET(agdev->as_out_alt, 0); +} + +static int +in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr) +{ + struct usb_request *req = fn->config->cdev->req; + struct audio_dev *agdev = func_to_agdev(fn); + struct snd_uac2_chip *uac2 = &agdev->uac2; + u16 w_length = le16_to_cpu(cr->wLength); + u16 w_index = le16_to_cpu(cr->wIndex); + u16 w_value = le16_to_cpu(cr->wValue); + u8 entity_id = (w_index >> 8) & 0xff; + u8 control_selector = w_value >> 8; + int value = -EOPNOTSUPP; + + if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { + struct cntrl_cur_lay3 c; + + if (entity_id == USB_IN_CLK_ID) + c.dCUR = p_srate; + else if (entity_id == USB_OUT_CLK_ID) + c.dCUR = c_srate; + + value = min_t(unsigned, w_length, sizeof c); + memcpy(req->buf, &c, value); + } else if (control_selector == UAC2_CS_CONTROL_CLOCK_VALID) { + *(u8 *)req->buf = 1; + value = min_t(unsigned, w_length, 1); + } else { + dev_err(&uac2->pdev.dev, + "%s:%d control_selector=%d TODO!\n", + __func__, __LINE__, control_selector); + } + + return value; +} + +static int +in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr) +{ + struct usb_request *req = fn->config->cdev->req; + struct audio_dev *agdev = func_to_agdev(fn); + struct snd_uac2_chip *uac2 = &agdev->uac2; + u16 w_length = le16_to_cpu(cr->wLength); + u16 w_index = le16_to_cpu(cr->wIndex); + u16 w_value = le16_to_cpu(cr->wValue); + u8 entity_id = (w_index >> 8) & 0xff; + u8 control_selector = w_value >> 8; + struct cntrl_range_lay3 r; + int value = -EOPNOTSUPP; + + if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { + if (entity_id == USB_IN_CLK_ID) + r.dMIN = p_srate; + else if (entity_id == USB_OUT_CLK_ID) + r.dMIN = c_srate; + else + return -EOPNOTSUPP; + + r.dMAX = r.dMIN; + r.dRES = 0; + r.wNumSubRanges = 1; + + value = min_t(unsigned, w_length, sizeof r); + memcpy(req->buf, &r, value); + } else { + dev_err(&uac2->pdev.dev, + "%s:%d control_selector=%d TODO!\n", + __func__, __LINE__, control_selector); + } + + return value; +} + +static int +ac_rq_in(struct usb_function *fn, const struct usb_ctrlrequest *cr) +{ + if (cr->bRequest == UAC2_CS_CUR) + return in_rq_cur(fn, cr); + else if (cr->bRequest == UAC2_CS_RANGE) + return in_rq_range(fn, cr); + else + return -EOPNOTSUPP; +} + +static int +out_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr) +{ + u16 w_length = le16_to_cpu(cr->wLength); + u16 w_value = le16_to_cpu(cr->wValue); + u8 control_selector = w_value >> 8; + + if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) + return w_length; + + return -EOPNOTSUPP; +} + +static int +setup_rq_inf(struct usb_function *fn, const struct usb_ctrlrequest *cr) +{ + struct audio_dev *agdev = func_to_agdev(fn); + struct snd_uac2_chip *uac2 = &agdev->uac2; + u16 w_index = le16_to_cpu(cr->wIndex); + u8 intf = w_index & 0xff; + + if (intf != INTF_GET(agdev->ac_alt)) { + dev_err(&uac2->pdev.dev, + "%s:%d Error!\n", __func__, __LINE__); + return -EOPNOTSUPP; + } + + if (cr->bRequestType & USB_DIR_IN) + return ac_rq_in(fn, cr); + else if (cr->bRequest == UAC2_CS_CUR) + return out_rq_cur(fn, cr); + + return -EOPNOTSUPP; +} + +static int +afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr) +{ + struct usb_composite_dev *cdev = fn->config->cdev; + struct audio_dev *agdev = func_to_agdev(fn); + struct snd_uac2_chip *uac2 = &agdev->uac2; + struct usb_request *req = cdev->req; + u16 w_length = le16_to_cpu(cr->wLength); + int value = -EOPNOTSUPP; + + /* Only Class specific requests are supposed to reach here */ + if ((cr->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) + return -EOPNOTSUPP; + + if ((cr->bRequestType & USB_RECIP_MASK) == USB_RECIP_INTERFACE) + value = setup_rq_inf(fn, cr); + else + dev_err(&uac2->pdev.dev, "%s:%d Error!\n", __func__, __LINE__); + + if (value >= 0) { + req->length = value; + req->zero = value < w_length; + value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); + if (value < 0) { + dev_err(&uac2->pdev.dev, + "%s:%d Error!\n", __func__, __LINE__); + req->status = 0; + } + } + + return value; +} + +static int audio_bind_config(struct usb_configuration *cfg) +{ + int id, res; + + agdev_g = kzalloc(sizeof *agdev_g, GFP_KERNEL); + if (agdev_g == NULL) { + printk(KERN_ERR "Unable to allocate audio gadget\n"); + return -ENOMEM; + } + + id = usb_string_id(cfg->cdev); + if (id < 0) + return id; + + strings_fn[STR_ASSOC].id = id; + iad_desc.iFunction = id, + + id = usb_string_id(cfg->cdev); + if (id < 0) + return id; + + strings_fn[STR_IF_CTRL].id = id; + std_ac_if_desc.iInterface = id, + + id = usb_string_id(cfg->cdev); + if (id < 0) + return id; + + strings_fn[STR_CLKSRC_IN].id = id; + in_clk_src_desc.iClockSource = id, + + id = usb_string_id(cfg->cdev); + if (id < 0) + return id; + + strings_fn[STR_CLKSRC_OUT].id = id; + out_clk_src_desc.iClockSource = id, + + id = usb_string_id(cfg->cdev); + if (id < 0) + return id; + + strings_fn[STR_USB_IT].id = id; + usb_out_it_desc.iTerminal = id, + + id = usb_string_id(cfg->cdev); + if (id < 0) + return id; + + strings_fn[STR_IO_IT].id = id; + io_in_it_desc.iTerminal = id; + + id = usb_string_id(cfg->cdev); + if (id < 0) + return id; + + strings_fn[STR_USB_OT].id = id; + usb_in_ot_desc.iTerminal = id; + + id = usb_string_id(cfg->cdev); + if (id < 0) + return id; + + strings_fn[STR_IO_OT].id = id; + io_out_ot_desc.iTerminal = id; + + id = usb_string_id(cfg->cdev); + if (id < 0) + return id; + + strings_fn[STR_AS_OUT_ALT0].id = id; + std_as_out_if0_desc.iInterface = id; + + id = usb_string_id(cfg->cdev); + if (id < 0) + return id; + + strings_fn[STR_AS_OUT_ALT1].id = id; + std_as_out_if1_desc.iInterface = id; + + id = usb_string_id(cfg->cdev); + if (id < 0) + return id; + + strings_fn[STR_AS_IN_ALT0].id = id; + std_as_in_if0_desc.iInterface = id; + + id = usb_string_id(cfg->cdev); + if (id < 0) + return id; + + strings_fn[STR_AS_IN_ALT1].id = id; + std_as_in_if1_desc.iInterface = id; + + agdev_g->func.name = "uac2_func"; + agdev_g->func.strings = fn_strings; + agdev_g->func.bind = afunc_bind; + agdev_g->func.unbind = afunc_unbind; + agdev_g->func.set_alt = afunc_set_alt; + agdev_g->func.get_alt = afunc_get_alt; + agdev_g->func.disable = afunc_disable; + agdev_g->func.setup = afunc_setup; + + /* Initialize the configurable parameters */ + usb_out_it_desc.bNrChannels = num_channels(c_chmask); + usb_out_it_desc.bmChannelConfig = cpu_to_le32(c_chmask); + io_in_it_desc.bNrChannels = num_channels(p_chmask); + io_in_it_desc.bmChannelConfig = cpu_to_le32(p_chmask); + as_out_hdr_desc.bNrChannels = num_channels(c_chmask); + as_out_hdr_desc.bmChannelConfig = cpu_to_le32(c_chmask); + as_in_hdr_desc.bNrChannels = num_channels(p_chmask); + as_in_hdr_desc.bmChannelConfig = cpu_to_le32(p_chmask); + as_out_fmt1_desc.bSubslotSize = c_ssize; + as_out_fmt1_desc.bBitResolution = c_ssize * 8; + as_in_fmt1_desc.bSubslotSize = p_ssize; + as_in_fmt1_desc.bBitResolution = p_ssize * 8; + + snprintf(clksrc_in, sizeof(clksrc_in), "%uHz", p_srate); + snprintf(clksrc_out, sizeof(clksrc_out), "%uHz", c_srate); + + res = usb_add_function(cfg, &agdev_g->func); + if (res < 0) + kfree(agdev_g); + + return res; +} + +static void +uac2_unbind_config(struct usb_configuration *cfg) +{ + kfree(agdev_g); + agdev_g = NULL; +} From 5407a3c3d942e75d4d123d213fd692bce5acc961 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 15 Feb 2012 09:34:26 +0200 Subject: [PATCH 115/269] usb: host: ehci: allow ehci_* symbols to be unused not all platforms will use all of those ehci_* symbols on their hc_driver structure. Sometimes we might need to provide a modified version of a certain method or not provide it at all, as is the case with OMAPs which don't support port handoff feature. Whenever we compile a kernel for an OMAP board with EHCI enabled, we get compile warnings: drivers/usb/host/ehci-hub.c:1079: warning: 'ehci_relinquish_port' \ defined but not used drivers/usb/host/ehci-hub.c:1088: warning: 'ehci_port_handed_over' \ defined but not used In order to cleanup those warnings, we're adding __maybe_unused annotation to those functions. Signed-off-by: Felipe Balbi Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 77bbb2357e47..01011dd0cb5d 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -107,7 +107,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) ehci->owned_ports = 0; } -static int ehci_port_change(struct ehci_hcd *ehci) +static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci) { int i = HCS_N_PORTS(ehci->hcs_params); @@ -1076,7 +1076,8 @@ error_exit: return retval; } -static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) +static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd, + int portnum) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -1085,7 +1086,8 @@ static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) set_owner(ehci, --portnum, PORT_OWNER); } -static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum) +static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd, + int portnum) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); u32 __iomem *reg; From a003c187cac7a88101fe7f254bde6582865f7908 Mon Sep 17 00:00:00 2001 From: Danny Kukawka Date: Wed, 15 Feb 2012 18:56:07 +0100 Subject: [PATCH 116/269] usb: at91_udc: linux/prefetch.h included twice drivers/usb/gadget/at91_udc.c included 'linux/prefetch.h' twice, remove the duplicate. Signed-off-by: Danny Kukawka Signed-off-by: Felipe Balbi --- drivers/usb/gadget/at91_udc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 143a7256b598..d8dee225bf8e 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include From f9c56cdd3905c96c600456203637bd7ec8ec6383 Mon Sep 17 00:00:00 2001 From: Ido Shayevitz Date: Wed, 8 Feb 2012 13:56:48 +0200 Subject: [PATCH 117/269] usb: gadget: Clear usb_endpoint_descriptor inside the struct usb_ep on disable This fix a bug in f_serial, which expect the ep->desc to be NULL after disabling an endpoint. Cc: stable@vger.kernel.org Signed-off-by: Ido Shayevitz Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 1 + drivers/usb/gadget/amd5536udc.c | 1 + drivers/usb/gadget/at91_udc.c | 1 + drivers/usb/gadget/atmel_usba_udc.c | 1 + drivers/usb/gadget/ci13xxx_udc.c | 1 + drivers/usb/gadget/fsl_qe_udc.c | 1 + drivers/usb/gadget/fsl_udc_core.c | 1 + drivers/usb/gadget/goku_udc.c | 1 + drivers/usb/gadget/langwell_udc.c | 1 + drivers/usb/gadget/mv_udc_core.c | 1 + drivers/usb/gadget/omap_udc.c | 1 + drivers/usb/gadget/pch_udc.c | 1 + drivers/usb/gadget/pxa25x_udc.c | 2 ++ drivers/usb/gadget/s3c-hsudc.c | 2 ++ drivers/usb/gadget/s3c2410_udc.c | 2 ++ 15 files changed, 18 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index a696bde53222..a1a04d00a9e4 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -440,6 +440,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dep->stream_capable = false; dep->desc = NULL; + dep->endpoint.desc = NULL; dep->comp_desc = NULL; dep->type = 0; dep->flags = 0; diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index c16ff55a74e8..18883bd0f162 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -445,6 +445,7 @@ static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep) VDBG(ep->dev, "ep-%d reset\n", ep->num); ep->desc = NULL; + ep->ep.desc = NULL; ep->ep.ops = &udc_ep_ops; INIT_LIST_HEAD(&ep->queue); diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index d8dee225bf8e..15a8cdb2ded5 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -557,6 +557,7 @@ static int at91_ep_disable (struct usb_ep * _ep) /* restore the endpoint's pristine config */ ep->desc = NULL; + ep->ep.desc = NULL; ep->ep.maxpacket = ep->maxpacket; /* reset fifos and endpoint */ diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index e2fb6d583bd9..5e10f651ad63 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -659,6 +659,7 @@ static int usba_ep_disable(struct usb_ep *_ep) return -EINVAL; } ep->desc = NULL; + ep->ep.desc = NULL; list_splice_init(&ep->queue, &req_list); if (ep->can_dma) { diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 27e313718422..9e892890e08a 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -2181,6 +2181,7 @@ static int ep_disable(struct usb_ep *ep) } while (mEp->dir != direction); mEp->desc = NULL; + mEp->ep.desc = NULL; spin_unlock_irqrestore(mEp->lock, flags); return retval; diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index b95697c03d07..877a2c46672b 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -1638,6 +1638,7 @@ static int qe_ep_disable(struct usb_ep *_ep) /* Nuke all pending requests (does flush) */ nuke(ep, -ESHUTDOWN); ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 1; ep->tx_req = NULL; qe_ep_reset(udc, ep->epnum); diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index d7ea6c076ce9..b54357350422 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -659,6 +659,7 @@ static int fsl_ep_disable(struct usb_ep *_ep) nuke(ep, -ESHUTDOWN); ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 1; spin_unlock_irqrestore(&udc->lock, flags); diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 5af70fcce139..59777490a19a 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -235,6 +235,7 @@ static void ep_reset(struct goku_udc_regs __iomem *regs, struct goku_ep *ep) ep->ep.maxpacket = MAX_FIFO_SIZE; ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 1; ep->irqs = 0; ep->dma = 0; diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index fa0fcc11263f..a2bb5e476f54 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -492,6 +492,7 @@ static int langwell_ep_disable(struct usb_ep *_ep) nuke(ep, -ESHUTDOWN); ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 1; spin_unlock_irqrestore(&dev->lock, flags); diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 8dd398b99e2f..ec6009fc050f 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -608,6 +608,7 @@ static int mv_ep_disable(struct usb_ep *_ep) nuke(ep, -ESHUTDOWN); ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 1; spin_unlock_irqrestore(&udc->lock, flags); diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 576cd8578b45..7d0835e4bb92 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -251,6 +251,7 @@ static int omap_ep_disable(struct usb_ep *_ep) spin_lock_irqsave(&ep->udc->lock, flags); ep->desc = NULL; + ep->ep.desc = NULL; nuke (ep, -ESHUTDOWN); ep->ep.maxpacket = ep->maxpacket; ep->has_dma = 0; diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index a992084d3890..350dbcd90681 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -1742,6 +1742,7 @@ static int pch_udc_pcd_ep_disable(struct usb_ep *usbep) pch_udc_ep_disable(ep); pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num)); ep->desc = NULL; + ep->ep.desc = NULL; INIT_LIST_HEAD(&ep->queue); spin_unlock_irqrestore(&ep->dev->lock, iflags); return 0; diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index dd470635f4f7..33adf3884275 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -283,6 +283,7 @@ static int pxa25x_ep_disable (struct usb_ep *_ep) pxa25x_ep_fifo_flush (_ep); ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 1; local_irq_restore(flags); @@ -1192,6 +1193,7 @@ static void udc_reinit(struct pxa25x_udc *dev) list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list); ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 0; INIT_LIST_HEAD (&ep->queue); ep->pio_irqs = 0; diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index 5e8729374fba..ace95f933689 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -817,6 +817,7 @@ static int s3c_hsudc_ep_disable(struct usb_ep *_ep) s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN); hsep->desc = 0; + hsep->ep.desc = NULL; hsep->stopped = 1; spin_unlock_irqrestore(&hsudc->lock, flags); @@ -1006,6 +1007,7 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc, hsep->ep.ops = &s3c_hsudc_ep_ops; hsep->fifo = hsudc->regs + S3C_BR(epnum); hsep->desc = 0; + hsep->ep.desc = NULL; hsep->stopped = 0; hsep->wedge = 0; diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 3f87cb9344bb..ab9c65e2c1d5 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1148,6 +1148,7 @@ static int s3c2410_udc_ep_disable(struct usb_ep *_ep) dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name); ep->desc = NULL; + ep->ep.desc = NULL; ep->halted = 1; s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN); @@ -1630,6 +1631,7 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev) ep->dev = dev; ep->desc = NULL; + ep->ep.desc = NULL; ep->halted = 0; INIT_LIST_HEAD (&ep->queue); } From 3b2a2e47174cd978258bbb0fdf2e2b1b5ec2144c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 20 Feb 2012 17:35:50 -0800 Subject: [PATCH 118/269] usb: renesas_usbhs: bugfix: add .release function to gpriv->gadget.dev This patch fixup below warning on device_unregister() renesas_usbhs renesas_usbhs.1: host probed renesas_usbhs renesas_usbhs.1: gadget probed renesas_usbhs renesas_usbhs.1: irq request err ------------[ cut here ]------------ WARNING: at ${LINUX}/drivers/base/core.c:1) Device 'gadget' does not have a release() function, it is broken and must be fi. Modules linked in: [] (unwind_backtrace+0x0/0xe4) from [] (warn_slowpath_commo) [] (warn_slowpath_common+0x4c/0x64) from [] (warn_slowpath_) [] (warn_slowpath_fmt+0x2c/0x3c) from [] (device_release+0x) [] (device_release+0x70/0x84) from [] (kobject_cleanup+0x58) [] (kobject_cleanup+0x58/0x6c) from [] (usbhs_mod_gadget_re) [] (usbhs_mod_gadget_remove+0x3c/0x6c) from [] (usbhs_mod_p) [] (usbhs_mod_probe+0x68/0x80) from [] (usbhs_probe+0x1cc/0) ... Cc: stable@vger.kernel.org Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/mod_gadget.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 528691d5f3e2..f37b20c82c80 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -941,6 +941,11 @@ static int usbhsg_stop(struct usbhs_priv *priv) return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED); } +static void usbhs_mod_gadget_release(struct device *pdev) +{ + /* do nothing */ +} + int usbhs_mod_gadget_probe(struct usbhs_priv *priv) { struct usbhsg_gpriv *gpriv; @@ -989,6 +994,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) */ dev_set_name(&gpriv->gadget.dev, "gadget"); gpriv->gadget.dev.parent = dev; + gpriv->gadget.dev.release = usbhs_mod_gadget_release; gpriv->gadget.name = "renesas_usbhs_udc"; gpriv->gadget.ops = &usbhsg_gadget_ops; gpriv->gadget.max_speed = USB_SPEED_HIGH; From c5cc5ed86667d4ae74fe40ee4ed893f4b46aba05 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Thu, 16 Feb 2012 09:36:25 +0800 Subject: [PATCH 119/269] usb: fsl_udc_core: Fix scheduling while atomic dump message When loading g_ether gadget, there is below message: Backtrace: [<80012248>] (dump_backtrace+0x0/0x10c) from [<803cb42c>] (dump_stack+0x18/0x1c) r7:00000000 r6:80512000 r5:8052bef8 r4:80513f30 [<803cb414>] (dump_stack+0x0/0x1c) from [<8000feb4>] (show_regs+0x44/0x50) [<8000fe70>] (show_regs+0x0/0x50) from [<8004c840>] (__schedule_bug+0x68/0x84) r5:8052bef8 r4:80513f30 [<8004c7d8>] (__schedule_bug+0x0/0x84) from [<803cd0e4>] (__schedule+0x4b0/0x528) r5:8052bef8 r4:809aad00 [<803ccc34>] (__schedule+0x0/0x528) from [<803cd214>] (_cond_resched+0x44/0x58) [<803cd1d0>] (_cond_resched+0x0/0x58) from [<800a9488>] (dma_pool_alloc+0x184/0x250) r5:9f9b4000 r4:9fb4fb80 [<800a9304>] (dma_pool_alloc+0x0/0x250) from [<802a8ad8>] (fsl_req_to_dtd+0xac/0x180) [<802a8a2c>] (fsl_req_to_dtd+0x0/0x180) from [<802a8ce4>] (fsl_ep_queue+0x138/0x274) [<802a8bac>] (fsl_ep_queue+0x0/0x274) from [<7f004328>] (composite_setup+0x2d4/0xfac [g_ether]) [<7f004054>] (composite_setup+0x0/0xfac [g_ether]) from [<802a9bb4>] (fsl_udc_irq+0x8dc/0xd38) [<802a92d8>] (fsl_udc_irq+0x0/0xd38) from [<800704f8>] (handle_irq_event_percpu+0x54/0x188) [<800704a4>] (handle_irq_event_percpu+0x0/0x188) from [<80070674>] (handle_irq_event+0x48/0x68) [<8007062c>] (handle_irq_event+0x0/0x68) from [<800738ec>] (handle_level_irq+0xb4/0x138) r5:80514f94 r4:80514f40 [<80073838>] (handle_level_irq+0x0/0x138) from [<8006ffa4>] (generic_handle_irq+0x38/0x44) r7:00000012 r6:80510b1c r5:80529860 r4:80512000 [<8006ff6c>] (generic_handle_irq+0x0/0x44) from [<8000f4c4>] (handle_IRQ+0x54/0xb4) [<8000f470>] (handle_IRQ+0x0/0xb4) from [<800085b8>] (tzic_handle_irq+0x64/0x94) r9:412fc085 r8:00000000 r7:80513f30 r6:00000001 r5:00000000 r4:00000000 [<80008554>] (tzic_handle_irq+0x0/0x94) from [<8000e680>] (__irq_svc+0x40/0x60) The reason of above dump message is calling dma_poll_alloc with can-schedule mem_flags at atomic context. To fix this problem, below changes are made: - fsl_req_to_dtd doesn't need to be protected by spin_lock_irqsave, as struct usb_request can be access at process context. Move lock to beginning of hardware visit (fsl_queue_td). - Change the memory flag which using to allocate dTD descriptor buffer, the memory flag can be from gadget layer. It is tested at i.mx51 bbg board with g_mass_storage, g_ether, g_serial. Cc: stable@vger.kernel.org Signed-off-by: Peter Chen Acked-by: Li Yang Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fsl_udc_core.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index b54357350422..8db5a666e2ab 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -769,7 +769,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) * @is_last: return flag if it is the last dTD of the request * return: pointer to the built dTD */ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, - dma_addr_t *dma, int *is_last) + dma_addr_t *dma, int *is_last, gfp_t gfp_flags) { u32 swap_temp; struct ep_td_struct *dtd; @@ -778,7 +778,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, *length = min(req->req.length - req->req.actual, (unsigned)EP_MAX_LENGTH_TRANSFER); - dtd = dma_pool_alloc(udc_controller->td_pool, GFP_KERNEL, dma); + dtd = dma_pool_alloc(udc_controller->td_pool, gfp_flags, dma); if (dtd == NULL) return dtd; @@ -828,7 +828,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, } /* Generate dtd chain for a request */ -static int fsl_req_to_dtd(struct fsl_req *req) +static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags) { unsigned count; int is_last; @@ -837,7 +837,7 @@ static int fsl_req_to_dtd(struct fsl_req *req) dma_addr_t dma; do { - dtd = fsl_build_dtd(req, &count, &dma, &is_last); + dtd = fsl_build_dtd(req, &count, &dma, &is_last, gfp_flags); if (dtd == NULL) return -ENOMEM; @@ -911,13 +911,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) req->req.actual = 0; req->dtd_count = 0; - spin_lock_irqsave(&udc->lock, flags); - /* build dtds and push them to device queue */ - if (!fsl_req_to_dtd(req)) { + if (!fsl_req_to_dtd(req, gfp_flags)) { + spin_lock_irqsave(&udc->lock, flags); fsl_queue_td(ep, req); } else { - spin_unlock_irqrestore(&udc->lock, flags); return -ENOMEM; } @@ -1296,7 +1294,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction) ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); req->mapped = 1; - if (fsl_req_to_dtd(req) == 0) + if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0) fsl_queue_td(ep, req); else return -ENOMEM; @@ -1380,7 +1378,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, req->mapped = 1; /* prime the data phase */ - if ((fsl_req_to_dtd(req) == 0)) + if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0)) fsl_queue_td(ep, req); else /* no mem */ goto stall; From 39287076e46d2c19aaceaa6f0a44168ae4d257ec Mon Sep 17 00:00:00 2001 From: Supriya Karanth Date: Fri, 17 Feb 2012 14:54:52 +0530 Subject: [PATCH 120/269] usb: musb: Reselect index reg in interrupt context musb INDEX register is getting modified/corrupted during temporary un-locking in a SMP system. Set this register with proper value after re-acquiring the lock Scenario: --------- CPU1 is handling a data transfer completion interrupt received for the CLASS1 EP CPU2 is handling a CLASS2 thread which is queuing data to musb for transfer Below is the error sequence: CPU1 | CPU2 -------------------------------------------------------------------- Data transfer completion inter- | rupt recieved. | | musb INDEX reg set to CLASS1 EP | | musb LOCK is acquired. | | | CLASS2 thread queues data. | | CLASS2 thread tries to acquire musb | LOCK but lock is already taken by | CLASS1, so CLASS2 thread is | spinning. | From Interrupt Context musb | giveback function is called | | The giveback function releases | CLASS2 thread now acquires LOCK LOCK | | ClASS1 Request's completion cal-| ClASS2 schedules the data transfer and lback is called | sets the MUSB INDEX to Class2 EP number | Interrupt handler for CLASS1 EP | tries to acquire LOCK and is | spinning | | Interrupt for Class1 EP acquires| Class2 completes the scheduling etc and the MUSB LOCK | releases the musb LOCK | Interrupt for Class1 EP schedul-| es the next data transfer | but musb INDEX register is still| set to CLASS2 EP | Since the MUSB INDEX register is set to a different endpoint, we read and modify the wrong registers. Hence data transfer will not happen properly. This results in unpredictable behavior So, the MUSB INDEX register is set to proper value again when interrupt re-acquires the lock Cc: stable@vger.kernel.org Signed-off-by: Supriya Karanth Signed-off-by: Praveena Nadahally Reviewed-by: srinidhi kasagar Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 59ab98f08e9e..957d9ca3d06d 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -574,6 +574,15 @@ void musb_g_tx(struct musb *musb, u8 epnum) if (request->actual == request->length) { musb_g_giveback(musb_ep, request, 0); + /* + * In the giveback function the MUSB lock is + * released and acquired after sometime. During + * this time period the INDEX register could get + * changed by the gadget_queue function especially + * on SMP systems. Reselect the INDEX to be sure + * we are reading/modifying the right registers + */ + musb_ep_select(mbase, epnum); req = musb_ep->desc ? next_request(musb_ep) : NULL; if (!req) { dev_dbg(musb->controller, "%s idle now\n", @@ -983,6 +992,15 @@ void musb_g_rx(struct musb *musb, u8 epnum) } #endif musb_g_giveback(musb_ep, request, 0); + /* + * In the giveback function the MUSB lock is + * released and acquired after sometime. During + * this time period the INDEX register could get + * changed by the gadget_queue function especially + * on SMP systems. Reselect the INDEX to be sure + * we are reading/modifying the right registers + */ + musb_ep_select(mbase, epnum); req = next_request(musb_ep); if (!req) From 765e0ba62613fb90f09c1b5926750df0aa56f349 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Feb 2012 14:55:59 -0500 Subject: [PATCH 121/269] usb-serial: new API for driver registration This patch (as1522) adds two new routines to the usb-serial core, for registering and unregistering serial drivers. Instead of registering the usb_driver and usb_serial_drivers separately, with error checking for each one, the drivers can all be registered and unregistered by a single function call. This reduces duplicated code. More importantly, the new core routines change the order in which the drivers are registered. Currently the usb-serial drivers are all registered first and the usb_driver is done last, which leaves a window for problems. A udev script may quickly add a new dynamic-ID for a usb-serial driver, causing the corresponding usb_driver to be probed. If the usb_driver hasn't been registered yet then an oops will occur. The new routine prevents such problems by registering the usb_driver first. To insure that it gets probed properly for already-attached serial devices, we call driver_attach() after all the usb-serial drivers have been registered. Along with adding the new routines, the patch modifies the "generic" serial driver to use them. Further patches will similarly modify all the other in-tree USB serial drivers. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 17 +++----- drivers/usb/serial/usb-serial.c | 75 +++++++++++++++++++++++++++++++++ include/linux/usb/serial.h | 9 ++++ 3 files changed, 90 insertions(+), 11 deletions(-) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 2a2fa2d0489d..664deb63807c 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -54,7 +54,6 @@ static struct usb_driver generic_driver = { .probe = generic_probe, .disconnect = usb_serial_disconnect, .id_table = generic_serial_ids, - .no_dynamic_id = 1, }; /* All of the device info needed for the Generic Serial Converter */ @@ -64,7 +63,6 @@ struct usb_serial_driver usb_serial_generic_device = { .name = "generic", }, .id_table = generic_device_ids, - .usb_driver = &generic_driver, .num_ports = 1, .disconnect = usb_serial_generic_disconnect, .release = usb_serial_generic_release, @@ -73,6 +71,10 @@ struct usb_serial_driver usb_serial_generic_device = { .resume = usb_serial_generic_resume, }; +static struct usb_serial_driver * const serial_drivers[] = { + &usb_serial_generic_device, NULL +}; + static int generic_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -97,13 +99,7 @@ int usb_serial_generic_register(int _debug) USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT; /* register our generic driver with ourselves */ - retval = usb_serial_register(&usb_serial_generic_device); - if (retval) - goto exit; - retval = usb_register(&generic_driver); - if (retval) - usb_serial_deregister(&usb_serial_generic_device); -exit: + retval = usb_serial_register_drivers(&generic_driver, serial_drivers); #endif return retval; } @@ -112,8 +108,7 @@ void usb_serial_generic_deregister(void) { #ifdef CONFIG_USB_SERIAL_GENERIC /* remove our generic driver */ - usb_deregister(&generic_driver); - usb_serial_deregister(&usb_serial_generic_device); + usb_serial_deregister_drivers(&generic_driver, serial_drivers); #endif } diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 611b206591cb..45b3658c601f 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1338,6 +1338,11 @@ static void fixup_generic(struct usb_serial_driver *device) set_to_generic_if_null(device, prepare_write_buffer); } +/* + * The next two routines are mainly for internal use. + * They are exported only for out-of-tree modules. + * New drivers should call usb_serial_{de}register_drivers() instead. + */ int usb_serial_register(struct usb_serial_driver *driver) { int retval; @@ -1386,6 +1391,76 @@ void usb_serial_deregister(struct usb_serial_driver *device) } EXPORT_SYMBOL_GPL(usb_serial_deregister); +/** + * usb_serial_register_drivers - register drivers for a usb-serial module + * @udriver: usb_driver used for matching devices/interfaces + * @serial_drivers: NULL-terminated array of pointers to drivers to be registered + * + * Registers @udriver and all the drivers in the @serial_drivers array. + * Automatically fills in the .no_dynamic_id field in @udriver and + * the .usb_driver field in each serial driver. + */ +int usb_serial_register_drivers(struct usb_driver *udriver, + struct usb_serial_driver * const serial_drivers[]) +{ + int rc; + const struct usb_device_id *saved_id_table; + struct usb_serial_driver * const *sd; + + /* + * udriver must be registered before any of the serial drivers, + * because the store_new_id() routine for the serial drivers (in + * bus.c) probes udriver. + * + * Performance hack: We don't want udriver to be probed until + * the serial drivers are registered, because the probe would + * simply fail for lack of a matching serial driver. + * Therefore save off udriver's id_table until we are all set. + */ + saved_id_table = udriver->id_table; + udriver->id_table = NULL; + + udriver->no_dynamic_id = 1; + rc = usb_register(udriver); + if (rc) + return rc; + + for (sd = serial_drivers; *sd; ++sd) { + (*sd)->usb_driver = udriver; + rc = usb_serial_register(*sd); + if (rc) + goto failed; + } + + /* Now restore udriver's id_table and look for matches */ + udriver->id_table = saved_id_table; + rc = driver_attach(&udriver->drvwrap.driver); + return 0; + + failed: + while (sd-- > serial_drivers) + usb_serial_deregister(*sd); + usb_deregister(udriver); + return rc; +} +EXPORT_SYMBOL_GPL(usb_serial_register_drivers); + +/** + * usb_serial_deregister_drivers - deregister drivers for a usb-serial module + * @udriver: usb_driver to unregister + * @serial_drivers: NULL-terminated array of pointers to drivers to be deregistered + * + * Deregisters @udriver and all the drivers in the @serial_drivers array. + */ +void usb_serial_deregister_drivers(struct usb_driver *udriver, + struct usb_serial_driver * const serial_drivers[]) +{ + for (; *serial_drivers; ++serial_drivers) + usb_serial_deregister(*serial_drivers); + usb_deregister(udriver); +} +EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers); + /* Module information */ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 10cb74d2ad1d..8c8dbf9c5b89 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -300,8 +300,17 @@ struct usb_serial_driver { #define to_usb_serial_driver(d) \ container_of(d, struct usb_serial_driver, driver) +/* + * These two routines are kept only for backward compatibility. + * Don't use them; call usb_serial_{de}register_drivers() instead. + */ extern int usb_serial_register(struct usb_serial_driver *driver); extern void usb_serial_deregister(struct usb_serial_driver *driver); + +extern int usb_serial_register_drivers(struct usb_driver *udriver, + struct usb_serial_driver * const serial_drivers[]); +extern void usb_serial_deregister_drivers(struct usb_driver *udriver, + struct usb_serial_driver * const serial_drivers[]); extern void usb_serial_port_softint(struct usb_serial_port *port); extern int usb_serial_probe(struct usb_interface *iface, From 08a4f6bc2e7046ce50849d7589b7d0763926d808 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Feb 2012 14:56:17 -0500 Subject: [PATCH 122/269] usb-serial: use new registration API in [a-c]* drivers This patch (as1523) modifies the following usb-serial drivers to utilize the new usb_serial_{de}register_drivers() routines: aircable, ark3116, belkin_sa, ch341, cp210x, cyberjack, and cypress_m8. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/aircable.c | 23 +++++------------- drivers/usb/serial/ark3116.c | 17 ++++++------- drivers/usb/serial/belkin_sa.c | 26 ++++++++------------ drivers/usb/serial/ch341.c | 19 +++++---------- drivers/usb/serial/cp210x.c | 29 ++++++++--------------- drivers/usb/serial/cyberjack.c | 29 +++++++++-------------- drivers/usb/serial/cypress_m8.c | 42 ++++++++------------------------- 7 files changed, 60 insertions(+), 125 deletions(-) diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index 123bf9155339..dbf3bddc1b51 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -175,7 +175,6 @@ static struct usb_driver aircable_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver aircable_device = { @@ -183,7 +182,6 @@ static struct usb_serial_driver aircable_device = { .owner = THIS_MODULE, .name = "aircable", }, - .usb_driver = &aircable_driver, .id_table = id_table, .num_ports = 1, .bulk_out_size = HCI_COMPLETE_FRAME, @@ -194,27 +192,18 @@ static struct usb_serial_driver aircable_device = { .unthrottle = usb_serial_generic_unthrottle, }; +static struct usb_serial_driver * const serial_drivers[] = { + &aircable_device, NULL +}; + static int __init aircable_init(void) { - int retval; - retval = usb_serial_register(&aircable_device); - if (retval) - goto failed_serial_register; - retval = usb_register(&aircable_driver); - if (retval) - goto failed_usb_register; - return 0; - -failed_usb_register: - usb_serial_deregister(&aircable_device); -failed_serial_register: - return retval; + return usb_serial_register_drivers(&aircable_driver, serial_drivers); } static void __exit aircable_exit(void) { - usb_deregister(&aircable_driver); - usb_serial_deregister(&aircable_device); + usb_serial_deregister_drivers(&aircable_driver, serial_drivers); } MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 69328dcfd91a..ab2cf1165c60 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -719,7 +719,6 @@ static struct usb_driver ark3116_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver ark3116_device = { @@ -728,7 +727,6 @@ static struct usb_serial_driver ark3116_device = { .name = "ark3116", }, .id_table = id_table, - .usb_driver = &ark3116_driver, .num_ports = 1, .attach = ark3116_attach, .release = ark3116_release, @@ -745,28 +743,27 @@ static struct usb_serial_driver ark3116_device = { .process_read_urb = ark3116_process_read_urb, }; +static struct usb_serial_driver * const serial_drivers[] = { + &ark3116_device, NULL +}; + static int __init ark3116_init(void) { int retval; - retval = usb_serial_register(&ark3116_device); - if (retval) - return retval; - retval = usb_register(&ark3116_driver); + retval = usb_serial_register_drivers(&ark3116_driver, serial_drivers); if (retval == 0) { printk(KERN_INFO "%s:" DRIVER_VERSION ":" DRIVER_DESC "\n", KBUILD_MODNAME); - } else - usb_serial_deregister(&ark3116_device); + } return retval; } static void __exit ark3116_exit(void) { - usb_deregister(&ark3116_driver); - usb_serial_deregister(&ark3116_device); + usb_serial_deregister_drivers(&ark3116_driver, serial_drivers); } module_init(ark3116_init); diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 29ffeb6279c7..e8b473f5acf7 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -78,7 +78,6 @@ static struct usb_driver belkin_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; /* All of the device info needed for the serial converters */ @@ -88,7 +87,6 @@ static struct usb_serial_driver belkin_device = { .name = "belkin", }, .description = "Belkin / Peracom / GoHubs USB Serial Adapter", - .usb_driver = &belkin_driver, .id_table = id_table_combined, .num_ports = 1, .open = belkin_sa_open, @@ -103,6 +101,10 @@ static struct usb_serial_driver belkin_device = { .release = belkin_sa_release, }; +static struct usb_serial_driver * const serial_drivers[] = { + &belkin_device, NULL +}; + struct belkin_sa_private { spinlock_t lock; unsigned long control_state; @@ -526,25 +528,17 @@ exit: static int __init belkin_sa_init(void) { int retval; - retval = usb_serial_register(&belkin_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&belkin_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&belkin_device); -failed_usb_serial_register: + + retval = usb_serial_register_drivers(&belkin_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit belkin_sa_exit (void) { - usb_deregister(&belkin_driver); - usb_serial_deregister(&belkin_device); + usb_serial_deregister_drivers(&belkin_driver, serial_drivers); } diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 5e53cc59e652..23de3b039a28 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -625,7 +625,6 @@ static struct usb_driver ch341_driver = { .resume = usb_serial_resume, .reset_resume = ch341_reset_resume, .id_table = id_table, - .no_dynamic_id = 1, .supports_autosuspend = 1, }; @@ -635,7 +634,6 @@ static struct usb_serial_driver ch341_device = { .name = "ch341-uart", }, .id_table = id_table, - .usb_driver = &ch341_driver, .num_ports = 1, .open = ch341_open, .dtr_rts = ch341_dtr_rts, @@ -650,23 +648,18 @@ static struct usb_serial_driver ch341_device = { .attach = ch341_attach, }; +static struct usb_serial_driver * const serial_drivers[] = { + &ch341_device, NULL +}; + static int __init ch341_init(void) { - int retval; - - retval = usb_serial_register(&ch341_device); - if (retval) - return retval; - retval = usb_register(&ch341_driver); - if (retval) - usb_serial_deregister(&ch341_device); - return retval; + return usb_serial_register_drivers(&ch341_driver, serial_drivers); } static void __exit ch341_exit(void) { - usb_deregister(&ch341_driver); - usb_serial_deregister(&ch341_device); + usb_serial_deregister_drivers(&ch341_driver, serial_drivers); } module_init(ch341_init); diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index ec9dc4e9a3ff..01a9374357f1 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -154,7 +154,6 @@ static struct usb_driver cp210x_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver cp210x_device = { @@ -162,7 +161,6 @@ static struct usb_serial_driver cp210x_device = { .owner = THIS_MODULE, .name = "cp210x", }, - .usb_driver = &cp210x_driver, .id_table = id_table, .num_ports = 1, .bulk_in_size = 256, @@ -177,6 +175,10 @@ static struct usb_serial_driver cp210x_device = { .dtr_rts = cp210x_dtr_rts }; +static struct usb_serial_driver * const serial_drivers[] = { + &cp210x_device, NULL +}; + /* Config request types */ #define REQTYPE_HOST_TO_DEVICE 0x41 #define REQTYPE_DEVICE_TO_HOST 0xc1 @@ -852,27 +854,16 @@ static int __init cp210x_init(void) { int retval; - retval = usb_serial_register(&cp210x_device); - if (retval) - return retval; /* Failed to register */ - - retval = usb_register(&cp210x_driver); - if (retval) { - /* Failed to register */ - usb_serial_deregister(&cp210x_device); - return retval; - } - - /* Success */ - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; + retval = usb_serial_register_drivers(&cp210x_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); + return retval; } static void __exit cp210x_exit(void) { - usb_deregister(&cp210x_driver); - usb_serial_deregister(&cp210x_device); + usb_serial_deregister_drivers(&cp210x_driver, serial_drivers); } module_init(cp210x_init); diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 6bc3802a581a..d2e536f649ba 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -82,7 +82,6 @@ static struct usb_driver cyberjack_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver cyberjack_device = { @@ -91,7 +90,6 @@ static struct usb_serial_driver cyberjack_device = { .name = "cyberjack", }, .description = "Reiner SCT Cyberjack USB card reader", - .usb_driver = &cyberjack_driver, .id_table = id_table, .num_ports = 1, .attach = cyberjack_startup, @@ -106,6 +104,10 @@ static struct usb_serial_driver cyberjack_device = { .write_bulk_callback = cyberjack_write_bulk_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &cyberjack_device, NULL +}; + struct cyberjack_private { spinlock_t lock; /* Lock for SMP */ short rdtodo; /* Bytes still to read */ @@ -476,28 +478,19 @@ exit: static int __init cyberjack_init(void) { int retval; - retval = usb_serial_register(&cyberjack_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&cyberjack_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION " " - DRIVER_AUTHOR "\n"); - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); - - return 0; -failed_usb_register: - usb_serial_deregister(&cyberjack_device); -failed_usb_serial_register: + retval = usb_serial_register_drivers(&cyberjack_driver, serial_drivers); + if (retval == 0) { + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION " " + DRIVER_AUTHOR "\n"); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); + } return retval; } static void __exit cyberjack_exit(void) { - usb_deregister(&cyberjack_driver); - usb_serial_deregister(&cyberjack_device); + usb_serial_deregister_drivers(&cyberjack_driver, serial_drivers); } module_init(cyberjack_init); diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 5ae86b349cad..bc5057513d5d 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -94,7 +94,6 @@ static struct usb_driver cypress_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; enum packet_format { @@ -163,7 +162,6 @@ static struct usb_serial_driver cypress_earthmate_device = { .name = "earthmate", }, .description = "DeLorme Earthmate USB", - .usb_driver = &cypress_driver, .id_table = id_table_earthmate, .num_ports = 1, .attach = cypress_earthmate_startup, @@ -190,7 +188,6 @@ static struct usb_serial_driver cypress_hidcom_device = { .name = "cyphidcom", }, .description = "HID->COM RS232 Adapter", - .usb_driver = &cypress_driver, .id_table = id_table_cyphidcomrs232, .num_ports = 1, .attach = cypress_hidcom_startup, @@ -217,7 +214,6 @@ static struct usb_serial_driver cypress_ca42v2_device = { .name = "nokiaca42v2", }, .description = "Nokia CA-42 V2 Adapter", - .usb_driver = &cypress_driver, .id_table = id_table_nokiaca42v2, .num_ports = 1, .attach = cypress_ca42v2_startup, @@ -238,6 +234,11 @@ static struct usb_serial_driver cypress_ca42v2_device = { .write_int_callback = cypress_write_int_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &cypress_earthmate_device, &cypress_hidcom_device, + &cypress_ca42v2_device, NULL +}; + /***************************************************************************** * Cypress serial helper functions *****************************************************************************/ @@ -1356,30 +1357,10 @@ static int __init cypress_init(void) dbg("%s", __func__); - retval = usb_serial_register(&cypress_earthmate_device); - if (retval) - goto failed_em_register; - retval = usb_serial_register(&cypress_hidcom_device); - if (retval) - goto failed_hidcom_register; - retval = usb_serial_register(&cypress_ca42v2_device); - if (retval) - goto failed_ca42v2_register; - retval = usb_register(&cypress_driver); - if (retval) - goto failed_usb_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; - -failed_usb_register: - usb_serial_deregister(&cypress_ca42v2_device); -failed_ca42v2_register: - usb_serial_deregister(&cypress_hidcom_device); -failed_hidcom_register: - usb_serial_deregister(&cypress_earthmate_device); -failed_em_register: + retval = usb_serial_register_drivers(&cypress_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } @@ -1388,10 +1369,7 @@ static void __exit cypress_exit(void) { dbg("%s", __func__); - usb_deregister(&cypress_driver); - usb_serial_deregister(&cypress_earthmate_device); - usb_serial_deregister(&cypress_hidcom_device); - usb_serial_deregister(&cypress_ca42v2_device); + usb_serial_deregister_drivers(&cypress_driver, serial_drivers); } From 97b6b6d2339f67eb17d954930a908b762af66228 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Feb 2012 14:56:32 -0500 Subject: [PATCH 123/269] usb-serial: use new registration API in [d-h]* drivers This patch (as1524) modifies the following usb-serial drivers to utilize the new usb_serial_{de}register_drivers() routines: digi_acceleport, empeg, ftdi_sio, funsoft, garmin_gps, and hp4x. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/digi_acceleport.c | 32 ++++++++-------------------- drivers/usb/serial/empeg.c | 26 +++++++++------------- drivers/usb/serial/ftdi_sio.c | 26 ++++++++-------------- drivers/usb/serial/funsoft.c | 19 ++++++----------- drivers/usb/serial/garmin_gps.c | 25 +++++++--------------- drivers/usb/serial/hp4x.c | 26 +++++++++------------- 6 files changed, 52 insertions(+), 102 deletions(-) diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 2b1da0cc071a..f0e776bb1ffb 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -276,7 +276,6 @@ static struct usb_driver digi_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; @@ -288,7 +287,6 @@ static struct usb_serial_driver digi_acceleport_2_device = { .name = "digi_2", }, .description = "Digi 2 port USB adapter", - .usb_driver = &digi_driver, .id_table = id_table_2, .num_ports = 3, .open = digi_open, @@ -316,7 +314,6 @@ static struct usb_serial_driver digi_acceleport_4_device = { .name = "digi_4", }, .description = "Digi 4 port USB adapter", - .usb_driver = &digi_driver, .id_table = id_table_4, .num_ports = 4, .open = digi_open, @@ -337,6 +334,9 @@ static struct usb_serial_driver digi_acceleport_4_device = { .release = digi_release, }; +static struct usb_serial_driver * const serial_drivers[] = { + &digi_acceleport_2_device, &digi_acceleport_4_device, NULL +}; /* Functions */ @@ -1583,31 +1583,17 @@ static int digi_read_oob_callback(struct urb *urb) static int __init digi_init(void) { int retval; - retval = usb_serial_register(&digi_acceleport_2_device); - if (retval) - goto failed_acceleport_2_device; - retval = usb_serial_register(&digi_acceleport_4_device); - if (retval) - goto failed_acceleport_4_device; - retval = usb_register(&digi_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&digi_acceleport_4_device); -failed_acceleport_4_device: - usb_serial_deregister(&digi_acceleport_2_device); -failed_acceleport_2_device: + + retval = usb_serial_register_drivers(&digi_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit digi_exit (void) { - usb_deregister(&digi_driver); - usb_serial_deregister(&digi_acceleport_2_device); - usb_serial_deregister(&digi_acceleport_4_device); + usb_serial_deregister_drivers(&digi_driver, serial_drivers); } diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index aced6817bf95..51bcbd5d5e8e 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -56,7 +56,6 @@ static struct usb_driver empeg_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver empeg_device = { @@ -65,7 +64,6 @@ static struct usb_serial_driver empeg_device = { .name = "empeg", }, .id_table = id_table, - .usb_driver = &empeg_driver, .num_ports = 1, .bulk_out_size = 256, .throttle = usb_serial_generic_throttle, @@ -74,6 +72,10 @@ static struct usb_serial_driver empeg_device = { .init_termios = empeg_init_termios, }; +static struct usb_serial_driver * const serial_drivers[] = { + &empeg_device, NULL +}; + static int empeg_startup(struct usb_serial *serial) { int r; @@ -140,24 +142,16 @@ static int __init empeg_init(void) { int retval; - retval = usb_serial_register(&empeg_device); - if (retval) - return retval; - retval = usb_register(&empeg_driver); - if (retval) { - usb_serial_deregister(&empeg_device); - return retval; - } - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; + retval = usb_serial_register_drivers(&empeg_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); + return retval; } static void __exit empeg_exit(void) { - usb_deregister(&empeg_driver); - usb_serial_deregister(&empeg_device); + usb_serial_deregister_drivers(&empeg_driver, serial_drivers); } diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f770415305f8..615cf2c4915c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -857,7 +857,6 @@ static struct usb_driver ftdi_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; static const char *ftdi_chip_name[] = { @@ -915,7 +914,6 @@ static struct usb_serial_driver ftdi_sio_device = { .name = "ftdi_sio", }, .description = "FTDI USB Serial Device", - .usb_driver = &ftdi_driver, .id_table = id_table_combined, .num_ports = 1, .bulk_in_size = 512, @@ -938,6 +936,10 @@ static struct usb_serial_driver ftdi_sio_device = { .break_ctl = ftdi_break_ctl, }; +static struct usb_serial_driver * const serial_drivers[] = { + &ftdi_sio_device, NULL +}; + #define WDR_TIMEOUT 5000 /* default urb timeout */ #define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */ @@ -2420,19 +2422,10 @@ static int __init ftdi_init(void) id_table_combined[i].idVendor = vendor; id_table_combined[i].idProduct = product; } - retval = usb_serial_register(&ftdi_sio_device); - if (retval) - goto failed_sio_register; - retval = usb_register(&ftdi_driver); - if (retval) - goto failed_usb_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&ftdi_sio_device); -failed_sio_register: + retval = usb_serial_register_drivers(&ftdi_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } @@ -2440,8 +2433,7 @@ static void __exit ftdi_exit(void) { dbg("%s", __func__); - usb_deregister(&ftdi_driver); - usb_serial_deregister(&ftdi_sio_device); + usb_serial_deregister_drivers(&ftdi_driver, serial_drivers); } diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c index 5d4b099dcf8b..bb274a244ae9 100644 --- a/drivers/usb/serial/funsoft.c +++ b/drivers/usb/serial/funsoft.c @@ -29,7 +29,6 @@ static struct usb_driver funsoft_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver funsoft_device = { @@ -38,27 +37,21 @@ static struct usb_serial_driver funsoft_device = { .name = "funsoft", }, .id_table = id_table, - .usb_driver = &funsoft_driver, .num_ports = 1, }; +static struct usb_serial_driver * const serial_drivers[] = { + &funsoft_device, NULL +}; + static int __init funsoft_init(void) { - int retval; - - retval = usb_serial_register(&funsoft_device); - if (retval) - return retval; - retval = usb_register(&funsoft_driver); - if (retval) - usb_serial_deregister(&funsoft_device); - return retval; + return usb_serial_register_drivers(&funsoft_driver, serial_drivers); } static void __exit funsoft_exit(void) { - usb_deregister(&funsoft_driver); - usb_serial_deregister(&funsoft_device); + usb_serial_deregister_drivers(&funsoft_driver, serial_drivers); } module_init(funsoft_init); diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 21343378c322..69da3abcb363 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -224,7 +224,6 @@ static struct usb_driver garmin_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; @@ -1497,7 +1496,6 @@ static struct usb_serial_driver garmin_device = { .name = "garmin_gps", }, .description = "Garmin GPS usb/tty", - .usb_driver = &garmin_driver, .id_table = id_table, .num_ports = 1, .open = garmin_open, @@ -1514,33 +1512,26 @@ static struct usb_serial_driver garmin_device = { .read_int_callback = garmin_read_int_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &garmin_device, NULL +}; static int __init garmin_init(void) { int retval; - retval = usb_serial_register(&garmin_device); - if (retval) - goto failed_garmin_register; - retval = usb_register(&garmin_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; -failed_usb_register: - usb_serial_deregister(&garmin_device); -failed_garmin_register: + retval = usb_serial_register_drivers(&garmin_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit garmin_exit(void) { - usb_deregister(&garmin_driver); - usb_serial_deregister(&garmin_device); + usb_serial_deregister_drivers(&garmin_driver, serial_drivers); } diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c index 809379159b0e..325cf092b61c 100644 --- a/drivers/usb/serial/hp4x.c +++ b/drivers/usb/serial/hp4x.c @@ -41,7 +41,6 @@ static struct usb_driver hp49gp_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver hp49gp_device = { @@ -50,32 +49,27 @@ static struct usb_serial_driver hp49gp_device = { .name = "hp4X", }, .id_table = id_table, - .usb_driver = &hp49gp_driver, .num_ports = 1, }; +static struct usb_serial_driver * const serial_drivers[] = { + &hp49gp_device, NULL +}; + static int __init hp49gp_init(void) { int retval; - retval = usb_serial_register(&hp49gp_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&hp49gp_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&hp49gp_device); -failed_usb_serial_register: + + retval = usb_serial_register_drivers(&hp49gp_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit hp49gp_exit(void) { - usb_deregister(&hp49gp_driver); - usb_serial_deregister(&hp49gp_device); + usb_serial_deregister_drivers(&hp49gp_driver, serial_drivers); } module_init(hp49gp_init); From 7dbe2460989b10644651e779b17b683627feea48 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Feb 2012 14:56:57 -0500 Subject: [PATCH 124/269] usb-serial: use new registration API in [i-j]* drivers This patch (as1525) modifies the following usb-serial drivers to utilize the new usb_serial_{de}register_drivers() routines: io_edgeport, io_ti, ipaq, ipw, ir-usb, and iuu_phoenix. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_edgeport.c | 41 ++++++-------------------------- drivers/usb/serial/io_tables.h | 10 ++++---- drivers/usb/serial/io_ti.c | 33 ++++++++----------------- drivers/usb/serial/ipaq.c | 26 ++++++++------------ drivers/usb/serial/ipw.c | 24 +++++++------------ drivers/usb/serial/ir-usb.c | 30 +++++++---------------- drivers/usb/serial/iuu_phoenix.c | 26 ++++++++------------ 7 files changed, 60 insertions(+), 130 deletions(-) diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 616b07862771..55afa233aacd 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -3189,35 +3189,12 @@ static int __init edgeport_init(void) { int retval; - retval = usb_serial_register(&edgeport_2port_device); - if (retval) - goto failed_2port_device_register; - retval = usb_serial_register(&edgeport_4port_device); - if (retval) - goto failed_4port_device_register; - retval = usb_serial_register(&edgeport_8port_device); - if (retval) - goto failed_8port_device_register; - retval = usb_serial_register(&epic_device); - if (retval) - goto failed_epic_device_register; - retval = usb_register(&io_driver); - if (retval) - goto failed_usb_register; - atomic_set(&CmdUrbs, 0); - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; - -failed_usb_register: - usb_serial_deregister(&epic_device); -failed_epic_device_register: - usb_serial_deregister(&edgeport_8port_device); -failed_8port_device_register: - usb_serial_deregister(&edgeport_4port_device); -failed_4port_device_register: - usb_serial_deregister(&edgeport_2port_device); -failed_2port_device_register: + retval = usb_serial_register_drivers(&io_driver, serial_drivers); + if (retval == 0) { + atomic_set(&CmdUrbs, 0); + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); + } return retval; } @@ -3228,11 +3205,7 @@ failed_2port_device_register: ****************************************************************************/ static void __exit edgeport_exit (void) { - usb_deregister(&io_driver); - usb_serial_deregister(&edgeport_2port_device); - usb_serial_deregister(&edgeport_4port_device); - usb_serial_deregister(&edgeport_8port_device); - usb_serial_deregister(&epic_device); + usb_serial_deregister_drivers(&io_driver, serial_drivers); } module_init(edgeport_init); diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index 178b22eb32b1..d0e7c9affb6f 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -100,7 +100,6 @@ static struct usb_driver io_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; static struct usb_serial_driver edgeport_2port_device = { @@ -109,7 +108,6 @@ static struct usb_serial_driver edgeport_2port_device = { .name = "edgeport_2", }, .description = "Edgeport 2 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_2port_id_table, .num_ports = 2, .open = edge_open, @@ -139,7 +137,6 @@ static struct usb_serial_driver edgeport_4port_device = { .name = "edgeport_4", }, .description = "Edgeport 4 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_4port_id_table, .num_ports = 4, .open = edge_open, @@ -169,7 +166,6 @@ static struct usb_serial_driver edgeport_8port_device = { .name = "edgeport_8", }, .description = "Edgeport 8 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_8port_id_table, .num_ports = 8, .open = edge_open, @@ -199,7 +195,6 @@ static struct usb_serial_driver epic_device = { .name = "epic", }, .description = "EPiC device", - .usb_driver = &io_driver, .id_table = Epic_port_id_table, .num_ports = 1, .open = edge_open, @@ -223,5 +218,10 @@ static struct usb_serial_driver epic_device = { .write_bulk_callback = edge_bulk_out_data_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &edgeport_2port_device, &edgeport_4port_device, + &edgeport_8port_device, &epic_device, NULL +}; + #endif diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 58a3697246a8..484db3331f88 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -202,7 +202,6 @@ static struct usb_driver io_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; @@ -2725,7 +2724,6 @@ static struct usb_serial_driver edgeport_1port_device = { .name = "edgeport_ti_1", }, .description = "Edgeport TI 1 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_1port_id_table, .num_ports = 1, .open = edge_open, @@ -2757,7 +2755,6 @@ static struct usb_serial_driver edgeport_2port_device = { .name = "edgeport_ti_2", }, .description = "Edgeport TI 2 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_2port_id_table, .num_ports = 2, .open = edge_open, @@ -2782,35 +2779,25 @@ static struct usb_serial_driver edgeport_2port_device = { .write_bulk_callback = edge_bulk_out_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &edgeport_1port_device, &edgeport_2port_device, NULL +}; + static int __init edgeport_init(void) { int retval; - retval = usb_serial_register(&edgeport_1port_device); - if (retval) - goto failed_1port_device_register; - retval = usb_serial_register(&edgeport_2port_device); - if (retval) - goto failed_2port_device_register; - retval = usb_register(&io_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&edgeport_2port_device); -failed_2port_device_register: - usb_serial_deregister(&edgeport_1port_device); -failed_1port_device_register: + + retval = usb_serial_register_drivers(&io_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit edgeport_exit(void) { - usb_deregister(&io_driver); - usb_serial_deregister(&edgeport_1port_device); - usb_serial_deregister(&edgeport_2port_device); + usb_serial_deregister_drivers(&io_driver, serial_drivers); } module_init(edgeport_init); diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 06053a920dd8..10c02b8b5664 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -510,7 +510,6 @@ static struct usb_driver ipaq_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = ipaq_id_table, - .no_dynamic_id = 1, }; @@ -521,7 +520,6 @@ static struct usb_serial_driver ipaq_device = { .name = "ipaq", }, .description = "PocketPC PDA", - .usb_driver = &ipaq_driver, .id_table = ipaq_id_table, .bulk_in_size = 256, .bulk_out_size = 256, @@ -530,6 +528,10 @@ static struct usb_serial_driver ipaq_device = { .calc_num_ports = ipaq_calc_num_ports, }; +static struct usb_serial_driver * const serial_drivers[] = { + &ipaq_device, NULL +}; + static int ipaq_open(struct tty_struct *tty, struct usb_serial_port *port) { @@ -624,30 +626,22 @@ static int ipaq_startup(struct usb_serial *serial) static int __init ipaq_init(void) { int retval; - retval = usb_serial_register(&ipaq_device); - if (retval) - goto failed_usb_serial_register; + if (vendor) { ipaq_id_table[0].idVendor = vendor; ipaq_id_table[0].idProduct = product; } - retval = usb_register(&ipaq_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&ipaq_device); -failed_usb_serial_register: + retval = usb_serial_register_drivers(&ipaq_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit ipaq_exit(void) { - usb_deregister(&ipaq_driver); - usb_serial_deregister(&ipaq_device); + usb_serial_deregister_drivers(&ipaq_driver, serial_drivers); } diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 6f9356f3f99e..27b8886f1055 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -144,7 +144,6 @@ static struct usb_driver usb_ipw_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = usb_ipw_ids, - .no_dynamic_id = 1, }; static bool debug; @@ -318,7 +317,6 @@ static struct usb_serial_driver ipw_device = { .name = "ipw", }, .description = "IPWireless converter", - .usb_driver = &usb_ipw_driver, .id_table = usb_ipw_ids, .num_ports = 1, .disconnect = usb_wwan_disconnect, @@ -331,29 +329,25 @@ static struct usb_serial_driver ipw_device = { .write = usb_wwan_write, }; +static struct usb_serial_driver * const serial_drivers[] = { + &ipw_device, NULL +}; static int __init usb_ipw_init(void) { int retval; - retval = usb_serial_register(&ipw_device); - if (retval) - return retval; - retval = usb_register(&usb_ipw_driver); - if (retval) { - usb_serial_deregister(&ipw_device); - return retval; - } - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; + retval = usb_serial_register_drivers(&usb_ipw_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); + return retval; } static void __exit usb_ipw_exit(void) { - usb_deregister(&usb_ipw_driver); - usb_serial_deregister(&ipw_device); + usb_serial_deregister_drivers(&usb_ipw_driver, serial_drivers); } module_init(usb_ipw_init); diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 84a396e83671..84965cd65c76 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -82,7 +82,6 @@ static struct usb_driver ir_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = ir_id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver ir_device = { @@ -91,7 +90,6 @@ static struct usb_serial_driver ir_device = { .name = "ir-usb", }, .description = "IR Dongle", - .usb_driver = &ir_driver, .id_table = ir_id_table, .num_ports = 1, .set_termios = ir_set_termios, @@ -101,6 +99,10 @@ static struct usb_serial_driver ir_device = { .process_read_urb = ir_process_read_urb, }; +static struct usb_serial_driver * const serial_drivers[] = { + &ir_device, NULL +}; + static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc) { dbg("bLength=%x", desc->bLength); @@ -445,30 +447,16 @@ static int __init ir_init(void) ir_device.bulk_out_size = buffer_size; } - retval = usb_serial_register(&ir_device); - if (retval) - goto failed_usb_serial_register; - - retval = usb_register(&ir_driver); - if (retval) - goto failed_usb_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; - -failed_usb_register: - usb_serial_deregister(&ir_device); - -failed_usb_serial_register: + retval = usb_serial_register_drivers(&ir_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit ir_exit(void) { - usb_deregister(&ir_driver); - usb_serial_deregister(&ir_device); + usb_serial_deregister_drivers(&ir_driver, serial_drivers); } diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 3077a4436976..97a7ea2a5e4f 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -56,7 +56,6 @@ static struct usb_driver iuu_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; /* turbo parameter */ @@ -1274,7 +1273,6 @@ static struct usb_serial_driver iuu_device = { .name = "iuu_phoenix", }, .id_table = id_table, - .usb_driver = &iuu_driver, .num_ports = 1, .bulk_in_size = 512, .bulk_out_size = 512, @@ -1292,28 +1290,24 @@ static struct usb_serial_driver iuu_device = { .release = iuu_release, }; +static struct usb_serial_driver * const serial_drivers[] = { + &iuu_device, NULL +}; + static int __init iuu_init(void) { int retval; - retval = usb_serial_register(&iuu_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&iuu_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&iuu_device); -failed_usb_serial_register: + + retval = usb_serial_register_drivers(&iuu_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit iuu_exit(void) { - usb_deregister(&iuu_driver); - usb_serial_deregister(&iuu_device); + usb_serial_deregister_drivers(&iuu_driver, serial_drivers); } module_init(iuu_init); From 4d2a7aff1062048ea59214b49ca1d915586d6d6d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Feb 2012 14:57:09 -0500 Subject: [PATCH 125/269] usb-serial: use new registration API in [k-m]* drivers This patch (as1526) modifies the following usb-serial drivers to utilize the new usb_serial_{de}register_drivers() routines: keyspan, kl5kusb105, kobil_sct, mct_u232, mos7720, mos7840, and moto_modem. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan.c | 38 +++++---------------------------- drivers/usb/serial/keyspan.h | 10 ++++----- drivers/usb/serial/kl5kusb105.c | 26 +++++++++------------- drivers/usb/serial/kobil_sct.c | 25 +++++++--------------- drivers/usb/serial/mct_u232.c | 26 +++++++++------------- drivers/usb/serial/mos7720.c | 32 ++++++++------------------- drivers/usb/serial/mos7840.c | 32 +++++++++------------------ drivers/usb/serial/moto_modem.c | 19 ++++++----------- 8 files changed, 63 insertions(+), 145 deletions(-) diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 4cc36c761801..0d5d3025a663 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -134,45 +134,17 @@ struct keyspan_port_private { static int __init keyspan_init(void) { int retval; - retval = usb_serial_register(&keyspan_pre_device); - if (retval) - goto failed_pre_device_register; - retval = usb_serial_register(&keyspan_1port_device); - if (retval) - goto failed_1port_device_register; - retval = usb_serial_register(&keyspan_2port_device); - if (retval) - goto failed_2port_device_register; - retval = usb_serial_register(&keyspan_4port_device); - if (retval) - goto failed_4port_device_register; - retval = usb_register(&keyspan_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; -failed_usb_register: - usb_serial_deregister(&keyspan_4port_device); -failed_4port_device_register: - usb_serial_deregister(&keyspan_2port_device); -failed_2port_device_register: - usb_serial_deregister(&keyspan_1port_device); -failed_1port_device_register: - usb_serial_deregister(&keyspan_pre_device); -failed_pre_device_register: + retval = usb_serial_register_drivers(&keyspan_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit keyspan_exit(void) { - usb_deregister(&keyspan_driver); - usb_serial_deregister(&keyspan_pre_device); - usb_serial_deregister(&keyspan_1port_device); - usb_serial_deregister(&keyspan_2port_device); - usb_serial_deregister(&keyspan_4port_device); + usb_serial_deregister_drivers(&keyspan_driver, serial_drivers); } module_init(keyspan_init); diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 13fa1d1cc900..622853c9e384 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -492,7 +492,6 @@ static struct usb_driver keyspan_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = keyspan_ids_combined, - .no_dynamic_id = 1, }; /* usb_device_id table for the pre-firmware download keyspan devices */ @@ -545,7 +544,6 @@ static struct usb_serial_driver keyspan_pre_device = { .name = "keyspan_no_firm", }, .description = "Keyspan - (without firmware)", - .usb_driver = &keyspan_driver, .id_table = keyspan_pre_ids, .num_ports = 1, .attach = keyspan_fake_startup, @@ -557,7 +555,6 @@ static struct usb_serial_driver keyspan_1port_device = { .name = "keyspan_1", }, .description = "Keyspan 1 port adapter", - .usb_driver = &keyspan_driver, .id_table = keyspan_1port_ids, .num_ports = 1, .open = keyspan_open, @@ -580,7 +577,6 @@ static struct usb_serial_driver keyspan_2port_device = { .name = "keyspan_2", }, .description = "Keyspan 2 port adapter", - .usb_driver = &keyspan_driver, .id_table = keyspan_2port_ids, .num_ports = 2, .open = keyspan_open, @@ -603,7 +599,6 @@ static struct usb_serial_driver keyspan_4port_device = { .name = "keyspan_4", }, .description = "Keyspan 4 port adapter", - .usb_driver = &keyspan_driver, .id_table = keyspan_4port_ids, .num_ports = 4, .open = keyspan_open, @@ -620,4 +615,9 @@ static struct usb_serial_driver keyspan_4port_device = { .release = keyspan_release, }; +static struct usb_serial_driver * const serial_drivers[] = { + &keyspan_pre_device, &keyspan_1port_device, + &keyspan_2port_device, &keyspan_4port_device, NULL +}; + #endif diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index fc064e1442ca..0e65e50edd50 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -91,7 +91,6 @@ static struct usb_driver kl5kusb105d_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver kl5kusb105d_device = { @@ -100,7 +99,6 @@ static struct usb_serial_driver kl5kusb105d_device = { .name = "kl5kusb105d", }, .description = "KL5KUSB105D / PalmConnect", - .usb_driver = &kl5kusb105d_driver, .id_table = id_table, .num_ports = 1, .bulk_out_size = 64, @@ -118,6 +116,10 @@ static struct usb_serial_driver kl5kusb105d_device = { .prepare_write_buffer = klsi_105_prepare_write_buffer, }; +static struct usb_serial_driver * const serial_drivers[] = { + &kl5kusb105d_device, NULL +}; + struct klsi_105_port_settings { __u8 pktlen; /* always 5, it seems */ __u8 baudrate; @@ -694,26 +696,18 @@ static int klsi_105_tiocmset(struct tty_struct *tty, static int __init klsi_105_init(void) { int retval; - retval = usb_serial_register(&kl5kusb105d_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&kl5kusb105d_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&kl5kusb105d_device); -failed_usb_serial_register: + retval = usb_serial_register_drivers(&kl5kusb105d_driver, + serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit klsi_105_exit(void) { - usb_deregister(&kl5kusb105d_driver); - usb_serial_deregister(&kl5kusb105d_device); + usb_serial_deregister_drivers(&kl5kusb105d_driver, serial_drivers); } diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index a92a3efb507b..a033dd7dc265 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -90,7 +90,6 @@ static struct usb_driver kobil_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; @@ -100,7 +99,6 @@ static struct usb_serial_driver kobil_device = { .name = "kobil", }, .description = "KOBIL USB smart card terminal", - .usb_driver = &kobil_driver, .id_table = id_table, .num_ports = 1, .attach = kobil_startup, @@ -117,6 +115,9 @@ static struct usb_serial_driver kobil_device = { .read_int_callback = kobil_read_int_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &kobil_device, NULL +}; struct kobil_private { int write_int_endpoint_address; @@ -685,28 +686,18 @@ static int kobil_ioctl(struct tty_struct *tty, static int __init kobil_init(void) { int retval; - retval = usb_serial_register(&kobil_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&kobil_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; -failed_usb_register: - usb_serial_deregister(&kobil_device); -failed_usb_serial_register: + retval = usb_serial_register_drivers(&kobil_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit kobil_exit(void) { - usb_deregister(&kobil_driver); - usb_serial_deregister(&kobil_device); + usb_serial_deregister_drivers(&kobil_driver, serial_drivers); } module_init(kobil_init); diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 27fa9c8a77b0..6d9a7f8b13db 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -88,7 +88,6 @@ static struct usb_driver mct_u232_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; static struct usb_serial_driver mct_u232_device = { @@ -97,7 +96,6 @@ static struct usb_serial_driver mct_u232_device = { .name = "mct_u232", }, .description = "MCT U232", - .usb_driver = &mct_u232_driver, .id_table = id_table_combined, .num_ports = 1, .open = mct_u232_open, @@ -116,6 +114,10 @@ static struct usb_serial_driver mct_u232_device = { .get_icount = mct_u232_get_icount, }; +static struct usb_serial_driver * const serial_drivers[] = { + &mct_u232_device, NULL +}; + struct mct_u232_private { spinlock_t lock; unsigned int control_state; /* Modem Line Setting (TIOCM) */ @@ -907,26 +909,18 @@ static int mct_u232_get_icount(struct tty_struct *tty, static int __init mct_u232_init(void) { int retval; - retval = usb_serial_register(&mct_u232_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&mct_u232_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&mct_u232_device); -failed_usb_serial_register: + + retval = usb_serial_register_drivers(&mct_u232_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit mct_u232_exit(void) { - usb_deregister(&mct_u232_driver); - usb_serial_deregister(&mct_u232_device); + usb_serial_deregister_drivers(&mct_u232_driver, serial_drivers); } module_init(mct_u232_init); diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 4fb29b4aaad6..4dfbad80418c 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -2169,7 +2169,6 @@ static struct usb_driver usb_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = moschip_port_id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver moschip7720_2port_driver = { @@ -2178,7 +2177,6 @@ static struct usb_serial_driver moschip7720_2port_driver = { .name = "moschip7720", }, .description = "Moschip 2 port adapter", - .usb_driver = &usb_driver, .id_table = moschip_port_id_table, .calc_num_ports = mos77xx_calc_num_ports, .open = mos7720_open, @@ -2201,38 +2199,26 @@ static struct usb_serial_driver moschip7720_2port_driver = { .read_int_callback = NULL /* dynamically assigned in probe() */ }; +static struct usb_serial_driver * const serial_drivers[] = { + &moschip7720_2port_driver, NULL +}; + static int __init moschip7720_init(void) { int retval; dbg("%s: Entering ..........", __func__); - /* Register with the usb serial */ - retval = usb_serial_register(&moschip7720_2port_driver); - if (retval) - goto failed_port_device_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - /* Register with the usb */ - retval = usb_register(&usb_driver); - if (retval) - goto failed_usb_register; - - return 0; - -failed_usb_register: - usb_serial_deregister(&moschip7720_2port_driver); - -failed_port_device_register: + retval = usb_serial_register_drivers(&usb_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit moschip7720_exit(void) { - usb_deregister(&usb_driver); - usb_serial_deregister(&moschip7720_2port_driver); + usb_serial_deregister_drivers(&usb_driver, serial_drivers); } module_init(moschip7720_init); diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 19b11cece6ba..b45522e12f68 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2638,7 +2638,6 @@ static struct usb_driver io_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = moschip_id_table_combined, - .no_dynamic_id = 1, }; static struct usb_serial_driver moschip7840_4port_device = { @@ -2647,7 +2646,6 @@ static struct usb_serial_driver moschip7840_4port_device = { .name = "mos7840", }, .description = DRIVER_DESC, - .usb_driver = &io_driver, .id_table = moschip_port_id_table, .num_ports = 4, .open = mos7840_open, @@ -2674,6 +2672,10 @@ static struct usb_serial_driver moschip7840_4port_device = { .read_int_callback = mos7840_interrupt_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &moschip7840_4port_device, NULL +}; + /**************************************************************************** * moschip7840_init * This is called by the module subsystem, or on startup to initialize us @@ -2684,24 +2686,12 @@ static int __init moschip7840_init(void) dbg("%s", " mos7840_init :entering.........."); - /* Register with the usb serial */ - retval = usb_serial_register(&moschip7840_4port_device); + retval = usb_serial_register_drivers(&io_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); - if (retval) - goto failed_port_device_register; - - dbg("%s", "Entering..."); - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - /* Register with the usb */ - retval = usb_register(&io_driver); - if (retval == 0) { - dbg("%s", "Leaving..."); - return 0; - } - usb_serial_deregister(&moschip7840_4port_device); -failed_port_device_register: + dbg("%s", "Leaving..."); return retval; } @@ -2714,9 +2704,7 @@ static void __exit moschip7840_exit(void) dbg("%s", " mos7840_exit :entering.........."); - usb_deregister(&io_driver); - - usb_serial_deregister(&moschip7840_4port_device); + usb_serial_deregister_drivers(&io_driver, serial_drivers); dbg("%s", "Entering..."); } diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c index e2bfecc46402..0af57d31ab82 100644 --- a/drivers/usb/serial/moto_modem.c +++ b/drivers/usb/serial/moto_modem.c @@ -36,7 +36,6 @@ static struct usb_driver moto_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver moto_device = { @@ -45,27 +44,21 @@ static struct usb_serial_driver moto_device = { .name = "moto-modem", }, .id_table = id_table, - .usb_driver = &moto_driver, .num_ports = 1, }; +static struct usb_serial_driver * const serial_drivers[] = { + &moto_device, NULL +}; + static int __init moto_init(void) { - int retval; - - retval = usb_serial_register(&moto_device); - if (retval) - return retval; - retval = usb_register(&moto_driver); - if (retval) - usb_serial_deregister(&moto_device); - return retval; + return usb_serial_register_drivers(&moto_driver, serial_drivers); } static void __exit moto_exit(void) { - usb_deregister(&moto_driver); - usb_serial_deregister(&moto_device); + usb_serial_deregister_drivers(&moto_driver, serial_drivers); } module_init(moto_init); From f667ddad41e303ebc2c6d5bf3105dffe2fbdd717 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Feb 2012 14:57:18 -0500 Subject: [PATCH 126/269] usb-serial: use new registration API in [n-p]* drivers This patch (as1527) modifies the following usb-serial drivers to utilize the new usb_serial_{de}register_drivers() routines: navman, omninet, opticon, option, oti6858, and pl2303. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/navman.c | 19 ++++++------------- drivers/usb/serial/omninet.c | 26 ++++++++++---------------- drivers/usb/serial/opticon.c | 19 ++++++------------- drivers/usb/serial/option.c | 27 +++++++++------------------ drivers/usb/serial/oti6858.c | 19 ++++++------------- drivers/usb/serial/pl2303.c | 23 ++++++++--------------- 6 files changed, 45 insertions(+), 88 deletions(-) diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index b28f1db0195f..fd4b2c833c0b 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c @@ -35,7 +35,6 @@ static struct usb_driver navman_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static void navman_read_int_callback(struct urb *urb) @@ -122,7 +121,6 @@ static struct usb_serial_driver navman_device = { .name = "navman", }, .id_table = id_table, - .usb_driver = &navman_driver, .num_ports = 1, .open = navman_open, .close = navman_close, @@ -130,23 +128,18 @@ static struct usb_serial_driver navman_device = { .read_int_callback = navman_read_int_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &navman_device, NULL +}; + static int __init navman_init(void) { - int retval; - - retval = usb_serial_register(&navman_device); - if (retval) - return retval; - retval = usb_register(&navman_driver); - if (retval) - usb_serial_deregister(&navman_device); - return retval; + return usb_serial_register_drivers(&navman_driver, serial_drivers); } static void __exit navman_exit(void) { - usb_deregister(&navman_driver); - usb_serial_deregister(&navman_device); + usb_serial_deregister_drivers(&navman_driver, serial_drivers); } module_init(navman_init); diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 033e8afa6c77..975d5c559ccb 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -62,7 +62,6 @@ static struct usb_driver omninet_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; @@ -72,7 +71,6 @@ static struct usb_serial_driver zyxel_omninet_device = { .name = "omninet", }, .description = "ZyXEL - omni.net lcd plus usb", - .usb_driver = &omninet_driver, .id_table = id_table, .num_ports = 1, .attach = omninet_attach, @@ -86,6 +84,10 @@ static struct usb_serial_driver zyxel_omninet_device = { .release = omninet_release, }; +static struct usb_serial_driver * const serial_drivers[] = { + &zyxel_omninet_device, NULL +}; + /* The protocol. * @@ -323,26 +325,18 @@ static void omninet_release(struct usb_serial *serial) static int __init omninet_init(void) { int retval; - retval = usb_serial_register(&zyxel_omninet_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&omninet_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&zyxel_omninet_device); -failed_usb_serial_register: + + retval = usb_serial_register_drivers(&omninet_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit omninet_exit(void) { - usb_deregister(&omninet_driver); - usb_serial_deregister(&zyxel_omninet_device); + usb_serial_deregister_drivers(&omninet_driver, serial_drivers); } diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 262ded9e076b..7001ad779b94 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -604,7 +604,6 @@ static struct usb_driver opticon_driver = { .suspend = opticon_suspend, .resume = opticon_resume, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver opticon_device = { @@ -613,7 +612,6 @@ static struct usb_serial_driver opticon_device = { .name = "opticon", }, .id_table = id_table, - .usb_driver = &opticon_driver, .num_ports = 1, .attach = opticon_startup, .open = opticon_open, @@ -629,23 +627,18 @@ static struct usb_serial_driver opticon_device = { .tiocmset = opticon_tiocmset, }; +static struct usb_serial_driver * const serial_drivers[] = { + &opticon_device, NULL +}; + static int __init opticon_init(void) { - int retval; - - retval = usb_serial_register(&opticon_device); - if (retval) - return retval; - retval = usb_register(&opticon_driver); - if (retval) - usb_serial_deregister(&opticon_device); - return retval; + return usb_serial_register_drivers(&opticon_driver, serial_drivers); } static void __exit opticon_exit(void) { - usb_deregister(&opticon_driver); - usb_serial_deregister(&opticon_device); + usb_serial_deregister_drivers(&opticon_driver, serial_drivers); } module_init(opticon_init); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index b54afceb9611..138a7b98cda4 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1212,7 +1212,6 @@ static struct usb_driver option_driver = { .supports_autosuspend = 1, #endif .id_table = option_ids, - .no_dynamic_id = 1, }; /* The card has three separate interfaces, which the serial driver @@ -1225,7 +1224,6 @@ static struct usb_serial_driver option_1port_device = { .name = "option1", }, .description = "GSM modem (1-port)", - .usb_driver = &option_driver, .id_table = option_ids, .num_ports = 1, .probe = option_probe, @@ -1249,6 +1247,10 @@ static struct usb_serial_driver option_1port_device = { #endif }; +static struct usb_serial_driver * const serial_drivers[] = { + &option_1port_device, NULL +}; + static bool debug; /* per port private data */ @@ -1284,28 +1286,17 @@ struct option_port_private { static int __init option_init(void) { int retval; - retval = usb_serial_register(&option_1port_device); - if (retval) - goto failed_1port_device_register; - retval = usb_register(&option_driver); - if (retval) - goto failed_driver_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; - -failed_driver_register: - usb_serial_deregister(&option_1port_device); -failed_1port_device_register: + retval = usb_serial_register_drivers(&option_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit option_exit(void) { - usb_deregister(&option_driver); - usb_serial_deregister(&option_1port_device); + usb_serial_deregister_drivers(&option_driver, serial_drivers); } module_init(option_init); diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 343e626a06f8..53f2768c9a36 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -71,7 +71,6 @@ static struct usb_driver oti6858_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static bool debug; @@ -157,7 +156,6 @@ static struct usb_serial_driver oti6858_device = { .name = "oti6858", }, .id_table = id_table, - .usb_driver = &oti6858_driver, .num_ports = 1, .open = oti6858_open, .close = oti6858_close, @@ -176,6 +174,10 @@ static struct usb_serial_driver oti6858_device = { .release = oti6858_release, }; +static struct usb_serial_driver * const serial_drivers[] = { + &oti6858_device, NULL +}; + struct oti6858_private { spinlock_t lock; @@ -960,21 +962,12 @@ static void oti6858_write_bulk_callback(struct urb *urb) static int __init oti6858_init(void) { - int retval; - - retval = usb_serial_register(&oti6858_device); - if (retval == 0) { - retval = usb_register(&oti6858_driver); - if (retval) - usb_serial_deregister(&oti6858_device); - } - return retval; + return usb_serial_register_drivers(&oti6858_driver, serial_drivers); } static void __exit oti6858_exit(void) { - usb_deregister(&oti6858_driver); - usb_serial_deregister(&oti6858_device); + usb_serial_deregister_drivers(&oti6858_driver, serial_drivers); } module_init(oti6858_init); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 3d8cda57ce7a..cc65d810c8f5 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -104,7 +104,6 @@ static struct usb_driver pl2303_driver = { .id_table = id_table, .suspend = usb_serial_suspend, .resume = usb_serial_resume, - .no_dynamic_id = 1, .supports_autosuspend = 1, }; @@ -834,7 +833,6 @@ static struct usb_serial_driver pl2303_device = { .name = "pl2303", }, .id_table = id_table, - .usb_driver = &pl2303_driver, .num_ports = 1, .bulk_in_size = 256, .bulk_out_size = 256, @@ -853,28 +851,23 @@ static struct usb_serial_driver pl2303_device = { .release = pl2303_release, }; +static struct usb_serial_driver * const serial_drivers[] = { + &pl2303_device, NULL +}; + static int __init pl2303_init(void) { int retval; - retval = usb_serial_register(&pl2303_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&pl2303_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&pl2303_device); -failed_usb_serial_register: + retval = usb_serial_register_drivers(&pl2303_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); return retval; } static void __exit pl2303_exit(void) { - usb_deregister(&pl2303_driver); - usb_serial_deregister(&pl2303_device); + usb_serial_deregister_drivers(&pl2303_driver, serial_drivers); } module_init(pl2303_init); From d860322f34e4a53f347b1aeae23d5b72f1e91b8c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Feb 2012 14:57:25 -0500 Subject: [PATCH 127/269] usb-serial: use new registration API in [q-s]* drivers This patch (as1528) modifies the following usb-serial drivers to utilize the new usb_serial_{de}register_drivers() routines: qcaux, qcserial, safe_serial, siemens_mpi, sierra, spcp8x5, ssu100, and symbolserial. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcaux.c | 19 ++++++------------- drivers/usb/serial/qcserial.c | 22 ++++++---------------- drivers/usb/serial/safe_serial.c | 24 +++++++----------------- drivers/usb/serial/siemens_mpi.c | 26 +++++++++++--------------- drivers/usb/serial/sierra.c | 29 +++++++++-------------------- drivers/usb/serial/spcp8x5.c | 26 ++++++++++---------------- drivers/usb/serial/ssu100.c | 31 +++++++++---------------------- drivers/usb/serial/symbolserial.c | 19 ++++++------------- 8 files changed, 64 insertions(+), 132 deletions(-) diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index a34819884c1a..a2ce274b3f28 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -82,7 +82,6 @@ static struct usb_driver qcaux_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver qcaux_device = { @@ -91,27 +90,21 @@ static struct usb_serial_driver qcaux_device = { .name = "qcaux", }, .id_table = id_table, - .usb_driver = &qcaux_driver, .num_ports = 1, }; +static struct usb_serial_driver * const serial_drivers[] = { + &qcaux_device, NULL +}; + static int __init qcaux_init(void) { - int retval; - - retval = usb_serial_register(&qcaux_device); - if (retval) - return retval; - retval = usb_register(&qcaux_driver); - if (retval) - usb_serial_deregister(&qcaux_device); - return retval; + return usb_serial_register_drivers(&qcaux_driver, serial_drivers); } static void __exit qcaux_exit(void) { - usb_deregister(&qcaux_driver); - usb_serial_deregister(&qcaux_device); + usb_serial_deregister_drivers(&qcaux_driver, serial_drivers); } module_init(qcaux_init); diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index f98800f2324c..70e9f1abdad1 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -246,7 +246,6 @@ static struct usb_serial_driver qcdevice = { }, .description = "Qualcomm USB modem", .id_table = id_table, - .usb_driver = &qcdriver, .num_ports = 1, .probe = qcprobe, .open = usb_wwan_open, @@ -263,27 +262,18 @@ static struct usb_serial_driver qcdevice = { #endif }; +static struct usb_serial_driver * const serial_drivers[] = { + &qcdevice, NULL +}; + static int __init qcinit(void) { - int retval; - - retval = usb_serial_register(&qcdevice); - if (retval) - return retval; - - retval = usb_register(&qcdriver); - if (retval) { - usb_serial_deregister(&qcdevice); - return retval; - } - - return 0; + return usb_serial_register_drivers(&qcdriver, serial_drivers); } static void __exit qcexit(void) { - usb_deregister(&qcdriver); - usb_serial_deregister(&qcdevice); + usb_serial_deregister_drivers(&qcdriver, serial_drivers); } module_init(qcinit); diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index d074b3740dcb..ae4ee30c7411 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c @@ -156,7 +156,6 @@ static struct usb_driver safe_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static const __u16 crc10_table[256] = { @@ -309,16 +308,19 @@ static struct usb_serial_driver safe_device = { .name = "safe_serial", }, .id_table = id_table, - .usb_driver = &safe_driver, .num_ports = 1, .process_read_urb = safe_process_read_urb, .prepare_write_buffer = safe_prepare_write_buffer, .attach = safe_startup, }; +static struct usb_serial_driver * const serial_drivers[] = { + &safe_device, NULL +}; + static int __init safe_init(void) { - int i, retval; + int i; printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" DRIVER_DESC "\n"); @@ -337,24 +339,12 @@ static int __init safe_init(void) } } - retval = usb_serial_register(&safe_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&safe_driver); - if (retval) - goto failed_usb_register; - - return 0; -failed_usb_register: - usb_serial_deregister(&safe_device); -failed_usb_serial_register: - return retval; + return usb_serial_register_drivers(&safe_driver, serial_drivers); } static void __exit safe_exit(void) { - usb_deregister(&safe_driver); - usb_serial_deregister(&safe_device); + usb_serial_deregister_drivers(&safe_driver, serial_drivers); } module_init(safe_init); diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c index 74cd4ccdb3fc..8aa4c1aef6d1 100644 --- a/drivers/usb/serial/siemens_mpi.c +++ b/drivers/usb/serial/siemens_mpi.c @@ -42,33 +42,29 @@ static struct usb_serial_driver siemens_usb_mpi_device = { .name = "siemens_mpi", }, .id_table = id_table, - .usb_driver = &siemens_usb_mpi_driver, .num_ports = 1, }; +static struct usb_serial_driver * const serial_drivers[] = { + &siemens_usb_mpi_device, NULL +}; + static int __init siemens_usb_mpi_init(void) { int retval; - retval = usb_serial_register(&siemens_usb_mpi_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&siemens_usb_mpi_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO DRIVER_DESC "\n"); - printk(KERN_INFO DRIVER_VERSION " " DRIVER_AUTHOR "\n"); - return retval; -failed_usb_register: - usb_serial_deregister(&siemens_usb_mpi_device); -failed_usb_serial_register: + retval = usb_serial_register_drivers(&siemens_usb_mpi_driver, + serial_drivers); + if (retval == 0) { + printk(KERN_INFO DRIVER_DESC "\n"); + printk(KERN_INFO DRIVER_VERSION " " DRIVER_AUTHOR "\n"); + } return retval; } static void __exit siemens_usb_mpi_exit(void) { - usb_deregister(&siemens_usb_mpi_driver); - usb_serial_deregister(&siemens_usb_mpi_device); + usb_serial_deregister_drivers(&siemens_usb_mpi_driver, serial_drivers); } module_init(siemens_usb_mpi_init); diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index fdae0a4407cb..d75a75b83e9f 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -1084,7 +1084,6 @@ static struct usb_driver sierra_driver = { .resume = usb_serial_resume, .reset_resume = sierra_reset_resume, .id_table = id_table, - .no_dynamic_id = 1, .supports_autosuspend = 1, }; @@ -1095,7 +1094,6 @@ static struct usb_serial_driver sierra_device = { }, .description = "Sierra USB modem", .id_table = id_table, - .usb_driver = &sierra_driver, .calc_num_ports = sierra_calc_num_ports, .probe = sierra_probe, .open = sierra_open, @@ -1113,34 +1111,25 @@ static struct usb_serial_driver sierra_device = { .read_int_callback = sierra_instat_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &sierra_device, NULL +}; + /* Functions used by new usb-serial code. */ static int __init sierra_init(void) { int retval; - retval = usb_serial_register(&sierra_device); - if (retval) - goto failed_device_register; - - retval = usb_register(&sierra_driver); - if (retval) - goto failed_driver_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; - -failed_driver_register: - usb_serial_deregister(&sierra_device); -failed_device_register: + retval = usb_serial_register_drivers(&sierra_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit sierra_exit(void) { - usb_deregister(&sierra_driver); - usb_serial_deregister(&sierra_device); + usb_serial_deregister_drivers(&sierra_driver, serial_drivers); } module_init(sierra_init); diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index d7f5eee18f00..af898937d4b1 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -156,7 +156,6 @@ static struct usb_driver spcp8x5_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; @@ -649,7 +648,6 @@ static struct usb_serial_driver spcp8x5_device = { .name = "SPCP8x5", }, .id_table = id_table, - .usb_driver = &spcp8x5_driver, .num_ports = 1, .open = spcp8x5_open, .dtr_rts = spcp8x5_dtr_rts, @@ -664,28 +662,24 @@ static struct usb_serial_driver spcp8x5_device = { .process_read_urb = spcp8x5_process_read_urb, }; +static struct usb_serial_driver * const serial_drivers[] = { + &spcp8x5_device, NULL +}; + static int __init spcp8x5_init(void) { int retval; - retval = usb_serial_register(&spcp8x5_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&spcp8x5_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&spcp8x5_device); -failed_usb_serial_register: + + retval = usb_serial_register_drivers(&spcp8x5_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit spcp8x5_exit(void) { - usb_deregister(&spcp8x5_driver); - usb_serial_deregister(&spcp8x5_device); + usb_serial_deregister_drivers(&spcp8x5_driver, serial_drivers); } module_init(spcp8x5_init); diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 7697858d8858..ab8842107a8b 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -70,7 +70,6 @@ static struct usb_driver ssu100_driver = { .id_table = id_table, .suspend = usb_serial_suspend, .resume = usb_serial_resume, - .no_dynamic_id = 1, .supports_autosuspend = 1, }; @@ -677,7 +676,6 @@ static struct usb_serial_driver ssu100_device = { }, .description = DRIVER_DESC, .id_table = id_table, - .usb_driver = &ssu100_driver, .num_ports = 1, .open = ssu100_open, .close = ssu100_close, @@ -693,37 +691,26 @@ static struct usb_serial_driver ssu100_device = { .disconnect = usb_serial_generic_disconnect, }; +static struct usb_serial_driver * const serial_drivers[] = { + &ssu100_device, NULL +}; + static int __init ssu100_init(void) { int retval; dbg("%s", __func__); - /* register with usb-serial */ - retval = usb_serial_register(&ssu100_device); - - if (retval) - goto failed_usb_sio_register; - - retval = usb_register(&ssu100_driver); - if (retval) - goto failed_usb_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; - -failed_usb_register: - usb_serial_deregister(&ssu100_device); -failed_usb_sio_register: + retval = usb_serial_register_drivers(&ssu100_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit ssu100_exit(void) { - usb_deregister(&ssu100_driver); - usb_serial_deregister(&ssu100_device); + usb_serial_deregister_drivers(&ssu100_driver, serial_drivers); } module_init(ssu100_init); diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index 50651cf4fc61..76cd9f2a08c0 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -287,7 +287,6 @@ static struct usb_driver symbol_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver symbol_device = { @@ -296,7 +295,6 @@ static struct usb_serial_driver symbol_device = { .name = "symbol", }, .id_table = id_table, - .usb_driver = &symbol_driver, .num_ports = 1, .attach = symbol_startup, .open = symbol_open, @@ -307,23 +305,18 @@ static struct usb_serial_driver symbol_device = { .unthrottle = symbol_unthrottle, }; +static struct usb_serial_driver * const serial_drivers[] = { + &symbol_device, NULL +}; + static int __init symbol_init(void) { - int retval; - - retval = usb_serial_register(&symbol_device); - if (retval) - return retval; - retval = usb_register(&symbol_driver); - if (retval) - usb_serial_deregister(&symbol_device); - return retval; + return usb_serial_register_drivers(&symbol_driver, serial_drivers); } static void __exit symbol_exit(void) { - usb_deregister(&symbol_driver); - usb_serial_deregister(&symbol_device); + usb_serial_deregister_drivers(&symbol_driver, serial_drivers); } module_init(symbol_init); From 29618e9fb5507b9fcf07f739a8506a3640495945 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Feb 2012 14:57:32 -0500 Subject: [PATCH 128/269] usb-serial: use new registration API in [t-z]* drivers This patch (as1529) modifies the following usb-serial drivers to utilize the new usb_serial_{de}register_drivers() routines: ti_usb_3410_5052, usb_debug, visor, vivopay-serial, whiteheat, and zio. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 35 ++++++------------------- drivers/usb/serial/usb_debug.c | 19 +++++--------- drivers/usb/serial/visor.c | 37 ++++++--------------------- drivers/usb/serial/vivopay-serial.c | 27 ++++++++----------- drivers/usb/serial/whiteheat.c | 32 +++++++---------------- drivers/usb/serial/zio.c | 19 +++++--------- 6 files changed, 48 insertions(+), 121 deletions(-) diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 74f2c7746cc4..ab74123d658e 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -216,7 +216,6 @@ static struct usb_driver ti_usb_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = ti_id_table_combined, - .no_dynamic_id = 1, }; static struct usb_serial_driver ti_1port_device = { @@ -225,7 +224,6 @@ static struct usb_serial_driver ti_1port_device = { .name = "ti_usb_3410_5052_1", }, .description = "TI USB 3410 1 port adapter", - .usb_driver = &ti_usb_driver, .id_table = ti_id_table_3410, .num_ports = 1, .attach = ti_startup, @@ -254,7 +252,6 @@ static struct usb_serial_driver ti_2port_device = { .name = "ti_usb_3410_5052_2", }, .description = "TI USB 5052 2 port adapter", - .usb_driver = &ti_usb_driver, .id_table = ti_id_table_5052, .num_ports = 2, .attach = ti_startup, @@ -277,6 +274,9 @@ static struct usb_serial_driver ti_2port_device = { .write_bulk_callback = ti_bulk_out_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &ti_1port_device, &ti_2port_device, NULL +}; /* Module */ @@ -344,36 +344,17 @@ static int __init ti_init(void) ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE; } - ret = usb_serial_register(&ti_1port_device); - if (ret) - goto failed_1port; - ret = usb_serial_register(&ti_2port_device); - if (ret) - goto failed_2port; - - ret = usb_register(&ti_usb_driver); - if (ret) - goto failed_usb; - - printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":" - TI_DRIVER_DESC "\n"); - - return 0; - -failed_usb: - usb_serial_deregister(&ti_2port_device); -failed_2port: - usb_serial_deregister(&ti_1port_device); -failed_1port: + ret = usb_serial_register_drivers(&ti_usb_driver, serial_drivers); + if (ret == 0) + printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":" + TI_DRIVER_DESC "\n"); return ret; } static void __exit ti_exit(void) { - usb_deregister(&ti_usb_driver); - usb_serial_deregister(&ti_1port_device); - usb_serial_deregister(&ti_2port_device); + usb_serial_deregister_drivers(&ti_usb_driver, serial_drivers); } diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index 9b632e753210..5b29b4a2ebc7 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -40,7 +40,6 @@ static struct usb_driver debug_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; /* This HW really does not support a serial break, so one will be @@ -74,30 +73,24 @@ static struct usb_serial_driver debug_device = { .name = "debug", }, .id_table = id_table, - .usb_driver = &debug_driver, .num_ports = 1, .bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE, .break_ctl = usb_debug_break_ctl, .process_read_urb = usb_debug_process_read_urb, }; +static struct usb_serial_driver * const serial_drivers[] = { + &debug_device, NULL +}; + static int __init debug_init(void) { - int retval; - - retval = usb_serial_register(&debug_device); - if (retval) - return retval; - retval = usb_register(&debug_driver); - if (retval) - usb_serial_deregister(&debug_device); - return retval; + return usb_serial_register_drivers(&debug_driver, serial_drivers); } static void __exit debug_exit(void) { - usb_deregister(&debug_driver); - usb_serial_deregister(&debug_device); + usb_serial_deregister_drivers(&debug_driver, serial_drivers); } module_init(debug_init); diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 210e4b10dc11..71d696474f24 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -173,7 +173,6 @@ static struct usb_driver visor_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; /* All of the device info needed for the Handspring Visor, @@ -184,7 +183,6 @@ static struct usb_serial_driver handspring_device = { .name = "visor", }, .description = "Handspring Visor / Palm OS", - .usb_driver = &visor_driver, .id_table = id_table, .num_ports = 2, .bulk_out_size = 256, @@ -205,7 +203,6 @@ static struct usb_serial_driver clie_5_device = { .name = "clie_5", }, .description = "Sony Clie 5.0", - .usb_driver = &visor_driver, .id_table = clie_id_5_table, .num_ports = 2, .bulk_out_size = 256, @@ -226,7 +223,6 @@ static struct usb_serial_driver clie_3_5_device = { .name = "clie_3.5", }, .description = "Sony Clie 3.5", - .usb_driver = &visor_driver, .id_table = clie_id_3_5_table, .num_ports = 1, .bulk_out_size = 256, @@ -237,6 +233,10 @@ static struct usb_serial_driver clie_3_5_device = { .attach = clie_3_5_startup, }; +static struct usb_serial_driver * const serial_drivers[] = { + &handspring_device, &clie_5_device, &clie_3_5_device, NULL +}; + /****************************************************************************** * Handspring Visor specific driver functions ******************************************************************************/ @@ -685,38 +685,17 @@ static int __init visor_init(void) ": Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x\n", vendor, product); } - retval = usb_serial_register(&handspring_device); - if (retval) - goto failed_handspring_register; - retval = usb_serial_register(&clie_3_5_device); - if (retval) - goto failed_clie_3_5_register; - retval = usb_serial_register(&clie_5_device); - if (retval) - goto failed_clie_5_register; - retval = usb_register(&visor_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&clie_5_device); -failed_clie_5_register: - usb_serial_deregister(&clie_3_5_device); -failed_clie_3_5_register: - usb_serial_deregister(&handspring_device); -failed_handspring_register: + retval = usb_serial_register_drivers(&visor_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); return retval; } static void __exit visor_exit (void) { - usb_deregister(&visor_driver); - usb_serial_deregister(&handspring_device); - usb_serial_deregister(&clie_3_5_device); - usb_serial_deregister(&clie_5_device); + usb_serial_deregister_drivers(&visor_driver, serial_drivers); } diff --git a/drivers/usb/serial/vivopay-serial.c b/drivers/usb/serial/vivopay-serial.c index f719d00972fc..a6f113bd4fae 100644 --- a/drivers/usb/serial/vivopay-serial.c +++ b/drivers/usb/serial/vivopay-serial.c @@ -30,7 +30,6 @@ static struct usb_driver vivopay_serial_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver vivopay_serial_device = { @@ -39,32 +38,28 @@ static struct usb_serial_driver vivopay_serial_device = { .name = "vivopay-serial", }, .id_table = id_table, - .usb_driver = &vivopay_serial_driver, .num_ports = 1, }; +static struct usb_serial_driver * const serial_drivers[] = { + &vivopay_serial_device, NULL +}; + static int __init vivopay_serial_init(void) { int retval; - retval = usb_serial_register(&vivopay_serial_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&vivopay_serial_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&vivopay_serial_device); -failed_usb_serial_register: + + retval = usb_serial_register_drivers(&vivopay_serial_driver, + serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit vivopay_serial_exit(void) { - usb_deregister(&vivopay_serial_driver); - usb_serial_deregister(&vivopay_serial_device); + usb_serial_deregister_drivers(&vivopay_serial_driver, serial_drivers); } module_init(vivopay_serial_init); diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 007cf3a2481a..a29be37a3a67 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -83,7 +83,6 @@ static struct usb_driver whiteheat_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; /* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */ @@ -121,7 +120,6 @@ static struct usb_serial_driver whiteheat_fake_device = { .name = "whiteheatnofirm", }, .description = "Connect Tech - WhiteHEAT - (prerenumeration)", - .usb_driver = &whiteheat_driver, .id_table = id_table_prerenumeration, .num_ports = 1, .probe = whiteheat_firmware_download, @@ -134,7 +132,6 @@ static struct usb_serial_driver whiteheat_device = { .name = "whiteheat", }, .description = "Connect Tech - WhiteHEAT", - .usb_driver = &whiteheat_driver, .id_table = id_table_std, .num_ports = 4, .attach = whiteheat_attach, @@ -155,6 +152,9 @@ static struct usb_serial_driver whiteheat_device = { .write_bulk_callback = whiteheat_write_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &whiteheat_fake_device, &whiteheat_device, NULL +}; struct whiteheat_command_private { struct mutex mutex; @@ -1461,32 +1461,18 @@ out: static int __init whiteheat_init(void) { int retval; - retval = usb_serial_register(&whiteheat_fake_device); - if (retval) - goto failed_fake_register; - retval = usb_serial_register(&whiteheat_device); - if (retval) - goto failed_device_register; - retval = usb_register(&whiteheat_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: - usb_serial_deregister(&whiteheat_device); -failed_device_register: - usb_serial_deregister(&whiteheat_fake_device); -failed_fake_register: + + retval = usb_serial_register_drivers(&whiteheat_driver, serial_drivers); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit whiteheat_exit(void) { - usb_deregister(&whiteheat_driver); - usb_serial_deregister(&whiteheat_fake_device); - usb_serial_deregister(&whiteheat_device); + usb_serial_deregister_drivers(&whiteheat_driver, serial_drivers); } diff --git a/drivers/usb/serial/zio.c b/drivers/usb/serial/zio.c index f57967278833..ae8115aab77d 100644 --- a/drivers/usb/serial/zio.c +++ b/drivers/usb/serial/zio.c @@ -27,7 +27,6 @@ static struct usb_driver zio_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver zio_device = { @@ -36,27 +35,21 @@ static struct usb_serial_driver zio_device = { .name = "zio", }, .id_table = id_table, - .usb_driver = &zio_driver, .num_ports = 1, }; +static struct usb_serial_driver * const serial_drivers[] = { + &zio_device, NULL +}; + static int __init zio_init(void) { - int retval; - - retval = usb_serial_register(&zio_device); - if (retval) - return retval; - retval = usb_register(&zio_driver); - if (retval) - usb_serial_deregister(&zio_device); - return retval; + return usb_serial_register_drivers(&zio_driver, serial_drivers); } static void __exit zio_exit(void) { - usb_deregister(&zio_driver); - usb_serial_deregister(&zio_device); + usb_serial_deregister_drivers(&zio_driver, serial_drivers); } module_init(zio_init); From 69276a33bd1d272dc9c3bd577038954811bd1831 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Feb 2012 14:57:37 -0500 Subject: [PATCH 129/269] usb-serial: use new registration API in staging drivers This patch (as1530) modifies the following usb-serial drivers from drivers/staging to utilize the new usb_serial_{de}register_drivers() routines: quatech_usb2 and serqt_usb2. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/staging/quatech_usb2/quatech_usb2.c | 32 +++++++-------------- drivers/staging/serqt_usb2/serqt_usb2.c | 30 ++++++------------- 2 files changed, 19 insertions(+), 43 deletions(-) diff --git a/drivers/staging/quatech_usb2/quatech_usb2.c b/drivers/staging/quatech_usb2/quatech_usb2.c index 897a3a99c794..b8a078abd6c7 100644 --- a/drivers/staging/quatech_usb2/quatech_usb2.c +++ b/drivers/staging/quatech_usb2/quatech_usb2.c @@ -135,7 +135,6 @@ static struct usb_driver quausb2_usb_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = quausb2_id_table, - .no_dynamic_id = 1, }; /** @@ -1942,7 +1941,6 @@ static struct usb_serial_driver quatech2_device = { .name = "quatech_usb2", }, .description = DRIVER_DESC, - .usb_driver = &quausb2_usb_driver, .id_table = quausb2_id_table, .num_ports = 8, .open = qt2_open, @@ -1964,37 +1962,27 @@ static struct usb_serial_driver quatech2_device = { .write_bulk_callback = qt2_write_bulk_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &quatech2_device, NULL +}; + static int __init quausb2_usb_init(void) { int retval; dbg("%s\n", __func__); - /* register with usb-serial */ - retval = usb_serial_register(&quatech2_device); - - if (retval) - goto failed_usb_serial_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - /* register with usb */ - - retval = usb_register(&quausb2_usb_driver); + retval = usb_serial_register_drivers(&quausb2_usb_driver, + serial_drivers); if (retval == 0) - return 0; - - /* if we're here, usb_register() failed */ - usb_serial_deregister(&quatech2_device); -failed_usb_serial_register: - return retval; + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); + return retval; } static void __exit quausb2_usb_exit(void) { - usb_deregister(&quausb2_usb_driver); - usb_serial_deregister(&quatech2_device); + usb_serial_deregister_drivers(&quausb2_usb_driver, serial_drivers); } module_init(quausb2_usb_init); diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c index 1c5780f1571b..04b6be86df1a 100644 --- a/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/drivers/staging/serqt_usb2/serqt_usb2.c @@ -200,7 +200,6 @@ static struct usb_driver serqt_usb_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = serqt_id_table, - .no_dynamic_id = 1, }; static int port_paranoia_check(struct usb_serial_port *port, @@ -1590,7 +1589,6 @@ static struct usb_serial_driver quatech_device = { .name = "serqt", }, .description = DRIVER_DESC, - .usb_driver = &serqt_usb_driver, .id_table = serqt_id_table, .num_ports = 8, .open = qt_open, @@ -1610,37 +1608,27 @@ static struct usb_serial_driver quatech_device = { .release = qt_release, }; +static struct usb_serial_driver * const serial_drivers[] = { + &quatech_device, NULL +}; + static int __init serqt_usb_init(void) { int retval; dbg("%s\n", __func__); - /* register with usb-serial */ - retval = usb_serial_register(&quatech_device); - - if (retval) - goto failed_usb_serial_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - /* register with usb */ - - retval = usb_register(&serqt_usb_driver); + retval = usb_serial_register_drivers(&serqt_usb_driver, + serial_drivers); if (retval == 0) - return 0; - - /* if we're here, usb_register() failed */ - usb_serial_deregister(&quatech_device); -failed_usb_serial_register: + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); return retval; } static void __exit serqt_usb_exit(void) { - usb_deregister(&serqt_usb_driver); - usb_serial_deregister(&quatech_device); + usb_serial_deregister_drivers(&serqt_usb_driver, serial_drivers); } module_init(serqt_usb_init); From 8c49fc99b67eab0f75c3353406745d379c782121 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Feb 2012 12:49:34 -0800 Subject: [PATCH 130/269] usb-serial: use new registration API in keyspan_pda.c This was missed in Alan's last round of conversions. Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan_pda.c | 61 ++++++++------------------------ 1 file changed, 14 insertions(+), 47 deletions(-) diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 7c62a7048302..b88a7906d4c2 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -91,7 +91,6 @@ static struct usb_driver keyspan_pda_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, }; static const struct usb_device_id id_table_std[] = { @@ -779,7 +778,6 @@ static struct usb_serial_driver keyspan_pda_fake_device = { .name = "keyspan_pda_pre", }, .description = "Keyspan PDA - (prerenumeration)", - .usb_driver = &keyspan_pda_driver, .id_table = id_table_fake, .num_ports = 1, .attach = keyspan_pda_fake_startup, @@ -793,7 +791,6 @@ static struct usb_serial_driver xircom_pgs_fake_device = { .name = "xircom_no_firm", }, .description = "Xircom / Entregra PGS - (prerenumeration)", - .usb_driver = &keyspan_pda_driver, .id_table = id_table_fake_xircom, .num_ports = 1, .attach = keyspan_pda_fake_startup, @@ -806,7 +803,6 @@ static struct usb_serial_driver keyspan_pda_device = { .name = "keyspan_pda", }, .description = "Keyspan PDA", - .usb_driver = &keyspan_pda_driver, .id_table = id_table_std, .num_ports = 1, .dtr_rts = keyspan_pda_dtr_rts, @@ -827,56 +823,27 @@ static struct usb_serial_driver keyspan_pda_device = { .release = keyspan_pda_release, }; +static struct usb_serial_driver * const serial_drivers[] = { + &keyspan_pda_device, +#ifdef KEYSPAN + &keyspan_pda_fake_device, +#endif +#ifdef XIRCOM + &xircom_pgs_fake_device, +#endif + NULL +}; static int __init keyspan_pda_init(void) { - int retval; - retval = usb_serial_register(&keyspan_pda_device); - if (retval) - goto failed_pda_register; -#ifdef KEYSPAN - retval = usb_serial_register(&keyspan_pda_fake_device); - if (retval) - goto failed_pda_fake_register; -#endif -#ifdef XIRCOM - retval = usb_serial_register(&xircom_pgs_fake_device); - if (retval) - goto failed_xircom_register; -#endif - retval = usb_register(&keyspan_pda_driver); - if (retval) - goto failed_usb_register; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -failed_usb_register: -#ifdef XIRCOM - usb_serial_deregister(&xircom_pgs_fake_device); -failed_xircom_register: -#endif /* XIRCOM */ -#ifdef KEYSPAN - usb_serial_deregister(&keyspan_pda_fake_device); -#endif -#ifdef KEYSPAN -failed_pda_fake_register: -#endif - usb_serial_deregister(&keyspan_pda_device); -failed_pda_register: - return retval; + return usb_serial_register_drivers(&keyspan_pda_driver, + serial_drivers); } - static void __exit keyspan_pda_exit(void) { - usb_deregister(&keyspan_pda_driver); - usb_serial_deregister(&keyspan_pda_device); -#ifdef KEYSPAN - usb_serial_deregister(&keyspan_pda_fake_device); -#endif -#ifdef XIRCOM - usb_serial_deregister(&xircom_pgs_fake_device); -#endif + usb_serial_deregister_drivers(&keyspan_pda_driver, + serial_drivers); } From f799e7678390029e322ae2dc3cda389b11f38124 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Feb 2012 12:50:30 -0800 Subject: [PATCH 131/269] USB: serial: remove usb_serial_register and usb_serial_deregister No one uses them anymore, they should be using the safer usb_serial_register_drivers() and usb_serial_deregister_drivers() functions instead. Thanks to Alan Stern for writing these functions and porting all in-kernel users to them. Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 12 ++---------- include/linux/usb/serial.h | 7 ------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 45b3658c601f..63ba47dbcc71 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1338,12 +1338,7 @@ static void fixup_generic(struct usb_serial_driver *device) set_to_generic_if_null(device, prepare_write_buffer); } -/* - * The next two routines are mainly for internal use. - * They are exported only for out-of-tree modules. - * New drivers should call usb_serial_{de}register_drivers() instead. - */ -int usb_serial_register(struct usb_serial_driver *driver) +static int usb_serial_register(struct usb_serial_driver *driver) { int retval; @@ -1377,10 +1372,8 @@ int usb_serial_register(struct usb_serial_driver *driver) mutex_unlock(&table_lock); return retval; } -EXPORT_SYMBOL_GPL(usb_serial_register); - -void usb_serial_deregister(struct usb_serial_driver *device) +static void usb_serial_deregister(struct usb_serial_driver *device) { printk(KERN_INFO "USB Serial deregistering driver %s\n", device->description); @@ -1389,7 +1382,6 @@ void usb_serial_deregister(struct usb_serial_driver *device) usb_serial_bus_deregister(device); mutex_unlock(&table_lock); } -EXPORT_SYMBOL_GPL(usb_serial_deregister); /** * usb_serial_register_drivers - register drivers for a usb-serial module diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 8c8dbf9c5b89..34c06a723dcc 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -300,13 +300,6 @@ struct usb_serial_driver { #define to_usb_serial_driver(d) \ container_of(d, struct usb_serial_driver, driver) -/* - * These two routines are kept only for backward compatibility. - * Don't use them; call usb_serial_{de}register_drivers() instead. - */ -extern int usb_serial_register(struct usb_serial_driver *driver); -extern void usb_serial_deregister(struct usb_serial_driver *driver); - extern int usb_serial_register_drivers(struct usb_driver *udriver, struct usb_serial_driver * const serial_drivers[]); extern void usb_serial_deregister_drivers(struct usb_driver *udriver, From c192c8e71a2ded01170c1a992cd21aaedc822756 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 24 Feb 2012 13:08:43 -0600 Subject: [PATCH 132/269] USB: qcserial: don't grab QMI port on Gobi 1000 devices Gobi 1000 devices have a different port layout, which wasn't respected by the current driver, and thus it grabbed the QMI/net port. In the near future we'll be attaching another driver to the QMI/net port for these devices (cdc-wdm and qmi_wwan) so make sure the qcserial driver doesn't claim them. This patch also prevents qcserial from binding to interfaces 0 and 1 on 1K devices because those interfaces do not respond. Signed-off-by: Dan Williams Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcserial.c | 105 ++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 43 deletions(-) diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 70e9f1abdad1..4f3a5a794884 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -24,39 +24,44 @@ static bool debug; +#define DEVICE_G1K(v, p) \ + USB_DEVICE(v, p), .driver_info = 1 + static const struct usb_device_id id_table[] = { - {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ - {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ - {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */ - {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ - {USB_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ - {USB_DEVICE(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */ - {USB_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ - {USB_DEVICE(0x413c, 0x8171)}, /* Dell Gobi QDL device */ - {USB_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ - {USB_DEVICE(0x1410, 0xa008)}, /* Novatel Gobi QDL device */ - {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi QDL device */ - {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi QDL device */ - {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi QDL device */ - {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi QDL device */ - {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi QDL device */ - {USB_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ - {USB_DEVICE(0x0b05, 0x1774)}, /* Asus Gobi QDL device */ - {USB_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ - {USB_DEVICE(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */ - {USB_DEVICE(0x1557, 0x0a80)}, /* OQO Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9008)}, /* Generic Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9201)}, /* Generic Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ - {USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ + /* Gobi 1000 devices */ + {DEVICE_G1K(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ + {DEVICE_G1K(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ + {DEVICE_G1K(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */ + {DEVICE_G1K(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ + {DEVICE_G1K(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */ + {DEVICE_G1K(0x413c, 0x8172)}, /* Dell Gobi Modem device */ + {DEVICE_G1K(0x413c, 0x8171)}, /* Dell Gobi QDL device */ + {DEVICE_G1K(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ + {DEVICE_G1K(0x1410, 0xa008)}, /* Novatel Gobi QDL device */ + {DEVICE_G1K(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ + {DEVICE_G1K(0x0b05, 0x1774)}, /* Asus Gobi QDL device */ + {DEVICE_G1K(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ + {DEVICE_G1K(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */ + {DEVICE_G1K(0x1557, 0x0a80)}, /* OQO Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9008)}, /* Generic Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9201)}, /* Generic Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ + {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ + + /* Gobi 2000 devices */ + {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */ + {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi 2000 QDL device */ + {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi 2000 QDL device */ + {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi 2000 QDL device */ + {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi 2000 QDL device */ {USB_DEVICE(0x413c, 0x8185)}, /* Dell Gobi 2000 QDL device (N0218, VU936) */ {USB_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */ {USB_DEVICE(0x05c6, 0x9208)}, /* Generic Gobi 2000 QDL device */ @@ -92,6 +97,8 @@ static const struct usb_device_id id_table[] = { {USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */ {USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ + /* Gobi 3000 devices */ + {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Gobi 3000 QDL */ {USB_DEVICE(0x05c6, 0x920c)}, /* Gobi 3000 QDL */ {USB_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */ {USB_DEVICE(0x1410, 0xa020)}, /* Novatel Gobi 3000 QDL */ @@ -122,8 +129,10 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) int retval = -ENODEV; __u8 nintf; __u8 ifnum; + bool is_gobi1k = id->driver_info ? true : false; dbg("%s", __func__); + dbg("Is Gobi 1000 = %d", is_gobi1k); nintf = serial->dev->actconfig->desc.bNumInterfaces; dbg("Num Interfaces = %d", nintf); @@ -169,15 +178,25 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) case 3: case 4: - /* Composite mode */ - /* ifnum == 0 is a broadband network adapter */ - if (ifnum == 1) { - /* - * Diagnostics Monitor (serial line 9600 8N1) - * Qualcomm DM protocol - * use "libqcdm" (ModemManager) for communication - */ - dbg("Diagnostics Monitor found"); + /* Composite mode; don't bind to the QMI/net interface as that + * gets handled by other drivers. + */ + + /* Gobi 1K USB layout: + * 0: serial port (doesn't respond) + * 1: serial port (doesn't respond) + * 2: AT-capable modem port + * 3: QMI/net + * + * Gobi 2K+ USB layout: + * 0: QMI/net + * 1: DM/DIAG (use libqcdm from ModemManager for communication) + * 2: AT-capable modem port + * 3: NMEA + */ + + if (ifnum == 1 && !is_gobi1k) { + dbg("Gobi 2K+ DM/DIAG interface found"); retval = usb_set_interface(serial->dev, ifnum, 0); if (retval < 0) { dev_err(&serial->dev->dev, @@ -196,13 +215,13 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) retval = -ENODEV; kfree(data); } - } else if (ifnum==3) { + } else if (ifnum==3 && !is_gobi1k) { /* * NMEA (serial line 9600 8N1) * # echo "\$GPS_START" > /dev/ttyUSBx * # echo "\$GPS_STOP" > /dev/ttyUSBx */ - dbg("NMEA GPS interface found"); + dbg("Gobi 2K+ NMEA GPS interface found"); retval = usb_set_interface(serial->dev, ifnum, 0); if (retval < 0) { dev_err(&serial->dev->dev, From 711c68b3c0f7a924ffbee4aa962d8f62b85188ff Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 12 Feb 2012 06:00:41 +0000 Subject: [PATCH 133/269] cdc-wdm: Fix more races on the read path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We must not allow the input buffer length to change while we're shuffling the buffer contents. We also mustn't clear the WDM_READ flag after more data might have arrived. Therefore move both of these into the spinlocked region at the bottom of wdm_read(). When reading desc->length without holding the iuspin lock, use ACCESS_ONCE() to ensure the compiler doesn't re-read it with inconsistent results. Signed-off-by: Ben Hutchings Tested-by: Bjørn Mork Cc: Oliver Neukum Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index b27bbb957e16..7ca54d4dea92 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -391,7 +391,7 @@ outnl: static ssize_t wdm_read (struct file *file, char __user *buffer, size_t count, loff_t *ppos) { - int rv, cntr = 0; + int rv, cntr; int i = 0; struct wdm_device *desc = file->private_data; @@ -400,7 +400,8 @@ static ssize_t wdm_read if (rv < 0) return -ERESTARTSYS; - if (desc->length == 0) { + cntr = ACCESS_ONCE(desc->length); + if (cntr == 0) { desc->read = 0; retry: if (test_bit(WDM_DISCONNECTING, &desc->flags)) { @@ -455,25 +456,30 @@ retry: goto retry; } clear_bit(WDM_READ, &desc->flags); + cntr = desc->length; spin_unlock_irq(&desc->iuspin); } - cntr = count > desc->length ? desc->length : count; + if (cntr > count) + cntr = count; rv = copy_to_user(buffer, desc->ubuf, cntr); if (rv > 0) { rv = -EFAULT; goto err; } + spin_lock_irq(&desc->iuspin); + for (i = 0; i < desc->length - cntr; i++) desc->ubuf[i] = desc->ubuf[i + cntr]; - spin_lock_irq(&desc->iuspin); desc->length -= cntr; - spin_unlock_irq(&desc->iuspin); /* in case we had outstanding data */ if (!desc->length) clear_bit(WDM_READ, &desc->flags); + + spin_unlock_irq(&desc->iuspin); + rv = cntr; err: From 0cedc4e1c870d5d4811b3ed2aca98b41334f10e4 Mon Sep 17 00:00:00 2001 From: Neil Zhang Date: Fri, 24 Feb 2012 10:14:40 +0800 Subject: [PATCH 134/269] usb: host: remove ehci-pxa168.c Since ehci-mv.c can cover Marvell PXA and MMP series including PXA168, so this driver seems redundant now. Signed-off-by: Neil Zhang Cc: Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 7 - drivers/usb/host/ehci-hcd.c | 5 - drivers/usb/host/ehci-pxa168.c | 363 --------------------------------- 3 files changed, 375 deletions(-) delete mode 100644 drivers/usb/host/ehci-pxa168.c diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 353cdd488b93..b11b09fd61c3 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -606,10 +606,3 @@ config USB_OCTEON_OHCI config USB_OCTEON2_COMMON bool default y if USB_OCTEON_EHCI || USB_OCTEON_OHCI - -config USB_PXA168_EHCI - bool "Marvell PXA168 on-chip EHCI HCD support" - depends on USB_EHCI_HCD && ARCH_MMP - help - Enable support for Marvell PXA168 SoC's on-chip EHCI - host controller diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 4918b0c59af9..06e2548b549c 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1361,11 +1361,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_grlib_driver #endif -#ifdef CONFIG_USB_PXA168_EHCI -#include "ehci-pxa168.c" -#define PLATFORM_DRIVER ehci_pxa168_driver -#endif - #ifdef CONFIG_CPU_XLR #include "ehci-xls.c" #define PLATFORM_DRIVER ehci_xls_driver diff --git a/drivers/usb/host/ehci-pxa168.c b/drivers/usb/host/ehci-pxa168.c deleted file mode 100644 index 8d0e7a22e711..000000000000 --- a/drivers/usb/host/ehci-pxa168.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * drivers/usb/host/ehci-pxa168.c - * - * Tanmay Upadhyay - * - * Based on drivers/usb/host/ehci-orion.c - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include -#include -#include -#include - -#define USB_PHY_CTRL_REG 0x4 -#define USB_PHY_PLL_REG 0x8 -#define USB_PHY_TX_REG 0xc - -#define FBDIV_SHIFT 4 - -#define ICP_SHIFT 12 -#define ICP_15 2 -#define ICP_20 3 -#define ICP_25 4 - -#define KVCO_SHIFT 15 - -#define PLLCALI12_SHIFT 25 -#define CALI12_VDD 0 -#define CALI12_09 1 -#define CALI12_10 2 -#define CALI12_11 3 - -#define PLLVDD12_SHIFT 27 -#define VDD12_VDD 0 -#define VDD12_10 1 -#define VDD12_11 2 -#define VDD12_12 3 - -#define PLLVDD18_SHIFT 29 -#define VDD18_19 0 -#define VDD18_20 1 -#define VDD18_21 2 -#define VDD18_22 3 - - -#define PLL_READY (1 << 23) -#define VCOCAL_START (1 << 21) -#define REG_RCAL_START (1 << 12) - -struct pxa168_usb_drv_data { - struct ehci_hcd ehci; - struct clk *pxa168_usb_clk; - struct resource *usb_phy_res; - void __iomem *usb_phy_reg_base; -}; - -static int ehci_pxa168_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; - - ehci_reset(ehci); - retval = ehci_halt(ehci); - if (retval) - return retval; - - /* - * data structure init - */ - retval = ehci_init(hcd); - if (retval) - return retval; - - hcd->has_tt = 1; - - ehci_port_power(ehci, 0); - - return retval; -} - -static const struct hc_driver ehci_pxa168_hc_driver = { - .description = hcd_name, - .product_desc = "Marvell PXA168 EHCI", - .hcd_priv_size = sizeof(struct pxa168_usb_drv_data), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - - /* - * basic lifecycle operations - */ - .reset = ehci_pxa168_setup, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; - -static int pxa168_usb_phy_init(struct platform_device *pdev) -{ - struct resource *res; - void __iomem *usb_phy_reg_base; - struct pxa168_usb_pdata *pdata; - struct pxa168_usb_drv_data *drv_data; - struct usb_hcd *hcd = platform_get_drvdata(pdev); - unsigned long reg_val; - int pll_retry_cont = 10000, err = 0; - - drv_data = (struct pxa168_usb_drv_data *)hcd->hcd_priv; - pdata = (struct pxa168_usb_pdata *)pdev->dev.platform_data; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res) { - dev_err(&pdev->dev, - "Found HC with no PHY register addr. Check %s setup!\n", - dev_name(&pdev->dev)); - return -ENODEV; - } - - if (!request_mem_region(res->start, resource_size(res), - ehci_pxa168_hc_driver.description)) { - dev_dbg(&pdev->dev, "controller already in use\n"); - return -EBUSY; - } - - usb_phy_reg_base = ioremap(res->start, resource_size(res)); - if (usb_phy_reg_base == NULL) { - dev_dbg(&pdev->dev, "error mapping memory\n"); - err = -EFAULT; - goto err1; - } - drv_data->usb_phy_reg_base = usb_phy_reg_base; - drv_data->usb_phy_res = res; - - /* If someone wants to init USB phy in board specific way */ - if (pdata && pdata->phy_init) - return pdata->phy_init(usb_phy_reg_base); - - /* Power up the PHY and PLL */ - writel(readl(usb_phy_reg_base + USB_PHY_CTRL_REG) | 0x3, - usb_phy_reg_base + USB_PHY_CTRL_REG); - - /* Configure PHY PLL */ - reg_val = readl(usb_phy_reg_base + USB_PHY_PLL_REG) & ~(0x7e03ffff); - reg_val |= (VDD18_22 << PLLVDD18_SHIFT | VDD12_12 << PLLVDD12_SHIFT | - CALI12_11 << PLLCALI12_SHIFT | 3 << KVCO_SHIFT | - ICP_15 << ICP_SHIFT | 0xee << FBDIV_SHIFT | 0xb); - writel(reg_val, usb_phy_reg_base + USB_PHY_PLL_REG); - - /* Make sure PHY PLL is ready */ - while (!(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & PLL_READY)) { - if (!(pll_retry_cont--)) { - dev_dbg(&pdev->dev, "USB PHY PLL not ready\n"); - err = -EIO; - goto err2; - } - } - - /* Toggle VCOCAL_START bit of U2PLL for PLL calibration */ - udelay(200); - writel(readl(usb_phy_reg_base + USB_PHY_PLL_REG) | VCOCAL_START, - usb_phy_reg_base + USB_PHY_PLL_REG); - udelay(40); - writel(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & ~VCOCAL_START, - usb_phy_reg_base + USB_PHY_PLL_REG); - - /* Toggle REG_RCAL_START bit of U2PTX for impedance calibration */ - udelay(400); - writel(readl(usb_phy_reg_base + USB_PHY_TX_REG) | REG_RCAL_START, - usb_phy_reg_base + USB_PHY_TX_REG); - udelay(40); - writel(readl(usb_phy_reg_base + USB_PHY_TX_REG) & ~REG_RCAL_START, - usb_phy_reg_base + USB_PHY_TX_REG); - - /* Make sure PHY PLL is ready again */ - pll_retry_cont = 0; - while (!(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & PLL_READY)) { - if (!(pll_retry_cont--)) { - dev_dbg(&pdev->dev, "USB PHY PLL not ready\n"); - err = -EIO; - goto err2; - } - } - - return 0; -err2: - iounmap(usb_phy_reg_base); -err1: - release_mem_region(res->start, resource_size(res)); - return err; -} - -static int __devinit ehci_pxa168_drv_probe(struct platform_device *pdev) -{ - struct resource *res; - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - struct pxa168_usb_drv_data *drv_data; - void __iomem *regs; - int irq, err = 0; - - if (usb_disabled()) - return -ENODEV; - - pr_debug("Initializing pxa168-SoC USB Host Controller\n"); - - irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(&pdev->dev, - "Found HC with no IRQ. Check %s setup!\n", - dev_name(&pdev->dev)); - err = -ENODEV; - goto err1; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, - "Found HC with no register addr. Check %s setup!\n", - dev_name(&pdev->dev)); - err = -ENODEV; - goto err1; - } - - if (!request_mem_region(res->start, resource_size(res), - ehci_pxa168_hc_driver.description)) { - dev_dbg(&pdev->dev, "controller already in use\n"); - err = -EBUSY; - goto err1; - } - - regs = ioremap(res->start, resource_size(res)); - if (regs == NULL) { - dev_dbg(&pdev->dev, "error mapping memory\n"); - err = -EFAULT; - goto err2; - } - - hcd = usb_create_hcd(&ehci_pxa168_hc_driver, - &pdev->dev, dev_name(&pdev->dev)); - if (!hcd) { - err = -ENOMEM; - goto err3; - } - - drv_data = (struct pxa168_usb_drv_data *)hcd->hcd_priv; - - /* Enable USB clock */ - drv_data->pxa168_usb_clk = clk_get(&pdev->dev, "PXA168-USBCLK"); - if (IS_ERR(drv_data->pxa168_usb_clk)) { - dev_err(&pdev->dev, "Couldn't get USB clock\n"); - err = PTR_ERR(drv_data->pxa168_usb_clk); - goto err4; - } - clk_enable(drv_data->pxa168_usb_clk); - - err = pxa168_usb_phy_init(pdev); - if (err) { - dev_err(&pdev->dev, "USB PHY initialization failed\n"); - goto err5; - } - - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - hcd->regs = regs; - - ehci = hcd_to_ehci(hcd); - ehci->caps = hcd->regs + 0x100; - ehci->regs = hcd->regs + 0x100 + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - hcd->has_tt = 1; - ehci->sbrn = 0x20; - - err = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED); - if (err) - goto err5; - - return 0; - -err5: - clk_disable(drv_data->pxa168_usb_clk); - clk_put(drv_data->pxa168_usb_clk); -err4: - usb_put_hcd(hcd); -err3: - iounmap(regs); -err2: - release_mem_region(res->start, resource_size(res)); -err1: - dev_err(&pdev->dev, "init %s fail, %d\n", - dev_name(&pdev->dev), err); - - return err; -} - -static int __exit ehci_pxa168_drv_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct pxa168_usb_drv_data *drv_data = - (struct pxa168_usb_drv_data *)hcd->hcd_priv; - - usb_remove_hcd(hcd); - - /* Power down PHY & PLL */ - writel(readl(drv_data->usb_phy_reg_base + USB_PHY_CTRL_REG) & (~0x3), - drv_data->usb_phy_reg_base + USB_PHY_CTRL_REG); - - clk_disable(drv_data->pxa168_usb_clk); - clk_put(drv_data->pxa168_usb_clk); - - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - - iounmap(drv_data->usb_phy_reg_base); - release_mem_region(drv_data->usb_phy_res->start, - resource_size(drv_data->usb_phy_res)); - - usb_put_hcd(hcd); - - return 0; -} - -MODULE_ALIAS("platform:pxa168-ehci"); - -static struct platform_driver ehci_pxa168_driver = { - .probe = ehci_pxa168_drv_probe, - .remove = __exit_p(ehci_pxa168_drv_remove), - .shutdown = usb_hcd_platform_shutdown, - .driver.name = "pxa168-ehci", -}; From b7a205545345578712611106b371538992e142ff Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 12 Feb 2012 06:02:43 +0000 Subject: [PATCH 135/269] cdc-wdm: Don't clear WDM_READ unless entire read buffer is emptied MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The WDM_READ flag is cleared later iff desc->length is reduced to 0. Signed-off-by: Ben Hutchings Tested-by: Bjørn Mork Cc: Oliver Neukum Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 7ca54d4dea92..6037b503153f 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -455,7 +455,6 @@ retry: spin_unlock_irq(&desc->iuspin); goto retry; } - clear_bit(WDM_READ, &desc->flags); cntr = desc->length; spin_unlock_irq(&desc->iuspin); } From 4c954326823585bd014f36b2babd39c107c2bbb4 Mon Sep 17 00:00:00 2001 From: Pan Jiafei Date: Fri, 17 Feb 2012 13:57:16 +0800 Subject: [PATCH 136/269] USB: ehci-fsl: Turn on cache snooping on MPC8xxx If a MPC8xxx was being used, 'have_sysif_regs' should be set and it should setup cache snooping for all the 4GB space on both PPC32 and PPC64. Signed-off-by: Pan Jiafei Acked-by: Li Yang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-fsl.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 10e008a730a5..cd30ea4416a6 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -252,22 +252,19 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) if (pdata->have_sysif_regs) { temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004); - out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b); + + /* + * Turn on cache snooping hardware, since some PowerPC platforms + * wholly rely on hardware to deal with cache coherent + */ + + /* Setup Snooping for all the 4GB space */ + /* SNOOP1 starts from 0x0, size 2G */ + out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB); + /* SNOOP2 starts from 0x80000000, size 2G */ + out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB); } -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) - /* - * Turn on cache snooping hardware, since some PowerPC platforms - * wholly rely on hardware to deal with cache coherent - */ - - /* Setup Snooping for all the 4GB space */ - /* SNOOP1 starts from 0x0, size 2G */ - out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB); - /* SNOOP2 starts from 0x80000000, size 2G */ - out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB); -#endif - if ((pdata->operating_mode == FSL_USB2_DR_HOST) || (pdata->operating_mode == FSL_USB2_DR_OTG)) ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); From 18c75720e667719c923e0547abb60dfcd9c4ee90 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 17 Feb 2012 17:21:24 -0500 Subject: [PATCH 137/269] USB: allow users to run setserial with cdc-acm We had a user report that running setserial on /dev/ttyACM0 didn't work. He pointed at an old patch by Oliver Neukum from 2008 that never went anywhere.. http://permalink.gmane.org/gmane.linux.usb.general/9236 I made some minor changes to get it to apply again, and got the user to retest on 3.1, and he reported it worked for him. https://bugzilla.redhat.com/show_bug.cgi?id=787607 The diff below is against 3.3rc. The only difference between this and the version the user tested is the removal of the if (!ACM_READY) test Havard removed ACM_READY in 99823f457d5994b3bd3775515578c8bfacc64b04 I'm unclear if there's need for a different test in its place. From: Oliver Neukum Signed-off-by: Dave Jones Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 9543b19d410c..6dcc3a3fe6d1 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -773,10 +774,37 @@ static int acm_tty_tiocmset(struct tty_struct *tty, return acm_set_control(acm, acm->ctrlout = newctrl); } +static int get_serial_info(struct acm *acm, struct serial_struct __user *info) +{ + struct serial_struct tmp; + + if (!info) + return -EINVAL; + + memset(&tmp, 0, sizeof(tmp)); + tmp.flags = ASYNC_LOW_LATENCY; + tmp.xmit_fifo_size = acm->writesize; + tmp.baud_base = le32_to_cpu(acm->line.dwDTERate); + + if (copy_to_user(info, &tmp, sizeof(tmp))) + return -EFAULT; + else + return 0; +} + static int acm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { - return -ENOIOCTLCMD; + struct acm *acm = tty->driver_data; + int rv = -ENOIOCTLCMD; + + switch (cmd) { + case TIOCGSERIAL: /* gets serial port data */ + rv = get_serial_info(acm, (struct serial_struct __user *) arg); + break; + } + + return rv; } static const __u32 acm_tty_speed[] = { From aefd49206814413b5ade2f98ff062c4c8d47ec4f Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 17 Feb 2012 16:30:04 +0100 Subject: [PATCH 138/269] usb: isp1362-hcd: Convert to module_platform_driver Move the usb_disabled() check to the probe function and get rid of the rather pointless message on module load. Signed-off-by: Tobias Klauser Acked-by: Mike Frysinger Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1362-hcd.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index e5fd8aa57af1..9e63cdf1ab75 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2693,6 +2693,9 @@ static int __devinit isp1362_probe(struct platform_device *pdev) struct resource *irq_res; unsigned int irq_flags = 0; + if (usb_disabled()) + return -ENODEV; + /* basic sanity checks first. board-specific init logic should * have initialized this the three resources and probably board * specific platform_data. we don't probe for IRQs, and do only @@ -2864,19 +2867,4 @@ static struct platform_driver isp1362_driver = { }, }; -/*-------------------------------------------------------------------------*/ - -static int __init isp1362_init(void) -{ - if (usb_disabled()) - return -ENODEV; - pr_info("driver %s, %s\n", hcd_name, DRIVER_VERSION); - return platform_driver_register(&isp1362_driver); -} -module_init(isp1362_init); - -static void __exit isp1362_cleanup(void) -{ - platform_driver_unregister(&isp1362_driver); -} -module_exit(isp1362_cleanup); +module_platform_driver(isp1362_driver); From 855ef452ee112abf3973e00c53c109c5e9744add Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Fri, 17 Feb 2012 23:06:47 +0900 Subject: [PATCH 139/269] usb: Fix typo in ehci-dbg.c Correct spelling "peridic" to "periodic" in drivers/usb/host/ehci-dbg.c Signed-off-by: Masanari Iida Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index d6d74d2e09f4..fd9109d7eb0e 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -107,7 +107,7 @@ static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) HCC_PER_PORT_CHANGE_EVENT(params) ? " ppce" : "", HCC_HW_PREFETCH(params) ? " hw prefetch" : "", HCC_32FRAME_PERIODIC_LIST(params) ? - " 32 peridic list" : ""); + " 32 periodic list" : ""); } } #else From e90fc3cb087ce5c5f81e814358222cd6d197b5db Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Thu, 16 Feb 2012 09:41:52 +0800 Subject: [PATCH 140/269] usb: Fix build error due to dma_mask is not at pdev_archdata at ARM When build i.mx platform with imx_v6_v7_defconfig, and after adding USB Gadget support, it has below build error: CC drivers/usb/host/fsl-mph-dr-of.o drivers/usb/host/fsl-mph-dr-of.c: In function 'fsl_usb2_device_register': drivers/usb/host/fsl-mph-dr-of.c:97: error: 'struct pdev_archdata' has no member named 'dma_mask' It has discussed at: http://www.spinics.net/lists/linux-usb/msg57302.html For PowerPC, there is dma_mask at struct pdev_archdata, but there is no dma_mask at struct pdev_archdata for ARM. The pdev_archdata is related to specific platform, it should NOT be accessed by cross platform drivers, like USB. The code for pdev_archdata should be useless, as for PowerPC, it has already gotten the value for pdev->dev.dma_mask at function arch_setup_pdev_archdata of arch/powerpc/kernel/setup-common.c. Tested-by: Ramneek Mehresh Signed-off-by: Peter Chen Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fsl-mph-dr-of.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 7916e56a725e..ab333ac6071d 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -94,7 +94,6 @@ struct platform_device * __devinit fsl_usb2_device_register( pdev->dev.parent = &ofdev->dev; pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask; - pdev->dev.dma_mask = &pdev->archdata.dma_mask; *pdev->dev.dma_mask = *ofdev->dev.dma_mask; retval = platform_device_add_data(pdev, pdata, sizeof(*pdata)); From 28c56ea1431421dec51b7b229369e991481453df Mon Sep 17 00:00:00 2001 From: Shengzhou Liu Date: Thu, 16 Feb 2012 18:02:20 +0800 Subject: [PATCH 141/269] powerpc/usb: fix bug of kernel hang when initializing usb If USB UTMI PHY is not enable, writing to portsc register will lead to kernel hang during boot up. Signed-off-by: Shengzhou Liu Reported-by: Benjamin Herrenschmidt Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-fsl.c | 4 ++++ drivers/usb/host/ehci-fsl.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index cd30ea4416a6..7a15c2235758 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -216,6 +216,8 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, unsigned int port_offset) { u32 portsc; + struct usb_hcd *hcd = ehci_to_hcd(ehci); + void __iomem *non_ehci = hcd->regs; portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]); portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW); @@ -231,6 +233,8 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, portsc |= PORT_PTS_PTW; /* fall through */ case FSL_USB2_PHY_UTMI: + /* enable UTMI PHY */ + setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN); portsc |= PORT_PTS_UTMI; break; case FSL_USB2_PHY_NONE: diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index 6d5a94e9bb3c..863fb0c080d7 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -47,6 +47,7 @@ #define FSL_SOC_USB_PRICTRL 0x40c /* NOTE: big-endian */ #define FSL_SOC_USB_SICTRL 0x410 /* NOTE: big-endian */ #define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */ +#define CTRL_UTMI_PHY_EN (1<<9) #define CTRL_PHY_CLK_VALID (1 << 17) #define SNOOP_SIZE_2GB 0x1e #endif /* _EHCI_FSL_H */ From 4898e07174b79013afd2b422ef6c4336ef8e6783 Mon Sep 17 00:00:00 2001 From: "jwboyer@redhat.com" Date: Mon, 20 Feb 2012 15:34:34 -0500 Subject: [PATCH 142/269] USB: ums_realtek: do not use stack memory for DMA in __do_config_autodelink __do_config_autodelink passes the data variable to the transport function. If the calling functions pass a stack variable, this will eventually trigger a DMA-API debug backtrace for mapping stack memory in the DMA buffer. Fix this by calling kmemdup for the passed data instead. Signed-off-by: Josh Boyer Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/realtek_cr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index b1c2fe8b6dcd..84a4bc0cbee4 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -507,9 +507,14 @@ static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len) { int retval; u8 cmnd[12] = {0}; + u8 *buf; US_DEBUGP("%s, addr = 0xfe47, len = %d\n", __FUNCTION__, len); + buf = kmemdup(data, len, GFP_NOIO); + if (!buf) + return USB_STOR_TRANSPORT_ERROR; + cmnd[0] = 0xF0; cmnd[1] = 0x0E; cmnd[2] = 0xfe; @@ -517,7 +522,8 @@ static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len) cmnd[4] = (u8)(len >> 8); cmnd[5] = (u8)len; - retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, data, len, DMA_TO_DEVICE, NULL); + retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, buf, len, DMA_TO_DEVICE, NULL); + kfree(buf); if (retval != USB_STOR_TRANSPORT_GOOD) { return -EIO; } From 8c1b369394d188afb954ef470d90ac887438530c Mon Sep 17 00:00:00 2001 From: Deepak Sikri Date: Fri, 24 Feb 2012 14:49:31 +0530 Subject: [PATCH 143/269] USB: ehci-spear: Add PM support This patch adds support for standby/S2R/hibernate for ehci-spear driver. Signed-off-by: Deepak Sikri Signed-off-by: Pratyush Anand Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-spear.c | 83 ++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c index b115b0b76e33..6e928559169c 100644 --- a/drivers/usb/host/ehci-spear.c +++ b/drivers/usb/host/ehci-spear.c @@ -11,8 +11,10 @@ * more details. */ -#include #include +#include +#include +#include struct spear_ehci { struct ehci_hcd ehci; @@ -90,6 +92,82 @@ static const struct hc_driver ehci_spear_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; +#ifdef CONFIG_PM +static int ehci_spear_drv_suspend(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + unsigned long flags; + int rc = 0; + + if (time_before(jiffies, ehci->next_statechange)) + msleep(10); + + /* + * Root hub was already suspended. Disable irq emission and mark HW + * unaccessible. The PM and USB cores make sure that the root hub is + * either suspended or stopped. + */ + spin_lock_irqsave(&ehci->lock, flags); + ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); + ehci_writel(ehci, 0, &ehci->regs->intr_enable); + ehci_readl(ehci, &ehci->regs->intr_enable); + spin_unlock_irqrestore(&ehci->lock, flags); + + return rc; +} + +static int ehci_spear_drv_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + + if (time_before(jiffies, ehci->next_statechange)) + msleep(100); + + if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { + int mask = INTR_MASK; + + ehci_prepare_ports_for_controller_resume(ehci); + + if (!hcd->self.root_hub->do_remote_wakeup) + mask &= ~STS_PCD; + + ehci_writel(ehci, mask, &ehci->regs->intr_enable); + ehci_readl(ehci, &ehci->regs->intr_enable); + return 0; + } + + usb_root_hub_lost_power(hcd->self.root_hub); + + /* + * Else reset, to cope with power loss or flush-to-storage style + * "resume" having let BIOS kick in during reboot. + */ + ehci_halt(ehci); + ehci_reset(ehci); + + /* emptying the schedule aborts any urbs */ + spin_lock_irq(&ehci->lock); + if (ehci->reclaim) + end_unlink_async(ehci); + + ehci_work(ehci); + spin_unlock_irq(&ehci->lock); + + ehci_writel(ehci, ehci->command, &ehci->regs->command); + ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); + ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ + + /* here we "know" root ports should always stay powered */ + ehci_port_power(ehci, 1); + return 0; +} +#endif /* CONFIG_PM */ + +static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend, + ehci_spear_drv_resume); + static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd ; @@ -205,7 +283,8 @@ static struct platform_driver spear_ehci_hcd_driver = { .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "spear-ehci", - .bus = &platform_bus_type + .bus = &platform_bus_type, + .pm = &ehci_spear_pm_ops, } }; From 2b4ffe31a2380de7c893e345659b0730d6dc62d3 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 23 Feb 2012 17:26:33 +0900 Subject: [PATCH 144/269] USB: ohci-exynos: replace hcd->state with ohci->rh_state This patch removes uses of hcd->state and replaces hcd->state with ohci->rh_state field. Signed-off-by: Jingoo Han Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-exynos.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index 55aa35aa3d7b..37bb20ebb6fc 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -212,12 +212,10 @@ static int exynos_ohci_suspend(struct device *dev) * mark HW unaccessible, bail out if RH has been resumed. Use * the spinlock to properly synchronize with possible pending * RH suspend or resume activity. - * - * This is still racy as hcd->state is manipulated outside of - * any locks =P But that will be a different fix. */ spin_lock_irqsave(&ohci->lock, flags); - if (hcd->state != HC_STATE_SUSPENDED && hcd->state != HC_STATE_HALT) { + if (ohci->rh_state != OHCI_RH_SUSPENDED && + ohci->rh_state != OHCI_RH_HALTED) { rc = -EINVAL; goto fail; } From a219b666e89bd2f7810b4eaaf4d7382ad0e6ecb1 Mon Sep 17 00:00:00 2001 From: Neil Zhang Date: Thu, 23 Feb 2012 11:41:54 +0800 Subject: [PATCH 145/269] usb: host: add dependence for USB_EHCI_MV This ehci driver is mainly designed to support host controller found on Marvell PXA and MMP Soc series. Add the dependence to avoid the potential build failure which may include two EHCI controller drivers. Signed-off-by: Neil Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index b11b09fd61c3..dd045173ab79 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -196,7 +196,7 @@ config USB_EHCI_S5P config USB_EHCI_MV bool "EHCI support for Marvell on-chip controller" - depends on USB_EHCI_HCD + depends on USB_EHCI_HCD && (ARCH_PXA || ARCH_MMP) select USB_EHCI_ROOT_HUB_TT ---help--- Enables support for Marvell (including PXA and MMP series) on-chip From 6d161b99f875269ad4ffa44375e1e54bca6fd02e Mon Sep 17 00:00:00 2001 From: Scott Dial Date: Fri, 24 Feb 2012 19:04:09 -0500 Subject: [PATCH 146/269] usb-serial: Add support for the Sealevel SeaLINK+8 2038-ROHS device This patch adds new device IDs to the ftdi_sio module to support the new Sealevel SeaLINK+8 2038-ROHS device. Signed-off-by: Scott Dial Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 4 ++++ drivers/usb/serial/ftdi_sio_ids.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 615cf2c4915c..feafa85dd07e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -536,6 +536,10 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) }, { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) }, { USB_DEVICE(OCT_VID, OCT_US101_PID) }, { USB_DEVICE(OCT_VID, OCT_DK201_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 6f6058f0db1b..ed74019c5b46 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -680,6 +680,10 @@ #define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */ #define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */ #define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */ +#define SEALEVEL_2803R_1_PID 0Xa02a /* SeaLINK+8 (2803-ROHS) Port 1+2 */ +#define SEALEVEL_2803R_2_PID 0Xa02b /* SeaLINK+8 (2803-ROHS) Port 3+4 */ +#define SEALEVEL_2803R_3_PID 0Xa02c /* SeaLINK+8 (2803-ROHS) Port 5+6 */ +#define SEALEVEL_2803R_4_PID 0Xa02d /* SeaLINK+8 (2803-ROHS) Port 7+8 */ /* * JETI SPECTROMETER SPECBOS 1201 From b1c711d629358576e8896a18e74cd5f4d811d7f7 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:17 +0200 Subject: [PATCH 147/269] usb: otg: mv_otg: Start using struct usb_otg Use struct usb_otg members with OTG specific functions instead of usb_phy members. [ balbi@ti.com : fixed a compile error on isp1704_charger.c ] Signed-off-by: Heikki Krogerus Reviewed-by: Marek Vasut Acked-by: Neil Zhang Signed-off-by: Felipe Balbi --- drivers/power/isp1704_charger.c | 12 ++-- drivers/usb/otg/mv_otg.c | 110 ++++++++++++++++++-------------- drivers/usb/otg/mv_otg.h | 2 +- 3 files changed, 69 insertions(+), 55 deletions(-) diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c index 58ad6e998ca0..1289a5f790a1 100644 --- a/drivers/power/isp1704_charger.c +++ b/drivers/power/isp1704_charger.c @@ -274,8 +274,8 @@ static void isp1704_charger_work(struct work_struct *data) case POWER_SUPPLY_TYPE_USB: default: /* enable data pullups */ - if (isp->phy->gadget) - usb_gadget_connect(isp->phy->gadget); + if (isp->phy->otg->gadget) + usb_gadget_connect(isp->phy->otg->gadget); } break; case USB_EVENT_NONE: @@ -293,8 +293,8 @@ static void isp1704_charger_work(struct work_struct *data) * chargers. The pullups may be enabled elsewhere, so this can * not be the final solution. */ - if (isp->phy->gadget) - usb_gadget_disconnect(isp->phy->gadget); + if (isp->phy->otg->gadget) + usb_gadget_disconnect(isp->phy->otg->gadget); isp1704_charger_set_power(isp, 0); break; @@ -459,8 +459,8 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) * enumerated. The charger driver should be always loaded before any * gadget is loaded. */ - if (isp->phy->gadget) - usb_gadget_disconnect(isp->phy->gadget); + if (isp->phy->otg->gadget) + usb_gadget_disconnect(isp->phy->otg->gadget); /* Detect charger if VBUS is valid (the cable was already plugged). */ ret = isp1704_read(isp, ULPI_USB_INT_STS); diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c index 6e05d58effe1..6cc6c3ffbb83 100644 --- a/drivers/usb/otg/mv_otg.c +++ b/drivers/usb/otg/mv_otg.c @@ -55,16 +55,16 @@ static char *state_string[] = { "a_vbus_err" }; -static int mv_otg_set_vbus(struct usb_phy *otg, bool on) +static int mv_otg_set_vbus(struct usb_otg *otg, bool on) { - struct mv_otg *mvotg = container_of(otg, struct mv_otg, otg); + struct mv_otg *mvotg = container_of(otg->phy, struct mv_otg, phy); if (mvotg->pdata->set_vbus == NULL) return -ENODEV; return mvotg->pdata->set_vbus(on); } -static int mv_otg_set_host(struct usb_phy *otg, +static int mv_otg_set_host(struct usb_otg *otg, struct usb_bus *host) { otg->host = host; @@ -72,7 +72,7 @@ static int mv_otg_set_host(struct usb_phy *otg, return 0; } -static int mv_otg_set_peripheral(struct usb_phy *otg, +static int mv_otg_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) { otg->gadget = gadget; @@ -203,7 +203,7 @@ static void mv_otg_init_irq(struct mv_otg *mvotg) static void mv_otg_start_host(struct mv_otg *mvotg, int on) { #ifdef CONFIG_USB - struct usb_phy *otg = &mvotg->otg; + struct usb_otg *otg = mvotg->phy.otg; struct usb_hcd *hcd; if (!otg->host) @@ -222,12 +222,12 @@ static void mv_otg_start_host(struct mv_otg *mvotg, int on) static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on) { - struct usb_phy *otg = &mvotg->otg; + struct usb_otg *otg = mvotg->phy.otg; if (!otg->gadget) return; - dev_info(otg->dev, "gadget %s\n", on ? "on" : "off"); + dev_info(mvotg->phy.dev, "gadget %s\n", on ? "on" : "off"); if (on) usb_gadget_vbus_connect(otg->gadget); @@ -343,69 +343,69 @@ static void mv_otg_update_inputs(struct mv_otg *mvotg) static void mv_otg_update_state(struct mv_otg *mvotg) { struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl; - struct usb_phy *otg = &mvotg->otg; - int old_state = otg->state; + struct usb_phy *phy = &mvotg->phy; + int old_state = phy->state; switch (old_state) { case OTG_STATE_UNDEFINED: - otg->state = OTG_STATE_B_IDLE; + phy->state = OTG_STATE_B_IDLE; /* FALL THROUGH */ case OTG_STATE_B_IDLE: if (otg_ctrl->id == 0) - otg->state = OTG_STATE_A_IDLE; + phy->state = OTG_STATE_A_IDLE; else if (otg_ctrl->b_sess_vld) - otg->state = OTG_STATE_B_PERIPHERAL; + phy->state = OTG_STATE_B_PERIPHERAL; break; case OTG_STATE_B_PERIPHERAL: if (!otg_ctrl->b_sess_vld || otg_ctrl->id == 0) - otg->state = OTG_STATE_B_IDLE; + phy->state = OTG_STATE_B_IDLE; break; case OTG_STATE_A_IDLE: if (otg_ctrl->id) - otg->state = OTG_STATE_B_IDLE; + phy->state = OTG_STATE_B_IDLE; else if (!(otg_ctrl->a_bus_drop) && (otg_ctrl->a_bus_req || otg_ctrl->a_srp_det)) - otg->state = OTG_STATE_A_WAIT_VRISE; + phy->state = OTG_STATE_A_WAIT_VRISE; break; case OTG_STATE_A_WAIT_VRISE: if (otg_ctrl->a_vbus_vld) - otg->state = OTG_STATE_A_WAIT_BCON; + phy->state = OTG_STATE_A_WAIT_BCON; break; case OTG_STATE_A_WAIT_BCON: if (otg_ctrl->id || otg_ctrl->a_bus_drop || otg_ctrl->a_wait_bcon_timeout) { mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER); mvotg->otg_ctrl.a_wait_bcon_timeout = 0; - otg->state = OTG_STATE_A_WAIT_VFALL; + phy->state = OTG_STATE_A_WAIT_VFALL; otg_ctrl->a_bus_req = 0; } else if (!otg_ctrl->a_vbus_vld) { mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER); mvotg->otg_ctrl.a_wait_bcon_timeout = 0; - otg->state = OTG_STATE_A_VBUS_ERR; + phy->state = OTG_STATE_A_VBUS_ERR; } else if (otg_ctrl->b_conn) { mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER); mvotg->otg_ctrl.a_wait_bcon_timeout = 0; - otg->state = OTG_STATE_A_HOST; + phy->state = OTG_STATE_A_HOST; } break; case OTG_STATE_A_HOST: if (otg_ctrl->id || !otg_ctrl->b_conn || otg_ctrl->a_bus_drop) - otg->state = OTG_STATE_A_WAIT_BCON; + phy->state = OTG_STATE_A_WAIT_BCON; else if (!otg_ctrl->a_vbus_vld) - otg->state = OTG_STATE_A_VBUS_ERR; + phy->state = OTG_STATE_A_VBUS_ERR; break; case OTG_STATE_A_WAIT_VFALL: if (otg_ctrl->id || (!otg_ctrl->b_conn && otg_ctrl->a_sess_vld) || otg_ctrl->a_bus_req) - otg->state = OTG_STATE_A_IDLE; + phy->state = OTG_STATE_A_IDLE; break; case OTG_STATE_A_VBUS_ERR: if (otg_ctrl->id || otg_ctrl->a_clr_err || otg_ctrl->a_bus_drop) { otg_ctrl->a_clr_err = 0; - otg->state = OTG_STATE_A_WAIT_VFALL; + phy->state = OTG_STATE_A_WAIT_VFALL; } break; default: @@ -416,15 +416,17 @@ static void mv_otg_update_state(struct mv_otg *mvotg) static void mv_otg_work(struct work_struct *work) { struct mv_otg *mvotg; - struct usb_phy *otg; + struct usb_phy *phy; + struct usb_otg *otg; int old_state; mvotg = container_of((struct delayed_work *)work, struct mv_otg, work); run: /* work queue is single thread, or we need spin_lock to protect */ - otg = &mvotg->otg; - old_state = otg->state; + phy = &mvotg->phy; + otg = phy->otg; + old_state = phy->state; if (!mvotg->active) return; @@ -432,14 +434,14 @@ run: mv_otg_update_inputs(mvotg); mv_otg_update_state(mvotg); - if (old_state != otg->state) { + if (old_state != phy->state) { dev_info(&mvotg->pdev->dev, "change from state %s to %s\n", state_string[old_state], - state_string[otg->state]); + state_string[phy->state]); - switch (otg->state) { + switch (phy->state) { case OTG_STATE_B_IDLE: - mvotg->otg.default_a = 0; + otg->default_a = 0; if (old_state == OTG_STATE_B_PERIPHERAL) mv_otg_start_periphrals(mvotg, 0); mv_otg_reset(mvotg); @@ -450,14 +452,14 @@ run: mv_otg_start_periphrals(mvotg, 1); break; case OTG_STATE_A_IDLE: - mvotg->otg.default_a = 1; + otg->default_a = 1; mv_otg_enable(mvotg); if (old_state == OTG_STATE_A_WAIT_VFALL) mv_otg_start_host(mvotg, 0); mv_otg_reset(mvotg); break; case OTG_STATE_A_WAIT_VRISE: - mv_otg_set_vbus(&mvotg->otg, 1); + mv_otg_set_vbus(otg, 1); break; case OTG_STATE_A_WAIT_BCON: if (old_state != OTG_STATE_A_HOST) @@ -479,7 +481,7 @@ run: * here. In fact, it need host driver to notify us. */ mvotg->otg_ctrl.b_conn = 0; - mv_otg_set_vbus(&mvotg->otg, 0); + mv_otg_set_vbus(otg, 0); break; case OTG_STATE_A_VBUS_ERR: break; @@ -548,8 +550,8 @@ set_a_bus_req(struct device *dev, struct device_attribute *attr, return -1; /* We will use this interface to change to A device */ - if (mvotg->otg.state != OTG_STATE_B_IDLE - && mvotg->otg.state != OTG_STATE_A_IDLE) + if (mvotg->phy.state != OTG_STATE_B_IDLE + && mvotg->phy.state != OTG_STATE_A_IDLE) return -1; /* The clock may disabled and we need to set irq for ID detected */ @@ -579,7 +581,7 @@ set_a_clr_err(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct mv_otg *mvotg = dev_get_drvdata(dev); - if (!mvotg->otg.default_a) + if (!mvotg->phy.otg->default_a) return -1; if (count > 2) @@ -615,7 +617,7 @@ set_a_bus_drop(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct mv_otg *mvotg = dev_get_drvdata(dev); - if (!mvotg->otg.default_a) + if (!mvotg->phy.otg->default_a) return -1; if (count > 2) @@ -688,9 +690,10 @@ int mv_otg_remove(struct platform_device *pdev) for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++) clk_put(mvotg->clk[clk_i]); - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); platform_set_drvdata(pdev, NULL); + kfree(mvotg->phy.otg); kfree(mvotg); return 0; @@ -700,6 +703,7 @@ static int mv_otg_probe(struct platform_device *pdev) { struct mv_usb_platform_data *pdata = pdev->dev.platform_data; struct mv_otg *mvotg; + struct usb_otg *otg; struct resource *r; int retval = 0, clk_i, i; size_t size; @@ -716,6 +720,12 @@ static int mv_otg_probe(struct platform_device *pdev) return -ENOMEM; } + otg = kzalloc(sizeof *otg, GFP_KERNEL); + if (!otg) { + kfree(mvotg); + return -ENOMEM; + } + platform_set_drvdata(pdev, mvotg); mvotg->pdev = pdev; @@ -741,12 +751,15 @@ static int mv_otg_probe(struct platform_device *pdev) /* OTG common part */ mvotg->pdev = pdev; - mvotg->otg.dev = &pdev->dev; - mvotg->otg.label = driver_name; - mvotg->otg.set_host = mv_otg_set_host; - mvotg->otg.set_peripheral = mv_otg_set_peripheral; - mvotg->otg.set_vbus = mv_otg_set_vbus; - mvotg->otg.state = OTG_STATE_UNDEFINED; + mvotg->phy.dev = &pdev->dev; + mvotg->phy.otg = otg; + mvotg->phy.label = driver_name; + mvotg->phy.state = OTG_STATE_UNDEFINED; + + otg->phy = &mvotg->phy; + otg->set_host = mv_otg_set_host; + otg->set_peripheral = mv_otg_set_peripheral; + otg->set_vbus = mv_otg_set_vbus; for (i = 0; i < OTG_TIMER_NUM; i++) init_timer(&mvotg->otg_ctrl.timer[i]); @@ -840,7 +853,7 @@ static int mv_otg_probe(struct platform_device *pdev) goto err_disable_clk; } - retval = otg_set_transceiver(&mvotg->otg); + retval = usb_set_transceiver(&mvotg->phy); if (retval < 0) { dev_err(&pdev->dev, "can't register transceiver, %d\n", retval); @@ -867,7 +880,7 @@ static int mv_otg_probe(struct platform_device *pdev) return 0; err_set_transceiver: - otg_set_transceiver(NULL); + usb_set_transceiver(NULL); err_free_irq: free_irq(mvotg->irq, mvotg); err_disable_clk: @@ -888,6 +901,7 @@ err_put_clk: clk_put(mvotg->clk[clk_i]); platform_set_drvdata(pdev, NULL); + kfree(otg); kfree(mvotg); return retval; @@ -898,10 +912,10 @@ static int mv_otg_suspend(struct platform_device *pdev, pm_message_t state) { struct mv_otg *mvotg = platform_get_drvdata(pdev); - if (mvotg->otg.state != OTG_STATE_B_IDLE) { + if (mvotg->phy.state != OTG_STATE_B_IDLE) { dev_info(&pdev->dev, "OTG state is not B_IDLE, it is %d!\n", - mvotg->otg.state); + mvotg->phy.state); return -EAGAIN; } diff --git a/drivers/usb/otg/mv_otg.h b/drivers/usb/otg/mv_otg.h index a74ee07a2727..8a9e351b36ba 100644 --- a/drivers/usb/otg/mv_otg.h +++ b/drivers/usb/otg/mv_otg.h @@ -136,7 +136,7 @@ struct mv_otg_regs { }; struct mv_otg { - struct usb_phy otg; + struct usb_phy phy; struct mv_otg_ctrl otg_ctrl; /* base address */ From b96d3b08365f5a9603f50f3aadca6012f7eaffa1 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:18 +0200 Subject: [PATCH 148/269] usb: Convert all users to new usb_phy Use the new usb_phy_* functions with transceiver operations instead of the old otg functions. Includes fixes from Sascha Hauer. Signed-off-by: Heikki Krogerus Acked-by: Sascha Hauer Acked-by: Pavankumar Kondeti Acked-by: Li Yang Acked-by: Alan Stern Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- arch/arm/mach-tegra/usb_phy.c | 4 ++-- drivers/usb/gadget/ci13xxx_msm.c | 4 ++-- drivers/usb/gadget/ci13xxx_udc.c | 10 +++++----- drivers/usb/gadget/fsl_udc_core.c | 4 ++-- drivers/usb/gadget/langwell_udc.c | 4 ++-- drivers/usb/gadget/mv_udc_core.c | 2 +- drivers/usb/gadget/omap_udc.c | 14 ++++++++------ drivers/usb/gadget/pxa25x_udc.c | 8 ++++---- drivers/usb/gadget/pxa27x_udc.c | 6 +++--- drivers/usb/gadget/s3c-hsudc.c | 6 +++--- drivers/usb/host/ehci-fsl.c | 2 +- drivers/usb/host/ehci-msm.c | 14 +++++++------- drivers/usb/host/ehci-mv.c | 6 +++--- drivers/usb/host/ehci-mxc.c | 10 ++++++---- drivers/usb/host/ehci-tegra.c | 6 +++--- drivers/usb/host/ohci-omap.c | 2 +- drivers/usb/musb/am35x.c | 4 ++-- drivers/usb/musb/blackfin.c | 4 ++-- drivers/usb/musb/da8xx.c | 4 ++-- drivers/usb/musb/davinci.c | 6 +++--- drivers/usb/musb/musb_core.c | 11 +++++------ drivers/usb/musb/musb_gadget.c | 2 +- drivers/usb/musb/omap2430.c | 22 +++++++++++----------- drivers/usb/musb/tusb6010.c | 6 +++--- drivers/usb/musb/ux500.c | 8 ++++---- 25 files changed, 86 insertions(+), 83 deletions(-) diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c index 37576a721aeb..ad321f9e2bb8 100644 --- a/arch/arm/mach-tegra/usb_phy.c +++ b/arch/arm/mach-tegra/usb_phy.c @@ -608,13 +608,13 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) writel(val, base + ULPI_TIMING_CTRL_1); /* Fix VbusInvalid due to floating VBUS */ - ret = otg_io_write(phy->ulpi, 0x40, 0x08); + ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08); if (ret) { pr_err("%s: ulpi write failed\n", __func__); return ret; } - ret = otg_io_write(phy->ulpi, 0x80, 0x0B); + ret = usb_phy_io_write(phy->ulpi, 0x80, 0x0B); if (ret) { pr_err("%s: ulpi write failed\n", __func__); return ret; diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c index 1fc612914c52..d07e44c05e9b 100644 --- a/drivers/usb/gadget/ci13xxx_msm.c +++ b/drivers/usb/gadget/ci13xxx_msm.c @@ -37,10 +37,10 @@ static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event) * Put the transceiver in non-driving mode. Otherwise host * may not detect soft-disconnection. */ - val = otg_io_read(udc->transceiver, ULPI_FUNC_CTRL); + val = usb_phy_io_read(udc->transceiver, ULPI_FUNC_CTRL); val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; - otg_io_write(udc->transceiver, val, ULPI_FUNC_CTRL); + usb_phy_io_write(udc->transceiver, val, ULPI_FUNC_CTRL); break; default: dev_dbg(dev, "unknown ci13xxx_udc event\n"); diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 27e313718422..68ad160f2589 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -2537,7 +2537,7 @@ static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA) struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget); if (udc->transceiver) - return otg_set_power(udc->transceiver, mA); + return usb_phy_set_power(udc->transceiver, mA); return -ENOTSUPP; } @@ -2900,7 +2900,7 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev, if (retval < 0) goto free_udc; - udc->transceiver = otg_get_transceiver(); + udc->transceiver = usb_get_transceiver(); if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) { if (udc->transceiver == NULL) { @@ -2946,7 +2946,7 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev, remove_trans: if (udc->transceiver) { otg_set_peripheral(udc->transceiver, &udc->gadget); - otg_put_transceiver(udc->transceiver); + usb_put_transceiver(udc->transceiver); } err("error = %i", retval); @@ -2958,7 +2958,7 @@ unreg_device: device_unregister(&udc->gadget.dev); put_transceiver: if (udc->transceiver) - otg_put_transceiver(udc->transceiver); + usb_put_transceiver(udc->transceiver); free_udc: kfree(udc); _udc = NULL; @@ -2982,7 +2982,7 @@ static void udc_remove(void) if (udc->transceiver) { otg_set_peripheral(udc->transceiver, &udc->gadget); - otg_put_transceiver(udc->transceiver); + usb_put_transceiver(udc->transceiver); } #ifdef CONFIG_USB_GADGET_DEBUG_FILES dbg_remove_files(&udc->gadget.dev); diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index b04712f19f1e..21fdfdb18ba8 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1217,7 +1217,7 @@ static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA) udc = container_of(gadget, struct fsl_udc, gadget); if (udc->transceiver) - return otg_set_power(udc->transceiver, mA); + return usb_phy_set_power(udc->transceiver, mA); return -ENOTSUPP; } @@ -2430,7 +2430,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) #ifdef CONFIG_USB_OTG if (pdata->operating_mode == FSL_USB2_DR_OTG) { - udc_controller->transceiver = otg_get_transceiver(); + udc_controller->transceiver = usb_get_transceiver(); if (!udc_controller->transceiver) { ERR("Can't find OTG driver!\n"); ret = -ENODEV; diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index e2293c1588ee..b19a9e46e69d 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -1261,9 +1261,9 @@ static int langwell_vbus_draw(struct usb_gadget *_gadget, unsigned mA) dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if (dev->transceiver) { - dev_vdbg(&dev->pdev->dev, "otg_set_power\n"); + dev_vdbg(&dev->pdev->dev, "usb_phy_set_power\n"); dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); - return otg_set_power(dev->transceiver, mA); + return usb_phy_set_power(dev->transceiver, mA); } dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index f97e737d26f7..50baf3ea336b 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -2181,7 +2181,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev) #ifdef CONFIG_USB_OTG_UTILS if (pdata->mode == MV_USB_MODE_OTG) - udc->transceiver = otg_get_transceiver(); + udc->transceiver = usb_get_transceiver(); #endif udc->clknum = pdata->clknum; diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index d3529787351d..e82c6995ce26 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -1345,7 +1345,7 @@ static int omap_vbus_draw(struct usb_gadget *gadget, unsigned mA) udc = container_of(gadget, struct omap_udc, gadget); if (udc->transceiver) - return otg_set_power(udc->transceiver, mA); + return usb_phy_set_power(udc->transceiver, mA); return -EOPNOTSUPP; } @@ -1839,11 +1839,13 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src) spin_lock(&udc->lock); } if (udc->transceiver) - otg_set_suspend(udc->transceiver, 1); + usb_phy_set_suspend( + udc->transceiver, 1); } else { VDBG("resume\n"); if (udc->transceiver) - otg_set_suspend(udc->transceiver, 0); + usb_phy_set_suspend( + udc->transceiver, 0); if (udc->gadget.speed == USB_SPEED_FULL && udc->driver->resume) { spin_unlock(&udc->lock); @@ -2863,7 +2865,7 @@ static int __init omap_udc_probe(struct platform_device *pdev) * use it. Except for OTG, we don't _need_ to talk to one; * but not having one probably means no VBUS detection. */ - xceiv = otg_get_transceiver(); + xceiv = usb_get_transceiver(); if (xceiv) type = xceiv->label; else if (config->otg) { @@ -3009,7 +3011,7 @@ cleanup1: cleanup0: if (xceiv) - otg_put_transceiver(xceiv); + usb_put_transceiver(xceiv); if (cpu_is_omap16xx() || cpu_is_omap24xx() || cpu_is_omap7xx()) { clk_disable(hhc_clk); @@ -3039,7 +3041,7 @@ static int __exit omap_udc_remove(struct platform_device *pdev) pullup_disable(udc); if (udc->transceiver) { - otg_put_transceiver(udc->transceiver); + usb_put_transceiver(udc->transceiver); udc->transceiver = NULL; } omap_writew(0, UDC_SYSCON1); diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index dd470635f4f7..b86518e49415 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -995,7 +995,7 @@ static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) udc = container_of(_gadget, struct pxa25x_udc, gadget); if (udc->transceiver) - return otg_set_power(udc->transceiver, mA); + return usb_phy_set_power(udc->transceiver, mA); return -EOPNOTSUPP; } @@ -2159,7 +2159,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) dev->dev = &pdev->dev; dev->mach = pdev->dev.platform_data; - dev->transceiver = otg_get_transceiver(); + dev->transceiver = usb_get_transceiver(); if (gpio_is_valid(dev->mach->gpio_pullup)) { if ((retval = gpio_request(dev->mach->gpio_pullup, @@ -2238,7 +2238,7 @@ lubbock_fail0: gpio_free(dev->mach->gpio_pullup); err_gpio_pullup: if (dev->transceiver) { - otg_put_transceiver(dev->transceiver); + usb_put_transceiver(dev->transceiver); dev->transceiver = NULL; } clk_put(dev->clk); @@ -2280,7 +2280,7 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev) clk_put(dev->clk); if (dev->transceiver) { - otg_put_transceiver(dev->transceiver); + usb_put_transceiver(dev->transceiver); dev->transceiver = NULL; } diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index f4c44eb806c3..1906ed0dcdc2 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1666,7 +1666,7 @@ static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) udc = to_gadget_udc(_gadget); if (udc->transceiver) - return otg_set_power(udc->transceiver, mA); + return usb_phy_set_power(udc->transceiver, mA); return -EOPNOTSUPP; } @@ -2463,7 +2463,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) udc->dev = &pdev->dev; udc->mach = pdev->dev.platform_data; - udc->transceiver = otg_get_transceiver(); + udc->transceiver = usb_get_transceiver(); gpio = udc->mach->gpio_pullup; if (gpio_is_valid(gpio)) { @@ -2542,7 +2542,7 @@ static int __exit pxa_udc_remove(struct platform_device *_dev) if (gpio_is_valid(gpio)) gpio_free(gpio); - otg_put_transceiver(udc->transceiver); + usb_put_transceiver(udc->transceiver); udc->transceiver = NULL; platform_set_drvdata(_dev, NULL); diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index dea475a61fd3..e124bfa399f5 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -1243,7 +1243,7 @@ static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA) return -ENODEV; if (hsudc->transceiver) - return otg_set_power(hsudc->transceiver, mA); + return usb_phy_set_power(hsudc->transceiver, mA); return -EOPNOTSUPP; } @@ -1275,7 +1275,7 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev) hsudc->dev = dev; hsudc->pd = pdev->dev.platform_data; - hsudc->transceiver = otg_get_transceiver(); + hsudc->transceiver = usb_get_transceiver(); for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++) hsudc->supplies[i].supply = s3c_hsudc_supply_names[i]; @@ -1377,7 +1377,7 @@ err_remap: release_mem_region(res->start, resource_size(res)); err_res: if (hsudc->transceiver) - otg_put_transceiver(hsudc->transceiver); + usb_put_transceiver(hsudc->transceiver); regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies); err_supplies: diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index b556a72264d1..481effdc7f54 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -142,7 +142,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, if (pdata->operating_mode == FSL_USB2_DR_OTG) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - ehci->transceiver = otg_get_transceiver(); + ehci->transceiver = usb_get_transceiver(); dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, transceiver=0x%p\n", hcd, ehci, ehci->transceiver); diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index ef7c4319c6e4..d8db5ecf5e37 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -32,7 +32,7 @@ #define MSM_USB_BASE (hcd->regs) -static struct usb_phy *otg; +static struct usb_phy *phy; static int ehci_msm_reset(struct usb_hcd *hcd) { @@ -145,14 +145,14 @@ static int ehci_msm_probe(struct platform_device *pdev) * powering up VBUS, mapping of registers address space and power * management. */ - otg = otg_get_transceiver(); - if (!otg) { + phy = usb_get_transceiver(); + if (!phy) { dev_err(&pdev->dev, "unable to find transceiver\n"); ret = -ENODEV; goto unmap; } - ret = otg_set_host(otg, &hcd->self); + ret = otg_set_host(phy, &hcd->self); if (ret < 0) { dev_err(&pdev->dev, "unable to register with transceiver\n"); goto put_transceiver; @@ -169,7 +169,7 @@ static int ehci_msm_probe(struct platform_device *pdev) return 0; put_transceiver: - otg_put_transceiver(otg); + usb_put_transceiver(phy); unmap: iounmap(hcd->regs); put_hcd: @@ -186,8 +186,8 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); - otg_set_host(otg, NULL); - otg_put_transceiver(otg); + otg_set_host(phy, NULL); + usb_put_transceiver(phy); usb_put_hcd(hcd); diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 39ca79e008d9..62a63b598149 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -253,7 +253,7 @@ static int mv_ehci_probe(struct platform_device *pdev) ehci_mv->mode = pdata->mode; if (ehci_mv->mode == MV_USB_MODE_OTG) { #ifdef CONFIG_USB_OTG_UTILS - ehci_mv->otg = otg_get_transceiver(); + ehci_mv->otg = usb_get_transceiver(); if (!ehci_mv->otg) { dev_err(&pdev->dev, "unable to find transceiver\n"); @@ -303,7 +303,7 @@ err_set_vbus: #ifdef CONFIG_USB_OTG_UTILS err_put_transceiver: if (ehci_mv->otg) - otg_put_transceiver(ehci_mv->otg); + usb_put_transceiver(ehci_mv->otg); #endif err_disable_clk: mv_ehci_disable(ehci_mv); @@ -333,7 +333,7 @@ static int mv_ehci_remove(struct platform_device *pdev) if (ehci_mv->otg) { otg_set_host(ehci_mv->otg, NULL); - otg_put_transceiver(ehci_mv->otg); + usb_put_transceiver(ehci_mv->otg); } if (ehci_mv->mode == MV_USB_MODE_HOST) { diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index 55978fcfa4b2..b762fe0955b9 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -220,7 +220,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) /* Initialize the transceiver */ if (pdata->otg) { pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET; - ret = otg_init(pdata->otg); + ret = usb_phy_init(pdata->otg); if (ret) { dev_err(dev, "unable to init transceiver, probably missing\n"); ret = -ENODEV; @@ -247,9 +247,11 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) * It's in violation of USB specs */ if (machine_is_mx51_efikamx() || machine_is_mx51_efikasb()) { - flags = otg_io_read(pdata->otg, ULPI_OTG_CTRL); + flags = usb_phy_io_read(pdata->otg, + ULPI_OTG_CTRL); flags |= ULPI_OTG_CTRL_CHRGVBUS; - ret = otg_io_write(pdata->otg, flags, ULPI_OTG_CTRL); + ret = usb_phy_io_write(pdata->otg, flags, + ULPI_OTG_CTRL); if (ret) { dev_err(dev, "unable to set CHRVBUS\n"); goto err_add; @@ -297,7 +299,7 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) pdata->exit(pdev); if (pdata->otg) - otg_shutdown(pdata->otg); + usb_phy_shutdown(pdata->otg); usb_remove_hcd(hcd); iounmap(hcd->regs); diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 2e157144dcf6..701a0bf58623 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -733,7 +733,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) #ifdef CONFIG_USB_OTG_UTILS if (pdata->operating_mode == TEGRA_USB_OTG) { - tegra->transceiver = otg_get_transceiver(); + tegra->transceiver = usb_get_transceiver(); if (tegra->transceiver) otg_set_host(tegra->transceiver, &hcd->self); } @@ -751,7 +751,7 @@ fail: #ifdef CONFIG_USB_OTG_UTILS if (tegra->transceiver) { otg_set_host(tegra->transceiver, NULL); - otg_put_transceiver(tegra->transceiver); + usb_put_transceiver(tegra->transceiver); } #endif tegra_usb_phy_close(tegra->phy); @@ -809,7 +809,7 @@ static int tegra_ehci_remove(struct platform_device *pdev) #ifdef CONFIG_USB_OTG_UTILS if (tegra->transceiver) { otg_set_host(tegra->transceiver, NULL); - otg_put_transceiver(tegra->transceiver); + usb_put_transceiver(tegra->transceiver); } #endif diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index db3968656d21..744e25da800f 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -210,7 +210,7 @@ static int ohci_omap_init(struct usb_hcd *hcd) #ifdef CONFIG_USB_OTG if (need_transceiver) { - ohci->transceiver = otg_get_transceiver(); + ohci->transceiver = usb_get_transceiver(); if (ohci->transceiver) { int status = otg_set_host(ohci->transceiver, &ohci_to_hcd(ohci)->self); diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index cb942b6cfe2b..ba96740de896 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -364,7 +364,7 @@ static int am35x_musb_init(struct musb *musb) return -ENODEV; usb_nop_xceiv_register(); - musb->xceiv = otg_get_transceiver(); + musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) return -ENODEV; @@ -406,7 +406,7 @@ static int am35x_musb_exit(struct musb *musb) if (data->set_phy_power) data->set_phy_power(0); - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index fc8e9edbcb82..5fefd656671b 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -415,7 +415,7 @@ static int bfin_musb_init(struct musb *musb) gpio_direction_output(musb->config->gpio_vrsel, 0); usb_nop_xceiv_register(); - musb->xceiv = otg_get_transceiver(); + musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) { gpio_free(musb->config->gpio_vrsel); return -ENODEV; @@ -440,7 +440,7 @@ static int bfin_musb_exit(struct musb *musb) { gpio_free(musb->config->gpio_vrsel); - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; } diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index f0cb7767fa6a..bd38119bc66c 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -425,7 +425,7 @@ static int da8xx_musb_init(struct musb *musb) goto fail; usb_nop_xceiv_register(); - musb->xceiv = otg_get_transceiver(); + musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) goto fail; @@ -458,7 +458,7 @@ static int da8xx_musb_exit(struct musb *musb) phy_off(); - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index f2a63dd0dfce..49a47d244a27 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -384,7 +384,7 @@ static int davinci_musb_init(struct musb *musb) u32 revision; usb_nop_xceiv_register(); - musb->xceiv = otg_get_transceiver(); + musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) return -ENODEV; @@ -443,7 +443,7 @@ static int davinci_musb_init(struct musb *musb) return 0; fail: - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return -ENODEV; } @@ -492,7 +492,7 @@ static int davinci_musb_exit(struct musb *musb) phy_off(); - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index f9ecd5ebf267..7e9be74dba4d 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -131,9 +131,9 @@ static inline struct musb *dev_to_musb(struct device *dev) /*-------------------------------------------------------------------------*/ #ifndef CONFIG_BLACKFIN -static int musb_ulpi_read(struct usb_phy *otg, u32 offset) +static int musb_ulpi_read(struct usb_phy *phy, u32 offset) { - void __iomem *addr = otg->io_priv; + void __iomem *addr = phy->io_priv; int i = 0; u8 r; u8 power; @@ -165,10 +165,9 @@ static int musb_ulpi_read(struct usb_phy *otg, u32 offset) return musb_readb(addr, MUSB_ULPI_REG_DATA); } -static int musb_ulpi_write(struct usb_phy *otg, - u32 offset, u32 data) +static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) { - void __iomem *addr = otg->io_priv; + void __iomem *addr = phy->io_priv; int i = 0; u8 r = 0; u8 power; @@ -200,7 +199,7 @@ static int musb_ulpi_write(struct usb_phy *otg, #define musb_ulpi_write NULL #endif -static struct otg_io_access_ops musb_ulpi_access = { +static struct usb_phy_io_ops musb_ulpi_access = { .read = musb_ulpi_read, .write = musb_ulpi_write, }; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 0524a34be3c7..3a1793663d91 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1703,7 +1703,7 @@ static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA) if (!musb->xceiv->set_power) return -EOPNOTSUPP; - return otg_set_power(musb->xceiv, mA); + return usb_phy_set_power(musb->xceiv, mA); } static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on) diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index a427fcb13430..96a3d3763cc4 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -247,7 +247,7 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work) if (!is_otg_enabled(musb) || musb->gadget_driver) { pm_runtime_get_sync(musb->controller); - otg_init(musb->xceiv); + usb_phy_init(musb->xceiv); omap2430_musb_set_vbus(musb, 1); } break; @@ -257,7 +257,7 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work) if (musb->gadget_driver) pm_runtime_get_sync(musb->controller); - otg_init(musb->xceiv); + usb_phy_init(musb->xceiv); break; case USB_EVENT_NONE: @@ -273,7 +273,7 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work) if (musb->xceiv->set_vbus) otg_set_vbus(musb->xceiv, 0); } - otg_shutdown(musb->xceiv); + usb_phy_shutdown(musb->xceiv); break; default: dev_dbg(musb->controller, "ID float\n"); @@ -291,7 +291,7 @@ static int omap2430_musb_init(struct musb *musb) * up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. */ - musb->xceiv = otg_get_transceiver(); + musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) { pr_err("HS USB OTG: no transceiver configured\n"); return -ENODEV; @@ -326,7 +326,7 @@ static int omap2430_musb_init(struct musb *musb) musb_readl(musb->mregs, OTG_SIMENABLE)); musb->nb.notifier_call = musb_otg_notifications; - status = otg_register_notifier(musb->xceiv, &musb->nb); + status = usb_register_notifier(musb->xceiv, &musb->nb); if (status) dev_dbg(musb->controller, "notification register failed\n"); @@ -350,7 +350,7 @@ static void omap2430_musb_enable(struct musb *musb) switch (musb->xceiv->last_event) { case USB_EVENT_ID: - otg_init(musb->xceiv); + usb_phy_init(musb->xceiv); if (data->interface_type != MUSB_INTERFACE_UTMI) break; devctl = musb_readb(musb->mregs, MUSB_DEVCTL); @@ -369,7 +369,7 @@ static void omap2430_musb_enable(struct musb *musb) break; case USB_EVENT_VBUS: - otg_init(musb->xceiv); + usb_phy_init(musb->xceiv); break; default: @@ -380,7 +380,7 @@ static void omap2430_musb_enable(struct musb *musb) static void omap2430_musb_disable(struct musb *musb) { if (musb->xceiv->last_event) - otg_shutdown(musb->xceiv); + usb_phy_shutdown(musb->xceiv); } static int omap2430_musb_exit(struct musb *musb) @@ -389,7 +389,7 @@ static int omap2430_musb_exit(struct musb *musb) cancel_work_sync(&musb->otg_notifier_work); omap2430_low_level_exit(musb); - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); return 0; } @@ -495,7 +495,7 @@ static int omap2430_runtime_suspend(struct device *dev) OTG_INTERFSEL); omap2430_low_level_exit(musb); - otg_set_suspend(musb->xceiv, 1); + usb_phy_set_suspend(musb->xceiv, 1); return 0; } @@ -509,7 +509,7 @@ static int omap2430_runtime_resume(struct device *dev) musb_writel(musb->mregs, OTG_INTERFSEL, musb->context.otg_interfsel); - otg_set_suspend(musb->xceiv, 0); + usb_phy_set_suspend(musb->xceiv, 0); return 0; } diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 0665c14cc540..496cc0364836 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -1078,7 +1078,7 @@ static int tusb_musb_init(struct musb *musb) int ret; usb_nop_xceiv_register(); - musb->xceiv = otg_get_transceiver(); + musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) return -ENODEV; @@ -1130,7 +1130,7 @@ done: if (sync) iounmap(sync); - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); } return ret; @@ -1146,7 +1146,7 @@ static int tusb_musb_exit(struct musb *musb) iounmap(musb->sync_va); - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; } diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index f7e04bf34a13..0f5667415b78 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -37,7 +37,7 @@ struct ux500_glue { static int ux500_musb_init(struct musb *musb) { - musb->xceiv = otg_get_transceiver(); + musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) { pr_err("HS USB OTG: no transceiver configured\n"); return -ENODEV; @@ -48,7 +48,7 @@ static int ux500_musb_init(struct musb *musb) static int ux500_musb_exit(struct musb *musb) { - otg_put_transceiver(musb->xceiv); + usb_put_transceiver(musb->xceiv); return 0; } @@ -160,7 +160,7 @@ static int ux500_suspend(struct device *dev) struct ux500_glue *glue = dev_get_drvdata(dev); struct musb *musb = glue_to_musb(glue); - otg_set_suspend(musb->xceiv, 1); + usb_phy_set_suspend(musb->xceiv, 1); clk_disable(glue->clk); return 0; @@ -178,7 +178,7 @@ static int ux500_resume(struct device *dev) return ret; } - otg_set_suspend(musb->xceiv, 0); + usb_phy_set_suspend(musb->xceiv, 0); return 0; } From 136ced891ad2762dfe5ba476103e82ea2b9aff41 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:19 +0200 Subject: [PATCH 149/269] usb: otg: Remove OTG specific members from usb_phy All the drivers are now converted to use struct usb_otg, so removing the OTG specific members from struct usb_phy. Signed-off-by: Heikki Krogerus Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- include/linux/usb/otg.h | 50 +++++------------------------------------ 1 file changed, 5 insertions(+), 45 deletions(-) diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 5c1cfbc73555..de89342098e4 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -89,15 +89,11 @@ struct usb_phy { const char *label; unsigned int flags; - u8 default_a; enum usb_otg_state state; enum usb_phy_events last_event; struct usb_otg *otg; - struct usb_bus *host; - struct usb_gadget *gadget; - struct usb_phy_io_ops *io_ops; void __iomem *io_priv; @@ -112,32 +108,14 @@ struct usb_phy { int (*init)(struct usb_phy *x); void (*shutdown)(struct usb_phy *x); - /* bind/unbind the host controller */ - int (*set_host)(struct usb_phy *x, - struct usb_bus *host); - - /* bind/unbind the peripheral controller */ - int (*set_peripheral)(struct usb_phy *x, - struct usb_gadget *gadget); - /* effective for B devices, ignored for A-peripheral */ int (*set_power)(struct usb_phy *x, unsigned mA); - /* effective for A-peripheral, ignored for B devices */ - int (*set_vbus)(struct usb_phy *x, - bool enabled); - /* for non-OTG B devices: set transceiver into suspend mode */ int (*set_suspend)(struct usb_phy *x, int suspend); - /* for B devices only: start session with A-Host */ - int (*start_srp)(struct usb_phy *x); - - /* start or continue HNP role switch */ - int (*start_hnp)(struct usb_phy *x); - }; @@ -219,7 +197,7 @@ otg_start_hnp(struct usb_phy *x) if (x->otg && x->otg->start_hnp) return x->otg->start_hnp(x->otg); - return x->start_hnp(x); + return -ENOTSUPP; } /* Context: can sleep */ @@ -229,7 +207,7 @@ otg_set_vbus(struct usb_phy *x, bool enabled) if (x->otg && x->otg->set_vbus) return x->otg->set_vbus(x->otg, enabled); - return x->set_vbus(x, enabled); + return -ENOTSUPP; } /* for HCDs */ @@ -239,7 +217,7 @@ otg_set_host(struct usb_phy *x, struct usb_bus *host) if (x->otg && x->otg->set_host) return x->otg->set_host(x->otg, host); - return x->set_host(x, host); + return -ENOTSUPP; } /* for usb peripheral controller drivers */ @@ -251,7 +229,7 @@ otg_set_peripheral(struct usb_phy *x, struct usb_gadget *periph) if (x->otg && x->otg->set_peripheral) return x->otg->set_peripheral(x->otg, periph); - return x->set_peripheral(x, periph); + return -ENOTSUPP; } static inline int @@ -278,7 +256,7 @@ otg_start_srp(struct usb_phy *x) if (x->otg && x->otg->start_srp) return x->otg->start_srp(x->otg); - return x->start_srp(x); + return -ENOTSUPP; } /* notifiers */ @@ -297,22 +275,4 @@ usb_unregister_notifier(struct usb_phy *x, struct notifier_block *nb) /* for OTG controller drivers (and maybe other stuff) */ extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num); -/* Temporary aliases for transceiver functions */ -#define otg_set_transceiver(x) usb_set_transceiver(x) -#define otg_get_transceiver() usb_get_transceiver() -#define otg_put_transceiver(x) usb_put_transceiver(x) - -#define otg_io_read(x, a) usb_phy_io_read(x, a) -#define otg_io_write(x, a, b) usb_phy_io_write(x, a, b) - -#define otg_init(x) usb_phy_init(x) -#define otg_shutdown(x) usb_phy_shutdown(x) -#define otg_set_power(x, a) usb_phy_set_power(x, a) -#define otg_set_suspend(x, a) usb_phy_set_suspend(x, a) - -#define otg_register_notifier(x, a) usb_register_notifier(x, a) -#define otg_unregister_notifier(x, a) usb_unregiser_notifier(x, a) - -#define otg_io_access_ops usb_phy_io_ops - #endif /* __LINUX_USB_OTG_H */ From 6e13c6505cdff9766d5268ffb8c972c1a2f996e6 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 13 Feb 2012 13:24:20 +0200 Subject: [PATCH 150/269] usb: otg: Convert all users to pass struct usb_otg for OTG functions This changes the otg functions so that they receive struct otg instead of struct usb_phy as parameter and converts all users of these functions to pass the otg member of their usb_phy. Includes fixes to IMX code from Sascha Hauer. [ balbi@ti.com : fixed a compile warning on ehci-mv.c ] Signed-off-by: Heikki Krogerus Acked-by: Sascha Hauer Acked-by: Igor Grinberg Acked-by: Pavankumar Kondeti Acked-by: Li Yang Acked-by: Alan Stern Reviewed-by: Marek Vasut Signed-off-by: Felipe Balbi --- arch/arm/mach-pxa/pxa3xx-ulpi.c | 8 ++++---- drivers/usb/gadget/ci13xxx_udc.c | 7 ++++--- drivers/usb/gadget/fsl_udc_core.c | 5 +++-- drivers/usb/gadget/langwell_udc.c | 2 +- drivers/usb/gadget/mv_udc_core.c | 3 ++- drivers/usb/gadget/omap_udc.c | 7 ++++--- drivers/usb/gadget/pxa25x_udc.c | 5 +++-- drivers/usb/gadget/pxa27x_udc.c | 5 +++-- drivers/usb/gadget/s3c-hsudc.c | 5 +++-- drivers/usb/host/ehci-fsl.c | 4 ++-- drivers/usb/host/ehci-hub.c | 2 +- drivers/usb/host/ehci-msm.c | 4 ++-- drivers/usb/host/ehci-mv.c | 4 ++-- drivers/usb/host/ehci-mxc.c | 2 +- drivers/usb/host/ehci-tegra.c | 6 +++--- drivers/usb/host/ohci-omap.c | 6 +++--- drivers/usb/musb/musb_core.c | 2 +- drivers/usb/musb/musb_gadget.c | 8 ++++---- drivers/usb/musb/omap2430.c | 8 ++++---- include/linux/usb/otg.h | 30 +++++++++++++++--------------- 20 files changed, 65 insertions(+), 58 deletions(-) diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c index a13f33565623..5ead6d480c6d 100644 --- a/arch/arm/mach-pxa/pxa3xx-ulpi.c +++ b/arch/arm/mach-pxa/pxa3xx-ulpi.c @@ -145,13 +145,13 @@ static int pxa310_start_otg_host_transcvr(struct usb_bus *host) return err; } - err = otg_set_vbus(u2d->otg, 1); + err = otg_set_vbus(u2d->otg->otg, 1); if (err) { pr_err("OTG transceiver VBUS set failed"); return err; } - err = otg_set_host(u2d->otg, host); + err = otg_set_host(u2d->otg->otg, host); if (err) pr_err("OTG transceiver Host mode set failed"); @@ -189,8 +189,8 @@ static void pxa310_stop_otg_hc(void) { pxa310_otg_transceiver_rtsm(); - otg_set_host(u2d->otg, NULL); - otg_set_vbus(u2d->otg, 0); + otg_set_host(u2d->otg->otg, NULL); + otg_set_vbus(u2d->otg->otg, 0); usb_phy_shutdown(u2d->otg); } diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 68ad160f2589..b27cb0b0077b 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -2928,7 +2928,8 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev, goto unreg_device; if (udc->transceiver) { - retval = otg_set_peripheral(udc->transceiver, &udc->gadget); + retval = otg_set_peripheral(udc->transceiver->otg, + &udc->gadget); if (retval) goto remove_dbg; } @@ -2945,7 +2946,7 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev, remove_trans: if (udc->transceiver) { - otg_set_peripheral(udc->transceiver, &udc->gadget); + otg_set_peripheral(udc->transceiver->otg, &udc->gadget); usb_put_transceiver(udc->transceiver); } @@ -2981,7 +2982,7 @@ static void udc_remove(void) usb_del_gadget_udc(&udc->gadget); if (udc->transceiver) { - otg_set_peripheral(udc->transceiver, &udc->gadget); + otg_set_peripheral(udc->transceiver->otg, &udc->gadget); usb_put_transceiver(udc->transceiver); } #ifdef CONFIG_USB_GADGET_DEBUG_FILES diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 21fdfdb18ba8..1e8c0c425fa1 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1966,7 +1966,8 @@ static int fsl_start(struct usb_gadget_driver *driver, /* connect to bus through transceiver */ if (udc_controller->transceiver) { - retval = otg_set_peripheral(udc_controller->transceiver, + retval = otg_set_peripheral( + udc_controller->transceiver->otg, &udc_controller->gadget); if (retval < 0) { ERR("can't bind to transceiver\n"); @@ -2006,7 +2007,7 @@ static int fsl_stop(struct usb_gadget_driver *driver) return -EINVAL; if (udc_controller->transceiver) - otg_set_peripheral(udc_controller->transceiver, NULL); + otg_set_peripheral(udc_controller->transceiver->otg, NULL); /* stop DR, disable intr */ dr_controller_stop(udc_controller); diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index b19a9e46e69d..42a88b680f25 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -1906,7 +1906,7 @@ static int langwell_stop(struct usb_gadget *g, /* unbind OTG transceiver */ if (dev->transceiver) - (void)otg_set_peripheral(dev->transceiver, 0); + (void)otg_set_peripheral(dev->transceiver->otg, 0); /* disable interrupt and set controller to stop state */ langwell_udc_stop(dev); diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 50baf3ea336b..7369fd92c03f 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -1384,7 +1384,8 @@ static int mv_udc_start(struct usb_gadget_driver *driver, } if (udc->transceiver) { - retval = otg_set_peripheral(udc->transceiver, &udc->gadget); + retval = otg_set_peripheral(udc->transceiver->otg, + &udc->gadget); if (retval) { dev_err(&udc->dev->dev, "unable to register peripheral to otg\n"); diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index e82c6995ce26..ace8a652b32b 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -1213,7 +1213,7 @@ static int omap_wakeup(struct usb_gadget *gadget) /* NOTE: non-OTG systems may use SRP TOO... */ } else if (!(udc->devstat & UDC_ATT)) { if (udc->transceiver) - retval = otg_start_srp(udc->transceiver); + retval = otg_start_srp(udc->transceiver->otg); } spin_unlock_irqrestore(&udc->lock, flags); @@ -2156,7 +2156,8 @@ static int omap_udc_start(struct usb_gadget_driver *driver, /* connect to bus through transceiver */ if (udc->transceiver) { - status = otg_set_peripheral(udc->transceiver, &udc->gadget); + status = otg_set_peripheral(udc->transceiver->otg, + &udc->gadget); if (status < 0) { ERR("can't bind to transceiver\n"); if (driver->unbind) { @@ -2202,7 +2203,7 @@ static int omap_udc_stop(struct usb_gadget_driver *driver) omap_vbus_session(&udc->gadget, 0); if (udc->transceiver) - (void) otg_set_peripheral(udc->transceiver, NULL); + (void) otg_set_peripheral(udc->transceiver->otg, NULL); else pullup_disable(udc); diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index b86518e49415..df681b5cd695 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -1301,7 +1301,8 @@ fail: /* connect to bus through transceiver */ if (dev->transceiver) { - retval = otg_set_peripheral(dev->transceiver, &dev->gadget); + retval = otg_set_peripheral(dev->transceiver->otg, + &dev->gadget); if (retval) { DMSG("can't bind to transceiver\n"); if (driver->unbind) @@ -1360,7 +1361,7 @@ static int pxa25x_stop(struct usb_gadget_driver *driver) local_irq_enable(); if (dev->transceiver) - (void) otg_set_peripheral(dev->transceiver, NULL); + (void) otg_set_peripheral(dev->transceiver->otg, NULL); driver->unbind(&dev->gadget); dev->gadget.dev.driver = NULL; diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 1906ed0dcdc2..98acb3ab9e17 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1835,7 +1835,8 @@ static int pxa27x_udc_start(struct usb_gadget_driver *driver, driver->driver.name); if (udc->transceiver) { - retval = otg_set_peripheral(udc->transceiver, &udc->gadget); + retval = otg_set_peripheral(udc->transceiver->otg, + &udc->gadget); if (retval) { dev_err(udc->dev, "can't bind to transceiver\n"); goto transceiver_fail; @@ -1908,7 +1909,7 @@ static int pxa27x_udc_stop(struct usb_gadget_driver *driver) driver->driver.name); if (udc->transceiver) - return otg_set_peripheral(udc->transceiver, NULL); + return otg_set_peripheral(udc->transceiver->otg, NULL); return 0; } diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index e124bfa399f5..c2f3aa650584 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -1166,7 +1166,8 @@ static int s3c_hsudc_start(struct usb_gadget *gadget, /* connect to bus through transceiver */ if (hsudc->transceiver) { - ret = otg_set_peripheral(hsudc->transceiver, &hsudc->gadget); + ret = otg_set_peripheral(hsudc->transceiver->otg, + &hsudc->gadget); if (ret) { dev_err(hsudc->dev, "%s: can't bind to transceiver\n", hsudc->gadget.name); @@ -1214,7 +1215,7 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget, spin_unlock_irqrestore(&hsudc->lock, flags); if (hsudc->transceiver) - (void) otg_set_peripheral(hsudc->transceiver, NULL); + (void) otg_set_peripheral(hsudc->transceiver->otg, NULL); disable_irq(hsudc->irq); diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 481effdc7f54..4786ba5f2e6c 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -147,7 +147,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, hcd, ehci, ehci->transceiver); if (ehci->transceiver) { - retval = otg_set_host(ehci->transceiver, + retval = otg_set_host(ehci->transceiver->otg, &ehci_to_hcd(ehci)->self); if (retval) { if (ehci->transceiver) @@ -194,7 +194,7 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd, struct ehci_hcd *ehci = hcd_to_ehci(hcd); if (ehci->transceiver) { - otg_set_host(ehci->transceiver, NULL); + otg_set_host(ehci->transceiver->otg, NULL); put_device(ehci->transceiver->dev); } diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 77bbb2357e47..75a2b30d8aa6 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -727,7 +727,7 @@ static int ehci_hub_control ( #ifdef CONFIG_USB_OTG if ((hcd->self.otg_port == (wIndex + 1)) && hcd->self.b_hnp_enable) { - otg_start_hnp(ehci->transceiver); + otg_start_hnp(ehci->transceiver->otg); break; } #endif diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index d8db5ecf5e37..9803a55fd5f4 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -152,7 +152,7 @@ static int ehci_msm_probe(struct platform_device *pdev) goto unmap; } - ret = otg_set_host(phy, &hcd->self); + ret = otg_set_host(phy->otg, &hcd->self); if (ret < 0) { dev_err(&pdev->dev, "unable to register with transceiver\n"); goto put_transceiver; @@ -186,7 +186,7 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); - otg_set_host(phy, NULL); + otg_set_host(phy->otg, NULL); usb_put_transceiver(phy); usb_put_hcd(hcd); diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 62a63b598149..a936bbcff8f4 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -261,7 +261,7 @@ static int mv_ehci_probe(struct platform_device *pdev) goto err_disable_clk; } - retval = otg_set_host(ehci_mv->otg, &hcd->self); + retval = otg_set_host(ehci_mv->otg->otg, &hcd->self); if (retval < 0) { dev_err(&pdev->dev, "unable to register with transceiver\n"); @@ -332,7 +332,7 @@ static int mv_ehci_remove(struct platform_device *pdev) usb_remove_hcd(hcd); if (ehci_mv->otg) { - otg_set_host(ehci_mv->otg, NULL); + otg_set_host(ehci_mv->otg->otg, NULL); usb_put_transceiver(ehci_mv->otg); } diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index b762fe0955b9..a797d51ecbe8 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -226,7 +226,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) ret = -ENODEV; goto err_add; } - ret = otg_set_vbus(pdata->otg, 1); + ret = otg_set_vbus(pdata->otg->otg, 1); if (ret) { dev_err(dev, "unable to enable vbus on transceiver\n"); goto err_add; diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 701a0bf58623..3de48a2d7955 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -735,7 +735,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) if (pdata->operating_mode == TEGRA_USB_OTG) { tegra->transceiver = usb_get_transceiver(); if (tegra->transceiver) - otg_set_host(tegra->transceiver, &hcd->self); + otg_set_host(tegra->transceiver->otg, &hcd->self); } #endif @@ -750,7 +750,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) fail: #ifdef CONFIG_USB_OTG_UTILS if (tegra->transceiver) { - otg_set_host(tegra->transceiver, NULL); + otg_set_host(tegra->transceiver->otg, NULL); usb_put_transceiver(tegra->transceiver); } #endif @@ -808,7 +808,7 @@ static int tegra_ehci_remove(struct platform_device *pdev) #ifdef CONFIG_USB_OTG_UTILS if (tegra->transceiver) { - otg_set_host(tegra->transceiver, NULL); + otg_set_host(tegra->transceiver->otg, NULL); usb_put_transceiver(tegra->transceiver); } #endif diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 744e25da800f..96451e41ee8a 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -171,7 +171,7 @@ static void start_hnp(struct ohci_hcd *ohci) unsigned long flags; u32 l; - otg_start_hnp(ohci->transceiver); + otg_start_hnp(ohci->transceiver->otg); local_irq_save(flags); ohci->transceiver->state = OTG_STATE_A_SUSPEND; @@ -212,7 +212,7 @@ static int ohci_omap_init(struct usb_hcd *hcd) if (need_transceiver) { ohci->transceiver = usb_get_transceiver(); if (ohci->transceiver) { - int status = otg_set_host(ohci->transceiver, + int status = otg_set_host(ohci->transceiver->otg, &ohci_to_hcd(ohci)->self); dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n", ohci->transceiver->label, status); @@ -404,7 +404,7 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) usb_remove_hcd(hcd); if (ohci->transceiver) { - (void) otg_set_host(ohci->transceiver, 0); + (void) otg_set_host(ohci->transceiver->otg, 0); put_device(ohci->transceiver->dev); } if (machine_is_omap_osk()) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 7e9be74dba4d..88bf453e33da 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1961,7 +1961,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) if (is_host_enabled(musb)) { struct usb_hcd *hcd = musb_to_hcd(musb); - otg_set_host(musb->xceiv, &hcd->self); + otg_set_host(musb->xceiv->otg, &hcd->self); if (is_otg_enabled(musb)) hcd->self.otg_port = 1; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 3a1793663d91..caeaf9f96f73 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1624,7 +1624,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget) } spin_unlock_irqrestore(&musb->lock, flags); - otg_start_srp(musb->xceiv); + otg_start_srp(musb->xceiv->otg); spin_lock_irqsave(&musb->lock, flags); /* Block idling for at least 1s */ @@ -1915,7 +1915,7 @@ static int musb_gadget_start(struct usb_gadget *g, spin_lock_irqsave(&musb->lock, flags); musb->is_active = 1; - otg_set_peripheral(musb->xceiv, &musb->g); + otg_set_peripheral(otg, &musb->g); musb->xceiv->state = OTG_STATE_B_IDLE; /* @@ -1947,7 +1947,7 @@ static int musb_gadget_start(struct usb_gadget *g, if ((musb->xceiv->last_event == USB_EVENT_ID) && otg->set_vbus) - otg_set_vbus(musb->xceiv, 1); + otg_set_vbus(otg, 1); hcd->self.uses_pio_for_control = 1; } @@ -2029,7 +2029,7 @@ static int musb_gadget_stop(struct usb_gadget *g, musb->xceiv->state = OTG_STATE_UNDEFINED; stop_activity(musb, driver); - otg_set_peripheral(musb->xceiv, NULL); + otg_set_peripheral(musb->xceiv->otg, NULL); dev_dbg(musb->controller, "unregistering driver %s\n", driver->function); diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 96a3d3763cc4..d8df60a9fc2a 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -164,8 +164,8 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) } } - if (ret && musb->xceiv->set_vbus) - otg_set_vbus(musb->xceiv, 1); + if (ret && otg->set_vbus) + otg_set_vbus(otg, 1); } else { musb->is_active = 1; otg->default_a = 1; @@ -270,8 +270,8 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work) } if (data->interface_type == MUSB_INTERFACE_UTMI) { - if (musb->xceiv->set_vbus) - otg_set_vbus(musb->xceiv, 0); + if (musb->xceiv->otg->set_vbus) + otg_set_vbus(musb->xceiv->otg, 0); } usb_phy_shutdown(musb->xceiv); break; diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index de89342098e4..f67810f8f21b 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -192,30 +192,30 @@ static inline const char *otg_state_string(enum usb_otg_state state) /* Context: can sleep */ static inline int -otg_start_hnp(struct usb_phy *x) +otg_start_hnp(struct usb_otg *otg) { - if (x->otg && x->otg->start_hnp) - return x->otg->start_hnp(x->otg); + if (otg && otg->start_hnp) + return otg->start_hnp(otg); return -ENOTSUPP; } /* Context: can sleep */ static inline int -otg_set_vbus(struct usb_phy *x, bool enabled) +otg_set_vbus(struct usb_otg *otg, bool enabled) { - if (x->otg && x->otg->set_vbus) - return x->otg->set_vbus(x->otg, enabled); + if (otg && otg->set_vbus) + return otg->set_vbus(otg, enabled); return -ENOTSUPP; } /* for HCDs */ static inline int -otg_set_host(struct usb_phy *x, struct usb_bus *host) +otg_set_host(struct usb_otg *otg, struct usb_bus *host) { - if (x->otg && x->otg->set_host) - return x->otg->set_host(x->otg, host); + if (otg && otg->set_host) + return otg->set_host(otg, host); return -ENOTSUPP; } @@ -224,10 +224,10 @@ otg_set_host(struct usb_phy *x, struct usb_bus *host) /* Context: can sleep */ static inline int -otg_set_peripheral(struct usb_phy *x, struct usb_gadget *periph) +otg_set_peripheral(struct usb_otg *otg, struct usb_gadget *periph) { - if (x->otg && x->otg->set_peripheral) - return x->otg->set_peripheral(x->otg, periph); + if (otg && otg->set_peripheral) + return otg->set_peripheral(otg, periph); return -ENOTSUPP; } @@ -251,10 +251,10 @@ usb_phy_set_suspend(struct usb_phy *x, int suspend) } static inline int -otg_start_srp(struct usb_phy *x) +otg_start_srp(struct usb_otg *otg) { - if (x->otg && x->otg->start_srp) - return x->otg->start_srp(x->otg); + if (otg && otg->start_srp) + return otg->start_srp(otg); return -ENOTSUPP; } From 170b778ffbfca8619b6971e8a5e8b864712b72e2 Mon Sep 17 00:00:00 2001 From: Cyril Roelandt Date: Sat, 25 Feb 2012 02:14:57 +0100 Subject: [PATCH 151/269] usb: amd5536udc: Fix brace coding style issues. Remove a bunch of unneeded braces. Signed-off-by: Cyril Roelandt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/amd5536udc.c | 93 +++++++++++++-------------------- 1 file changed, 36 insertions(+), 57 deletions(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 18883bd0f162..7df2f7082908 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -204,9 +204,8 @@ static void print_regs(struct udc *dev) DBG(dev, "DMA mode = BF (buffer fill mode)\n"); dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "BF"); } - if (!use_dma) { + if (!use_dma) dev_info(&dev->pdev->dev, "FIFO mode\n"); - } DBG(dev, "-------------------------------------------------------\n"); } @@ -570,9 +569,8 @@ udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq) VDBG(ep->dev, "req->td_data=%p\n", req->td_data); /* free dma chain if created */ - if (req->chain_len > 1) { + if (req->chain_len > 1) udc_free_dma_chain(ep->dev, req); - } pci_pool_free(ep->dev->data_requests, req->td_data, req->td_phys); @@ -640,9 +638,8 @@ udc_txfifo_write(struct udc_ep *ep, struct usb_request *req) bytes = remaining; /* dwords first */ - for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) { + for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) writel(*(buf + i), ep->txfifo); - } /* remaining bytes must be written by byte access */ for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) { @@ -661,9 +658,8 @@ static int udc_rxfifo_read_dwords(struct udc *dev, u32 *buf, int dwords) VDBG(dev, "udc_read_dwords(): %d dwords\n", dwords); - for (i = 0; i < dwords; i++) { + for (i = 0; i < dwords; i++) *(buf + i) = readl(dev->rxfifo); - } return 0; } @@ -676,9 +672,8 @@ static int udc_rxfifo_read_bytes(struct udc *dev, u8 *buf, int bytes) VDBG(dev, "udc_read_bytes(): %d bytes\n", bytes); /* dwords first */ - for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) { + for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) *((u32 *)(buf + (i<<2))) = readl(dev->rxfifo); - } /* remaining bytes must be read by byte access */ if (bytes % UDC_DWORD_BYTES) { @@ -898,9 +893,8 @@ static struct udc_data_dma *udc_get_last_dma_desc(struct udc_request *req) struct udc_data_dma *td; td = req->td_data; - while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) { + while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) td = phys_to_virt(td->next); - } return td; @@ -950,21 +944,18 @@ static int udc_create_dma_chain( dma_addr = DMA_DONT_USE; /* unset L bit in first desc for OUT */ - if (!ep->in) { + if (!ep->in) req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L); - } /* alloc only new desc's if not already available */ len = req->req.length / ep->ep.maxpacket; - if (req->req.length % ep->ep.maxpacket) { + if (req->req.length % ep->ep.maxpacket) len++; - } if (len > req->chain_len) { /* shorter chain already allocated before */ - if (req->chain_len > 1) { + if (req->chain_len > 1) udc_free_dma_chain(ep->dev, req); - } req->chain_len = len; create_new_chain = 1; } @@ -1007,11 +998,12 @@ static int udc_create_dma_chain( /* link td and assign tx bytes */ if (i == buf_len) { - if (create_new_chain) { + if (create_new_chain) req->td_data->next = dma_addr; - } else { - /* req->td_data->next = virt_to_phys(td); */ - } + /* + else + req->td_data->next = virt_to_phys(td); + */ /* write tx bytes */ if (ep->in) { /* first desc */ @@ -1025,11 +1017,12 @@ static int udc_create_dma_chain( UDC_DMA_IN_STS_TXBYTES); } } else { - if (create_new_chain) { + if (create_new_chain) last->next = dma_addr; - } else { - /* last->next = virt_to_phys(td); */ - } + /* + else + last->next = virt_to_phys(td); + */ if (ep->in) { /* write tx bytes */ td->status = AMD_ADDBITS(td->status, @@ -1480,11 +1473,10 @@ static int startup_registers(struct udc *dev) /* program speed */ tmp = readl(&dev->regs->cfg); - if (use_fullspeed) { + if (use_fullspeed) tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD); - } else { + else tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD); - } writel(tmp, &dev->regs->cfg); return 0; @@ -1505,9 +1497,8 @@ static void udc_basic_init(struct udc *dev) mod_timer(&udc_timer, jiffies - 1); } /* stop poll stall timer */ - if (timer_pending(&udc_pollstall_timer)) { + if (timer_pending(&udc_pollstall_timer)) mod_timer(&udc_pollstall_timer, jiffies - 1); - } /* disable DMA */ tmp = readl(&dev->regs->ctl); tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_RDE); @@ -1541,11 +1532,10 @@ static void udc_setup_endpoints(struct udc *dev) /* read enum speed */ tmp = readl(&dev->regs->sts); tmp = AMD_GETBITS(tmp, UDC_DEVSTS_ENUM_SPEED); - if (tmp == UDC_DEVSTS_ENUM_SPEED_HIGH) { + if (tmp == UDC_DEVSTS_ENUM_SPEED_HIGH) dev->gadget.speed = USB_SPEED_HIGH; - } else if (tmp == UDC_DEVSTS_ENUM_SPEED_FULL) { + else if (tmp == UDC_DEVSTS_ENUM_SPEED_FULL) dev->gadget.speed = USB_SPEED_FULL; - } /* set basic ep parameters */ for (tmp = 0; tmp < UDC_EP_NUM; tmp++) { @@ -1571,9 +1561,8 @@ static void udc_setup_endpoints(struct udc *dev) * disabling ep interrupts when ENUM interrupt occurs but ep is * not enabled by gadget driver */ - if (!ep->desc) { + if (!ep->desc) ep_init(dev->regs, ep); - } if (use_dma) { /* @@ -1671,9 +1660,8 @@ static void udc_tasklet_disconnect(unsigned long par) spin_lock(&dev->lock); /* empty queues */ - for (tmp = 0; tmp < UDC_EP_NUM; tmp++) { + for (tmp = 0; tmp < UDC_EP_NUM; tmp++) empty_req_queue(&dev->ep[tmp]); - } } @@ -1747,9 +1735,8 @@ static void udc_timer_function(unsigned long v) * open the fifo */ udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV; - if (!stop_timer) { + if (!stop_timer) add_timer(&udc_timer); - } } else { /* * fifo contains data now, setup timer for opening @@ -1761,9 +1748,8 @@ static void udc_timer_function(unsigned long v) set_rde++; /* debug: lhadmot_timer_start = 221070 */ udc_timer.expires = jiffies + HZ*UDC_RDE_TIMER_SECONDS; - if (!stop_timer) { + if (!stop_timer) add_timer(&udc_timer); - } } } else @@ -1908,19 +1894,17 @@ static void activate_control_endpoints(struct udc *dev) mod_timer(&udc_timer, jiffies - 1); } /* stop pollstall timer */ - if (timer_pending(&udc_pollstall_timer)) { + if (timer_pending(&udc_pollstall_timer)) mod_timer(&udc_pollstall_timer, jiffies - 1); - } /* enable DMA */ tmp = readl(&dev->regs->ctl); tmp |= AMD_BIT(UDC_DEVCTL_MODE) | AMD_BIT(UDC_DEVCTL_RDE) | AMD_BIT(UDC_DEVCTL_TDE); - if (use_dma_bufferfill_mode) { + if (use_dma_bufferfill_mode) tmp |= AMD_BIT(UDC_DEVCTL_BF); - } else if (use_dma_ppb_du) { + else if (use_dma_ppb_du) tmp |= AMD_BIT(UDC_DEVCTL_DU); - } writel(tmp, &dev->regs->ctl); } @@ -2105,9 +2089,8 @@ static void udc_ep0_set_rde(struct udc *dev) udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV; set_rde = 1; - if (!stop_timer) { + if (!stop_timer) add_timer(&udc_timer); - } } } } @@ -2295,9 +2278,8 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix) jiffies + HZ*UDC_RDE_TIMER_SECONDS; set_rde = 1; - if (!stop_timer) { + if (!stop_timer) add_timer(&udc_timer); - } } if (ep->num != UDC_EP0OUT_IX) dev->data_ep_queued = 0; @@ -2319,9 +2301,8 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix) /* check pending CNAKS */ if (cnak_pending) { /* CNAk processing when rxfifo empty only */ - if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) { + if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) udc_process_cnak_queue(dev); - } } /* clear OUT bits in ep status */ @@ -2582,9 +2563,8 @@ __acquires(dev->lock) if (!timer_pending(&udc_timer)) { udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV; - if (!stop_timer) { + if (!stop_timer) add_timer(&udc_timer); - } } } @@ -2698,9 +2678,8 @@ __acquires(dev->lock) /* check pending CNAKS */ if (cnak_pending) { /* CNAk processing when rxfifo empty only */ - if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) { + if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) udc_process_cnak_queue(dev); - } } finished: From 5647a149e2b9260530a11c8494b529de56e226ab Mon Sep 17 00:00:00 2001 From: Cyril Roelandt Date: Sat, 25 Feb 2012 02:14:58 +0100 Subject: [PATCH 152/269] usb: amd5536udc: Fix coding style issues. Remove unnecessary whitespaces. Signed-off-by: Cyril Roelandt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/amd5536udc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 7df2f7082908..5e2cc0addb85 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -2115,7 +2115,7 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix) if (use_dma) { /* BNA event ? */ if (tmp & AMD_BIT(UDC_EPSTS_BNA)) { - DBG(dev, "BNA ep%dout occurred - DESPTR = %x \n", + DBG(dev, "BNA ep%dout occurred - DESPTR = %x\n", ep->num, readl(&ep->regs->desptr)); /* clear BNA */ writel(tmp | AMD_BIT(UDC_EPSTS_BNA), &ep->regs->sts); @@ -2330,7 +2330,7 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix) /* BNA ? */ if (epsts & AMD_BIT(UDC_EPSTS_BNA)) { dev_err(&dev->pdev->dev, - "BNA ep%din occurred - DESPTR = %08lx \n", + "BNA ep%din occurred - DESPTR = %08lx\n", ep->num, (unsigned long) readl(&ep->regs->desptr)); @@ -2343,7 +2343,7 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix) /* HE event ? */ if (epsts & AMD_BIT(UDC_EPSTS_HE)) { dev_err(&dev->pdev->dev, - "HE ep%dn occurred - DESPTR = %08lx \n", + "HE ep%dn occurred - DESPTR = %08lx\n", ep->num, (unsigned long) readl(&ep->regs->desptr)); /* clear HE */ @@ -2703,7 +2703,7 @@ static irqreturn_t udc_control_in_isr(struct udc *dev) tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->sts); /* DMA completion */ if (tmp & AMD_BIT(UDC_EPSTS_TDC)) { - VDBG(dev, "isr: TDC clear \n"); + VDBG(dev, "isr: TDC clear\n"); ret_val = IRQ_HANDLED; /* clear TDC bit */ From 1435db486c131b4b76d8e2a261ae6292ffc3f7ca Mon Sep 17 00:00:00 2001 From: Cyril Roelandt Date: Sat, 25 Feb 2012 02:14:59 +0100 Subject: [PATCH 153/269] usb: amd5536udc: Fix indentation Remove an unnecessary level of indentation. Signed-off-by: Cyril Roelandt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/amd5536udc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 5e2cc0addb85..ad72ab72f041 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -2409,9 +2409,9 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix) /* write fifo */ udc_txfifo_write(ep, &req->req); len = req->req.length - req->req.actual; - if (len > ep->ep.maxpacket) - len = ep->ep.maxpacket; - req->req.actual += len; + if (len > ep->ep.maxpacket) + len = ep->ep.maxpacket; + req->req.actual += len; if (req->req.actual == req->req.length || (len != ep->ep.maxpacket)) { /* complete req */ From 1b8860df38963218a30e9f1f39d649c992cb9efa Mon Sep 17 00:00:00 2001 From: Cyril Roelandt Date: Sat, 25 Feb 2012 02:15:00 +0100 Subject: [PATCH 154/269] usb: amd5536udc: use the DEFINE_PCI_DEVICE_TABLE macro Use DEFINE_PCI_DEVICE_TABLE instead of "const struct pci_device_id". Signed-off-by: Cyril Roelandt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/amd5536udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index ad72ab72f041..d28bc245ad52 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3406,7 +3406,7 @@ static int udc_remote_wakeup(struct udc *dev) } /* PCI device parameters */ -static const struct pci_device_id pci_id[] = { +static DEFINE_PCI_DEVICE_TABLE(pci_id) = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096), .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, From 34af373865b91aa4108134b5a4748d40a100111c Mon Sep 17 00:00:00 2001 From: Cyril Roelandt Date: Sun, 26 Feb 2012 16:00:25 +0100 Subject: [PATCH 155/269] usb: amd5536udc: Fix the type of ep_string Use "static const char *const" instead of "static const char *". Signed-off-by: Cyril Roelandt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/amd5536udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index d28bc245ad52..9349c4eb688d 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -140,7 +140,7 @@ static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect, /* endpoint names used for print */ static const char ep0_string[] = "ep0in"; -static const char *ep_string[] = { +static const char *const ep_string[] = { ep0_string, "ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk", "ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk", From c15e03e1553d8fb334de26727b0edadd582a46e7 Mon Sep 17 00:00:00 2001 From: Cyril Roelandt Date: Sat, 25 Feb 2012 02:15:02 +0100 Subject: [PATCH 156/269] usb: amd5536udc: Remove old CVS markers Git does not care about CVS markers. Signed-off-by: Cyril Roelandt Signed-off-by: Felipe Balbi --- drivers/usb/gadget/amd5536udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 9349c4eb688d..1355a2f5e685 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -29,7 +29,7 @@ /* Driver strings */ #define UDC_MOD_DESCRIPTION "AMD 5536 UDC - USB Device Controller" -#define UDC_DRIVER_VERSION_STRING "01.00.0206 - $Revision: #3 $" +#define UDC_DRIVER_VERSION_STRING "01.00.0206" /* system */ #include From a698908d3b3be915ac20cd37faeff1216f6b4fe8 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 15 Dec 2011 13:31:48 +0200 Subject: [PATCH 157/269] usb: gadget: add generic map/unmap request utilities such utilities are currently duplicated on all UDC drivers basically with the same structure. Let's group all implementations into one generic implementation and get rid of that duplication. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc-core.c | 52 +++++++++++++++++++++++++++++++++++ include/linux/usb/gadget.h | 10 +++++++ 2 files changed, 62 insertions(+) diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 0b0d12ccc487..56da49f31d6c 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,57 @@ static DEFINE_MUTEX(udc_lock); /* ------------------------------------------------------------------------- */ +int usb_gadget_map_request(struct usb_gadget *gadget, + struct usb_request *req, int is_in) +{ + if (req->length == 0) + return 0; + + if (req->num_sgs) { + int mapped; + + mapped = dma_map_sg(&gadget->dev, req->sg, req->num_sgs, + is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + if (mapped == 0) { + dev_err(&gadget->dev, "failed to map SGs\n"); + return -EFAULT; + } + + req->num_mapped_sgs = mapped; + } else { + req->dma = dma_map_single(&gadget->dev, req->buf, req->length, + is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + + if (dma_mapping_error(&gadget->dev, req->dma)) { + dev_err(&gadget->dev, "failed to map buffer\n"); + return -EFAULT; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(usb_gadget_map_request); + +void usb_gadget_unmap_request(struct usb_gadget *gadget, + struct usb_request *req, int is_in) +{ + if (req->length == 0) + return; + + if (req->num_mapped_sgs) { + dma_unmap_sg(&gadget->dev, req->sg, req->num_mapped_sgs, + is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + + req->num_mapped_sgs = 0; + } else { + dma_unmap_single(&gadget->dev, req->dma, req->length, + is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + } +} +EXPORT_SYMBOL_GPL(usb_gadget_unmap_request); + +/* ------------------------------------------------------------------------- */ + /** * usb_gadget_start - tells usb device controller to start up * @gadget: The gadget we want to get started diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index da653b5c7134..9517466ababb 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -950,6 +950,16 @@ static inline void usb_free_descriptors(struct usb_descriptor_header **v) /*-------------------------------------------------------------------------*/ +/* utility to simplify map/unmap of usb_requests to/from DMA */ + +extern int usb_gadget_map_request(struct usb_gadget *gadget, + struct usb_request *req, int is_in); + +extern void usb_gadget_unmap_request(struct usb_gadget *gadget, + struct usb_request *req, int is_in); + +/*-------------------------------------------------------------------------*/ + /* utility wrapping a simple endpoint selection policy */ extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *, From 0fc9a1be09d9f8b19bcf64ab96836cb92beb0970 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 19 Dec 2011 11:32:34 +0200 Subject: [PATCH 158/269] usb: dwc3: gadget: use generic map/unmap routines those routines have everything we need to map/unmap USB requests and it's better to use them. In order to achieve that, we had to add a simple change on how we allocate and use our setup buffer; we cannot allocate it from coherent anymore otherwise the generic map/unmap routines won't be able to easily know that the GetStatus request already has a DMA address. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 2 - drivers/usb/dwc3/ep0.c | 16 +++++-- drivers/usb/dwc3/gadget.c | 93 +++++++-------------------------------- drivers/usb/dwc3/gadget.h | 2 - 4 files changed, 30 insertions(+), 83 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 9e57f8e9bf17..a72f42ffbbee 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -572,7 +572,6 @@ struct dwc3_request { * @ctrl_req_addr: dma address of ctrl_req * @ep0_trb: dma address of ep0_trb * @ep0_usb_req: dummy req used while handling STD USB requests - * @setup_buf_addr: dma address of setup_buf * @ep0_bounce_addr: dma address of ep0_bounce * @lock: for synchronizing * @dev: pointer to our struct device @@ -609,7 +608,6 @@ struct dwc3 { u8 *setup_buf; dma_addr_t ctrl_req_addr; dma_addr_t ep0_trb_addr; - dma_addr_t setup_buf_addr; dma_addr_t ep0_bounce_addr; struct dwc3_request ep0_usb_req; /* device lock */ diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 2f51de57593a..24137d8563c9 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -309,7 +309,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc, dep = dwc->eps[0]; dwc->ep0_usb_req.dep = dep; dwc->ep0_usb_req.request.length = sizeof(*response_pkt); - dwc->ep0_usb_req.request.dma = dwc->setup_buf_addr; + dwc->ep0_usb_req.request.buf = dwc->setup_buf; dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl; return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req); @@ -686,7 +686,12 @@ static void dwc3_ep0_do_control_data(struct dwc3 *dwc, DWC3_TRBCTL_CONTROL_DATA); } else if ((req->request.length % dep->endpoint.maxpacket) && (event->endpoint_number == 0)) { - dwc3_map_buffer_to_dma(req); + ret = usb_gadget_map_request(&dwc->gadget, &req->request, + event->endpoint_number); + if (ret) { + dev_dbg(dwc->dev, "failed to map request\n"); + return; + } WARN_ON(req->request.length > dep->endpoint.maxpacket); @@ -701,7 +706,12 @@ static void dwc3_ep0_do_control_data(struct dwc3 *dwc, dwc->ep0_bounce_addr, dep->endpoint.maxpacket, DWC3_TRBCTL_CONTROL_DATA); } else { - dwc3_map_buffer_to_dma(req); + ret = usb_gadget_map_request(&dwc->gadget, &req->request, + event->endpoint_number); + if (ret) { + dev_dbg(dwc->dev, "failed to map request\n"); + return; + } ret = dwc3_ep0_start_trans(dwc, event->endpoint_number, req->request.dma, req->request.length, diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index a1a04d00a9e4..1009e7e47a24 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -54,70 +54,6 @@ #include "gadget.h" #include "io.h" -#define DMA_ADDR_INVALID (~(dma_addr_t)0) - -void dwc3_map_buffer_to_dma(struct dwc3_request *req) -{ - struct dwc3 *dwc = req->dep->dwc; - - if (req->request.length == 0) { - /* req->request.dma = dwc->setup_buf_addr; */ - return; - } - - if (req->request.num_sgs) { - int mapped; - - mapped = dma_map_sg(dwc->dev, req->request.sg, - req->request.num_sgs, - req->direction ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - if (mapped < 0) { - dev_err(dwc->dev, "failed to map SGs\n"); - return; - } - - req->request.num_mapped_sgs = mapped; - return; - } - - if (req->request.dma == DMA_ADDR_INVALID) { - req->request.dma = dma_map_single(dwc->dev, req->request.buf, - req->request.length, req->direction - ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - req->mapped = true; - } -} - -void dwc3_unmap_buffer_from_dma(struct dwc3_request *req) -{ - struct dwc3 *dwc = req->dep->dwc; - - if (req->request.length == 0) { - req->request.dma = DMA_ADDR_INVALID; - return; - } - - if (req->request.num_mapped_sgs) { - req->request.dma = DMA_ADDR_INVALID; - dma_unmap_sg(dwc->dev, req->request.sg, - req->request.num_sgs, - req->direction ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - - req->request.num_mapped_sgs = 0; - return; - } - - if (req->mapped) { - dma_unmap_single(dwc->dev, req->request.dma, - req->request.length, req->direction - ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - req->mapped = 0; - req->request.dma = DMA_ADDR_INVALID; - } -} - void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, int status) { @@ -144,14 +80,15 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, if (req->request.status == -EINPROGRESS) req->request.status = status; - dwc3_unmap_buffer_from_dma(req); + usb_gadget_unmap_request(&dwc->gadget, &req->request, + req->direction); dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n", req, dep->name, req->request.actual, req->request.length, status); spin_unlock(&dwc->lock); - req->request.complete(&req->dep->endpoint, &req->request); + req->request.complete(&dep->endpoint, &req->request); spin_lock(&dwc->lock); } @@ -563,7 +500,6 @@ static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep, req->epnum = dep->number; req->dep = dep; - req->request.dma = DMA_ADDR_INVALID; return &req->request; } @@ -822,7 +758,8 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, * here and stop, unmap, free and del each of the linked * requests instead of we do now. */ - dwc3_unmap_buffer_from_dma(req); + usb_gadget_unmap_request(&dwc->gadget, &req->request, + req->direction); list_del(&req->list); return ret; } @@ -838,6 +775,9 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) { + struct dwc3 *dwc = dep->dwc; + int ret; + req->request.actual = 0; req->request.status = -EINPROGRESS; req->direction = dep->direction; @@ -855,7 +795,11 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) * This will also avoid Host cancelling URBs due to too * many NACKs. */ - dwc3_map_buffer_to_dma(req); + ret = usb_gadget_map_request(&dwc->gadget, &req->request, + dep->direction); + if (ret) + return ret; + list_add_tail(&req->list, &dep->request_list); /* @@ -2150,9 +2094,8 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) goto err1; } - dwc->setup_buf = dma_alloc_coherent(dwc->dev, - sizeof(*dwc->setup_buf) * 2, - &dwc->setup_buf_addr, GFP_KERNEL); + dwc->setup_buf = kzalloc(sizeof(*dwc->setup_buf) * 2, + GFP_KERNEL); if (!dwc->setup_buf) { dev_err(dwc->dev, "failed to allocate setup buffer\n"); ret = -ENOMEM; @@ -2243,8 +2186,7 @@ err4: dwc->ep0_bounce_addr); err3: - dma_free_coherent(dwc->dev, sizeof(*dwc->setup_buf) * 2, - dwc->setup_buf, dwc->setup_buf_addr); + kfree(dwc->setup_buf); err2: dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb), @@ -2273,8 +2215,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc) dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce, dwc->ep0_bounce_addr); - dma_free_coherent(dwc->dev, sizeof(*dwc->setup_buf) * 2, - dwc->setup_buf, dwc->setup_buf_addr); + kfree(dwc->setup_buf); dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb), dwc->ep0_trb, dwc->ep0_trb_addr); diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index d97f467d41cc..12f1e104977f 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -108,8 +108,6 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value); int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, unsigned cmd, struct dwc3_gadget_ep_cmd_params *params); -void dwc3_map_buffer_to_dma(struct dwc3_request *req); -void dwc3_unmap_buffer_from_dma(struct dwc3_request *req); /** * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW From ac8a138cb61d641e1522f3470f1a85f2df21b8bf Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 19 Dec 2011 11:48:24 +0200 Subject: [PATCH 159/269] usb: gadget: langwell: use generic map/unmap functions those routines have everything we need to map/unmap USB requests and it's better to use them. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/langwell_udc.c | 45 +++++-------------------------- 1 file changed, 7 insertions(+), 38 deletions(-) diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index a2bb5e476f54..e91f11a8e2b1 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -406,16 +406,7 @@ static void done(struct langwell_ep *ep, struct langwell_request *req, dma_pool_free(dev->dtd_pool, curr_dtd, curr_dtd->dtd_dma); } - if (req->mapped) { - dma_unmap_single(&dev->pdev->dev, - req->req.dma, req->req.length, - is_in(ep) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - req->req.dma = DMA_ADDR_INVALID; - req->mapped = 0; - } else - dma_sync_single_for_cpu(&dev->pdev->dev, req->req.dma, - req->req.length, - is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + usb_gadget_unmap_request(&dev->gadget, &req->req, is_in(ep)); if (status != -ESHUTDOWN) dev_dbg(&dev->pdev->dev, @@ -755,7 +746,8 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req, struct langwell_ep *ep; struct langwell_udc *dev; unsigned long flags; - int is_iso = 0, zlflag = 0; + int is_iso = 0; + int ret; /* always require a cpu-view buffer */ req = container_of(_req, struct langwell_request, req); @@ -782,33 +774,10 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req, if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) return -ESHUTDOWN; - /* set up dma mapping in case the caller didn't */ - if (_req->dma == DMA_ADDR_INVALID) { - /* WORKAROUND: WARN_ON(size == 0) */ - if (_req->length == 0) { - dev_vdbg(&dev->pdev->dev, "req->length: 0->1\n"); - zlflag = 1; - _req->length++; - } - - _req->dma = dma_map_single(&dev->pdev->dev, - _req->buf, _req->length, - is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - if (zlflag && (_req->length == 1)) { - dev_vdbg(&dev->pdev->dev, "req->length: 1->0\n"); - zlflag = 0; - _req->length = 0; - } - - req->mapped = 1; - dev_vdbg(&dev->pdev->dev, "req->mapped = 1\n"); - } else { - dma_sync_single_for_device(&dev->pdev->dev, - _req->dma, _req->length, - is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - req->mapped = 0; - dev_vdbg(&dev->pdev->dev, "req->mapped = 0\n"); - } + /* set up dma mapping */ + ret = usb_gadget_map_request(&dev->gadget, &req->req, is_in(ep)); + if (ret) + return ret; dev_dbg(&dev->pdev->dev, "%s queue req %p, len %u, buf %p, dma 0x%08x\n", From ade78f9feb2ee3e03460ef3730d7656c4903d999 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 19 Dec 2011 11:57:16 +0200 Subject: [PATCH 160/269] usb: renesas: gadget: use generic map/unmap routines those routines have everything we need to map/unmap USB requests and it's better to use them. Tested-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/mod_gadget.c | 75 +++++++------------------- 1 file changed, 18 insertions(+), 57 deletions(-) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index f37b20c82c80..937f2d40c747 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -165,69 +165,32 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep, /* * dma map/unmap */ -static int usbhsg_dma_map(struct device *dev, - struct usbhs_pkt *pkt, - enum dma_data_direction dir) -{ - struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); - struct usb_request *req = &ureq->req; - - if (pkt->dma != DMA_ADDR_INVALID) { - dev_err(dev, "dma is already mapped\n"); - return -EIO; - } - - if (req->dma == DMA_ADDR_INVALID) { - pkt->dma = dma_map_single(dev, pkt->buf, pkt->length, dir); - } else { - dma_sync_single_for_device(dev, req->dma, req->length, dir); - pkt->dma = req->dma; - } - - if (dma_mapping_error(dev, pkt->dma)) { - dev_err(dev, "dma mapping error %llx\n", (u64)pkt->dma); - return -EIO; - } - - return 0; -} - -static int usbhsg_dma_unmap(struct device *dev, - struct usbhs_pkt *pkt, - enum dma_data_direction dir) -{ - struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); - struct usb_request *req = &ureq->req; - - if (pkt->dma == DMA_ADDR_INVALID) { - dev_err(dev, "dma is not mapped\n"); - return -EIO; - } - - if (req->dma == DMA_ADDR_INVALID) - dma_unmap_single(dev, pkt->dma, pkt->length, dir); - else - dma_sync_single_for_cpu(dev, req->dma, req->length, dir); - - pkt->dma = DMA_ADDR_INVALID; - - return 0; -} - static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map) { + struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); + struct usb_request *req = &ureq->req; struct usbhs_pipe *pipe = pkt->pipe; struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe); struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); - struct device *dev = usbhsg_gpriv_to_dev(gpriv); enum dma_data_direction dir; + int ret = 0; - dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + dir = usbhs_pipe_is_dir_host(pipe); - if (map) - return usbhsg_dma_map(dev, pkt, dir); - else - return usbhsg_dma_unmap(dev, pkt, dir); + if (map) { + /* it can not use scatter/gather */ + WARN_ON(req->num_sgs); + + ret = usb_gadget_map_request(&gpriv->gadget, req, dir); + if (ret < 0) + return ret; + + pkt->dma = req->dma; + } else { + usb_gadget_unmap_request(&gpriv->gadget, req, dir); + } + + return ret; } /* @@ -657,8 +620,6 @@ static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq)); - ureq->req.dma = DMA_ADDR_INVALID; - return &ureq->req; } From 220e860009ff4091b75f614eb0d09a7a8486bbe6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 19 Dec 2011 12:01:28 +0200 Subject: [PATCH 161/269] usb: gadget: amd5536: use generic map/unmap routines those routines have everything we need to map/unmap USB requests and it's better to use them. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/amd5536udc.c | 33 ++++++--------------------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 1355a2f5e685..2204a4c68d85 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -827,20 +827,8 @@ __acquires(ep->dev->lock) dev = ep->dev; /* unmap DMA */ - if (req->dma_mapping) { - if (ep->in) - pci_unmap_single(dev->pdev, - req->req.dma, - req->req.length, - PCI_DMA_TODEVICE); - else - pci_unmap_single(dev->pdev, - req->req.dma, - req->req.length, - PCI_DMA_FROMDEVICE); - req->dma_mapping = 0; - req->req.dma = DMA_DONT_USE; - } + if (ep->dma) + usb_gadget_unmap_request(&dev->gadget, &req->req, ep->in); halted = ep->halted; ep->halted = 1; @@ -1089,20 +1077,11 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp) return -ESHUTDOWN; /* map dma (usually done before) */ - if (ep->dma && usbreq->length != 0 - && (usbreq->dma == DMA_DONT_USE || usbreq->dma == 0)) { + if (ep->dma) { VDBG(dev, "DMA map req %p\n", req); - if (ep->in) - usbreq->dma = pci_map_single(dev->pdev, - usbreq->buf, - usbreq->length, - PCI_DMA_TODEVICE); - else - usbreq->dma = pci_map_single(dev->pdev, - usbreq->buf, - usbreq->length, - PCI_DMA_FROMDEVICE); - req->dma_mapping = 1; + retval = usb_gadget_map_request(&udc->gadget, usbreq, ep->in); + if (retval) + return retval; } VDBG(dev, "%s queue req %p, len %d req->td_data=%p buf %p\n", From 05d00fbe87f185d55edf7461d4f714a3909bc908 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 19 Dec 2011 12:03:57 +0200 Subject: [PATCH 162/269] usb: gadget: r8a66597: use generic map/unmap routines those routines have everything we need to map/unmap USB requests and it's better to use them. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/r8a66597-udc.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index f5b8d215e1d5..c4401e7dd3a6 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -663,11 +663,7 @@ static int sudmac_alloc_channel(struct r8a66597 *r8a66597, ep->fifoctr = D0FIFOCTR; /* dma mapping */ - req->req.dma = dma_map_single(r8a66597_to_dev(ep->r8a66597), - req->req.buf, req->req.length, - dma->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - - return 0; + return usb_gadget_map_request(&r8a66597->gadget, &req->req, dma->dir); } static void sudmac_free_channel(struct r8a66597 *r8a66597, @@ -677,9 +673,7 @@ static void sudmac_free_channel(struct r8a66597 *r8a66597, if (!r8a66597_is_sudmac(r8a66597)) return; - dma_unmap_single(r8a66597_to_dev(ep->r8a66597), - req->req.dma, req->req.length, - ep->dma->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + usb_gadget_unmap_request(&r8a66597->gadget, &req->req, ep->dma->dir); r8a66597_bclr(r8a66597, DREQE, ep->fifosel); r8a66597_change_curpipe(r8a66597, 0, 0, ep->fifosel); From af93f2c77ac79e2f0bed542b5890f618d9d0cdb3 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 19 Dec 2011 12:07:40 +0200 Subject: [PATCH 163/269] usb: gadget: net2272: use generic map/umap routines those routines have everything we need to map/unmap USB requests and it's better to use them. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2272.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index 7322d293213e..01ae56f47174 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -385,12 +385,9 @@ net2272_done(struct net2272_ep *ep, struct net2272_request *req, int status) status = req->req.status; dev = ep->dev; - if (use_dma && req->mapped) { - dma_unmap_single(dev->dev, req->req.dma, req->req.length, - ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - req->req.dma = DMA_ADDR_INVALID; - req->mapped = 0; - } + if (use_dma && ep->dma) + usb_gadget_unmap_request(&dev->gadget, &req->req, + ep->is_in); if (status && status != -ESHUTDOWN) dev_vdbg(dev->dev, "complete %s req %p stat %d len %u/%u buf %p\n", @@ -850,10 +847,11 @@ net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) return -ESHUTDOWN; /* set up dma mapping in case the caller didn't */ - if (use_dma && ep->dma && _req->dma == DMA_ADDR_INVALID) { - _req->dma = dma_map_single(dev->dev, _req->buf, _req->length, - ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - req->mapped = 1; + if (use_dma && ep->dma) { + status = usb_gadget_map_request(&dev->gadget, _req, + ep->is_in); + if (status) + return status; } dev_vdbg(dev->dev, "%s queue req %p, len %d buf %p dma %08llx %s\n", From ae4d7933344e8bc5702cdc56e9498d3852cf3b2a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 19 Dec 2011 12:09:56 +0200 Subject: [PATCH 164/269] usb: gadget: net2280: use generic map/unmap routines those routines have everything we need to map/unmap USB requests and it's better to use them. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2280.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index cdedd1336745..a5ccabc37f30 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -806,12 +806,8 @@ done (struct net2280_ep *ep, struct net2280_request *req, int status) status = req->req.status; dev = ep->dev; - if (req->mapped) { - pci_unmap_single (dev->pdev, req->req.dma, req->req.length, - ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - req->req.dma = DMA_ADDR_INVALID; - req->mapped = 0; - } + if (ep->dma) + usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in); if (status && status != -ESHUTDOWN) VDEBUG (dev, "complete %s req %p stat %d len %u/%u\n", @@ -857,10 +853,13 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) return -EOPNOTSUPP; /* set up dma mapping in case the caller didn't */ - if (ep->dma && _req->dma == DMA_ADDR_INVALID) { - _req->dma = pci_map_single (dev->pdev, _req->buf, _req->length, - ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - req->mapped = 1; + if (ep->dma) { + int ret; + + ret = usb_gadget_map_request(&dev->gadget, _req, + ep->is_in); + if (ret) + return ret; } #if 0 From 6440093f5eae9842feb06e40d41c3bd569b6b461 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 19 Dec 2011 12:11:44 +0200 Subject: [PATCH 165/269] usb: gadget: goku: use generic map/unmap routines those routines have everything we need to map/unmap USB requests and it's better to use them. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/goku_udc.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 59777490a19a..e1dfd32dc805 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -311,12 +311,9 @@ done(struct goku_ep *ep, struct goku_request *req, int status) status = req->req.status; dev = ep->dev; - if (req->mapped) { - pci_unmap_single(dev->pdev, req->req.dma, req->req.length, - ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - req->req.dma = DMA_ADDR_INVALID; - req->mapped = 0; - } + + if (ep->dma) + usb_gadget_unmap_request(&dev->gadget, &req->req, ep->is_in); #ifndef USB_TRACE if (status && status != -ESHUTDOWN) @@ -737,10 +734,11 @@ goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) return -EBUSY; /* set up dma mapping in case the caller didn't */ - if (ep->dma && _req->dma == DMA_ADDR_INVALID) { - _req->dma = pci_map_single(dev->pdev, _req->buf, _req->length, - ep->is_in ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - req->mapped = 1; + if (ep->dma) { + status = usb_gadget_map_request(&dev->gadget, &req->req, + ep->is_in); + if (status) + return status; } #ifdef USB_TRACE From 656d2b3964a9d0f9864d472f8dfa2dd7dd42e6c0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 09:20:09 -0800 Subject: [PATCH 166/269] USB: ftdi_sio: fix problem when the manufacture is a NULL string On some misconfigured ftdi_sio devices, if the manufacturer string is NULL, the kernel will oops when the device is plugged in. This patch fixes the problem. Reported-by: Wojciech M Zabolotny Tested-by: Wojciech M Zabolotny Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index feafa85dd07e..989262606684 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1769,7 +1769,8 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial) dbg("%s", __func__); - if (strcmp(udev->manufacturer, "CALAO Systems") == 0) + if ((udev->manufacturer) && + (strcmp(udev->manufacturer, "CALAO Systems") == 0)) return ftdi_jtag_probe(serial); return 0; From 87364624e2dd07c387b13e2ce0fda33448ef4247 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sat, 25 Feb 2012 19:09:40 -0500 Subject: [PATCH 167/269] usb: fix defined but not used warnings in hcd-pci.c Shows up on ia64 builds (and possibly elsewhere) for configs that don't set PM_RUNTIME or PM_SLEEP as follows: drivers/usb/core/hcd-pci.c:383:12: warning: 'suspend_common' defined but not used drivers/usb/core/hcd-pci.c:438:12: warning: 'resume_common' defined but not used As per above, the functions are only used if RUNTIME/SLEEP are set, so make the two functions conditional on these Kconfig values. Signed-off-by: Paul Gortmaker Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd-pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 81e2c0d9c17d..622b4a48e732 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -380,6 +380,7 @@ static int check_root_hub_suspended(struct device *dev) return 0; } +#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME) static int suspend_common(struct device *dev, bool do_wakeup) { struct pci_dev *pci_dev = to_pci_dev(dev); @@ -471,6 +472,7 @@ static int resume_common(struct device *dev, int event) } return retval; } +#endif /* SLEEP || RUNTIME */ #ifdef CONFIG_PM_SLEEP From 79857e8e7b1ba740f8025b540f1e171c9a0a5d31 Mon Sep 17 00:00:00 2001 From: Shengzhou Liu Date: Sat, 25 Feb 2012 23:56:30 +0800 Subject: [PATCH 168/269] powerpc/usb: fix usb CTRL_PHY_CLK_VALID breaks on some platform Fix checking of CTRL_PHY_CLK_VALID bit break on some platform on which there is not USB CTRL_PHY_CLK_VALID bit. - P1023/P3041/P5020 etc,have this bit - P3060/4080/PSC913x do have this bit, but not mentioned in RM. - P1022(perhaps and other) has no this bit Signed-off-by: Shengzhou Liu Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-fsl.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 7a15c2235758..e9d8a0cca47b 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -248,7 +248,11 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) struct usb_hcd *hcd = ehci_to_hcd(ehci); struct fsl_usb2_platform_data *pdata; void __iomem *non_ehci = hcd->regs; - u32 temp; + u32 temp, chip, rev, svr; + + svr = mfspr(SPRN_SVR); + chip = svr >> 16; + rev = (svr >> 4) & 0xf; pdata = hcd->self.controller->platform_data; @@ -274,12 +278,6 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); if (pdata->operating_mode == FSL_USB2_MPH_HOST) { - unsigned int chip, rev, svr; - - svr = mfspr(SPRN_SVR); - chip = svr >> 16; - rev = (svr >> 4) & 0xf; - /* Deal with USB Erratum #14 on MPC834x Rev 1.0 & 1.1 chips */ if ((rev == 1) && (chip >= 0x8050) && (chip <= 0x8055)) ehci->has_fsl_port_bug = 1; @@ -301,9 +299,15 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); } - if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & CTRL_PHY_CLK_VALID)) { - printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n"); - return -ENODEV; + /* There is no CTRL_PHY_CLK_VALID bit on some platforms, e.g. P1022 */ +#define SVR_P1022_N_ID 0x80E6 +#define SVR_P1022_S_ID 0x80EE + if (chip != SVR_P1022_N_ID && chip != SVR_P1022_S_ID) { + if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & + CTRL_PHY_CLK_VALID)) { + printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n"); + return -ENODEV; + } } return 0; } From 0d8520a1d7f43328bc7085d4244d93c595064157 Mon Sep 17 00:00:00 2001 From: Meng Zhang Date: Mon, 27 Feb 2012 08:24:19 +0100 Subject: [PATCH 169/269] USB: option: Add MediaTek MT6276M modem&app interfaces Add MEDIATEK products to Option driver Signed-off-by: Meng Zhang Signed-off-by: Matthias Urlichs Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 138a7b98cda4..ab5047944d1d 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -484,6 +484,9 @@ static void option_instat_callback(struct urb *urb); #define LG_VENDOR_ID 0x1004 #define LG_PRODUCT_L02C 0x618f +/* MediaTek products */ +#define MEDIATEK_VENDOR_ID 0x0e8d + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -1198,6 +1201,10 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) }, { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */ + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) }, /* MediaTek MT6276M modem & app port */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); From 7ac4704c099125214a4f0a4bd54ce94d15be2ffb Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sat, 25 Feb 2012 18:28:09 +0100 Subject: [PATCH 170/269] usb/storage: a couple defines from drivers/usb/storage/transport.h to include/linux/usb/storage.h This moves the BOT data structures for CBW and CSW from drivers internal header file to global include able file in include/. The storage gadget is using the same name for CSW but a different for CBW so I fix it up properly. The same goes for the ub driver and keucr driver in staging. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 37 --------------------------- drivers/staging/keucr/transport.h | 37 --------------------------- drivers/usb/gadget/f_mass_storage.c | 2 +- drivers/usb/gadget/file_storage.c | 2 +- drivers/usb/gadget/storage_common.c | 19 -------------- drivers/usb/storage/transport.h | 39 ----------------------------- include/linux/usb/storage.h | 39 +++++++++++++++++++++++++++++ 7 files changed, 41 insertions(+), 134 deletions(-) diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 7333b9e44411..298ac75ac8e5 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -117,43 +117,6 @@ #define UB_SENSE_SIZE 18 -/* - */ - -/* command block wrapper */ -struct bulk_cb_wrap { - __le32 Signature; /* contains 'USBC' */ - u32 Tag; /* unique per command id */ - __le32 DataTransferLength; /* size of data */ - u8 Flags; /* direction in bit 0 */ - u8 Lun; /* LUN */ - u8 Length; /* of of the CDB */ - u8 CDB[UB_MAX_CDB_SIZE]; /* max command */ -}; - -#define US_BULK_CB_WRAP_LEN 31 -#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */ -#define US_BULK_FLAG_IN 1 -#define US_BULK_FLAG_OUT 0 - -/* command status wrapper */ -struct bulk_cs_wrap { - __le32 Signature; /* should = 'USBS' */ - u32 Tag; /* same as original command */ - __le32 Residue; /* amount not transferred */ - u8 Status; /* see below */ -}; - -#define US_BULK_CS_WRAP_LEN 13 -#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ -#define US_BULK_STAT_OK 0 -#define US_BULK_STAT_FAIL 1 -#define US_BULK_STAT_PHASE 2 - -/* bulk-only class specific requests */ -#define US_BULK_RESET_REQUEST 0xff -#define US_BULK_GET_MAX_LUN 0xfe - /* */ struct ub_dev; diff --git a/drivers/staging/keucr/transport.h b/drivers/staging/keucr/transport.h index 4ae57d0145b2..2a11a98375d7 100644 --- a/drivers/staging/keucr/transport.h +++ b/drivers/staging/keucr/transport.h @@ -3,43 +3,6 @@ #include -/* Bulk only data structures */ - -/* command block wrapper */ -struct bulk_cb_wrap { - __le32 Signature; /* contains 'USBC' */ - __u32 Tag; /* unique per command id */ - __le32 DataTransferLength; /* size of data */ - __u8 Flags; /* direction in bit 0 */ - __u8 Lun; /* LUN normally 0 */ - __u8 Length; /* of of the CDB */ - __u8 CDB[16]; /* max command */ -}; - -#define US_BULK_CB_WRAP_LEN 31 -#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */ -#define US_BULK_FLAG_IN 1 -#define US_BULK_FLAG_OUT 0 - -/* command status wrapper */ -struct bulk_cs_wrap { - __le32 Signature; /* should = 'USBS' */ - __u32 Tag; /* same as original command */ - __le32 Residue; /* amount not transferred */ - __u8 Status; /* see below */ - __u8 Filler[18]; -}; - -#define US_BULK_CS_WRAP_LEN 13 -#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ -#define US_BULK_STAT_OK 0 -#define US_BULK_STAT_FAIL 1 -#define US_BULK_STAT_PHASE 2 - -/* bulk-only class specific requests */ -#define US_BULK_RESET_REQUEST 0xff -#define US_BULK_GET_MAX_LUN 0xfe - /* usb_stor_bulk_transfer_xxx() return codes, in order of severity */ #define USB_STOR_XFER_GOOD 0 /* good transfer */ #define USB_STOR_XFER_SHORT 1 /* transferred less than expected */ diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index ee8ceec01560..9e71fe7fc502 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -2221,7 +2221,7 @@ unknown_cmnd: static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) { struct usb_request *req = bh->outreq; - struct fsg_bulk_cb_wrap *cbw = req->buf; + struct bulk_cb_wrap *cbw = req->buf; struct fsg_common *common = fsg->common; /* Was this a real packet? Should it be ignored? */ diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 47766f0e7caa..15e6e8e55ef6 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -2609,7 +2609,7 @@ static int do_scsi_command(struct fsg_dev *fsg) static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) { struct usb_request *req = bh->outreq; - struct fsg_bulk_cb_wrap *cbw = req->buf; + struct bulk_cb_wrap *cbw = req->buf; /* Was this a real packet? Should it be ignored? */ if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index 85ea14e2545e..4095696b1582 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -153,29 +153,10 @@ /* Bulk-only data structures */ -/* Command Block Wrapper */ -struct fsg_bulk_cb_wrap { - __le32 Signature; /* Contains 'USBC' */ - u32 Tag; /* Unique per command id */ - __le32 DataTransferLength; /* Size of the data */ - u8 Flags; /* Direction in bit 7 */ - u8 Lun; /* LUN (normally 0) */ - u8 Length; /* Of the CDB, <= MAX_COMMAND_SIZE */ - u8 CDB[16]; /* Command Data Block */ -}; - #define USB_BULK_CB_WRAP_LEN 31 #define USB_BULK_CB_SIG 0x43425355 /* Spells out USBC */ #define USB_BULK_IN_FLAG 0x80 -/* Command Status Wrapper */ -struct bulk_cs_wrap { - __le32 Signature; /* Should = 'USBS' */ - u32 Tag; /* Same as original command */ - __le32 Residue; /* Amount not transferred */ - u8 Status; /* See below */ -}; - #define USB_BULK_CS_WRAP_LEN 13 #define USB_BULK_CS_SIG 0x53425355 /* Spells out 'USBS' */ #define USB_STATUS_PASS 0 diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h index 242ff5e791a5..9369d752d419 100644 --- a/drivers/usb/storage/transport.h +++ b/drivers/usb/storage/transport.h @@ -41,45 +41,6 @@ #include -/* - * Bulk only data structures - */ - -/* command block wrapper */ -struct bulk_cb_wrap { - __le32 Signature; /* contains 'USBC' */ - __u32 Tag; /* unique per command id */ - __le32 DataTransferLength; /* size of data */ - __u8 Flags; /* direction in bit 0 */ - __u8 Lun; /* LUN normally 0 */ - __u8 Length; /* of of the CDB */ - __u8 CDB[16]; /* max command */ -}; - -#define US_BULK_CB_WRAP_LEN 31 -#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */ -#define US_BULK_FLAG_IN 1 -#define US_BULK_FLAG_OUT 0 - -/* command status wrapper */ -struct bulk_cs_wrap { - __le32 Signature; /* should = 'USBS' */ - __u32 Tag; /* same as original command */ - __le32 Residue; /* amount not transferred */ - __u8 Status; /* see below */ - __u8 Filler[18]; -}; - -#define US_BULK_CS_WRAP_LEN 13 -#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ -#define US_BULK_STAT_OK 0 -#define US_BULK_STAT_FAIL 1 -#define US_BULK_STAT_PHASE 2 - -/* bulk-only class specific requests */ -#define US_BULK_RESET_REQUEST 0xff -#define US_BULK_GET_MAX_LUN 0xfe - /* * usb_stor_bulk_transfer_xxx() return codes, in order of severity */ diff --git a/include/linux/usb/storage.h b/include/linux/usb/storage.h index d7fc910f1dc4..87a94bf34d47 100644 --- a/include/linux/usb/storage.h +++ b/include/linux/usb/storage.h @@ -45,4 +45,43 @@ #define USB_PR_DEVICE 0xff /* Use device's value */ + /* + * Bulk only data structures + */ + +/* command block wrapper */ +struct bulk_cb_wrap { + __le32 Signature; /* contains 'USBC' */ + __u32 Tag; /* unique per command id */ + __le32 DataTransferLength; /* size of data */ + __u8 Flags; /* direction in bit 0 */ + __u8 Lun; /* LUN normally 0 */ + __u8 Length; /* of of the CDB */ + __u8 CDB[16]; /* max command */ +}; + +#define US_BULK_CB_WRAP_LEN 31 +#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */ +#define US_BULK_FLAG_IN 1 +#define US_BULK_FLAG_OUT 0 + +/* command status wrapper */ +struct bulk_cs_wrap { + __le32 Signature; /* should = 'USBS' */ + __u32 Tag; /* same as original command */ + __le32 Residue; /* amount not transferred */ + __u8 Status; /* see below */ + __u8 Filler[18]; +}; + +#define US_BULK_CS_WRAP_LEN 13 +#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ +#define US_BULK_STAT_OK 0 +#define US_BULK_STAT_FAIL 1 +#define US_BULK_STAT_PHASE 2 + +/* bulk-only class specific requests */ +#define US_BULK_RESET_REQUEST 0xff +#define US_BULK_GET_MAX_LUN 0xfe + #endif From b8db6d6402ddca1c78a27407fbd10a6ccb23ab14 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sat, 25 Feb 2012 18:28:10 +0100 Subject: [PATCH 171/269] usb/storage: redefine US_BULK_FLAG_IN and use it US_BULK_FLAG_IN is defined as 1 and not used. The USB storage spec says that bit 7 of flags within CBW defines the data direction. 1 is DATA-IN (read from device) and 0 is the DATA-OUT. Bit 6 is obselete and bits 0-5 are reserved. This patch redefines the unsued define US_BULK_FLAG_IN from 1 to 1 << 7 aka 0x80 and replaces the obvious users. In a following patch the storage gadget will use it as well. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/ene_ub6250.c | 26 +++++++++++++------------- drivers/usb/storage/realtek_cr.c | 4 ++-- drivers/usb/storage/transport.c | 3 ++- include/linux/usb/storage.h | 2 +- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index 30532d93eecc..e7e678109500 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -674,7 +674,7 @@ static int sd_scsi_read(struct us_data *us, struct scsi_cmnd *srb) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = blenByte; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[5] = (unsigned char)(bnByte); bcb->CDB[4] = (unsigned char)(bnByte>>8); @@ -858,7 +858,7 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x200; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x02; /* in init.c ENE_MSInit() is 0x01 */ @@ -877,7 +877,7 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x4; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x03; @@ -1170,7 +1170,7 @@ static int ms_read_eraseblock(struct us_data *us, u32 PhyBlockAddr) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x200; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF2; bcb->CDB[1] = 0x06; bcb->CDB[4] = (unsigned char)(bn); @@ -1249,7 +1249,7 @@ static int ms_lib_overwrite_extra(struct us_data *us, u32 PhyBlockAddr, memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x4; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF2; bcb->CDB[1] = 0x05; bcb->CDB[5] = (unsigned char)(PageNum); @@ -1331,7 +1331,7 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x4; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x03; bcb->CDB[5] = (unsigned char)(PageNum); @@ -1533,7 +1533,7 @@ static int ms_lib_read_extrablock(struct us_data *us, u32 PhyBlock, memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x4 * blen; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x03; bcb->CDB[5] = (unsigned char)(PageNum); @@ -1650,7 +1650,7 @@ static int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = blenByte; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x02; bcb->CDB[5] = (unsigned char)(bn); @@ -1694,7 +1694,7 @@ static int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x200 * len; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x02; bcb->CDB[5] = (unsigned char)(blkno); @@ -1827,7 +1827,7 @@ static int ene_get_card_type(struct us_data *us, u16 index, void *buf) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x01; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xED; bcb->CDB[2] = (unsigned char)(index>>8); bcb->CDB[3] = (unsigned char)index; @@ -2083,7 +2083,7 @@ static int ene_ms_init(struct us_data *us) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x200; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x01; @@ -2134,7 +2134,7 @@ static int ene_sd_init(struct us_data *us) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF2; result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0); @@ -2153,7 +2153,7 @@ static int ene_sd_init(struct us_data *us) memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = 0x200; - bcb->Flags = 0x80; + bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index 84a4bc0cbee4..63cf2822e299 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -219,7 +219,7 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun, /* set up the command wrapper */ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = cpu_to_le32(buf_len); - bcb->Flags = (dir == DMA_FROM_DEVICE) ? 1 << 7 : 0; + bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : 0; bcb->Tag = ++us->tag; bcb->Lun = lun; bcb->Length = cmd_len; @@ -305,7 +305,7 @@ static int rts51x_bulk_transport_special(struct us_data *us, u8 lun, /* set up the command wrapper */ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = cpu_to_le32(buf_len); - bcb->Flags = (dir == DMA_FROM_DEVICE) ? 1 << 7 : 0; + bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : 0; bcb->Tag = ++us->tag; bcb->Lun = lun; bcb->Length = cmd_len; diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 0e5c91c6187f..c70109e5d60b 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -1071,7 +1071,8 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) /* set up the command wrapper */ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->DataTransferLength = cpu_to_le32(transfer_length); - bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0; + bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? + US_BULK_FLAG_IN : 0; bcb->Tag = ++us->tag; bcb->Lun = srb->device->lun; if (us->fflags & US_FL_SCM_MULT_TARG) diff --git a/include/linux/usb/storage.h b/include/linux/usb/storage.h index 87a94bf34d47..4de58b15fad6 100644 --- a/include/linux/usb/storage.h +++ b/include/linux/usb/storage.h @@ -62,7 +62,7 @@ struct bulk_cb_wrap { #define US_BULK_CB_WRAP_LEN 31 #define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */ -#define US_BULK_FLAG_IN 1 +#define US_BULK_FLAG_IN (1 << 7) #define US_BULK_FLAG_OUT 0 /* command status wrapper */ From 775dafdcd330d021cee984459fbdacfc01d29f69 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sat, 25 Feb 2012 18:28:11 +0100 Subject: [PATCH 172/269] usb/gadget: use common defines within the storage gadget This replaces the remaining defines which are available in "public" include/ directory and are re-defined by the storage gadget. This is patch is basicaly search & replace followed by the removal of the defines. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_mass_storage.c | 24 ++++++++++++------------ drivers/usb/gadget/file_storage.c | 24 ++++++++++++------------ drivers/usb/gadget/storage_common.c | 21 --------------------- 3 files changed, 24 insertions(+), 45 deletions(-) diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 9e71fe7fc502..84e6573ea74e 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -620,7 +620,7 @@ static int fsg_setup(struct usb_function *f, switch (ctrl->bRequest) { - case USB_BULK_RESET_REQUEST: + case US_BULK_RESET_REQUEST: if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) break; @@ -636,7 +636,7 @@ static int fsg_setup(struct usb_function *f, raise_exception(fsg->common, FSG_STATE_RESET); return DELAYED_STATUS; - case USB_BULK_GET_MAX_LUN_REQUEST: + case US_BULK_GET_MAX_LUN: if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) break; @@ -1742,7 +1742,7 @@ static int send_status(struct fsg_common *common) struct fsg_buffhd *bh; struct bulk_cs_wrap *csw; int rc; - u8 status = USB_STATUS_PASS; + u8 status = US_BULK_STAT_OK; u32 sd, sdinfo = 0; /* Wait for the next buffer to become available */ @@ -1763,11 +1763,11 @@ static int send_status(struct fsg_common *common) if (common->phase_error) { DBG(common, "sending phase-error status\n"); - status = USB_STATUS_PHASE_ERROR; + status = US_BULK_STAT_PHASE; sd = SS_INVALID_COMMAND; } else if (sd != SS_NO_SENSE) { DBG(common, "sending command-failure status\n"); - status = USB_STATUS_FAIL; + status = US_BULK_STAT_FAIL; VDBG(common, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" " info x%x\n", SK(sd), ASC(sd), ASCQ(sd), sdinfo); @@ -1776,12 +1776,12 @@ static int send_status(struct fsg_common *common) /* Store and send the Bulk-only CSW */ csw = (void *)bh->buf; - csw->Signature = cpu_to_le32(USB_BULK_CS_SIG); + csw->Signature = cpu_to_le32(US_BULK_CS_SIGN); csw->Tag = common->tag; csw->Residue = cpu_to_le32(common->residue); csw->Status = status; - bh->inreq->length = USB_BULK_CS_WRAP_LEN; + bh->inreq->length = US_BULK_CS_WRAP_LEN; bh->inreq->zero = 0; if (!start_in_transfer(common, bh)) /* Don't know what to do if common->fsg is NULL */ @@ -2229,9 +2229,9 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) return -EINVAL; /* Is the CBW valid? */ - if (req->actual != USB_BULK_CB_WRAP_LEN || + if (req->actual != US_BULK_CB_WRAP_LEN || cbw->Signature != cpu_to_le32( - USB_BULK_CB_SIG)) { + US_BULK_CB_SIGN)) { DBG(fsg, "invalid CBW: len %u sig 0x%x\n", req->actual, le32_to_cpu(cbw->Signature)); @@ -2253,7 +2253,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) } /* Is the CBW meaningful? */ - if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || + if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN || cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " "cmdlen %u\n", @@ -2273,7 +2273,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) /* Save the command for later */ common->cmnd_size = cbw->Length; memcpy(common->cmnd, cbw->CDB, common->cmnd_size); - if (cbw->Flags & USB_BULK_IN_FLAG) + if (cbw->Flags & US_BULK_FLAG_IN) common->data_dir = DATA_DIR_TO_HOST; else common->data_dir = DATA_DIR_FROM_HOST; @@ -2303,7 +2303,7 @@ static int get_next_command(struct fsg_common *common) } /* Queue a request to read a Bulk-only CBW */ - set_bulk_out_req_length(common, bh, USB_BULK_CB_WRAP_LEN); + set_bulk_out_req_length(common, bh, US_BULK_CB_WRAP_LEN); if (!start_out_transfer(common, bh)) /* Don't know what to do if common->fsg is NULL */ return -EIO; diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 15e6e8e55ef6..4fac56927741 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -855,7 +855,7 @@ static int class_setup_req(struct fsg_dev *fsg, if (transport_is_bbb()) { switch (ctrl->bRequest) { - case USB_BULK_RESET_REQUEST: + case US_BULK_RESET_REQUEST: if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) break; @@ -871,7 +871,7 @@ static int class_setup_req(struct fsg_dev *fsg, value = DELAYED_STATUS; break; - case USB_BULK_GET_MAX_LUN_REQUEST: + case US_BULK_GET_MAX_LUN: if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) break; @@ -2125,7 +2125,7 @@ static int send_status(struct fsg_dev *fsg) struct fsg_lun *curlun = fsg->curlun; struct fsg_buffhd *bh; int rc; - u8 status = USB_STATUS_PASS; + u8 status = US_BULK_STAT_OK; u32 sd, sdinfo = 0; /* Wait for the next buffer to become available */ @@ -2146,11 +2146,11 @@ static int send_status(struct fsg_dev *fsg) if (fsg->phase_error) { DBG(fsg, "sending phase-error status\n"); - status = USB_STATUS_PHASE_ERROR; + status = US_BULK_STAT_PHASE; sd = SS_INVALID_COMMAND; } else if (sd != SS_NO_SENSE) { DBG(fsg, "sending command-failure status\n"); - status = USB_STATUS_FAIL; + status = US_BULK_STAT_FAIL; VDBG(fsg, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" " info x%x\n", SK(sd), ASC(sd), ASCQ(sd), sdinfo); @@ -2160,12 +2160,12 @@ static int send_status(struct fsg_dev *fsg) struct bulk_cs_wrap *csw = bh->buf; /* Store and send the Bulk-only CSW */ - csw->Signature = cpu_to_le32(USB_BULK_CS_SIG); + csw->Signature = cpu_to_le32(US_BULK_CS_SIGN); csw->Tag = fsg->tag; csw->Residue = cpu_to_le32(fsg->residue); csw->Status = status; - bh->inreq->length = USB_BULK_CS_WRAP_LEN; + bh->inreq->length = US_BULK_CS_WRAP_LEN; bh->inreq->zero = 0; start_transfer(fsg, fsg->bulk_in, bh->inreq, &bh->inreq_busy, &bh->state); @@ -2616,9 +2616,9 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) return -EINVAL; /* Is the CBW valid? */ - if (req->actual != USB_BULK_CB_WRAP_LEN || + if (req->actual != US_BULK_CB_WRAP_LEN || cbw->Signature != cpu_to_le32( - USB_BULK_CB_SIG)) { + US_BULK_CB_SIGN)) { DBG(fsg, "invalid CBW: len %u sig 0x%x\n", req->actual, le32_to_cpu(cbw->Signature)); @@ -2638,7 +2638,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) } /* Is the CBW meaningful? */ - if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || + if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN || cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " "cmdlen %u\n", @@ -2656,7 +2656,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) /* Save the command for later */ fsg->cmnd_size = cbw->Length; memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size); - if (cbw->Flags & USB_BULK_IN_FLAG) + if (cbw->Flags & US_BULK_FLAG_IN) fsg->data_dir = DATA_DIR_TO_HOST; else fsg->data_dir = DATA_DIR_FROM_HOST; @@ -2685,7 +2685,7 @@ static int get_next_command(struct fsg_dev *fsg) } /* Queue a request to read a Bulk-only CBW */ - set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN); + set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN); start_transfer(fsg, fsg->bulk_out, bh->outreq, &bh->outreq_busy, &bh->state); diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index 4095696b1582..52ab4098b3c9 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -145,29 +145,8 @@ #endif /* DUMP_MSGS */ - - - - /*-------------------------------------------------------------------------*/ -/* Bulk-only data structures */ - -#define USB_BULK_CB_WRAP_LEN 31 -#define USB_BULK_CB_SIG 0x43425355 /* Spells out USBC */ -#define USB_BULK_IN_FLAG 0x80 - -#define USB_BULK_CS_WRAP_LEN 13 -#define USB_BULK_CS_SIG 0x53425355 /* Spells out 'USBS' */ -#define USB_STATUS_PASS 0 -#define USB_STATUS_FAIL 1 -#define USB_STATUS_PHASE_ERROR 2 - -/* Bulk-only class specific requests */ -#define USB_BULK_RESET_REQUEST 0xff -#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe - - /* CBI Interrupt data structure */ struct interrupt_data { u8 bType; From 03892d5fefbe7d4df68466bd4cfda86fac84ebd8 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sat, 25 Feb 2012 18:28:12 +0100 Subject: [PATCH 173/269] usb/storage: remove Filler member from struct bulk_cs_wrap As Alan Stern pointed out this member has nothing to do with the Command Status Wrapper (CSW) as specified by the Universal Serial Bus Mass Storage Class Bulk-Only Transport rev 1.0. It defines the structure without the additional 18 filler bytes and defines the total size of the struct to exactly 13 bytes. Larger responses should be dropped. All in-tree users use a defines instead of sizeof() of this struct as far I can tell. Cc: Alan Stern Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/storage.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/usb/storage.h b/include/linux/usb/storage.h index 4de58b15fad6..cb33fff2ba0b 100644 --- a/include/linux/usb/storage.h +++ b/include/linux/usb/storage.h @@ -71,7 +71,6 @@ struct bulk_cs_wrap { __u32 Tag; /* same as original command */ __le32 Residue; /* amount not transferred */ __u8 Status; /* see below */ - __u8 Filler[18]; }; #define US_BULK_CS_WRAP_LEN 13 From d1cddb4a8e9b09c33158acae05c48069d74fa4d0 Mon Sep 17 00:00:00 2001 From: Greg KH Date: Fri, 24 Feb 2012 15:38:14 -0800 Subject: [PATCH 174/269] USB: create module_usb_serial_driver macro Now that Alan Stern has cleaned up the usb serial driver registration, we have the ability to create a module_usb_serial_driver macro to make things a bit simpler, like the other *_driver macros created. But, as we need two functions here, we can't reuse the existing module_driver() macro, so we need to roll our own. Here's a patch implementing module_usb_serial_driver() and it converts the pl2303 driver to use it, showing a nice cleanup. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 18 +----------------- include/linux/usb/serial.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index cc65d810c8f5..ff4a174fa5de 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -855,23 +855,7 @@ static struct usb_serial_driver * const serial_drivers[] = { &pl2303_device, NULL }; -static int __init pl2303_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&pl2303_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); - return retval; -} - -static void __exit pl2303_exit(void) -{ - usb_serial_deregister_drivers(&pl2303_driver, serial_drivers); -} - -module_init(pl2303_init); -module_exit(pl2303_exit); +module_usb_serial_driver(pl2303_driver, serial_drivers); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 34c06a723dcc..7b1db841e2a8 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -406,5 +406,33 @@ do { \ } \ } while (0) +/* + * module_usb_serial_driver() - Helper macro for registering a USB Serial driver + * @__usb_driver: usb_driver struct to register + * @__serial_drivers: list of usb_serial drivers to register + * + * Helper macro for USB serial drivers which do not do anything special + * in module init/exit. This eliminates a lot of boilerplate. Each + * module may only use this macro once, and calling it replaces + * module_init() and module_exit() + * + * Note, we can't use the generic module_driver() call here, due to the + * two parameters in the usb_serial_* functions, so we roll our own here + * :( + */ +#define module_usb_serial_driver(__usb_driver, __serial_drivers) \ +static int __init usb_serial_driver_init(void) \ +{ \ + return usb_serial_register_drivers(&(__usb_driver), \ + (__serial_drivers)); \ +} \ +module_init(usb_serial_driver_init); \ +static void __exit usb_serial_driver_exit(void) \ +{ \ + return usb_serial_deregister_drivers(&(__usb_driver), \ + (__serial_drivers)); \ +} \ +module_exit(usb_serial_driver_exit); + #endif /* __LINUX_USB_SERIAL_H */ From f136e8b61c205fa6dccdc45fbda372f3acb2b5ab Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:27 -0800 Subject: [PATCH 175/269] USB: serial: quatech_usb2.c: use module_usb_serial_driver This converts the quatech_usb2.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Lucas De Marchi CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/staging/quatech_usb2/quatech_usb2.c | 22 +-------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/drivers/staging/quatech_usb2/quatech_usb2.c b/drivers/staging/quatech_usb2/quatech_usb2.c index b8a078abd6c7..bb977e00cc86 100644 --- a/drivers/staging/quatech_usb2/quatech_usb2.c +++ b/drivers/staging/quatech_usb2/quatech_usb2.c @@ -1966,27 +1966,7 @@ static struct usb_serial_driver * const serial_drivers[] = { &quatech2_device, NULL }; -static int __init quausb2_usb_init(void) -{ - int retval; - - dbg("%s\n", __func__); - - retval = usb_serial_register_drivers(&quausb2_usb_driver, - serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit quausb2_usb_exit(void) -{ - usb_serial_deregister_drivers(&quausb2_usb_driver, serial_drivers); -} - -module_init(quausb2_usb_init); -module_exit(quausb2_usb_exit); +module_usb_serial_driver(quausb2_usb_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); From e42f85f3d410a5457a2db61d883437ac9e32cecc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:30 -0800 Subject: [PATCH 176/269] USB: serial: serqt_usb2.c: use module_usb_serial_driver This converts the serqt_usb2.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Bill Pemberton CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/staging/serqt_usb2/serqt_usb2.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c index 04b6be86df1a..ae1d815e2a53 100644 --- a/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/drivers/staging/serqt_usb2/serqt_usb2.c @@ -1612,27 +1612,7 @@ static struct usb_serial_driver * const serial_drivers[] = { &quatech_device, NULL }; -static int __init serqt_usb_init(void) -{ - int retval; - - dbg("%s\n", __func__); - - retval = usb_serial_register_drivers(&serqt_usb_driver, - serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit serqt_usb_exit(void) -{ - usb_serial_deregister_drivers(&serqt_usb_driver, serial_drivers); -} - -module_init(serqt_usb_init); -module_exit(serqt_usb_exit); +module_usb_serial_driver(serqt_usb_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); From 6f84a5198f3ff537da2a0a0d2d50e6d8f91d0383 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:32 -0800 Subject: [PATCH 177/269] USB: serial: aircable.c: use module_usb_serial_driver This converts the aircable.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Paul Gortmaker CC: Lucas De Marchi CC: Rusty Russell CC: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/aircable.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index dbf3bddc1b51..eec4fb9a35c1 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -196,23 +196,12 @@ static struct usb_serial_driver * const serial_drivers[] = { &aircable_device, NULL }; -static int __init aircable_init(void) -{ - return usb_serial_register_drivers(&aircable_driver, serial_drivers); -} - -static void __exit aircable_exit(void) -{ - usb_serial_deregister_drivers(&aircable_driver, serial_drivers); -} +module_usb_serial_driver(aircable_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); -module_init(aircable_init); -module_exit(aircable_exit); - module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); From a9a535d35844044e3df56e49df5176db26bbb487 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:35 -0800 Subject: [PATCH 178/269] USB: serial: ark3116.c: use module_usb_serial_driver This converts the ark3116.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab CC: Bart Hartgers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ark3116.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index ab2cf1165c60..f99f47100dd8 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -747,27 +747,8 @@ static struct usb_serial_driver * const serial_drivers[] = { &ark3116_device, NULL }; -static int __init ark3116_init(void) -{ - int retval; +module_usb_serial_driver(ark3116_driver, serial_drivers); - retval = usb_serial_register_drivers(&ark3116_driver, serial_drivers); - if (retval == 0) { - printk(KERN_INFO "%s:" - DRIVER_VERSION ":" - DRIVER_DESC "\n", - KBUILD_MODNAME); - } - return retval; -} - -static void __exit ark3116_exit(void) -{ - usb_serial_deregister_drivers(&ark3116_driver, serial_drivers); -} - -module_init(ark3116_init); -module_exit(ark3116_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR(DRIVER_AUTHOR); From d2daea74cca96a9af28f55e361ae359e7027d26f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:35 -0800 Subject: [PATCH 179/269] USB: serial: belkin_sa.c: use module_usb_serial_driver This converts the belkin_sa.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: William Greathouse Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/belkin_sa.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index e8b473f5acf7..a52e0d2cec31 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -524,26 +524,7 @@ exit: return retval; } - -static int __init belkin_sa_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&belkin_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit belkin_sa_exit (void) -{ - usb_serial_deregister_drivers(&belkin_driver, serial_drivers); -} - - -module_init(belkin_sa_init); -module_exit(belkin_sa_exit); +module_usb_serial_driver(belkin_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); From a5f5e6c2d80d073e09918e7a02f3355503ff3922 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:37 -0800 Subject: [PATCH 180/269] USB: serial: ch341.c: use module_usb_serial_driver This converts the ch341.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ch341.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 23de3b039a28..aaab32db31d0 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -652,21 +652,9 @@ static struct usb_serial_driver * const serial_drivers[] = { &ch341_device, NULL }; -static int __init ch341_init(void) -{ - return usb_serial_register_drivers(&ch341_driver, serial_drivers); -} +module_usb_serial_driver(ch341_driver, serial_drivers); -static void __exit ch341_exit(void) -{ - usb_serial_deregister_drivers(&ch341_driver, serial_drivers); -} - -module_init(ch341_init); -module_exit(ch341_exit); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); - -/* EOF ch341.c */ From 274f3b1e82c899fd1b39822c2ee39bbac52f3d3c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:40 -0800 Subject: [PATCH 181/269] USB: serial: cp210x.c: use module_usb_serial_driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This converts the cp210x.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Johan Hovold CC: Rusty Russell CC: Florian Fainelli CC: "Malte Schröder" Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 01a9374357f1..651b2aa13486 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -850,24 +850,7 @@ static int cp210x_startup(struct usb_serial *serial) return 0; } -static int __init cp210x_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&cp210x_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit cp210x_exit(void) -{ - usb_serial_deregister_drivers(&cp210x_driver, serial_drivers); -} - -module_init(cp210x_init); -module_exit(cp210x_exit); +module_usb_serial_driver(cp210x_driver, serial_drivers); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); From 5671df5c1c6ee664ebc66a5be60a282afee8d340 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:40 -0800 Subject: [PATCH 182/269] USB: serial: cyberjack.c: use module_usb_serial_driver This converts the cyberjack.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Matthias Bruestle and Harald Welte Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cyberjack.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index d2e536f649ba..d39b9418f2fb 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -475,26 +475,7 @@ exit: usb_serial_port_softint(port); } -static int __init cyberjack_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&cyberjack_driver, serial_drivers); - if (retval == 0) { - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION " " - DRIVER_AUTHOR "\n"); - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); - } - return retval; -} - -static void __exit cyberjack_exit(void) -{ - usb_serial_deregister_drivers(&cyberjack_driver, serial_drivers); -} - -module_init(cyberjack_init); -module_exit(cyberjack_exit); +module_usb_serial_driver(cyberjack_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); From 7e3131f897969f94f605f3e929e2da35202c86d6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:41 -0800 Subject: [PATCH 183/269] USB: serial: cypress_m8.c: use module_usb_serial_driver This converts the cypress_m8.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Lonnie Mendez Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cypress_m8.c | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index bc5057513d5d..afc886c75d2f 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -1346,35 +1346,7 @@ static void cypress_write_int_callback(struct urb *urb) cypress_send(port); } - -/***************************************************************************** - * Module functions - *****************************************************************************/ - -static int __init cypress_init(void) -{ - int retval; - - dbg("%s", __func__); - - retval = usb_serial_register_drivers(&cypress_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - - -static void __exit cypress_exit(void) -{ - dbg("%s", __func__); - - usb_serial_deregister_drivers(&cypress_driver, serial_drivers); -} - - -module_init(cypress_init); -module_exit(cypress_exit); +module_usb_serial_driver(cypress_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); From 89ddc53c4ab1e297058b2995541541c22b9de160 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:41 -0800 Subject: [PATCH 184/269] USB: serial: digi_acceleport.c: use module_usb_serial_driver This converts the digi_acceleport.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Peter Berger CC: Al Borchers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/digi_acceleport.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index f0e776bb1ffb..999f91bf70de 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -1580,26 +1580,7 @@ static int digi_read_oob_callback(struct urb *urb) } -static int __init digi_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&digi_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit digi_exit (void) -{ - usb_serial_deregister_drivers(&digi_driver, serial_drivers); -} - - -module_init(digi_init); -module_exit(digi_exit); - +module_usb_serial_driver(digi_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); From 10a6b9ce8ecf0dcaabb10089bdf1b4bb30f3092a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:42 -0800 Subject: [PATCH 185/269] USB: serial: empeg.c: use module_usb_serial_driver This converts the empeg.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Gary Brubaker Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/empeg.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 51bcbd5d5e8e..5b99fc09e327 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -138,25 +138,7 @@ static void empeg_init_termios(struct tty_struct *tty) tty_encode_baud_rate(tty, 115200, 115200); } -static int __init empeg_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&empeg_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit empeg_exit(void) -{ - usb_serial_deregister_drivers(&empeg_driver, serial_drivers); -} - - -module_init(empeg_init); -module_exit(empeg_exit); +module_usb_serial_driver(empeg_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); From 65e3b087d55b224a8c036976535601dd66a7cebd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:44 -0800 Subject: [PATCH 186/269] USB: serial: funsoft.c: use module_usb_serial_driver This converts the funsoft.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/funsoft.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c index bb274a244ae9..4577b3607922 100644 --- a/drivers/usb/serial/funsoft.c +++ b/drivers/usb/serial/funsoft.c @@ -44,18 +44,8 @@ static struct usb_serial_driver * const serial_drivers[] = { &funsoft_device, NULL }; -static int __init funsoft_init(void) -{ - return usb_serial_register_drivers(&funsoft_driver, serial_drivers); -} +module_usb_serial_driver(funsoft_driver, serial_drivers); -static void __exit funsoft_exit(void) -{ - usb_serial_deregister_drivers(&funsoft_driver, serial_drivers); -} - -module_init(funsoft_init); -module_exit(funsoft_exit); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); From db62c08128acdb6f37038f3711621b52963fe5eb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:46 -0800 Subject: [PATCH 187/269] USB: serial: garmin_gps.c: use module_usb_serial_driver This converts the garmin_gps.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Johan Hovold CC: Andrew Morton CC: Rusty Russell CC: Mike Frysinger Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/garmin_gps.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 69da3abcb363..e8eb6347bf3a 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1516,29 +1516,7 @@ static struct usb_serial_driver * const serial_drivers[] = { &garmin_device, NULL }; - -static int __init garmin_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&garmin_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - - -static void __exit garmin_exit(void) -{ - usb_serial_deregister_drivers(&garmin_driver, serial_drivers); -} - - - - -module_init(garmin_init); -module_exit(garmin_exit); +module_usb_serial_driver(garmin_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); @@ -1548,4 +1526,3 @@ module_param(debug, bool, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(debug, "Debug enabled or not"); module_param(initial_mode, int, S_IRUGO); MODULE_PARM_DESC(initial_mode, "Initial mode"); - From 68e9c9a7fdbddab3407596b3e7f1a4972d045444 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:49 -0800 Subject: [PATCH 188/269] USB: serial: hp4x.c: use module_usb_serial_driver This converts the hp4x.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/hp4x.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c index 325cf092b61c..2563e788c9b3 100644 --- a/drivers/usb/serial/hp4x.c +++ b/drivers/usb/serial/hp4x.c @@ -56,24 +56,7 @@ static struct usb_serial_driver * const serial_drivers[] = { &hp49gp_device, NULL }; -static int __init hp49gp_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&hp49gp_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit hp49gp_exit(void) -{ - usb_serial_deregister_drivers(&hp49gp_driver, serial_drivers); -} - -module_init(hp49gp_init); -module_exit(hp49gp_exit); +module_usb_serial_driver(hp49gp_driver, serial_drivers); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); From 36ccce49128c1bce042273ee723e93f7cca06330 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:51 -0800 Subject: [PATCH 189/269] USB: serial: io_edgeport.c: use module_usb_serial_driver This converts the io_edgeport.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Johan Hovold CC: Rusty Russell CC: Huzaifa Sidhpurwala CC: Kuninori Morimoto Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_edgeport.c | 35 +++----------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 55afa233aacd..323e87235711 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -193,7 +193,8 @@ static const struct divisor_table_entry divisor_table[] = { /* local variables */ static bool debug; -static atomic_t CmdUrbs; /* Number of outstanding Command Write Urbs */ +/* Number of outstanding Command Write Urbs */ +static atomic_t CmdUrbs = ATOMIC_INIT(0); /* local function prototypes */ @@ -3180,38 +3181,8 @@ static void edge_release(struct usb_serial *serial) kfree(edge_serial); } +module_usb_serial_driver(io_driver, serial_drivers); -/**************************************************************************** - * edgeport_init - * This is called by the module subsystem, or on startup to initialize us - ****************************************************************************/ -static int __init edgeport_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&io_driver, serial_drivers); - if (retval == 0) { - atomic_set(&CmdUrbs, 0); - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - } - return retval; -} - - -/**************************************************************************** - * edgeport_exit - * Called when the driver is about to be unloaded. - ****************************************************************************/ -static void __exit edgeport_exit (void) -{ - usb_serial_deregister_drivers(&io_driver, serial_drivers); -} - -module_init(edgeport_init); -module_exit(edgeport_exit); - -/* Module information */ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); From 8485f8c9652b226726827e61fb43647bf22e691f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:53 -0800 Subject: [PATCH 190/269] USB: serial: io_ti.c: use module_usb_serial_driver This converts the io_ti.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Johan Hovold CC: Lucas De Marchi CC: "Eric W. Biederman" CC: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 484db3331f88..40a95a7fe383 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2783,27 +2783,8 @@ static struct usb_serial_driver * const serial_drivers[] = { &edgeport_1port_device, &edgeport_2port_device, NULL }; +module_usb_serial_driver(io_driver, serial_drivers); -static int __init edgeport_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&io_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit edgeport_exit(void) -{ - usb_serial_deregister_drivers(&io_driver, serial_drivers); -} - -module_init(edgeport_init); -module_exit(edgeport_exit); - -/* Module information */ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); From f939484bb6473e51c1516ab9a4f3a7620cd95d72 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:56 -0800 Subject: [PATCH 191/269] USB: serial: ipw.c: use module_usb_serial_driver This converts the ipw.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Rusty Russell CC: Oliver Neukum CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ipw.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 27b8886f1055..76a06406e26a 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -333,25 +333,7 @@ static struct usb_serial_driver * const serial_drivers[] = { &ipw_device, NULL }; - -static int __init usb_ipw_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&usb_ipw_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit usb_ipw_exit(void) -{ - usb_serial_deregister_drivers(&usb_ipw_driver, serial_drivers); -} - -module_init(usb_ipw_init); -module_exit(usb_ipw_exit); +module_usb_serial_driver(usb_ipw_driver, serial_drivers); /* Module information */ MODULE_AUTHOR(DRIVER_AUTHOR); From d01bf4139d411369828b8d104fde418882226da5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:58 -0800 Subject: [PATCH 192/269] USB: serial: iuu_phoenix.c: use module_usb_serial_driver This converts the iuu_phoenix.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Rusty Russell CC: Johan Hovold CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/iuu_phoenix.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 97a7ea2a5e4f..f2192d527db0 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -1294,24 +1294,7 @@ static struct usb_serial_driver * const serial_drivers[] = { &iuu_device, NULL }; -static int __init iuu_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&iuu_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit iuu_exit(void) -{ - usb_serial_deregister_drivers(&iuu_driver, serial_drivers); -} - -module_init(iuu_init); -module_exit(iuu_exit); +module_usb_serial_driver(iuu_driver, serial_drivers); MODULE_AUTHOR("Alain Degreffe eczema@ecze.com"); From 165c793d9291c007f957e73cf6a5d7ffcb8b4d1e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:59 -0800 Subject: [PATCH 193/269] USB: serial: keyspan.c: use module_usb_serial_driver This converts the keyspan.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 0d5d3025a663..a39ddd1b0dca 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -130,25 +130,7 @@ struct keyspan_port_private { #include "keyspan_usa67msg.h" -/* Functions used by new usb-serial code. */ -static int __init keyspan_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&keyspan_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit keyspan_exit(void) -{ - usb_serial_deregister_drivers(&keyspan_driver, serial_drivers); -} - -module_init(keyspan_init); -module_exit(keyspan_exit); +module_usb_serial_driver(keyspan_driver, serial_drivers); static void keyspan_break_ctl(struct tty_struct *tty, int break_state) { From d40f5b0c0c6bc67fa35078501d097bf11f16483a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:11:59 -0800 Subject: [PATCH 194/269] USB: serial: keyspan_pda.c: use module_usb_serial_driver This converts the keyspan_pda.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan_pda.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index b88a7906d4c2..693bcdfcb3d5 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -834,21 +834,7 @@ static struct usb_serial_driver * const serial_drivers[] = { NULL }; -static int __init keyspan_pda_init(void) -{ - return usb_serial_register_drivers(&keyspan_pda_driver, - serial_drivers); -} - -static void __exit keyspan_pda_exit(void) -{ - usb_serial_deregister_drivers(&keyspan_pda_driver, - serial_drivers); -} - - -module_init(keyspan_pda_init); -module_exit(keyspan_pda_exit); +module_usb_serial_driver(keyspan_pda_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); @@ -856,4 +842,3 @@ MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); - From 11f79858ce0393b6b721f91cd8f69ec7c0192f9b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:00 -0800 Subject: [PATCH 195/269] USB: serial: kl5kusb105.c: use module_usb_serial_driver This converts the kl5kusb105.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kl5kusb105.c | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 0e65e50edd50..10f05407e535 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -692,32 +692,11 @@ static int klsi_105_tiocmset(struct tty_struct *tty, return retval; } - -static int __init klsi_105_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&kl5kusb105d_driver, - serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit klsi_105_exit(void) -{ - usb_serial_deregister_drivers(&kl5kusb105d_driver, serial_drivers); -} - - -module_init(klsi_105_init); -module_exit(klsi_105_exit); +module_usb_serial_driver(kl5kusb105d_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "enable extensive debugging messages"); From 8a9040b123b9fd325c38a985c109289d04349873 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:02 -0800 Subject: [PATCH 196/269] USB: serial: kobil_sct.c: use module_usb_serial_driver This converts the kobil_sct.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Johan Hovold CC: Jiri Slaby CC: Alan Stern CC: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kobil_sct.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index a033dd7dc265..4a9a75eb9b95 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -683,25 +683,7 @@ static int kobil_ioctl(struct tty_struct *tty, } } -static int __init kobil_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&kobil_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - - -static void __exit kobil_exit(void) -{ - usb_serial_deregister_drivers(&kobil_driver, serial_drivers); -} - -module_init(kobil_init); -module_exit(kobil_exit); +module_usb_serial_driver(kobil_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); From 193ecee4424937e55945c955cbd09717a66dbc07 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:05 -0800 Subject: [PATCH 197/269] USB: serial: mct_u232.c: use module_usb_serial_driver This converts the mct_u232.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mct_u232.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 6d9a7f8b13db..6edd26130e25 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -906,25 +906,7 @@ static int mct_u232_get_icount(struct tty_struct *tty, return 0; } -static int __init mct_u232_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&mct_u232_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - - -static void __exit mct_u232_exit(void) -{ - usb_serial_deregister_drivers(&mct_u232_driver, serial_drivers); -} - -module_init(mct_u232_init); -module_exit(mct_u232_exit); +module_usb_serial_driver(mct_u232_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); From 964e2b8425f5f37baa4f1fe6c15cdaf258d5cb51 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:07 -0800 Subject: [PATCH 198/269] USB: serial: mos7720.c: use module_usb_serial_driver This converts the mos7720.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7720.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 4dfbad80418c..bdce82034122 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -2203,28 +2203,8 @@ static struct usb_serial_driver * const serial_drivers[] = { &moschip7720_2port_driver, NULL }; -static int __init moschip7720_init(void) -{ - int retval; +module_usb_serial_driver(usb_driver, serial_drivers); - dbg("%s: Entering ..........", __func__); - - retval = usb_serial_register_drivers(&usb_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit moschip7720_exit(void) -{ - usb_serial_deregister_drivers(&usb_driver, serial_drivers); -} - -module_init(moschip7720_init); -module_exit(moschip7720_exit); - -/* Module information */ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); From e7414d9a6d71027a2a0e8e4af6ef3cca7eaef80a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:10 -0800 Subject: [PATCH 199/269] USB: serial: mos7840.c: use module_usb_serial_driver This converts the mos7840.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 37 +----------------------------------- 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index b45522e12f68..f7e6e30f53ee 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2676,43 +2676,8 @@ static struct usb_serial_driver * const serial_drivers[] = { &moschip7840_4port_device, NULL }; -/**************************************************************************** - * moschip7840_init - * This is called by the module subsystem, or on startup to initialize us - ****************************************************************************/ -static int __init moschip7840_init(void) -{ - int retval; +module_usb_serial_driver(io_driver, serial_drivers); - dbg("%s", " mos7840_init :entering.........."); - - retval = usb_serial_register_drivers(&io_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - dbg("%s", "Leaving..."); - return retval; -} - -/**************************************************************************** - * moschip7840_exit - * Called when the driver is about to be unloaded. - ****************************************************************************/ -static void __exit moschip7840_exit(void) -{ - - dbg("%s", " mos7840_exit :entering.........."); - - usb_serial_deregister_drivers(&io_driver, serial_drivers); - - dbg("%s", "Entering..."); -} - -module_init(moschip7840_init); -module_exit(moschip7840_exit); - -/* Module information */ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); From 54cbcf51264ee63444a7f768a3ef9a7a0e0c4449 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:12 -0800 Subject: [PATCH 200/269] USB: serial: moto_modem.c: use module_usb_serial_driver This converts the moto_modem.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Alan Stern CC: Elizabeth Jennifer Myers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/moto_modem.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c index 0af57d31ab82..3ab6214b4bbf 100644 --- a/drivers/usb/serial/moto_modem.c +++ b/drivers/usb/serial/moto_modem.c @@ -51,16 +51,5 @@ static struct usb_serial_driver * const serial_drivers[] = { &moto_device, NULL }; -static int __init moto_init(void) -{ - return usb_serial_register_drivers(&moto_driver, serial_drivers); -} - -static void __exit moto_exit(void) -{ - usb_serial_deregister_drivers(&moto_driver, serial_drivers); -} - -module_init(moto_init); -module_exit(moto_exit); +module_usb_serial_driver(moto_driver, serial_drivers); MODULE_LICENSE("GPL"); From 78365eaaa136142dfae8ae0964f533014a389f80 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:14 -0800 Subject: [PATCH 201/269] USB: serial: navman.c: use module_usb_serial_driver This converts the navman.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/navman.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index fd4b2c833c0b..29ab6eb5b536 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c @@ -132,18 +132,8 @@ static struct usb_serial_driver * const serial_drivers[] = { &navman_device, NULL }; -static int __init navman_init(void) -{ - return usb_serial_register_drivers(&navman_driver, serial_drivers); -} +module_usb_serial_driver(navman_driver, serial_drivers); -static void __exit navman_exit(void) -{ - usb_serial_deregister_drivers(&navman_driver, serial_drivers); -} - -module_init(navman_init); -module_exit(navman_exit); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); From 6384eaefd337b465417e9b64ebf74717703c0788 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:17 -0800 Subject: [PATCH 202/269] USB: serial: omninet.c: use module_usb_serial_driver This converts the omninet.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/omninet.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 975d5c559ccb..88dc785bb298 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -321,27 +321,7 @@ static void omninet_release(struct usb_serial *serial) kfree(usb_get_serial_port_data(port)); } - -static int __init omninet_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&omninet_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - - -static void __exit omninet_exit(void) -{ - usb_serial_deregister_drivers(&omninet_driver, serial_drivers); -} - - -module_init(omninet_init); -module_exit(omninet_exit); +module_usb_serial_driver(omninet_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); From e206b7f831da365a38b22f72ba42db288db71c65 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:19 -0800 Subject: [PATCH 203/269] USB: serial: opticon.c: use module_usb_serial_driver This converts the opticon.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Rusty Russell CC: Johan Hovold CC: Kuninori Morimoto CC: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 7001ad779b94..82cc9d202b83 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -631,18 +631,8 @@ static struct usb_serial_driver * const serial_drivers[] = { &opticon_device, NULL }; -static int __init opticon_init(void) -{ - return usb_serial_register_drivers(&opticon_driver, serial_drivers); -} +module_usb_serial_driver(opticon_driver, serial_drivers); -static void __exit opticon_exit(void) -{ - usb_serial_deregister_drivers(&opticon_driver, serial_drivers); -} - -module_init(opticon_init); -module_exit(opticon_exit); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); From 9334c4c16e6fa80dc55865897337b49c1753f33b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:19 -0800 Subject: [PATCH 204/269] USB: serial: option.c: use module_usb_serial_driver This converts the option.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ab5047944d1d..005511b2ee08 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1289,25 +1289,7 @@ struct option_port_private { unsigned long tx_start_time[N_OUT_URB]; }; -/* Functions used by new usb-serial code. */ -static int __init option_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&option_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit option_exit(void) -{ - usb_serial_deregister_drivers(&option_driver, serial_drivers); -} - -module_init(option_init); -module_exit(option_exit); +module_usb_serial_driver(option_driver, serial_drivers); static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason, const struct option_blacklist_info *blacklist) From db55a0492d87c80d8d9a5cf330c58dee55757cba Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:22 -0800 Subject: [PATCH 205/269] USB: serial: oti6858.c: use module_usb_serial_driver This converts the oti6858.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/oti6858.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 53f2768c9a36..5fdc33c6a3c0 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -958,20 +958,7 @@ static void oti6858_write_bulk_callback(struct urb *urb) } } -/* module description and (de)initialization */ - -static int __init oti6858_init(void) -{ - return usb_serial_register_drivers(&oti6858_driver, serial_drivers); -} - -static void __exit oti6858_exit(void) -{ - usb_serial_deregister_drivers(&oti6858_driver, serial_drivers); -} - -module_init(oti6858_init); -module_exit(oti6858_exit); +module_usb_serial_driver(oti6858_driver, serial_drivers); MODULE_DESCRIPTION(OTI6858_DESCRIPTION); MODULE_AUTHOR(OTI6858_AUTHOR); From 5bce269d3a464b436d9b416105821aa5257fee36 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:24 -0800 Subject: [PATCH 206/269] USB: serial: qcaux.c: use module_usb_serial_driver This converts the qcaux.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Alan Stern CC: Dan Williams Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcaux.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index a2ce274b3f28..966245680f55 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -97,16 +97,5 @@ static struct usb_serial_driver * const serial_drivers[] = { &qcaux_device, NULL }; -static int __init qcaux_init(void) -{ - return usb_serial_register_drivers(&qcaux_driver, serial_drivers); -} - -static void __exit qcaux_exit(void) -{ - usb_serial_deregister_drivers(&qcaux_driver, serial_drivers); -} - -module_init(qcaux_init); -module_exit(qcaux_exit); +module_usb_serial_driver(qcaux_driver, serial_drivers); MODULE_LICENSE("GPL"); From 3d8d7296f7dbc7c977b8552dcfa649817d91d24c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:26 -0800 Subject: [PATCH 207/269] USB: serial: qcserial.c: use module_usb_serial_driver This converts the qcserial.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Steven Hardy CC: Thomas Tuttle CC: Paul Gortmaker CC: Rusty Russell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcserial.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 4f3a5a794884..0206b10c9e6e 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -285,18 +285,7 @@ static struct usb_serial_driver * const serial_drivers[] = { &qcdevice, NULL }; -static int __init qcinit(void) -{ - return usb_serial_register_drivers(&qcdriver, serial_drivers); -} - -static void __exit qcexit(void) -{ - usb_serial_deregister_drivers(&qcdriver, serial_drivers); -} - -module_init(qcinit); -module_exit(qcexit); +module_usb_serial_driver(qcdriver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); From b4264af2c59e287153e99c7b4e7516086366d272 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:29 -0800 Subject: [PATCH 208/269] USB: serial: siemens_mpi.c: use module_usb_serial_driver This converts the siemens_mpi.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/siemens_mpi.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c index 8aa4c1aef6d1..46c0430fd38b 100644 --- a/drivers/usb/serial/siemens_mpi.c +++ b/drivers/usb/serial/siemens_mpi.c @@ -49,26 +49,8 @@ static struct usb_serial_driver * const serial_drivers[] = { &siemens_usb_mpi_device, NULL }; -static int __init siemens_usb_mpi_init(void) -{ - int retval; +module_usb_serial_driver(siemens_usb_mpi_driver, serial_drivers); - retval = usb_serial_register_drivers(&siemens_usb_mpi_driver, - serial_drivers); - if (retval == 0) { - printk(KERN_INFO DRIVER_DESC "\n"); - printk(KERN_INFO DRIVER_VERSION " " DRIVER_AUTHOR "\n"); - } - return retval; -} - -static void __exit siemens_usb_mpi_exit(void) -{ - usb_serial_deregister_drivers(&siemens_usb_mpi_driver, serial_drivers); -} - -module_init(siemens_usb_mpi_init); -module_exit(siemens_usb_mpi_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); From c9d521747872ecb77ba39bb9a8162449cd74d343 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:31 -0800 Subject: [PATCH 209/269] USB: serial: sierra.c: use module_usb_serial_driver This converts the sierra.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Alan Stern CC: Rusty Russell CC: Johan Hovold CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index d75a75b83e9f..f14465a83dd1 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -1115,25 +1115,7 @@ static struct usb_serial_driver * const serial_drivers[] = { &sierra_device, NULL }; -/* Functions used by new usb-serial code. */ -static int __init sierra_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&sierra_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit sierra_exit(void) -{ - usb_serial_deregister_drivers(&sierra_driver, serial_drivers); -} - -module_init(sierra_init); -module_exit(sierra_exit); +module_usb_serial_driver(sierra_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); From a385c150a49e8ef49cd27318a6fd7759ed6bfa42 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:34 -0800 Subject: [PATCH 210/269] USB: serial: spcp8x5.c: use module_usb_serial_driver This converts the spcp8x5.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/spcp8x5.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index af898937d4b1..f06c9a8f3d37 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -666,24 +666,7 @@ static struct usb_serial_driver * const serial_drivers[] = { &spcp8x5_device, NULL }; -static int __init spcp8x5_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&spcp8x5_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit spcp8x5_exit(void) -{ - usb_serial_deregister_drivers(&spcp8x5_driver, serial_drivers); -} - -module_init(spcp8x5_init); -module_exit(spcp8x5_exit); +module_usb_serial_driver(spcp8x5_driver, serial_drivers); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); From 3a67460715481772068aebf8c945667c285f2207 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:36 -0800 Subject: [PATCH 211/269] USB: serial: ssu100.c: use module_usb_serial_driver This converts the ssu100.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ssu100.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index ab8842107a8b..3cdc8a52de44 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -695,26 +695,7 @@ static struct usb_serial_driver * const serial_drivers[] = { &ssu100_device, NULL }; -static int __init ssu100_init(void) -{ - int retval; - - dbg("%s", __func__); - - retval = usb_serial_register_drivers(&ssu100_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit ssu100_exit(void) -{ - usb_serial_deregister_drivers(&ssu100_driver, serial_drivers); -} - -module_init(ssu100_init); -module_exit(ssu100_exit); +module_usb_serial_driver(ssu100_driver, serial_drivers); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); From ba76df3f65ce08413563119c9c77852b0835fbef Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:38 -0800 Subject: [PATCH 212/269] USB: serial: symbolserial.c: use module_usb_serial_driver This converts the symbolserial.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Rusty Russell CC: Johan Hovold CC: Kuninori Morimoto CC: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/symbolserial.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index 76cd9f2a08c0..1a5be136e6cf 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -309,18 +309,8 @@ static struct usb_serial_driver * const serial_drivers[] = { &symbol_device, NULL }; -static int __init symbol_init(void) -{ - return usb_serial_register_drivers(&symbol_driver, serial_drivers); -} +module_usb_serial_driver(symbol_driver, serial_drivers); -static void __exit symbol_exit(void) -{ - usb_serial_deregister_drivers(&symbol_driver, serial_drivers); -} - -module_init(symbol_init); -module_exit(symbol_exit); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR); From 491c77a96689821bbe6acbef7dd1544bec35f794 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:41 -0800 Subject: [PATCH 213/269] USB: serial: usb_debug.c: use module_usb_serial_driver This converts the usb_debug.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Johan Hovold CC: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb_debug.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index 5b29b4a2ebc7..e3e8995a4739 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -83,16 +83,5 @@ static struct usb_serial_driver * const serial_drivers[] = { &debug_device, NULL }; -static int __init debug_init(void) -{ - return usb_serial_register_drivers(&debug_driver, serial_drivers); -} - -static void __exit debug_exit(void) -{ - usb_serial_deregister_drivers(&debug_driver, serial_drivers); -} - -module_init(debug_init); -module_exit(debug_exit); +module_usb_serial_driver(debug_driver, serial_drivers); MODULE_LICENSE("GPL"); From b99dab079445f5d586d4d9e0f81d3d07ecbf51f4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:43 -0800 Subject: [PATCH 214/269] USB: serial: vivopay-serial.c: use module_usb_serial_driver This converts the vivopay-serial.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/vivopay-serial.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/usb/serial/vivopay-serial.c b/drivers/usb/serial/vivopay-serial.c index a6f113bd4fae..078f338b5feb 100644 --- a/drivers/usb/serial/vivopay-serial.c +++ b/drivers/usb/serial/vivopay-serial.c @@ -45,25 +45,7 @@ static struct usb_serial_driver * const serial_drivers[] = { &vivopay_serial_device, NULL }; -static int __init vivopay_serial_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&vivopay_serial_driver, - serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - -static void __exit vivopay_serial_exit(void) -{ - usb_serial_deregister_drivers(&vivopay_serial_driver, serial_drivers); -} - -module_init(vivopay_serial_init); -module_exit(vivopay_serial_exit); +module_usb_serial_driver(vivopay_serial_driver, serial_drivers); MODULE_AUTHOR("Forest Bond "); MODULE_DESCRIPTION(DRIVER_DESC); From 421f38835fe677d8c2e8c25628ae9cd4019653d2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:44 -0800 Subject: [PATCH 215/269] USB: serial: whiteheat.c: use module_usb_serial_driver This converts the whiteheat.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Support Department Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/whiteheat.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index a29be37a3a67..407e23c87946 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -1454,30 +1454,7 @@ out: tty_kref_put(tty); } - -/***************************************************************************** - * Connect Tech's White Heat module functions - *****************************************************************************/ -static int __init whiteheat_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&whiteheat_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; -} - - -static void __exit whiteheat_exit(void) -{ - usb_serial_deregister_drivers(&whiteheat_driver, serial_drivers); -} - - -module_init(whiteheat_init); -module_exit(whiteheat_exit); +module_usb_serial_driver(whiteheat_driver, serial_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); From dba607f9f0aebfa8f29b3eb911250aa19d5d71a8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:12:46 -0800 Subject: [PATCH 216/269] USB: serial: zio.c: use module_usb_serial_driver This converts the zio.c driver to use the module_usb_serial_driver() call instead of having to have a module_init/module_exit function, saving a lot of duplicated code. CC: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/zio.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/usb/serial/zio.c b/drivers/usb/serial/zio.c index ae8115aab77d..9d0bb3752cd4 100644 --- a/drivers/usb/serial/zio.c +++ b/drivers/usb/serial/zio.c @@ -42,16 +42,5 @@ static struct usb_serial_driver * const serial_drivers[] = { &zio_device, NULL }; -static int __init zio_init(void) -{ - return usb_serial_register_drivers(&zio_driver, serial_drivers); -} - -static void __exit zio_exit(void) -{ - usb_serial_deregister_drivers(&zio_driver, serial_drivers); -} - -module_init(zio_init); -module_exit(zio_exit); +module_usb_serial_driver(zio_driver, serial_drivers); MODULE_LICENSE("GPL"); From aac1fc386fa13f9f450909fcfb02e73db55f0c0f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Feb 2012 13:36:35 -0800 Subject: [PATCH 217/269] USB: serial: add Fintek F81232 usb to serial driver This is the first cut at a driver for the Fintek F81232 USB to serial single port converter. This provides the initial framework for the device, and some data can move through it, but no line settings are handled, so it's not that useful yet. It does give people a starting place to work from. Thank to Fintek for providing samples and specifications, without which, this driver would have never been able to be written. Cc: Amanda Ying Cc: Tom Tsai Cc: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 9 + drivers/usb/serial/Makefile | 1 + drivers/usb/serial/f81232.c | 405 ++++++++++++++++++++++++++++++++++++ 3 files changed, 415 insertions(+) create mode 100644 drivers/usb/serial/f81232.c diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 677f577c0243..434df7f2a4bd 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -238,6 +238,15 @@ config USB_SERIAL_EDGEPORT_TI To compile this driver as a module, choose M here: the module will be called io_ti. +config USB_SERIAL_F81232 + tristate "USB Fintek F81232 Single Port Serial Driver" + help + Say Y here if you want to use the Fintek F81232 single + port usb to serial adapter. + + To compile this driver as a module, choose M here: the + module will be called f81232. + config USB_SERIAL_GARMIN tristate "USB Garmin GPS driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 9e536eefb32c..5ac438b40270 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o +obj-$(CONFIG_USB_SERIAL_F81232) += f81232.o obj-$(CONFIG_USB_SERIAL_FTDI_SIO) += ftdi_sio.o obj-$(CONFIG_USB_SERIAL_FUNSOFT) += funsoft.o obj-$(CONFIG_USB_SERIAL_GARMIN) += garmin_gps.o diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c new file mode 100644 index 000000000000..88c0b1963920 --- /dev/null +++ b/drivers/usb/serial/f81232.c @@ -0,0 +1,405 @@ +/* + * Fintek F81232 USB to serial adaptor driver + * + * Copyright (C) 2012 Greg Kroah-Hartman (gregkh@linuxfoundation.org) + * Copyright (C) 2012 Linux Foundation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool debug; + +static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x1934, 0x0706) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, id_table); + +#define CONTROL_DTR 0x01 +#define CONTROL_RTS 0x02 + +#define UART_STATE 0x08 +#define UART_STATE_TRANSIENT_MASK 0x74 +#define UART_DCD 0x01 +#define UART_DSR 0x02 +#define UART_BREAK_ERROR 0x04 +#define UART_RING 0x08 +#define UART_FRAME_ERROR 0x10 +#define UART_PARITY_ERROR 0x20 +#define UART_OVERRUN_ERROR 0x40 +#define UART_CTS 0x80 + +struct f81232_private { + spinlock_t lock; + wait_queue_head_t delta_msr_wait; + u8 line_control; + u8 line_status; +}; + +static void f81232_update_line_status(struct usb_serial_port *port, + unsigned char *data, + unsigned int actual_length) +{ +} + +static void f81232_read_int_callback(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + unsigned char *data = urb->transfer_buffer; + unsigned int actual_length = urb->actual_length; + int status = urb->status; + int retval; + + dbg("%s (%d)", __func__, port->number); + + switch (status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __func__, + status); + return; + default: + dbg("%s - nonzero urb status received: %d", __func__, + status); + goto exit; + } + + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, urb->transfer_buffer); + + f81232_update_line_status(port, data, actual_length); + +exit: + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(&urb->dev->dev, + "%s - usb_submit_urb failed with result %d\n", + __func__, retval); +} + +static void f81232_process_read_urb(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + struct f81232_private *priv = usb_get_serial_port_data(port); + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + char tty_flag = TTY_NORMAL; + unsigned long flags; + u8 line_status; + int i; + + /* update line status */ + spin_lock_irqsave(&priv->lock, flags); + line_status = priv->line_status; + priv->line_status &= ~UART_STATE_TRANSIENT_MASK; + spin_unlock_irqrestore(&priv->lock, flags); + wake_up_interruptible(&priv->delta_msr_wait); + + if (!urb->actual_length) + return; + + tty = tty_port_tty_get(&port->port); + if (!tty) + return; + + /* break takes precedence over parity, */ + /* which takes precedence over framing errors */ + if (line_status & UART_BREAK_ERROR) + tty_flag = TTY_BREAK; + else if (line_status & UART_PARITY_ERROR) + tty_flag = TTY_PARITY; + else if (line_status & UART_FRAME_ERROR) + tty_flag = TTY_FRAME; + dbg("%s - tty_flag = %d", __func__, tty_flag); + + /* overrun is special, not associated with a char */ + if (line_status & UART_OVERRUN_ERROR) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + + if (port->port.console && port->sysrq) { + for (i = 0; i < urb->actual_length; ++i) + if (!usb_serial_handle_sysrq_char(port, data[i])) + tty_insert_flip_char(tty, data[i], tty_flag); + } else { + tty_insert_flip_string_fixed_flag(tty, data, tty_flag, + urb->actual_length); + } + + tty_flip_buffer_push(tty); + tty_kref_put(tty); +} + +static int set_control_lines(struct usb_device *dev, u8 value) +{ + /* FIXME - Stubbed out for now */ + return 0; +} + +static void f81232_break_ctl(struct tty_struct *tty, int break_state) +{ + /* FIXME - Stubbed out for now */ + + /* + * break_state = -1 to turn on break, and 0 to turn off break + * see drivers/char/tty_io.c to see it used. + * last_set_data_urb_value NEVER has the break bit set in it. + */ +} + +static void f81232_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) +{ + /* FIXME - Stubbed out for now */ + + /* Don't change anything if nothing has changed */ + if (!tty_termios_hw_change(tty->termios, old_termios)) + return; + + /* Do the real work here... */ +} + +static int f81232_tiocmget(struct tty_struct *tty) +{ + /* FIXME - Stubbed out for now */ + return 0; +} + +static int f81232_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + /* FIXME - Stubbed out for now */ + return 0; +} + +static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port) +{ + struct ktermios tmp_termios; + int result; + + /* Setup termios */ + if (tty) + f81232_set_termios(tty, port, &tmp_termios); + + dbg("%s - submitting interrupt urb", __func__); + result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (result) { + dev_err(&port->dev, "%s - failed submitting interrupt urb," + " error %d\n", __func__, result); + return result; + } + + result = usb_serial_generic_open(tty, port); + if (result) { + usb_kill_urb(port->interrupt_in_urb); + return result; + } + + port->port.drain_delay = 256; + return 0; +} + +static void f81232_close(struct usb_serial_port *port) +{ + usb_serial_generic_close(port); + usb_kill_urb(port->interrupt_in_urb); +} + +static void f81232_dtr_rts(struct usb_serial_port *port, int on) +{ + struct f81232_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + u8 control; + + spin_lock_irqsave(&priv->lock, flags); + /* Change DTR and RTS */ + if (on) + priv->line_control |= (CONTROL_DTR | CONTROL_RTS); + else + priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); + control = priv->line_control; + spin_unlock_irqrestore(&priv->lock, flags); + set_control_lines(port->serial->dev, control); +} + +static int f81232_carrier_raised(struct usb_serial_port *port) +{ + struct f81232_private *priv = usb_get_serial_port_data(port); + if (priv->line_status & UART_DCD) + return 1; + return 0; +} + +static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +{ + struct f81232_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + unsigned int prevstatus; + unsigned int status; + unsigned int changed; + + spin_lock_irqsave(&priv->lock, flags); + prevstatus = priv->line_status; + spin_unlock_irqrestore(&priv->lock, flags); + + while (1) { + interruptible_sleep_on(&priv->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + + spin_lock_irqsave(&priv->lock, flags); + status = priv->line_status; + spin_unlock_irqrestore(&priv->lock, flags); + + changed = prevstatus ^ status; + + if (((arg & TIOCM_RNG) && (changed & UART_RING)) || + ((arg & TIOCM_DSR) && (changed & UART_DSR)) || + ((arg & TIOCM_CD) && (changed & UART_DCD)) || + ((arg & TIOCM_CTS) && (changed & UART_CTS))) { + return 0; + } + prevstatus = status; + } + /* NOTREACHED */ + return 0; +} + +static int f81232_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct serial_struct ser; + struct usb_serial_port *port = tty->driver_data; + dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); + + switch (cmd) { + case TIOCGSERIAL: + memset(&ser, 0, sizeof ser); + ser.type = PORT_16654; + ser.line = port->serial->minor; + ser.port = port->number; + ser.baud_base = 460800; + + if (copy_to_user((void __user *)arg, &ser, sizeof ser)) + return -EFAULT; + + return 0; + + case TIOCMIWAIT: + dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + return wait_modem_info(port, arg); + default: + dbg("%s not supported = 0x%04x", __func__, cmd); + break; + } + return -ENOIOCTLCMD; +} + +static int f81232_startup(struct usb_serial *serial) +{ + struct f81232_private *priv; + int i; + + for (i = 0; i < serial->num_ports; ++i) { + priv = kzalloc(sizeof(struct f81232_private), GFP_KERNEL); + if (!priv) + goto cleanup; + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + usb_set_serial_port_data(serial->port[i], priv); + } + return 0; + +cleanup: + for (--i; i >= 0; --i) { + priv = usb_get_serial_port_data(serial->port[i]); + kfree(priv); + usb_set_serial_port_data(serial->port[i], NULL); + } + return -ENOMEM; +} + +static void f81232_release(struct usb_serial *serial) +{ + int i; + struct f81232_private *priv; + + for (i = 0; i < serial->num_ports; ++i) { + priv = usb_get_serial_port_data(serial->port[i]); + kfree(priv); + } +} + +static struct usb_driver f81232_driver = { + .name = "f81232", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, + .no_dynamic_id = 1, + .supports_autosuspend = 1, +}; + +static struct usb_serial_driver f81232_device = { + .driver = { + .owner = THIS_MODULE, + .name = "f81232", + }, + .id_table = id_table, + .usb_driver = &f81232_driver, + .num_ports = 1, + .bulk_in_size = 256, + .bulk_out_size = 256, + .open = f81232_open, + .close = f81232_close, + .dtr_rts = f81232_dtr_rts, + .carrier_raised = f81232_carrier_raised, + .ioctl = f81232_ioctl, + .break_ctl = f81232_break_ctl, + .set_termios = f81232_set_termios, + .tiocmget = f81232_tiocmget, + .tiocmset = f81232_tiocmset, + .process_read_urb = f81232_process_read_urb, + .read_int_callback = f81232_read_int_callback, + .attach = f81232_startup, + .release = f81232_release, +}; + +static struct usb_serial_driver * const serial_drivers[] = { + &f81232_device, + NULL, +}; + +module_usb_serial_driver(f81232_driver, serial_drivers); + +MODULE_DESCRIPTION("Fintek F81232 USB to serial adaptor driver"); +MODULE_AUTHOR("Greg Kroah-Hartman Date: Wed, 29 Feb 2012 16:49:21 -0800 Subject: [PATCH 218/269] Revert "powerpc/usb: fix usb CTRL_PHY_CLK_VALID breaks on some platform" This reverts commit 79857e8e7b1ba740f8025b540f1e171c9a0a5d31. To quote Shengzhou Liu: I'm sorry, please don't apply this patch. It appears not only on P1022 platform. There will be more breaks on other platforms regarding CTRL_PHY_CLK_VALID bit. I will post a new patch with well compatibility on all platforms as soon as I get necessary confirmations. Cc: Shengzhou Liu Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-fsl.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index e9d8a0cca47b..7a15c2235758 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -248,11 +248,7 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) struct usb_hcd *hcd = ehci_to_hcd(ehci); struct fsl_usb2_platform_data *pdata; void __iomem *non_ehci = hcd->regs; - u32 temp, chip, rev, svr; - - svr = mfspr(SPRN_SVR); - chip = svr >> 16; - rev = (svr >> 4) & 0xf; + u32 temp; pdata = hcd->self.controller->platform_data; @@ -278,6 +274,12 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); if (pdata->operating_mode == FSL_USB2_MPH_HOST) { + unsigned int chip, rev, svr; + + svr = mfspr(SPRN_SVR); + chip = svr >> 16; + rev = (svr >> 4) & 0xf; + /* Deal with USB Erratum #14 on MPC834x Rev 1.0 & 1.1 chips */ if ((rev == 1) && (chip >= 0x8050) && (chip <= 0x8055)) ehci->has_fsl_port_bug = 1; @@ -299,15 +301,9 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); } - /* There is no CTRL_PHY_CLK_VALID bit on some platforms, e.g. P1022 */ -#define SVR_P1022_N_ID 0x80E6 -#define SVR_P1022_S_ID 0x80EE - if (chip != SVR_P1022_N_ID && chip != SVR_P1022_S_ID) { - if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & - CTRL_PHY_CLK_VALID)) { - printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n"); - return -ENODEV; - } + if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & CTRL_PHY_CLK_VALID)) { + printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n"); + return -ENODEV; } return 0; } From 7204cf584836c24b4b06e4ad4a8e6bb8ea84908e Mon Sep 17 00:00:00 2001 From: Daniele Palmas Date: Wed, 29 Feb 2012 15:32:05 +0100 Subject: [PATCH 219/269] USB: option driver: adding support for Telit CC864-SINGLE, CC864-DUAL and DE910-DUAL modems Adding PID for Telit CC864-SINGLE, CC864-DUAL and DE910-DUAL modems Signed-off-by: Daniele Palmas Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 005511b2ee08..f9b11fb8e25c 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -307,6 +307,9 @@ static void option_instat_callback(struct urb *urb); #define TELIT_VENDOR_ID 0x1bc7 #define TELIT_PRODUCT_UC864E 0x1003 #define TELIT_PRODUCT_UC864G 0x1004 +#define TELIT_PRODUCT_CC864_DUAL 0x1005 +#define TELIT_PRODUCT_CC864_SINGLE 0x1006 +#define TELIT_PRODUCT_DE910_DUAL 0x1010 /* ZTE PRODUCTS */ #define ZTE_VENDOR_ID 0x19d2 @@ -771,6 +774,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, From 444aa7fa9bd752d19ce472d3e02558b987c3cc67 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Wed, 29 Feb 2012 10:05:37 +0100 Subject: [PATCH 220/269] USB: ftdi_sio: add support for BeagleBone rev A5+ BeagleBone changed to the default FTDI 0403:6010 id in rev A5 to make life easier for Windows users, so we need a similar workaround as the Calao board to support it. Signed-off-by: Peter Korsgaard Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 989262606684..b160c252bf13 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1769,8 +1769,8 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial) dbg("%s", __func__); - if ((udev->manufacturer) && - (strcmp(udev->manufacturer, "CALAO Systems") == 0)) + if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) || + (udev->product && !strcmp(udev->product, "BeagleBone/XDS100"))) return ftdi_jtag_probe(serial); return 0; From cd70469d084fde198dc07c1a31b8463562228a5a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 29 Feb 2012 16:46:23 +0200 Subject: [PATCH 221/269] usb: core: hcd: make hcd->irq unsigned There's really no point in having hcd->irq as a signed integer when we consider the fact that IRQ 0 means NO_IRQ. In order to avoid confusion, make hcd->irq unsigned and fix users who were passing -1 as the IRQ number to usb_add_hcd. Tested-by: Kuninori Morimoto Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 6 +++--- drivers/usb/host/ohci-hcd.c | 2 +- drivers/usb/host/xhci-ring.c | 2 +- drivers/usb/host/xhci.c | 8 ++++---- drivers/usb/musb/musb_core.c | 2 +- drivers/usb/musb/musb_gadget.c | 2 +- include/linux/usb/hcd.h | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index e1282328fc27..9d7fc9a39933 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2352,7 +2352,7 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd, "io mem" : "io base", (unsigned long long)hcd->rsrc_start); } else { - hcd->irq = -1; + hcd->irq = 0; if (hcd->rsrc_start) dev_info(hcd->self.controller, "%s 0x%08llx\n", (hcd->driver->flags & HCD_MEMORY) ? @@ -2508,7 +2508,7 @@ err_register_root_hub: clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); del_timer_sync(&hcd->rh_timer); err_hcd_driver_start: - if (usb_hcd_is_primary_hcd(hcd) && hcd->irq >= 0) + if (usb_hcd_is_primary_hcd(hcd) && hcd->irq > 0) free_irq(irqnum, hcd); err_request_irq: err_hcd_driver_setup: @@ -2573,7 +2573,7 @@ void usb_remove_hcd(struct usb_hcd *hcd) del_timer_sync(&hcd->rh_timer); if (usb_hcd_is_primary_hcd(hcd)) { - if (hcd->irq >= 0) + if (hcd->irq > 0) free_irq(hcd->irq, hcd); } diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 34b9edd86651..831fa40c609a 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -899,7 +899,7 @@ static void ohci_stop (struct usb_hcd *hcd) ohci_usb_reset (ohci); ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); free_irq(hcd->irq, hcd); - hcd->irq = -1; + hcd->irq = 0; if (quirk_zfmicro(ohci)) del_timer(&ohci->unlink_watchdog); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 3a033240ec64..9e71f7c46a85 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2396,7 +2396,7 @@ hw_died: /* FIXME when MSI-X is supported and there are multiple vectors */ /* Clear the MSI-X event interrupt status */ - if (hcd->irq != -1) { + if (hcd->irq) { u32 irq_pending; /* Acknowledge the PCI interrupt */ irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index c939f5fdef9e..a629ad860329 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -224,13 +224,13 @@ static void xhci_free_irq(struct xhci_hcd *xhci) int ret; /* return if using legacy interrupt */ - if (xhci_to_hcd(xhci)->irq >= 0) + if (xhci_to_hcd(xhci)->irq > 0) return; ret = xhci_free_msi(xhci); if (!ret) return; - if (pdev->irq >= 0) + if (pdev->irq > 0) free_irq(pdev->irq, xhci_to_hcd(xhci)); return; @@ -341,7 +341,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd) /* unregister the legacy interrupt */ if (hcd->irq) free_irq(hcd->irq, hcd); - hcd->irq = -1; + hcd->irq = 0; ret = xhci_setup_msix(xhci); if (ret) @@ -349,7 +349,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd) ret = xhci_setup_msi(xhci); if (!ret) - /* hcd->irq is -1, we have MSI */ + /* hcd->irq is 0, we have MSI */ return 0; if (!pdev->irq) { diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index b527e9e6dbac..0f8b82918a40 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1987,7 +1987,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb->xceiv->otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_IDLE; - status = usb_add_hcd(musb_to_hcd(musb), -1, 0); + status = usb_add_hcd(musb_to_hcd(musb), 0, 0); hcd->self.uses_pio_for_control = 1; dev_dbg(musb->controller, "%s mode, status %d, devctl %02x %c\n", diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index a495a3079c07..f42c29b11f71 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1957,7 +1957,7 @@ static int musb_gadget_start(struct usb_gadget *g, * handles power budgeting ... this way also * ensures HdrcStart is indirectly called. */ - retval = usb_add_hcd(musb_to_hcd(musb), -1, 0); + retval = usb_add_hcd(musb_to_hcd(musb), 0, 0); if (retval < 0) { dev_dbg(musb->controller, "add_hcd failed, %d\n", retval); goto err2; diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 2e6071efbfb7..5de415707c23 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -127,7 +127,7 @@ struct usb_hcd { unsigned authorized_default:1; unsigned has_tt:1; /* Integrated TT in root hub */ - int irq; /* irq allocated */ + unsigned int irq; /* irq allocated */ void __iomem *regs; /* device memory/io */ u64 rsrc_start; /* memory/io resource start */ u64 rsrc_len; /* memory/io resource length */ From d28a9689c93195d39f91f35a9519876688605b65 Mon Sep 17 00:00:00 2001 From: Anton Tikhomirov Date: Wed, 15 Feb 2012 17:04:56 +0900 Subject: [PATCH 222/269] usb: dwc3: Add Exynos Specific Glue layer Adds Exynos Specific Glue layer to support USB peripherals on Samsung Exynos5 chips. [ balbi@ti.com : prevent compilation of Exynos glue layer on platforms which don't provide clk API implementation ] Signed-off-by: Anton Tikhomirov Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/Makefile | 13 ++ drivers/usb/dwc3/dwc3-exynos.c | 151 ++++++++++++++++++++++ include/linux/platform_data/dwc3-exynos.h | 24 ++++ 3 files changed, 188 insertions(+) create mode 100644 drivers/usb/dwc3/dwc3-exynos.c create mode 100644 include/linux/platform_data/dwc3-exynos.h diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 900ae74357f1..d441fe4c180b 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -28,6 +28,19 @@ endif obj-$(CONFIG_USB_DWC3) += dwc3-omap.o +## +# REVISIT Samsung Exynos platform needs the clk API which isn't +# defined on all architectures. If we allow dwc3-exynos.c compile +# always we will fail the linking phase on those architectures +# which don't provide clk api implementation and that's unnaceptable. +# +# When Samsung's platform start supporting pm_runtime, this check +# for HAVE_CLK should be removed. +## +ifneq ($(CONFIG_HAVE_CLK),) + obj-$(CONFIG_USB_DWC3) += dwc3-exynos.o +endif + ifneq ($(CONFIG_PCI),) obj-$(CONFIG_USB_DWC3) += dwc3-pci.o endif diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c new file mode 100644 index 000000000000..d19030198086 --- /dev/null +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -0,0 +1,151 @@ +/** + * dwc3-exynos.c - Samsung EXYNOS DWC3 Specific Glue layer + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Author: Anton Tikhomirov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core.h" + +struct dwc3_exynos { + struct platform_device *dwc3; + struct device *dev; + + struct clk *clk; +}; + +static int __devinit dwc3_exynos_probe(struct platform_device *pdev) +{ + struct dwc3_exynos_data *pdata = pdev->dev.platform_data; + struct platform_device *dwc3; + struct dwc3_exynos *exynos; + struct clk *clk; + + int devid; + int ret = -ENOMEM; + + exynos = kzalloc(sizeof(*exynos), GFP_KERNEL); + if (!exynos) { + dev_err(&pdev->dev, "not enough memory\n"); + goto err0; + } + + platform_set_drvdata(pdev, exynos); + + devid = dwc3_get_device_id(); + if (devid < 0) + goto err1; + + dwc3 = platform_device_alloc("dwc3", devid); + if (!dwc3) { + dev_err(&pdev->dev, "couldn't allocate dwc3 device\n"); + goto err2; + } + + clk = clk_get(&pdev->dev, "usbdrd30"); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "couldn't get clock\n"); + ret = -EINVAL; + goto err3; + } + + dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask); + + dwc3->dev.parent = &pdev->dev; + dwc3->dev.dma_mask = pdev->dev.dma_mask; + dwc3->dev.dma_parms = pdev->dev.dma_parms; + exynos->dwc3 = dwc3; + exynos->dev = &pdev->dev; + exynos->clk = clk; + + clk_enable(exynos->clk); + + /* PHY initialization */ + if (!pdata) { + dev_dbg(&pdev->dev, "missing platform data\n"); + } else { + if (pdata->phy_init) + pdata->phy_init(pdev, pdata->phy_type); + } + + ret = platform_device_add_resources(dwc3, pdev->resource, + pdev->num_resources); + if (ret) { + dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n"); + goto err4; + } + + ret = platform_device_add(dwc3); + if (ret) { + dev_err(&pdev->dev, "failed to register dwc3 device\n"); + goto err4; + } + + return 0; + +err4: + if (pdata && pdata->phy_exit) + pdata->phy_exit(pdev, pdata->phy_type); + + clk_disable(clk); + clk_put(clk); +err3: + platform_device_put(dwc3); +err2: + dwc3_put_device_id(devid); +err1: + kfree(exynos); +err0: + return ret; +} + +static int __devexit dwc3_exynos_remove(struct platform_device *pdev) +{ + struct dwc3_exynos *exynos = platform_get_drvdata(pdev); + struct dwc3_exynos_data *pdata = pdev->dev.platform_data; + + platform_device_unregister(exynos->dwc3); + + dwc3_put_device_id(exynos->dwc3->id); + + if (pdata && pdata->phy_exit) + pdata->phy_exit(pdev, pdata->phy_type); + + clk_disable(exynos->clk); + clk_put(exynos->clk); + + kfree(exynos); + + return 0; +} + +static struct platform_driver dwc3_exynos_driver = { + .probe = dwc3_exynos_probe, + .remove = __devexit_p(dwc3_exynos_remove), + .driver = { + .name = "exynos-dwc3", + }, +}; + +module_platform_driver(dwc3_exynos_driver); + +MODULE_ALIAS("platform:exynos-dwc3"); +MODULE_AUTHOR("Anton Tikhomirov "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("DesignWare USB3 EXYNOS Glue Layer"); diff --git a/include/linux/platform_data/dwc3-exynos.h b/include/linux/platform_data/dwc3-exynos.h new file mode 100644 index 000000000000..5eb7da9b3772 --- /dev/null +++ b/include/linux/platform_data/dwc3-exynos.h @@ -0,0 +1,24 @@ +/** + * dwc3-exynos.h - Samsung EXYNOS DWC3 Specific Glue layer, header. + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Author: Anton Tikhomirov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _DWC3_EXYNOS_H_ +#define _DWC3_EXYNOS_H_ + +struct dwc3_exynos_data { + int phy_type; + int (*phy_init)(struct platform_device *pdev, int type); + int (*phy_exit)(struct platform_device *pdev, int type); +}; + +#endif /* _DWC3_EXYNOS_H_ */ From 802ca85067e11cdeddeb34ef53de03e5a7d509da Mon Sep 17 00:00:00 2001 From: Chanho Park Date: Wed, 15 Feb 2012 18:27:55 +0900 Subject: [PATCH 223/269] usb: dwc3: use devm_xxx functions This patch enables to use devm_xxx functions during probing driver. The devm_xxx series functions are able to release resource when the driver is detatched. We can remove several codes to release resources in the probe function. Signed-off-by: Chanho Park Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 84 +++++++++++++++-------------------- drivers/usb/dwc3/dwc3-omap.c | 85 ++++++++++++++---------------------- drivers/usb/dwc3/dwc3-pci.c | 46 +++++++++---------- 3 files changed, 90 insertions(+), 125 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index d119a1fbf946..c181f3e84cfa 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -408,6 +408,7 @@ static int __devinit dwc3_probe(struct platform_device *pdev) struct device_node *node = pdev->dev.of_node; struct resource *res; struct dwc3 *dwc; + struct device *dev = &pdev->dev; int ret = -ENOMEM; int irq; @@ -417,39 +418,39 @@ static int __devinit dwc3_probe(struct platform_device *pdev) u8 mode; - mem = kzalloc(sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); + mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); if (!mem) { - dev_err(&pdev->dev, "not enough memory\n"); - goto err0; + dev_err(dev, "not enough memory\n"); + return -ENOMEM; } dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); dwc->mem = mem; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { - dev_err(&pdev->dev, "missing resource\n"); - goto err1; + dev_err(dev, "missing resource\n"); + return -ENODEV; } dwc->res = res; - res = request_mem_region(res->start, resource_size(res), - dev_name(&pdev->dev)); + res = devm_request_mem_region(dev, res->start, resource_size(res), + dev_name(dev)); if (!res) { - dev_err(&pdev->dev, "can't request mem region\n"); - goto err1; + dev_err(dev, "can't request mem region\n"); + return -ENOMEM; } - regs = ioremap(res->start, resource_size(res)); + regs = devm_ioremap(dev, res->start, resource_size(res)); if (!regs) { - dev_err(&pdev->dev, "ioremap failed\n"); - goto err2; + dev_err(dev, "ioremap failed\n"); + return -ENOMEM; } irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "missing IRQ\n"); - goto err3; + dev_err(dev, "missing IRQ\n"); + return -ENODEV; } spin_lock_init(&dwc->lock); @@ -457,7 +458,7 @@ static int __devinit dwc3_probe(struct platform_device *pdev) dwc->regs = regs; dwc->regs_size = resource_size(res); - dwc->dev = &pdev->dev; + dwc->dev = dev; dwc->irq = irq; if (!strncmp("super", maximum_speed, 5)) @@ -474,14 +475,14 @@ static int __devinit dwc3_probe(struct platform_device *pdev) if (of_get_property(node, "tx-fifo-resize", NULL)) dwc->needs_fifo_resize = true; - pm_runtime_enable(&pdev->dev); - pm_runtime_get_sync(&pdev->dev); - pm_runtime_forbid(&pdev->dev); + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + pm_runtime_forbid(dev); ret = dwc3_core_init(dwc); if (ret) { - dev_err(&pdev->dev, "failed to initialize core\n"); - goto err3; + dev_err(dev, "failed to initialize core\n"); + return ret; } mode = DWC3_MODE(dwc->hwparams.hwparams0); @@ -491,49 +492,49 @@ static int __devinit dwc3_probe(struct platform_device *pdev) dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); ret = dwc3_gadget_init(dwc); if (ret) { - dev_err(&pdev->dev, "failed to initialize gadget\n"); - goto err4; + dev_err(dev, "failed to initialize gadget\n"); + goto err1; } break; case DWC3_MODE_HOST: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); ret = dwc3_host_init(dwc); if (ret) { - dev_err(&pdev->dev, "failed to initialize host\n"); - goto err4; + dev_err(dev, "failed to initialize host\n"); + goto err1; } break; case DWC3_MODE_DRD: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); ret = dwc3_host_init(dwc); if (ret) { - dev_err(&pdev->dev, "failed to initialize host\n"); - goto err4; + dev_err(dev, "failed to initialize host\n"); + goto err1; } ret = dwc3_gadget_init(dwc); if (ret) { - dev_err(&pdev->dev, "failed to initialize gadget\n"); - goto err4; + dev_err(dev, "failed to initialize gadget\n"); + goto err1; } break; default: - dev_err(&pdev->dev, "Unsupported mode of operation %d\n", mode); - goto err4; + dev_err(dev, "Unsupported mode of operation %d\n", mode); + goto err1; } dwc->mode = mode; ret = dwc3_debugfs_init(dwc); if (ret) { - dev_err(&pdev->dev, "failed to initialize debugfs\n"); - goto err5; + dev_err(dev, "failed to initialize debugfs\n"); + goto err2; } - pm_runtime_allow(&pdev->dev); + pm_runtime_allow(dev); return 0; -err5: +err2: switch (mode) { case DWC3_MODE_DEVICE: dwc3_gadget_exit(dwc); @@ -550,19 +551,9 @@ err5: break; } -err4: +err1: dwc3_core_exit(dwc); -err3: - iounmap(regs); - -err2: - release_mem_region(res->start, resource_size(res)); - -err1: - kfree(dwc->mem); - -err0: return ret; } @@ -595,9 +586,6 @@ static int __devexit dwc3_remove(struct platform_device *pdev) } dwc3_core_exit(dwc); - release_mem_region(res->start, resource_size(res)); - iounmap(dwc->regs); - kfree(dwc->mem); return 0; } diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 64e29c31df22..f2e6b050dab3 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -203,6 +203,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) struct platform_device *dwc3; struct dwc3_omap *omap; struct resource *res; + struct device *dev = &pdev->dev; int devid; int size; @@ -215,59 +216,57 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) void __iomem *base; void *context; - omap = kzalloc(sizeof(*omap), GFP_KERNEL); + omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL); if (!omap) { - dev_err(&pdev->dev, "not enough memory\n"); - goto err0; + dev_err(dev, "not enough memory\n"); + return -ENOMEM; } platform_set_drvdata(pdev, omap); irq = platform_get_irq(pdev, 1); if (irq < 0) { - dev_err(&pdev->dev, "missing IRQ resource\n"); - ret = -EINVAL; - goto err1; + dev_err(dev, "missing IRQ resource\n"); + return -EINVAL; } res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res) { - dev_err(&pdev->dev, "missing memory base resource\n"); - ret = -EINVAL; - goto err1; + dev_err(dev, "missing memory base resource\n"); + return -EINVAL; } - base = ioremap_nocache(res->start, resource_size(res)); + base = devm_ioremap_nocache(dev, res->start, resource_size(res)); if (!base) { - dev_err(&pdev->dev, "ioremap failed\n"); - goto err1; + dev_err(dev, "ioremap failed\n"); + return -ENOMEM; } devid = dwc3_get_device_id(); if (devid < 0) - goto err2; + return -ENODEV; dwc3 = platform_device_alloc("dwc3", devid); if (!dwc3) { - dev_err(&pdev->dev, "couldn't allocate dwc3 device\n"); - goto err3; + dev_err(dev, "couldn't allocate dwc3 device\n"); + goto err1; } - context = kzalloc(resource_size(res), GFP_KERNEL); + context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL); if (!context) { - dev_err(&pdev->dev, "couldn't allocate dwc3 context memory\n"); - goto err4; + dev_err(dev, "couldn't allocate dwc3 context memory\n"); + goto err2; } spin_lock_init(&omap->lock); - dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask); + dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask); - dwc3->dev.parent = &pdev->dev; - dwc3->dev.dma_mask = pdev->dev.dma_mask; - dwc3->dev.dma_parms = pdev->dev.dma_parms; + dwc3->dev.parent = dev; + dwc3->dev.dma_mask = dev->dma_mask; + dwc3->dev.dma_parms = dev->dma_parms; omap->resource_size = resource_size(res); omap->context = context; - omap->dev = &pdev->dev; + omap->dev = dev; omap->irq = irq; omap->base = base; omap->dwc3 = dwc3; @@ -279,7 +278,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) reg |= *utmi_mode; } else { if (!pdata) { - dev_dbg(&pdev->dev, "missing platform data\n"); + dev_dbg(dev, "missing platform data\n"); } else { switch (pdata->utmi_mode) { case DWC3_OMAP_UTMI_MODE_SW: @@ -289,7 +288,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; break; default: - dev_dbg(&pdev->dev, "UNKNOWN utmi mode %d\n", + dev_dbg(dev, "UNKNOWN utmi mode %d\n", pdata->utmi_mode); } } @@ -310,12 +309,12 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) dwc3_writel(omap->base, USBOTGSS_SYSCONFIG, reg); - ret = request_irq(omap->irq, dwc3_omap_interrupt, 0, + ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0, "dwc3-omap", omap); if (ret) { - dev_err(&pdev->dev, "failed to request IRQ #%d --> %d\n", + dev_err(dev, "failed to request IRQ #%d --> %d\n", omap->irq, ret); - goto err5; + goto err2; } /* enable all IRQs */ @@ -337,37 +336,24 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) ret = platform_device_add_resources(dwc3, pdev->resource, pdev->num_resources); if (ret) { - dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n"); - goto err6; + dev_err(dev, "couldn't add resources to dwc3 device\n"); + goto err2; } ret = platform_device_add(dwc3); if (ret) { - dev_err(&pdev->dev, "failed to register dwc3 device\n"); - goto err6; + dev_err(dev, "failed to register dwc3 device\n"); + goto err2; } return 0; -err6: - free_irq(omap->irq, omap); - -err5: - kfree(omap->context); - -err4: +err2: platform_device_put(dwc3); -err3: +err1: dwc3_put_device_id(devid); -err2: - iounmap(base); - -err1: - kfree(omap); - -err0: return ret; } @@ -378,11 +364,6 @@ static int __devexit dwc3_omap_remove(struct platform_device *pdev) platform_device_unregister(omap->dwc3); dwc3_put_device_id(omap->dwc3->id); - free_irq(omap->irq, omap); - iounmap(omap->base); - - kfree(omap->context); - kfree(omap); return 0; } diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 64e1f7c67b08..05d3a3efbc15 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -61,19 +61,20 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci, struct dwc3_pci *glue; int ret = -ENOMEM; int devid; + struct device *dev = &pci->dev; - glue = kzalloc(sizeof(*glue), GFP_KERNEL); + glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL); if (!glue) { - dev_err(&pci->dev, "not enough memory\n"); - goto err0; + dev_err(dev, "not enough memory\n"); + return -ENOMEM; } - glue->dev = &pci->dev; + glue->dev = dev; ret = pci_enable_device(pci); if (ret) { - dev_err(&pci->dev, "failed to enable pci device\n"); - goto err1; + dev_err(dev, "failed to enable pci device\n"); + return -ENODEV; } pci_set_power_state(pci, PCI_D0); @@ -81,12 +82,12 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci, devid = dwc3_get_device_id(); if (devid < 0) - goto err2; + goto err1; dwc3 = platform_device_alloc("dwc3", devid); if (!dwc3) { - dev_err(&pci->dev, "couldn't allocate dwc3 device\n"); - goto err3; + dev_err(dev, "couldn't allocate dwc3 device\n"); + goto err1; } memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); @@ -102,41 +103,37 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci, ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res)); if (ret) { - dev_err(&pci->dev, "couldn't add resources to dwc3 device\n"); - goto err4; + dev_err(dev, "couldn't add resources to dwc3 device\n"); + goto err2; } pci_set_drvdata(pci, glue); - dma_set_coherent_mask(&dwc3->dev, pci->dev.coherent_dma_mask); + dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask); - dwc3->dev.dma_mask = pci->dev.dma_mask; - dwc3->dev.dma_parms = pci->dev.dma_parms; - dwc3->dev.parent = &pci->dev; + dwc3->dev.dma_mask = dev->dma_mask; + dwc3->dev.dma_parms = dev->dma_parms; + dwc3->dev.parent = dev; glue->dwc3 = dwc3; ret = platform_device_add(dwc3); if (ret) { - dev_err(&pci->dev, "failed to register dwc3 device\n"); - goto err4; + dev_err(dev, "failed to register dwc3 device\n"); + goto err3; } return 0; -err4: +err3: pci_set_drvdata(pci, NULL); platform_device_put(dwc3); -err3: +err2: dwc3_put_device_id(devid); -err2: +err1: pci_disable_device(pci); -err1: - kfree(glue); - -err0: return ret; } @@ -148,7 +145,6 @@ static void __devexit dwc3_pci_remove(struct pci_dev *pci) platform_device_unregister(glue->dwc3); pci_set_drvdata(pci, NULL); pci_disable_device(pci); - kfree(glue); } static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = { From 2cd0e8512169b125fb0ff1f9ec3f8505eecb3012 Mon Sep 17 00:00:00 2001 From: Danny Kukawka Date: Wed, 15 Feb 2012 18:55:51 +0100 Subject: [PATCH 224/269] usb: dwc3: linux/module.h included twice drivers/usb/dwc3/core.c and drivers/usb/dwc3/dwc3-omap.c included 'linux/module.h' twice, remove the duplicates. Signed-off-by: Danny Kukawka Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 1 - drivers/usb/dwc3/dwc3-omap.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c181f3e84cfa..a1576f00ead7 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -52,7 +52,6 @@ #include #include -#include #include "core.h" #include "gadget.h" diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index f2e6b050dab3..d7d9c0ec9515 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -47,7 +47,6 @@ #include #include #include -#include #include "core.h" #include "io.h" From 1d046793958f128dd43d42a4a0dac48bf6914273 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Wed, 15 Feb 2012 18:56:56 -0800 Subject: [PATCH 225/269] usb: dwc3: clean up whitespace damage, typos, missing parens, etc. trivial patch, no functional changes Signed-off-by: Paul Zimmerman Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 14 +++++----- drivers/usb/dwc3/core.h | 22 ++++++++-------- drivers/usb/dwc3/dwc3-pci.c | 4 +-- drivers/usb/dwc3/ep0.c | 2 +- drivers/usb/dwc3/gadget.c | 51 ++++++++++++++++++------------------- 5 files changed, 46 insertions(+), 47 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index a1576f00ead7..33d986832013 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -167,11 +167,11 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc, } /** - * dwc3_alloc_one_event_buffer - Allocated one event buffer structure + * dwc3_alloc_one_event_buffer - Allocates one event buffer structure * @dwc: Pointer to our controller context structure * @length: size of the event buffer * - * Returns a pointer to the allocated event buffer structure on succes + * Returns a pointer to the allocated event buffer structure on success * otherwise ERR_PTR(errno). */ static struct dwc3_event_buffer *__devinit @@ -215,10 +215,10 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc) /** * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length - * @dwc: Pointer to out controller context structure + * @dwc: pointer to our controller context structure * @length: size of event buffer * - * Returns 0 on success otherwise negative errno. In error the case, dwc + * Returns 0 on success otherwise negative errno. In the error case, dwc * may contain some buffers allocated but not all which were requested. */ static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) @@ -251,7 +251,7 @@ static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) /** * dwc3_event_buffers_setup - setup our allocated event buffers - * @dwc: Pointer to out controller context structure + * @dwc: pointer to our controller context structure * * Returns 0 on success otherwise negative errno. */ @@ -363,9 +363,9 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc) /* * WORKAROUND: DWC3 revisions <1.90a have a bug - * when The device fails to connect at SuperSpeed + * where the device can fail to connect at SuperSpeed * and falls back to high-speed mode which causes - * the device to enter in a Connect/Disconnect loop + * the device to enter a Connect/Disconnect loop */ if (dwc->revision < DWC3_REVISION_190A) reg |= DWC3_GCTL_U2RSTECN; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 696b20a8b1fa..81d1c0aeb6c5 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -145,22 +145,22 @@ /* Bit fields */ /* Global Configuration Register */ -#define DWC3_GCTL_PWRDNSCALE(n) (n << 19) +#define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19) #define DWC3_GCTL_U2RSTECN (1 << 16) -#define DWC3_GCTL_RAMCLKSEL(x) ((x & DWC3_GCTL_CLK_MASK) << 6) +#define DWC3_GCTL_RAMCLKSEL(x) (((x) & DWC3_GCTL_CLK_MASK) << 6) #define DWC3_GCTL_CLK_BUS (0) #define DWC3_GCTL_CLK_PIPE (1) #define DWC3_GCTL_CLK_PIPEHALF (2) #define DWC3_GCTL_CLK_MASK (3) #define DWC3_GCTL_PRTCAP(n) (((n) & (3 << 12)) >> 12) -#define DWC3_GCTL_PRTCAPDIR(n) (n << 12) +#define DWC3_GCTL_PRTCAPDIR(n) ((n) << 12) #define DWC3_GCTL_PRTCAP_HOST 1 #define DWC3_GCTL_PRTCAP_DEVICE 2 #define DWC3_GCTL_PRTCAP_OTG 3 #define DWC3_GCTL_CORESOFTRESET (1 << 11) -#define DWC3_GCTL_SCALEDOWN(n) (n << 4) +#define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) #define DWC3_GCTL_DISSCRAMBLE (1 << 3) #define DWC3_GCTL_DSBLCLKGTNG (1 << 0) @@ -177,7 +177,7 @@ #define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000) /* Global HWPARAMS1 Register */ -#define DWC3_GHWPARAMS1_EN_PWROPT(n) ((n & (3 << 24)) >> 24) +#define DWC3_GHWPARAMS1_EN_PWROPT(n) (((n) & (3 << 24)) >> 24) #define DWC3_GHWPARAMS1_EN_PWROPT_NO 0 #define DWC3_GHWPARAMS1_EN_PWROPT_CLK 1 @@ -273,10 +273,10 @@ /* Device Endpoint Command Register */ #define DWC3_DEPCMD_PARAM_SHIFT 16 -#define DWC3_DEPCMD_PARAM(x) (x << DWC3_DEPCMD_PARAM_SHIFT) -#define DWC3_DEPCMD_GET_RSC_IDX(x) ((x >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f) +#define DWC3_DEPCMD_PARAM(x) ((x) << DWC3_DEPCMD_PARAM_SHIFT) +#define DWC3_DEPCMD_GET_RSC_IDX(x) (((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f) #define DWC3_DEPCMD_STATUS_MASK (0x0f << 12) -#define DWC3_DEPCMD_STATUS(x) ((x & DWC3_DEPCMD_STATUS_MASK) >> 12) +#define DWC3_DEPCMD_STATUS(x) (((x) & DWC3_DEPCMD_STATUS_MASK) >> 12) #define DWC3_DEPCMD_HIPRI_FORCERM (1 << 11) #define DWC3_DEPCMD_CMDACT (1 << 10) #define DWC3_DEPCMD_CMDIOC (1 << 8) @@ -683,9 +683,9 @@ struct dwc3_event_depevt { #define DEPEVT_STATUS_TRANSFER_ACTIVE (1 << 3) /* Within XferComplete */ -#define DEPEVT_STATUS_BUSERR (1 << 0) -#define DEPEVT_STATUS_SHORT (1 << 1) -#define DEPEVT_STATUS_IOC (1 << 2) +#define DEPEVT_STATUS_BUSERR (1 << 0) +#define DEPEVT_STATUS_SHORT (1 << 1) +#define DEPEVT_STATUS_IOC (1 << 2) #define DEPEVT_STATUS_LST (1 << 3) /* Stream event only */ diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 05d3a3efbc15..74bac06652c4 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -69,7 +69,7 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci, return -ENOMEM; } - glue->dev = dev; + glue->dev = dev; ret = pci_enable_device(pci); if (ret) { @@ -114,7 +114,7 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci, dwc3->dev.dma_mask = dev->dma_mask; dwc3->dev.dma_parms = dev->dma_parms; dwc3->dev.parent = dev; - glue->dwc3 = dwc3; + glue->dwc3 = dwc3; ret = platform_device_add(dwc3); if (ret) { diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 5a067090f27e..4fa2c9873eab 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -374,7 +374,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, case USB_RECIP_ENDPOINT: switch (wValue) { case USB_ENDPOINT_HALT: - dep = dwc3_wIndex_to_dep(dwc, wIndex); + dep = dwc3_wIndex_to_dep(dwc, wIndex); if (!dep) return -EINVAL; ret = __dwc3_gadget_ep_set_halt(dep, set); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index eeba2227c28f..d121e73d89ae 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -548,7 +548,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, memset(&trb_link, 0, sizeof(trb_link)); - /* Link TRB for ISOC. The HWO but is never reset */ + /* Link TRB for ISOC. The HWO bit is never reset */ trb_st_hw = &dep->trb_pool[0]; trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1]; @@ -818,9 +818,9 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, * @dep: endpoint for which requests are being prepared * @starting: true if the endpoint is idle and no requests are queued. * - * The functions goes through the requests list and setups TRBs for the - * transfers. The functions returns once there are not more TRBs available or - * it run out of requests. + * The function goes through the requests list and sets up TRBs for the + * transfers. The function returns once there are no more TRBs available or + * it runs out of requests. */ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) { @@ -834,8 +834,8 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; /* - * if busy & slot are equal than it is either full or empty. If we are - * starting to proceed requests then we are empty. Otherwise we ar + * If busy & slot are equal than it is either full or empty. If we are + * starting to process requests then we are empty. Otherwise we are * full and don't do anything */ if (!trbs_left) { @@ -846,7 +846,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) * In case we start from scratch, we queue the ISOC requests * starting from slot 1. This is done because we use ring * buffer and have no LST bit to stop us. Instead, we place - * IOC bit TRB_NUM/4. We try to avoid to having an interrupt + * IOC bit every TRB_NUM/4. We try to avoid having an interrupt * after the first request so we start at slot 1 and have * 7 requests proceed before we hit the first IOC. * Other transfer types don't use the ring buffer and are @@ -882,8 +882,8 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) length = sg_dma_len(s); dma = sg_dma_address(s); - if (i == (request->num_mapped_sgs - 1) - || sg_is_last(s)) { + if (i == (request->num_mapped_sgs - 1) || + sg_is_last(s)) { last_one = true; chain = false; } @@ -951,8 +951,7 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, dwc3_prepare_trbs(dep, start_new); /* - * req points to the first request where HWO changed - * from 0 to 1 + * req points to the first request where HWO changed from 0 to 1 */ req = next_request(&dep->req_queued); } @@ -978,7 +977,7 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, /* * FIXME we need to iterate over the list of requests * here and stop, unmap, free and del each of the linked - * requests instead of we do now. + * requests instead of what we do now. */ dwc3_unmap_buffer_from_dma(req); list_del(&req->list); @@ -1011,7 +1010,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) * particular token from the Host side. * * This will also avoid Host cancelling URBs due to too - * many NACKs. + * many NAKs. */ dwc3_map_buffer_to_dma(req); list_add_tail(&req->list, &dep->request_list); @@ -1034,10 +1033,10 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) start_trans = 1; if (usb_endpoint_xfer_isoc(dep->desc) && - dep->flags & DWC3_EP_BUSY) + (dep->flags & DWC3_EP_BUSY)) start_trans = 0; - ret = __dwc3_gadget_kick_transfer(dep, 0, start_trans); + ret = __dwc3_gadget_kick_transfer(dep, 0, start_trans); if (ret && ret != -EBUSY) { struct dwc3 *dwc = dep->dwc; @@ -1291,10 +1290,10 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g) reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; dwc3_writel(dwc->regs, DWC3_DCTL, reg); - /* pool until Link State change to ON */ + /* poll until Link State changes to ON */ timeout = jiffies + msecs_to_jiffies(100); - while (!(time_after(jiffies, timeout))) { + while (!time_after(jiffies, timeout)) { reg = dwc3_readl(dwc->regs, DWC3_DSTS); /* in HS, means ON */ @@ -1558,10 +1557,10 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) /* * We continue despite the error. There is not much we - * can do. If we don't clean in up we loop for ever. If - * we skip the TRB than it gets overwritten reused after - * a while since we use them in a ring buffer. a BUG() - * would help. Lets hope that if this occures, someone + * can do. If we don't clean it up we loop forever. If + * we skip the TRB then it gets overwritten after a + * while since we use them in a ring buffer. A BUG() + * would help. Lets hope that if this occurs, someone * fixes the root cause instead of looking away :) */ dev_err(dwc->dev, "%s's TRB (%p) still owned by HW\n", @@ -1614,7 +1613,7 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, if (event->status & DEPEVT_STATUS_BUSERR) status = -ECONNRESET; - clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status); + clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status); if (clean_busy) { dep->flags &= ~DWC3_EP_BUSY; dep->res_trans_idx = 0; @@ -1678,8 +1677,8 @@ static void dwc3_process_ep_cmd_complete(struct dwc3_ep *dep, struct dwc3_event_depevt mod_ev = *event; /* - * We were asked to remove one requests. It is possible that this - * request and a few other were started together and have the same + * We were asked to remove one request. It is possible that this + * request and a few others were started together and have the same * transfer index. Since we stopped the complete endpoint we don't * know how many requests were already completed (and not yet) * reported and how could be done (later). We purge them all until @@ -1688,7 +1687,7 @@ static void dwc3_process_ep_cmd_complete(struct dwc3_ep *dep, mod_ev.status = DEPEVT_STATUS_LST; dwc3_cleanup_done_reqs(dwc, dep, &mod_ev, -ESHUTDOWN); dep->flags &= ~DWC3_EP_BUSY; - /* pending requets are ignored and are queued on XferNotReady */ + /* pending requests are ignored and are queued on XferNotReady */ } static void dwc3_ep_cmd_compl(struct dwc3_ep *dep, @@ -2285,7 +2284,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc) /** * dwc3_gadget_init - Initializes gadget related registers - * @dwc: Pointer to out controller context structure + * @dwc: pointer to our controller context structure * * Returns 0 on success otherwise negative errno. */ From 075cd14d2a8d35afc39ad28fc7b968275881266b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 4 Feb 2012 16:37:14 +0300 Subject: [PATCH 226/269] usb: dwc3: make dwc3_get_device_id() return the id We always return zero instead of the id we found. Cc: stable@vger.kernel.org Signed-off-by: Dan Carpenter Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 33d986832013..3fd4e843139e 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -86,7 +86,7 @@ again: id = -ENOMEM; } - return 0; + return id; } EXPORT_SYMBOL_GPL(dwc3_get_device_id); From 8d62cd65d74d0e241b3a152f7347bb66126b705b Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Wed, 15 Feb 2012 13:35:06 +0200 Subject: [PATCH 227/269] usb: dwc3: gadget: don't wrap around the TRB poll on non-ISOC If we have a non-ISOC endpoint, we will not have a Link TRB pointing to the beginning of the TRB pool. On such endpoints, we don't want to let the driver wrap around the TRB pool otherwise controller will hang waiting for a valid TRB. Cc: stable@vger.kernel.org Signed-off-by: Paul Zimmerman Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index d121e73d89ae..48b2d0d14481 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -826,6 +826,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) { struct dwc3_request *req, *n; u32 trbs_left; + u32 max; unsigned int last_one = 0; BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); @@ -833,6 +834,13 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) /* the first request must not be queued */ trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; + /* Can't wrap around on a non-isoc EP since there's no link TRB */ + if (!usb_endpoint_xfer_isoc(dep->desc)) { + max = DWC3_TRB_NUM - (dep->free_slot & DWC3_TRB_MASK); + if (trbs_left > max) + trbs_left = max; + } + /* * If busy & slot are equal than it is either full or empty. If we are * starting to process requests then we are empty. Otherwise we are From 27a78d6a283d6782438f72306746afe4bf44c215 Mon Sep 17 00:00:00 2001 From: Anton Tikhomirov Date: Thu, 23 Feb 2012 15:38:46 +0900 Subject: [PATCH 228/269] usb: dwc3: use proper function for setting endpoint name It's wrong to use the size of array as an argument for strncat. Memory corruption is possible. strlcat is exactly what we need here. Cc: stable@vger.kernel.org Signed-off-by: Anton Tikhomirov Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 48b2d0d14481..60b75c302aa4 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -643,16 +643,16 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep, switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_CONTROL: - strncat(dep->name, "-control", sizeof(dep->name)); + strlcat(dep->name, "-control", sizeof(dep->name)); break; case USB_ENDPOINT_XFER_ISOC: - strncat(dep->name, "-isoc", sizeof(dep->name)); + strlcat(dep->name, "-isoc", sizeof(dep->name)); break; case USB_ENDPOINT_XFER_BULK: - strncat(dep->name, "-bulk", sizeof(dep->name)); + strlcat(dep->name, "-bulk", sizeof(dep->name)); break; case USB_ENDPOINT_XFER_INT: - strncat(dep->name, "-int", sizeof(dep->name)); + strlcat(dep->name, "-int", sizeof(dep->name)); break; default: dev_err(dwc->dev, "invalid endpoint transfer type\n"); From 9bafa56c7cee5c6fa68de5924220abb220c7e229 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 17 Feb 2012 14:10:16 -0800 Subject: [PATCH 229/269] usb: dwc3: fix bogus test in dwc3_gadget_start_isoc Zero is a valid value for a microframe number. So remove the bogus test for non-zero in dwc3_gadget_start_isoc(). Cc: stable@vger.kernel.org Signed-off-by: Paul Zimmerman Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 60b75c302aa4..fac11491850f 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1656,7 +1656,7 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, static void dwc3_gadget_start_isoc(struct dwc3 *dwc, struct dwc3_ep *dep, const struct dwc3_event_depevt *event) { - u32 uf; + u32 uf, mask; if (list_empty(&dep->request_list)) { dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n", @@ -1664,16 +1664,10 @@ static void dwc3_gadget_start_isoc(struct dwc3 *dwc, return; } - if (event->parameters) { - u32 mask; - - mask = ~(dep->interval - 1); - uf = event->parameters & mask; - /* 4 micro frames in the future */ - uf += dep->interval * 4; - } else { - uf = 0; - } + mask = ~(dep->interval - 1); + uf = event->parameters & mask; + /* 4 micro frames in the future */ + uf += dep->interval * 4; __dwc3_gadget_kick_transfer(dep, uf, 1); } From 3e87c42a29f14c7a346f912e084f6ab13ea8288b Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 24 Feb 2012 17:32:13 -0800 Subject: [PATCH 230/269] usb: dwc3: replace hard-coded constant in DWC3_GCTL_SCALEDOWN(3) Define DWC3_GCTL_SCALEDOWN_MASK and use it in place of DWC3_GCTL_SCALEDOWN(3). Signed-off-by: Paul Zimmerman Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 2 +- drivers/usb/dwc3/core.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 3fd4e843139e..fd6917b8d0d7 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -350,7 +350,7 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc) dwc3_cache_hwparams(dwc); reg = dwc3_readl(dwc->regs, DWC3_GCTL); - reg &= ~DWC3_GCTL_SCALEDOWN(3); + reg &= ~DWC3_GCTL_SCALEDOWN_MASK; reg &= ~DWC3_GCTL_DISSCRAMBLE; switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 81d1c0aeb6c5..f124643353bb 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -161,6 +161,7 @@ #define DWC3_GCTL_CORESOFTRESET (1 << 11) #define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) +#define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3) #define DWC3_GCTL_DISSCRAMBLE (1 << 3) #define DWC3_GCTL_DSBLCLKGTNG (1 << 0) From 7d26b58735f5badf2b7ce3320c6ba21b603c77a9 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 24 Feb 2012 17:32:14 -0800 Subject: [PATCH 231/269] usb: dwc3: pci: fix failure path in dwc3_pci_probe() dwc3_pci_probe() would return success even if the calls to dwc3_get_device_id() or platform_device_alloc() fail, fix that. Signed-off-by: Paul Zimmerman Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 74bac06652c4..dcc64791b4e1 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -81,8 +81,10 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci, pci_set_master(pci); devid = dwc3_get_device_id(); - if (devid < 0) + if (devid < 0) { + ret = -ENOMEM; goto err1; + } dwc3 = platform_device_alloc("dwc3", devid); if (!dwc3) { From aee63e3cb6b0396b99c6387a47cb90a7417f3957 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 24 Feb 2012 17:32:15 -0800 Subject: [PATCH 232/269] usb: dwc3: shorten long delay in dwc3_gadget_set_link_state() The loop in dwc3_gadget_set_link_state() was using a udelay(500), which is a long time to delay in interrupt context. Change it to udelay(5) and increase the loop count to match. Signed-off-by: Paul Zimmerman Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index fac11491850f..e2633dd03f8c 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -95,11 +95,11 @@ int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode) * @state: the state to put link into * * Caller should take care of locking. This function will - * return 0 on success or -EINVAL. + * return 0 on success or -ETIMEDOUT. */ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) { - int retries = 100; + int retries = 10000; u32 reg; reg = dwc3_readl(dwc->regs, DWC3_DCTL); @@ -113,11 +113,10 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) while (--retries) { reg = dwc3_readl(dwc->regs, DWC3_DSTS); - /* in HS, means ON */ if (DWC3_DSTS_USBLNKST(reg) == state) return 0; - udelay(500); + udelay(5); } dev_vdbg(dwc->dev, "link state change request timed out\n"); From 249a456930cd2df29d085fb738b0e8f4bc1680cf Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 24 Feb 2012 17:32:16 -0800 Subject: [PATCH 233/269] usb: dwc3: take lock while modifying flags dwc3_gadget_ep_set_wedge() and dwc3_gadget_set_selfpowered() were modifying dwc->flags/dwc->is_selfpowered without taking the lock. Since those modifications are non-atomic, that could cause other flags to be corrupted. Fix them both to take the lock. Signed-off-by: Paul Zimmerman Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index e2633dd03f8c..bfdfd4f151f8 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1196,8 +1196,12 @@ out: static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep) { struct dwc3_ep *dep = to_dwc3_ep(ep); + struct dwc3 *dwc = dep->dwc; + unsigned long flags; + spin_lock_irqsave(&dwc->lock, flags); dep->flags |= DWC3_EP_WEDGE; + spin_unlock_irqrestore(&dwc->lock, flags); return dwc3_gadget_ep_set_halt(ep, 1); } @@ -1323,8 +1327,11 @@ static int dwc3_gadget_set_selfpowered(struct usb_gadget *g, int is_selfpowered) { struct dwc3 *dwc = gadget_to_dwc(g); + unsigned long flags; + spin_lock_irqsave(&dwc->lock, flags); dwc->is_selfpowered = !!is_selfpowered; + spin_unlock_irqrestore(&dwc->lock, flags); return 0; } From c2df85ca31645ed3c68c56bd30a3673e034224f1 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Fri, 24 Feb 2012 17:32:18 -0800 Subject: [PATCH 234/269] usb: dwc3: clear 'res_trans_idx' as soon as it becomes invalid Transfer resource index is cleared in hardware when XFERCOMPLETE event is generated, so clear the driver's res_trans_idx variable immediately after that event is received. The upcoming hibernation patches depend on this change. Signed-off-by: Paul Zimmerman Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 1 + drivers/usb/dwc3/gadget.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 4fa2c9873eab..73efdf6938a2 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -617,6 +617,7 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc, struct dwc3_ep *dep = dwc->eps[event->endpoint_number]; dep->flags &= ~DWC3_EP_BUSY; + dep->res_trans_idx = 0; dwc->setup_packet_pending = false; switch (dwc->ep0state) { diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index bfdfd4f151f8..da317f6a8bce 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1628,10 +1628,8 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, status = -ECONNRESET; clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status); - if (clean_busy) { + if (clean_busy) dep->flags &= ~DWC3_EP_BUSY; - dep->res_trans_idx = 0; - } /* * WORKAROUND: This is the 2nd half of U1/U2 -> U0 workaround. @@ -1736,6 +1734,8 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, switch (event->endpoint_event) { case DWC3_DEPEVT_XFERCOMPLETE: + dep->res_trans_idx = 0; + if (usb_endpoint_xfer_isoc(dep->desc)) { dev_dbg(dwc->dev, "%s is an Isochronous endpoint\n", dep->name); From a5360a53a7ccad5ed9ccef210b94fef13c6e5529 Mon Sep 17 00:00:00 2001 From: Preston Fick Date: Fri, 24 Feb 2012 13:42:39 -0600 Subject: [PATCH 235/269] usb: cp210x: Update to support CP2105 and multiple interface devices This patch updates the cp210x driver to support CP210x multiple interface devices devices from Silicon Labs. The existing driver always sends control requests to interface 0, which is hardcoded in the usb_control_msg function calls. This only allows for single interface devices to be used, and causes a bug when using ports on an interface other than 0 in the multiple interface devices. Here are the changes included in this patch: - Updated the device list to contain the Silicon Labs factory default VID/PID for multiple interface CP210x devices - Created a cp210x_port_private struct created for each port on startup, this struct holds the interface number - Added a cp210x_release function to clean up the cp210x_port_private memory created on startup - Modified usb_get_config and usb_set_config to get a pointer to the cp210x_port_private struct, and use the interface number there in the usb_control_message wIndex param Signed-off-by: Preston Fick Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 44 ++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 651b2aa13486..0310e2df59f5 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -49,6 +49,7 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, unsigned int, unsigned int); static void cp210x_break_ctl(struct tty_struct *, int); static int cp210x_startup(struct usb_serial *); +static void cp210x_release(struct usb_serial *); static void cp210x_dtr_rts(struct usb_serial_port *p, int on); static bool debug; @@ -121,6 +122,8 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */ { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */ @@ -149,6 +152,10 @@ static const struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE(usb, id_table); +struct cp210x_port_private { + __u8 bInterfaceNumber; +}; + static struct usb_driver cp210x_driver = { .name = "cp210x", .probe = usb_serial_probe, @@ -172,6 +179,7 @@ static struct usb_serial_driver cp210x_device = { .tiocmget = cp210x_tiocmget, .tiocmset = cp210x_tiocmset, .attach = cp210x_startup, + .release = cp210x_release, .dtr_rts = cp210x_dtr_rts }; @@ -263,6 +271,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, unsigned int *data, int size) { struct usb_serial *serial = port->serial; + struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); __le32 *buf; int result, i, length; @@ -278,7 +287,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, /* Issue the request, attempting to read 'size' bytes */ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), request, REQTYPE_DEVICE_TO_HOST, 0x0000, - 0, buf, size, 300); + port_priv->bInterfaceNumber, buf, size, 300); /* Convert data into an array of integers */ for (i = 0; i < length; i++) @@ -309,6 +318,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, unsigned int *data, int size) { struct usb_serial *serial = port->serial; + struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); __le32 *buf; int result, i, length; @@ -330,12 +340,12 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_DEVICE, 0x0000, - 0, buf, size, 300); + port_priv->bInterfaceNumber, buf, size, 300); } else { result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_DEVICE, data[0], - 0, NULL, 0, 300); + port_priv->bInterfaceNumber, NULL, 0, 300); } kfree(buf); @@ -845,11 +855,39 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state) static int cp210x_startup(struct usb_serial *serial) { + struct cp210x_port_private *port_priv; + int i; + /* cp210x buffers behave strangely unless device is reset */ usb_reset_device(serial->dev); + + for (i = 0; i < serial->num_ports; i++) { + port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); + if (!port_priv) + return -ENOMEM; + + memset(port_priv, 0x00, sizeof(*port_priv)); + port_priv->bInterfaceNumber = + serial->interface->cur_altsetting->desc.bInterfaceNumber; + + usb_set_serial_port_data(serial->port[i], port_priv); + } + return 0; } +static void cp210x_release(struct usb_serial *serial) +{ + struct cp210x_port_private *port_priv; + int i; + + for (i = 0; i < serial->num_ports; i++) { + port_priv = usb_get_serial_port_data(serial->port[i]); + kfree(port_priv); + usb_set_serial_port_data(serial->port[i], NULL); + } +} + module_usb_serial_driver(cp210x_driver, serial_drivers); MODULE_DESCRIPTION(DRIVER_DESC); From b1116dcc63a91ee79a122abea025aab15ea2c8e7 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 28 Feb 2012 12:57:20 +0100 Subject: [PATCH 236/269] usb: dwc3: core: Convert to module_platform_driver Use the module_platform_driver macro. Signed-off-by: Tobias Klauser Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/core.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index fd6917b8d0d7..7bd815a507e8 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -597,19 +597,9 @@ static struct platform_driver dwc3_driver = { }, }; +module_platform_driver(dwc3_driver); + MODULE_ALIAS("platform:dwc3"); MODULE_AUTHOR("Felipe Balbi "); MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); - -static int __devinit dwc3_init(void) -{ - return platform_driver_register(&dwc3_driver); -} -module_init(dwc3_init); - -static void __exit dwc3_exit(void) -{ - platform_driver_unregister(&dwc3_driver); -} -module_exit(dwc3_exit); From 2e8d3fe4bf680b8263e0c81a8aa46a8d07b0f7be Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 28 Feb 2012 12:57:21 +0100 Subject: [PATCH 237/269] usb: isp116x-hcd: Convert to module_platform_driver Use the module_platform_driver macro, move the usb_disabled() check to the probe function and get rid of the rather pointless message on module load. Signed-off-by: Tobias Klauser Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp116x-hcd.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index d91e5f211a76..924880087a74 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1569,6 +1569,9 @@ static int __devinit isp116x_probe(struct platform_device *pdev) int ret = 0; unsigned long irqflags; + if (usb_disabled()) + return -ENODEV; + if (pdev->num_resources < 3) { ret = -ENODEV; goto err1; @@ -1708,22 +1711,4 @@ static struct platform_driver isp116x_driver = { }, }; -/*-----------------------------------------------------------------*/ - -static int __init isp116x_init(void) -{ - if (usb_disabled()) - return -ENODEV; - - INFO("driver %s, %s\n", hcd_name, DRIVER_VERSION); - return platform_driver_register(&isp116x_driver); -} - -module_init(isp116x_init); - -static void __exit isp116x_cleanup(void) -{ - platform_driver_unregister(&isp116x_driver); -} - -module_exit(isp116x_cleanup); +module_platform_driver(isp116x_driver); From 427914801e553806ee6b25241603030ce376d43b Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 28 Feb 2012 12:57:22 +0100 Subject: [PATCH 238/269] usb: r8a66597-hcd: Convert to module_platform_driver Use the module_platform_driver macro, move the usb_disabled() check to the probe function and get rid of the rather pointless message on module load. Signed-off-by: Tobias Klauser Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/r8a66597-hcd.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index e84ca1928dbf..2bf1320dc9c3 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2428,6 +2428,9 @@ static int __devinit r8a66597_probe(struct platform_device *pdev) int i; unsigned long irq_trigger; + if (usb_disabled()) + return -ENODEV; + if (pdev->dev.dma_mask) { ret = -EINVAL; dev_err(&pdev->dev, "dma not supported\n"); @@ -2552,20 +2555,4 @@ static struct platform_driver r8a66597_driver = { }, }; -static int __init r8a66597_init(void) -{ - if (usb_disabled()) - return -ENODEV; - - printk(KERN_INFO KBUILD_MODNAME ": driver %s, %s\n", hcd_name, - DRIVER_VERSION); - return platform_driver_register(&r8a66597_driver); -} -module_init(r8a66597_init); - -static void __exit r8a66597_cleanup(void) -{ - platform_driver_unregister(&r8a66597_driver); -} -module_exit(r8a66597_cleanup); - +module_platform_driver(r8a66597_driver); From 6ef1a9276be455c114c000ef3d43666cb6ded371 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 28 Feb 2012 12:57:23 +0100 Subject: [PATCH 239/269] usb: sl811-hcd: Convert to module_platform_driver Use the module_platform_driver macro, move the usb_disabled() check to the probe function and get rid of the rather pointless message on module load. Signed-off-by: Tobias Klauser Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/sl811-hcd.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 961d6638d8f9..2a2cce2d2fa7 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -1632,6 +1632,9 @@ sl811h_probe(struct platform_device *dev) u8 tmp, ioaddr = 0; unsigned long irqflags; + if (usb_disabled()) + return -ENODEV; + /* basic sanity checks first. board-specific init logic should * have initialized these three resources and probably board * specific platform_data. we don't probe for IRQs, and do only @@ -1817,20 +1820,4 @@ struct platform_driver sl811h_driver = { }; EXPORT_SYMBOL(sl811h_driver); -/*-------------------------------------------------------------------------*/ - -static int __init sl811h_init(void) -{ - if (usb_disabled()) - return -ENODEV; - - INFO("driver %s, %s\n", hcd_name, DRIVER_VERSION); - return platform_driver_register(&sl811h_driver); -} -module_init(sl811h_init); - -static void __exit sl811h_cleanup(void) -{ - platform_driver_unregister(&sl811h_driver); -} -module_exit(sl811h_cleanup); +module_platform_driver(sl811h_driver); From b1443ac0e486842c133b8805ee035ab3ff918763 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 2 Mar 2012 21:51:00 +0300 Subject: [PATCH 240/269] usb: gadget: dummy_hcd: signedness bug in transfer() "len" is unsigned so it's never less than zero. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/dummy_hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 8cc1a88d21e7..e1cd56c5e2a8 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1352,7 +1352,7 @@ top: len = dummy_perform_transfer(urb, req, len); ep->last_io = jiffies; - if (len < 0) { + if ((int)len < 0) { req->req.status = len; } else { limit -= len; From 2a5be8783e0016d15e7907ddd212b2c312e196eb Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Thu, 1 Mar 2012 23:01:19 +0100 Subject: [PATCH 241/269] Allocate correct size (portably) in drivers/usb/gadget/f_midi.c::f_midi_bind() As the coverity checker puts it: "Passing argument "sizeof (midi_function) /*8*/" to function "kcalloc" and then casting the return value to "struct usb_descriptor_header **" is suspicious. ... In this particular case sizeof(struct usb_descriptor_header **) happens to be equal to sizeof(struct usb_descriptor_header *), but this is not a portable assumption." I believe we really do intend to use 'sizeof(*midi_function)' here, so this patch makes that change. Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_midi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c index 3797b3d6c622..2f7e8f2930cc 100644 --- a/drivers/usb/gadget/f_midi.c +++ b/drivers/usb/gadget/f_midi.c @@ -780,7 +780,7 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f) midi->out_ep->driver_data = cdev; /* claim */ /* allocate temporary function list */ - midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(midi_function), + midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(*midi_function), GFP_KERNEL); if (!midi_function) { status = -ENOMEM; From 371f3b49f2cb1a8b6ac09b6b108841ca92349eb1 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 29 Feb 2012 23:04:32 +0100 Subject: [PATCH 242/269] usb/core: remove "always" from usb_unlink_urb() kernel doc entry The kernel doc entry for usb_unlink_urb() contains the phrase "This request is always asynchronous.". The "always" leads to the assumption that the ->complete() callback is not called from within usb_unlink_urb(). This is not true. The HCD is allowed to call the ->complete() from within ->urb_dequeue() if it is appropriate for the hardware. This patch updates the kernel doc so usb-device driver authors make sure to drop all locks (and make sure it is okay to drop them) which are acquired by the complete callback before calling usb_unlink_urb(). Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/urb.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index f4f20c7b7765..7239a73c1b8c 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -527,10 +527,13 @@ EXPORT_SYMBOL_GPL(usb_submit_urb); * a driver's I/O routines to insure that all URB-related activity has * completed before it returns. * - * This request is always asynchronous. Success is indicated by - * returning -EINPROGRESS, at which time the URB will probably not yet - * have been given back to the device driver. When it is eventually - * called, the completion function will see @urb->status == -ECONNRESET. + * This request is asynchronous, however the HCD might call the ->complete() + * callback during unlink. Therefore when drivers call usb_unlink_urb(), they + * must not hold any locks that may be taken by the completion function. + * Success is indicated by returning -EINPROGRESS, at which time the URB will + * probably not yet have been given back to the device driver. When it is + * eventually called, the completion function will see @urb->status == + * -ECONNRESET. * Failure is indicated by usb_unlink_urb() returning any other value. * Unlinking will fail when @urb is not currently "linked" (i.e., it was * never submitted, or it was unlinked before, or the hardware is already From 60b9bd8d162174edd335c1b83dbc2bafde1e9d5f Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 1 Mar 2012 21:13:13 -0600 Subject: [PATCH 243/269] usb: ohci-pxa27x: add explicit include of hardware.h ohci-pxa27x needs cpu_is_pxa3xx macro. Signed-off-by: Rob Herring Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-pxa27x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 6313e4439f37..4db399c01348 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include From 85b4b3c8c189e0159101f7628a71411af072ff69 Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Fri, 2 Mar 2012 09:41:50 +0100 Subject: [PATCH 244/269] usb: gadgetfs: return number of bytes on ep0 read request A read from GadgetFS endpoint 0 during the data stage of a control request would always return 0 on success (as returned by wait_event_interruptible) despite having written data into the user buffer. This patch makes it correctly set the return value to the number of bytes read. Signed-off-by: Thomas Faber Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/inode.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index ae04266dba1b..4f18a0e46070 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1043,6 +1043,8 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) // FIXME don't call this with the spinlock held ... if (copy_to_user (buf, dev->req->buf, len)) retval = -EFAULT; + else + retval = len; clean_req (dev->gadget->ep0, dev->req); /* NOTE userspace can't yet choose to stall */ } From 5f0b3f9998ceca8414dfb7d0dba69209f11b44af Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 2 Mar 2012 11:08:14 +0300 Subject: [PATCH 245/269] usb: otg: ab8500-usb: make probe() work again The probe() function will always fail because we're testing the wrong variable. Signed-off-by: Dan Carpenter Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/ab8500-usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c index e6371ff5f583..a84af677dc59 100644 --- a/drivers/usb/otg/ab8500-usb.c +++ b/drivers/usb/otg/ab8500-usb.c @@ -489,7 +489,7 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) return -ENOMEM; otg = kzalloc(sizeof *otg, GFP_KERNEL); - if (!ab->phy.otg) { + if (!otg) { kfree(ab); return -ENOMEM; } From 30e9eb190f7930bf1edb0ec2d0ce10e300391abd Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Tue, 6 Mar 2012 11:49:04 +0900 Subject: [PATCH 246/269] usb/gadget/pch_udc: Fix compile error Greg's e-mail address was old. So, I resend it. Though I've tested this patch, http://marc.info/?l=linux-usb&m=132825305710285&w=2, I've received the following reports. http://kisskb.ellerman.id.au/kisskb/buildresult/5771890/ http://kisskb.ellerman.id.au/kisskb/buildresult/5771905/ So, I added header file for these symbols. Using this patch, this compile error must be disappeared. Reported-by: Paul Gortmaker Signed-off-by: Tomoya MORINAGA Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pch_udc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 350dbcd90681..65307064a6fd 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -16,6 +16,7 @@ #include #include #include +#include /* GPIO port for VBUS detecting */ static int vbus_gpio_port = -1; /* GPIO port number (-1:Not used) */ From 88555a63caafcc86b93b045dfc26cd7a8fa16350 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 5 Mar 2012 10:40:14 +0900 Subject: [PATCH 247/269] USB: ehci-s5p: add DMA burst support DMA burst support is added to improve performance in EHCI data transfer. The USB EHCI controller on Exynos SoCs can use INCR16, INCR8, and INCR4 mode. These modes of INSNREG00 register should be set in order to enable DMA burst transfer. This feature is also related to AHB spec. Signed-off-by: Jingoo Han Signed-off-by: Sangwook Lee Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-s5p.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index 293f7412992e..f098e2a291a0 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -17,6 +17,15 @@ #include #include +#define EHCI_INSNREG00(base) (base + 0x90) +#define EHCI_INSNREG00_ENA_INCR16 (0x1 << 25) +#define EHCI_INSNREG00_ENA_INCR8 (0x1 << 24) +#define EHCI_INSNREG00_ENA_INCR4 (0x1 << 23) +#define EHCI_INSNREG00_ENA_INCRX_ALIGN (0x1 << 22) +#define EHCI_INSNREG00_ENABLE_DMA_BURST \ + (EHCI_INSNREG00_ENA_INCR16 | EHCI_INSNREG00_ENA_INCR8 | \ + EHCI_INSNREG00_ENA_INCR4 | EHCI_INSNREG00_ENA_INCRX_ALIGN) + struct s5p_ehci_hcd { struct device *dev; struct usb_hcd *hcd; @@ -128,6 +137,9 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) ehci->regs = hcd->regs + HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase)); + /* DMA burst Enable */ + writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); + dbg_hcs_params(ehci, "reset"); dbg_hcc_params(ehci, "reset"); @@ -234,6 +246,9 @@ static int s5p_ehci_resume(struct device *dev) if (pdata && pdata->phy_init) pdata->phy_init(pdev, S5P_USB_PHY_HOST); + /* DMA burst Enable */ + writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); + if (time_before(jiffies, ehci->next_statechange)) msleep(100); From c1cee1d84001815a1b4321c49b995254c0df3100 Mon Sep 17 00:00:00 2001 From: Bruno Thomsen Date: Sun, 4 Mar 2012 15:19:14 +0100 Subject: [PATCH 248/269] USB: Microchip VID mislabeled as Hornby VID in ftdi_sio. Microchip VID (0x04d8) was mislabeled as Hornby VID according to USB-IDs. A Full Speed USB Demo Board PID (0x000a) was mislabeled as Hornby Elite (an Digital Command Controller Console for model railways). Most likely the Hornby based their design on PIC18F87J50 Full Speed USB Demo Board. Signed-off-by: Bruno Thomsen Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 +- drivers/usb/serial/ftdi_sio_ids.h | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index b160c252bf13..d8130993a922 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -801,7 +801,7 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(HORNBY_VID, HORNBY_ELITE_PID) }, + { USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index ed74019c5b46..2a87965b7723 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -532,10 +532,14 @@ #define ADI_GNICEPLUS_PID 0xF001 /* - * Hornby Elite + * Microchip Technology, Inc. + * + * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by: + * Hornby Elite - Digital Command Control Console + * http://www.hornby.com/hornby-dcc/controllers/ */ -#define HORNBY_VID 0x04D8 -#define HORNBY_ELITE_PID 0x000A +#define MICROCHIP_VID 0x04D8 +#define MICROCHIP_USB_BOARD_PID 0x000A /* CDC RS-232 Emulation Demo */ /* * RATOC REX-USB60F From 0dffb4862a5f109dc9b72e3a4e0ecc85a87ce397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Tue, 6 Mar 2012 17:29:20 +0100 Subject: [PATCH 249/269] usb: cdc-wdm: split out reusable parts of probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Preparing for the addition of subdriver registering as an alternative to probe for interface-less usage. This should not change anything apart from minor code reordering. Signed-off-by: Bjørn Mork Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 105 ++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 6037b503153f..451793036d37 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -631,47 +631,11 @@ static void wdm_rxwork(struct work_struct *work) /* --- hotplug --- */ -static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) +static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep, u16 bufsize) { - int rv = -EINVAL; + int rv = -ENOMEM; struct wdm_device *desc; - struct usb_host_interface *iface; - struct usb_endpoint_descriptor *ep; - struct usb_cdc_dmm_desc *dmhd; - u8 *buffer = intf->altsetting->extra; - int buflen = intf->altsetting->extralen; - u16 maxcom = WDM_DEFAULT_BUFSIZE; - if (!buffer) - goto out; - - while (buflen > 2) { - if (buffer [1] != USB_DT_CS_INTERFACE) { - dev_err(&intf->dev, "skipping garbage\n"); - goto next_desc; - } - - switch (buffer [2]) { - case USB_CDC_HEADER_TYPE: - break; - case USB_CDC_DMM_TYPE: - dmhd = (struct usb_cdc_dmm_desc *)buffer; - maxcom = le16_to_cpu(dmhd->wMaxCommand); - dev_dbg(&intf->dev, - "Finding maximum buffer length: %d", maxcom); - break; - default: - dev_err(&intf->dev, - "Ignoring extra header, type %d, length %d\n", - buffer[2], buffer[0]); - break; - } -next_desc: - buflen -= buffer[0]; - buffer += buffer[0]; - } - - rv = -ENOMEM; desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); if (!desc) goto out; @@ -679,18 +643,14 @@ next_desc: mutex_init(&desc->wlock); spin_lock_init(&desc->iuspin); init_waitqueue_head(&desc->wait); - desc->wMaxCommand = maxcom; + desc->wMaxCommand = bufsize; /* this will be expanded and needed in hardware endianness */ desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber); desc->intf = intf; INIT_WORK(&desc->rxwork, wdm_rxwork); rv = -EINVAL; - iface = intf->cur_altsetting; - if (iface->desc.bNumEndpoints != 1) - goto err; - ep = &iface->endpoint[0].desc; - if (!ep || !usb_endpoint_is_int_in(ep)) + if (!usb_endpoint_is_int_in(ep)) goto err; desc->wMaxPacketSize = usb_endpoint_maxp(ep); @@ -766,13 +726,56 @@ out: err2: usb_set_intfdata(intf, NULL); err: - free_urbs(desc); - kfree(desc->inbuf); - kfree(desc->sbuf); - kfree(desc->ubuf); - kfree(desc->orq); - kfree(desc->irq); - kfree(desc); + cleanup(desc); + return rv; +} + +static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + int rv = -EINVAL; + struct usb_host_interface *iface; + struct usb_endpoint_descriptor *ep; + struct usb_cdc_dmm_desc *dmhd; + u8 *buffer = intf->altsetting->extra; + int buflen = intf->altsetting->extralen; + u16 maxcom = WDM_DEFAULT_BUFSIZE; + + if (!buffer) + goto err; + while (buflen > 2) { + if (buffer[1] != USB_DT_CS_INTERFACE) { + dev_err(&intf->dev, "skipping garbage\n"); + goto next_desc; + } + + switch (buffer[2]) { + case USB_CDC_HEADER_TYPE: + break; + case USB_CDC_DMM_TYPE: + dmhd = (struct usb_cdc_dmm_desc *)buffer; + maxcom = le16_to_cpu(dmhd->wMaxCommand); + dev_dbg(&intf->dev, + "Finding maximum buffer length: %d", maxcom); + break; + default: + dev_err(&intf->dev, + "Ignoring extra header, type %d, length %d\n", + buffer[2], buffer[0]); + break; + } +next_desc: + buflen -= buffer[0]; + buffer += buffer[0]; + } + + iface = intf->cur_altsetting; + if (iface->desc.bNumEndpoints != 1) + goto err; + ep = &iface->endpoint[0].desc; + + rv = wdm_create(intf, ep, maxcom); + +err: return rv; } From b0c13860808a528cd580fdca61aef9f73352a331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Tue, 6 Mar 2012 17:29:21 +0100 Subject: [PATCH 250/269] usb: cdc-wdm: adding list lookup indirection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Register all interfaces handled by this driver in a list, getting rid of the dependency on usb_set_intfdata. This allows further generalization and simplification of the probe/create functions. This is needed to decouple wdm_open from the driver owning the interface, and it also allows us to share all the code in wdm_create with drivers unable to do usb_set_intfdata. Signed-off-by: Bjørn Mork Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 60 +++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 451793036d37..46827373ecf9 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -78,6 +78,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); #define WDM_DEFAULT_BUFSIZE 256 static DEFINE_MUTEX(wdm_mutex); +static DEFINE_SPINLOCK(wdm_device_list_lock); +static LIST_HEAD(wdm_device_list); /* --- method tables --- */ @@ -112,10 +114,39 @@ struct wdm_device { struct work_struct rxwork; int werr; int rerr; + + struct list_head device_list; }; static struct usb_driver wdm_driver; +/* return intfdata if we own the interface, else look up intf in the list */ +static struct wdm_device *wdm_find_device(struct usb_interface *intf) +{ + struct wdm_device *desc = NULL; + + spin_lock(&wdm_device_list_lock); + list_for_each_entry(desc, &wdm_device_list, device_list) + if (desc->intf == intf) + break; + spin_unlock(&wdm_device_list_lock); + + return desc; +} + +static struct wdm_device *wdm_find_device_by_minor(int minor) +{ + struct wdm_device *desc = NULL; + + spin_lock(&wdm_device_list_lock); + list_for_each_entry(desc, &wdm_device_list, device_list) + if (desc->intf->minor == minor) + break; + spin_unlock(&wdm_device_list_lock); + + return desc; +} + /* --- callbacks --- */ static void wdm_out_callback(struct urb *urb) { @@ -275,6 +306,9 @@ static void free_urbs(struct wdm_device *desc) static void cleanup(struct wdm_device *desc) { + spin_lock(&wdm_device_list_lock); + list_del(&desc->device_list); + spin_unlock(&wdm_device_list_lock); kfree(desc->sbuf); kfree(desc->inbuf); kfree(desc->orq); @@ -532,11 +566,11 @@ static int wdm_open(struct inode *inode, struct file *file) struct wdm_device *desc; mutex_lock(&wdm_mutex); - intf = usb_find_interface(&wdm_driver, minor); - if (!intf) + desc = wdm_find_device_by_minor(minor); + if (!desc) goto out; - desc = usb_get_intfdata(intf); + intf = desc->intf; if (test_bit(WDM_DISCONNECTING, &desc->flags)) goto out; file->private_data = desc; @@ -639,6 +673,7 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); if (!desc) goto out; + INIT_LIST_HEAD(&desc->device_list); mutex_init(&desc->rlock); mutex_init(&desc->wlock); spin_lock_init(&desc->iuspin); @@ -715,16 +750,17 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor desc ); - usb_set_intfdata(intf, desc); + spin_lock(&wdm_device_list_lock); + list_add(&desc->device_list, &wdm_device_list); + spin_unlock(&wdm_device_list_lock); + rv = usb_register_dev(intf, &wdm_class); if (rv < 0) - goto err2; + goto err; else dev_info(&intf->dev, "%s: USB WDM device\n", dev_name(intf->usb_dev)); out: return rv; -err2: - usb_set_intfdata(intf, NULL); err: cleanup(desc); return rv; @@ -785,8 +821,8 @@ static void wdm_disconnect(struct usb_interface *intf) unsigned long flags; usb_deregister_dev(intf, &wdm_class); + desc = wdm_find_device(intf); mutex_lock(&wdm_mutex); - desc = usb_get_intfdata(intf); /* the spinlock makes sure no new urbs are generated in the callbacks */ spin_lock_irqsave(&desc->iuspin, flags); @@ -810,7 +846,7 @@ static void wdm_disconnect(struct usb_interface *intf) #ifdef CONFIG_PM static int wdm_suspend(struct usb_interface *intf, pm_message_t message) { - struct wdm_device *desc = usb_get_intfdata(intf); + struct wdm_device *desc = wdm_find_device(intf); int rv = 0; dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); @@ -860,7 +896,7 @@ static int recover_from_urb_loss(struct wdm_device *desc) #ifdef CONFIG_PM static int wdm_resume(struct usb_interface *intf) { - struct wdm_device *desc = usb_get_intfdata(intf); + struct wdm_device *desc = wdm_find_device(intf); int rv; dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor); @@ -874,7 +910,7 @@ static int wdm_resume(struct usb_interface *intf) static int wdm_pre_reset(struct usb_interface *intf) { - struct wdm_device *desc = usb_get_intfdata(intf); + struct wdm_device *desc = wdm_find_device(intf); /* * we notify everybody using poll of @@ -898,7 +934,7 @@ static int wdm_pre_reset(struct usb_interface *intf) static int wdm_post_reset(struct usb_interface *intf) { - struct wdm_device *desc = usb_get_intfdata(intf); + struct wdm_device *desc = wdm_find_device(intf); int rv; clear_bit(WDM_RESETTING, &desc->flags); From 3cc3615749dbd1b891512d5c9a5bf4559cfa9741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Tue, 6 Mar 2012 17:29:22 +0100 Subject: [PATCH 251/269] usb: cdc-wdm: adding usb_cdc_wdm_register subdriver support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver can be used as a subdriver of another USB driver, allowing it to export a Device Managment interface consisting of a single interrupt endpoint with no dedicated USB interface. Some devices provide a Device Management function combined with a wwan function in a single USB interface having three endpoints (bulk in/out + interrupt). If the interrupt endpoint is used exclusively for DM notifications, then this driver can support that as a subdriver provided that the wwan driver calls the appropriate entry points on probe, suspend, resume, pre_reset, post_reset and disconnect. The main driver must have full control over all interface related settings, including the needs_remote_wakeup flag. A manage_power function must be provided by the main driver. A manage_power stub doing direct flag manipulation is used in normal driver mode. Signed-off-by: Bjørn Mork Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 63 ++++++++++++++++++++++++++++++++++--- include/linux/usb/cdc-wdm.h | 19 +++++++++++ 2 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 include/linux/usb/cdc-wdm.h diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 46827373ecf9..c6f6560d436c 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -23,6 +23,7 @@ #include #include #include +#include /* * Version Information @@ -116,6 +117,7 @@ struct wdm_device { int rerr; struct list_head device_list; + int (*manage_power)(struct usb_interface *, int); }; static struct usb_driver wdm_driver; @@ -580,7 +582,6 @@ static int wdm_open(struct inode *inode, struct file *file) dev_err(&desc->intf->dev, "Error autopm - %d\n", rv); goto out; } - intf->needs_remote_wakeup = 1; /* using write lock to protect desc->count */ mutex_lock(&desc->wlock); @@ -597,6 +598,8 @@ static int wdm_open(struct inode *inode, struct file *file) rv = 0; } mutex_unlock(&desc->wlock); + if (desc->count == 1) + desc->manage_power(intf, 1); usb_autopm_put_interface(desc->intf); out: mutex_unlock(&wdm_mutex); @@ -618,7 +621,7 @@ static int wdm_release(struct inode *inode, struct file *file) dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); kill_urbs(desc); if (!test_bit(WDM_DISCONNECTING, &desc->flags)) - desc->intf->needs_remote_wakeup = 0; + desc->manage_power(desc->intf, 0); } mutex_unlock(&wdm_mutex); return 0; @@ -665,7 +668,8 @@ static void wdm_rxwork(struct work_struct *work) /* --- hotplug --- */ -static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep, u16 bufsize) +static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep, + u16 bufsize, int (*manage_power)(struct usb_interface *, int)) { int rv = -ENOMEM; struct wdm_device *desc; @@ -750,6 +754,8 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor desc ); + desc->manage_power = manage_power; + spin_lock(&wdm_device_list_lock); list_add(&desc->device_list, &wdm_device_list); spin_unlock(&wdm_device_list_lock); @@ -766,6 +772,19 @@ err: return rv; } +static int wdm_manage_power(struct usb_interface *intf, int on) +{ + /* need autopm_get/put here to ensure the usbcore sees the new value */ + int rv = usb_autopm_get_interface(intf); + if (rv < 0) + goto err; + + intf->needs_remote_wakeup = on; + usb_autopm_put_interface(intf); +err: + return rv; +} + static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) { int rv = -EINVAL; @@ -809,12 +828,48 @@ next_desc: goto err; ep = &iface->endpoint[0].desc; - rv = wdm_create(intf, ep, maxcom); + rv = wdm_create(intf, ep, maxcom, &wdm_manage_power); err: return rv; } +/** + * usb_cdc_wdm_register - register a WDM subdriver + * @intf: usb interface the subdriver will associate with + * @ep: interrupt endpoint to monitor for notifications + * @bufsize: maximum message size to support for read/write + * + * Create WDM usb class character device and associate it with intf + * without binding, allowing another driver to manage the interface. + * + * The subdriver will manage the given interrupt endpoint exclusively + * and will issue control requests referring to the given intf. It + * will otherwise avoid interferring, and in particular not do + * usb_set_intfdata/usb_get_intfdata on intf. + * + * The return value is a pointer to the subdriver's struct usb_driver. + * The registering driver is responsible for calling this subdriver's + * disconnect, suspend, resume, pre_reset and post_reset methods from + * its own. + */ +struct usb_driver *usb_cdc_wdm_register(struct usb_interface *intf, + struct usb_endpoint_descriptor *ep, + int bufsize, + int (*manage_power)(struct usb_interface *, int)) +{ + int rv = -EINVAL; + + rv = wdm_create(intf, ep, bufsize, manage_power); + if (rv < 0) + goto err; + + return &wdm_driver; +err: + return ERR_PTR(rv); +} +EXPORT_SYMBOL(usb_cdc_wdm_register); + static void wdm_disconnect(struct usb_interface *intf) { struct wdm_device *desc; diff --git a/include/linux/usb/cdc-wdm.h b/include/linux/usb/cdc-wdm.h new file mode 100644 index 000000000000..719c332620fa --- /dev/null +++ b/include/linux/usb/cdc-wdm.h @@ -0,0 +1,19 @@ +/* + * USB CDC Device Management subdriver + * + * Copyright (c) 2012 Bjørn Mork + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef __LINUX_USB_CDC_WDM_H +#define __LINUX_USB_CDC_WDM_H + +extern struct usb_driver *usb_cdc_wdm_register(struct usb_interface *intf, + struct usb_endpoint_descriptor *ep, + int bufsize, + int (*manage_power)(struct usb_interface *, int)); + +#endif /* __LINUX_USB_CDC_WDM_H */ From 33d2832ab0149a26418d360af3c444969a63fb28 Mon Sep 17 00:00:00 2001 From: Orjan Friberg Date: Wed, 7 Mar 2012 17:16:14 +0100 Subject: [PATCH 252/269] USB: gadget: Make g_hid device class conform to spec. HID devices should specify this in their interface descriptors, not in the device descriptor. This fixes a "missing hardware id" bug under Windows 7 with a VIA VL800 (3.0) controller. Signed-off-by: Orjan Friberg Cc: Felipe Balbi Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/hid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index f888c3ede860..3493adf064f5 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -60,9 +60,9 @@ static struct usb_device_descriptor device_desc = { /* .bDeviceClass = USB_CLASS_COMM, */ /* .bDeviceSubClass = 0, */ /* .bDeviceProtocol = 0, */ - .bDeviceClass = 0xEF, - .bDeviceSubClass = 2, - .bDeviceProtocol = 1, + .bDeviceClass = USB_CLASS_PER_INTERFACE, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, /* .bMaxPacketSize0 = f(hardware) */ /* Vendor and product id can be overridden by module parameters. */ From 43d186fe992da93bb1dd34a7dd4534719624431c Mon Sep 17 00:00:00 2001 From: Aleksey Babahin Date: Thu, 8 Mar 2012 13:18:43 -0800 Subject: [PATCH 253/269] USB: serial: add metro-usb driver to the tree This driver is for the Metrologic barcode scanner. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 622 +++++++++++++++++++++++++++++++++ drivers/usb/serial/metro-usb.h | 52 +++ 2 files changed, 674 insertions(+) create mode 100644 drivers/usb/serial/metro-usb.c create mode 100644 drivers/usb/serial/metro-usb.h diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c new file mode 100644 index 000000000000..5b8ed50e5dda --- /dev/null +++ b/drivers/usb/serial/metro-usb.c @@ -0,0 +1,622 @@ +/* + Date Created: 9/15/2006 + File Name: metro-usb.c + Description: metro-usb.c is the drivers main source file. The driver is a USB to Serial converter. + The driver takes USB data and sends it to a virtual ttyUSB# serial port. + The driver interfaces with the usbserial.ko driver supplied by Linux. + + NOTES: + To install the driver: + 1. Install the usbserial.ko module supplied by Linux with: # insmod usbserial.ko + 2. Install the metro-usb.ko module with: # insmod metro-usb.ko vender=0x#### product=0x#### debug=1 + The vendor, product and debug parameters are optional. + + Some of this code is credited to Linux USB open source files that are distributed with Linux. + + Copyright: 2007 Metrologic Instruments. All rights reserved. + Copyright: 2011 Azimut Ltd. + Requirements: gedit.exe, notepad.exe + + Revision History: + + Date: Developer: Revisions: + ------------------------------------------------------------------------------ + 1/30/2007 Philip Nicastro Initial release. (v1.0.0.0) + 2/27/2007 Philip Nicastro Changed the metrousb_read_int_callback function to use a loop with the tty_insert_flip_char function to copy each byte to the tty layer. Removed the tty_buffer_request_room and the tty_insert_flip_string function calls. These calls were not supported on Fedora. + 2/27/2007 Philip Nicastro Released. (v1.1.0.0) + 10/07/2011 Aleksey Babahin Update for new kernel (tested on 2.6.38) + Add unidirection mode support + + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "metro-usb.h" +#include + +/* Version Information */ +#define DRIVER_VERSION "v1.2.0.0" +#define DRIVER_DESC "Metrologic Instruments Inc. - USB-POS driver" + +/* Device table list. */ +static struct usb_device_id id_table [] = { + { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID) }, + { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) }, + { }, /* Optional paramenter entry. */ + { }, /* Terminating entry. */ +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* Input parameter constants. */ +static int debug; +static __u16 vendor; +static __u16 product; + +/* Function prototypes. */ +static void metrousb_cleanup (struct usb_serial_port *port); +static void metrousb_close (struct usb_serial_port *port); +static int metrousb_open (struct tty_struct *tty, struct usb_serial_port *port); +static void metrousb_read_int_callback (struct urb *urb); +static void metrousb_shutdown (struct usb_serial *serial); +static int metrousb_startup (struct usb_serial *serial); +static void metrousb_throttle(struct tty_struct *tty); +static int metrousb_tiocmget(struct tty_struct *tty); +static int metrousb_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); +static void metrousb_unthrottle(struct tty_struct *tty); + +/* Driver structure. */ +static struct usb_driver metrousb_driver = { + .name = "metro-usb", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table +}; + +/* Device structure. */ +static struct usb_serial_driver metrousb_device = { + .driver = { + .owner = THIS_MODULE, + .name = "metro-usb", + }, + .description = "Metrologic USB to serial converter.", + .id_table = id_table, + .usb_driver = &metrousb_driver, + .num_ports = 1, + .open = metrousb_open, + .close = metrousb_close, + .read_int_callback = metrousb_read_int_callback, + .attach = metrousb_startup, + .release = metrousb_shutdown, + .throttle = metrousb_throttle, + .unthrottle = metrousb_unthrottle, + .tiocmget = metrousb_tiocmget, + .tiocmset = metrousb_tiocmset, +}; + +/* ---------------------------------------------------------------------------------------------- + Description: + Clean up any urbs and port information. + + Input: + struct usb_serial_port *: pointer to a usb_serial_port structure. + + Output: + int: Returns true (0) if successful, false otherwise. +*/ +static void metrousb_cleanup (struct usb_serial_port *port) +{ + dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + + if (port->serial->dev) { + /* Shutdown any interrupt in urbs. */ + if (port->interrupt_in_urb) { + usb_unlink_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_in_urb); + } + + // temp + // this will be needed for the write urb + /* Shutdown any interrupt_out_urbs. */ + //if (serial->num_bulk_in) + // usb_kill_urb(port->read_urb); + } +} + +/* ---------------------------------------------------------------------------------------------- + Description: + Close the open serial port. Cleanup any open serial port information. + + Input: + struct usb_serial_port *: pointer to a usb_serial_port structure. + struct file *: pointer to a file structure. + + Output: + int: Returns true (0) if successful, false otherwise. +*/ +static void metrousb_close (struct usb_serial_port *port) +{ + dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + metrousb_cleanup(port); +} + +/* ---------------------------------------------------------------------------------------------- + Description: + Driver exit. + + Input: + None: + + Output: + None: +*/ +static void __exit metrousb_exit(void) +{ + dbg("METRO-USB - %s", __FUNCTION__); + + usb_deregister(&metrousb_driver); + usb_serial_deregister(&metrousb_device); +} + +/* ---------------------------------------------------------------------------------------------- + Description: + Driver initialization. + + Input: + None: + + Output: + int: Returns true (0) if successful, false otherwise. +*/ +static int __init metrousb_init(void) +{ + int retval = 0; + int i = 0; + + dbg("METRO-USB - %s", __FUNCTION__); + + /* Add the device parameters if entered. */ + if ((vendor > 0) && (product > 0)) { + struct usb_device_id usb_dev_temp[] = { {USB_DEVICE(vendor, product) } }; + + /* Find the last entry in id_table */ + for (i=0; i < ARRAY_SIZE(id_table); i++) { + if (id_table[i].idVendor == 0) { + id_table[i] = usb_dev_temp[0]; + break; + } + } + + dbg("METRO-USB - %s - support added for unknown device: vendor=0x%x - product=0x%x", __FUNCTION__, vendor, product); + printk(KERN_INFO "Metro USB-POS support added for unknown device: vendor=0x%x - product=0x%x", vendor, product); + } + + /* Register the devices. */ + retval = usb_serial_register(&metrousb_device); + if (retval) + return retval; + + /* Register the driver. */ + retval = usb_register(&metrousb_driver); + if (retval) + usb_serial_deregister(&metrousb_device); + + printk(KERN_INFO DRIVER_DESC " : " DRIVER_VERSION); + + return retval; +} + +/* ---------------------------------------------------------------------------------------------- + Description: + Open the drivers serial port. + + Input: + struct usb_serial_port *: pointer to a usb_serial_port structure. + struct file *: pointer to a file structure. + + Output: + int: Returns true (0) if successful, false otherwise. +*/ +static int metrousb_open (struct tty_struct *tty, struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct metrousb_private *metro_priv = usb_get_serial_port_data(port); + unsigned long flags = 0; + int result = 0; + + dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + + /* Make sure the urb is initialized. */ + if (!port->interrupt_in_urb) { + dbg("METRO-USB - %s - interrupt urb not initialized for port number=%d", __FUNCTION__, port->number); + return -ENODEV; + } + + /* Set the private data information for the port. */ + spin_lock_irqsave(&metro_priv->lock, flags); + metro_priv->control_state = 0; + metro_priv->throttled = 0; + spin_unlock_irqrestore(&metro_priv->lock, flags); + + /* + * Force low_latency on so that our tty_push actually forces the data + * through, otherwise it is scheduled, and with high data rates (like + * with OHCI) data can get lost. + */ + if (tty) { + tty->low_latency = 1; + } + + /* Clear the urb pipe. */ + usb_clear_halt(serial->dev, port->interrupt_in_urb->pipe); + + /* Start reading from the device */ + usb_fill_int_urb (port->interrupt_in_urb, serial->dev, + usb_rcvintpipe (serial->dev, port->interrupt_in_endpointAddress), + port->interrupt_in_urb->transfer_buffer, + port->interrupt_in_urb->transfer_buffer_length, + metrousb_read_int_callback, port, 1); + result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + + if (result) { + dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d" + , __FUNCTION__, port->number, result); + goto exit; + } + + dbg("METRO-USB - %s - port open for port number=%d", __FUNCTION__, port->number); +exit: + return result; +} + +/* ---------------------------------------------------------------------------------------------- + Description: + Read the port from the read interrupt. + + Input: + struct urb *: urb structure to get data. + struct pt_regs *: pt_regs structure. + + Output: + None: +*/ +static void metrousb_read_int_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct metrousb_private *metro_priv = usb_get_serial_port_data(port); + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + int throttled = 0; + int result = 0; + unsigned long flags = 0; + + dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + + switch (urb->status) { + case 0: + /* Success status, read from the port. */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* urb has been terminated. */ + dbg("METRO-USB - %s - urb shutting down, port number=%d, error code=%d", + __FUNCTION__, port->number, result); + return; + default: + dbg("METRO-USB - %s - non-zero urb received, port number=%d, error code=%d", + __FUNCTION__, port->number, result); + goto exit; + } + + + /* Set the data read from the usb port into the serial port buffer. */ + tty = tty_port_tty_get(&port->port); + if (!tty) { + dbg("%s - bad tty pointer - exiting", __func__); + return; + } + + if (tty && urb->actual_length) { + // Loop through the data copying each byte to the tty layer. + tty_insert_flip_string(tty, data, urb->actual_length); + + // Force the data to the tty layer. + tty_flip_buffer_push(tty); + } + tty_kref_put(tty); + + /* Set any port variables. */ + spin_lock_irqsave(&metro_priv->lock, flags); + throttled = metro_priv->throttled; + spin_unlock_irqrestore(&metro_priv->lock, flags); + + /* Continue trying to read if set. */ + if (!throttled) { + usb_fill_int_urb (port->interrupt_in_urb, port->serial->dev, + usb_rcvintpipe (port->serial->dev, port->interrupt_in_endpointAddress), + port->interrupt_in_urb->transfer_buffer, + port->interrupt_in_urb->transfer_buffer_length, + metrousb_read_int_callback, port, 1); + + result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); + + if (result) { + dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d", + __FUNCTION__, port->number, result); + } + } + return; + +exit: + /* Try to resubmit the urb. */ + result = usb_submit_urb (urb, GFP_ATOMIC); + if (result) { + dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d", + __FUNCTION__, port->number, result); + } +} + +/* ---------------------------------------------------------------------------------------------- + Description: + Set the modem control state for the entered serial port. + + Input: + struct usb_serial_port *: pointer to a usb_serial_port structure. + unsigned int: control state value to set. + + Output: + int: Returns true (0) if successful, false otherwise. +*/ +static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int control_state) +{ + int retval = 0; + unsigned char mcr = METROUSB_MCR_NONE; + + dbg("METRO-USB - %s - control state=%d", __FUNCTION__, control_state); + + /* Set the modem control value. */ + if (control_state & TIOCM_DTR) + mcr |= METROUSB_MCR_DTR; + if (control_state & TIOCM_RTS) + mcr |= METROUSB_MCR_RTS; + + /* Send the command to the usb port. */ + retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + METROUSB_SET_REQUEST_TYPE, METROUSB_SET_MODEM_CTRL_REQUEST, + control_state, 0, NULL, 0, WDR_TIMEOUT); + if (retval < 0) + dbg("METRO-USB - %s - set modem ctrl=0x%x failed, error code=%d", __FUNCTION__, mcr, retval); + + return retval; +} + + +/* ---------------------------------------------------------------------------------------------- + Description: + Shutdown the driver. + + Input: + struct usb_serial *: pointer to a usb-serial structure. + + Output: + int: Returns true (0) if successful, false otherwise. +*/ +static void metrousb_shutdown (struct usb_serial *serial) +{ + int i = 0; + + dbg("METRO-USB - %s", __FUNCTION__); + + /* Stop reading and writing on all ports. */ + for (i=0; i < serial->num_ports; ++i) { + /* Close any open urbs. */ + metrousb_cleanup(serial->port[i]); + + /* Free memory. */ + kfree(usb_get_serial_port_data(serial->port[i])); + usb_set_serial_port_data(serial->port[i], NULL); + + dbg("METRO-USB - %s - freed port number=%d", __FUNCTION__, serial->port[i]->number); + } +} + +/* ---------------------------------------------------------------------------------------------- + Description: + Startup the driver. + + Input: + struct usb_serial *: pointer to a usb-serial structure. + + Output: + int: Returns true (0) if successful, false otherwise. +*/ +static int metrousb_startup(struct usb_serial *serial) +{ + struct metrousb_private *metro_priv; + struct usb_serial_port *port; + int i = 0; + + dbg("METRO-USB - %s", __FUNCTION__); + + /* Loop through the serial ports setting up the private structures. + * Currently we only use one port. */ + for (i = 0; i < serial->num_ports; ++i) { + port = serial->port[i]; + + /* Declare memory. */ + metro_priv = (struct metrousb_private *) kmalloc (sizeof(struct metrousb_private), GFP_KERNEL); + if (!metro_priv) + return -ENOMEM; + + /* Clear memory. */ + memset (metro_priv, 0x00, sizeof(struct metrousb_private)); + + /* Initialize memory. */ + spin_lock_init(&metro_priv->lock); + usb_set_serial_port_data(port, metro_priv); + + dbg("METRO-USB - %s - port number=%d.", __FUNCTION__, port->number); + } + + return 0; +} + +/* ---------------------------------------------------------------------------------------------- + Description: + Set the serial port throttle to stop reading from the port. + + Input: + struct usb_serial_port *: pointer to a usb_serial_port structure. + + Output: + None: +*/ +static void metrousb_throttle (struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct metrousb_private *metro_priv = usb_get_serial_port_data(port); + unsigned long flags = 0; + + dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + + /* Set the private information for the port to stop reading data. */ + spin_lock_irqsave(&metro_priv->lock, flags); + metro_priv->throttled = 1; + spin_unlock_irqrestore(&metro_priv->lock, flags); +} + +/* ---------------------------------------------------------------------------------------------- + Description: + Get the serial port control line states. + + Input: + struct usb_serial_port *: pointer to a usb_serial_port structure. + struct file *: pointer to a file structure. + + Output: + int: Returns the state of the control lines. +*/ +static int metrousb_tiocmget (struct tty_struct *tty) +{ + unsigned long control_state = 0; + struct usb_serial_port *port = tty->driver_data; + struct metrousb_private *metro_priv = usb_get_serial_port_data(port); + unsigned long flags = 0; + + dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + + spin_lock_irqsave(&metro_priv->lock, flags); + control_state = metro_priv->control_state; + spin_unlock_irqrestore(&metro_priv->lock, flags); + + return control_state; +} + +/* ---------------------------------------------------------------------------------------------- + Description: + Set the serial port control line states. + + Input: + struct usb_serial_port *: pointer to a usb_serial_port structure. + struct file *: pointer to a file structure. + unsigned int: line state to set. + unsigned int: line state to clear. + + Output: + int: Returns the state of the control lines. +*/ +static int metrousb_tiocmset (struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct usb_serial_port *port = tty->driver_data; + struct usb_serial *serial = port->serial; + struct metrousb_private *metro_priv = usb_get_serial_port_data(port); + unsigned long flags = 0; + unsigned long control_state = 0; + + dbg("METRO-USB - %s - port number=%d, set=%d, clear=%d", __FUNCTION__, port->number, set, clear); + + spin_lock_irqsave(&metro_priv->lock, flags); + control_state = metro_priv->control_state; + + // Set the RTS and DTR values. + if (set & TIOCM_RTS) + control_state |= TIOCM_RTS; + if (set & TIOCM_DTR) + control_state |= TIOCM_DTR; + if (clear & TIOCM_RTS) + control_state &= ~TIOCM_RTS; + if (clear & TIOCM_DTR) + control_state &= ~TIOCM_DTR; + + metro_priv->control_state = control_state; + spin_unlock_irqrestore(&metro_priv->lock, flags); + return metrousb_set_modem_ctrl(serial, control_state); +} + +/* ---------------------------------------------------------------------------------------------- + Description: + Set the serial port unthrottle to resume reading from the port. + + Input: + struct usb_serial_port *: pointer to a usb_serial_port structure. + + Output: + None: +*/ +static void metrousb_unthrottle (struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct metrousb_private *metro_priv = usb_get_serial_port_data(port); + unsigned long flags = 0; + int result = 0; + + dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + + /* Set the private information for the port to resume reading data. */ + spin_lock_irqsave(&metro_priv->lock, flags); + metro_priv->throttled = 0; + spin_unlock_irqrestore(&metro_priv->lock, flags); + + /* Submit the urb to read from the port. */ + port->interrupt_in_urb->dev = port->serial->dev; + result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); + if (result) { + dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d", + __FUNCTION__, port->number, result); + } +} + +/* Standard module function. */ +module_init(metrousb_init); +module_exit(metrousb_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR( "Philip Nicastro" ); +MODULE_AUTHOR( "Aleksey Babahin " ); +MODULE_DESCRIPTION( DRIVER_DESC ); + +/* Module input parameters */ +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Print debug info (bool 1=on, 0=off)"); + +module_param(vendor, ushort, 0); +MODULE_PARM_DESC(vendor, "User specified vendor ID (ushort)"); + +module_param(product, ushort, 0); +MODULE_PARM_DESC(product, "User specified product ID (ushort)"); + + + + diff --git a/drivers/usb/serial/metro-usb.h b/drivers/usb/serial/metro-usb.h new file mode 100644 index 000000000000..0367b6c8df07 --- /dev/null +++ b/drivers/usb/serial/metro-usb.h @@ -0,0 +1,52 @@ +/* + Date Created: 1/12/2007 + File Name: metro-usb.h + Description: metro-usb.h is the drivers header file. The driver is a USB to Serial converter. + The driver takes USB data and sends it to a virtual ttyUSB# serial port. + The driver interfaces with the usbserial.ko driver supplied by Linux. + + NOTES: + To install the driver: + 1. Install the usbserial.ko module supplied by Linux with: # insmod usbserial.ko + 2. Install the metro-usb.ko module with: # insmod metro-usb.ko vender=0x#### product=0x#### debug=1 + The vendor, product and debug parameters are optional. + + Copyright: 2007 Metrologic Instruments. All rights reserved. + Copyright: 2011 Azimut Ltd. + Requirements: Notepad.exe + + Revision History: + + Date: Developer: Revisions: + ------------------------------------------------------------------------------ + 1/12/2007 Philip Nicastro Initial release. (v1.0.0.0) + 10/07/2011 Aleksey Babahin Update for new kernel (tested on 2.6.38) + Add unidirection mode support + + +*/ + +#ifndef __LINUX_USB_SERIAL_METRO +#define __LINUX_USB_SERIAL_METRO + +/* Product information. */ +#define FOCUS_VENDOR_ID 0x0C2E +#define FOCUS_PRODUCT_ID 0x0720 +#define FOCUS_PRODUCT_ID_UNI 0x0710 + +#define METROUSB_SET_REQUEST_TYPE 0x40 +#define METROUSB_SET_MODEM_CTRL_REQUEST 10 +#define METROUSB_SET_BREAK_REQUEST 0x40 +#define METROUSB_MCR_NONE 0x8 /* Deactivate DTR and RTS. */ +#define METROUSB_MCR_RTS 0xa /* Activate RTS. */ +#define METROUSB_MCR_DTR 0x9 /* Activate DTR. */ +#define WDR_TIMEOUT 5000 /* default urb timeout. */ + +/* Private data structure. */ +struct metrousb_private { + spinlock_t lock; + int throttled; + unsigned long control_state; +}; + +#endif From 11a4f40064f38dcc369d716bea2020f6b5e290ff Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 8 Mar 2012 13:33:04 -0800 Subject: [PATCH 254/269] USB: serial: metro-usb: fix up usb_serial_register calls The usb serial core has changed how the driver is to be registered and unregistered recently. Make these changes to the driver so that it will properly build and work. Cc: Aleksey Babahin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 5b8ed50e5dda..bb6838959876 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -92,7 +92,6 @@ static struct usb_serial_driver metrousb_device = { }, .description = "Metrologic USB to serial converter.", .id_table = id_table, - .usb_driver = &metrousb_driver, .num_ports = 1, .open = metrousb_open, .close = metrousb_close, @@ -105,6 +104,11 @@ static struct usb_serial_driver metrousb_device = { .tiocmset = metrousb_tiocmset, }; +static struct usb_serial_driver * const serial_drivers[] = { + &metrousb_device, + NULL, +}; + /* ---------------------------------------------------------------------------------------------- Description: Clean up any urbs and port information. @@ -163,10 +167,7 @@ static void metrousb_close (struct usb_serial_port *port) */ static void __exit metrousb_exit(void) { - dbg("METRO-USB - %s", __FUNCTION__); - - usb_deregister(&metrousb_driver); - usb_serial_deregister(&metrousb_device); + usb_serial_deregister_drivers(&metrousb_driver, serial_drivers); } /* ---------------------------------------------------------------------------------------------- @@ -203,15 +204,10 @@ static int __init metrousb_init(void) } /* Register the devices. */ - retval = usb_serial_register(&metrousb_device); + retval = usb_serial_register_drivers(&metrousb_driver, serial_drivers); if (retval) return retval; - /* Register the driver. */ - retval = usb_register(&metrousb_driver); - if (retval) - usb_serial_deregister(&metrousb_device); - printk(KERN_INFO DRIVER_DESC " : " DRIVER_VERSION); return retval; From 62f2a83de0436d5d35eefc668e3b25db54406910 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 8 Mar 2012 13:34:01 -0800 Subject: [PATCH 255/269] USB: serial: metro-usb: add to the build This adds the metro-usb driver to the build system properly. Cc: Aleksey Babahin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 8 ++++++++ drivers/usb/serial/Makefile | 1 + 2 files changed, 9 insertions(+) diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 434df7f2a4bd..7141d6599060 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -426,6 +426,14 @@ config USB_SERIAL_MCT_U232 To compile this driver as a module, choose M here: the module will be called mct_u232. +config USB_SERIAL_METRO + tristate "USB Metrologic Instruments USB-POS Barcode Scanner Driver" + ---help--- + Say Y here if you want to use a USB POS Metrologic barcode scanner. + + To compile this driver as a module, choose M here: the + module will be called metro-usb. + config USB_SERIAL_MOS7720 tristate "USB Moschip 7720 Serial Driver" ---help--- diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 5ac438b40270..07f198ee0486 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o +obj-$(CONFIG_USB_SERIAL_METRO) += metro-usb.o obj-$(CONFIG_USB_SERIAL_MOS7720) += mos7720.o obj-$(CONFIG_USB_SERIAL_MOS7840) += mos7840.o obj-$(CONFIG_USB_SERIAL_MOTOROLA) += moto_modem.o From fdac0f647a2cf12e7152dc1d94dd08a1af4a2a82 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 8 Mar 2012 13:37:32 -0800 Subject: [PATCH 256/269] USB: serial: metro-usb: remove vendor and product module parameters All new usb serial drivers should be using the dynamic id function, not having module parameters for this type of thing. So remove them before anyone gets used to them being there. Cc: Aleksey Babahin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 35 ++-------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index bb6838959876..d0c47e1dab10 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -8,8 +8,7 @@ NOTES: To install the driver: 1. Install the usbserial.ko module supplied by Linux with: # insmod usbserial.ko - 2. Install the metro-usb.ko module with: # insmod metro-usb.ko vender=0x#### product=0x#### debug=1 - The vendor, product and debug parameters are optional. + 2. Install the metro-usb.ko module with: # insmod metro-usb.ko Some of this code is credited to Linux USB open source files that are distributed with Linux. @@ -54,15 +53,12 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID) }, { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) }, - { }, /* Optional paramenter entry. */ { }, /* Terminating entry. */ }; MODULE_DEVICE_TABLE(usb, id_table); /* Input parameter constants. */ -static int debug; -static __u16 vendor; -static __u16 product; +static bool debug; /* Function prototypes. */ static void metrousb_cleanup (struct usb_serial_port *port); @@ -183,26 +179,9 @@ static void __exit metrousb_exit(void) static int __init metrousb_init(void) { int retval = 0; - int i = 0; dbg("METRO-USB - %s", __FUNCTION__); - /* Add the device parameters if entered. */ - if ((vendor > 0) && (product > 0)) { - struct usb_device_id usb_dev_temp[] = { {USB_DEVICE(vendor, product) } }; - - /* Find the last entry in id_table */ - for (i=0; i < ARRAY_SIZE(id_table); i++) { - if (id_table[i].idVendor == 0) { - id_table[i] = usb_dev_temp[0]; - break; - } - } - - dbg("METRO-USB - %s - support added for unknown device: vendor=0x%x - product=0x%x", __FUNCTION__, vendor, product); - printk(KERN_INFO "Metro USB-POS support added for unknown device: vendor=0x%x - product=0x%x", vendor, product); - } - /* Register the devices. */ retval = usb_serial_register_drivers(&metrousb_driver, serial_drivers); if (retval) @@ -606,13 +585,3 @@ MODULE_DESCRIPTION( DRIVER_DESC ); /* Module input parameters */ module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Print debug info (bool 1=on, 0=off)"); - -module_param(vendor, ushort, 0); -MODULE_PARM_DESC(vendor, "User specified vendor ID (ushort)"); - -module_param(product, ushort, 0); -MODULE_PARM_DESC(product, "User specified product ID (ushort)"); - - - - From 1935e357bb2a3031772730293a3725e3cca07778 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 8 Mar 2012 13:39:53 -0800 Subject: [PATCH 257/269] USB: serial: metro-usb: convert to use module_usb_serial_driver Now that we aren't doing anything special in the init function, move to use the easier module_usb_serial_driver() call instead, saving a lot of lines of unnecessary code. Cc: Aleksey Babahin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 46 ++-------------------------------- 1 file changed, 2 insertions(+), 44 deletions(-) diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index d0c47e1dab10..919dd47ab46f 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -151,47 +151,6 @@ static void metrousb_close (struct usb_serial_port *port) metrousb_cleanup(port); } -/* ---------------------------------------------------------------------------------------------- - Description: - Driver exit. - - Input: - None: - - Output: - None: -*/ -static void __exit metrousb_exit(void) -{ - usb_serial_deregister_drivers(&metrousb_driver, serial_drivers); -} - -/* ---------------------------------------------------------------------------------------------- - Description: - Driver initialization. - - Input: - None: - - Output: - int: Returns true (0) if successful, false otherwise. -*/ -static int __init metrousb_init(void) -{ - int retval = 0; - - dbg("METRO-USB - %s", __FUNCTION__); - - /* Register the devices. */ - retval = usb_serial_register_drivers(&metrousb_driver, serial_drivers); - if (retval) - return retval; - - printk(KERN_INFO DRIVER_DESC " : " DRIVER_VERSION); - - return retval; -} - /* ---------------------------------------------------------------------------------------------- Description: Open the drivers serial port. @@ -574,9 +533,8 @@ static void metrousb_unthrottle (struct tty_struct *tty) } } -/* Standard module function. */ -module_init(metrousb_init); -module_exit(metrousb_exit); +module_usb_serial_driver(metrousb_driver, serial_drivers); + MODULE_LICENSE("GPL"); MODULE_AUTHOR( "Philip Nicastro" ); MODULE_AUTHOR( "Aleksey Babahin " ); From 159d4d8d5e9416dba78b84d4be10d7b1172728ee Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 8 Mar 2012 13:42:41 -0800 Subject: [PATCH 258/269] USB: serial: metro-usb: remove the .h file A driver doesn't need a .h file just for simple things like vendor ids and a private structure. So move it into the .c file instead, saving some overall lines. Cc: Aleksey Babahin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 23 +++++++++++++-- drivers/usb/serial/metro-usb.h | 52 ---------------------------------- 2 files changed, 21 insertions(+), 54 deletions(-) delete mode 100644 drivers/usb/serial/metro-usb.h diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 919dd47ab46f..d22a603597e8 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -40,15 +40,34 @@ #include #include #include -#include #include -#include "metro-usb.h" #include +#include /* Version Information */ #define DRIVER_VERSION "v1.2.0.0" #define DRIVER_DESC "Metrologic Instruments Inc. - USB-POS driver" +/* Product information. */ +#define FOCUS_VENDOR_ID 0x0C2E +#define FOCUS_PRODUCT_ID 0x0720 +#define FOCUS_PRODUCT_ID_UNI 0x0710 + +#define METROUSB_SET_REQUEST_TYPE 0x40 +#define METROUSB_SET_MODEM_CTRL_REQUEST 10 +#define METROUSB_SET_BREAK_REQUEST 0x40 +#define METROUSB_MCR_NONE 0x08 /* Deactivate DTR and RTS. */ +#define METROUSB_MCR_RTS 0x0a /* Activate RTS. */ +#define METROUSB_MCR_DTR 0x09 /* Activate DTR. */ +#define WDR_TIMEOUT 5000 /* default urb timeout. */ + +/* Private data structure. */ +struct metrousb_private { + spinlock_t lock; + int throttled; + unsigned long control_state; +}; + /* Device table list. */ static struct usb_device_id id_table [] = { { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID) }, diff --git a/drivers/usb/serial/metro-usb.h b/drivers/usb/serial/metro-usb.h deleted file mode 100644 index 0367b6c8df07..000000000000 --- a/drivers/usb/serial/metro-usb.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - Date Created: 1/12/2007 - File Name: metro-usb.h - Description: metro-usb.h is the drivers header file. The driver is a USB to Serial converter. - The driver takes USB data and sends it to a virtual ttyUSB# serial port. - The driver interfaces with the usbserial.ko driver supplied by Linux. - - NOTES: - To install the driver: - 1. Install the usbserial.ko module supplied by Linux with: # insmod usbserial.ko - 2. Install the metro-usb.ko module with: # insmod metro-usb.ko vender=0x#### product=0x#### debug=1 - The vendor, product and debug parameters are optional. - - Copyright: 2007 Metrologic Instruments. All rights reserved. - Copyright: 2011 Azimut Ltd. - Requirements: Notepad.exe - - Revision History: - - Date: Developer: Revisions: - ------------------------------------------------------------------------------ - 1/12/2007 Philip Nicastro Initial release. (v1.0.0.0) - 10/07/2011 Aleksey Babahin Update for new kernel (tested on 2.6.38) - Add unidirection mode support - - -*/ - -#ifndef __LINUX_USB_SERIAL_METRO -#define __LINUX_USB_SERIAL_METRO - -/* Product information. */ -#define FOCUS_VENDOR_ID 0x0C2E -#define FOCUS_PRODUCT_ID 0x0720 -#define FOCUS_PRODUCT_ID_UNI 0x0710 - -#define METROUSB_SET_REQUEST_TYPE 0x40 -#define METROUSB_SET_MODEM_CTRL_REQUEST 10 -#define METROUSB_SET_BREAK_REQUEST 0x40 -#define METROUSB_MCR_NONE 0x8 /* Deactivate DTR and RTS. */ -#define METROUSB_MCR_RTS 0xa /* Activate RTS. */ -#define METROUSB_MCR_DTR 0x9 /* Activate DTR. */ -#define WDR_TIMEOUT 5000 /* default urb timeout. */ - -/* Private data structure. */ -struct metrousb_private { - spinlock_t lock; - int throttled; - unsigned long control_state; -}; - -#endif From d4cbd6e990a798d21577ee2f42a3880da09edf3a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 8 Mar 2012 13:50:54 -0800 Subject: [PATCH 259/269] USB: serial: metro-usb: fix up coding style errors This fixes up all of the coding style errors, and removes the initial, unneeded comments on how to load the module and the old changelog which are no longer needed. There are still a number of coding style warnings left, I'll get to them later. Cc: Aleksey Babahin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 160 ++++++++++++++------------------- 1 file changed, 65 insertions(+), 95 deletions(-) diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index d22a603597e8..66e9355cfd00 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -1,32 +1,9 @@ /* - Date Created: 9/15/2006 - File Name: metro-usb.c - Description: metro-usb.c is the drivers main source file. The driver is a USB to Serial converter. - The driver takes USB data and sends it to a virtual ttyUSB# serial port. - The driver interfaces with the usbserial.ko driver supplied by Linux. - - NOTES: - To install the driver: - 1. Install the usbserial.ko module supplied by Linux with: # insmod usbserial.ko - 2. Install the metro-usb.ko module with: # insmod metro-usb.ko - - Some of this code is credited to Linux USB open source files that are distributed with Linux. + Some of this code is credited to Linux USB open source files that are + distributed with Linux. Copyright: 2007 Metrologic Instruments. All rights reserved. Copyright: 2011 Azimut Ltd. - Requirements: gedit.exe, notepad.exe - - Revision History: - - Date: Developer: Revisions: - ------------------------------------------------------------------------------ - 1/30/2007 Philip Nicastro Initial release. (v1.0.0.0) - 2/27/2007 Philip Nicastro Changed the metrousb_read_int_callback function to use a loop with the tty_insert_flip_char function to copy each byte to the tty layer. Removed the tty_buffer_request_room and the tty_insert_flip_string function calls. These calls were not supported on Fedora. - 2/27/2007 Philip Nicastro Released. (v1.1.0.0) - 10/07/2011 Aleksey Babahin Update for new kernel (tested on 2.6.38) - Add unidirection mode support - - */ #include @@ -41,8 +18,8 @@ #include #include #include +#include #include -#include /* Version Information */ #define DRIVER_VERSION "v1.2.0.0" @@ -59,7 +36,7 @@ #define METROUSB_MCR_NONE 0x08 /* Deactivate DTR and RTS. */ #define METROUSB_MCR_RTS 0x0a /* Activate RTS. */ #define METROUSB_MCR_DTR 0x09 /* Activate DTR. */ -#define WDR_TIMEOUT 5000 /* default urb timeout. */ +#define WDR_TIMEOUT 5000 /* default urb timeout. */ /* Private data structure. */ struct metrousb_private { @@ -69,7 +46,7 @@ struct metrousb_private { }; /* Device table list. */ -static struct usb_device_id id_table [] = { +static struct usb_device_id id_table[] = { { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID) }, { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) }, { }, /* Terminating entry. */ @@ -80,12 +57,12 @@ MODULE_DEVICE_TABLE(usb, id_table); static bool debug; /* Function prototypes. */ -static void metrousb_cleanup (struct usb_serial_port *port); -static void metrousb_close (struct usb_serial_port *port); -static int metrousb_open (struct tty_struct *tty, struct usb_serial_port *port); -static void metrousb_read_int_callback (struct urb *urb); -static void metrousb_shutdown (struct usb_serial *serial); -static int metrousb_startup (struct usb_serial *serial); +static void metrousb_cleanup(struct usb_serial_port *port); +static void metrousb_close(struct usb_serial_port *port); +static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port); +static void metrousb_read_int_callback(struct urb *urb); +static void metrousb_shutdown(struct usb_serial *serial); +static int metrousb_startup(struct usb_serial *serial); static void metrousb_throttle(struct tty_struct *tty); static int metrousb_tiocmget(struct tty_struct *tty); static int metrousb_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); @@ -105,18 +82,18 @@ static struct usb_serial_driver metrousb_device = { .owner = THIS_MODULE, .name = "metro-usb", }, - .description = "Metrologic USB to serial converter.", - .id_table = id_table, - .num_ports = 1, - .open = metrousb_open, - .close = metrousb_close, - .read_int_callback = metrousb_read_int_callback, - .attach = metrousb_startup, - .release = metrousb_shutdown, - .throttle = metrousb_throttle, - .unthrottle = metrousb_unthrottle, - .tiocmget = metrousb_tiocmget, - .tiocmset = metrousb_tiocmset, + .description = "Metrologic USB to serial converter.", + .id_table = id_table, + .num_ports = 1, + .open = metrousb_open, + .close = metrousb_close, + .read_int_callback = metrousb_read_int_callback, + .attach = metrousb_startup, + .release = metrousb_shutdown, + .throttle = metrousb_throttle, + .unthrottle = metrousb_unthrottle, + .tiocmget = metrousb_tiocmget, + .tiocmset = metrousb_tiocmset, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -134,7 +111,7 @@ static struct usb_serial_driver * const serial_drivers[] = { Output: int: Returns true (0) if successful, false otherwise. */ -static void metrousb_cleanup (struct usb_serial_port *port) +static void metrousb_cleanup(struct usb_serial_port *port) { dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); @@ -144,12 +121,6 @@ static void metrousb_cleanup (struct usb_serial_port *port) usb_unlink_urb(port->interrupt_in_urb); usb_kill_urb(port->interrupt_in_urb); } - - // temp - // this will be needed for the write urb - /* Shutdown any interrupt_out_urbs. */ - //if (serial->num_bulk_in) - // usb_kill_urb(port->read_urb); } } @@ -164,7 +135,7 @@ static void metrousb_cleanup (struct usb_serial_port *port) Output: int: Returns true (0) if successful, false otherwise. */ -static void metrousb_close (struct usb_serial_port *port) +static void metrousb_close(struct usb_serial_port *port) { dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); metrousb_cleanup(port); @@ -181,7 +152,7 @@ static void metrousb_close (struct usb_serial_port *port) Output: int: Returns true (0) if successful, false otherwise. */ -static int metrousb_open (struct tty_struct *tty, struct usb_serial_port *port) +static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) { struct usb_serial *serial = port->serial; struct metrousb_private *metro_priv = usb_get_serial_port_data(port); @@ -207,16 +178,15 @@ static int metrousb_open (struct tty_struct *tty, struct usb_serial_port *port) * through, otherwise it is scheduled, and with high data rates (like * with OHCI) data can get lost. */ - if (tty) { + if (tty) tty->low_latency = 1; - } /* Clear the urb pipe. */ usb_clear_halt(serial->dev, port->interrupt_in_urb->pipe); /* Start reading from the device */ - usb_fill_int_urb (port->interrupt_in_urb, serial->dev, - usb_rcvintpipe (serial->dev, port->interrupt_in_endpointAddress), + usb_fill_int_urb(port->interrupt_in_urb, serial->dev, + usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length, metrousb_read_int_callback, port, 1); @@ -244,7 +214,7 @@ exit: Output: None: */ -static void metrousb_read_int_callback (struct urb *urb) +static void metrousb_read_int_callback(struct urb *urb) { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct metrousb_private *metro_priv = usb_get_serial_port_data(port); @@ -257,20 +227,20 @@ static void metrousb_read_int_callback (struct urb *urb) dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); switch (urb->status) { - case 0: - /* Success status, read from the port. */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* urb has been terminated. */ - dbg("METRO-USB - %s - urb shutting down, port number=%d, error code=%d", - __FUNCTION__, port->number, result); - return; - default: - dbg("METRO-USB - %s - non-zero urb received, port number=%d, error code=%d", - __FUNCTION__, port->number, result); - goto exit; + case 0: + /* Success status, read from the port. */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* urb has been terminated. */ + dbg("METRO-USB - %s - urb shutting down, port number=%d, error code=%d", + __FUNCTION__, port->number, result); + return; + default: + dbg("METRO-USB - %s - non-zero urb received, port number=%d, error code=%d", + __FUNCTION__, port->number, result); + goto exit; } @@ -282,10 +252,10 @@ static void metrousb_read_int_callback (struct urb *urb) } if (tty && urb->actual_length) { - // Loop through the data copying each byte to the tty layer. + /* Loop through the data copying each byte to the tty layer. */ tty_insert_flip_string(tty, data, urb->actual_length); - // Force the data to the tty layer. + /* Force the data to the tty layer. */ tty_flip_buffer_push(tty); } tty_kref_put(tty); @@ -297,11 +267,11 @@ static void metrousb_read_int_callback (struct urb *urb) /* Continue trying to read if set. */ if (!throttled) { - usb_fill_int_urb (port->interrupt_in_urb, port->serial->dev, - usb_rcvintpipe (port->serial->dev, port->interrupt_in_endpointAddress), - port->interrupt_in_urb->transfer_buffer, - port->interrupt_in_urb->transfer_buffer_length, - metrousb_read_int_callback, port, 1); + usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev, + usb_rcvintpipe(port->serial->dev, port->interrupt_in_endpointAddress), + port->interrupt_in_urb->transfer_buffer, + port->interrupt_in_urb->transfer_buffer_length, + metrousb_read_int_callback, port, 1); result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); @@ -314,7 +284,7 @@ static void metrousb_read_int_callback (struct urb *urb) exit: /* Try to resubmit the urb. */ - result = usb_submit_urb (urb, GFP_ATOMIC); + result = usb_submit_urb(urb, GFP_ATOMIC); if (result) { dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d", __FUNCTION__, port->number, result); @@ -366,14 +336,14 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr Output: int: Returns true (0) if successful, false otherwise. */ -static void metrousb_shutdown (struct usb_serial *serial) +static void metrousb_shutdown(struct usb_serial *serial) { int i = 0; dbg("METRO-USB - %s", __FUNCTION__); /* Stop reading and writing on all ports. */ - for (i=0; i < serial->num_ports; ++i) { + for (i = 0; i < serial->num_ports; ++i) { /* Close any open urbs. */ metrousb_cleanup(serial->port[i]); @@ -409,12 +379,12 @@ static int metrousb_startup(struct usb_serial *serial) port = serial->port[i]; /* Declare memory. */ - metro_priv = (struct metrousb_private *) kmalloc (sizeof(struct metrousb_private), GFP_KERNEL); + metro_priv = kmalloc(sizeof(struct metrousb_private), GFP_KERNEL); if (!metro_priv) return -ENOMEM; /* Clear memory. */ - memset (metro_priv, 0x00, sizeof(struct metrousb_private)); + memset(metro_priv, 0x00, sizeof(struct metrousb_private)); /* Initialize memory. */ spin_lock_init(&metro_priv->lock); @@ -436,7 +406,7 @@ static int metrousb_startup(struct usb_serial *serial) Output: None: */ -static void metrousb_throttle (struct tty_struct *tty) +static void metrousb_throttle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct metrousb_private *metro_priv = usb_get_serial_port_data(port); @@ -461,7 +431,7 @@ static void metrousb_throttle (struct tty_struct *tty) Output: int: Returns the state of the control lines. */ -static int metrousb_tiocmget (struct tty_struct *tty) +static int metrousb_tiocmget(struct tty_struct *tty) { unsigned long control_state = 0; struct usb_serial_port *port = tty->driver_data; @@ -490,8 +460,8 @@ static int metrousb_tiocmget (struct tty_struct *tty) Output: int: Returns the state of the control lines. */ -static int metrousb_tiocmset (struct tty_struct *tty, - unsigned int set, unsigned int clear) +static int metrousb_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; @@ -504,7 +474,7 @@ static int metrousb_tiocmset (struct tty_struct *tty, spin_lock_irqsave(&metro_priv->lock, flags); control_state = metro_priv->control_state; - // Set the RTS and DTR values. + /* Set the RTS and DTR values. */ if (set & TIOCM_RTS) control_state |= TIOCM_RTS; if (set & TIOCM_DTR) @@ -529,7 +499,7 @@ static int metrousb_tiocmset (struct tty_struct *tty, Output: None: */ -static void metrousb_unthrottle (struct tty_struct *tty) +static void metrousb_unthrottle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; struct metrousb_private *metro_priv = usb_get_serial_port_data(port); @@ -555,9 +525,9 @@ static void metrousb_unthrottle (struct tty_struct *tty) module_usb_serial_driver(metrousb_driver, serial_drivers); MODULE_LICENSE("GPL"); -MODULE_AUTHOR( "Philip Nicastro" ); -MODULE_AUTHOR( "Aleksey Babahin " ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR("Philip Nicastro"); +MODULE_AUTHOR("Aleksey Babahin "); +MODULE_DESCRIPTION(DRIVER_DESC); /* Module input parameters */ module_param(debug, bool, S_IRUGO | S_IWUSR); From 9fbd1649d54edc614c64ab075f7485622fd6450a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 8 Mar 2012 13:55:41 -0800 Subject: [PATCH 260/269] USB: serial: metro-usb: remove function prototypes By rearranging the functions a bit, we can remove all function prototypes. Note, this also deleted the _close function, as it wasn't needed, it was doing the same thing the cleanup function did, so just call that instead. Cc: Aleksey Babahin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 265 +++++++++++++++------------------ 1 file changed, 118 insertions(+), 147 deletions(-) diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 66e9355cfd00..8758e01289b9 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -56,153 +56,6 @@ MODULE_DEVICE_TABLE(usb, id_table); /* Input parameter constants. */ static bool debug; -/* Function prototypes. */ -static void metrousb_cleanup(struct usb_serial_port *port); -static void metrousb_close(struct usb_serial_port *port); -static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port); -static void metrousb_read_int_callback(struct urb *urb); -static void metrousb_shutdown(struct usb_serial *serial); -static int metrousb_startup(struct usb_serial *serial); -static void metrousb_throttle(struct tty_struct *tty); -static int metrousb_tiocmget(struct tty_struct *tty); -static int metrousb_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -static void metrousb_unthrottle(struct tty_struct *tty); - -/* Driver structure. */ -static struct usb_driver metrousb_driver = { - .name = "metro-usb", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = id_table -}; - -/* Device structure. */ -static struct usb_serial_driver metrousb_device = { - .driver = { - .owner = THIS_MODULE, - .name = "metro-usb", - }, - .description = "Metrologic USB to serial converter.", - .id_table = id_table, - .num_ports = 1, - .open = metrousb_open, - .close = metrousb_close, - .read_int_callback = metrousb_read_int_callback, - .attach = metrousb_startup, - .release = metrousb_shutdown, - .throttle = metrousb_throttle, - .unthrottle = metrousb_unthrottle, - .tiocmget = metrousb_tiocmget, - .tiocmset = metrousb_tiocmset, -}; - -static struct usb_serial_driver * const serial_drivers[] = { - &metrousb_device, - NULL, -}; - -/* ---------------------------------------------------------------------------------------------- - Description: - Clean up any urbs and port information. - - Input: - struct usb_serial_port *: pointer to a usb_serial_port structure. - - Output: - int: Returns true (0) if successful, false otherwise. -*/ -static void metrousb_cleanup(struct usb_serial_port *port) -{ - dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); - - if (port->serial->dev) { - /* Shutdown any interrupt in urbs. */ - if (port->interrupt_in_urb) { - usb_unlink_urb(port->interrupt_in_urb); - usb_kill_urb(port->interrupt_in_urb); - } - } -} - -/* ---------------------------------------------------------------------------------------------- - Description: - Close the open serial port. Cleanup any open serial port information. - - Input: - struct usb_serial_port *: pointer to a usb_serial_port structure. - struct file *: pointer to a file structure. - - Output: - int: Returns true (0) if successful, false otherwise. -*/ -static void metrousb_close(struct usb_serial_port *port) -{ - dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); - metrousb_cleanup(port); -} - -/* ---------------------------------------------------------------------------------------------- - Description: - Open the drivers serial port. - - Input: - struct usb_serial_port *: pointer to a usb_serial_port structure. - struct file *: pointer to a file structure. - - Output: - int: Returns true (0) if successful, false otherwise. -*/ -static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - struct metrousb_private *metro_priv = usb_get_serial_port_data(port); - unsigned long flags = 0; - int result = 0; - - dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); - - /* Make sure the urb is initialized. */ - if (!port->interrupt_in_urb) { - dbg("METRO-USB - %s - interrupt urb not initialized for port number=%d", __FUNCTION__, port->number); - return -ENODEV; - } - - /* Set the private data information for the port. */ - spin_lock_irqsave(&metro_priv->lock, flags); - metro_priv->control_state = 0; - metro_priv->throttled = 0; - spin_unlock_irqrestore(&metro_priv->lock, flags); - - /* - * Force low_latency on so that our tty_push actually forces the data - * through, otherwise it is scheduled, and with high data rates (like - * with OHCI) data can get lost. - */ - if (tty) - tty->low_latency = 1; - - /* Clear the urb pipe. */ - usb_clear_halt(serial->dev, port->interrupt_in_urb->pipe); - - /* Start reading from the device */ - usb_fill_int_urb(port->interrupt_in_urb, serial->dev, - usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), - port->interrupt_in_urb->transfer_buffer, - port->interrupt_in_urb->transfer_buffer_length, - metrousb_read_int_callback, port, 1); - result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); - - if (result) { - dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d" - , __FUNCTION__, port->number, result); - goto exit; - } - - dbg("METRO-USB - %s - port open for port number=%d", __FUNCTION__, port->number); -exit: - return result; -} - /* ---------------------------------------------------------------------------------------------- Description: Read the port from the read interrupt. @@ -291,6 +144,91 @@ exit: } } +/* ---------------------------------------------------------------------------------------------- + Description: + Clean up any urbs and port information. + + Input: + struct usb_serial_port *: pointer to a usb_serial_port structure. + + Output: + int: Returns true (0) if successful, false otherwise. +*/ +static void metrousb_cleanup(struct usb_serial_port *port) +{ + dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + + if (port->serial->dev) { + /* Shutdown any interrupt in urbs. */ + if (port->interrupt_in_urb) { + usb_unlink_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_in_urb); + } + } +} + +/* ---------------------------------------------------------------------------------------------- + Description: + Open the drivers serial port. + + Input: + struct usb_serial_port *: pointer to a usb_serial_port structure. + struct file *: pointer to a file structure. + + Output: + int: Returns true (0) if successful, false otherwise. +*/ +static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct metrousb_private *metro_priv = usb_get_serial_port_data(port); + unsigned long flags = 0; + int result = 0; + + dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + + /* Make sure the urb is initialized. */ + if (!port->interrupt_in_urb) { + dbg("METRO-USB - %s - interrupt urb not initialized for port number=%d", __FUNCTION__, port->number); + return -ENODEV; + } + + /* Set the private data information for the port. */ + spin_lock_irqsave(&metro_priv->lock, flags); + metro_priv->control_state = 0; + metro_priv->throttled = 0; + spin_unlock_irqrestore(&metro_priv->lock, flags); + + /* + * Force low_latency on so that our tty_push actually forces the data + * through, otherwise it is scheduled, and with high data rates (like + * with OHCI) data can get lost. + */ + if (tty) + tty->low_latency = 1; + + /* Clear the urb pipe. */ + usb_clear_halt(serial->dev, port->interrupt_in_urb->pipe); + + /* Start reading from the device */ + usb_fill_int_urb(port->interrupt_in_urb, serial->dev, + usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), + port->interrupt_in_urb->transfer_buffer, + port->interrupt_in_urb->transfer_buffer_length, + metrousb_read_int_callback, port, 1); + result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + + if (result) { + dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d" + , __FUNCTION__, port->number, result); + goto exit; + } + + dbg("METRO-USB - %s - port open for port number=%d", __FUNCTION__, port->number); +exit: + return result; +} + /* ---------------------------------------------------------------------------------------------- Description: Set the modem control state for the entered serial port. @@ -522,6 +460,39 @@ static void metrousb_unthrottle(struct tty_struct *tty) } } +/* Driver structure. */ +static struct usb_driver metrousb_driver = { + .name = "metro-usb", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table +}; + +/* Device structure. */ +static struct usb_serial_driver metrousb_device = { + .driver = { + .owner = THIS_MODULE, + .name = "metro-usb", + }, + .description = "Metrologic USB to serial converter.", + .id_table = id_table, + .num_ports = 1, + .open = metrousb_open, + .close = metrousb_cleanup, + .read_int_callback = metrousb_read_int_callback, + .attach = metrousb_startup, + .release = metrousb_shutdown, + .throttle = metrousb_throttle, + .unthrottle = metrousb_unthrottle, + .tiocmget = metrousb_tiocmget, + .tiocmset = metrousb_tiocmset, +}; + +static struct usb_serial_driver * const serial_drivers[] = { + &metrousb_device, + NULL, +}; + module_usb_serial_driver(metrousb_driver, serial_drivers); MODULE_LICENSE("GPL"); From dd63b0b4d6d036e1d5f7008c97c30789415489de Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 8 Mar 2012 13:58:13 -0800 Subject: [PATCH 261/269] USB: serial: metro-usb: remove function header comments They aren't needed, make the checkpatch tool unhappy, and in some places, aren't even correct. So just remove them, they get in the way and are messy. Cc: Aleksey Babahin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 110 --------------------------------- 1 file changed, 110 deletions(-) diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 8758e01289b9..e968d3396813 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -56,17 +56,6 @@ MODULE_DEVICE_TABLE(usb, id_table); /* Input parameter constants. */ static bool debug; -/* ---------------------------------------------------------------------------------------------- - Description: - Read the port from the read interrupt. - - Input: - struct urb *: urb structure to get data. - struct pt_regs *: pt_regs structure. - - Output: - None: -*/ static void metrousb_read_int_callback(struct urb *urb) { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; @@ -144,16 +133,6 @@ exit: } } -/* ---------------------------------------------------------------------------------------------- - Description: - Clean up any urbs and port information. - - Input: - struct usb_serial_port *: pointer to a usb_serial_port structure. - - Output: - int: Returns true (0) if successful, false otherwise. -*/ static void metrousb_cleanup(struct usb_serial_port *port) { dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); @@ -167,17 +146,6 @@ static void metrousb_cleanup(struct usb_serial_port *port) } } -/* ---------------------------------------------------------------------------------------------- - Description: - Open the drivers serial port. - - Input: - struct usb_serial_port *: pointer to a usb_serial_port structure. - struct file *: pointer to a file structure. - - Output: - int: Returns true (0) if successful, false otherwise. -*/ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) { struct usb_serial *serial = port->serial; @@ -229,17 +197,6 @@ exit: return result; } -/* ---------------------------------------------------------------------------------------------- - Description: - Set the modem control state for the entered serial port. - - Input: - struct usb_serial_port *: pointer to a usb_serial_port structure. - unsigned int: control state value to set. - - Output: - int: Returns true (0) if successful, false otherwise. -*/ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int control_state) { int retval = 0; @@ -263,17 +220,6 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr return retval; } - -/* ---------------------------------------------------------------------------------------------- - Description: - Shutdown the driver. - - Input: - struct usb_serial *: pointer to a usb-serial structure. - - Output: - int: Returns true (0) if successful, false otherwise. -*/ static void metrousb_shutdown(struct usb_serial *serial) { int i = 0; @@ -293,16 +239,6 @@ static void metrousb_shutdown(struct usb_serial *serial) } } -/* ---------------------------------------------------------------------------------------------- - Description: - Startup the driver. - - Input: - struct usb_serial *: pointer to a usb-serial structure. - - Output: - int: Returns true (0) if successful, false otherwise. -*/ static int metrousb_startup(struct usb_serial *serial) { struct metrousb_private *metro_priv; @@ -334,16 +270,6 @@ static int metrousb_startup(struct usb_serial *serial) return 0; } -/* ---------------------------------------------------------------------------------------------- - Description: - Set the serial port throttle to stop reading from the port. - - Input: - struct usb_serial_port *: pointer to a usb_serial_port structure. - - Output: - None: -*/ static void metrousb_throttle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; @@ -358,17 +284,6 @@ static void metrousb_throttle(struct tty_struct *tty) spin_unlock_irqrestore(&metro_priv->lock, flags); } -/* ---------------------------------------------------------------------------------------------- - Description: - Get the serial port control line states. - - Input: - struct usb_serial_port *: pointer to a usb_serial_port structure. - struct file *: pointer to a file structure. - - Output: - int: Returns the state of the control lines. -*/ static int metrousb_tiocmget(struct tty_struct *tty) { unsigned long control_state = 0; @@ -385,19 +300,6 @@ static int metrousb_tiocmget(struct tty_struct *tty) return control_state; } -/* ---------------------------------------------------------------------------------------------- - Description: - Set the serial port control line states. - - Input: - struct usb_serial_port *: pointer to a usb_serial_port structure. - struct file *: pointer to a file structure. - unsigned int: line state to set. - unsigned int: line state to clear. - - Output: - int: Returns the state of the control lines. -*/ static int metrousb_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { @@ -427,16 +329,6 @@ static int metrousb_tiocmset(struct tty_struct *tty, return metrousb_set_modem_ctrl(serial, control_state); } -/* ---------------------------------------------------------------------------------------------- - Description: - Set the serial port unthrottle to resume reading from the port. - - Input: - struct usb_serial_port *: pointer to a usb_serial_port structure. - - Output: - None: -*/ static void metrousb_unthrottle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; @@ -460,7 +352,6 @@ static void metrousb_unthrottle(struct tty_struct *tty) } } -/* Driver structure. */ static struct usb_driver metrousb_driver = { .name = "metro-usb", .probe = usb_serial_probe, @@ -468,7 +359,6 @@ static struct usb_driver metrousb_driver = { .id_table = id_table }; -/* Device structure. */ static struct usb_serial_driver metrousb_device = { .driver = { .owner = THIS_MODULE, From 8111e4ecf9373f6d76504416b0e76b18372f3598 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 8 Mar 2012 14:00:11 -0800 Subject: [PATCH 262/269] USB: serial: metro-usb: remove unneeded cast and function call We should use kzalloc() instead of kmalloc() and memset(), and remove an unneeded void * cast as well. Cc: Aleksey Babahin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index e968d3396813..6b7d2779148c 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -58,7 +58,7 @@ static bool debug; static void metrousb_read_int_callback(struct urb *urb) { - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial_port *port = urb->context; struct metrousb_private *metro_priv = usb_get_serial_port_data(port); struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; @@ -253,13 +253,10 @@ static int metrousb_startup(struct usb_serial *serial) port = serial->port[i]; /* Declare memory. */ - metro_priv = kmalloc(sizeof(struct metrousb_private), GFP_KERNEL); + metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL); if (!metro_priv) return -ENOMEM; - /* Clear memory. */ - memset(metro_priv, 0x00, sizeof(struct metrousb_private)); - /* Initialize memory. */ spin_lock_init(&metro_priv->lock); usb_set_serial_port_data(port, metro_priv); From 5db51b50c10f3bf56d5c636832c5556ead90562d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 8 Mar 2012 14:16:12 -0800 Subject: [PATCH 263/269] USB: serial: metro-usb: move to use dev_dbg() instead of dbg() This properly ties the driver into the dynamic debug system and provides the needed device identification when the messages are printed out. It also removes a ton of checkpatch warnings as well, which is always a nice validation that it's the correct thing to do. Cc: Aleksey Babahin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 78 +++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 6b7d2779148c..6e1622f2a297 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -66,7 +66,7 @@ static void metrousb_read_int_callback(struct urb *urb) int result = 0; unsigned long flags = 0; - dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + dev_dbg(&port->dev, "%s\n", __func__); switch (urb->status) { case 0: @@ -76,12 +76,14 @@ static void metrousb_read_int_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* urb has been terminated. */ - dbg("METRO-USB - %s - urb shutting down, port number=%d, error code=%d", - __FUNCTION__, port->number, result); + dev_dbg(&port->dev, + "%s - urb shutting down, error code=%d\n", + __func__, result); return; default: - dbg("METRO-USB - %s - non-zero urb received, port number=%d, error code=%d", - __FUNCTION__, port->number, result); + dev_dbg(&port->dev, + "%s - non-zero urb received, error code=%d\n", + __func__, result); goto exit; } @@ -89,7 +91,8 @@ static void metrousb_read_int_callback(struct urb *urb) /* Set the data read from the usb port into the serial port buffer. */ tty = tty_port_tty_get(&port->port); if (!tty) { - dbg("%s - bad tty pointer - exiting", __func__); + dev_dbg(&port->dev, "%s - bad tty pointer - exiting\n", + __func__); return; } @@ -117,25 +120,25 @@ static void metrousb_read_int_callback(struct urb *urb) result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); - if (result) { - dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d", - __FUNCTION__, port->number, result); - } + if (result) + dev_dbg(&port->dev, + "%s - failed submitting interrupt in urb, error code=%d\n", + __func__, result); } return; exit: /* Try to resubmit the urb. */ result = usb_submit_urb(urb, GFP_ATOMIC); - if (result) { - dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d", - __FUNCTION__, port->number, result); - } + if (result) + dev_dbg(&port->dev, + "%s - failed submitting interrupt in urb, error code=%d\n", + __func__, result); } static void metrousb_cleanup(struct usb_serial_port *port) { - dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + dev_dbg(&port->dev, "%s\n", __func__); if (port->serial->dev) { /* Shutdown any interrupt in urbs. */ @@ -153,11 +156,12 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) unsigned long flags = 0; int result = 0; - dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + dev_dbg(&port->dev, "%s\n", __func__); /* Make sure the urb is initialized. */ if (!port->interrupt_in_urb) { - dbg("METRO-USB - %s - interrupt urb not initialized for port number=%d", __FUNCTION__, port->number); + dev_dbg(&port->dev, "%s - interrupt urb not initialized\n", + __func__); return -ENODEV; } @@ -187,12 +191,13 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (result) { - dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d" - , __FUNCTION__, port->number, result); + dev_dbg(&port->dev, + "%s - failed submitting interrupt in urb, error code=%d\n", + __func__, result); goto exit; } - dbg("METRO-USB - %s - port open for port number=%d", __FUNCTION__, port->number); + dev_dbg(&port->dev, "%s - port open\n", __func__); exit: return result; } @@ -202,7 +207,8 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr int retval = 0; unsigned char mcr = METROUSB_MCR_NONE; - dbg("METRO-USB - %s - control state=%d", __FUNCTION__, control_state); + dev_dbg(&serial->dev->dev, "%s - control state = %d\n", + __func__, control_state); /* Set the modem control value. */ if (control_state & TIOCM_DTR) @@ -215,7 +221,9 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr METROUSB_SET_REQUEST_TYPE, METROUSB_SET_MODEM_CTRL_REQUEST, control_state, 0, NULL, 0, WDR_TIMEOUT); if (retval < 0) - dbg("METRO-USB - %s - set modem ctrl=0x%x failed, error code=%d", __FUNCTION__, mcr, retval); + dev_dbg(&serial->dev->dev, + "%s - set modem ctrl=0x%x failed, error code=%d\n", + __func__, mcr, retval); return retval; } @@ -224,7 +232,7 @@ static void metrousb_shutdown(struct usb_serial *serial) { int i = 0; - dbg("METRO-USB - %s", __FUNCTION__); + dev_dbg(&serial->dev->dev, "%s\n", __func__); /* Stop reading and writing on all ports. */ for (i = 0; i < serial->num_ports; ++i) { @@ -235,7 +243,8 @@ static void metrousb_shutdown(struct usb_serial *serial) kfree(usb_get_serial_port_data(serial->port[i])); usb_set_serial_port_data(serial->port[i], NULL); - dbg("METRO-USB - %s - freed port number=%d", __FUNCTION__, serial->port[i]->number); + dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n", + __func__, serial->port[i]->number); } } @@ -245,7 +254,7 @@ static int metrousb_startup(struct usb_serial *serial) struct usb_serial_port *port; int i = 0; - dbg("METRO-USB - %s", __FUNCTION__); + dev_dbg(&serial->dev->dev, "%s\n", __func__); /* Loop through the serial ports setting up the private structures. * Currently we only use one port. */ @@ -261,7 +270,8 @@ static int metrousb_startup(struct usb_serial *serial) spin_lock_init(&metro_priv->lock); usb_set_serial_port_data(port, metro_priv); - dbg("METRO-USB - %s - port number=%d.", __FUNCTION__, port->number); + dev_dbg(&serial->dev->dev, "%s - port number=%d\n ", + __func__, port->number); } return 0; @@ -273,7 +283,7 @@ static void metrousb_throttle(struct tty_struct *tty) struct metrousb_private *metro_priv = usb_get_serial_port_data(port); unsigned long flags = 0; - dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); /* Set the private information for the port to stop reading data. */ spin_lock_irqsave(&metro_priv->lock, flags); @@ -288,7 +298,7 @@ static int metrousb_tiocmget(struct tty_struct *tty) struct metrousb_private *metro_priv = usb_get_serial_port_data(port); unsigned long flags = 0; - dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); spin_lock_irqsave(&metro_priv->lock, flags); control_state = metro_priv->control_state; @@ -306,7 +316,7 @@ static int metrousb_tiocmset(struct tty_struct *tty, unsigned long flags = 0; unsigned long control_state = 0; - dbg("METRO-USB - %s - port number=%d, set=%d, clear=%d", __FUNCTION__, port->number, set, clear); + dev_dbg(tty->dev, "%s - set=%d, clear=%d\n", __func__, set, clear); spin_lock_irqsave(&metro_priv->lock, flags); control_state = metro_priv->control_state; @@ -333,7 +343,7 @@ static void metrousb_unthrottle(struct tty_struct *tty) unsigned long flags = 0; int result = 0; - dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); /* Set the private information for the port to resume reading data. */ spin_lock_irqsave(&metro_priv->lock, flags); @@ -343,10 +353,10 @@ static void metrousb_unthrottle(struct tty_struct *tty) /* Submit the urb to read from the port. */ port->interrupt_in_urb->dev = port->serial->dev; result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); - if (result) { - dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d", - __FUNCTION__, port->number, result); - } + if (result) + dev_dbg(tty->dev, + "failed submitting interrupt in urb error code=%d\n", + result); } static struct usb_driver metrousb_driver = { From 47594d5528f28a4c025c2955c68104c75815637c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Wr=C3=B3bel?= Date: Fri, 9 Mar 2012 14:40:18 +0100 Subject: [PATCH 264/269] USB: ftdi_sio: new PID: Distortec JTAG-lock-pick MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Wróbel Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio_ids.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d8130993a922..4c53236f9baf 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -850,6 +850,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(ST_VID, ST_STMCLT1030_PID), .driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk }, { USB_DEVICE(FTDI_VID, FTDI_RF_R106) }, + { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 2a87965b7723..ae55ca8a199b 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -97,6 +97,8 @@ #define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */ #define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */ +#define FTDI_DISTORTEC_JTAG_LOCK_PICK_PID 0xCFF8 + /* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */ /* the VID is the standard ftdi vid (FTDI_VID) */ #define FTDI_SCS_DEVICE_0_PID 0xD010 /* SCS PTC-IIusb */ From 423ce8caab7ea2b13f4a29ce0839369528aafaeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Thu, 19 Jan 2012 15:37:22 +0000 Subject: [PATCH 265/269] net: usb: qmi_wwan: New driver for Huawei QMI based WWAN devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some WWAN LTE/3G devices based on chipsets from Qualcomm provide near standard CDC ECM interfaces in addition to the usual serial interfaces. The Huawei E392/E398 are examples of such devices. These typically cannot be fully configured using AT commands over a serial interface. It is necessary to speak the proprietary Qualcomm MSM Interface (QMI) protocol to the device to enable the ethernet proxy functionality. The devices embed the QMI protocol in CDC on the control interface, using standard CDC commands and notifications. The do not otherwise use CDC commands for the ethernet function. This driver does therefore not need access to any other aspects of the control interface than the descriptors attached to it. Another driver, cdc-wdm, will provide userspace access to the QMI protocol independently of this driver. To facilitate this, this driver avoids binding to the control interface, and uses only the associated data interface after parsing the common CDC functional descriptors on the control interface. You will want both the cdc-wdm and option drivers as companions to this driver, to have full access to all interfaces and protocols exported by the device. Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/Kconfig | 22 ++++ drivers/net/usb/Makefile | 1 + drivers/net/usb/qmi_wwan.c | 228 +++++++++++++++++++++++++++++++++++++ 3 files changed, 251 insertions(+) create mode 100644 drivers/net/usb/qmi_wwan.c diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 233576127934..4bad899fb38f 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -398,6 +398,27 @@ config USB_NET_KALMIA To compile this driver as a module, choose M here: the module will be called kalmia. +config USB_NET_QMI_WWAN + tristate "QMI WWAN driver for Qualcomm MSM based 3G and LTE modems" + depends on USB_USBNET + help + Support WWAN LTE/3G devices based on Qualcomm Mobile Data Modem + (MDM) chipsets. Examples of such devices are + * Huawei E392/E398 + + This driver will only drive the ethernet part of the chips. + The devices require additional configuration to be usable. + Multiple management interfaces with linux drivers are + available: + + * option: AT commands on /dev/ttyUSBx + * cdc-wdm: Qualcomm MSM Interface (QMI) protocol on /dev/cdc-wdmx + + A modem manager with support for QMI is recommended. + + To compile this driver as a module, choose M here: the + module will be called qmi_wwan. + config USB_HSO tristate "Option USB High Speed Mobile Devices" depends on USB && RFKILL @@ -461,4 +482,5 @@ config USB_VL600 http://ubuntuforums.org/showpost.php?p=10589647&postcount=17 + endmenu diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index c203fa21f6b1..a2e2d72c52a0 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -29,4 +29,5 @@ obj-$(CONFIG_USB_SIERRA_NET) += sierra_net.o obj-$(CONFIG_USB_NET_CX82310_ETH) += cx82310_eth.o obj-$(CONFIG_USB_NET_CDC_NCM) += cdc_ncm.o obj-$(CONFIG_USB_VL600) += lg-vl600.o +obj-$(CONFIG_USB_NET_QMI_WWAN) += qmi_wwan.o diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c new file mode 100644 index 000000000000..739e6de7abcb --- /dev/null +++ b/drivers/net/usb/qmi_wwan.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2012 Bjørn Mork + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* The name of the CDC Device Management driver */ +#define DM_DRIVER "cdc_wdm" + +/* + * This driver supports wwan (3G/LTE/?) devices using a vendor + * specific management protocol called Qualcomm MSM Interface (QMI) - + * in addition to the more common AT commands over serial interface + * management + * + * QMI is wrapped in CDC, using CDC encapsulated commands on the + * control ("master") interface of a two-interface CDC Union + * resembling standard CDC ECM. The devices do not use the control + * interface for any other CDC messages. Most likely because the + * management protocol is used in place of the standard CDC + * notifications NOTIFY_NETWORK_CONNECTION and NOTIFY_SPEED_CHANGE + * + * Handling a protocol like QMI is out of the scope for any driver. + * It can be exported as a character device using the cdc-wdm driver, + * which will enable userspace applications ("modem managers") to + * handle it. This may be required to use the network interface + * provided by the driver. + * + * These devices may alternatively/additionally be configured using AT + * commands on any of the serial interfaces driven by the option driver + * + * This driver binds only to the data ("slave") interface to enable + * the cdc-wdm driver to bind to the control interface. It still + * parses the CDC functional descriptors on the control interface to + * a) verify that this is indeed a handled interface (CDC Union + * header lists it as slave) + * b) get MAC address and other ethernet config from the CDC Ethernet + * header + * c) enable user bind requests against the control interface, which + * is the common way to bind to CDC Ethernet Control Model type + * interfaces + * d) provide a hint to the user about which interface is the + * corresponding management interface + */ + +static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) +{ + int status = -1; + struct usb_interface *control = NULL; + u8 *buf = intf->cur_altsetting->extra; + int len = intf->cur_altsetting->extralen; + struct usb_interface_descriptor *desc = &intf->cur_altsetting->desc; + struct usb_cdc_union_desc *cdc_union = NULL; + struct usb_cdc_ether_desc *cdc_ether = NULL; + u32 required = 1 << USB_CDC_HEADER_TYPE | 1 << USB_CDC_UNION_TYPE; + u32 found = 0; + + /* + * assume a data interface has no additional descriptors and + * that the control and data interface are numbered + * consecutively - this holds for the Huawei device at least + */ + if (len == 0 && desc->bInterfaceNumber > 0) { + control = usb_ifnum_to_if(dev->udev, desc->bInterfaceNumber - 1); + if (!control) + goto err; + + buf = control->cur_altsetting->extra; + len = control->cur_altsetting->extralen; + dev_dbg(&intf->dev, "guessing \"control\" => %s, \"data\" => this\n", + dev_name(&control->dev)); + } + + while (len > 3) { + struct usb_descriptor_header *h = (void *)buf; + + /* ignore any misplaced descriptors */ + if (h->bDescriptorType != USB_DT_CS_INTERFACE) + goto next_desc; + + /* buf[2] is CDC descriptor subtype */ + switch (buf[2]) { + case USB_CDC_HEADER_TYPE: + if (found & 1 << USB_CDC_HEADER_TYPE) { + dev_dbg(&intf->dev, "extra CDC header\n"); + goto err; + } + if (h->bLength != sizeof(struct usb_cdc_header_desc)) { + dev_dbg(&intf->dev, "CDC header len %u\n", h->bLength); + goto err; + } + break; + case USB_CDC_UNION_TYPE: + if (found & 1 << USB_CDC_UNION_TYPE) { + dev_dbg(&intf->dev, "extra CDC union\n"); + goto err; + } + if (h->bLength != sizeof(struct usb_cdc_union_desc)) { + dev_dbg(&intf->dev, "CDC union len %u\n", h->bLength); + goto err; + } + cdc_union = (struct usb_cdc_union_desc *)buf; + break; + case USB_CDC_ETHERNET_TYPE: + if (found & 1 << USB_CDC_ETHERNET_TYPE) { + dev_dbg(&intf->dev, "extra CDC ether\n"); + goto err; + } + if (h->bLength != sizeof(struct usb_cdc_ether_desc)) { + dev_dbg(&intf->dev, "CDC ether len %u\n", h->bLength); + goto err; + } + cdc_ether = (struct usb_cdc_ether_desc *)buf; + break; + } + + /* + * Remember which CDC functional descriptors we've seen. Works + * for all types we care about, of which USB_CDC_ETHERNET_TYPE + * (0x0f) is the highest numbered + */ + if (buf[2] < 32) + found |= 1 << buf[2]; + +next_desc: + len -= h->bLength; + buf += h->bLength; + } + + /* did we find all the required ones? */ + if ((found & required) != required) { + dev_err(&intf->dev, "CDC functional descriptors missing\n"); + goto err; + } + + /* give the user a helpful hint if trying to bind to the wrong interface */ + if (cdc_union && desc->bInterfaceNumber == cdc_union->bMasterInterface0) { + dev_err(&intf->dev, "leaving \"control\" interface for " DM_DRIVER " - try binding to %s instead!\n", + dev_name(&usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0)->dev)); + goto err; + } + + /* errors aren't fatal - we can live with the dynamic address */ + if (cdc_ether) { + dev->hard_mtu = le16_to_cpu(cdc_ether->wMaxSegmentSize); + usbnet_get_ethernet_addr(dev, cdc_ether->iMACAddress); + } + + /* success! point the user to the management interface */ + if (control) + dev_info(&intf->dev, "Use \"" DM_DRIVER "\" for QMI interface %s\n", + dev_name(&control->dev)); + + /* XXX: add a sysfs symlink somewhere to help management applications find it? */ + + /* collect bulk endpoints now that we know intf == "data" interface */ + status = usbnet_get_endpoints(dev, intf); + +err: + return status; +} + +/* stolen from cdc_ether.c */ +static int qmi_wwan_manage_power(struct usbnet *dev, int on) +{ + dev->intf->needs_remote_wakeup = on; + return 0; +} + +static const struct driver_info qmi_wwan_info = { + .description = "QMI speaking wwan device", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind, + .manage_power = qmi_wwan_manage_power, +}; + +#define HUAWEI_VENDOR_ID 0x12D1 + +static const struct usb_device_id products[] = { +{ + /* Huawei E392, E398 and possibly others sharing both device id and more... */ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = HUAWEI_VENDOR_ID, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 8, /* NOTE: This is the *slave* interface of the CDC Union! */ + .driver_info = (unsigned long)&qmi_wwan_info, +}, { +}, /* END */ +}; +MODULE_DEVICE_TABLE(usb, products); + +static struct usb_driver qmi_wwan_driver = { + .name = "qmi_wwan", + .id_table = products, + .probe = usbnet_probe, + .disconnect = usbnet_disconnect, + .suspend = usbnet_suspend, + .resume = usbnet_resume, + .reset_resume = usbnet_resume, + .supports_autosuspend = 1, +}; + +static int __init qmi_wwan_init(void) +{ + return usb_register(&qmi_wwan_driver); +} +module_init(qmi_wwan_init); + +static void __exit qmi_wwan_exit(void) +{ + usb_deregister(&qmi_wwan_driver); +} +module_exit(qmi_wwan_exit); + +MODULE_AUTHOR("Bjørn Mork "); +MODULE_DESCRIPTION("Qualcomm MSM Interface (QMI) WWAN driver"); +MODULE_LICENSE("GPL"); From c3ecb08abef7690c6bc2d22f099cf3ee56881a30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 9 Mar 2012 12:35:05 +0100 Subject: [PATCH 266/269] net: qmi_wwan: support devices having a shared QMI/wwan interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the new cdc-wdm subdriver interface to create a device management device even for USB devices having a single combined QMI/wwan USB interface with three endpoints (int, bulk in, bulk out) instead of separate data and control interfaces. Some Huawei devices can be switched to a single interface mode for use with other operating systems than Linux. This adds support for these devices when they run in such non-Linux modes. Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/qmi_wwan.c | 168 +++++++++++++++++++++++++++++++++---- 1 file changed, 152 insertions(+), 16 deletions(-) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 739e6de7abcb..a61c7a1aff8b 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -13,6 +13,7 @@ #include #include #include +#include /* The name of the CDC Device Management driver */ #define DM_DRIVER "cdc_wdm" @@ -64,6 +65,9 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) struct usb_cdc_ether_desc *cdc_ether = NULL; u32 required = 1 << USB_CDC_HEADER_TYPE | 1 << USB_CDC_UNION_TYPE; u32 found = 0; + atomic_t *pmcount = (void *)&dev->data[1]; + + atomic_set(pmcount, 0); /* * assume a data interface has no additional descriptors and @@ -170,13 +174,127 @@ err: return status; } -/* stolen from cdc_ether.c */ +/* using a counter to merge subdriver requests with our own into a combined state */ static int qmi_wwan_manage_power(struct usbnet *dev, int on) { - dev->intf->needs_remote_wakeup = on; - return 0; + atomic_t *pmcount = (void *)&dev->data[1]; + int rv = 0; + + dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(pmcount), on); + + if ((on && atomic_add_return(1, pmcount) == 1) || (!on && atomic_dec_and_test(pmcount))) { + /* need autopm_get/put here to ensure the usbcore sees the new value */ + rv = usb_autopm_get_interface(dev->intf); + if (rv < 0) + goto err; + dev->intf->needs_remote_wakeup = on; + usb_autopm_put_interface(dev->intf); + } +err: + return rv; } +static int qmi_wwan_cdc_wdm_manage_power(struct usb_interface *intf, int on) +{ + struct usbnet *dev = usb_get_intfdata(intf); + return qmi_wwan_manage_power(dev, on); +} + +/* Some devices combine the "control" and "data" functions into a + * single interface with all three endpoints: interrupt + bulk in and + * out + * + * Setting up cdc-wdm as a subdriver owning the interrupt endpoint + * will let it provide userspace access to the encapsulated QMI + * protocol without interfering with the usbnet operations. + */ +static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf) +{ + int rv; + struct usb_driver *subdriver = NULL; + atomic_t *pmcount = (void *)&dev->data[1]; + + atomic_set(pmcount, 0); + + /* collect all three endpoints */ + rv = usbnet_get_endpoints(dev, intf); + if (rv < 0) + goto err; + + /* require interrupt endpoint for subdriver */ + if (!dev->status) { + rv = -EINVAL; + goto err; + } + + subdriver = usb_cdc_wdm_register(intf, &dev->status->desc, 512, &qmi_wwan_cdc_wdm_manage_power); + if (IS_ERR(subdriver)) { + rv = PTR_ERR(subdriver); + goto err; + } + + /* can't let usbnet use the interrupt endpoint */ + dev->status = NULL; + + /* save subdriver struct for suspend/resume wrappers */ + dev->data[0] = (unsigned long)subdriver; + +err: + return rv; +} + +static void qmi_wwan_unbind_shared(struct usbnet *dev, struct usb_interface *intf) +{ + struct usb_driver *subdriver = (void *)dev->data[0]; + + if (subdriver && subdriver->disconnect) + subdriver->disconnect(intf); + + dev->data[0] = (unsigned long)NULL; +} + +/* suspend/resume wrappers calling both usbnet and the cdc-wdm + * subdriver if present. + * + * NOTE: cdc-wdm also supports pre/post_reset, but we cannot provide + * wrappers for those without adding usbnet reset support first. + */ +static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct usbnet *dev = usb_get_intfdata(intf); + struct usb_driver *subdriver = (void *)dev->data[0]; + int ret; + + ret = usbnet_suspend(intf, message); + if (ret < 0) + goto err; + + if (subdriver && subdriver->suspend) + ret = subdriver->suspend(intf, message); + if (ret < 0) + usbnet_resume(intf); +err: + return ret; +} + +static int qmi_wwan_resume(struct usb_interface *intf) +{ + struct usbnet *dev = usb_get_intfdata(intf); + struct usb_driver *subdriver = (void *)dev->data[0]; + int ret = 0; + + if (subdriver && subdriver->resume) + ret = subdriver->resume(intf); + if (ret < 0) + goto err; + ret = usbnet_resume(intf); + if (ret < 0 && subdriver && subdriver->resume && subdriver->suspend) + subdriver->suspend(intf, PMSG_SUSPEND); +err: + return ret; +} + + static const struct driver_info qmi_wwan_info = { .description = "QMI speaking wwan device", .flags = FLAG_WWAN, @@ -184,19 +302,37 @@ static const struct driver_info qmi_wwan_info = { .manage_power = qmi_wwan_manage_power, }; +static const struct driver_info qmi_wwan_shared = { + .description = "QMI speaking wwan device with combined interface", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind_shared, + .unbind = qmi_wwan_unbind_shared, + .manage_power = qmi_wwan_manage_power, +}; + #define HUAWEI_VENDOR_ID 0x12D1 static const struct usb_device_id products[] = { -{ - /* Huawei E392, E398 and possibly others sharing both device id and more... */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = HUAWEI_VENDOR_ID, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 8, /* NOTE: This is the *slave* interface of the CDC Union! */ - .driver_info = (unsigned long)&qmi_wwan_info, -}, { -}, /* END */ + { /* Huawei E392, E398 and possibly others sharing both device id and more... */ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = HUAWEI_VENDOR_ID, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 8, /* NOTE: This is the *slave* interface of the CDC Union! */ + .driver_info = (unsigned long)&qmi_wwan_info, + }, + { /* Huawei E392, E398 and possibly others in "Windows mode" + * using a combined control and data interface without any CDC + * functional descriptors + */ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = HUAWEI_VENDOR_ID, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 17, + .driver_info = (unsigned long)&qmi_wwan_shared, + }, + { } /* END */ }; MODULE_DEVICE_TABLE(usb, products); @@ -205,9 +341,9 @@ static struct usb_driver qmi_wwan_driver = { .id_table = products, .probe = usbnet_probe, .disconnect = usbnet_disconnect, - .suspend = usbnet_suspend, - .resume = usbnet_resume, - .reset_resume = usbnet_resume, + .suspend = qmi_wwan_suspend, + .resume = qmi_wwan_resume, + .reset_resume = qmi_wwan_resume, .supports_autosuspend = 1, }; From b086cf04fc1bfc89b306aab2fb0f67e3cc294037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 9 Mar 2012 12:35:06 +0100 Subject: [PATCH 267/269] net: qmi_wwan: add Gobi and Pantech UML290 device IDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding the Pantech UML290 and all non-QDL Gobi device IDs from the qcserial driver now that we have support for shared net/QMI USB interfaces. Most of these are not yet tested with this driver, but should be mostly identical to tested devices, except for device IDs. Gobi devices provide several different interfaces (serial/net/other) using the exact same class, subclass and protocol values. This driver will only support the net/QMI function while there are other drivers supporting other device functions. The net/QMI interface number may also differ from device to device. It has been noted that all the other interfaces have additional functional descriptors, so we use that to detect the interface supported by this driver. Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/qmi_wwan.c | 82 +++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index a61c7a1aff8b..e14479dd2438 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -243,6 +243,29 @@ err: return rv; } +/* Gobi devices uses identical class/protocol codes for all interfaces regardless + * of function. Some of these are CDC ACM like and have the exact same endpoints + * we are looking for. This leaves two possible strategies for identifying the + * correct interface: + * a) hardcoding interface number, or + * b) use the fact that the wwan interface is the only one lacking additional + * (CDC functional) descriptors + * + * Let's see if we can get away with the generic b) solution. + */ +static int qmi_wwan_bind_gobi(struct usbnet *dev, struct usb_interface *intf) +{ + int rv = -EINVAL; + + /* ignore any interface with additional descriptors */ + if (intf->cur_altsetting->extralen) + goto err; + + rv = qmi_wwan_bind_shared(dev, intf); +err: + return rv; +} + static void qmi_wwan_unbind_shared(struct usbnet *dev, struct usb_interface *intf) { struct usb_driver *subdriver = (void *)dev->data[0]; @@ -310,7 +333,18 @@ static const struct driver_info qmi_wwan_shared = { .manage_power = qmi_wwan_manage_power, }; +static const struct driver_info qmi_wwan_gobi = { + .description = "Qualcomm Gobi wwan/QMI device", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind_gobi, + .unbind = qmi_wwan_unbind_shared, + .manage_power = qmi_wwan_manage_power, +}; + #define HUAWEI_VENDOR_ID 0x12D1 +#define QMI_GOBI_DEVICE(vend, prod) \ + USB_DEVICE(vend, prod), \ + .driver_info = (unsigned long)&qmi_wwan_gobi static const struct usb_device_id products[] = { { /* Huawei E392, E398 and possibly others sharing both device id and more... */ @@ -332,7 +366,53 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 17, .driver_info = (unsigned long)&qmi_wwan_shared, }, - { } /* END */ + { /* Pantech UML290 */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x106c, + .idProduct = 0x3718, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xf0, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_shared, + }, + {QMI_GOBI_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ + {QMI_GOBI_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ + {QMI_GOBI_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ + {QMI_GOBI_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ + {QMI_GOBI_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ + {QMI_GOBI_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ + {QMI_GOBI_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ + {QMI_GOBI_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ + {QMI_GOBI_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ + {QMI_GOBI_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ + {QMI_GOBI_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ + {QMI_GOBI_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ + {QMI_GOBI_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ + {QMI_GOBI_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ + {QMI_GOBI_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */ + {QMI_GOBI_DEVICE(0x05c6, 0x920b)}, /* Generic Gobi 2000 Modem device */ + {QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */ + {QMI_GOBI_DEVICE(0x05c6, 0x9245)}, /* Samsung Gobi 2000 Modem device (VL176) */ + {QMI_GOBI_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */ + {QMI_GOBI_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */ + {QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */ + {QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */ + {QMI_GOBI_DEVICE(0x05c6, 0x9275)}, /* iRex Technologies Gobi 2000 Modem device (VR307) */ + {QMI_GOBI_DEVICE(0x1199, 0x9001)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ + {QMI_GOBI_DEVICE(0x1199, 0x9002)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ + {QMI_GOBI_DEVICE(0x1199, 0x9003)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ + {QMI_GOBI_DEVICE(0x1199, 0x9004)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ + {QMI_GOBI_DEVICE(0x1199, 0x9005)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ + {QMI_GOBI_DEVICE(0x1199, 0x9006)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ + {QMI_GOBI_DEVICE(0x1199, 0x9007)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ + {QMI_GOBI_DEVICE(0x1199, 0x9008)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ + {QMI_GOBI_DEVICE(0x1199, 0x9009)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ + {QMI_GOBI_DEVICE(0x1199, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ + {QMI_GOBI_DEVICE(0x1199, 0x9011)}, /* Sierra Wireless Gobi 2000 Modem device (MC8305) */ + {QMI_GOBI_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ + {QMI_GOBI_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ + {QMI_GOBI_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ + { } /* END */ }; MODULE_DEVICE_TABLE(usb, products); From cd4946188aac597d187a765127fd26fa3644c29f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 25 Feb 2012 11:25:58 +0100 Subject: [PATCH 268/269] driver-core: Allow additional parameters for module_driver Allow module_driver take additional parameters which will be passed to the register and unregister function calls. This allows it to be used in cases where additional parameters are required (e.g. usb_serial_register_drivers). Signed-off-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/linux/device.h b/include/linux/device.h index b63fb393aa58..bccccef520dc 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -1007,19 +1007,20 @@ extern long sysfs_deprecated; * @__driver: driver name * @__register: register function for this driver type * @__unregister: unregister function for this driver type + * @...: Additional arguments to be passed to __register and __unregister. * * Use this macro to construct bus specific macros for registering * drivers, and do not use it on its own. */ -#define module_driver(__driver, __register, __unregister) \ +#define module_driver(__driver, __register, __unregister, ...) \ static int __init __driver##_init(void) \ { \ - return __register(&(__driver)); \ + return __register(&(__driver) , ##__VA_ARGS__); \ } \ module_init(__driver##_init); \ static void __exit __driver##_exit(void) \ { \ - __unregister(&(__driver)); \ + __unregister(&(__driver) , ##__VA_ARGS__); \ } \ module_exit(__driver##_exit); From b790f5d1260b4c962bd066cd34ae982943c27fe1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 9 Mar 2012 16:38:14 -0800 Subject: [PATCH 269/269] USB: serial: use module_driver() macro Now that module_driver() can handle varargs, use it instead of rolling our own version. Cc: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/serial.h | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 7b1db841e2a8..fbb666b1b670 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -416,23 +416,10 @@ do { \ * module may only use this macro once, and calling it replaces * module_init() and module_exit() * - * Note, we can't use the generic module_driver() call here, due to the - * two parameters in the usb_serial_* functions, so we roll our own here - * :( */ #define module_usb_serial_driver(__usb_driver, __serial_drivers) \ -static int __init usb_serial_driver_init(void) \ -{ \ - return usb_serial_register_drivers(&(__usb_driver), \ - (__serial_drivers)); \ -} \ -module_init(usb_serial_driver_init); \ -static void __exit usb_serial_driver_exit(void) \ -{ \ - return usb_serial_deregister_drivers(&(__usb_driver), \ - (__serial_drivers)); \ -} \ -module_exit(usb_serial_driver_exit); + module_driver(__usb_driver, usb_serial_register_drivers, \ + usb_serial_deregister_drivers, __serial_drivers) #endif /* __LINUX_USB_SERIAL_H */