diff options
Diffstat (limited to 'drivers/usb/gadget')
25 files changed, 387 insertions, 400 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 1a556a628971..72a9797dbbae 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -13,6 +13,7 @@ #include <linux/module.h> #include <linux/device.h> #include <linux/utsname.h> +#include <linux/bitfield.h> #include <linux/usb/composite.h> #include <linux/usb/otg.h> @@ -734,47 +735,77 @@ static int bos_desc(struct usb_composite_dev *cdev) /* The SuperSpeedPlus USB Device Capability descriptor */ if (gadget_is_superspeed_plus(cdev->gadget)) { struct usb_ssp_cap_descriptor *ssp_cap; + u8 ssac = 1; + u8 ssic; + int i; - ssp_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength); - bos->bNumDeviceCaps++; + if (cdev->gadget->max_ssp_rate == USB_SSP_GEN_2x2) + ssac = 3; /* - * Report typical values. + * Paired RX and TX sublink speed attributes share + * the same SSID. */ + ssic = (ssac + 1) / 2 - 1; + + ssp_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength); + bos->bNumDeviceCaps++; - le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SSP_CAP_SIZE(1)); - ssp_cap->bLength = USB_DT_USB_SSP_CAP_SIZE(1); + le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SSP_CAP_SIZE(ssac)); + ssp_cap->bLength = USB_DT_USB_SSP_CAP_SIZE(ssac); ssp_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY; ssp_cap->bDevCapabilityType = USB_SSP_CAP_TYPE; ssp_cap->bReserved = 0; ssp_cap->wReserved = 0; - /* SSAC = 1 (2 attributes) */ - ssp_cap->bmAttributes = cpu_to_le32(1); + ssp_cap->bmAttributes = + cpu_to_le32(FIELD_PREP(USB_SSP_SUBLINK_SPEED_ATTRIBS, ssac) | + FIELD_PREP(USB_SSP_SUBLINK_SPEED_IDS, ssic)); - /* Min RX/TX Lane Count = 1 */ ssp_cap->wFunctionalitySupport = - cpu_to_le16((1 << 8) | (1 << 12)); + cpu_to_le16(FIELD_PREP(USB_SSP_MIN_SUBLINK_SPEED_ATTRIBUTE_ID, 0) | + FIELD_PREP(USB_SSP_MIN_RX_LANE_COUNT, 1) | + FIELD_PREP(USB_SSP_MIN_TX_LANE_COUNT, 1)); /* - * bmSublinkSpeedAttr[0]: - * ST = Symmetric, RX - * LSE = 3 (Gbps) - * LP = 1 (SuperSpeedPlus) - * LSM = 10 (10 Gbps) - */ - ssp_cap->bmSublinkSpeedAttr[0] = - cpu_to_le32((3 << 4) | (1 << 14) | (0xa << 16)); - /* - * bmSublinkSpeedAttr[1] = - * ST = Symmetric, TX - * LSE = 3 (Gbps) - * LP = 1 (SuperSpeedPlus) - * LSM = 10 (10 Gbps) + * Use 1 SSID if the gadget supports up to gen2x1 or not + * specified: + * - SSID 0 for symmetric RX/TX sublink speed of 10 Gbps. + * + * Use 1 SSID if the gadget supports up to gen1x2: + * - SSID 0 for symmetric RX/TX sublink speed of 5 Gbps. + * + * Use 2 SSIDs if the gadget supports up to gen2x2: + * - SSID 0 for symmetric RX/TX sublink speed of 5 Gbps. + * - SSID 1 for symmetric RX/TX sublink speed of 10 Gbps. */ - ssp_cap->bmSublinkSpeedAttr[1] = - cpu_to_le32((3 << 4) | (1 << 14) | - (0xa << 16) | (1 << 7)); + for (i = 0; i < ssac + 1; i++) { + u8 ssid; + u8 mantissa; + u8 type; + + ssid = i >> 1; + + if (cdev->gadget->max_ssp_rate == USB_SSP_GEN_2x1 || + cdev->gadget->max_ssp_rate == USB_SSP_GEN_UNKNOWN) + mantissa = 10; + else + mantissa = 5 << ssid; + + if (i % 2) + type = USB_SSP_SUBLINK_SPEED_ST_SYM_TX; + else + type = USB_SSP_SUBLINK_SPEED_ST_SYM_RX; + + ssp_cap->bmSublinkSpeedAttr[i] = + cpu_to_le32(FIELD_PREP(USB_SSP_SUBLINK_SPEED_SSID, ssid) | + FIELD_PREP(USB_SSP_SUBLINK_SPEED_LSE, + USB_SSP_SUBLINK_SPEED_LSE_GBPS) | + FIELD_PREP(USB_SSP_SUBLINK_SPEED_ST, type) | + FIELD_PREP(USB_SSP_SUBLINK_SPEED_LP, + USB_SSP_SUBLINK_SPEED_LP_SSP) | + FIELD_PREP(USB_SSP_SUBLINK_SPEED_LSM, mantissa)); + } } return le16_to_cpu(bos->wTotalLength); @@ -2042,7 +2073,7 @@ done: return value; } -void composite_disconnect(struct usb_gadget *gadget) +static void __composite_disconnect(struct usb_gadget *gadget) { struct usb_composite_dev *cdev = get_gadget_data(gadget); unsigned long flags; @@ -2059,6 +2090,23 @@ void composite_disconnect(struct usb_gadget *gadget) spin_unlock_irqrestore(&cdev->lock, flags); } +void composite_disconnect(struct usb_gadget *gadget) +{ + usb_gadget_vbus_draw(gadget, 0); + __composite_disconnect(gadget); +} + +void composite_reset(struct usb_gadget *gadget) +{ + /* + * Section 1.4.13 Standard Downstream Port of the USB battery charging + * specification v1.2 states that a device connected on a SDP shall only + * draw at max 100mA while in a connected, but unconfigured state. + */ + usb_gadget_vbus_draw(gadget, 100); + __composite_disconnect(gadget); +} + /*-------------------------------------------------------------------------*/ static ssize_t suspended_show(struct device *dev, struct device_attribute *attr, @@ -2379,7 +2427,7 @@ static const struct usb_gadget_driver composite_driver_template = { .unbind = composite_unbind, .setup = composite_setup, - .reset = composite_disconnect, + .reset = composite_reset, .disconnect = composite_disconnect, .suspend = composite_suspend, diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 36ffb43f9c1a..0d56f33d63c2 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -1488,6 +1488,28 @@ static void configfs_composite_disconnect(struct usb_gadget *gadget) spin_unlock_irqrestore(&gi->spinlock, flags); } +static void configfs_composite_reset(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev; + struct gadget_info *gi; + unsigned long flags; + + cdev = get_gadget_data(gadget); + if (!cdev) + return; + + gi = container_of(cdev, struct gadget_info, cdev); + spin_lock_irqsave(&gi->spinlock, flags); + cdev = get_gadget_data(gadget); + if (!cdev || gi->unbind) { + spin_unlock_irqrestore(&gi->spinlock, flags); + return; + } + + composite_reset(gadget); + spin_unlock_irqrestore(&gi->spinlock, flags); +} + static void configfs_composite_suspend(struct usb_gadget *gadget) { struct usb_composite_dev *cdev; @@ -1537,7 +1559,7 @@ static const struct usb_gadget_driver configfs_driver_template = { .unbind = configfs_composite_unbind, .setup = configfs_composite_setup, - .reset = configfs_composite_disconnect, + .reset = configfs_composite_reset, .disconnect = configfs_composite_disconnect, .suspend = configfs_composite_suspend, diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index 8fff995b8dd5..71a1a26e85c7 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -87,7 +87,7 @@ struct f_midi { struct snd_rawmidi_substream *out_substream[MAX_PORTS]; unsigned long out_triggered; - struct tasklet_struct tasklet; + struct work_struct work; unsigned int in_ports; unsigned int out_ports; int index; @@ -698,9 +698,11 @@ drop_out: f_midi_drop_out_substreams(midi); } -static void f_midi_in_tasklet(struct tasklet_struct *t) +static void f_midi_in_work(struct work_struct *work) { - struct f_midi *midi = from_tasklet(midi, t, tasklet); + struct f_midi *midi; + + midi = container_of(work, struct f_midi, work); f_midi_transmit(midi); } @@ -737,7 +739,7 @@ static void f_midi_in_trigger(struct snd_rawmidi_substream *substream, int up) VDBG(midi, "%s() %d\n", __func__, up); midi->in_ports_array[substream->number].active = up; if (up) - tasklet_hi_schedule(&midi->tasklet); + queue_work(system_highpri_wq, &midi->work); } static int f_midi_out_open(struct snd_rawmidi_substream *substream) @@ -875,7 +877,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f) int status, n, jack = 1, i = 0, endpoint_descriptor_index = 0; midi->gadget = cdev->gadget; - tasklet_setup(&midi->tasklet, f_midi_in_tasklet); + INIT_WORK(&midi->work, f_midi_in_work); status = f_midi_register_card(midi); if (status < 0) goto fail_register; diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 2f1eb2e81d30..61ce8e68f7a3 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -51,6 +51,8 @@ #define GET_PORT_STATUS 1 #define SOFT_RESET 2 +#define DEFAULT_Q_LEN 10 /* same as legacy g_printer gadget */ + static int major, minors; static struct class *usb_gadget_class; static DEFINE_IDA(printer_ida); @@ -1364,6 +1366,9 @@ static struct usb_function_instance *gprinter_alloc_inst(void) opts->func_inst.free_func_inst = gprinter_free_inst; ret = &opts->func_inst; + /* Make sure q_len is initialized, otherwise the bound device can't support read/write! */ + opts->q_len = DEFAULT_Q_LEN; + mutex_lock(&printer_ida_lock); if (ida_is_empty(&printer_ida)) { diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c index e6d32c536781..265c4d805f81 100644 --- a/drivers/usb/gadget/function/u_audio.c +++ b/drivers/usb/gadget/function/u_audio.c @@ -23,11 +23,6 @@ #define PRD_SIZE_MAX PAGE_SIZE #define MIN_PERIODS 4 -struct uac_req { - struct uac_rtd_params *pp; /* parent param */ - struct usb_request *req; -}; - /* Runtime data params for one stream */ struct uac_rtd_params { struct snd_uac_chip *uac; /* parent chip */ @@ -41,9 +36,8 @@ struct uac_rtd_params { void *rbuf; unsigned int max_psize; /* MaxPacketSize of endpoint */ - struct uac_req *ureq; - spinlock_t lock; + struct usb_request **reqs; }; struct snd_uac_chip { @@ -79,17 +73,20 @@ static const struct snd_pcm_hardware uac_pcm_hardware = { static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) { unsigned int pending; - unsigned long flags, flags2; unsigned int hw_ptr; int status = req->status; - struct uac_req *ur = req->context; struct snd_pcm_substream *substream; struct snd_pcm_runtime *runtime; - struct uac_rtd_params *prm = ur->pp; + struct uac_rtd_params *prm = req->context; struct snd_uac_chip *uac = prm->uac; /* i/f shutting down */ - if (!prm->ep_enabled || req->status == -ESHUTDOWN) + if (!prm->ep_enabled) { + usb_ep_free_request(ep, req); + return; + } + + if (req->status == -ESHUTDOWN) return; /* @@ -106,16 +103,14 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) if (!substream) goto exit; - snd_pcm_stream_lock_irqsave(substream, flags2); + snd_pcm_stream_lock(substream); runtime = substream->runtime; if (!runtime || !snd_pcm_running(substream)) { - snd_pcm_stream_unlock_irqrestore(substream, flags2); + snd_pcm_stream_unlock(substream); goto exit; } - spin_lock_irqsave(&prm->lock, flags); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { /* * For each IN packet, take the quotient of the current data @@ -142,8 +137,6 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) hw_ptr = prm->hw_ptr; - spin_unlock_irqrestore(&prm->lock, flags); - /* Pack USB load in ALSA ring buffer */ pending = runtime->dma_bytes - hw_ptr; @@ -167,12 +160,10 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) } } - spin_lock_irqsave(&prm->lock, flags); /* update hw_ptr after data is copied to memory */ prm->hw_ptr = (hw_ptr + req->actual) % runtime->dma_bytes; hw_ptr = prm->hw_ptr; - spin_unlock_irqrestore(&prm->lock, flags); - snd_pcm_stream_unlock_irqrestore(substream, flags2); + snd_pcm_stream_unlock(substream); if ((hw_ptr % snd_pcm_lib_period_bytes(substream)) < req->actual) snd_pcm_period_elapsed(substream); @@ -188,7 +179,6 @@ static int uac_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct uac_rtd_params *prm; struct g_audio *audio_dev; struct uac_params *params; - unsigned long flags; int err = 0; audio_dev = uac->audio_dev; @@ -199,8 +189,6 @@ static int uac_pcm_trigger(struct snd_pcm_substream *substream, int cmd) else prm = &uac->c_prm; - spin_lock_irqsave(&prm->lock, flags); - /* Reset */ prm->hw_ptr = 0; @@ -217,8 +205,6 @@ static int uac_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 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 * params->req_number); @@ -239,6 +225,25 @@ static snd_pcm_uframes_t uac_pcm_pointer(struct snd_pcm_substream *substream) return bytes_to_frames(substream->runtime, prm->hw_ptr); } +static u64 uac_ssize_to_fmt(int ssize) +{ + u64 ret; + + switch (ssize) { + case 3: + ret = SNDRV_PCM_FMTBIT_S24_3LE; + break; + case 4: + ret = SNDRV_PCM_FMTBIT_S32_LE; + break; + default: + ret = SNDRV_PCM_FMTBIT_S16_LE; + break; + } + + return ret; +} + static int uac_pcm_open(struct snd_pcm_substream *substream) { struct snd_uac_chip *uac = snd_pcm_substream_chip(substream); @@ -262,36 +267,14 @@ static int uac_pcm_open(struct snd_pcm_substream *substream) runtime->hw = uac_pcm_hardware; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - spin_lock_init(&uac->p_prm.lock); runtime->hw.rate_min = p_srate; - switch (p_ssize) { - case 3: - runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE; - break; - case 4: - runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE; - break; - default: - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; - break; - } + runtime->hw.formats = uac_ssize_to_fmt(p_ssize); runtime->hw.channels_min = num_channels(p_chmask); runtime->hw.period_bytes_min = 2 * uac->p_prm.max_psize / runtime->hw.periods_min; } else { - spin_lock_init(&uac->c_prm.lock); runtime->hw.rate_min = c_srate; - switch (c_ssize) { - case 3: - runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE; - break; - case 4: - runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE; - break; - default: - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; - break; - } + runtime->hw.formats = uac_ssize_to_fmt(c_ssize); runtime->hw.channels_min = num_channels(c_chmask); runtime->hw.period_bytes_min = 2 * uac->c_prm.max_psize / runtime->hw.periods_min; @@ -335,10 +318,16 @@ static inline void free_ep(struct uac_rtd_params *prm, struct usb_ep *ep) params = &audio_dev->params; for (i = 0; i < params->req_number; 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 (prm->reqs[i]) { + if (usb_ep_dequeue(ep, prm->reqs[i])) + usb_ep_free_request(ep, prm->reqs[i]); + /* + * If usb_ep_dequeue() cannot successfully dequeue the + * request, the request will be freed by the completion + * callback. + */ + + prm->reqs[i] = NULL; } } @@ -367,22 +356,21 @@ int u_audio_start_capture(struct g_audio *audio_dev) usb_ep_enable(ep); for (i = 0; i < params->req_number; i++) { - if (!prm->ureq[i].req) { + if (!prm->reqs[i]) { req = usb_ep_alloc_request(ep, GFP_ATOMIC); if (req == NULL) return -ENOMEM; - prm->ureq[i].req = req; - prm->ureq[i].pp = prm; + prm->reqs[i] = req; req->zero = 0; - req->context = &prm->ureq[i]; + req->context = prm; req->length = req_len; req->complete = u_audio_iso_complete; req->buf = prm->rbuf + i * ep->maxpacket; } - if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC)) + if (usb_ep_queue(ep, prm->reqs[i], GFP_ATOMIC)) dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); } @@ -445,22 +433,21 @@ int u_audio_start_playback(struct g_audio *audio_dev) usb_ep_enable(ep); for (i = 0; i < params->req_number; i++) { - if (!prm->ureq[i].req) { + if (!prm->reqs[i]) { req = usb_ep_alloc_request(ep, GFP_ATOMIC); if (req == NULL) return -ENOMEM; - prm->ureq[i].req = req; - prm->ureq[i].pp = prm; + prm->reqs[i] = req; req->zero = 0; - req->context = &prm->ureq[i]; + req->context = prm; req->length = req_len; req->complete = u_audio_iso_complete; req->buf = prm->rbuf + i * ep->maxpacket; } - if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC)) + if (usb_ep_queue(ep, prm->reqs[i], GFP_ATOMIC)) dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); } @@ -505,9 +492,10 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, uac->c_prm.uac = uac; prm->max_psize = g_audio->out_ep_maxpsize; - prm->ureq = kcalloc(params->req_number, sizeof(struct uac_req), - GFP_KERNEL); - if (!prm->ureq) { + prm->reqs = kcalloc(params->req_number, + sizeof(struct usb_request *), + GFP_KERNEL); + if (!prm->reqs) { err = -ENOMEM; goto fail; } @@ -527,9 +515,10 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, uac->p_prm.uac = uac; prm->max_psize = g_audio->in_ep_maxpsize; - prm->ureq = kcalloc(params->req_number, sizeof(struct uac_req), - GFP_KERNEL); - if (!prm->ureq) { + prm->reqs = kcalloc(params->req_number, + sizeof(struct usb_request *), + GFP_KERNEL); + if (!prm->reqs) { err = -ENOMEM; goto fail; } @@ -582,8 +571,8 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, snd_fail: snd_card_free(card); fail: - kfree(uac->p_prm.ureq); - kfree(uac->c_prm.ureq); + kfree(uac->p_prm.reqs); + kfree(uac->c_prm.reqs); kfree(uac->p_prm.rbuf); kfree(uac->c_prm.rbuf); kfree(uac); @@ -605,8 +594,8 @@ void g_audio_cleanup(struct g_audio *g_audio) if (card) snd_card_free(card); - kfree(uac->p_prm.ureq); - kfree(uac->c_prm.ureq); + kfree(uac->p_prm.reqs); + kfree(uac->c_prm.reqs); kfree(uac->p_prm.rbuf); kfree(uac->c_prm.rbuf); kfree(uac); diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index c019f2b0c0af..d1d044d9f859 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -80,6 +80,7 @@ struct eth_dev { bool zlp; bool no_skb_reserve; + bool ifname_set; u8 host_mac[ETH_ALEN]; u8 dev_mac[ETH_ALEN]; }; @@ -1004,15 +1005,45 @@ EXPORT_SYMBOL_GPL(gether_get_qmult); int gether_get_ifname(struct net_device *net, char *name, int len) { + struct eth_dev *dev = netdev_priv(net); int ret; rtnl_lock(); - ret = scnprintf(name, len, "%s\n", netdev_name(net)); + ret = scnprintf(name, len, "%s\n", + dev->ifname_set ? net->name : netdev_name(net)); rtnl_unlock(); return ret; } EXPORT_SYMBOL_GPL(gether_get_ifname); +int gether_set_ifname(struct net_device *net, const char *name, int len) +{ + struct eth_dev *dev = netdev_priv(net); + char tmp[IFNAMSIZ]; + const char *p; + + if (name[len - 1] == '\n') + len--; + + if (len >= sizeof(tmp)) + return -E2BIG; + + strscpy(tmp, name, len + 1); + if (!dev_valid_name(tmp)) + return -EINVAL; + + /* Require exactly one %d, so binding will not fail with EEXIST. */ + p = strchr(name, '%'); + if (!p || p[1] != 'd' || strchr(p + 2, '%')) + return -EINVAL; + + strncpy(net->name, tmp, sizeof(net->name)); + dev->ifname_set = true; + + return 0; +} +EXPORT_SYMBOL_GPL(gether_set_ifname); + /* * gether_cleanup - remove Ethernet-over-USB device * Context: may sleep diff --git a/drivers/usb/gadget/function/u_ether.h b/drivers/usb/gadget/function/u_ether.h index 10dd640684e2..40144546d1b0 100644 --- a/drivers/usb/gadget/function/u_ether.h +++ b/drivers/usb/gadget/function/u_ether.h @@ -244,6 +244,18 @@ unsigned gether_get_qmult(struct net_device *net); */ int gether_get_ifname(struct net_device *net, char *name, int len); +/** + * gether_set_ifname - set an ethernet-over-usb link interface name + * @net: device representing this link + * @name: new interface name + * @len: length of @name + * + * This sets the interface name of this ethernet-over-usb link. + * A single terminating newline, if any, is ignored. + * Returns zero on success, else negative errno. + */ +int gether_set_ifname(struct net_device *net, const char *name, int len); + void gether_cleanup(struct eth_dev *dev); /* connect/disconnect is handled by individual functions */ diff --git a/drivers/usb/gadget/function/u_ether_configfs.h b/drivers/usb/gadget/function/u_ether_configfs.h index bd92b5703013..3dfb460908fa 100644 --- a/drivers/usb/gadget/function/u_ether_configfs.h +++ b/drivers/usb/gadget/function/u_ether_configfs.h @@ -148,7 +148,20 @@ out: \ return ret; \ } \ \ - CONFIGFS_ATTR_RO(_f_##_opts_, ifname) + static ssize_t _f_##_opts_ifname_store(struct config_item *item, \ + const char *page, size_t len)\ + { \ + struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ + int ret = -EBUSY; \ + \ + mutex_lock(&opts->lock); \ + if (!opts->refcnt) \ + ret = gether_set_ifname(opts->net, page, len); \ + mutex_unlock(&opts->lock); \ + return ret ?: len; \ + } \ + \ + CONFIGFS_ATTR(_f_##_opts_, ifname) #define USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(_f_, _n_) \ static ssize_t _f_##_opts_##_n_##_show(struct config_item *item,\ diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index 2caccbb6e014..1e59204ec7aa 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -258,9 +258,7 @@ __acquires(&port->port_lock) list_del(&req->list); req->zero = kfifo_is_empty(&port->port_write_buf); - pr_vdebug("ttyGS%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n", - port->port_num, len, *((u8 *)req->buf), - *((u8 *)req->buf+1), *((u8 *)req->buf+2)); + pr_vdebug("ttyGS%d: tx len=%d, %3ph ...\n", port->port_num, len, req->buf); /* Drop lock while we call out of driver; completions * could be issued while we do so. Disconnection may @@ -346,7 +344,7 @@ __acquires(&port->port_lock) } /* - * RX tasklet takes data out of the RX queue and hands it up to the TTY + * RX work takes data out of the RX queue and hands it up to the TTY * layer until it refuses to take any more data (or is throttled back). * Then it issues reads for any further data. * @@ -709,7 +707,7 @@ raced_with_open: /* Iff we're disconnected, there can be no I/O in flight so it's * ok to free the circular buffer; else just scrub it. And don't - * let the push tasklet fire again until we're re-opened. + * let the push async work fire again until we're re-opened. */ if (gser == NULL) kfifo_free(&port->port_write_buf); diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig index f02c38b32a2b..11dd6e8adc8a 100644 --- a/drivers/usb/gadget/legacy/Kconfig +++ b/drivers/usb/gadget/legacy/Kconfig @@ -515,10 +515,15 @@ config USB_G_WEBCAM config USB_RAW_GADGET tristate "USB Raw Gadget" help - USB Raw Gadget is a kernel module that provides a userspace interface - for the USB Gadget subsystem. Essentially it allows to emulate USB - devices from userspace. See Documentation/usb/raw-gadget.rst for - details. + USB Raw Gadget is a gadget driver that gives userspace low-level + control over the gadget's communication process. + + Like any other gadget driver, Raw Gadget implements USB devices via + the USB gadget API. Unlike most gadget drivers, Raw Gadget does not + implement any concrete USB functions itself but requires userspace + to do that. + + See Documentation/usb/raw-gadget.rst for details. Say "y" to link the driver statically, or "m" to build a dynamically linked module called "raw_gadget". diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c index 062dfac30399..c5a2c734234a 100644 --- a/drivers/usb/gadget/legacy/raw_gadget.c +++ b/drivers/usb/gadget/legacy/raw_gadget.c @@ -3,7 +3,8 @@ * USB Raw Gadget driver. * See Documentation/usb/raw-gadget.rst for more details. * - * Andrey Konovalov <andreyknvl@gmail.com> + * Copyright (c) 2020 Google, Inc. + * Author: Andrey Konovalov <andreyknvl@gmail.com> */ #include <linux/compiler.h> diff --git a/drivers/usb/gadget/udc/bdc/Kconfig b/drivers/usb/gadget/udc/bdc/Kconfig index fb01ff47b64c..8bedb7f64eba 100644 --- a/drivers/usb/gadget/udc/bdc/Kconfig +++ b/drivers/usb/gadget/udc/bdc/Kconfig @@ -11,14 +11,3 @@ config USB_BDC_UDC Say "y" here to link the driver statically, or "m" to build a dynamically linked module called "bdc". - -if USB_BDC_UDC - -comment "Platform Support" -config USB_BDC_PCI - tristate "BDC support for PCIe based platforms" - depends on USB_PCI && BROKEN - default USB_BDC_UDC - help - Enable support for platforms which have BDC connected through PCIe, such as Lego3 FPGA platform. -endif diff --git a/drivers/usb/gadget/udc/bdc/Makefile b/drivers/usb/gadget/udc/bdc/Makefile index 52cb5ea48bbe..1b21c9518efc 100644 --- a/drivers/usb/gadget/udc/bdc/Makefile +++ b/drivers/usb/gadget/udc/bdc/Makefile @@ -5,5 +5,3 @@ bdc-y := bdc_core.o bdc_cmd.o bdc_ep.o bdc_udc.o ifneq ($(CONFIG_USB_GADGET_VERBOSE),) bdc-y += bdc_dbg.o endif - -obj-$(CONFIG_USB_BDC_PCI) += bdc_pci.o diff --git a/drivers/usb/gadget/udc/bdc/bdc.h b/drivers/usb/gadget/udc/bdc/bdc.h index ac75e25c3b6a..8d00b1239f21 100644 --- a/drivers/usb/gadget/udc/bdc/bdc.h +++ b/drivers/usb/gadget/udc/bdc/bdc.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * bdc.h - header for the BRCM BDC USB3.0 device controller * @@ -35,7 +35,7 @@ /* * Maximum size of ep0 response buffer for ch9 requests, * the set_sel request uses 6 so far, the max. -*/ + */ #define EP0_RESPONSE_BUFF 6 /* Start with SS as default */ #define EP0_MAX_PKT_SIZE 512 @@ -86,23 +86,23 @@ #define BDC_EPSTS5 0x74 #define BDC_EPSTS6 0x78 #define BDC_EPSTS7 0x7c -#define BDC_SRRBAL(n) (0x200 + (n * 0x10)) -#define BDC_SRRBAH(n) (0x204 + (n * 0x10)) -#define BDC_SRRINT(n) (0x208 + (n * 0x10)) -#define BDC_INTCTLS(n) (0x20c + (n * 0x10)) +#define BDC_SRRBAL(n) (0x200 + ((n) * 0x10)) +#define BDC_SRRBAH(n) (0x204 + ((n) * 0x10)) +#define BDC_SRRINT(n) (0x208 + ((n) * 0x10)) +#define BDC_INTCTLS(n) (0x20c + ((n) * 0x10)) /* Extended capability regs */ #define BDC_FSCNOC 0xcd4 #define BDC_FSCNIC 0xce4 -#define NUM_NCS(p) (p >> 28) +#define NUM_NCS(p) ((p) >> 28) /* Register bit fields and Masks */ /* BDC Configuration 0 */ #define BDC_PGS(p) (((p) & (0x7 << 8)) >> 8) -#define BDC_SPB(p) (p & 0x7) +#define BDC_SPB(p) ((p) & 0x7) /* BDC Capability1 */ -#define BDC_P64 (1 << 0) +#define BDC_P64 BIT(0) /* BDC Command register */ #define BDC_CMD_FH 0xe @@ -111,9 +111,9 @@ #define BDC_CMD_BLA 0x3 #define BDC_CMD_EPC 0x2 #define BDC_CMD_DVC 0x1 -#define BDC_CMD_CWS (0x1 << 5) +#define BDC_CMD_CWS BIT(5) #define BDC_CMD_CST(p) (((p) & (0xf << 6))>>6) -#define BDC_CMD_EPN(p) ((p & 0x1f) << 10) +#define BDC_CMD_EPN(p) (((p) & 0x1f) << 10) #define BDC_SUB_CMD_ADD (0x1 << 17) #define BDC_SUB_CMD_FWK (0x4 << 17) /* Reset sequence number */ @@ -124,7 +124,7 @@ #define BDC_SUB_CMD_EP_STP (0x2 << 17) #define BDC_SUB_CMD_EP_STL (0x4 << 17) #define BDC_SUB_CMD_EP_RST (0x1 << 17) -#define BDC_CMD_SRD (1 << 27) +#define BDC_CMD_SRD BIT(27) /* CMD completion status */ #define BDC_CMDS_SUCC 0x1 @@ -141,19 +141,19 @@ #define EPM_SHIFT 4 /* BDC USPSC */ -#define BDC_VBC (1 << 31) -#define BDC_PRC (1 << 30) -#define BDC_PCE (1 << 29) -#define BDC_CFC (1 << 28) -#define BDC_PCC (1 << 27) -#define BDC_PSC (1 << 26) -#define BDC_VBS (1 << 25) -#define BDC_PRS (1 << 24) -#define BDC_PCS (1 << 23) +#define BDC_VBC BIT(31) +#define BDC_PRC BIT(30) +#define BDC_PCE BIT(29) +#define BDC_CFC BIT(28) +#define BDC_PCC BIT(27) +#define BDC_PSC BIT(26) +#define BDC_VBS BIT(25) +#define BDC_PRS BIT(24) +#define BDC_PCS BIT(23) #define BDC_PSP(p) (((p) & (0x7 << 20))>>20) -#define BDC_SCN (1 << 8) -#define BDC_SDC (1 << 7) -#define BDC_SWS (1 << 4) +#define BDC_SCN BIT(8) +#define BDC_SDC BIT(7) +#define BDC_SWS BIT(4) #define BDC_USPSC_RW (BDC_SCN|BDC_SDC|BDC_SWS|0xf) #define BDC_PSP(p) (((p) & (0x7 << 20))>>20) @@ -163,21 +163,21 @@ #define BDC_SPEED_HS 0x3 #define BDC_SPEED_SS 0x4 -#define BDC_PST(p) (p & 0xf) +#define BDC_PST(p) ((p) & 0xf) #define BDC_PST_MASK 0xf /* USPPMS */ -#define BDC_U2E (0x1 << 31) -#define BDC_U1E (0x1 << 30) -#define BDC_U2A (0x1 << 29) -#define BDC_PORT_W1S (0x1 << 17) +#define BDC_U2E BIT(31) +#define BDC_U1E BIT(30) +#define BDC_U2A BIT(29) +#define BDC_PORT_W1S BIT(17) #define BDC_U1T(p) ((p) & 0xff) #define BDC_U2T(p) (((p) & 0xff) << 8) #define BDC_U1T_MASK 0xff /* USBPM2 */ /* Hardware LPM Enable */ -#define BDC_HLE (1 << 16) +#define BDC_HLE BIT(16) /* BDC Status and Control */ #define BDC_COP_RST (1 << 29) @@ -186,11 +186,11 @@ #define BDC_COP_MASK (BDC_COP_RST|BDC_COP_RUN|BDC_COP_STP) -#define BDC_COS (1 << 28) +#define BDC_COS BIT(28) #define BDC_CSTS(p) (((p) & (0x7 << 20)) >> 20) -#define BDC_MASK_MCW (1 << 7) -#define BDC_GIE (1 << 1) -#define BDC_GIP (1 << 0) +#define BDC_MASK_MCW BIT(7) +#define BDC_GIE BIT(1) +#define BDC_GIP BIT(0) #define BDC_HLT 1 #define BDC_NOR 2 @@ -201,19 +201,19 @@ #define BD_CHAIN 0xf #define BD_TFS_SHIFT 4 -#define BD_SOT (1 << 26) -#define BD_EOT (1 << 27) -#define BD_ISP (1 << 29) -#define BD_IOC (1 << 30) -#define BD_SBF (1 << 31) +#define BD_SOT BIT(26) +#define BD_EOT BIT(27) +#define BD_ISP BIT(29) +#define BD_IOC BIT(30) +#define BD_SBF BIT(31) #define BD_INTR_TARGET(p) (((p) & 0x1f) << 27) -#define BDC_SRR_RWS (1 << 4) -#define BDC_SRR_RST (1 << 3) -#define BDC_SRR_ISR (1 << 2) -#define BDC_SRR_IE (1 << 1) -#define BDC_SRR_IP (1 << 0) +#define BDC_SRR_RWS BIT(4) +#define BDC_SRR_RST BIT(3) +#define BDC_SRR_ISR BIT(2) +#define BDC_SRR_IE BIT(1) +#define BDC_SRR_IP BIT(0) #define BDC_SRR_EPI(p) (((p) & (0xff << 24)) >> 24) #define BDC_SRR_DPI(p) (((p) & (0xff << 16)) >> 16) #define BDC_SRR_DPI_MASK 0x00ff0000 @@ -221,14 +221,14 @@ #define MARK_CHAIN_BD (BD_CHAIN|BD_EOT|BD_SOT) /* Control transfer BD specific fields */ -#define BD_DIR_IN (1 << 25) +#define BD_DIR_IN BIT(25) #define BDC_PTC_MASK 0xf0000000 /* status report defines */ #define SR_XSF 0 #define SR_USPC 4 -#define SR_BD_LEN(p) (p & 0xffffff) +#define SR_BD_LEN(p) ((p) & 0xffffff) #define XSF_SUCC 0x1 #define XSF_SHORT 0x3 @@ -241,13 +241,13 @@ /* Transfer BD fields */ #define BD_LEN(p) ((p) & 0x1ffff) -#define BD_LTF (1 << 25) +#define BD_LTF BIT(25) #define BD_TYPE_DS 0x1 #define BD_TYPE_SS 0x2 -#define BDC_EP_ENABLED (1 << 0) -#define BDC_EP_STALL (1 << 1) -#define BDC_EP_STOP (1 << 2) +#define BDC_EP_ENABLED BIT(0) +#define BDC_EP_STALL BIT(1) +#define BDC_EP_STOP BIT(2) /* One BD can transfer max 65536 bytes */ #define BD_MAX_BUFF_SIZE (1 << 16) @@ -266,9 +266,9 @@ /* FUNCTION WAKE DEV NOTIFICATION interval, USB3 spec table 8.13 */ #define BDC_TNOTIFY 2500 /*in ms*/ /* Devstatus bitfields */ -#define REMOTE_WAKEUP_ISSUED (1 << 16) -#define DEVICE_SUSPENDED (1 << 17) -#define FUNC_WAKE_ISSUED (1 << 18) +#define REMOTE_WAKEUP_ISSUED BIT(16) +#define DEVICE_SUSPENDED BIT(17) +#define FUNC_WAKE_ISSUED BIT(18) #define REMOTE_WAKE_ENABLE (1 << USB_DEVICE_REMOTE_WAKEUP) /* On disconnect, preserve these bits and clear rest */ @@ -466,24 +466,24 @@ static inline void bdc_writel(void __iomem *base, u32 offset, u32 value) } /* Buffer descriptor list operations */ -void bdc_notify_xfr(struct bdc *, u32); -void bdc_softconn(struct bdc *); -void bdc_softdisconn(struct bdc *); -int bdc_run(struct bdc *); -int bdc_stop(struct bdc *); -int bdc_reset(struct bdc *); -int bdc_udc_init(struct bdc *); -void bdc_udc_exit(struct bdc *); -int bdc_reinit(struct bdc *); +void bdc_notify_xfr(struct bdc *bdc, u32 epnum); +void bdc_softconn(struct bdc *bdc); +void bdc_softdisconn(struct bdc *bdc); +int bdc_run(struct bdc *bdc); +int bdc_stop(struct bdc *bdc); +int bdc_reset(struct bdc *bdc); +int bdc_udc_init(struct bdc *bdc); +void bdc_udc_exit(struct bdc *bdc); +int bdc_reinit(struct bdc *bdc); /* Status report handlers */ /* Upstream port status change sr */ -void bdc_sr_uspc(struct bdc *, struct bdc_sr *); +void bdc_sr_uspc(struct bdc *bdc, struct bdc_sr *sreport); /* transfer sr */ -void bdc_sr_xsf(struct bdc *, struct bdc_sr *); +void bdc_sr_xsf(struct bdc *bdc, struct bdc_sr *sreport); /* EP0 XSF handlers */ -void bdc_xsf_ep0_setup_recv(struct bdc *, struct bdc_sr *); -void bdc_xsf_ep0_data_start(struct bdc *, struct bdc_sr *); -void bdc_xsf_ep0_status_start(struct bdc *, struct bdc_sr *); +void bdc_xsf_ep0_setup_recv(struct bdc *bdc, struct bdc_sr *sreport); +void bdc_xsf_ep0_data_start(struct bdc *bdc, struct bdc_sr *sreport); +void bdc_xsf_ep0_status_start(struct bdc *bdc, struct bdc_sr *sreport); #endif /* __LINUX_BDC_H__ */ diff --git a/drivers/usb/gadget/udc/bdc/bdc_cmd.c b/drivers/usb/gadget/udc/bdc/bdc_cmd.c index 44c2a5eef785..995f79c79f96 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_cmd.c +++ b/drivers/usb/gadget/udc/bdc/bdc_cmd.c @@ -163,7 +163,7 @@ int bdc_config_ep(struct bdc *bdc, struct bdc_ep *ep) usb_endpoint_xfer_isoc(desc)) { param2 |= si; if (usb_endpoint_xfer_isoc(desc) && comp_desc) - mul = comp_desc->bmAttributes; + mul = comp_desc->bmAttributes; } param2 |= mul << EPM_SHIFT; diff --git a/drivers/usb/gadget/udc/bdc/bdc_cmd.h b/drivers/usb/gadget/udc/bdc/bdc_cmd.h index 29cc988a671a..533ad52fa6d0 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_cmd.h +++ b/drivers/usb/gadget/udc/bdc/bdc_cmd.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * bdc_cmd.h - header for the BDC debug functions * @@ -10,15 +10,14 @@ #define __LINUX_BDC_CMD_H__ /* Command operations */ -int bdc_address_device(struct bdc *, u32); -int bdc_config_ep(struct bdc *, struct bdc_ep *); -int bdc_dconfig_ep(struct bdc *, struct bdc_ep *); -int bdc_stop_ep(struct bdc *, int); -int bdc_ep_set_stall(struct bdc *, int); -int bdc_ep_clear_stall(struct bdc *, int); -int bdc_ep_set_halt(struct bdc_ep *, u32 , int); -int bdc_ep_bla(struct bdc *, struct bdc_ep *, dma_addr_t); -int bdc_function_wake(struct bdc*, u8); -int bdc_function_wake_fh(struct bdc*, u8); +int bdc_address_device(struct bdc *bdc, u32 add); +int bdc_config_ep(struct bdc *bdc, struct bdc_ep *ep); +int bdc_dconfig_ep(struct bdc *bdc, struct bdc_ep *ep); +int bdc_stop_ep(struct bdc *bdc, int epnum); +int bdc_ep_set_stall(struct bdc *bdc, int epnum); +int bdc_ep_clear_stall(struct bdc *bdc, int epnum); +int bdc_ep_bla(struct bdc *bdc, struct bdc_ep *ep, dma_addr_t dma_addr); +int bdc_function_wake(struct bdc *bdc, u8 intf); +int bdc_function_wake_fh(struct bdc *bdc, u8 intf); #endif /* __LINUX_BDC_CMD_H__ */ diff --git a/drivers/usb/gadget/udc/bdc/bdc_dbg.c b/drivers/usb/gadget/udc/bdc/bdc_dbg.c index 7ba7448ad743..9c03e13308ca 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_dbg.c +++ b/drivers/usb/gadget/udc/bdc/bdc_dbg.c @@ -68,7 +68,7 @@ void bdc_dbg_srr(struct bdc *bdc, u32 srr_num) sr = bdc->srr.sr_bds; addr = bdc->srr.dma_addr; - dev_vdbg(bdc->dev, "bdc_dbg_srr sr:%p dqp_index:%d\n", + dev_vdbg(bdc->dev, "%s sr:%p dqp_index:%d\n", __func__, sr, bdc->srr.dqp_index); for (i = 0; i < NUM_SR_ENTRIES; i++) { sr = &bdc->srr.sr_bds[i]; diff --git a/drivers/usb/gadget/udc/bdc/bdc_dbg.h b/drivers/usb/gadget/udc/bdc/bdc_dbg.h index 373d5abffbb8..acd8332f8584 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_dbg.h +++ b/drivers/usb/gadget/udc/bdc/bdc_dbg.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * bdc_dbg.h - header for the BDC debug functions * @@ -12,10 +12,10 @@ #include "bdc.h" #ifdef CONFIG_USB_GADGET_VERBOSE -void bdc_dbg_bd_list(struct bdc *, struct bdc_ep*); -void bdc_dbg_srr(struct bdc *, u32); -void bdc_dbg_regs(struct bdc *); -void bdc_dump_epsts(struct bdc *); +void bdc_dbg_bd_list(struct bdc *bdc, struct bdc_ep *ep); +void bdc_dbg_srr(struct bdc *bdc, u32 srr_num); +void bdc_dbg_regs(struct bdc *bdc); +void bdc_dump_epsts(struct bdc *bdc); #else static inline void bdc_dbg_regs(struct bdc *bdc) { } diff --git a/drivers/usb/gadget/udc/bdc/bdc_ep.c b/drivers/usb/gadget/udc/bdc/bdc_ep.c index fafdc9fdb4a5..8e2f20b12519 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_ep.c +++ b/drivers/usb/gadget/udc/bdc/bdc_ep.c @@ -68,7 +68,7 @@ static void ep_bd_list_free(struct bdc_ep *ep, u32 num_tabs) * check if the bd_table struct is allocated ? * if yes, then check if bd memory has been allocated, then * free the dma_pool and also the bd_table struct memory - */ + */ bd_table = bd_list->bd_table_array[index]; dev_dbg(bdc->dev, "bd_table:%p index:%d\n", bd_table, index); if (!bd_table) { @@ -147,7 +147,7 @@ static int ep_bd_list_alloc(struct bdc_ep *ep) /* Allocate memory for each table */ for (index = 0; index < num_tabs; index++) { /* Allocate memory for bd_table structure */ - bd_table = kzalloc(sizeof(struct bd_table), GFP_ATOMIC); + bd_table = kzalloc(sizeof(*bd_table), GFP_ATOMIC); if (!bd_table) goto fail; @@ -275,7 +275,7 @@ static inline int find_end_bdi(struct bdc_ep *ep, int next_hwd_bdi) end_bdi = next_hwd_bdi - 1; if (end_bdi < 0) end_bdi = ep->bd_list.max_bdi - 1; - else if ((end_bdi % (ep->bd_list.num_bds_table-1)) == 0) + else if ((end_bdi % (ep->bd_list.num_bds_table-1)) == 0) end_bdi--; return end_bdi; @@ -756,7 +756,7 @@ static int ep_dequeue(struct bdc_ep *ep, struct bdc_req *req) dev_dbg(bdc->dev, "%s ep:%s start:%d end:%d\n", __func__, ep->name, start_bdi, end_bdi); - dev_dbg(bdc->dev, "ep_dequeue ep=%p ep->desc=%p\n", + dev_dbg(bdc->dev, "%s ep=%p ep->desc=%p\n", __func__, ep, (void *)ep->usb_ep.desc); /* if still connected, stop the ep to see where the HW is ? */ if (!(bdc_readl(bdc->regs, BDC_USPC) & BDC_PST_MASK)) { @@ -795,7 +795,7 @@ static int ep_dequeue(struct bdc_ep *ep, struct bdc_req *req) start_pending = true; end_pending = true; } else if (end_bdi >= curr_hw_dqpi || end_bdi <= eqp_bdi) { - end_pending = true; + end_pending = true; } } else { if (start_bdi >= curr_hw_dqpi) { @@ -1405,7 +1405,7 @@ static int ep0_set_sel(struct bdc *bdc, } /* - * Queue a 0 byte bd only if wLength is more than the length and and length is + * Queue a 0 byte bd only if wLength is more than the length and length is * a multiple of MaxPacket then queue 0 byte BD */ static int ep0_queue_zlp(struct bdc *bdc) @@ -1858,12 +1858,12 @@ static int bdc_gadget_ep_enable(struct usb_ep *_ep, int ret; if (!_ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT) { - pr_debug("bdc_gadget_ep_enable invalid parameters\n"); + pr_debug("%s invalid parameters\n", __func__); return -EINVAL; } if (!desc->wMaxPacketSize) { - pr_debug("bdc_gadget_ep_enable missing wMaxPacketSize\n"); + pr_debug("%s missing wMaxPacketSize\n", __func__); return -EINVAL; } diff --git a/drivers/usb/gadget/udc/bdc/bdc_ep.h b/drivers/usb/gadget/udc/bdc/bdc_ep.h index a37ff8033b4f..4d3affd07a65 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_ep.h +++ b/drivers/usb/gadget/udc/bdc/bdc_ep.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * bdc_ep.h - header for the BDC debug functions * @@ -9,9 +9,9 @@ #ifndef __LINUX_BDC_EP_H__ #define __LINUX_BDC_EP_H__ -int bdc_init_ep(struct bdc *); -int bdc_ep_disable(struct bdc_ep *); -int bdc_ep_enable(struct bdc_ep *); -void bdc_free_ep(struct bdc *); +int bdc_init_ep(struct bdc *bdc); +int bdc_ep_disable(struct bdc_ep *ep); +int bdc_ep_enable(struct bdc_ep *ep); +void bdc_free_ep(struct bdc *bdc); #endif /* __LINUX_BDC_EP_H__ */ diff --git a/drivers/usb/gadget/udc/bdc/bdc_pci.c b/drivers/usb/gadget/udc/bdc/bdc_pci.c deleted file mode 100644 index 6dbc489513cd..000000000000 --- a/drivers/usb/gadget/udc/bdc/bdc_pci.c +++ /dev/null @@ -1,128 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * bdc_pci.c - BRCM BDC USB3.0 device controller PCI interface file. - * - * Copyright (C) 2014 Broadcom Corporation - * - * Author: Ashwini Pahuja - * - * Based on drivers under drivers/usb/ - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/pci.h> -#include <linux/pci_ids.h> -#include <linux/platform_device.h> - -#include "bdc.h" - -#define BDC_PCI_PID 0x1570 - -struct bdc_pci { - struct device *dev; - struct platform_device *bdc; -}; - -static int bdc_setup_msi(struct pci_dev *pci) -{ - int ret; - - ret = pci_enable_msi(pci); - if (ret) { - pr_err("failed to allocate MSI entry\n"); - return ret; - } - - return ret; -} - -static int bdc_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) -{ - struct resource res[2]; - struct platform_device *bdc; - struct bdc_pci *glue; - int ret = -ENOMEM; - - glue = devm_kzalloc(&pci->dev, sizeof(*glue), GFP_KERNEL); - if (!glue) - return -ENOMEM; - - glue->dev = &pci->dev; - ret = pci_enable_device(pci); - if (ret) { - dev_err(&pci->dev, "failed to enable pci device\n"); - return -ENODEV; - } - pci_set_master(pci); - - bdc = platform_device_alloc(BRCM_BDC_NAME, PLATFORM_DEVID_AUTO); - if (!bdc) - return -ENOMEM; - - memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); - bdc_setup_msi(pci); - - res[0].start = pci_resource_start(pci, 0); - res[0].end = pci_resource_end(pci, 0); - res[0].name = BRCM_BDC_NAME; - res[0].flags = IORESOURCE_MEM; - - res[1].start = pci->irq; - res[1].name = BRCM_BDC_NAME; - res[1].flags = IORESOURCE_IRQ; - - ret = platform_device_add_resources(bdc, res, ARRAY_SIZE(res)); - if (ret) { - dev_err(&pci->dev, - "couldn't add resources to bdc device\n"); - platform_device_put(bdc); - return ret; - } - - pci_set_drvdata(pci, glue); - - dma_set_coherent_mask(&bdc->dev, pci->dev.coherent_dma_mask); - - bdc->dev.dma_mask = pci->dev.dma_mask; - bdc->dev.dma_parms = pci->dev.dma_parms; - bdc->dev.parent = &pci->dev; - glue->bdc = bdc; - - ret = platform_device_add(bdc); - if (ret) { - dev_err(&pci->dev, "failed to register bdc device\n"); - platform_device_put(bdc); - return ret; - } - - return 0; -} - -static void bdc_pci_remove(struct pci_dev *pci) -{ - struct bdc_pci *glue = pci_get_drvdata(pci); - - platform_device_unregister(glue->bdc); - pci_disable_msi(pci); -} - -static struct pci_device_id bdc_pci_id_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, BDC_PCI_PID), }, - {} /* Terminating Entry */ -}; - -MODULE_DEVICE_TABLE(pci, bdc_pci_id_table); - -static struct pci_driver bdc_pci_driver = { - .name = "bdc-pci", - .id_table = bdc_pci_id_table, - .probe = bdc_pci_probe, - .remove = bdc_pci_remove, -}; - -MODULE_AUTHOR("Ashwini Pahuja <ashwini.linux@gmail.com>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("BRCM BDC USB3 PCI Glue layer"); -module_pci_driver(bdc_pci_driver); diff --git a/drivers/usb/gadget/udc/bdc/bdc_udc.c b/drivers/usb/gadget/udc/bdc/bdc_udc.c index 248426a3e88a..5ac0ef88334e 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_udc.c +++ b/drivers/usb/gadget/udc/bdc/bdc_udc.c @@ -164,7 +164,7 @@ static void bdc_func_wake_timer(struct work_struct *work) /* * Check if host has started transferring on endpoints * FUNC_WAKE_ISSUED is cleared when transfer has started after resume - */ + */ if (bdc->devstatus & FUNC_WAKE_ISSUED) { dev_dbg(bdc->dev, "FUNC_WAKE_ISSUED FLAG IS STILL SET\n"); /* flag is still set, so again send func wake */ @@ -205,7 +205,7 @@ static void handle_link_state_change(struct bdc *bdc, u32 uspc) * if not then send function wake again every * TNotification secs until host initiates * transfer to BDC, USB3 spec Table 8.13 - */ + */ schedule_delayed_work( &bdc->func_wake_notify, msecs_to_jiffies(BDC_TNOTIFY)); @@ -379,7 +379,7 @@ static int bdc_udc_start(struct usb_gadget *gadget, * Run the controller from here and when BDC is connected to * Host then driver will receive a USPC SR with VBUS present * and then driver will do a softconnect. - */ + */ ret = bdc_run(bdc); if (ret) { dev_err(bdc->dev, "%s bdc run fail\n", __func__); @@ -530,7 +530,7 @@ int bdc_udc_init(struct bdc *bdc) bdc->gadget.name = BRCM_BDC_NAME; ret = devm_request_irq(bdc->dev, bdc->irq, bdc_udc_interrupt, - IRQF_SHARED , BRCM_BDC_NAME, bdc); + IRQF_SHARED, BRCM_BDC_NAME, bdc); if (ret) { dev_err(bdc->dev, "failed to request irq #%d %d\n", diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index ea114f922ccf..493ff93f7dda 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -29,6 +29,7 @@ * @list: for use by the udc class driver * @vbus: for udcs who care about vbus status, this value is real vbus status; * for udcs who do not care about vbus status, this value is always true + * @started: the UDC's started state. True if the UDC had started. * * This represents the internal data structure which is used by the UDC-class * to hold information about udc driver and gadget together. @@ -39,6 +40,7 @@ struct usb_udc { struct device dev; struct list_head list; bool vbus; + bool started; }; static struct class *udc_class; @@ -1082,7 +1084,18 @@ EXPORT_SYMBOL_GPL(usb_gadget_udc_reset); */ static inline int usb_gadget_udc_start(struct usb_udc *udc) { - return udc->gadget->ops->udc_start(udc->gadget, udc->driver); + int ret; + + if (udc->started) { + dev_err(&udc->dev, "UDC had already started\n"); + return -EBUSY; + } + + ret = udc->gadget->ops->udc_start(udc->gadget, udc->driver); + if (!ret) + udc->started = true; + + return ret; } /** @@ -1098,7 +1111,13 @@ static inline int usb_gadget_udc_start(struct usb_udc *udc) */ static inline void usb_gadget_udc_stop(struct usb_udc *udc) { + if (!udc->started) { + dev_err(&udc->dev, "UDC had already stopped\n"); + return; + } + udc->gadget->ops->udc_stop(udc->gadget); + udc->started = false; } /** @@ -1114,12 +1133,18 @@ static inline void usb_gadget_udc_stop(struct usb_udc *udc) static inline void usb_gadget_udc_set_speed(struct usb_udc *udc, enum usb_device_speed speed) { - if (udc->gadget->ops->udc_set_speed) { - enum usb_device_speed s; + struct usb_gadget *gadget = udc->gadget; + enum usb_device_speed s; - s = min(speed, udc->gadget->max_speed); - udc->gadget->ops->udc_set_speed(udc->gadget, s); - } + if (speed == USB_SPEED_UNKNOWN) + s = gadget->max_speed; + else + s = min(speed, gadget->max_speed); + + if (s == USB_SPEED_SUPER_PLUS && gadget->ops->udc_set_ssp_rate) + gadget->ops->udc_set_ssp_rate(gadget, gadget->max_ssp_rate); + else if (gadget->ops->udc_set_speed) + gadget->ops->udc_set_speed(gadget, s); } /** @@ -1222,6 +1247,8 @@ int usb_add_gadget(struct usb_gadget *gadget) udc->gadget = gadget; gadget->udc = udc; + udc->started = false; + mutex_lock(&udc_lock); list_add_tail(&udc->list, &udc_list); diff --git a/drivers/usb/gadget/udc/snps_udc_core.c b/drivers/usb/gadget/udc/snps_udc_core.c index 6c726d2e1788..d046c09fa566 100644 --- a/drivers/usb/gadget/udc/snps_udc_core.c +++ b/drivers/usb/gadget/udc/snps_udc_core.c @@ -36,7 +36,6 @@ #include <asm/unaligned.h> #include "amd5536udc.h" -static void udc_tasklet_disconnect(unsigned long); static void udc_setup_endpoints(struct udc *dev); static void udc_soft_reset(struct udc *dev); static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep); @@ -95,9 +94,6 @@ static struct timer_list udc_pollstall_timer; static int stop_pollstall_timer; static DECLARE_COMPLETION(on_pollstall_exit); -/* tasklet for usb disconnect */ -static DECLARE_TASKLET_OLD(disconnect_tasklet, udc_tasklet_disconnect); - /* endpoint names used for print */ static const char ep0_string[] = "ep0in"; static const struct { @@ -1637,6 +1633,8 @@ static void usb_connect(struct udc *dev) */ static void usb_disconnect(struct udc *dev) { + u32 tmp; + /* Return if already disconnected */ if (!dev->connected) return; @@ -1648,23 +1646,6 @@ static void usb_disconnect(struct udc *dev) /* mask interrupts */ udc_mask_unused_interrupts(dev); - /* REVISIT there doesn't seem to be a point to having this - * talk to a tasklet ... do it directly, we already hold - * the spinlock needed to process the disconnect. - */ - - tasklet_schedule(&disconnect_tasklet); -} - -/* Tasklet for disconnect to be outside of interrupt context */ -static void udc_tasklet_disconnect(unsigned long par) -{ - struct udc *dev = udc; - u32 tmp; - - DBG(dev, "Tasklet disconnect\n"); - spin_lock_irq(&dev->lock); - if (dev->driver) { spin_unlock(&dev->lock); dev->driver->disconnect(&dev->gadget); @@ -1673,13 +1654,10 @@ static void udc_tasklet_disconnect(unsigned long par) /* empty queues */ for (tmp = 0; tmp < UDC_EP_NUM; tmp++) empty_req_queue(&dev->ep[tmp]); - } /* disable ep0 */ - ep_init(dev->regs, - &dev->ep[UDC_EP0IN_IX]); - + ep_init(dev->regs, &dev->ep[UDC_EP0IN_IX]); if (!soft_reset_occured) { /* init controller by soft reset */ @@ -1695,8 +1673,6 @@ static void udc_tasklet_disconnect(unsigned long par) tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD); writel(tmp, &dev->regs->cfg); } - - spin_unlock_irq(&dev->lock); } /* Reset the UDC core */ diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c index d5e9d20c097d..72f2ea062d55 100644 --- a/drivers/usb/gadget/udc/udc-xilinx.c +++ b/drivers/usb/gadget/udc/udc-xilinx.c @@ -843,8 +843,8 @@ static int __xudc_ep_enable(struct xusb_ep *ep, break; } - ep->buffer0ready = 0; - ep->buffer1ready = 0; + ep->buffer0ready = false; + ep->buffer1ready = false; ep->curbufnum = 0; ep->rambase = rambase[ep->epnumber]; xudc_epconfig(ep, udc); @@ -868,11 +868,11 @@ static int __xudc_ep_enable(struct xusb_ep *ep, if (ep->epnumber && !ep->is_in) { udc->write_fn(udc->addr, XUSB_BUFFREADY_OFFSET, 1 << ep->epnumber); - ep->buffer0ready = 1; + ep->buffer0ready = true; udc->write_fn(udc->addr, XUSB_BUFFREADY_OFFSET, (1 << (ep->epnumber + XUSB_STATUS_EP_BUFF2_SHIFT))); - ep->buffer1ready = 1; + ep->buffer1ready = true; } return 0; @@ -1954,7 +1954,7 @@ static void xudc_nonctrl_ep_handler(struct xusb_udc *udc, u8 epnum, if (intrstatus & (XUSB_STATUS_EP0_BUFF1_COMP_MASK << epnum)) ep->buffer0ready = 0; if (intrstatus & (XUSB_STATUS_EP0_BUFF2_COMP_MASK << epnum)) - ep->buffer1ready = 0; + ep->buffer1ready = false; if (list_empty(&ep->queue)) return; |