diff options
Diffstat (limited to 'drivers/usb')
53 files changed, 383 insertions, 446 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index e4b27413f528..94573fb68304 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -74,7 +74,7 @@ config USB After choosing your HCD, then select drivers for the USB peripherals you'll be using. You may want to check out the information provided in <file:Documentation/usb/> and especially the links given in - <file:Documentation/usb/usb-help.txt>. + <file:Documentation/usb/usb-help.rst>. To compile this driver as a module, choose M here: the module will be called usbcore. diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 829e947cabf5..6a5ee8e6da10 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1622,6 +1622,25 @@ static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on) static int ci_udc_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver); static int ci_udc_stop(struct usb_gadget *gadget); + +/* Match ISOC IN from the highest endpoint */ +static struct usb_ep *ci_udc_match_ep(struct usb_gadget *gadget, + struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *comp_desc) +{ + struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); + struct usb_ep *ep; + + if (usb_endpoint_xfer_isoc(desc) && usb_endpoint_dir_in(desc)) { + list_for_each_entry_reverse(ep, &ci->gadget.ep_list, ep_list) { + if (ep->caps.dir_in && !ep->claimed) + return ep; + } + } + + return NULL; +} + /** * Device operations part of the API to the USB controller hardware, * which don't involve endpoints (or i/o) @@ -1635,6 +1654,7 @@ static const struct usb_gadget_ops usb_gadget_ops = { .vbus_draw = ci_udc_vbus_draw, .udc_start = ci_udc_start, .udc_stop = ci_udc_stop, + .match_ep = ci_udc_match_ep, }; static int init_eps(struct ci_hdrc *ci) diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig index 52f3a531a82f..f8a798900093 100644 --- a/drivers/usb/class/Kconfig +++ b/drivers/usb/class/Kconfig @@ -10,7 +10,7 @@ config USB_ACM ---help--- This driver supports USB modems and ISDN adapters which support the Communication Device Class Abstract Control Model interface. - Please read <file:Documentation/usb/acm.txt> for details. + Please read <file:Documentation/usb/acm.rst> for details. If your modem only reports "Cls=ff(vend.)" in the descriptors in /sys/kernel/debug/usb/devices, then your modem will not work with this diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index aa17dab6c4ea..a951ce69f10e 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -48,9 +48,6 @@ #define USB_DEVICE_MAX (USB_MAXBUS * 128) #define USB_SG_SIZE 16384 /* split-size for large txs */ -/* Mutual exclusion for removal, open, and release */ -DEFINE_MUTEX(usbfs_mutex); - struct usb_dev_state { struct list_head list; /* state list */ struct usb_device *dev; @@ -979,15 +976,9 @@ static int usbdev_open(struct inode *inode, struct file *file) ret = -ENODEV; - /* Protect against simultaneous removal or release */ - mutex_lock(&usbfs_mutex); - /* usbdev device-node */ if (imajor(inode) == USB_DEVICE_MAJOR) dev = usbdev_lookup_by_devt(inode->i_rdev); - - mutex_unlock(&usbfs_mutex); - if (!dev) goto out_free_ps; @@ -1308,6 +1299,39 @@ static int proc_connectinfo(struct usb_dev_state *ps, void __user *arg) return 0; } +static int proc_conninfo_ex(struct usb_dev_state *ps, + void __user *arg, size_t size) +{ + struct usbdevfs_conninfo_ex ci; + struct usb_device *udev = ps->dev; + + if (size < sizeof(ci.size)) + return -EINVAL; + + memset(&ci, 0, sizeof(ci)); + ci.size = sizeof(ci); + ci.busnum = udev->bus->busnum; + ci.devnum = udev->devnum; + ci.speed = udev->speed; + + while (udev && udev->portnum != 0) { + if (++ci.num_ports <= ARRAY_SIZE(ci.ports)) + ci.ports[ARRAY_SIZE(ci.ports) - ci.num_ports] = + udev->portnum; + udev = udev->parent; + } + + if (ci.num_ports < ARRAY_SIZE(ci.ports)) + memmove(&ci.ports[0], + &ci.ports[ARRAY_SIZE(ci.ports) - ci.num_ports], + ci.num_ports); + + if (copy_to_user(arg, &ci, min(sizeof(ci), size))) + return -EFAULT; + + return 0; +} + static int proc_resetdevice(struct usb_dev_state *ps) { struct usb_host_config *actconfig = ps->dev->actconfig; @@ -1486,15 +1510,15 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb ret = -EFAULT; goto error; } - if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) { + if (uurb->buffer_length < (le16_to_cpu(dr->wLength) + 8)) { ret = -EINVAL; goto error; } ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest, - le16_to_cpup(&dr->wIndex)); + le16_to_cpu(dr->wIndex)); if (ret) goto error; - uurb->buffer_length = le16_to_cpup(&dr->wLength); + uurb->buffer_length = le16_to_cpu(dr->wLength); uurb->buffer += 8; if ((dr->bRequestType & USB_DIR_IN) && uurb->buffer_length) { is_in = 1; @@ -1509,9 +1533,9 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb "bRequest=%02x wValue=%04x " "wIndex=%04x wLength=%04x\n", dr->bRequestType, dr->bRequest, - __le16_to_cpup(&dr->wValue), - __le16_to_cpup(&dr->wIndex), - __le16_to_cpup(&dr->wLength)); + __le16_to_cpu(dr->wValue), + __le16_to_cpu(dr->wIndex), + __le16_to_cpu(dr->wLength)); u = sizeof(struct usb_ctrlrequest); break; @@ -2250,7 +2274,7 @@ static int proc_get_capabilities(struct usb_dev_state *ps, void __user *arg) caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM | USBDEVFS_CAP_REAP_AFTER_DISCONNECT | USBDEVFS_CAP_MMAP | - USBDEVFS_CAP_DROP_PRIVILEGES; + USBDEVFS_CAP_DROP_PRIVILEGES | USBDEVFS_CAP_CONNINFO_EX; if (!ps->dev->bus->no_stop_on_short) caps |= USBDEVFS_CAP_BULK_CONTINUATION; if (ps->dev->bus->sg_tablesize) @@ -2549,6 +2573,13 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, break; } + /* Handle variable-length commands */ + switch (cmd & ~IOCSIZE_MASK) { + case USBDEVFS_CONNINFO_EX(0): + ret = proc_conninfo_ex(ps, p, _IOC_SIZE(cmd)); + break; + } + done: usb_unlock_device(dev); if (ret >= 0) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 82cc3766cb23..a59e1573b43b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2721,7 +2721,7 @@ static bool use_new_scheme(struct usb_device *udev, int retry, } /* Is a USB 3.0 port in the Inactive or Compliance Mode state? - * Port worm reset is required to recover + * Port warm reset is required to recover */ static bool hub_port_warm_reset_required(struct usb_hub *hub, int port1, u16 portstatus) diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c index ab474b11523e..e6143663778f 100644 --- a/drivers/usb/core/notify.c +++ b/drivers/usb/core/notify.c @@ -53,11 +53,8 @@ void usb_notify_add_device(struct usb_device *udev) void usb_notify_remove_device(struct usb_device *udev) { - /* Protect against simultaneous usbfs open */ - mutex_lock(&usbfs_mutex); blocking_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev); - mutex_unlock(&usbfs_mutex); } void usb_notify_add_bus(struct usb_bus *ubus) diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index d95a5358f73d..bd8d01f85a13 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -169,7 +169,6 @@ extern const struct attribute_group *usb_device_groups[]; extern const struct attribute_group *usb_interface_groups[]; /* usbfs stuff */ -extern struct mutex usbfs_mutex; extern struct usb_driver usbfs_driver; extern const struct file_operations usbfs_devices_fops; extern const struct file_operations usbdev_file_operations; diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 9ece4affb9d4..55f841a54015 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -254,6 +254,15 @@ static void dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg) val = (hsotg->hw_params.utmi_phy_data_width == GHWCFG4_UTMI_PHY_DATA_WIDTH_8) ? 8 : 16; + if (hsotg->phy) { + /* + * If using the generic PHY framework, check if the PHY bus + * width is 8-bit and set the phyif appropriately. + */ + if (phy_get_bus_width(hsotg->phy) == 8) + val = 8; + } + hsotg->params.phy_utmi_width = val; } diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 3e6c3c8a32ff..80fd3c6dcd1c 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -271,15 +271,6 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) hsotg->plat = dev_get_platdata(hsotg->dev); - if (hsotg->phy) { - /* - * If using the generic PHY framework, check if the PHY bus - * width is 8-bit and set the phyif appropriately. - */ - if (phy_get_bus_width(hsotg->phy) == 8) - hsotg->params.phy_utmi_width = 8; - } - /* Clock */ hsotg->clk = devm_clk_get_optional(hsotg->dev, "otg"); if (IS_ERR(hsotg->clk)) { diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index ec189d7855a0..02ff850278b1 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -228,7 +228,7 @@ config USB_CONFIGFS specified simply by creating appropriate directories in configfs. Associating functions with configurations is done by creating appropriate symbolic links. - For more information see Documentation/usb/gadget_configfs.txt. + For more information see Documentation/usb/gadget_configfs.rst. config USB_CONFIGFS_SERIAL bool "Generic serial bulk in/out" @@ -441,7 +441,7 @@ config USB_CONFIGFS_F_HID The HID function driver provides generic emulation of USB Human Interface Devices (HID). - For more information, see Documentation/usb/gadget_hid.txt. + For more information, see Documentation/usb/gadget_hid.rst. config USB_CONFIGFS_F_UVC bool "USB Webcam function" @@ -466,7 +466,7 @@ config USB_CONFIGFS_F_PRINTER receive or send printer data. It can use ioctl calls to the device file to get or set printer status. - For more information, see Documentation/usb/gadget_printer.txt + For more information, see Documentation/usb/gadget_printer.rst which includes sample code for accessing the device file. config USB_CONFIGFS_F_TCM diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 982c3e89eb0d..b1fba3132427 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -47,7 +47,7 @@ * * For more information about MSF and in particular its module * parameters and sysfs interface read the - * <Documentation/usb/mass-storage.txt> file. + * <Documentation/usb/mass-storage.rst> file. */ /* diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig index 94fc3c462930..69ff7f8c86f5 100644 --- a/drivers/usb/gadget/legacy/Kconfig +++ b/drivers/usb/gadget/legacy/Kconfig @@ -287,7 +287,7 @@ config USB_G_SERIAL Say "y" to link the driver statically, or "m" to build a dynamically linked module called "g_serial". - For more information, see Documentation/usb/gadget_serial.txt + For more information, see Documentation/usb/gadget_serial.rst which includes instructions and a "driver info file" needed to make MS-Windows work with CDC ACM. @@ -321,7 +321,7 @@ config USB_G_PRINTER Say "y" to link the driver statically, or "m" to build a dynamically linked module called "g_printer". - For more information, see Documentation/usb/gadget_printer.txt + For more information, see Documentation/usb/gadget_printer.rst which includes sample code for accessing the device file. if TTY @@ -436,7 +436,7 @@ config USB_G_HID The HID gadget driver provides generic emulation of USB Human Interface Devices (HID). - For more information, see Documentation/usb/gadget_hid.txt which + For more information, see Documentation/usb/gadget_hid.rst which includes sample code for accessing the device files. Say "y" to link the driver statically, or "m" to build a diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index fb3406ea8592..40b5de597112 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -114,7 +114,7 @@ config USB_EHCI_HCD Controller Driver or UHCI (for Via motherboards) Host Controller Driver too. - You may want to read <file:Documentation/usb/ehci.txt>. + You may want to read <file:Documentation/usb/ehci.rst>. To compile this driver as a module, choose M here: the module will be called ehci-hcd. diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 0da68df259c8..e835a22b12af 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -10,6 +10,7 @@ * Most of code borrowed from the Linux-3.7 EHCI driver */ #include <linux/module.h> +#include <linux/of.h> #include <linux/device.h> #include <linux/dmapool.h> #include <linux/kernel.h> @@ -5669,9 +5670,18 @@ static int fotg210_hcd_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id fotg210_of_match[] = { + { .compatible = "faraday,fotg210" }, + {}, +}; +MODULE_DEVICE_TABLE(of, fotg210_of_match); +#endif + static struct platform_driver fotg210_hcd_driver = { .driver = { .name = "fotg210-hcd", + .of_match_table = of_match_ptr(fotg210_of_match), }, .probe = fotg210_hcd_probe, .remove = fotg210_hcd_remove, diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h index 650240846ee2..4c49688a069d 100644 --- a/drivers/usb/host/isp1362.h +++ b/drivers/usb/host/isp1362.h @@ -11,7 +11,7 @@ #define USE_32BIT 0 -/* These options are mutually eclusive */ +/* These options are mutually exclusive */ #define USE_PLATFORM_DELAY 0 #define USE_NDELAY 0 diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index a52fd96e70e9..9741cdeea9d7 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1619,8 +1619,13 @@ static void handle_port_status(struct xhci_hcd *xhci, usb_hcd_resume_root_hub(hcd); } - if (hcd->speed >= HCD_USB3 && (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) + if (hcd->speed >= HCD_USB3 && + (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) { + slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1); + if (slot_id && xhci->devs[slot_id]) + xhci->devs[slot_id]->flags |= VDEV_PORT_ERROR; bus_state->port_remote_wakeup &= ~(1 << hcd_portnum); + } if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) { xhci_dbg(xhci, "port resume event for port %d\n", port_id); @@ -1825,6 +1830,14 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci, { struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index]; struct xhci_command *command; + + /* + * Avoid resetting endpoint if link is inactive. Can cause host hang. + * Device will be reset soon to recover the link so don't do anything + */ + if (xhci->devs[slot_id]->flags & VDEV_PORT_ERROR) + return; + command = xhci_alloc_command(xhci, false, GFP_ATOMIC); if (!command) return; diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index 294158113d62..dafc65911fc0 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -354,29 +354,6 @@ enum tegra_xusb_mbox_cmd { MBOX_CMD_NAK }; -static const char * const mbox_cmd_name[] = { - [ 1] = "MSG_ENABLE", - [ 2] = "INC_FALCON_CLOCK", - [ 3] = "DEC_FALCON_CLOCK", - [ 4] = "INC_SSPI_CLOCK", - [ 5] = "DEC_SSPI_CLOCK", - [ 6] = "SET_BW", - [ 7] = "SET_SS_PWR_GATING", - [ 8] = "SET_SS_PWR_UNGATING", - [ 9] = "SAVE_DFE_CTLE_CTX", - [ 10] = "AIRPLANE_MODE_ENABLED", - [ 11] = "AIRPLANE_MODE_DISABLED", - [ 12] = "START_HSIC_IDLE", - [ 13] = "STOP_HSIC_IDLE", - [ 14] = "DBC_WAKE_STACK", - [ 15] = "HSIC_PRETEND_CONNECT", - [ 16] = "RESET_SSPI", - [ 17] = "DISABLE_SS_LFPS_DETECTION", - [ 18] = "ENABLE_SS_LFPS_DETECTION", - [128] = "ACK", - [129] = "NAK", -}; - struct tegra_xusb_mbox_msg { u32 cmd; u32 data; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index ef5702a45067..248cd7a8b163 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1466,6 +1466,10 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag xhci_dbg(xhci, "urb submitted during PCI suspend\n"); return -ESHUTDOWN; } + if (xhci->devs[slot_id]->flags & VDEV_PORT_ERROR) { + xhci_dbg(xhci, "Can't queue urb, port error, link inactive\n"); + return -ENODEV; + } if (usb_endpoint_xfer_isoc(&urb->ep->desc)) num_tds = urb->number_of_packets; @@ -3754,6 +3758,7 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd, } /* If necessary, update the number of active TTs on this root port */ xhci_update_tt_active_eps(xhci, virt_dev, old_active_eps); + virt_dev->flags = 0; ret = 0; command_cleanup: @@ -5062,16 +5067,26 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) } else { /* * Some 3.1 hosts return sbrn 0x30, use xhci supported protocol - * minor revision instead of sbrn + * minor revision instead of sbrn. Minor revision is a two digit + * BCD containing minor and sub-minor numbers, only show minor. */ - minor_rev = xhci->usb3_rhub.min_rev; - if (minor_rev) { + minor_rev = xhci->usb3_rhub.min_rev / 0x10; + + switch (minor_rev) { + case 2: + hcd->speed = HCD_USB32; + hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; + hcd->self.root_hub->rx_lanes = 2; + hcd->self.root_hub->tx_lanes = 2; + break; + case 1: hcd->speed = HCD_USB31; hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; + break; } - xhci_info(xhci, "Host supports USB 3.%x %s SuperSpeed\n", + xhci_info(xhci, "Host supports USB 3.%x %sSuperSpeed\n", minor_rev, - minor_rev ? "Enhanced" : ""); + minor_rev ? "Enhanced " : ""); xhci->usb3_rhub.hcd = hcd; /* xHCI private pointer was set in xhci_pci_probe for the second diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 34789f4db555..7a264962a1a9 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1012,6 +1012,15 @@ struct xhci_virt_device { u8 real_port; struct xhci_interval_bw_table *bw_table; struct xhci_tt_bw_info *tt_info; + /* + * flags for state tracking based on events and issued commands. + * Software can not rely on states from output contexts because of + * latency between events and xHC updating output context values. + * See xhci 1.1 section 4.8.3 for more details + */ + unsigned long flags; +#define VDEV_PORT_ERROR BIT(0) /* Port error, link inactive */ + /* The current max exit latency for the enabled USB3 link states. */ u16 current_mel; /* Used for the debugfs interfaces. */ diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index c97f270338bf..a829cd0ef5f3 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -51,7 +51,7 @@ config USB_RIO500 tristate "USB Diamond Rio500 support" help Say Y here if you want to connect a USB Rio500 mp3 player to your - computer's USB port. Please read <file:Documentation/usb/rio.txt> + computer's USB port. Please read <file:Documentation/usb/rio.rst> for more information. To compile this driver as a module, choose M here: the diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 9465fb95d70a..344d523b0502 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -343,7 +343,6 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, struct adu_device *dev; size_t bytes_read = 0; size_t bytes_to_read = count; - int i; int retval = 0; int timeout = 0; int should_submit = 0; @@ -371,23 +370,22 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, timeout = COMMAND_TIMEOUT; dev_dbg(&dev->udev->dev, "%s : about to start looping\n", __func__); while (bytes_to_read) { - int data_in_secondary = dev->secondary_tail - dev->secondary_head; + size_t data_in_secondary = dev->secondary_tail - dev->secondary_head; dev_dbg(&dev->udev->dev, - "%s : while, data_in_secondary=%d, status=%d\n", + "%s : while, data_in_secondary=%zu, status=%d\n", __func__, data_in_secondary, dev->interrupt_in_urb->status); if (data_in_secondary) { /* drain secondary buffer */ - int amount = bytes_to_read < data_in_secondary ? bytes_to_read : data_in_secondary; - i = copy_to_user(buffer, dev->read_buffer_secondary+dev->secondary_head, amount); - if (i) { + size_t amount = min(bytes_to_read, data_in_secondary); + if (copy_to_user(buffer, dev->read_buffer_secondary+dev->secondary_head, amount)) { retval = -EFAULT; goto exit; } - dev->secondary_head += (amount - i); - bytes_read += (amount - i); - bytes_to_read -= (amount - i); + dev->secondary_head += amount; + bytes_read += amount; + bytes_to_read -= amount; } else { /* we check the primary buffer */ spin_lock_irqsave (&dev->buflock, flags); diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig index 48f1b2dadb24..ffc7cd422874 100644 --- a/drivers/usb/mon/Kconfig +++ b/drivers/usb/mon/Kconfig @@ -8,6 +8,6 @@ config USB_MON help If you select this option, a component which captures the USB traffic between peripheral-specific drivers and HC drivers will be built. - For more information, see <file:Documentation/usb/usbmon.txt>. + For more information, see <file:Documentation/usb/usbmon.rst>. If unsure, say Y, if allowed, otherwise M. diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index a501ea609019..4c3de777ef6c 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -3,6 +3,7 @@ * Renesas USB driver * * Copyright (C) 2011 Renesas Solutions Corp. + * Copyright (C) 2019 Renesas Electronics Corporation * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> */ #include <linux/clk.h> @@ -52,8 +53,8 @@ */ #define usbhs_platform_call(priv, func, args...)\ (!(priv) ? -ENODEV : \ - !((priv)->pfunc.func) ? 0 : \ - (priv)->pfunc.func(args)) + !((priv)->pfunc->func) ? 0 : \ + (priv)->pfunc->func(args)) /* * common functions @@ -83,6 +84,11 @@ struct usbhs_priv *usbhs_pdev_to_priv(struct platform_device *pdev) return dev_get_drvdata(&pdev->dev); } +int usbhs_get_id_as_gadget(struct platform_device *pdev) +{ + return USBHS_GADGET; +} + /* * syscfg functions */ @@ -287,11 +293,7 @@ static void usbhsc_set_buswait(struct usbhs_priv *priv) static bool usbhsc_is_multi_clks(struct usbhs_priv *priv) { - if (priv->dparam.type == USBHS_TYPE_RCAR_GEN3 || - priv->dparam.type == USBHS_TYPE_RCAR_GEN3_WITH_PLL) - return true; - - return false; + return priv->dparam.multi_clks; } static int usbhsc_clk_get(struct device *dev, struct usbhs_priv *priv) @@ -300,7 +302,7 @@ static int usbhsc_clk_get(struct device *dev, struct usbhs_priv *priv) return 0; /* The first clock should exist */ - priv->clks[0] = of_clk_get(dev->of_node, 0); + priv->clks[0] = of_clk_get(dev_of_node(dev), 0); if (IS_ERR(priv->clks[0])) return PTR_ERR(priv->clks[0]); @@ -308,7 +310,7 @@ static int usbhsc_clk_get(struct device *dev, struct usbhs_priv *priv) * To backward compatibility with old DT, this driver checks the return * value if it's -ENOENT or not. */ - priv->clks[1] = of_clk_get(dev->of_node, 1); + priv->clks[1] = of_clk_get(dev_of_node(dev), 1); if (PTR_ERR(priv->clks[1]) == -ENOENT) priv->clks[1] = NULL; else if (IS_ERR(priv->clks[1])) @@ -447,7 +449,7 @@ static void usbhsc_hotplug(struct usbhs_priv *priv) /* * get vbus status from platform */ - enable = usbhs_platform_call(priv, get_vbus, pdev); + enable = usbhs_mod_info_call(priv, get_vbus, pdev); /* * get id from platform @@ -513,7 +515,7 @@ static void usbhsc_notify_hotplug(struct work_struct *work) usbhsc_hotplug(priv); } -static int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev) +int usbhsc_schedule_notify_hotplug(struct platform_device *pdev) { struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); int delay = usbhs_get_dparam(priv, detection_delay); @@ -528,170 +530,92 @@ static int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev) return 0; } -static const struct usbhs_of_data rcar_gen2_data = { - .platform_callback = &usbhs_rcar2_ops, - .param = { - .type = USBHS_TYPE_RCAR_GEN2, - .has_usb_dmac = 1, - .pipe_configs = usbhsc_new_pipe, - .pipe_size = ARRAY_SIZE(usbhsc_new_pipe), - } -}; - -static const struct usbhs_of_data rcar_gen3_data = { - .platform_callback = &usbhs_rcar3_ops, - .param = { - .type = USBHS_TYPE_RCAR_GEN3, - .has_usb_dmac = 1, - .pipe_configs = usbhsc_new_pipe, - .pipe_size = ARRAY_SIZE(usbhsc_new_pipe), - } -}; - -static const struct usbhs_of_data rcar_gen3_with_pll_data = { - .platform_callback = &usbhs_rcar3_with_pll_ops, - .param = { - .type = USBHS_TYPE_RCAR_GEN3_WITH_PLL, - .has_usb_dmac = 1, - .pipe_configs = usbhsc_new_pipe, - .pipe_size = ARRAY_SIZE(usbhsc_new_pipe), - } -}; - -static const struct usbhs_of_data rza1_data = { - .platform_callback = &usbhs_rza1_ops, - .param = { - .type = USBHS_TYPE_RZA1, - .pipe_configs = usbhsc_new_pipe, - .pipe_size = ARRAY_SIZE(usbhsc_new_pipe), - } -}; - -static const struct usbhs_of_data rza2_data = { - .platform_callback = &usbhs_rza2_ops, - .param = { - .type = USBHS_TYPE_RZA2, - .has_cnen = 1, - .cfifo_byte_addr = 1, - .pipe_configs = usbhsc_new_pipe, - .pipe_size = ARRAY_SIZE(usbhsc_new_pipe), - } -}; - /* * platform functions */ static const struct of_device_id usbhs_of_match[] = { { .compatible = "renesas,usbhs-r8a774c0", - .data = &rcar_gen3_with_pll_data, + .data = &usbhs_rcar_gen3_with_pll_plat_info, }, { .compatible = "renesas,usbhs-r8a7790", - .data = &rcar_gen2_data, + .data = &usbhs_rcar_gen2_plat_info, }, { .compatible = "renesas,usbhs-r8a7791", - .data = &rcar_gen2_data, + .data = &usbhs_rcar_gen2_plat_info, }, { .compatible = "renesas,usbhs-r8a7794", - .data = &rcar_gen2_data, + .data = &usbhs_rcar_gen2_plat_info, }, { .compatible = "renesas,usbhs-r8a7795", - .data = &rcar_gen3_data, + .data = &usbhs_rcar_gen3_plat_info, }, { .compatible = "renesas,usbhs-r8a7796", - .data = &rcar_gen3_data, + .data = &usbhs_rcar_gen3_plat_info, }, { .compatible = "renesas,usbhs-r8a77990", - .data = &rcar_gen3_with_pll_data, + .data = &usbhs_rcar_gen3_with_pll_plat_info, }, { .compatible = "renesas,usbhs-r8a77995", - .data = &rcar_gen3_with_pll_data, + .data = &usbhs_rcar_gen3_with_pll_plat_info, }, { .compatible = "renesas,rcar-gen2-usbhs", - .data = &rcar_gen2_data, + .data = &usbhs_rcar_gen2_plat_info, }, { .compatible = "renesas,rcar-gen3-usbhs", - .data = &rcar_gen3_data, + .data = &usbhs_rcar_gen3_plat_info, }, { .compatible = "renesas,rza1-usbhs", - .data = &rza1_data, + .data = &usbhs_rza1_plat_info, }, { .compatible = "renesas,rza2-usbhs", - .data = &rza2_data, + .data = &usbhs_rza2_plat_info, }, { }, }; MODULE_DEVICE_TABLE(of, usbhs_of_match); -static struct renesas_usbhs_platform_info *usbhs_parse_dt(struct device *dev) -{ - struct renesas_usbhs_platform_info *info; - struct renesas_usbhs_driver_param *dparam; - const struct usbhs_of_data *data; - u32 tmp; - int gpio; - - info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); - if (!info) - return NULL; - - data = of_device_get_match_data(dev); - if (!data) - return NULL; - - dparam = &info->driver_param; - memcpy(dparam, &data->param, sizeof(data->param)); - memcpy(&info->platform_callback, data->platform_callback, - sizeof(*data->platform_callback)); - - if (!of_property_read_u32(dev->of_node, "renesas,buswait", &tmp)) - dparam->buswait_bwait = tmp; - gpio = of_get_named_gpio_flags(dev->of_node, "renesas,enable-gpio", 0, - NULL); - if (gpio > 0) - dparam->enable_gpio = gpio; - - return info; -} - static int usbhs_probe(struct platform_device *pdev) { - struct renesas_usbhs_platform_info *info = renesas_usbhs_get_info(pdev); - struct renesas_usbhs_driver_callback *dfunc; + const struct renesas_usbhs_platform_info *info; struct usbhs_priv *priv; struct resource *res, *irq_res; - int ret; + struct device *dev = &pdev->dev; + int ret, gpio; + u32 tmp; /* check device node */ - if (pdev->dev.of_node) - info = pdev->dev.platform_data = usbhs_parse_dt(&pdev->dev); + if (dev_of_node(dev)) + info = of_device_get_match_data(dev); + else + info = renesas_usbhs_get_info(pdev); /* check platform information */ if (!info) { - dev_err(&pdev->dev, "no platform information\n"); + dev_err(dev, "no platform information\n"); return -EINVAL; } /* platform data */ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq_res) { - dev_err(&pdev->dev, "Not enough Renesas USB platform resources.\n"); + dev_err(dev, "Not enough Renesas USB platform resources.\n"); return -ENODEV; } /* usb private data */ - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -700,13 +624,13 @@ static int usbhs_probe(struct platform_device *pdev) if (IS_ERR(priv->base)) return PTR_ERR(priv->base); - if (of_property_read_bool(pdev->dev.of_node, "extcon")) { - priv->edev = extcon_get_edev_by_phandle(&pdev->dev, 0); + if (of_property_read_bool(dev_of_node(dev), "extcon")) { + priv->edev = extcon_get_edev_by_phandle(dev, 0); if (IS_ERR(priv->edev)) return PTR_ERR(priv->edev); } - priv->rsts = devm_reset_control_array_get_optional_shared(&pdev->dev); + priv->rsts = devm_reset_control_array_get_optional_shared(dev); if (IS_ERR(priv->rsts)) return PTR_ERR(priv->rsts); @@ -714,33 +638,34 @@ static int usbhs_probe(struct platform_device *pdev) * care platform info */ - memcpy(&priv->dparam, - &info->driver_param, - sizeof(struct renesas_usbhs_driver_param)); + priv->dparam = info->driver_param; if (!info->platform_callback.get_id) { - dev_err(&pdev->dev, "no platform callbacks"); + dev_err(dev, "no platform callbacks\n"); return -EINVAL; } - memcpy(&priv->pfunc, - &info->platform_callback, - sizeof(struct renesas_usbhs_platform_callback)); - - /* set driver callback functions for platform */ - dfunc = &info->driver_callback; - dfunc->notify_hotplug = usbhsc_drvcllbck_notify_hotplug; + priv->pfunc = &info->platform_callback; /* set default param if platform doesn't have */ - if (!priv->dparam.pipe_configs) { + if (usbhs_get_dparam(priv, has_new_pipe_configs)) { + priv->dparam.pipe_configs = usbhsc_new_pipe; + priv->dparam.pipe_size = ARRAY_SIZE(usbhsc_new_pipe); + } else if (!priv->dparam.pipe_configs) { priv->dparam.pipe_configs = usbhsc_default_pipe; priv->dparam.pipe_size = ARRAY_SIZE(usbhsc_default_pipe); } if (!priv->dparam.pio_dma_border) priv->dparam.pio_dma_border = 64; /* 64byte */ + if (!of_property_read_u32(dev_of_node(dev), "renesas,buswait", &tmp)) + priv->dparam.buswait_bwait = tmp; + gpio = of_get_named_gpio_flags(dev_of_node(dev), "renesas,enable-gpio", + 0, NULL); + if (gpio > 0) + priv->dparam.enable_gpio = gpio; /* FIXME */ /* runtime power control ? */ - if (priv->pfunc.get_vbus) + if (priv->pfunc->get_vbus) usbhs_get_dparam(priv, runtime_pwctrl) = 1; /* @@ -773,7 +698,7 @@ static int usbhs_probe(struct platform_device *pdev) if (ret) goto probe_fail_rst; - ret = usbhsc_clk_get(&pdev->dev, priv); + ret = usbhsc_clk_get(dev, priv); if (ret) goto probe_fail_clks; @@ -789,8 +714,7 @@ static int usbhs_probe(struct platform_device *pdev) ret = !gpio_get_value(priv->dparam.enable_gpio); gpio_free(priv->dparam.enable_gpio); if (ret) { - dev_warn(&pdev->dev, - "USB function not selected (GPIO %d)\n", + dev_warn(dev, "USB function not selected (GPIO %d)\n", priv->dparam.enable_gpio); ret = -ENOTSUPP; goto probe_end_mod_exit; @@ -806,7 +730,7 @@ static int usbhs_probe(struct platform_device *pdev) */ ret = usbhs_platform_call(priv, hardware_init, pdev); if (ret < 0) { - dev_err(&pdev->dev, "platform init failed.\n"); + dev_err(dev, "platform init failed.\n"); goto probe_end_mod_exit; } @@ -814,18 +738,20 @@ static int usbhs_probe(struct platform_device *pdev) usbhs_platform_call(priv, phy_reset, pdev); /* power control */ - pm_runtime_enable(&pdev->dev); + pm_runtime_enable(dev); if (!usbhs_get_dparam(priv, runtime_pwctrl)) { usbhsc_power_ctrl(priv, 1); usbhs_mod_autonomy_mode(priv); + } else { + usbhs_mod_non_autonomy_mode(priv); } /* * manual call notify_hotplug for cold plug */ - usbhsc_drvcllbck_notify_hotplug(pdev); + usbhsc_schedule_notify_hotplug(pdev); - dev_info(&pdev->dev, "probed\n"); + dev_info(dev, "probed\n"); return ret; @@ -840,7 +766,7 @@ probe_end_fifo_exit: probe_end_pipe_exit: usbhs_pipe_remove(priv); - dev_info(&pdev->dev, "probe failed (%d)\n", ret); + dev_info(dev, "probe failed (%d)\n", ret); return ret; } @@ -848,13 +774,9 @@ probe_end_pipe_exit: static int usbhs_remove(struct platform_device *pdev) { struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); - struct renesas_usbhs_platform_info *info = renesas_usbhs_get_info(pdev); - struct renesas_usbhs_driver_callback *dfunc = &info->driver_callback; dev_dbg(&pdev->dev, "usb remove\n"); - dfunc->notify_hotplug = NULL; - /* power off */ if (!usbhs_get_dparam(priv, runtime_pwctrl)) usbhsc_power_ctrl(priv, 0); @@ -899,7 +821,7 @@ static __maybe_unused int usbhsc_resume(struct device *dev) usbhs_platform_call(priv, phy_reset, pdev); - usbhsc_drvcllbck_notify_hotplug(pdev); + usbhsc_schedule_notify_hotplug(pdev); return 0; } diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h index de74ebd1a347..d1a0a35ecfff 100644 --- a/drivers/usb/renesas_usbhs/common.h +++ b/drivers/usb/renesas_usbhs/common.h @@ -3,6 +3,7 @@ * Renesas USB driver * * Copyright (C) 2011 Renesas Solutions Corp. + * Copyright (C) 2019 Renesas Electronics Corporation * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> */ #ifndef RENESAS_USB_DRIVER_H @@ -251,7 +252,7 @@ struct usbhs_priv { unsigned int irq; unsigned long irqflags; - struct renesas_usbhs_platform_callback pfunc; + const struct renesas_usbhs_platform_callback *pfunc; struct renesas_usbhs_driver_param dparam; struct delayed_work notify_hotplug_work; @@ -281,11 +282,6 @@ struct usbhs_priv { struct clk *clks[2]; }; -struct usbhs_of_data { - const struct renesas_usbhs_platform_callback *platform_callback; - const struct renesas_usbhs_driver_param param; -}; - /* * common */ @@ -296,6 +292,8 @@ void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data); #define usbhs_lock(p, f) spin_lock_irqsave(usbhs_priv_to_lock(p), f) #define usbhs_unlock(p, f) spin_unlock_irqrestore(usbhs_priv_to_lock(p), f) +int usbhs_get_id_as_gadget(struct platform_device *pdev); + /* * sysconfig */ @@ -317,6 +315,7 @@ void usbhs_bus_send_sof_enable(struct usbhs_priv *priv); void usbhs_bus_send_reset(struct usbhs_priv *priv); int usbhs_bus_get_speed(struct usbhs_priv *priv); int usbhs_vbus_ctrl(struct usbhs_priv *priv, int enable); +int usbhsc_schedule_notify_hotplug(struct platform_device *pdev); /* * frame diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index e84d2ac2a30a..a345b2ef976e 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -3,6 +3,7 @@ * Renesas USB driver * * Copyright (C) 2011 Renesas Solutions Corp. + * Copyright (C) 2019 Renesas Electronics Corporation * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> */ #include <linux/delay.h> @@ -1277,7 +1278,7 @@ static void usbhsf_dma_init(struct usbhs_priv *priv, struct usbhs_fifo *fifo, { struct device *dev = usbhs_priv_to_dev(priv); - if (dev->of_node) + if (dev_of_node(dev)) usbhsf_dma_init_dt(dev, fifo, channel); else usbhsf_dma_init_pdev(fifo); diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 7475c4f64724..10fc65596014 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c @@ -3,6 +3,7 @@ * Renesas USB driver * * Copyright (C) 2011 Renesas Solutions Corp. + * Copyright (C) 2019 Renesas Electronics Corporation * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> */ #include <linux/interrupt.h> @@ -10,15 +11,6 @@ #include "common.h" #include "mod.h" -#define usbhs_priv_to_modinfo(priv) (&priv->mod_info) -#define usbhs_mod_info_call(priv, func, param...) \ -({ \ - struct usbhs_mod_info *info; \ - info = usbhs_priv_to_modinfo(priv); \ - !info->func ? 0 : \ - info->func(param); \ -}) - /* * autonomy * @@ -41,7 +33,7 @@ static int usbhsm_autonomy_irq_vbus(struct usbhs_priv *priv, { struct platform_device *pdev = usbhs_priv_to_pdev(priv); - renesas_usbhs_call_notify_hotplug(pdev); + usbhsc_schedule_notify_hotplug(pdev); return 0; } @@ -50,12 +42,19 @@ void usbhs_mod_autonomy_mode(struct usbhs_priv *priv) { struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); - info->irq_vbus = usbhsm_autonomy_irq_vbus; - priv->pfunc.get_vbus = usbhsm_autonomy_get_vbus; + info->irq_vbus = usbhsm_autonomy_irq_vbus; + info->get_vbus = usbhsm_autonomy_get_vbus; usbhs_irq_callback_update(priv, NULL); } +void usbhs_mod_non_autonomy_mode(struct usbhs_priv *priv) +{ + struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); + + info->get_vbus = priv->pfunc->get_vbus; +} + /* * host / gadget functions * diff --git a/drivers/usb/renesas_usbhs/mod.h b/drivers/usb/renesas_usbhs/mod.h index a4a61d6b82a1..65dc19ca528e 100644 --- a/drivers/usb/renesas_usbhs/mod.h +++ b/drivers/usb/renesas_usbhs/mod.h @@ -3,6 +3,7 @@ * Renesas USB driver * * Copyright (C) 2011 Renesas Solutions Corp. + * Copyright (C) 2019 Renesas Electronics Corporation * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> */ #ifndef RENESAS_USB_MOD_H @@ -84,15 +85,20 @@ struct usbhs_mod_info { /* * INTSTS0 :: VBINT * - * This function will be used as autonomy mode - * when platform cannot call notify_hotplug. + * This function will be used as autonomy mode (runtime_pwctrl == 0) + * when the platform doesn't have own get_vbus function. * - * This callback cannot be member of "struct usbhs_mod" - * because it will be used even though - * host/gadget has not been selected. + * This callback cannot be member of "struct usbhs_mod" because it + * will be used even though host/gadget has not been selected. */ int (*irq_vbus)(struct usbhs_priv *priv, struct usbhs_irq_state *irq_state); + + /* + * This function will be used on any gadget mode. To simplify the code, + * this member is in here. + */ + int (*get_vbus)(struct platform_device *pdev); }; /* @@ -107,6 +113,7 @@ int usbhs_mod_probe(struct usbhs_priv *priv); void usbhs_mod_remove(struct usbhs_priv *priv); void usbhs_mod_autonomy_mode(struct usbhs_priv *priv); +void usbhs_mod_non_autonomy_mode(struct usbhs_priv *priv); /* * status functions @@ -129,6 +136,15 @@ void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod); mod->func(param); \ }) +#define usbhs_priv_to_modinfo(priv) (&priv->mod_info) +#define usbhs_mod_info_call(priv, func, param...) \ +({ \ + struct usbhs_mod_info *info; \ + info = usbhs_priv_to_modinfo(priv); \ + !info->func ? 0 : \ + info->func(param); \ +}) + /* * host / gadget control */ diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 59cac40aafcc..4d571a5205e2 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -3,6 +3,7 @@ * Renesas USB driver * * Copyright (C) 2011 Renesas Solutions Corp. + * Copyright (C) 2019 Renesas Electronics Corporation * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> */ #include <linux/delay.h> @@ -914,8 +915,8 @@ static void usbhs_mod_phy_mode(struct usbhs_priv *priv) { struct usbhs_mod_info *info = &priv->mod_info; - info->irq_vbus = NULL; - priv->pfunc.get_vbus = usbhsm_phy_get_vbus; + info->irq_vbus = NULL; + info->get_vbus = usbhsm_phy_get_vbus; usbhs_irq_callback_update(priv, NULL); } @@ -1023,7 +1024,7 @@ static int usbhsg_vbus_session(struct usb_gadget *gadget, int is_active) gpriv->vbus_active = !!is_active; - renesas_usbhs_call_notify_hotplug(pdev); + usbhsc_schedule_notify_hotplug(pdev); return 0; } diff --git a/drivers/usb/renesas_usbhs/rcar2.c b/drivers/usb/renesas_usbhs/rcar2.c index 0027092b1118..440d213e1749 100644 --- a/drivers/usb/renesas_usbhs/rcar2.c +++ b/drivers/usb/renesas_usbhs/rcar2.c @@ -3,6 +3,7 @@ * Renesas USB driver R-Car Gen. 2 initialization and power control * * Copyright (C) 2014 Ulrich Hecht + * Copyright (C) 2019 Renesas Electronics Corporation */ #include <linux/gpio.h> @@ -62,14 +63,15 @@ static int usbhs_rcar2_power_ctrl(struct platform_device *pdev, return retval; } -static int usbhs_rcar2_get_id(struct platform_device *pdev) -{ - return USBHS_GADGET; -} - -const struct renesas_usbhs_platform_callback usbhs_rcar2_ops = { - .hardware_init = usbhs_rcar2_hardware_init, - .hardware_exit = usbhs_rcar2_hardware_exit, - .power_ctrl = usbhs_rcar2_power_ctrl, - .get_id = usbhs_rcar2_get_id, +const struct renesas_usbhs_platform_info usbhs_rcar_gen2_plat_info = { + .platform_callback = { + .hardware_init = usbhs_rcar2_hardware_init, + .hardware_exit = usbhs_rcar2_hardware_exit, + .power_ctrl = usbhs_rcar2_power_ctrl, + .get_id = usbhs_get_id_as_gadget, + }, + .driver_param = { + .has_usb_dmac = 1, + .has_new_pipe_configs = 1, + }, }; diff --git a/drivers/usb/renesas_usbhs/rcar2.h b/drivers/usb/renesas_usbhs/rcar2.h index 45e3526cedeb..7d88732c5bff 100644 --- a/drivers/usb/renesas_usbhs/rcar2.h +++ b/drivers/usb/renesas_usbhs/rcar2.h @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0 #include "common.h" -extern const struct renesas_usbhs_platform_callback - usbhs_rcar2_ops; +extern const struct renesas_usbhs_platform_info usbhs_rcar_gen2_plat_info; diff --git a/drivers/usb/renesas_usbhs/rcar3.c b/drivers/usb/renesas_usbhs/rcar3.c index 5e730e9b40ef..c181b2a0b9d3 100644 --- a/drivers/usb/renesas_usbhs/rcar3.c +++ b/drivers/usb/renesas_usbhs/rcar3.c @@ -2,7 +2,7 @@ /* * Renesas USB driver R-Car Gen. 3 initialization and power control * - * Copyright (C) 2016 Renesas Electronics Corporation + * Copyright (C) 2016-2019 Renesas Electronics Corporation */ #include <linux/delay.h> @@ -95,17 +95,26 @@ static int usbhs_rcar3_power_and_pll_ctrl(struct platform_device *pdev, return 0; } -static int usbhs_rcar3_get_id(struct platform_device *pdev) -{ - return USBHS_GADGET; -} - -const struct renesas_usbhs_platform_callback usbhs_rcar3_ops = { - .power_ctrl = usbhs_rcar3_power_ctrl, - .get_id = usbhs_rcar3_get_id, +const struct renesas_usbhs_platform_info usbhs_rcar_gen3_plat_info = { + .platform_callback = { + .power_ctrl = usbhs_rcar3_power_ctrl, + .get_id = usbhs_get_id_as_gadget, + }, + .driver_param = { + .has_usb_dmac = 1, + .multi_clks = 1, + .has_new_pipe_configs = 1, + }, }; -const struct renesas_usbhs_platform_callback usbhs_rcar3_with_pll_ops = { - .power_ctrl = usbhs_rcar3_power_and_pll_ctrl, - .get_id = usbhs_rcar3_get_id, +const struct renesas_usbhs_platform_info usbhs_rcar_gen3_with_pll_plat_info = { + .platform_callback = { + .power_ctrl = usbhs_rcar3_power_and_pll_ctrl, + .get_id = usbhs_get_id_as_gadget, + }, + .driver_param = { + .has_usb_dmac = 1, + .multi_clks = 1, + .has_new_pipe_configs = 1, + }, }; diff --git a/drivers/usb/renesas_usbhs/rcar3.h b/drivers/usb/renesas_usbhs/rcar3.h index 49e535a31771..c7c5ec1e3af2 100644 --- a/drivers/usb/renesas_usbhs/rcar3.h +++ b/drivers/usb/renesas_usbhs/rcar3.h @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include "common.h" -extern const struct renesas_usbhs_platform_callback usbhs_rcar3_ops; -extern const struct renesas_usbhs_platform_callback usbhs_rcar3_with_pll_ops; +extern const struct renesas_usbhs_platform_info usbhs_rcar_gen3_plat_info; +extern const struct renesas_usbhs_platform_info + usbhs_rcar_gen3_with_pll_plat_info; diff --git a/drivers/usb/renesas_usbhs/rza.c b/drivers/usb/renesas_usbhs/rza.c index 8c739bd24acd..24de64edb674 100644 --- a/drivers/usb/renesas_usbhs/rza.c +++ b/drivers/usb/renesas_usbhs/rza.c @@ -3,7 +3,7 @@ * Renesas USB driver RZ/A initialization and power control * * Copyright (C) 2018 Chris Brandt - * Copyright (C) 2018 Renesas Electronics Corporation + * Copyright (C) 2018-2019 Renesas Electronics Corporation */ #include <linux/delay.h> @@ -41,12 +41,12 @@ static int usbhs_rza1_hardware_init(struct platform_device *pdev) return 0; } -static int usbhs_rza_get_id(struct platform_device *pdev) -{ - return USBHS_GADGET; -} - -const struct renesas_usbhs_platform_callback usbhs_rza1_ops = { - .hardware_init = usbhs_rza1_hardware_init, - .get_id = usbhs_rza_get_id, +const struct renesas_usbhs_platform_info usbhs_rza1_plat_info = { + .platform_callback = { + .hardware_init = usbhs_rza1_hardware_init, + .get_id = usbhs_get_id_as_gadget, + }, + .driver_param = { + .has_new_pipe_configs = 1, + }, }; diff --git a/drivers/usb/renesas_usbhs/rza.h b/drivers/usb/renesas_usbhs/rza.h index 073a53d1d442..1ca42a6fd480 100644 --- a/drivers/usb/renesas_usbhs/rza.h +++ b/drivers/usb/renesas_usbhs/rza.h @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 #include "common.h" -extern const struct renesas_usbhs_platform_callback usbhs_rza1_ops; -extern const struct renesas_usbhs_platform_callback usbhs_rza2_ops; +extern const struct renesas_usbhs_platform_info usbhs_rza1_plat_info; +extern const struct renesas_usbhs_platform_info usbhs_rza2_plat_info; diff --git a/drivers/usb/renesas_usbhs/rza2.c b/drivers/usb/renesas_usbhs/rza2.c index 9d8551f93533..021749594389 100644 --- a/drivers/usb/renesas_usbhs/rza2.c +++ b/drivers/usb/renesas_usbhs/rza2.c @@ -59,14 +59,16 @@ static int usbhs_rza2_power_ctrl(struct platform_device *pdev, return retval; } -static int usbhs_rza2_get_id(struct platform_device *pdev) -{ - return USBHS_GADGET; -} - -const struct renesas_usbhs_platform_callback usbhs_rza2_ops = { - .hardware_init = usbhs_rza2_hardware_init, - .hardware_exit = usbhs_rza2_hardware_exit, - .power_ctrl = usbhs_rza2_power_ctrl, - .get_id = usbhs_rza2_get_id, +const struct renesas_usbhs_platform_info usbhs_rza2_plat_info = { + .platform_callback = { + .hardware_init = usbhs_rza2_hardware_init, + .hardware_exit = usbhs_rza2_hardware_exit, + .power_ctrl = usbhs_rza2_power_ctrl, + .get_id = usbhs_get_id_as_gadget, + }, + .driver_param = { + .has_cnen = 1, + .cfifo_byte_addr = 1, + .has_new_pipe_configs = 1, + }, }; diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 7d031911d04e..67279c6bce33 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -11,7 +11,7 @@ menuconfig USB_SERIAL ports, or acts like a serial device, and you want to connect it to your USB bus. - Please read <file:Documentation/usb/usb-serial.txt> for more + Please read <file:Documentation/usb/usb-serial.rst> for more information on the specifics of the different devices that are supported, and on how to use them. @@ -47,7 +47,7 @@ config USB_SERIAL_GENERIC bool "USB Generic Serial Driver" help Say Y here if you want to use the generic USB serial driver. Please - read <file:Documentation/usb/usb-serial.txt> for more information on + read <file:Documentation/usb/usb-serial.rst> for more information on using this driver. It is recommended that the "USB Serial converter support" be compiled as a module for this driver to be used properly. @@ -163,7 +163,7 @@ config USB_SERIAL_EMPEG help Say Y here if you want to connect to your Empeg empeg-car Mark I/II mp3 player via USB. The driver uses a single ttyUSB{0,1,2,...} - device node. See <file:Documentation/usb/usb-serial.txt> for more + device node. See <file:Documentation/usb/usb-serial.rst> for more tidbits of information. To compile this driver as a module, choose M here: the @@ -199,7 +199,7 @@ config USB_SERIAL_IPAQ Say Y here if you want to connect to your Compaq iPAQ, HP Jornada or any other PDA running Windows CE 3.0 or PocketPC 2002 using a USB cradle/cable. For information on using the driver, - read <file:Documentation/usb/usb-serial.txt>. + read <file:Documentation/usb/usb-serial.rst>. To compile this driver as a module, choose M here: the module will be called ipaq. @@ -334,7 +334,7 @@ config USB_SERIAL_KLSI adapter sold by Palm Inc. for use with their Palm III and Palm V series PDAs. - Please read <file:Documentation/usb/usb-serial.txt> for more + Please read <file:Documentation/usb/usb-serial.rst> for more information. To compile this driver as a module, choose M here: the diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index c1235d5b9fba..9bb123ab9bc9 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -10,7 +10,7 @@ * and associated source files. Please see the usb/serial files for * individual credits and copyrights. * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver * * TODO: diff --git a/drivers/usb/serial/belkin_sa.h b/drivers/usb/serial/belkin_sa.h index 51bc06287603..a13a98d284f2 100644 --- a/drivers/usb/serial/belkin_sa.h +++ b/drivers/usb/serial/belkin_sa.h @@ -9,7 +9,7 @@ * and associated source files. Please see the usb/serial files for * individual credits and copyrights. * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver * * 12-Mar-2001 gkh diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 72d3ae1ebc64..216edd5826ca 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -7,7 +7,7 @@ * Copyright (C) 2003,2004 * Neil Whelchel (koyama@firstlight.net) * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver * * See http://geocities.com/i0xox0i for information on this driver and the diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index d680bec62547..405e835e93dd 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -8,7 +8,7 @@ * Copyright (C) 1999 - 2001 * Greg Kroah-Hartman (greg@kroah.com) * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 1d8461ae2c34..8b15bbf545d4 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -10,7 +10,7 @@ * Copyright (C) 2002 * Kuba Ober (kuba@mareimbrium.org) * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver * * See http://ftdi-usb-sio.sourceforge.net for up to date testing info diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 7643716b5299..302eb9530859 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -16,7 +16,7 @@ * was written by Roman Weissgaerber <weissg@vienna.at>, Dag Brattli * <dag@brattli.net>, and Jean Tourrilhes <jt@hpl.hp.com> * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver */ diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 38d43c4b7ce5..bf988f77d400 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -6,7 +6,7 @@ * Copyright (C) 1999, 2000 Brian Warner <warner@lothar.com> * Copyright (C) 2000 Al Borchers <borchers@steinerpoint.com> * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver */ diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index e51c9464ea42..5b6e982a9376 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -4,7 +4,7 @@ * * Copyright (C) 2013,2017 Johan Hovold <johan@kernel.org> * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver * * Please report both successes and troubles to the author at omninet@kroah.com diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 38ae0fc826cc..8151dd7a45e8 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -22,7 +22,7 @@ * So, THIS CODE CAN DESTROY OTi-6858 AND ANY OTHER DEVICES, THAT ARE * CONNECTED TO IT! * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver * * TODO: diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index d7abde14b3cf..9d27b76c5c6e 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -7,7 +7,7 @@ * * Original driver for 2.2.x by anonymous * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver */ diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 676c296103a2..a3179fea38c8 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -10,7 +10,7 @@ * This driver was originally based on the ACM driver by Armin Fuerst (which was * based on a driver by Brad Keryan) * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver */ diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 8ddbecc25d89..4412834db21c 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -6,7 +6,7 @@ * Copyright (C) 1999 - 2004 * Greg Kroah-Hartman (greg@kroah.com) * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver * */ diff --git a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h index fe290243f1ce..4bd69d047036 100644 --- a/drivers/usb/serial/visor.h +++ b/drivers/usb/serial/visor.h @@ -5,7 +5,7 @@ * Copyright (C) 1999 - 2003 * Greg Kroah-Hartman (greg@kroah.com) * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver. * */ diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index aefd84f88b59..79314d8c94a4 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -8,7 +8,7 @@ * Copyright (C) 1999 - 2001 * Greg Kroah-Hartman (greg@kroah.com) * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver */ diff --git a/drivers/usb/serial/whiteheat.h b/drivers/usb/serial/whiteheat.h index 72c1b0cf4063..00398149cd8d 100644 --- a/drivers/usb/serial/whiteheat.h +++ b/drivers/usb/serial/whiteheat.h @@ -8,7 +8,7 @@ * Copyright (C) 1999, 2000 * Greg Kroah-Hartman (greg@kroah.com) * - * See Documentation/usb/usb-serial.txt for more information on using this + * See Documentation/usb/usb-serial.rst for more information on using this * driver * */ diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/usb/wusbcore/Kconfig index 12e89189ca7d..abc0f361021f 100644 --- a/drivers/usb/wusbcore/Kconfig +++ b/drivers/usb/wusbcore/Kconfig @@ -5,11 +5,9 @@ config USB_WUSB tristate "Enable Wireless USB extensions" depends on UWB - select CRYPTO - select CRYPTO_BLKCIPHER - select CRYPTO_CBC - select CRYPTO_MANAGER - select CRYPTO_AES + select CRYPTO + select CRYPTO_AES + select CRYPTO_CCM help Enable the host-side support for Wireless USB. diff --git a/drivers/usb/wusbcore/crypto.c b/drivers/usb/wusbcore/crypto.c index edb7263bff40..9ee66483ee54 100644 --- a/drivers/usb/wusbcore/crypto.c +++ b/drivers/usb/wusbcore/crypto.c @@ -31,6 +31,9 @@ * funneled through AES are...16 bytes in size! */ +#include <crypto/aes.h> +#include <crypto/algapi.h> +#include <crypto/hash.h> #include <crypto/skcipher.h> #include <linux/crypto.h> #include <linux/module.h> @@ -109,16 +112,6 @@ struct aes_ccm_a { __be16 counter; /* Value of x */ } __attribute__((packed)); -static void bytewise_xor(void *_bo, const void *_bi1, const void *_bi2, - size_t size) -{ - u8 *bo = _bo; - const u8 *bi1 = _bi1, *bi2 = _bi2; - size_t itr; - for (itr = 0; itr < size; itr++) - bo[itr] = bi1[itr] ^ bi2[itr]; -} - /* Scratch space for MAC calculations. */ struct wusb_mac_scratch { struct aes_ccm_b0 b0; @@ -150,8 +143,7 @@ struct wusb_mac_scratch { * @a: ASCII string, 14 bytes long (I guess zero padded if needed; * we use exactly 14 bytes). * - * @b: data stream to be processed; cannot be a global or const local - * (will confuse the scatterlists) + * @b: data stream to be processed * * @blen: size of b... * @@ -160,16 +152,10 @@ struct wusb_mac_scratch { * @key. We bytewise xor B0 with B1 (1) and AES-crypt that. Then we * take the payload and divide it in blocks (16 bytes), xor them with * the previous crypto result (16 bytes) and crypt it, repeat the next - * block with the output of the previous one, rinse wash (I guess this - * is what AES CBC mode means...but I truly have no idea). So we use - * the CBC(AES) blkcipher, that does precisely that. The IV (Initial + * block with the output of the previous one, rinse wash. So we use + * the CBC-MAC(AES) shash, that does precisely that. The IV (Initial * Vector) is 16 bytes and is set to zero, so * - * See rfc3610. Linux crypto has a CBC implementation, but the - * documentation is scarce, to say the least, and the example code is - * so intricated that is difficult to understand how things work. Most - * of this is guess work -- bite me. - * * (1) Created as 6.5 says, again, using as l(a) 'Blen + 14', and * using the 14 bytes of @a to fill up * b1.{mac_header,e0,security_reserved,padding}. @@ -189,44 +175,24 @@ struct wusb_mac_scratch { * NOTE: blen is not aligned to a block size, we'll pad zeros, that's * what sg[4] is for. Maybe there is a smarter way to do this. */ -static int wusb_ccm_mac(struct crypto_sync_skcipher *tfm_cbc, - struct crypto_cipher *tfm_aes, +static int wusb_ccm_mac(struct crypto_shash *tfm_cbcmac, struct wusb_mac_scratch *scratch, void *mic, const struct aes_ccm_nonce *n, const struct aes_ccm_label *a, const void *b, size_t blen) { - int result = 0; - SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm_cbc); - struct scatterlist sg[4], sg_dst; - void *dst_buf; - size_t dst_size; - u8 *iv; - size_t zero_padding; + SHASH_DESC_ON_STACK(desc, tfm_cbcmac); + u8 iv[AES_BLOCK_SIZE]; /* * These checks should be compile time optimized out * ensure @a fills b1's mac_header and following fields */ - WARN_ON(sizeof(*a) != sizeof(scratch->b1) - sizeof(scratch->b1.la)); - WARN_ON(sizeof(scratch->b0) != sizeof(struct aes_ccm_block)); - WARN_ON(sizeof(scratch->b1) != sizeof(struct aes_ccm_block)); - WARN_ON(sizeof(scratch->ax) != sizeof(struct aes_ccm_block)); - - result = -ENOMEM; - zero_padding = blen % sizeof(struct aes_ccm_block); - if (zero_padding) - zero_padding = sizeof(struct aes_ccm_block) - zero_padding; - dst_size = blen + sizeof(scratch->b0) + sizeof(scratch->b1) + - zero_padding; - dst_buf = kzalloc(dst_size, GFP_KERNEL); - if (!dst_buf) - goto error_dst_buf; - - iv = kzalloc(crypto_sync_skcipher_ivsize(tfm_cbc), GFP_KERNEL); - if (!iv) - goto error_iv; + BUILD_BUG_ON(sizeof(*a) != sizeof(scratch->b1) - sizeof(scratch->b1.la)); + BUILD_BUG_ON(sizeof(scratch->b0) != sizeof(struct aes_ccm_block)); + BUILD_BUG_ON(sizeof(scratch->b1) != sizeof(struct aes_ccm_block)); + BUILD_BUG_ON(sizeof(scratch->ax) != sizeof(struct aes_ccm_block)); /* Setup B0 */ scratch->b0.flags = 0x59; /* Format B0 */ @@ -243,46 +209,28 @@ static int wusb_ccm_mac(struct crypto_sync_skcipher *tfm_cbc, scratch->b1.la = cpu_to_be16(blen + 14); memcpy(&scratch->b1.mac_header, a, sizeof(*a)); - sg_init_table(sg, ARRAY_SIZE(sg)); - sg_set_buf(&sg[0], &scratch->b0, sizeof(scratch->b0)); - sg_set_buf(&sg[1], &scratch->b1, sizeof(scratch->b1)); - sg_set_buf(&sg[2], b, blen); - /* 0 if well behaved :) */ - sg_set_page(&sg[3], ZERO_PAGE(0), zero_padding, 0); - sg_init_one(&sg_dst, dst_buf, dst_size); - - skcipher_request_set_sync_tfm(req, tfm_cbc); - skcipher_request_set_callback(req, 0, NULL, NULL); - skcipher_request_set_crypt(req, sg, &sg_dst, dst_size, iv); - result = crypto_skcipher_encrypt(req); - skcipher_request_zero(req); - if (result < 0) { - printk(KERN_ERR "E: can't compute CBC-MAC tag (MIC): %d\n", - result); - goto error_cbc_crypt; - } + desc->tfm = tfm_cbcmac; + crypto_shash_init(desc); + crypto_shash_update(desc, (u8 *)&scratch->b0, sizeof(scratch->b0) + + sizeof(scratch->b1)); + crypto_shash_finup(desc, b, blen, iv); /* Now we crypt the MIC Tag (*iv) with Ax -- values per WUSB1.0[6.5] * The procedure is to AES crypt the A0 block and XOR the MIC * Tag against it; we only do the first 8 bytes and place it * directly in the destination buffer. - * - * POS Crypto API: size is assumed to be AES's block size. - * Thanks for documenting it -- tip taken from airo.c */ scratch->ax.flags = 0x01; /* as per WUSB 1.0 spec */ scratch->ax.ccm_nonce = *n; scratch->ax.counter = 0; - crypto_cipher_encrypt_one(tfm_aes, (void *)&scratch->ax, - (void *)&scratch->ax); - bytewise_xor(mic, &scratch->ax, iv, 8); - result = 8; -error_cbc_crypt: - kfree(iv); -error_iv: - kfree(dst_buf); -error_dst_buf: - return result; + + /* reuse the CBC-MAC transform to perform the single block encryption */ + crypto_shash_digest(desc, (u8 *)&scratch->ax, sizeof(scratch->ax), + (u8 *)&scratch->ax); + + crypto_xor_cpy(mic, (u8 *)&scratch->ax, iv, 8); + + return 8; } /* @@ -298,45 +246,28 @@ ssize_t wusb_prf(void *out, size_t out_size, { ssize_t result, bytes = 0, bitr; struct aes_ccm_nonce n = *_n; - struct crypto_sync_skcipher *tfm_cbc; - struct crypto_cipher *tfm_aes; - struct wusb_mac_scratch *scratch; + struct crypto_shash *tfm_cbcmac; + struct wusb_mac_scratch scratch; u64 sfn = 0; __le64 sfn_le; - tfm_cbc = crypto_alloc_sync_skcipher("cbc(aes)", 0, 0); - if (IS_ERR(tfm_cbc)) { - result = PTR_ERR(tfm_cbc); - printk(KERN_ERR "E: can't load CBC(AES): %d\n", (int)result); - goto error_alloc_cbc; - } - result = crypto_sync_skcipher_setkey(tfm_cbc, key, 16); - if (result < 0) { - printk(KERN_ERR "E: can't set CBC key: %d\n", (int)result); - goto error_setkey_cbc; + tfm_cbcmac = crypto_alloc_shash("cbcmac(aes)", 0, 0); + if (IS_ERR(tfm_cbcmac)) { + result = PTR_ERR(tfm_cbcmac); + printk(KERN_ERR "E: can't load CBCMAC-AES: %d\n", (int)result); + goto error_alloc_cbcmac; } - tfm_aes = crypto_alloc_cipher("aes", 0, 0); - if (IS_ERR(tfm_aes)) { - result = PTR_ERR(tfm_aes); - printk(KERN_ERR "E: can't load AES: %d\n", (int)result); - goto error_alloc_aes; - } - result = crypto_cipher_setkey(tfm_aes, key, 16); + result = crypto_shash_setkey(tfm_cbcmac, key, AES_BLOCK_SIZE); if (result < 0) { - printk(KERN_ERR "E: can't set AES key: %d\n", (int)result); - goto error_setkey_aes; - } - scratch = kmalloc(sizeof(*scratch), GFP_KERNEL); - if (!scratch) { - result = -ENOMEM; - goto error_alloc_scratch; + printk(KERN_ERR "E: can't set CBCMAC-AES key: %d\n", (int)result); + goto error_setkey_cbcmac; } for (bitr = 0; bitr < (len + 63) / 64; bitr++) { sfn_le = cpu_to_le64(sfn++); memcpy(&n.sfn, &sfn_le, sizeof(n.sfn)); /* n.sfn++... */ - result = wusb_ccm_mac(tfm_cbc, tfm_aes, scratch, out + bytes, + result = wusb_ccm_mac(tfm_cbcmac, &scratch, out + bytes, &n, a, b, blen); if (result < 0) goto error_ccm_mac; @@ -344,15 +275,10 @@ ssize_t wusb_prf(void *out, size_t out_size, } result = bytes; - kfree(scratch); -error_alloc_scratch: error_ccm_mac: -error_setkey_aes: - crypto_free_cipher(tfm_aes); -error_alloc_aes: -error_setkey_cbc: - crypto_free_sync_skcipher(tfm_cbc); -error_alloc_cbc: +error_setkey_cbcmac: + crypto_free_shash(tfm_cbcmac); +error_alloc_cbcmac: return result; } @@ -377,12 +303,8 @@ static int wusb_oob_mic_verify(void) { int result; u8 mic[8]; - /* WUSB1.0[A.2] test vectors - * - * Need to keep it in the local stack as GCC 4.1.3something - * messes up and generates noise. - */ - struct usb_handshake stv_hsmic_hs = { + /* WUSB1.0[A.2] test vectors */ + static const struct usb_handshake stv_hsmic_hs = { .bMessageNumber = 2, .bStatus = 00, .tTKID = { 0x76, 0x98, 0x01 }, @@ -457,11 +379,8 @@ static int wusb_key_derive_verify(void) { int result = 0; struct wusb_keydvt_out keydvt_out; - /* These come from WUSB1.0[A.1] + 2006/12 errata - * NOTE: can't make this const or global -- somehow it seems - * the scatterlists for crypto get confused and we get - * bad data. There is no doc on this... */ - struct wusb_keydvt_in stv_keydvt_in_a1 = { + /* These come from WUSB1.0[A.1] + 2006/12 errata */ + static const struct wusb_keydvt_in stv_keydvt_in_a1 = { .hnonce = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f |