From 16b114a6d7973cf027e4c2b23eae1076eaf98c25 Mon Sep 17 00:00:00 2001 From: "Felipe F. Tonello" Date: Mon, 8 Aug 2016 21:30:04 +0100 Subject: usb: gadget: fix usb_ep_align_maybe endianness and new usb_ep_align USB spec specifies wMaxPacketSize to be little endian (as other properties), so when using this variable in the driver we should convert to the current CPU endianness if necessary. This patch also introduces usb_ep_align() which does always returns the aligned buffer size for an endpoint. This is useful to be used by USB requests allocator functions. Signed-off-by: Felipe F. Tonello Signed-off-by: Felipe Balbi --- include/linux/usb/gadget.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 612dbdfa388e..3cc93237ff98 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -417,9 +417,21 @@ static inline struct usb_gadget *dev_to_usb_gadget(struct device *dev) #define gadget_for_each_ep(tmp, gadget) \ list_for_each_entry(tmp, &(gadget)->ep_list, ep_list) +/** + * usb_ep_align - returns @len aligned to ep's maxpacketsize. + * @ep: the endpoint whose maxpacketsize is used to align @len + * @len: buffer size's length to align to @ep's maxpacketsize + * + * This helper is used to align buffer's size to an ep's maxpacketsize. + */ +static inline size_t usb_ep_align(struct usb_ep *ep, size_t len) +{ + return round_up(len, (size_t)le16_to_cpu(ep->desc->wMaxPacketSize)); +} + /** * usb_ep_align_maybe - returns @len aligned to ep's maxpacketsize if gadget - * requires quirk_ep_out_aligned_size, otherwise reguens len. + * requires quirk_ep_out_aligned_size, otherwise returns len. * @g: controller to check for quirk * @ep: the endpoint whose maxpacketsize is used to align @len * @len: buffer size's length to align to @ep's maxpacketsize @@ -430,8 +442,7 @@ static inline struct usb_gadget *dev_to_usb_gadget(struct device *dev) static inline size_t usb_ep_align_maybe(struct usb_gadget *g, struct usb_ep *ep, size_t len) { - return !g->quirk_ep_out_aligned_size ? len : - round_up(len, (size_t)ep->desc->wMaxPacketSize); + return g->quirk_ep_out_aligned_size ? usb_ep_align(ep, len) : len; } /** -- cgit v1.2.3 From 1a00b457a5482c3822bfc0fd64c088b2dba93e26 Mon Sep 17 00:00:00 2001 From: Felix Hädicke Date: Wed, 22 Jun 2016 01:12:08 +0200 Subject: usb: gadget: composite: let USB functions process ctrl reqs in cfg0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It can sometimes be necessary for gadget drivers to process non-standard control requests, which host devices can send without having sent USB_REQ_SET_CONFIGURATION. Therefore, the req_match() usb_function method is enhanced with the new parameter "config0". When a USB configuration is active, this parameter is false. When a non-core control request is processed in composite_setup(), without an active configuration, req_match() of the USB functions of all available configurations which implement this function, is called with config0=true. Then the control request gets processed by the first usb_function instance whose req_match() returns true. Signed-off-by: Felix Hädicke Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 16 ++++++++++------ drivers/usb/gadget/function/f_fs.c | 9 +++++++-- drivers/usb/gadget/function/f_printer.c | 6 +++++- include/linux/usb/composite.h | 3 ++- 4 files changed, 24 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 5ebe6af7976e..32176f779861 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1893,17 +1893,21 @@ unknown: /* functions always handle their interfaces and endpoints... * punt other recipients (other, WUSB, ...) to the current * configuration code. - * - * REVISIT it could make sense to let the composite device - * take such requests too, if that's ever needed: to work - * in config 0, etc. */ if (cdev->config) { list_for_each_entry(f, &cdev->config->functions, list) - if (f->req_match && f->req_match(f, ctrl)) + if (f->req_match && + f->req_match(f, ctrl, false)) goto try_fun_setup; - f = NULL; + } else { + struct usb_configuration *c; + list_for_each_entry(c, &cdev->configs, list) + list_for_each_entry(f, &c->functions, list) + if (f->req_match && + f->req_match(f, ctrl, true)) + goto try_fun_setup; } + f = NULL; switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_INTERFACE: diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index d7acab873836..d8f46f6233ac 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -99,7 +99,8 @@ static void ffs_func_disable(struct usb_function *); static int ffs_func_setup(struct usb_function *, const struct usb_ctrlrequest *); static bool ffs_func_req_match(struct usb_function *, - const struct usb_ctrlrequest *); + const struct usb_ctrlrequest *, + bool config0); static void ffs_func_suspend(struct usb_function *); static void ffs_func_resume(struct usb_function *); @@ -3136,10 +3137,14 @@ static int ffs_func_setup(struct usb_function *f, } static bool ffs_func_req_match(struct usb_function *f, - const struct usb_ctrlrequest *creq) + const struct usb_ctrlrequest *creq, + bool config0) { struct ffs_function *func = ffs_func_from_usb(f); + if (config0) + return false; + switch (creq->bRequestType & USB_RECIP_MASK) { case USB_RECIP_INTERFACE: return ffs_func_revmap_intf(func, diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 64706a789580..0de36cda6e41 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -889,13 +889,17 @@ static void printer_soft_reset(struct printer_dev *dev) /*-------------------------------------------------------------------------*/ static bool gprinter_req_match(struct usb_function *f, - const struct usb_ctrlrequest *ctrl) + const struct usb_ctrlrequest *ctrl, + bool config0) { struct printer_dev *dev = func_to_printer(f); u16 w_index = le16_to_cpu(ctrl->wIndex); u16 w_value = le16_to_cpu(ctrl->wValue); u16 w_length = le16_to_cpu(ctrl->wLength); + if (config0) + return false; + if ((ctrl->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE || (ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) return false; diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 2b81b24eb5aa..4616a49a1c2e 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -220,7 +220,8 @@ struct usb_function { int (*setup)(struct usb_function *, const struct usb_ctrlrequest *); bool (*req_match)(struct usb_function *, - const struct usb_ctrlrequest *); + const struct usb_ctrlrequest *, + bool config0); void (*suspend)(struct usb_function *); void (*resume)(struct usb_function *); -- cgit v1.2.3 From 60e7396f820fa67a007f2a2eb5d97d3e77a74881 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 22 Aug 2016 17:48:25 +0900 Subject: usb: gadget: add a new quirk to avoid skb_reserve in u_ether.c Some platforms (e.g. USB-DMAC on R-Car SoCs) has memory alignment restriction. If memory alignment is not match, the usb peripheral driver decides not to use the DMA controller. Then, the performance is not good. In the case of u_ether.c, since it calls skb_reserve() in rx_submit(), it is possible to cause memory alignment mismatch. So, this patch adds a new quirk "quirk_avoids_skb_reserve" to avoid skb_reserve() calling in u_ether.c to improve performance. A peripheral driver will set this flag and network gadget drivers (e.g. f_ncm.c) will reference the flag via gadget_avoids_skb_reserve(). Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- include/linux/usb/gadget.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'include/linux') diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 3cc93237ff98..8e81f9eb95e4 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -346,6 +346,8 @@ struct usb_gadget_ops { * or B-Peripheral wants to take host role. * @quirk_ep_out_aligned_size: epout requires buffer size to be aligned to * MaxPacketSize. + * @quirk_avoids_skb_reserve: udc/platform wants to avoid skb_reserve() in + * u_ether.c to improve performance. * @is_selfpowered: if the gadget is self-powered. * @deactivated: True if gadget is deactivated - in deactivated state it cannot * be connected. @@ -398,6 +400,7 @@ struct usb_gadget { unsigned quirk_altset_not_supp:1; unsigned quirk_stall_not_supp:1; unsigned quirk_zlp_not_supp:1; + unsigned quirk_avoids_skb_reserve:1; unsigned is_selfpowered:1; unsigned deactivated:1; unsigned connected:1; @@ -473,6 +476,16 @@ static inline int gadget_is_zlp_supported(struct usb_gadget *g) return !g->quirk_zlp_not_supp; } +/** + * gadget_avoids_skb_reserve - return true iff the hardware would like to avoid + * skb_reserve to improve performance. + * @g: controller to check for quirk + */ +static inline int gadget_avoids_skb_reserve(struct usb_gadget *g) +{ + return g->quirk_avoids_skb_reserve; +} + /** * gadget_is_dualspeed - return true iff the hardware handles high speed * @g: controller that might support both high and full speeds -- cgit v1.2.3 From 6691402313ddda232e6a401af8841b5fe676a62f Mon Sep 17 00:00:00 2001 From: Tal Shorer Date: Tue, 16 Aug 2016 19:04:47 +0300 Subject: usb: ulpi: add new api functions, {read|write}_dev() Add these two new api callbacks to struct ulpi_ops. These are different than read, write in that they pass the parent device directly instead of via the ops argument. They are intended to replace the old api functions. If the new api callbacks are missing, revert to calling the old ones as before. Acked-by: Heikki Krogerus Signed-off-by: Tal Shorer Signed-off-by: Felipe Balbi --- drivers/usb/common/ulpi.c | 8 ++++++-- include/linux/ulpi/interface.h | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index d1f419c7cddb..a877ddbbe826 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -21,13 +21,17 @@ int ulpi_read(struct ulpi *ulpi, u8 addr) { - return ulpi->ops->read(ulpi->ops, addr); + if (!ulpi->ops->read_dev) + return ulpi->ops->read(ulpi->ops, addr); + return ulpi->ops->read_dev(ulpi->dev.parent, addr); } EXPORT_SYMBOL_GPL(ulpi_read); int ulpi_write(struct ulpi *ulpi, u8 addr, u8 val) { - return ulpi->ops->write(ulpi->ops, addr, val); + if (!ulpi->ops->write_dev) + return ulpi->ops->write(ulpi->ops, addr, val); + return ulpi->ops->write_dev(ulpi->dev.parent, addr, val); } EXPORT_SYMBOL_GPL(ulpi_write); diff --git a/include/linux/ulpi/interface.h b/include/linux/ulpi/interface.h index 4de8ab491038..d8189d08eddb 100644 --- a/include/linux/ulpi/interface.h +++ b/include/linux/ulpi/interface.h @@ -15,6 +15,8 @@ struct ulpi_ops { struct device *dev; int (*read)(struct ulpi_ops *ops, u8 addr); int (*write)(struct ulpi_ops *ops, u8 addr, u8 val); + int (*read_dev)(struct device *dev, u8 addr); + int (*write_dev)(struct device *dev, u8 addr, u8 val); }; struct ulpi *ulpi_register_interface(struct device *, struct ulpi_ops *); -- cgit v1.2.3 From 5c42f38795645834a7c23998bd74d35a37bff078 Mon Sep 17 00:00:00 2001 From: Tal Shorer Date: Tue, 16 Aug 2016 19:04:49 +0300 Subject: usb: ulpi: remove calls to old api callbacks Now that all users use the new api callbacks, remove the old api callbacks and force new interface drivers to use the new api. Acked-by: Heikki Krogerus Signed-off-by: Tal Shorer Signed-off-by: Felipe Balbi --- drivers/usb/common/ulpi.c | 4 ---- include/linux/ulpi/interface.h | 2 -- 2 files changed, 6 deletions(-) (limited to 'include/linux') diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index a877ddbbe826..43142c3d94d7 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -21,16 +21,12 @@ int ulpi_read(struct ulpi *ulpi, u8 addr) { - if (!ulpi->ops->read_dev) - return ulpi->ops->read(ulpi->ops, addr); return ulpi->ops->read_dev(ulpi->dev.parent, addr); } EXPORT_SYMBOL_GPL(ulpi_read); int ulpi_write(struct ulpi *ulpi, u8 addr, u8 val) { - if (!ulpi->ops->write_dev) - return ulpi->ops->write(ulpi->ops, addr, val); return ulpi->ops->write_dev(ulpi->dev.parent, addr, val); } EXPORT_SYMBOL_GPL(ulpi_write); diff --git a/include/linux/ulpi/interface.h b/include/linux/ulpi/interface.h index d8189d08eddb..71f3c99771aa 100644 --- a/include/linux/ulpi/interface.h +++ b/include/linux/ulpi/interface.h @@ -13,8 +13,6 @@ struct ulpi; */ struct ulpi_ops { struct device *dev; - int (*read)(struct ulpi_ops *ops, u8 addr); - int (*write)(struct ulpi_ops *ops, u8 addr, u8 val); int (*read_dev)(struct device *dev, u8 addr); int (*write_dev)(struct device *dev, u8 addr, u8 val); }; -- cgit v1.2.3 From e6f74849784ccf275226d5d3ddfb96c71fa90383 Mon Sep 17 00:00:00 2001 From: Tal Shorer Date: Tue, 16 Aug 2016 19:04:50 +0300 Subject: usb: ulpi: rename operations {read|write}_dev to simply {read|write} With the removal of the old {read|write} operations, we can now safely rename the new api operations {read|write}_dev to use the shorter and clearer names {read|write}, respectively. Acked-by: Heikki Krogerus Signed-off-by: Tal Shorer Signed-off-by: Felipe Balbi --- drivers/usb/common/ulpi.c | 4 ++-- drivers/usb/dwc3/ulpi.c | 4 ++-- include/linux/ulpi/interface.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 43142c3d94d7..fdaed7c26c12 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -21,13 +21,13 @@ int ulpi_read(struct ulpi *ulpi, u8 addr) { - return ulpi->ops->read_dev(ulpi->dev.parent, addr); + return ulpi->ops->read(ulpi->dev.parent, addr); } EXPORT_SYMBOL_GPL(ulpi_read); int ulpi_write(struct ulpi *ulpi, u8 addr, u8 val) { - return ulpi->ops->write_dev(ulpi->dev.parent, addr, val); + return ulpi->ops->write(ulpi->dev.parent, addr, val); } EXPORT_SYMBOL_GPL(ulpi_write); diff --git a/drivers/usb/dwc3/ulpi.c b/drivers/usb/dwc3/ulpi.c index 94eeb7a42dbd..51ac939b2dfc 100644 --- a/drivers/usb/dwc3/ulpi.c +++ b/drivers/usb/dwc3/ulpi.c @@ -66,8 +66,8 @@ static int dwc3_ulpi_write(struct device *dev, u8 addr, u8 val) } static struct ulpi_ops dwc3_ulpi_ops = { - .read_dev = dwc3_ulpi_read, - .write_dev = dwc3_ulpi_write, + .read = dwc3_ulpi_read, + .write = dwc3_ulpi_write, }; int dwc3_ulpi_init(struct dwc3 *dwc) diff --git a/include/linux/ulpi/interface.h b/include/linux/ulpi/interface.h index 71f3c99771aa..ac3cd8058d9c 100644 --- a/include/linux/ulpi/interface.h +++ b/include/linux/ulpi/interface.h @@ -13,8 +13,8 @@ struct ulpi; */ struct ulpi_ops { struct device *dev; - int (*read_dev)(struct device *dev, u8 addr); - int (*write_dev)(struct device *dev, u8 addr, u8 val); + int (*read)(struct device *dev, u8 addr); + int (*write)(struct device *dev, u8 addr, u8 val); }; struct ulpi *ulpi_register_interface(struct device *, struct ulpi_ops *); -- cgit v1.2.3 From 042b0f31b2a87799a9c832f71474c5be3517e139 Mon Sep 17 00:00:00 2001 From: Tal Shorer Date: Tue, 16 Aug 2016 19:04:51 +0300 Subject: usb: ulpi: remove "dev" field from struct ulpi_ops Operations now use ulpi->dev.parent directly instead of via the ulpi_ops struct, making this field unused. Remove it. Acked-by: Heikki Krogerus Signed-off-by: Tal Shorer Signed-off-by: Felipe Balbi --- drivers/usb/common/ulpi.c | 1 - include/linux/ulpi/interface.h | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index fdaed7c26c12..0439e9638813 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -212,7 +212,6 @@ struct ulpi *ulpi_register_interface(struct device *dev, struct ulpi_ops *ops) return ERR_PTR(-ENOMEM); ulpi->ops = ops; - ops->dev = dev; ret = ulpi_register(dev, ulpi); if (ret) { diff --git a/include/linux/ulpi/interface.h b/include/linux/ulpi/interface.h index ac3cd8058d9c..cdedac87ed48 100644 --- a/include/linux/ulpi/interface.h +++ b/include/linux/ulpi/interface.h @@ -4,15 +4,14 @@ #include struct ulpi; +struct device; /** * struct ulpi_ops - ULPI register access - * @dev: the interface provider * @read: read operation for ULPI register access * @write: write operation for ULPI register access */ struct ulpi_ops { - struct device *dev; int (*read)(struct device *dev, u8 addr); int (*write)(struct device *dev, u8 addr, u8 val); }; -- cgit v1.2.3 From b9454f90c9432e1a70389c26c34e972090efcec6 Mon Sep 17 00:00:00 2001 From: Tal Shorer Date: Tue, 16 Aug 2016 19:04:52 +0300 Subject: usb: ulpi: make ops struct constant None of the core ulpi functions perform any changes to the operations struct, and logically as a struct that contains function pointers there's no reason it shouldn't be constant. Acked-by: Heikki Krogerus Signed-off-by: Tal Shorer Signed-off-by: Felipe Balbi --- drivers/usb/common/ulpi.c | 3 ++- include/linux/ulpi/driver.h | 2 +- include/linux/ulpi/interface.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 0439e9638813..d4ff6df859eb 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -202,7 +202,8 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi) * Allocates and registers a ULPI device and an interface for it. Called from * the USB controller that provides the ULPI interface. */ -struct ulpi *ulpi_register_interface(struct device *dev, struct ulpi_ops *ops) +struct ulpi *ulpi_register_interface(struct device *dev, + const struct ulpi_ops *ops) { struct ulpi *ulpi; int ret; diff --git a/include/linux/ulpi/driver.h b/include/linux/ulpi/driver.h index 388f6e08b9d4..a44408f6d532 100644 --- a/include/linux/ulpi/driver.h +++ b/include/linux/ulpi/driver.h @@ -15,7 +15,7 @@ struct ulpi_ops; */ struct ulpi { struct ulpi_device_id id; - struct ulpi_ops *ops; + const struct ulpi_ops *ops; struct device dev; }; diff --git a/include/linux/ulpi/interface.h b/include/linux/ulpi/interface.h index cdedac87ed48..a2011a919eb6 100644 --- a/include/linux/ulpi/interface.h +++ b/include/linux/ulpi/interface.h @@ -16,7 +16,7 @@ struct ulpi_ops { int (*write)(struct device *dev, u8 addr, u8 val); }; -struct ulpi *ulpi_register_interface(struct device *, struct ulpi_ops *); +struct ulpi *ulpi_register_interface(struct device *, const struct ulpi_ops *); void ulpi_unregister_interface(struct ulpi *); #endif /* __LINUX_ULPI_INTERFACE_H */ -- cgit v1.2.3