USB patches for 3.14-rc1

Here's the big USB pull request for 3.14-rc1
 
 Lots of little things all over the place, and the usual USB gadget
 updates, and XHCI fixes (some for an issue reported by a lot of people.)
 USB PHY updates as well as chipidea updates and fixes.
 
 All of these have been in the linux-next tree with no reported issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iEYEABECAAYFAlLdjwIACgkQMUfUDdst+ylBIQCgkRoR8lJc0L5lZ3fugIJL4IzZ
 j6AAn0nBLP6VI0cvUEi3TcrPTzv4MEuL
 =Yb+I
 -----END PGP SIGNATURE-----

Merge tag 'usb-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB updates from Greg KH:
 "Here's the big USB pull request for 3.14-rc1

  Lots of little things all over the place, and the usual USB gadget
  updates, and XHCI fixes (some for an issue reported by a lot of
  people).  USB PHY updates as well as chipidea updates and fixes.

  All of these have been in the linux-next tree with no reported issues"

* tag 'usb-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (318 commits)
  usb: chipidea: udc: using MultO at TD as real mult value for ISO-TX
  usb: chipidea: need to mask INT_STATUS when write otgsc
  usb: chipidea: put hw_phymode_configure before ci_usb_phy_init
  usb: chipidea: Fix Internal error: : 808 [#1] ARM related to STS flag
  usb: chipidea: imx: set CI_HDRC_IMX28_WRITE_FIX for imx28
  usb: chipidea: add freescale imx28 special write register method
  usb: ehci: add freescale imx28 special write register method
  usb: core: check for valid id_table when using the RefId feature
  usb: cdc-wdm: resp_count can be 0 even if WDM_READ is set
  usb: core: bail out if user gives an unknown RefId when using new_id
  usb: core: allow a reference device for new_id
  usb: core: add sanity checks when using bInterfaceClass with new_id
  USB: image: correct spelling mistake in comment
  USB: c67x00: correct spelling mistakes in comments
  usb: delete non-required instances of include <linux/init.h>
  usb:hub set hub->change_bits when over-current happens
  Revert "usb: chipidea: imx: set CI_HDRC_IMX28_WRITE_FIX for imx28"
  xhci: Set scatter-gather limit to avoid failed block writes.
  xhci: Avoid infinite loop when sg urb requires too many trbs
  usb: gadget: remove unused variable in gr_queue_int()
  ...
This commit is contained in:
Linus Torvalds 2014-01-20 16:13:02 -08:00
commit ec513b16c4
367 changed files with 16205 additions and 8087 deletions

View File

@ -0,0 +1,9 @@
What: /config/usb-gadget/gadget/functions/ffs.name
Date: Nov 2013
KenelVersion: 3.13
Description: The purpose of this directory is to create and remove it.
A corresponding USB function instance is created/removed.
There are no attributes here.
All parameters are set through FunctionFS.

View File

@ -0,0 +1,8 @@
What: /config/usb-gadget/gadget/functions/Loopback.name
Date: Nov 2013
KenelVersion: 3.13
Description:
The attributes:
qlen - depth of loopback queue
bulk_buflen - buffer length

View File

@ -0,0 +1,12 @@
What: /config/usb-gadget/gadget/functions/SourceSink.name
Date: Nov 2013
KenelVersion: 3.13
Description:
The attributes:
pattern - 0 (all zeros), 1 (mod63), 2 (none)
isoc_interval - 1..16
isoc_maxpacket - 0 - 1023 (fs), 0 - 1024 (hs/ss)
isoc_mult - 0..2 (hs/ss only)
isoc_maxburst - 0..15 (ss only)
qlen - buffer length

View File

@ -50,13 +50,19 @@ Description:
This may allow the driver to support more hardware than
was included in the driver's static device ID support
table at compile time. The format for the device ID is:
idVendor idProduct bInterfaceClass.
idVendor idProduct bInterfaceClass RefIdVendor RefIdProduct
The vendor ID and device ID fields are required, the
interface class is optional.
rest is optional. The Ref* tuple can be used to tell the
driver to use the same driver_data for the new device as
it is used for the reference device.
Upon successfully adding an ID, the driver will probe
for the device and attempt to bind to it. For example:
# echo "8086 10f5" > /sys/bus/usb/drivers/foo/new_id
Here add a new device (0458:7045) using driver_data from
an already supported device (0458:704c):
# echo "0458 7045 0 0458 704c" > /sys/bus/usb/drivers/foo/new_id
Reading from this file will list all dynamically added
device IDs in the same format, with one entry per
line. For example:

View File

@ -0,0 +1,16 @@
What: /sys/bus/platform/devices/tahvo-usb/otg_mode
Date: December 2013
Contact: Aaro Koskinen <aaro.koskinen@iki.fi>
Description:
Set or read the current OTG mode. Valid values are "host" and
"peripheral".
Reading: returns the current mode.
What: /sys/bus/platform/devices/tahvo-usb/vbus
Date: December 2013
Contact: Aaro Koskinen <aaro.koskinen@iki.fi>
Description:
Read the current VBUS state.
Reading: returns "on" or "off".

View File

@ -0,0 +1,15 @@
BROADCOM KONA USB2 PHY
Required properties:
- compatible: brcm,kona-usb2-phy
- reg: offset and length of the PHY registers
- #phy-cells: must be 0
Refer to phy/phy-bindings.txt for the generic PHY binding properties
Example:
usbphy: usb-phy@3f130000 {
compatible = "brcm,kona-usb2-phy";
reg = <0x3f130000 0x28>;
#phy-cells = <0>;
};

View File

@ -7,6 +7,14 @@ Required properties:
- snps,dwc2: A generic DWC2 USB controller with default parameters.
- reg : Should contain 1 register range (address and length)
- interrupts : Should contain 1 interrupt
- clocks: clock provider specifier
- clock-names: shall be "otg"
Refer to clk/clock-bindings.txt for generic clock consumer properties
Optional properties:
- phys: phy provider specifier
- phy-names: shall be "device"
Refer to phy/phy-bindings.txt for generic phy consumer properties
Example:
@ -14,4 +22,8 @@ Example:
compatible = "ralink,rt3050-usb, snps,dwc2";
reg = <0x101c0000 40000>;
interrupts = <18>;
clocks = <&usb_otg_ahb_clk>;
clock-names = "otg";
phys = <&usbphy>;
phy-names = "usb2-phy";
};

View File

@ -0,0 +1,28 @@
USB Peripheral Controller driver for Aeroflex Gaisler GRUSBDC.
The GRUSBDC USB Device Controller core is available in the GRLIB VHDL
IP core library.
Note: In the ordinary environment for the core, a Leon SPARC system,
these properties are built from information in the AMBA plug&play.
Required properties:
- name : Should be "GAISLER_USBDC" or "01_021"
- reg : Address and length of the register set for the device
- interrupts : Interrupt numbers for this device
Optional properties:
- epobufsizes : An array of buffer sizes for OUT endpoints. If the property is
not present, or for endpoints outside of the array, 1024 is assumed by
the driver.
- epibufsizes : An array of buffer sizes for IN endpoints. If the property is
not present, or for endpoints outside of the array, 1024 is assumed by
the driver.
For further information look in the documentation for the GLIB IP core library:
http://www.gaisler.com/products/grlib/grip.pdf

View File

@ -87,6 +87,8 @@ Required properties:
e.g. USB3 PHY and SATA PHY on OMAP5.
"ti,control-phy-dra7usb2" - if it has power down register like USB2 PHY on
DRA7 platform.
"ti,control-phy-am437usb2" - if it has power down register like USB2 PHY on
AM437 platform.
- reg : Address and length of the register set for the device. It contains
the address of "otghs_control" for control-phy-otghs or "power" register
for other types.

View File

@ -8,43 +8,7 @@
#define is_usb0_device(config) 0
#endif
struct omap_usb_config {
/* Configure drivers according to the connectors on your board:
* - "A" connector (rectagular)
* ... for host/OHCI use, set "register_host".
* - "B" connector (squarish) or "Mini-B"
* ... for device/gadget use, set "register_dev".
* - "Mini-AB" connector (very similar to Mini-B)
* ... for OTG use as device OR host, initialize "otg"
*/
unsigned register_host:1;
unsigned register_dev:1;
u8 otg; /* port number, 1-based: usb1 == 2 */
u8 hmc_mode;
/* implicitly true if otg: host supports remote wakeup? */
u8 rwc;
/* signaling pins used to talk to transceiver on usbN:
* 0 == usbN unused
* 2 == usb0-only, using internal transceiver
* 3 == 3 wire bidirectional
* 4 == 4 wire bidirectional
* 6 == 6 wire unidirectional (or TLL)
*/
u8 pins[3];
struct platform_device *udc_device;
struct platform_device *ohci_device;
struct platform_device *otg_device;
u32 (*usb0_init)(unsigned nwires, unsigned is_device);
u32 (*usb1_init)(unsigned nwires);
u32 (*usb2_init)(unsigned nwires, unsigned alt_pingroup);
int (*ocpi_enable)(void);
};
#include <linux/platform_data/usb-omap1.h>
void omap_otg_init(struct omap_usb_config *config);

View File

@ -57,4 +57,10 @@ config PHY_EXYNOS_DP_VIDEO
help
Support for Display Port PHY found on Samsung EXYNOS SoCs.
config BCM_KONA_USB2_PHY
tristate "Broadcom Kona USB2 PHY Driver"
depends on GENERIC_PHY
help
Enable this to support the Broadcom Kona USB 2.0 PHY.
endmenu

View File

@ -3,6 +3,7 @@
#
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o

View File

@ -0,0 +1,158 @@
/*
* phy-bcm-kona-usb2.c - Broadcom Kona USB2 Phy Driver
*
* Copyright (C) 2013 Linaro Limited
* Matt Porter <mporter@linaro.org>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#define OTGCTL (0)
#define OTGCTL_OTGSTAT2 BIT(31)
#define OTGCTL_OTGSTAT1 BIT(30)
#define OTGCTL_PRST_N_SW BIT(11)
#define OTGCTL_HRESET_N BIT(10)
#define OTGCTL_UTMI_LINE_STATE1 BIT(9)
#define OTGCTL_UTMI_LINE_STATE0 BIT(8)
#define P1CTL (8)
#define P1CTL_SOFT_RESET BIT(1)
#define P1CTL_NON_DRIVING BIT(0)
struct bcm_kona_usb {
void __iomem *regs;
};
static void bcm_kona_usb_phy_power(struct bcm_kona_usb *phy, int on)
{
u32 val;
val = readl(phy->regs + OTGCTL);
if (on) {
/* Configure and power PHY */
val &= ~(OTGCTL_OTGSTAT2 | OTGCTL_OTGSTAT1 |
OTGCTL_UTMI_LINE_STATE1 | OTGCTL_UTMI_LINE_STATE0);
val |= OTGCTL_PRST_N_SW | OTGCTL_HRESET_N;
} else {
val &= ~(OTGCTL_PRST_N_SW | OTGCTL_HRESET_N);
}
writel(val, phy->regs + OTGCTL);
}
static int bcm_kona_usb_phy_init(struct phy *gphy)
{
struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
u32 val;
/* Soft reset PHY */
val = readl(phy->regs + P1CTL);
val &= ~P1CTL_NON_DRIVING;
val |= P1CTL_SOFT_RESET;
writel(val, phy->regs + P1CTL);
writel(val & ~P1CTL_SOFT_RESET, phy->regs + P1CTL);
/* Reset needs to be asserted for 2ms */
mdelay(2);
writel(val | P1CTL_SOFT_RESET, phy->regs + P1CTL);
return 0;
}
static int bcm_kona_usb_phy_power_on(struct phy *gphy)
{
struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
bcm_kona_usb_phy_power(phy, 1);
return 0;
}
static int bcm_kona_usb_phy_power_off(struct phy *gphy)
{
struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
bcm_kona_usb_phy_power(phy, 0);
return 0;
}
static struct phy_ops ops = {
.init = bcm_kona_usb_phy_init,
.power_on = bcm_kona_usb_phy_power_on,
.power_off = bcm_kona_usb_phy_power_off,
.owner = THIS_MODULE,
};
static int bcm_kona_usb2_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct bcm_kona_usb *phy;
struct resource *res;
struct phy *gphy;
struct phy_provider *phy_provider;
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
phy->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(phy->regs))
return PTR_ERR(phy->regs);
platform_set_drvdata(pdev, phy);
gphy = devm_phy_create(dev, &ops, NULL);
if (IS_ERR(gphy))
return PTR_ERR(gphy);
/* The Kona PHY supports an 8-bit wide UTMI interface */
phy_set_bus_width(gphy, 8);
phy_set_drvdata(gphy, phy);
phy_provider = devm_of_phy_provider_register(dev,
of_phy_simple_xlate);
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
return 0;
}
static const struct of_device_id bcm_kona_usb2_dt_ids[] = {
{ .compatible = "brcm,kona-usb2-phy" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, bcm_kona_usb2_dt_ids);
static struct platform_driver bcm_kona_usb2_driver = {
.probe = bcm_kona_usb2_probe,
.driver = {
.name = "bcm-kona-usb2",
.owner = THIS_MODULE,
.of_match_table = bcm_kona_usb2_dt_ids,
},
};
module_platform_driver(bcm_kona_usb2_driver);
MODULE_ALIAS("platform:bcm-kona-usb2");
MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
MODULE_DESCRIPTION("BCM Kona USB 2.0 PHY driver");
MODULE_LICENSE("GPL v2");

View File

@ -3498,6 +3498,7 @@ static int octeon_usb_driver_probe(struct device *dev)
kfree(hcd);
return -1;
}
device_wakeup_enable(hcd->self.controller);
dev_dbg(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq);

View File

@ -2270,6 +2270,8 @@ static int oz_plat_probe(struct platform_device *dev)
usb_put_hcd(hcd);
return -1;
}
device_wakeup_enable(hcd->self.controller);
spin_lock_bh(&g_hcdlock);
g_ozhcd = ozhcd;
spin_unlock_bh(&g_hcdlock);

View File

@ -94,8 +94,6 @@ source "drivers/usb/wusbcore/Kconfig"
source "drivers/usb/host/Kconfig"
source "drivers/usb/musb/Kconfig"
source "drivers/usb/renesas_usbhs/Kconfig"
source "drivers/usb/class/Kconfig"
@ -106,6 +104,8 @@ source "drivers/usb/image/Kconfig"
endif
source "drivers/usb/musb/Kconfig"
source "drivers/usb/dwc3/Kconfig"
source "drivers/usb/dwc2/Kconfig"

View File

@ -35,7 +35,6 @@
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/mutex.h>

View File

@ -27,7 +27,6 @@
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/firmware.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>

View File

@ -57,7 +57,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/crc32.h>
#include <linux/usb.h>
#include <linux/firmware.h>

View File

@ -170,9 +170,9 @@ struct usbatm_control {
static void usbatm_atm_dev_close(struct atm_dev *atm_dev);
static int usbatm_atm_open(struct atm_vcc *vcc);
static void usbatm_atm_close(struct atm_vcc *vcc);
static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user * arg);
static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user *arg);
static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);
static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page);
static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t *pos, char *page);
static struct atmdev_ops usbatm_atm_devops = {
.dev_close = usbatm_atm_dev_close,
@ -739,7 +739,7 @@ static void usbatm_atm_dev_close(struct atm_dev *atm_dev)
usbatm_put_instance(instance); /* taken in usbatm_atm_init */
}
static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page)
static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t *pos, char *page)
{
struct usbatm_data *instance = atm_dev->dev_data;
int left = *pos;
@ -895,7 +895,7 @@ static void usbatm_atm_close(struct atm_vcc *vcc)
}
static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd,
void __user * arg)
void __user *arg)
{
struct usbatm_data *instance = atm_dev->dev_data;

View File

@ -2,8 +2,6 @@
# Makefile for Cypress C67X00 USB Controller
#
ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
obj-$(CONFIG_USB_C67X00_HCD) += c67x00.o
c67x00-y := c67x00-drv.o c67x00-ll-hpi.o c67x00-hcd.o c67x00-sched.o

View File

@ -384,6 +384,8 @@ int c67x00_hcd_probe(struct c67x00_sie *sie)
goto err2;
}
device_wakeup_enable(hcd->self.controller);
spin_lock_irqsave(&sie->lock, flags);
sie->private_data = c67x00;
sie->irq = c67x00_hcd_irq;

View File

@ -45,7 +45,7 @@
/*
* The current implementation switches between _STD (default) and _ISO (when
* isochronous transfers are scheduled), in order to optimize the throughput
* in normal cicrumstances, but also provide good isochronous behaviour.
* in normal circumstances, but also provide good isochronous behaviour.
*
* Bandwidth is described in bit time so with a 12MHz USB clock and 1ms
* frames; there are 12000 bit times per frame.

View File

@ -22,6 +22,7 @@
*/
#include <asm/byteorder.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/usb/c67x00.h>
@ -62,8 +63,8 @@ struct c67x00_lcp_int_data {
* HPI implementation
*
* The c67x00 chip also support control via SPI or HSS serial
* interfaces. However, this driver assumes that register access can
* be performed from IRQ context. While this is a safe assuption with
* interfaces. However, this driver assumes that register access can
* be performed from IRQ context. While this is a safe assumption with
* the HPI interface, it is not true for the serial interfaces.
*/
@ -73,13 +74,22 @@ struct c67x00_lcp_int_data {
#define HPI_ADDR 2
#define HPI_STATUS 3
/*
* According to CY7C67300 specification (tables 140 and 141) HPI read and
* write cycle duration Tcyc must be at least 6T long, where T is 1/48MHz,
* which is 125ns.
*/
#define HPI_T_CYC_NS 125
static inline u16 hpi_read_reg(struct c67x00_device *dev, int reg)
{
ndelay(HPI_T_CYC_NS);
return __raw_readw(dev->hpi.base + reg * dev->hpi.regstep);
}
static inline void hpi_write_reg(struct c67x00_device *dev, int reg, u16 value)
{
ndelay(HPI_T_CYC_NS);
__raw_writew(value, dev->hpi.base + reg * dev->hpi.regstep);
}

View File

@ -144,8 +144,6 @@ struct c67x00_urb_priv {
/* -------------------------------------------------------------------------- */
#ifdef DEBUG
/**
* dbg_td - Dump the contents of the TD
*/
@ -166,16 +164,8 @@ static void dbg_td(struct c67x00_hcd *c67x00, struct c67x00_td *td, char *msg)
dev_dbg(dev, "retry_cnt: 0x%02x\n", td->retry_cnt);
dev_dbg(dev, "residue: 0x%02x\n", td->residue);
dev_dbg(dev, "next_td_addr: 0x%04x\n", td_next_td_addr(td));
dev_dbg(dev, "data:");
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1,
td->data, td_length(td), 1);
dev_dbg(dev, "data: %*ph\n", td_length(td), td->data);
}
#else /* DEBUG */
static inline void
dbg_td(struct c67x00_hcd *c67x00, struct c67x00_td *td, char *msg) { }
#endif /* DEBUG */
/* -------------------------------------------------------------------------- */
/* Helper functions */
@ -372,6 +362,13 @@ int c67x00_urb_enqueue(struct usb_hcd *hcd,
struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
int port = get_root_port(urb->dev)-1;
/* Allocate and initialize urb private data */
urbp = kzalloc(sizeof(*urbp), mem_flags);
if (!urbp) {
ret = -ENOMEM;
goto err_urbp;
}
spin_lock_irqsave(&c67x00->lock, flags);
/* Make sure host controller is running */
@ -384,13 +381,6 @@ int c67x00_urb_enqueue(struct usb_hcd *hcd,
if (ret)
goto err_not_linked;
/* Allocate and initialize urb private data */
urbp = kzalloc(sizeof(*urbp), mem_flags);
if (!urbp) {
ret = -ENOMEM;
goto err_urbp;
}
INIT_LIST_HEAD(&urbp->hep_node);
urbp->urb = urb;
urbp->port = port;
@ -453,11 +443,11 @@ int c67x00_urb_enqueue(struct usb_hcd *hcd,
return 0;
err_epdata:
kfree(urbp);
err_urbp:
usb_hcd_unlink_urb_from_ep(hcd, urb);
err_not_linked:
spin_unlock_irqrestore(&c67x00->lock, flags);
kfree(urbp);
err_urbp:
return ret;
}
@ -780,7 +770,8 @@ static int c67x00_add_iso_urb(struct c67x00_hcd *c67x00, struct urb *urb)
ret = c67x00_create_td(c67x00, urb, td_buf, len, pid, 0,
urbp->cnt);
if (ret) {
printk(KERN_DEBUG "create failed: %d\n", ret);
dev_dbg(c67x00_hcd_dev(c67x00), "create failed: %d\n",
ret);
urb->iso_frame_desc[urbp->cnt].actual_length = 0;
urb->iso_frame_desc[urbp->cnt].status = ret;
if (urbp->cnt + 1 == urb->number_of_packets)

View File

@ -17,5 +17,5 @@ ifneq ($(CONFIG_PCI),)
endif
ifneq ($(CONFIG_OF),)
obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_imx.o usbmisc_imx.o
obj-$(CONFIG_USB_CHIPIDEA) += usbmisc_imx.o ci_hdrc_imx.o
endif

View File

@ -25,6 +25,35 @@
#define CI_HDRC_PAGE_SIZE 4096ul /* page size for TD's */
#define ENDPT_MAX 32
/******************************************************************************
* REGISTERS
*****************************************************************************/
/* register indices */
enum ci_hw_regs {
CAP_CAPLENGTH,
CAP_HCCPARAMS,
CAP_DCCPARAMS,
CAP_TESTMODE,
CAP_LAST = CAP_TESTMODE,
OP_USBCMD,
OP_USBSTS,
OP_USBINTR,
OP_DEVICEADDR,
OP_ENDPTLISTADDR,
OP_PORTSC,
OP_DEVLC,
OP_OTGSC,
OP_USBMODE,
OP_ENDPTSETUPSTAT,
OP_ENDPTPRIME,
OP_ENDPTFLUSH,
OP_ENDPTSTAT,
OP_ENDPTCOMPLETE,
OP_ENDPTCTRL,
/* endptctrl1..15 follow */
OP_LAST = OP_ENDPTCTRL + ENDPT_MAX / 2,
};
/******************************************************************************
* STRUCTURES
*****************************************************************************/
@ -98,7 +127,7 @@ struct hw_bank {
void __iomem *cap;
void __iomem *op;
size_t size;
void __iomem **regmap;
void __iomem *regmap[OP_LAST + 1];
};
/**
@ -135,6 +164,7 @@ struct hw_bank {
* @id_event: indicates there is an id event, and handled at ci_otg_work
* @b_sess_valid_event: indicates there is a vbus event, and handled
* at ci_otg_work
* @imx28_write_fix: Freescale imx28 needs swp instruction for writing
*/
struct ci_hdrc {
struct device *dev;
@ -173,6 +203,7 @@ struct ci_hdrc {
struct dentry *debugfs;
bool id_event;
bool b_sess_valid_event;
bool imx28_write_fix;
};
static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
@ -209,38 +240,6 @@ static inline void ci_role_stop(struct ci_hdrc *ci)
ci->roles[role]->stop(ci);
}
/******************************************************************************
* REGISTERS
*****************************************************************************/
/* register size */
#define REG_BITS (32)
/* register indices */
enum ci_hw_regs {
CAP_CAPLENGTH,
CAP_HCCPARAMS,
CAP_DCCPARAMS,
CAP_TESTMODE,
CAP_LAST = CAP_TESTMODE,
OP_USBCMD,
OP_USBSTS,
OP_USBINTR,
OP_DEVICEADDR,
OP_ENDPTLISTADDR,
OP_PORTSC,
OP_DEVLC,
OP_OTGSC,
OP_USBMODE,
OP_ENDPTSETUPSTAT,
OP_ENDPTPRIME,
OP_ENDPTFLUSH,
OP_ENDPTSTAT,
OP_ENDPTCOMPLETE,
OP_ENDPTCTRL,
/* endptctrl1..15 follow */
OP_LAST = OP_ENDPTCTRL + ENDPT_MAX / 2,
};
/**
* hw_read: reads from a hw register
* @reg: register index
@ -253,6 +252,26 @@ static inline u32 hw_read(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask)
return ioread32(ci->hw_bank.regmap[reg]) & mask;
}
#ifdef CONFIG_SOC_IMX28
static inline void imx28_ci_writel(u32 val, volatile void __iomem *addr)
{
__asm__ ("swp %0, %0, [%1]" : : "r"(val), "r"(addr));
}
#else
static inline void imx28_ci_writel(u32 val, volatile void __iomem *addr)
{
}
#endif
static inline void __hw_write(struct ci_hdrc *ci, u32 val,
void __iomem *addr)
{
if (ci->imx28_write_fix)
imx28_ci_writel(val, addr);
else
iowrite32(val, addr);
}
/**
* hw_write: writes to a hw register
* @reg: register index
@ -266,7 +285,7 @@ static inline void hw_write(struct ci_hdrc *ci, enum ci_hw_regs reg,
data = (ioread32(ci->hw_bank.regmap[reg]) & ~mask)
| (data & mask);
iowrite32(data, ci->hw_bank.regmap[reg]);
__hw_write(ci, data, ci->hw_bank.regmap[reg]);
}
/**
@ -281,7 +300,7 @@ static inline u32 hw_test_and_clear(struct ci_hdrc *ci, enum ci_hw_regs reg,
{
u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask;
iowrite32(val, ci->hw_bank.regmap[reg]);
__hw_write(ci, val, ci->hw_bank.regmap[reg]);
return val;
}

View File

@ -23,6 +23,26 @@
#include "ci.h"
#include "ci_hdrc_imx.h"
#define CI_HDRC_IMX_IMX28_WRITE_FIX BIT(0)
struct ci_hdrc_imx_platform_flag {
unsigned int flags;
};
static const struct ci_hdrc_imx_platform_flag imx27_usb_data = {
};
static const struct ci_hdrc_imx_platform_flag imx28_usb_data = {
.flags = CI_HDRC_IMX_IMX28_WRITE_FIX,
};
static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
{ .compatible = "fsl,imx28-usb", .data = &imx28_usb_data},
{ .compatible = "fsl,imx27-usb", .data = &imx27_usb_data},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
struct ci_hdrc_imx_data {
struct usb_phy *phy;
struct platform_device *ci_pdev;
@ -82,6 +102,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
CI_HDRC_DISABLE_STREAMING,
};
int ret;
const struct of_device_id *of_id =
of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev);
const struct ci_hdrc_imx_platform_flag *imx_platform_flag = of_id->data;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data) {
@ -115,6 +138,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
pdata.phy = data->phy;
if (imx_platform_flag->flags & CI_HDRC_IMX_IMX28_WRITE_FIX)
pdata.flags |= CI_HDRC_IMX28_WRITE_FIX;
ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
goto err_clk;
@ -173,12 +199,6 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
return 0;
}
static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
{ .compatible = "fsl,imx27-usb", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
static struct platform_driver ci_hdrc_imx_driver = {
.probe = ci_hdrc_imx_probe,
.remove = ci_hdrc_imx_remove,

View File

@ -9,6 +9,9 @@
* http://www.gnu.org/copyleft/gpl.html
*/
#ifndef __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H
#define __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H
struct imx_usbmisc_data {
int index;
@ -18,3 +21,5 @@ struct imx_usbmisc_data {
int imx_usbmisc_init(struct imx_usbmisc_data *);
int imx_usbmisc_init_post(struct imx_usbmisc_data *);
#endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */

View File

@ -112,7 +112,7 @@ static void ci_hdrc_pci_remove(struct pci_dev *pdev)
*
* Check "pci.h" for details
*/
static DEFINE_PCI_DEVICE_TABLE(ci_hdrc_pci_id_table) = {
static const struct pci_device_id ci_hdrc_pci_id_table[] = {
{
PCI_DEVICE(0x153F, 0x1004),
.driver_data = (kernel_ulong_t)&pci_platdata,

View File

@ -75,61 +75,54 @@
#include "otg.h"
/* Controller register map */
static uintptr_t ci_regs_nolpm[] = {
[CAP_CAPLENGTH] = 0x000UL,
[CAP_HCCPARAMS] = 0x008UL,
[CAP_DCCPARAMS] = 0x024UL,
[CAP_TESTMODE] = 0x038UL,
[OP_USBCMD] = 0x000UL,
[OP_USBSTS] = 0x004UL,
[OP_USBINTR] = 0x008UL,
[OP_DEVICEADDR] = 0x014UL,
[OP_ENDPTLISTADDR] = 0x018UL,
[OP_PORTSC] = 0x044UL,
[OP_DEVLC] = 0x084UL,
[OP_OTGSC] = 0x064UL,
[OP_USBMODE] = 0x068UL,
[OP_ENDPTSETUPSTAT] = 0x06CUL,
[OP_ENDPTPRIME] = 0x070UL,
[OP_ENDPTFLUSH] = 0x074UL,
[OP_ENDPTSTAT] = 0x078UL,
[OP_ENDPTCOMPLETE] = 0x07CUL,
[OP_ENDPTCTRL] = 0x080UL,
static const u8 ci_regs_nolpm[] = {
[CAP_CAPLENGTH] = 0x00U,
[CAP_HCCPARAMS] = 0x08U,
[CAP_DCCPARAMS] = 0x24U,
[CAP_TESTMODE] = 0x38U,
[OP_USBCMD] = 0x00U,
[OP_USBSTS] = 0x04U,
[OP_USBINTR] = 0x08U,
[OP_DEVICEADDR] = 0x14U,
[OP_ENDPTLISTADDR] = 0x18U,
[OP_PORTSC] = 0x44U,
[OP_DEVLC] = 0x84U,
[OP_OTGSC] = 0x64U,
[OP_USBMODE] = 0x68U,
[OP_ENDPTSETUPSTAT] = 0x6CU,
[OP_ENDPTPRIME] = 0x70U,
[OP_ENDPTFLUSH] = 0x74U,
[OP_ENDPTSTAT] = 0x78U,
[OP_ENDPTCOMPLETE] = 0x7CU,
[OP_ENDPTCTRL] = 0x80U,
};
static uintptr_t ci_regs_lpm[] = {
[CAP_CAPLENGTH] = 0x000UL,
[CAP_HCCPARAMS] = 0x008UL,
[CAP_DCCPARAMS] = 0x024UL,
[CAP_TESTMODE] = 0x0FCUL,
[OP_USBCMD] = 0x000UL,
[OP_USBSTS] = 0x004UL,
[OP_USBINTR] = 0x008UL,
[OP_DEVICEADDR] = 0x014UL,
[OP_ENDPTLISTADDR] = 0x018UL,
[OP_PORTSC] = 0x044UL,
[OP_DEVLC] = 0x084UL,
[OP_OTGSC] = 0x0C4UL,
[OP_USBMODE] = 0x0C8UL,
[OP_ENDPTSETUPSTAT] = 0x0D8UL,
[OP_ENDPTPRIME] = 0x0DCUL,
[OP_ENDPTFLUSH] = 0x0E0UL,
[OP_ENDPTSTAT] = 0x0E4UL,
[OP_ENDPTCOMPLETE] = 0x0E8UL,
[OP_ENDPTCTRL] = 0x0ECUL,
static const u8 ci_regs_lpm[] = {
[CAP_CAPLENGTH] = 0x00U,
[CAP_HCCPARAMS] = 0x08U,
[CAP_DCCPARAMS] = 0x24U,
[CAP_TESTMODE] = 0xFCU,
[OP_USBCMD] = 0x00U,
[OP_USBSTS] = 0x04U,
[OP_USBINTR] = 0x08U,
[OP_DEVICEADDR] = 0x14U,
[OP_ENDPTLISTADDR] = 0x18U,
[OP_PORTSC] = 0x44U,
[OP_DEVLC] = 0x84U,
[OP_OTGSC] = 0xC4U,
[OP_USBMODE] = 0xC8U,
[OP_ENDPTSETUPSTAT] = 0xD8U,
[OP_ENDPTPRIME] = 0xDCU,
[OP_ENDPTFLUSH] = 0xE0U,
[OP_ENDPTSTAT] = 0xE4U,
[OP_ENDPTCOMPLETE] = 0xE8U,
[OP_ENDPTCTRL] = 0xECU,
};
static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm)
{
int i;
kfree(ci->hw_bank.regmap);
ci->hw_bank.regmap = kzalloc((OP_LAST + 1) * sizeof(void *),
GFP_KERNEL);
if (!ci->hw_bank.regmap)
return -ENOMEM;
for (i = 0; i < OP_ENDPTCTRL; i++)
ci->hw_bank.regmap[i] =
(i <= CAP_LAST ? ci->hw_bank.cap : ci->hw_bank.op) +
@ -208,7 +201,8 @@ static int hw_device_init(struct ci_hdrc *ci, void __iomem *base)
reg = hw_read(ci, CAP_HCCPARAMS, HCCPARAMS_LEN) >>
__ffs(HCCPARAMS_LEN);
ci->hw_bank.lpm = reg;
hw_alloc_regmap(ci, !!reg);
if (reg)
hw_alloc_regmap(ci, !!reg);
ci->hw_bank.size = ci->hw_bank.op - ci->hw_bank.abs;
ci->hw_bank.size += OP_LAST;
ci->hw_bank.size /= sizeof(u32);
@ -242,7 +236,7 @@ static int hw_device_init(struct ci_hdrc *ci, void __iomem *base)
static void hw_phymode_configure(struct ci_hdrc *ci)
{
u32 portsc, lpm, sts;
u32 portsc, lpm, sts = 0;
switch (ci->platdata->phy_mode) {
case USBPHY_INTERFACE_MODE_UTMI:
@ -272,10 +266,12 @@ static void hw_phymode_configure(struct ci_hdrc *ci)
if (ci->hw_bank.lpm) {
hw_write(ci, OP_DEVLC, DEVLC_PTS(7) | DEVLC_PTW, lpm);
hw_write(ci, OP_DEVLC, DEVLC_STS, sts);
if (sts)
hw_write(ci, OP_DEVLC, DEVLC_STS, DEVLC_STS);
} else {
hw_write(ci, OP_PORTSC, PORTSC_PTS(7) | PORTSC_PTW, portsc);
hw_write(ci, OP_PORTSC, PORTSC_STS, sts);
if (sts)
hw_write(ci, OP_PORTSC, PORTSC_STS, PORTSC_STS);
}
}
@ -554,6 +550,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
ci->dev = dev;
ci->platdata = dev->platform_data;
ci->imx28_write_fix = !!(ci->platdata->flags &
CI_HDRC_IMX28_WRITE_FIX);
ret = hw_device_init(ci, base);
if (ret < 0) {
@ -561,6 +559,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -ENODEV;
}
hw_phymode_configure(ci);
ret = ci_usb_phy_init(ci);
if (ret) {
dev_err(dev, "unable to init phy: %d\n", ret);
@ -578,8 +578,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
ci_get_otg_capable(ci);
hw_phymode_configure(ci);
dr_mode = ci->platdata->dr_mode;
/* initialize role(s) before the interrupt is requested */
if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) {
@ -680,7 +678,6 @@ static int ci_hdrc_remove(struct platform_device *pdev)
ci_role_destroy(ci);
ci_hdrc_enter_lpm(ci, true);
ci_usb_phy_destroy(ci);
kfree(ci->hw_bank.regmap);
return 0;
}

View File

@ -65,6 +65,7 @@ static int host_start(struct ci_hdrc *ci)
ehci->caps = ci->hw_bank.cap;
ehci->has_hostpc = ci->hw_bank.lpm;
ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
ehci->imx28_write_fix = ci->imx28_write_fix;
if (ci->platdata->reg_vbus) {
ret = regulator_enable(ci->platdata->reg_vbus);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 Freescale Semiconductor, Inc.
* Copyright (C) 2013-2014 Freescale Semiconductor, Inc.
*
* Author: Peter Chen
*
@ -19,12 +19,12 @@ static inline void ci_clear_otg_interrupt(struct ci_hdrc *ci, u32 bits)
static inline void ci_enable_otg_interrupt(struct ci_hdrc *ci, u32 bits)
{
hw_write(ci, OP_OTGSC, bits, bits);
hw_write(ci, OP_OTGSC, bits | OTGSC_INT_STATUS_BITS, bits);
}
static inline void ci_disable_otg_interrupt(struct ci_hdrc *ci, u32 bits)
{
hw_write(ci, OP_OTGSC, bits, 0);
hw_write(ci, OP_OTGSC, bits | OTGSC_INT_STATUS_BITS, 0);
}
int ci_hdrc_otg_init(struct ci_hdrc *ci);

View File

@ -393,6 +393,14 @@ static int add_td_to_list(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq,
node->ptr->token = cpu_to_le32(length << __ffs(TD_TOTAL_BYTES));
node->ptr->token &= cpu_to_le32(TD_TOTAL_BYTES);
node->ptr->token |= cpu_to_le32(TD_STATUS_ACTIVE);
if (hwep->type == USB_ENDPOINT_XFER_ISOC && hwep->dir == TX) {
u32 mul = hwreq->req.length / hwep->ep.maxpacket;
if (hwreq->req.length == 0
|| hwreq->req.length % hwep->ep.maxpacket)
mul++;
node->ptr->token |= mul << __ffs(TD_MULTO);
}
temp = (u32) (hwreq->req.dma + hwreq->req.actual);
if (length) {
@ -515,10 +523,11 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
hwep->qh.ptr->td.token &=
cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE));
if (hwep->type == USB_ENDPOINT_XFER_ISOC) {
if (hwep->type == USB_ENDPOINT_XFER_ISOC && hwep->dir == RX) {
u32 mul = hwreq->req.length / hwep->ep.maxpacket;
if (hwreq->req.length % hwep->ep.maxpacket)
if (hwreq->req.length == 0
|| hwreq->req.length % hwep->ep.maxpacket)
mul++;
hwep->qh.ptr->cap |= mul << __ffs(QH_MULT);
}
@ -1173,6 +1182,12 @@ static int ep_enable(struct usb_ep *ep,
if (hwep->num)
cap |= QH_ZLT;
cap |= (hwep->ep.maxpacket << __ffs(QH_MAX_PKT)) & QH_MAX_PKT;
/*
* For ISO-TX, we set mult at QH as the largest value, and use
* MultO at TD as real mult value.
*/
if (hwep->type == USB_ENDPOINT_XFER_ISOC && hwep->dir == TX)
cap |= 3 << __ffs(QH_MULT);
hwep->qh.ptr->cap = cpu_to_le32(cap);
@ -1566,7 +1581,7 @@ static int init_eps(struct ci_hdrc *ci)
* eps, maxP is set by epautoconfig() called
* by gadget layer
*/
hwep->ep.maxpacket = (unsigned short)~0;
usb_ep_set_maxpacket_limit(&hwep->ep, (unsigned short)~0);
INIT_LIST_HEAD(&hwep->qh.queue);
hwep->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL,
@ -1586,7 +1601,7 @@ static int init_eps(struct ci_hdrc *ci)
else
ci->ep0in = hwep;
hwep->ep.maxpacket = CTRL_PAYLOAD_MAX;
usb_ep_set_maxpacket_limit(&hwep->ep, CTRL_PAYLOAD_MAX);
continue;
}

View File

@ -21,6 +21,10 @@
#define MX25_USB_PHY_CTRL_OFFSET 0x08
#define MX25_BM_EXTERNAL_VBUS_DIVIDER BIT(23)
#define MX27_H1_PM_BIT BIT(8)
#define MX27_H2_PM_BIT BIT(16)
#define MX27_OTG_PM_BIT BIT(24)
#define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08
#define MX53_USB_UH2_CTRL_OFFSET 0x14
#define MX53_USB_UH3_CTRL_OFFSET 0x18
@ -68,6 +72,36 @@ static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
return 0;
}
static int usbmisc_imx27_init(struct imx_usbmisc_data *data)
{
unsigned long flags;
u32 val;
switch (data->index) {
case 0:
val = MX27_OTG_PM_BIT;
break;
case 1:
val = MX27_H1_PM_BIT;
break;
case 2:
val = MX27_H2_PM_BIT;
break;
default:
return -EINVAL;
};
spin_lock_irqsave(&usbmisc->lock, flags);
if (data->disable_oc)
val = readl(usbmisc->base) | val;
else
val = readl(usbmisc->base) & ~val;
writel(val, usbmisc->base);
spin_unlock_irqrestore(&usbmisc->lock, flags);
return 0;
}
static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
{
void __iomem *reg = NULL;
@ -128,6 +162,10 @@ static const struct usbmisc_ops imx25_usbmisc_ops = {
.post = usbmisc_imx25_post,
};
static const struct usbmisc_ops imx27_usbmisc_ops = {
.init = usbmisc_imx27_init,
};
static const struct usbmisc_ops imx53_usbmisc_ops = {
.init = usbmisc_imx53_init,
};
@ -161,6 +199,14 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
.compatible = "fsl,imx25-usbmisc",
.data = &imx25_usbmisc_ops,
},
{
.compatible = "fsl,imx27-usbmisc",
.data = &imx27_usbmisc_ops,
},
{
.compatible = "fsl,imx51-usbmisc",
.data = &imx53_usbmisc_ops,
},
{
.compatible = "fsl,imx53-usbmisc",
.data = &imx53_usbmisc_ops,

View File

@ -262,6 +262,7 @@ static void acm_ctrl_irq(struct urb *urb)
struct usb_cdc_notification *dr = urb->transfer_buffer;
unsigned char *data;
int newctrl;
int difference;
int retval;
int status = urb->status;
@ -302,20 +303,31 @@ static void acm_ctrl_irq(struct urb *urb)
tty_port_tty_hangup(&acm->port, false);
}
difference = acm->ctrlin ^ newctrl;
spin_lock(&acm->read_lock);
acm->ctrlin = newctrl;
acm->oldcount = acm->iocount;
dev_dbg(&acm->control->dev,
"%s - input control lines: dcd%c dsr%c break%c "
"ring%c framing%c parity%c overrun%c\n",
__func__,
acm->ctrlin & ACM_CTRL_DCD ? '+' : '-',
acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
acm->ctrlin & ACM_CTRL_BRK ? '+' : '-',
acm->ctrlin & ACM_CTRL_RI ? '+' : '-',
acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-',
acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-',
acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-');
break;
if (difference & ACM_CTRL_DSR)
acm->iocount.dsr++;
if (difference & ACM_CTRL_BRK)
acm->iocount.brk++;
if (difference & ACM_CTRL_RI)
acm->iocount.rng++;
if (difference & ACM_CTRL_DCD)
acm->iocount.dcd++;
if (difference & ACM_CTRL_FRAMING)
acm->iocount.frame++;
if (difference & ACM_CTRL_PARITY)
acm->iocount.parity++;
if (difference & ACM_CTRL_OVERRUN)
acm->iocount.overrun++;
spin_unlock(&acm->read_lock);
if (difference)
wake_up_all(&acm->wioctl);
break;
default:
dev_dbg(&acm->control->dev,
@ -796,6 +808,72 @@ static int set_serial_info(struct acm *acm,
return retval;
}
static int wait_serial_change(struct acm *acm, unsigned long arg)
{
int rv = 0;
DECLARE_WAITQUEUE(wait, current);
struct async_icount old, new;
if (arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD ))
return -EINVAL;
do {
spin_lock_irq(&acm->read_lock);
old = acm->oldcount;
new = acm->iocount;
acm->oldcount = new;
spin_unlock_irq(&acm->read_lock);
if ((arg & TIOCM_DSR) &&
old.dsr != new.dsr)
break;
if ((arg & TIOCM_CD) &&
old.dcd != new.dcd)
break;
if ((arg & TIOCM_RI) &&
old.rng != new.rng)
break;
add_wait_queue(&acm->wioctl, &wait);
set_current_state(TASK_INTERRUPTIBLE);
schedule();
remove_wait_queue(&acm->wioctl, &wait);
if (acm->disconnected) {
if (arg & TIOCM_CD)
break;
else
rv = -ENODEV;
} else {
if (signal_pending(current))
rv = -ERESTARTSYS;
}
} while (!rv);
return rv;
}
static int get_serial_usage(struct acm *acm,
struct serial_icounter_struct __user *count)
{
struct serial_icounter_struct icount;
int rv = 0;
memset(&icount, 0, sizeof(icount));
icount.dsr = acm->iocount.dsr;
icount.rng = acm->iocount.rng;
icount.dcd = acm->iocount.dcd;
icount.frame = acm->iocount.frame;
icount.overrun = acm->iocount.overrun;
icount.parity = acm->iocount.parity;
icount.brk = acm->iocount.brk;
if (copy_to_user(count, &icount, sizeof(icount)) > 0)
rv = -EFAULT;
return rv;
}
static int acm_tty_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
@ -809,6 +887,18 @@ static int acm_tty_ioctl(struct tty_struct *tty,
case TIOCSSERIAL:
rv = set_serial_info(acm, (struct serial_struct __user *) arg);
break;
case TIOCMIWAIT:
rv = usb_autopm_get_interface(acm->control);
if (rv < 0) {
rv = -EIO;
break;
}
rv = wait_serial_change(acm, arg);
usb_autopm_put_interface(acm->control);
break;
case TIOCGICOUNT:
rv = get_serial_usage(acm, (struct serial_icounter_struct __user *) arg);
break;
}
return rv;
@ -1167,6 +1257,7 @@ static int acm_probe(struct usb_interface *intf,
acm->readsize = readsize;
acm->rx_buflimit = num_rx_buf;
INIT_WORK(&acm->work, acm_softint);
init_waitqueue_head(&acm->wioctl);
spin_lock_init(&acm->write_lock);
spin_lock_init(&acm->read_lock);
mutex_init(&acm->mutex);
@ -1383,6 +1474,7 @@ static void acm_disconnect(struct usb_interface *intf)
device_remove_file(&acm->control->dev,
&dev_attr_iCountryCodeRelDate);
}
wake_up_all(&acm->wioctl);
device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities);
usb_set_intfdata(acm->control, NULL);
usb_set_intfdata(acm->data, NULL);

View File

@ -106,6 +106,9 @@ struct acm {
struct work_struct work; /* work queue entry for line discipline waking up */
unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
unsigned int ctrlout; /* output control lines (DTR, RTS) */
struct async_icount iocount; /* counters for control line changes */
struct async_icount oldcount; /* for comparison of counter */
wait_queue_head_t wioctl; /* for ioctl */
unsigned int writesize; /* max packet size for the output bulk endpoint */
unsigned int readsize,ctrlsize; /* buffer sizes for freeing */
unsigned int minor; /* acm minor number */

View File

@ -432,6 +432,38 @@ static ssize_t wdm_write
return rv < 0 ? rv : count;
}
/*
* clear WDM_READ flag and possibly submit the read urb if resp_count
* is non-zero.
*
* Called with desc->iuspin locked
*/
static int clear_wdm_read_flag(struct wdm_device *desc)
{
int rv = 0;
clear_bit(WDM_READ, &desc->flags);
/* submit read urb only if the device is waiting for it */
if (!desc->resp_count || !--desc->resp_count)
goto out;
set_bit(WDM_RESPONDING, &desc->flags);
spin_unlock_irq(&desc->iuspin);
rv = usb_submit_urb(desc->response, GFP_KERNEL);
spin_lock_irq(&desc->iuspin);
if (rv) {
dev_err(&desc->intf->dev,
"usb_submit_urb failed with result %d\n", rv);
/* make sure the next notification trigger a submit */
clear_bit(WDM_RESPONDING, &desc->flags);
desc->resp_count = 0;
}
out:
return rv;
}
static ssize_t wdm_read
(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
@ -503,8 +535,10 @@ static ssize_t wdm_read
if (!desc->reslength) { /* zero length read */
dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);
clear_bit(WDM_READ, &desc->flags);
rv = clear_wdm_read_flag(desc);
spin_unlock_irq(&desc->iuspin);
if (rv < 0)
goto err;
goto retry;
}
cntr = desc->length;
@ -526,37 +560,9 @@ static ssize_t wdm_read
desc->length -= cntr;
/* in case we had outstanding data */
if (!desc->length) {
clear_bit(WDM_READ, &desc->flags);
if (--desc->resp_count) {
set_bit(WDM_RESPONDING, &desc->flags);
spin_unlock_irq(&desc->iuspin);
rv = usb_submit_urb(desc->response, GFP_KERNEL);
if (rv) {
dev_err(&desc->intf->dev,
"%s: usb_submit_urb failed with result %d\n",
__func__, rv);
spin_lock_irq(&desc->iuspin);
clear_bit(WDM_RESPONDING, &desc->flags);
spin_unlock_irq(&desc->iuspin);
if (rv == -ENOMEM) {
rv = schedule_work(&desc->rxwork);
if (rv)
dev_err(&desc->intf->dev, "Cannot schedule work\n");
} else {
spin_lock_irq(&desc->iuspin);
desc->resp_count = 0;
spin_unlock_irq(&desc->iuspin);
}
}
} else
spin_unlock_irq(&desc->iuspin);
} else
spin_unlock_irq(&desc->iuspin);
if (!desc->length)
clear_wdm_read_flag(desc);
spin_unlock_irq(&desc->iuspin);
rv = cntr;
err:

View File

@ -52,7 +52,6 @@
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/lp.h>
#include <linux/mutex.h>

View File

@ -21,7 +21,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>

View File

@ -2,8 +2,6 @@
# Makefile for USB Core files and filesystem
#
ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
usbcore-y += devio.o notify.o generic.o quirks.o devices.o

View File

@ -2,7 +2,7 @@
* DMA memory management for framework level HCD code (hc_driver)
*
* This implementation plugs in through generic "usb_bus" level methods,
* and should work with all USB controllers, regardles of bus type.
* and should work with all USB controllers, regardless of bus type.
*/
#include <linux/module.h>

View File

@ -3,7 +3,6 @@
#include <linux/usb/hcd.h>
#include <linux/usb/quirks.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <asm/byteorder.h>
@ -651,10 +650,6 @@ void usb_destroy_configuration(struct usb_device *dev)
*
* hub-only!! ... and only in reset path, or usb_new_device()
* (used by real hubs and virtual root hubs)
*
* NOTE: if this is a WUSB device and is not authorized, we skip the
* whole thing. A non-authorized USB device has no
* configurations.
*/
int usb_get_configuration(struct usb_device *dev)
{
@ -666,8 +661,6 @@ int usb_get_configuration(struct usb_device *dev)
struct usb_config_descriptor *desc;
cfgno = 0;
if (dev->authorized == 0) /* Not really an error */
goto out_not_authorized;
result = -ENOMEM;
if (ncfg > USB_MAXCONFIG) {
dev_warn(ddev, "too many configurations: %d, "
@ -751,7 +744,6 @@ int usb_get_configuration(struct usb_device *dev)
err:
kfree(desc);
out_not_authorized:
dev->descriptor.bNumConfigurations = cfgno;
err2:
if (result == -ENOMEM)

View File

@ -118,7 +118,7 @@ module_param(usbfs_memory_mb, uint, 0644);
MODULE_PARM_DESC(usbfs_memory_mb,
"maximum MB allowed for usbfs buffers (0 = no limit)");
/* Hard limit, necessary to avoid aithmetic overflow */
/* Hard limit, necessary to avoid arithmetic overflow */
#define USBFS_XFER_MAX (UINT_MAX / 2 - 1000000)
static atomic_t usbfs_memory_usage; /* Total memory currently allocated */

View File

@ -37,6 +37,7 @@
* and cause the driver to probe for all devices again.
*/
ssize_t usb_store_new_id(struct usb_dynids *dynids,
const struct usb_device_id *id_table,
struct device_driver *driver,
const char *buf, size_t count)
{
@ -44,11 +45,12 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
u32 idVendor = 0;
u32 idProduct = 0;
unsigned int bInterfaceClass = 0;
u32 refVendor, refProduct;
int fields = 0;
int retval = 0;
fields = sscanf(buf, "%x %x %x", &idVendor, &idProduct,
&bInterfaceClass);
fields = sscanf(buf, "%x %x %x %x %x", &idVendor, &idProduct,
&bInterfaceClass, &refVendor, &refProduct);
if (fields < 2)
return -EINVAL;
@ -60,11 +62,30 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
dynid->id.idVendor = idVendor;
dynid->id.idProduct = idProduct;
dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
if (fields == 3) {
if (fields > 2 && bInterfaceClass) {
if (bInterfaceClass > 255)
return -EINVAL;
dynid->id.bInterfaceClass = (u8)bInterfaceClass;
dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;
}
if (fields > 4) {
const struct usb_device_id *id = id_table;
if (!id)
return -ENODEV;
for (; id->match_flags; id++)
if (id->idVendor == refVendor && id->idProduct == refProduct)
break;
if (id->match_flags)
dynid->id.driver_info = id->driver_info;
else
return -ENODEV;
}
spin_lock(&dynids->lock);
list_add_tail(&dynid->node, &dynids->list);
spin_unlock(&dynids->lock);
@ -106,7 +127,7 @@ static ssize_t new_id_store(struct device_driver *driver,
{
struct usb_driver *usb_drv = to_usb_driver(driver);
return usb_store_new_id(&usb_drv->dynids, driver, buf, count);
return usb_store_new_id(&usb_drv->dynids, usb_drv->id_table, driver, buf, count);
}
static DRIVER_ATTR_RW(new_id);
@ -839,7 +860,7 @@ int usb_register_device_driver(struct usb_device_driver *new_udriver,
return -ENODEV;
new_udriver->drvwrap.for_devices = 1;
new_udriver->drvwrap.driver.name = (char *) new_udriver->name;
new_udriver->drvwrap.driver.name = new_udriver->name;
new_udriver->drvwrap.driver.bus = &usb_bus_type;
new_udriver->drvwrap.driver.probe = usb_probe_device;
new_udriver->drvwrap.driver.remove = usb_unbind_device;
@ -900,7 +921,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
return -ENODEV;
new_driver->drvwrap.for_devices = 0;
new_driver->drvwrap.driver.name = (char *) new_driver->name;
new_driver->drvwrap.driver.name = new_driver->name;
new_driver->drvwrap.driver.bus = &usb_bus_type;
new_driver->drvwrap.driver.probe = usb_probe_interface;
new_driver->drvwrap.driver.remove = usb_unbind_interface;

View File

@ -282,6 +282,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (retval != 0)
goto unmap_registers;
device_wakeup_enable(hcd->self.controller);
if (pci_dev_run_wake(dev))
pm_runtime_put_noidle(&dev->dev);

View File

@ -44,6 +44,7 @@
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/usb/phy.h>
#include "usb.h"
@ -1297,7 +1298,7 @@ EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep);
* DMA framework is dma_declare_coherent_memory()
*
* - So we use that, even though the primary requirement
* is that the memory be "local" (hence addressible
* is that the memory be "local" (hence addressable
* by that device), not "coherent".
*
*/
@ -2588,6 +2589,24 @@ int usb_add_hcd(struct usb_hcd *hcd,
int retval;
struct usb_device *rhdev;
if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->phy) {
struct usb_phy *phy = usb_get_phy_dev(hcd->self.controller, 0);
if (IS_ERR(phy)) {
retval = PTR_ERR(phy);
if (retval == -EPROBE_DEFER)
return retval;
} else {
retval = usb_phy_init(phy);
if (retval) {
usb_put_phy(phy);
return retval;
}
hcd->phy = phy;
hcd->remove_phy = 1;
}
}
dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
/* Keep old behaviour if authorized_default is not in [0, 1]. */
@ -2603,7 +2622,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
*/
if ((retval = hcd_buffer_create(hcd)) != 0) {
dev_dbg(hcd->self.controller, "pool alloc failed\n");
return retval;
goto err_remove_phy;
}
if ((retval = usb_register_bus(&hcd->self)) < 0)
@ -2693,12 +2712,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
usb_hcd_poll_rh_status(hcd);
/*
* Host controllers don't generate their own wakeup requests;
* they only forward requests from the root hub. Therefore
* controllers should always be enabled for remote wakeup.
*/
device_wakeup_enable(hcd->self.controller);
return retval;
error_create_attr_group:
@ -2734,6 +2747,12 @@ int usb_add_hcd(struct usb_hcd *hcd,
usb_deregister_bus(&hcd->self);
err_register_bus:
hcd_buffer_destroy(hcd);
err_remove_phy:
if (hcd->remove_phy && hcd->phy) {
usb_phy_shutdown(hcd->phy);
usb_put_phy(hcd->phy);
hcd->phy = NULL;
}
return retval;
}
EXPORT_SYMBOL_GPL(usb_add_hcd);
@ -2806,6 +2825,11 @@ void usb_remove_hcd(struct usb_hcd *hcd)
usb_put_dev(hcd->self.root_hub);
usb_deregister_bus(&hcd->self);
hcd_buffer_destroy(hcd);
if (hcd->remove_phy && hcd->phy) {
usb_phy_shutdown(hcd->phy);
usb_put_phy(hcd->phy);
hcd->phy = NULL;
}
}
EXPORT_SYMBOL_GPL(usb_remove_hcd);

View File

@ -33,13 +33,6 @@
#include "hub.h"
/* if we are in debug mode, always announce new devices */
#ifdef DEBUG
#ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES
#define CONFIG_USB_ANNOUNCE_NEW_DEVICES
#endif
#endif
#define USB_VENDOR_GENESYS_LOGIC 0x05e3
#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01
@ -1154,7 +1147,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
/* Tell khubd to disconnect the device or
* check for a new connection
*/
if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
if (udev || (portstatus & USB_PORT_STAT_CONNECTION) ||
(portstatus & USB_PORT_STAT_OVERCURRENT))
set_bit(port1, hub->change_bits);
} else if (portstatus & USB_PORT_STAT_ENABLE) {
@ -1607,7 +1601,7 @@ static void hub_disconnect(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata(intf);
struct usb_device *hdev = interface_to_usbdev(intf);
int i;
int port1;
/* Take the hub off the event list and don't let it be added again */
spin_lock_irq(&hub_event_lock);
@ -1622,11 +1616,15 @@ static void hub_disconnect(struct usb_interface *intf)
hub->error = 0;
hub_quiesce(hub, HUB_DISCONNECT);
usb_set_intfdata (intf, NULL);
/* Avoid races with recursively_mark_NOTATTACHED() */
spin_lock_irq(&device_state_lock);
port1 = hdev->maxchild;
hdev->maxchild = 0;
usb_set_intfdata(intf, NULL);
spin_unlock_irq(&device_state_lock);
for (i = 0; i < hdev->maxchild; i++)
usb_hub_remove_port_device(hub, i + 1);
hub->hdev->maxchild = 0;
for (; port1 > 0; --port1)
usb_hub_remove_port_device(hub, port1);
if (hub->hdev->speed == USB_SPEED_HIGH)
highspeed_hubs--;
@ -2235,17 +2233,13 @@ static int usb_enumerate_device(struct usb_device *udev)
return err;
}
}
if (udev->wusb == 1 && udev->authorized == 0) {
udev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
udev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
udev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
} else {
/* read the standard strings and cache them if present */
udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
udev->manufacturer = usb_cache_string(udev,
udev->descriptor.iManufacturer);
udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
}
/* read the standard strings and cache them if present */
udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
udev->manufacturer = usb_cache_string(udev,
udev->descriptor.iManufacturer);
udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
err = usb_enumerate_device_otg(udev);
if (err < 0)
return err;
@ -2427,16 +2421,6 @@ int usb_deauthorize_device(struct usb_device *usb_dev)
usb_dev->authorized = 0;
usb_set_configuration(usb_dev, -1);
kfree(usb_dev->product);
usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
kfree(usb_dev->manufacturer);
usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
kfree(usb_dev->serial);
usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
usb_destroy_configuration(usb_dev);
usb_dev->descriptor.bNumConfigurations = 0;
out_unauthorized:
usb_unlock_device(usb_dev);
return 0;
@ -2464,17 +2448,7 @@ int usb_authorize_device(struct usb_device *usb_dev)
goto error_device_descriptor;
}
kfree(usb_dev->product);
usb_dev->product = NULL;
kfree(usb_dev->manufacturer);
usb_dev->manufacturer = NULL;
kfree(usb_dev->serial);
usb_dev->serial = NULL;
usb_dev->authorized = 1;
result = usb_enumerate_device(usb_dev);
if (result < 0)
goto error_enumerate;
/* Choose and set the configuration. This registers the interfaces
* with the driver core and lets interface drivers bind to them.
*/
@ -2490,7 +2464,6 @@ int usb_authorize_device(struct usb_device *usb_dev)
}
dev_info(&usb_dev->dev, "authorized to connect\n");
error_enumerate:
error_device_descriptor:
usb_autosuspend_device(usb_dev);
error_autoresume:
@ -2523,10 +2496,25 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
#define HUB_LONG_RESET_TIME 200
#define HUB_RESET_TIMEOUT 800
/*
* "New scheme" enumeration causes an extra state transition to be
* exposed to an xhci host and causes USB3 devices to receive control
* commands in the default state. This has been seen to cause
* enumeration failures, so disable this enumeration scheme for USB3
* devices.
*/
static bool use_new_scheme(struct usb_device *udev, int retry)
{
if (udev->speed == USB_SPEED_SUPER)
return false;
return USE_NEW_SCHEME(retry);
}
static int hub_port_reset(struct usb_hub *hub, int port1,
struct usb_device *udev, unsigned int delay, bool warm);
/* Is a USB 3.0 port in the Inactive or Complinance Mode state?
/* Is a USB 3.0 port in the Inactive or Compliance Mode state?
* Port worm reset is required to recover
*/
static bool hub_port_warm_reset_required(struct usb_hub *hub, u16 portstatus)
@ -3334,7 +3322,8 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
udev = hub->ports[port1 - 1]->child;
if (udev && udev->can_submit) {
dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
dev_warn(&intf->dev, "port %d not suspended yet\n",
port1);
if (PMSG_IS_AUTO(msg))
return -EBUSY;
}
@ -3981,6 +3970,20 @@ static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev)
}
}
static int hub_enable_device(struct usb_device *udev)
{
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
if (!hcd->driver->enable_device)
return 0;
if (udev->state == USB_STATE_ADDRESS)
return 0;
if (udev->state != USB_STATE_DEFAULT)
return -EINVAL;
return hcd->driver->enable_device(hcd, udev);
}
/* Reset device, (re)assign address, get device descriptor.
* Device connection must be stable, no more debouncing needed.
* Returns device in USB_STATE_ADDRESS, except on error.
@ -4093,7 +4096,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
* this area, and this is how Linux has done it for ages.
* Change it cautiously.
*
* NOTE: If USE_NEW_SCHEME() is true we will start by issuing
* NOTE: If use_new_scheme() is true we will start by issuing
* a 64-byte GET_DESCRIPTOR request. This is what Windows does,
* so it may help with some non-standards-compliant devices.
* Otherwise we start with SET_ADDRESS and then try to read the
@ -4101,10 +4104,17 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
* value.
*/
for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3)) {
bool did_new_scheme = false;
if (use_new_scheme(udev, retry_counter)) {
struct usb_device_descriptor *buf;
int r = 0;
did_new_scheme = true;
retval = hub_enable_device(udev);
if (retval < 0)
goto fail;
#define GET_DESCRIPTOR_BUFSIZE 64
buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
if (!buf) {
@ -4193,7 +4203,11 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
* - read ep0 maxpacket even for high and low speed,
*/
msleep(10);
if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3))
/* use_new_scheme() checks the speed which may have
* changed since the initial look so we cache the result
* in did_new_scheme
*/
if (did_new_scheme)
break;
}
@ -4900,7 +4914,7 @@ static void hub_events(void)
static int hub_thread(void *__unused)
{
/* khubd needs to be freezable to avoid intefering with USB-PERSIST
/* khubd needs to be freezable to avoid interfering with USB-PERSIST
* port handover. Otherwise it might see that a full-speed device
* was gone before the EHCI controller had handed its port over to
* the companion full-speed controller.

View File

@ -78,7 +78,7 @@ struct usb_hub {
/**
* struct usb port - kernel's representation of a usb port
* @child: usb device attatched to the port
* @child: usb device attached to the port
* @dev: generic device interface
* @port_owner: port's owner
* @connect_type: port's connect type

View File

@ -6,7 +6,6 @@
#include <linux/usb.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/timer.h>
#include <linux/ctype.h>
@ -218,7 +217,7 @@ EXPORT_SYMBOL_GPL(usb_interrupt_msg);
*
* Return:
* If successful, 0. Otherwise a negative error number. The number of actual
* bytes transferred will be stored in the @actual_length paramater.
* bytes transferred will be stored in the @actual_length parameter.
*
*/
int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
@ -518,7 +517,7 @@ void usb_sg_wait(struct usb_sg_request *io)
io->urbs[i]->dev = io->dev;
retval = usb_submit_urb(io->urbs[i], GFP_ATOMIC);
/* after we submit, let completions or cancelations fire;
/* after we submit, let completions or cancellations fire;
* we handshake using io->status.
*/
spin_unlock_irq(&io->lock);

View File

@ -98,9 +98,6 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Alcor Micro Corp. Hub */
{ USB_DEVICE(0x058f, 0x9254), .driver_info = USB_QUIRK_RESET_RESUME },
/* MicroTouch Systems touchscreen */
{ USB_DEVICE(0x0596, 0x051e), .driver_info = USB_QUIRK_RESET_RESUME },
/* appletouch */
{ USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME },

View File

@ -837,7 +837,7 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
device_remove_bin_file(dev, &dev_bin_attr_descriptors);
}
/* Interface Accociation Descriptor fields */
/* Interface Association Descriptor fields */
#define usb_intf_assoc_attr(field, format_string) \
static ssize_t \
iad_##field##_show(struct device *dev, struct device_attribute *attr, \

View File

@ -2,7 +2,6 @@
#include <linux/string.h>
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/log2.h>
#include <linux/usb.h>
#include <linux/wait.h>
@ -53,7 +52,7 @@ EXPORT_SYMBOL_GPL(usb_init_urb);
* valid options for this.
*
* Creates an urb for the USB driver to use, initializes a few internal
* structures, incrementes the usage counter, and returns a pointer to it.
* structures, increments the usage counter, and returns a pointer to it.
*
* If the driver want to use this urb for interrupt, control, or bulk
* endpoints, pass '0' as the number of iso packets.
@ -281,7 +280,7 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
*
* Device drivers must explicitly request that repetition, by ensuring that
* some URB is always on the endpoint's queue (except possibly for short
* periods during completion callacks). When there is no longer an urb
* periods during completion callbacks). When there is no longer an urb
* queued, the endpoint's bandwidth reservation is canceled. This means
* drivers can use their completion handlers to ensure they keep bandwidth
* they need, by reinitializing and resubmitting the just-completed urb
@ -325,10 +324,14 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
*/
int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
{
static int pipetypes[4] = {
PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
};
int xfertype, max;
struct usb_device *dev;
struct usb_host_endpoint *ep;
int is_out;
unsigned int allowed;
if (!urb || !urb->complete)
return -EINVAL;
@ -436,15 +439,10 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
if (urb->transfer_buffer_length > INT_MAX)
return -EMSGSIZE;
#ifdef DEBUG
/* stuff that drivers shouldn't do, but which shouldn't
/*
* stuff that drivers shouldn't do, but which shouldn't
* cause problems in HCDs if they get it wrong.
*/
{
unsigned int allowed;
static int pipetypes[4] = {
PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
};
/* Check that the pipe's type matches the endpoint's type */
if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
@ -476,8 +474,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
if (allowed != urb->transfer_flags)
dev_WARN(&dev->dev, "BOGUS urb flags, %x --> %x\n",
urb->transfer_flags, allowed);
}
#endif
/*
* Force periodic transfer intervals to be legal values that are
* a power of two (so HCDs don't need to).
@ -492,9 +489,9 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
/* too small? */
switch (dev->speed) {
case USB_SPEED_WIRELESS:
if (urb->interval < 6)
if ((urb->interval < 6)
&& (xfertype == USB_ENDPOINT_XFER_INT))
return -EINVAL;
break;
default:
if (urb->interval <= 0)
return -EINVAL;

View File

@ -92,7 +92,7 @@ static int usb_acpi_check_port_connect_type(struct usb_device *hdev,
int ret = 0;
/*
* Accoding to ACPI Spec 9.13. PLD indicates whether usb port is
* According to ACPI Spec 9.13. PLD indicates whether usb port is
* user visible and _UPC indicates whether it is connectable. If
* the port was visible and connectable, it could be freely connected
* and disconnected with USB devices. If no visible and connectable,

View File

@ -2935,6 +2935,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
if (retval < 0)
goto error3;
device_wakeup_enable(hcd->self.controller);
dwc2_hcd_dump_state(hsotg);
dwc2_enable_global_interrupts(hsotg);

View File

@ -70,6 +70,13 @@ config USB_DWC3_PCI
One such PCIe-based platform is Synopsys' PCIe HAPS model of
this IP.
config USB_DWC3_KEYSTONE
tristate "Texas Instruments Keystone2 Platforms"
default USB_DWC3
help
Support of USB2/3 functionality in TI Keystone2 platforms.
Say 'Y' or 'M' here if you have one such device
comment "Debugging features"
config USB_DWC3_DEBUG

View File

@ -32,3 +32,4 @@ endif
obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o
obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o
obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o
obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o

View File

@ -50,6 +50,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
exynos->usb2_phy = pdev;
pdata.type = USB_PHY_TYPE_USB2;
pdata.gpio_reset = -1;
ret = platform_device_add_data(exynos->usb2_phy, &pdata, sizeof(pdata));
if (ret)

View File

@ -0,0 +1,202 @@
/**
* dwc3-keystone.c - Keystone Specific Glue layer
*
* Copyright (C) 2010-2013 Texas Instruments Incorporated - http://www.ti.com
*
* Author: WingMan Kwok <w-kwok2@ti.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/of_platform.h>
/* USBSS register offsets */
#define USBSS_REVISION 0x0000
#define USBSS_SYSCONFIG 0x0010
#define USBSS_IRQ_EOI 0x0018
#define USBSS_IRQSTATUS_RAW_0 0x0020
#define USBSS_IRQSTATUS_0 0x0024
#define USBSS_IRQENABLE_SET_0 0x0028
#define USBSS_IRQENABLE_CLR_0 0x002c
/* IRQ register bits */
#define USBSS_IRQ_EOI_LINE(n) BIT(n)
#define USBSS_IRQ_EVENT_ST BIT(0)
#define USBSS_IRQ_COREIRQ_EN BIT(0)
#define USBSS_IRQ_COREIRQ_CLR BIT(0)
static u64 kdwc3_dma_mask;
struct dwc3_keystone {
struct device *dev;
struct clk *clk;
void __iomem *usbss;
};
static inline u32 kdwc3_readl(void __iomem *base, u32 offset)
{
return readl(base + offset);
}
static inline void kdwc3_writel(void __iomem *base, u32 offset, u32 value)
{
writel(value, base + offset);
}
static void kdwc3_enable_irqs(struct dwc3_keystone *kdwc)
{
u32 val;
val = kdwc3_readl(kdwc->usbss, USBSS_IRQENABLE_SET_0);
val |= USBSS_IRQ_COREIRQ_EN;
kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_SET_0, val);
}
static void kdwc3_disable_irqs(struct dwc3_keystone *kdwc)
{
u32 val;
val = kdwc3_readl(kdwc->usbss, USBSS_IRQENABLE_SET_0);
val &= ~USBSS_IRQ_COREIRQ_EN;
kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_SET_0, val);
}
static irqreturn_t dwc3_keystone_interrupt(int irq, void *_kdwc)
{
struct dwc3_keystone *kdwc = _kdwc;
kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_CLR_0, USBSS_IRQ_COREIRQ_CLR);
kdwc3_writel(kdwc->usbss, USBSS_IRQSTATUS_0, USBSS_IRQ_EVENT_ST);
kdwc3_writel(kdwc->usbss, USBSS_IRQENABLE_SET_0, USBSS_IRQ_COREIRQ_EN);
kdwc3_writel(kdwc->usbss, USBSS_IRQ_EOI, USBSS_IRQ_EOI_LINE(0));
return IRQ_HANDLED;
}
static int kdwc3_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = pdev->dev.of_node;
struct dwc3_keystone *kdwc;
struct resource *res;
int error, irq;
kdwc = devm_kzalloc(dev, sizeof(*kdwc), GFP_KERNEL);
if (!kdwc)
return -ENOMEM;
platform_set_drvdata(pdev, kdwc);
kdwc->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "missing usbss resource\n");
return -EINVAL;
}
kdwc->usbss = devm_ioremap_resource(dev, res);
if (IS_ERR(kdwc->usbss))
return PTR_ERR(kdwc->usbss);
kdwc3_dma_mask = dma_get_mask(dev);
dev->dma_mask = &kdwc3_dma_mask;
kdwc->clk = devm_clk_get(kdwc->dev, "usb");
error = clk_prepare_enable(kdwc->clk);
if (error < 0) {
dev_dbg(kdwc->dev, "unable to enable usb clock, err %d\n",
error);
return error;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "missing irq\n");
goto err_irq;
}
error = devm_request_irq(dev, irq, dwc3_keystone_interrupt, IRQF_SHARED,
dev_name(dev), kdwc);
if (error) {
dev_err(dev, "failed to request IRQ #%d --> %d\n",
irq, error);
goto err_irq;
}
kdwc3_enable_irqs(kdwc);
error = of_platform_populate(node, NULL, NULL, dev);
if (error) {
dev_err(&pdev->dev, "failed to create dwc3 core\n");
goto err_core;
}
return 0;
err_core:
kdwc3_disable_irqs(kdwc);
err_irq:
clk_disable_unprepare(kdwc->clk);
return error;
}
static int kdwc3_remove_core(struct device *dev, void *c)
{
struct platform_device *pdev = to_platform_device(dev);
platform_device_unregister(pdev);
return 0;
}
static int kdwc3_remove(struct platform_device *pdev)
{
struct dwc3_keystone *kdwc = platform_get_drvdata(pdev);
kdwc3_disable_irqs(kdwc);
device_for_each_child(&pdev->dev, NULL, kdwc3_remove_core);
clk_disable_unprepare(kdwc->clk);
platform_set_drvdata(pdev, NULL);
return 0;
}
static const struct of_device_id kdwc3_of_match[] = {
{ .compatible = "ti,keystone-dwc3", },
{},
};
MODULE_DEVICE_TABLE(of, kdwc3_of_match);
static struct platform_driver kdwc3_driver = {
.probe = kdwc3_probe,
.remove = kdwc3_remove,
.driver = {
.name = "keystone-dwc3",
.owner = THIS_MODULE,
.of_match_table = kdwc3_of_match,
},
};
module_platform_driver(kdwc3_driver);
MODULE_ALIAS("platform:keystone-dwc3");
MODULE_AUTHOR("WingMan Kwok <w-kwok2@ti.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("DesignWare USB3 KEYSTONE Glue Layer");

View File

@ -20,7 +20,6 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/platform_data/dwc3-omap.h>
#include <linux/pm_runtime.h>
@ -120,9 +119,6 @@
#define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID (1 << 1)
struct dwc3_omap {
/* device lock */
spinlock_t lock;
struct device *dev;
int irq;
@ -280,8 +276,6 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
struct dwc3_omap *omap = _omap;
u32 reg;
spin_lock(&omap->lock);
reg = dwc3_omap_read_irqmisc_status(omap);
if (reg & USBOTGSS_IRQMISC_DMADISABLECLR) {
@ -322,8 +316,6 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
dwc3_omap_write_irq0_status(omap, reg);
spin_unlock(&omap->lock);
return IRQ_HANDLED;
}
@ -449,8 +441,6 @@ static int dwc3_omap_probe(struct platform_device *pdev)
}
}
spin_lock_init(&omap->lock);
omap->dev = dev;
omap->irq = irq;
omap->base = base;
@ -535,7 +525,7 @@ static int dwc3_omap_probe(struct platform_device *pdev)
edev = of_extcon_get_extcon_dev(dev, 0);
if (IS_ERR(edev)) {
dev_vdbg(dev, "couldn't get extcon device\n");
ret = PTR_ERR(edev);
ret = -EPROBE_DEFER;
goto err2;
}

View File

@ -52,6 +52,7 @@ static int dwc3_pci_register_phys(struct dwc3_pci *glue)
glue->usb2_phy = pdev;
pdata.type = USB_PHY_TYPE_USB2;
pdata.gpio_reset = -1;
ret = platform_device_add_data(glue->usb2_phy, &pdata, sizeof(pdata));
if (ret)
@ -182,7 +183,7 @@ static void dwc3_pci_remove(struct pci_dev *pci)
pci_disable_device(pci);
}
static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
static const struct pci_device_id dwc3_pci_id_table[] = {
{
PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),

View File

@ -1650,7 +1650,7 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
dev_vdbg(dwc->dev, "initializing %s\n", dep->name);
if (epnum == 0 || epnum == 1) {
dep->endpoint.maxpacket = 512;
usb_ep_set_maxpacket_limit(&dep->endpoint, 512);
dep->endpoint.maxburst = 1;
dep->endpoint.ops = &dwc3_gadget_ep0_ops;
if (!epnum)
@ -1658,7 +1658,7 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
} else {
int ret;
dep->endpoint.maxpacket = 1024;
usb_ep_set_maxpacket_limit(&dep->endpoint, 1024);
dep->endpoint.max_streams = 15;
dep->endpoint.ops = &dwc3_gadget_ep_ops;
list_add_tail(&dep->endpoint.ep_list,
@ -2596,6 +2596,12 @@ int dwc3_gadget_init(struct dwc3 *dwc)
dwc->gadget.sg_supported = true;
dwc->gadget.name = "dwc3-gadget";
/*
* Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize
* on ep out.
*/
dwc->gadget.quirk_ep_out_aligned_size = true;
/*
* REVISIT: Here we should clear all pending IRQs to be
* sure we're starting from a well known location.

View File

@ -216,6 +216,13 @@ config USB_FOTG210_UDC
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "fotg210_udc".
config USB_GR_UDC
tristate "Aeroflex Gaisler GRUSBDC USB Peripheral Controller Driver"
depends on HAS_DMA
help
Select this to support Aeroflex Gaisler GRUSBDC cores from the GRLIB
VHDL IP core library.
config USB_OMAP
tristate "OMAP USB Device Controller"
depends on ARCH_OMAP1
@ -294,11 +301,11 @@ config USB_PXA27X
gadget drivers to also be dynamically linked.
config USB_S3C_HSOTG
tristate "S3C HS/OtG USB Device controller"
depends on S3C_DEV_USB_HSOTG
depends on ARM
tristate "Designware/S3C HS/OtG USB Device controller"
help
The Samsung S3C64XX USB2.0 high-speed gadget controller
integrated into the S3C64XX series SoC.
The Designware USB2.0 high-speed gadget controller
integrated into many SoCs.
config USB_S3C2410
tristate "S3C2410 USB Device Controller"
@ -512,9 +519,6 @@ config USB_U_SERIAL
config USB_U_ETHER
tristate
config USB_U_RNDIS
tristate
config USB_F_SERIAL
tristate
@ -542,6 +546,9 @@ config USB_F_RNDIS
config USB_F_MASS_STORAGE
tristate
config USB_F_FS
tristate
choice
tristate "USB Gadget Drivers"
default USB_ETH
@ -642,7 +649,6 @@ config USB_CONFIGFS_RNDIS
depends on USB_CONFIGFS
depends on NET
select USB_U_ETHER
select USB_U_RNDIS
select USB_F_RNDIS
help
Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
@ -690,6 +696,31 @@ config USB_CONFIGFS_MASS_STORAGE
device (in much the same way as the "loop" device driver),
specified as a module parameter or sysfs option.
config USB_CONFIGFS_F_LB_SS
boolean "Loopback and sourcesink function (for testing)"
depends on USB_CONFIGFS
select USB_F_SS_LB
help
Loopback function loops back a configurable number of transfers.
Sourcesink function either sinks and sources bulk data.
It also implements control requests, for "chapter 9" conformance.
Make this be the first driver you try using on top of any new
USB peripheral controller driver. Then you can use host-side
test software, like the "usbtest" driver, to put your hardware
and its driver through a basic set of functional tests.
config USB_CONFIGFS_F_FS
boolean "Function filesystem (FunctionFS)"
depends on USB_CONFIGFS
select USB_F_FS
help
The Function Filesystem (FunctionFS) lets one create USB
composite functions in user space in the same way GadgetFS
lets one create USB gadgets in user space. This allows creation
of composite gadgets such that some of the functions are
implemented in kernel space (for instance Ethernet, serial or
mass storage) and other are implemented in user space.
config USB_ZERO
tristate "Gadget Zero (DEVELOPMENT)"
select USB_LIBCOMPOSITE
@ -760,7 +791,6 @@ config USB_ETH
depends on NET
select USB_LIBCOMPOSITE
select USB_U_ETHER
select USB_U_RNDIS
select USB_F_ECM
select USB_F_SUBSET
select CRC32
@ -864,6 +894,7 @@ config USB_GADGETFS
config USB_FUNCTIONFS
tristate "Function Filesystem"
select USB_LIBCOMPOSITE
select USB_F_FS
select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
help
The Function Filesystem (FunctionFS) lets one create USB
@ -883,6 +914,8 @@ config USB_FUNCTIONFS_ETH
bool "Include configuration with CDC ECM (Ethernet)"
depends on USB_FUNCTIONFS && NET
select USB_U_ETHER
select USB_F_ECM
select USB_F_SUBSET
help
Include a configuration with CDC ECM function (Ethernet) and the
Function Filesystem.
@ -891,7 +924,7 @@ config USB_FUNCTIONFS_RNDIS
bool "Include configuration with RNDIS (Ethernet)"
depends on USB_FUNCTIONFS && NET
select USB_U_ETHER
select USB_U_RNDIS
select USB_F_RNDIS
help
Include a configuration with RNDIS function (Ethernet) and the Filesystem.
@ -1065,7 +1098,6 @@ config USB_G_MULTI
config USB_G_MULTI_RNDIS
bool "RNDIS + CDC Serial + Storage configuration"
depends on USB_G_MULTI
select USB_U_RNDIS
select USB_F_RNDIS
default y
help

View File

@ -7,7 +7,7 @@ ccflags-$(CONFIG_USB_GADGET_VERBOSE) += -DVERBOSE_DEBUG
obj-$(CONFIG_USB_GADGET) += udc-core.o
obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
libcomposite-y := usbstring.o config.o epautoconf.o
libcomposite-y += composite.o functions.o configfs.o
libcomposite-y += composite.o functions.o configfs.o u_f.o
obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
obj-$(CONFIG_USB_NET2272) += net2272.o
obj-$(CONFIG_USB_NET2280) += net2280.o
@ -35,6 +35,7 @@ mv_udc-y := mv_udc_core.o
obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o
obj-$(CONFIG_USB_FOTG210_UDC) += fotg210-udc.o
obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o
obj-$(CONFIG_USB_GR_UDC) += gr_udc.o
# USB Functions
usb_f_acm-y := f_acm.o
@ -47,8 +48,6 @@ obj-$(CONFIG_USB_F_SERIAL) += usb_f_serial.o
usb_f_obex-y := f_obex.o
obj-$(CONFIG_USB_F_OBEX) += usb_f_obex.o
obj-$(CONFIG_USB_U_ETHER) += u_ether.o
u_rndis-y := rndis.o
obj-$(CONFIG_USB_U_RNDIS) += u_rndis.o
usb_f_ncm-y := f_ncm.o
obj-$(CONFIG_USB_F_NCM) += usb_f_ncm.o
usb_f_ecm-y := f_ecm.o
@ -59,10 +58,12 @@ usb_f_eem-y := f_eem.o
obj-$(CONFIG_USB_F_EEM) += usb_f_eem.o
usb_f_ecm_subset-y := f_subset.o
obj-$(CONFIG_USB_F_SUBSET) += usb_f_ecm_subset.o
usb_f_rndis-y := f_rndis.o
usb_f_rndis-y := f_rndis.o rndis.o
obj-$(CONFIG_USB_F_RNDIS) += usb_f_rndis.o
usb_f_mass_storage-y := f_mass_storage.o storage_common.o
obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
usb_f_fs-y := f_fs.o
obj-$(CONFIG_USB_F_FS) += usb_f_fs.o
#
# USB gadget drivers

View File

@ -107,7 +107,7 @@ static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
*/
#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
#endif /* CONFIG_USB_DEBUG */
#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);

View File

@ -40,7 +40,6 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
@ -446,7 +445,7 @@ static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep)
ep->ep.ops = &udc_ep_ops;
INIT_LIST_HEAD(&ep->queue);
ep->ep.maxpacket = (u16) ~0;
usb_ep_set_maxpacket_limit(&ep->ep,(u16) ~0);
/* set NAK */
tmp = readl(&ep->regs->ctl);
tmp |= AMD_BIT(UDC_EPCTL_SNAK);
@ -1564,12 +1563,15 @@ static void udc_setup_endpoints(struct udc *dev)
}
/* EP0 max packet */
if (dev->gadget.speed == USB_SPEED_FULL) {
dev->ep[UDC_EP0IN_IX].ep.maxpacket = UDC_FS_EP0IN_MAX_PKT_SIZE;
dev->ep[UDC_EP0OUT_IX].ep.maxpacket =
UDC_FS_EP0OUT_MAX_PKT_SIZE;
usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0IN_IX].ep,
UDC_FS_EP0IN_MAX_PKT_SIZE);
usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0OUT_IX].ep,
UDC_FS_EP0OUT_MAX_PKT_SIZE);
} else if (dev->gadget.speed == USB_SPEED_HIGH) {
dev->ep[UDC_EP0IN_IX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE;
dev->ep[UDC_EP0OUT_IX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE;
usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0IN_IX].ep,
UDC_EP0IN_MAX_PKT_SIZE);
usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0OUT_IX].ep,
UDC_EP0OUT_MAX_PKT_SIZE);
}
/*
@ -3338,7 +3340,7 @@ static int udc_remote_wakeup(struct udc *dev)
}
/* PCI device parameters */
static DEFINE_PCI_DEVICE_TABLE(pci_id) = {
static const struct pci_device_id pci_id[] = {
{
PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096),
.class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,

View File

@ -21,7 +21,6 @@
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/proc_fs.h>
@ -834,7 +833,7 @@ static void udc_reinit(struct at91_udc *udc)
ep->ep.desc = NULL;
ep->stopped = 0;
ep->fifo_bank = 0;
ep->ep.maxpacket = ep->maxpacket;
usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i);
/* initialize one queue per endpoint */
INIT_LIST_HEAD(&ep->queue);
@ -1759,15 +1758,15 @@ static int at91udc_probe(struct platform_device *pdev)
/* newer chips have more FIFO memory than rm9200 */
if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) {
udc->ep[0].maxpacket = 64;
udc->ep[3].maxpacket = 64;
udc->ep[4].maxpacket = 512;
udc->ep[5].maxpacket = 512;
usb_ep_set_maxpacket_limit(&udc->ep[0].ep, 64);
usb_ep_set_maxpacket_limit(&udc->ep[3].ep, 64);
usb_ep_set_maxpacket_limit(&udc->ep[4].ep, 512);
usb_ep_set_maxpacket_limit(&udc->ep[5].ep, 512);
} else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
udc->ep[3].maxpacket = 64;
usb_ep_set_maxpacket_limit(&udc->ep[3].ep, 64);
} else if (cpu_is_at91sam9263()) {
udc->ep[0].maxpacket = 64;
udc->ep[3].maxpacket = 64;
usb_ep_set_maxpacket_limit(&udc->ep[0].ep, 64);
usb_ep_set_maxpacket_limit(&udc->ep[3].ep, 64);
}
udc->udp_baseaddr = ioremap(res->start, resource_size(res));

View File

@ -1012,7 +1012,7 @@ static void nop_release(struct device *dev)
}
struct usb_gadget usba_gadget_template = {
static struct usb_gadget usba_gadget_template = {
.ops = &usba_udc_ops,
.max_speed = USB_SPEED_HIGH,
.name = "atmel_usba_udc",
@ -1904,7 +1904,7 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
ep->ep.ops = &usba_ep_ops;
ep->ep.maxpacket = ep->fifo_size;
usb_ep_set_maxpacket_limit(&ep->ep, ep->fifo_size);
ep->udc = udc;
INIT_LIST_HEAD(&ep->queue);
@ -1957,7 +1957,8 @@ static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
ep->ep.ops = &usba_ep_ops;
ep->ep.name = pdata->ep[i].name;
ep->fifo_size = ep->ep.maxpacket = pdata->ep[i].fifo_size;
ep->fifo_size = pdata->ep[i].fifo_size;
usb_ep_set_maxpacket_limit(&ep->ep, ep->fifo_size);
ep->udc = udc;
INIT_LIST_HEAD(&ep->queue);
ep->nr_banks = pdata->ep[i].nr_banks;
@ -1995,14 +1996,12 @@ static int __init usba_udc_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
pclk = clk_get(&pdev->dev, "pclk");
pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(pclk))
return PTR_ERR(pclk);
hclk = clk_get(&pdev->dev, "hclk");
if (IS_ERR(hclk)) {
ret = PTR_ERR(hclk);
goto err_get_hclk;
}
hclk = devm_clk_get(&pdev->dev, "hclk");
if (IS_ERR(hclk))
return PTR_ERR(hclk);
spin_lock_init(&udc->lock);
udc->pdev = pdev;
@ -2011,17 +2010,17 @@ static int __init usba_udc_probe(struct platform_device *pdev)
udc->vbus_pin = -ENODEV;
ret = -ENOMEM;
udc->regs = ioremap(regs->start, resource_size(regs));
udc->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
if (!udc->regs) {
dev_err(&pdev->dev, "Unable to map I/O memory, aborting.\n");
goto err_map_regs;
return ret;
}
dev_info(&pdev->dev, "MMIO registers at 0x%08lx mapped at %p\n",
(unsigned long)regs->start, udc->regs);
udc->fifo = ioremap(fifo->start, resource_size(fifo));
udc->fifo = devm_ioremap(&pdev->dev, fifo->start, resource_size(fifo));
if (!udc->fifo) {
dev_err(&pdev->dev, "Unable to map FIFO, aborting.\n");
goto err_map_fifo;
return ret;
}
dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
(unsigned long)fifo->start, udc->fifo);
@ -2032,7 +2031,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
ret = clk_prepare_enable(pclk);
if (ret) {
dev_err(&pdev->dev, "Unable to enable pclk, aborting.\n");
goto err_clk_enable;
return ret;
}
toggle_bias(0);
usba_writel(udc, CTRL, USBA_DISABLE_MASK);
@ -2043,22 +2042,22 @@ static int __init usba_udc_probe(struct platform_device *pdev)
else
udc->usba_ep = usba_udc_pdata(pdev, udc);
if (IS_ERR(udc->usba_ep)) {
ret = PTR_ERR(udc->usba_ep);
goto err_alloc_ep;
}
if (IS_ERR(udc->usba_ep))
return PTR_ERR(udc->usba_ep);
ret = request_irq(irq, usba_udc_irq, 0, "atmel_usba_udc", udc);
ret = devm_request_irq(&pdev->dev, irq, usba_udc_irq, 0,
"atmel_usba_udc", udc);
if (ret) {
dev_err(&pdev->dev, "Cannot request irq %d (error %d)\n",
irq, ret);
goto err_request_irq;
return ret;
}
udc->irq = irq;
if (gpio_is_valid(udc->vbus_pin)) {
if (!devm_gpio_request(&pdev->dev, udc->vbus_pin, "atmel_usba_udc")) {
ret = request_irq(gpio_to_irq(udc->vbus_pin),
ret = devm_request_irq(&pdev->dev,
gpio_to_irq(udc->vbus_pin),
usba_vbus_irq, 0,
"atmel_usba_udc", udc);
if (ret) {
@ -2077,31 +2076,13 @@ static int __init usba_udc_probe(struct platform_device *pdev)
ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
if (ret)
goto err_add_udc;
return ret;
usba_init_debugfs(udc);
for (i = 1; i < udc->num_ep; i++)
usba_ep_init_debugfs(udc, &udc->usba_ep[i]);
return 0;
err_add_udc:
if (gpio_is_valid(udc->vbus_pin))
free_irq(gpio_to_irq(udc->vbus_pin), udc);
free_irq(irq, udc);
err_request_irq:
err_alloc_ep:
err_clk_enable:
iounmap(udc->fifo);
err_map_fifo:
iounmap(udc->regs);
err_map_regs:
clk_put(hclk);
err_get_hclk:
clk_put(pclk);
return ret;
}
static int __exit usba_udc_remove(struct platform_device *pdev)
@ -2117,16 +2098,6 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
usba_ep_cleanup_debugfs(&udc->usba_ep[i]);
usba_cleanup_debugfs(udc);
if (gpio_is_valid(udc->vbus_pin)) {
free_irq(gpio_to_irq(udc->vbus_pin), udc);
}
free_irq(udc->irq, udc);
iounmap(udc->fifo);
iounmap(udc->regs);
clk_put(udc->hclk);
clk_put(udc->pclk);
return 0;
}

View File

@ -19,7 +19,6 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/kconfig.h>
@ -549,7 +548,7 @@ static void bcm63xx_ep_setup(struct bcm63xx_udc *udc)
if (idx < 0)
continue;
udc->bep[idx].ep.maxpacket = max_pkt;
usb_ep_set_maxpacket_limit(&udc->bep[idx].ep, max_pkt);
val = (idx << USBD_CSR_EP_LOG_SHIFT) |
(cfg->dir << USBD_CSR_EP_DIR_SHIFT) |
@ -943,7 +942,7 @@ static int bcm63xx_init_udc_hw(struct bcm63xx_udc *udc)
bep->ep.ops = &bcm63xx_udc_ep_ops;
list_add_tail(&bep->ep.ep_list, &udc->gadget.ep_list);
bep->halted = 0;
bep->ep.maxpacket = BCM63XX_MAX_CTRL_PKT;
usb_ep_set_maxpacket_limit(&bep->ep, BCM63XX_MAX_CTRL_PKT);
bep->udc = udc;
bep->ep.desc = NULL;
INIT_LIST_HEAD(&bep->queue);

View File

@ -1452,8 +1452,22 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
struct usb_configuration *c;
c = cdev->config;
if (c && c->setup)
if (!c)
goto done;
/* try current config's setup */
if (c->setup) {
value = c->setup(c, ctrl);
goto done;
}
/* try the only function in the current config */
if (!list_is_singular(&c->functions))
goto done;
f = list_first_entry(&c->functions, struct usb_function,
list);
if (f->setup)
value = f->setup(f, ctrl);
}
goto done;
@ -1714,7 +1728,7 @@ composite_resume(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev = get_gadget_data(gadget);
struct usb_function *f;
u8 maxpower;
u16 maxpower;
/* REVISIT: should we have config level
* suspend/resume callbacks?

View File

@ -4,6 +4,7 @@
#include <linux/device.h>
#include <linux/usb/composite.h>
#include <linux/usb/gadget_configfs.h>
#include "configfs.h"
int check_user_usb_string(const char *name,
struct usb_gadget_strings *stringtab_dev)
@ -564,6 +565,13 @@ static struct config_group *function_make(
usb_put_function_instance(fi);
return ERR_PTR(ret);
}
if (fi->set_inst_name) {
ret = fi->set_inst_name(fi, instance_name);
if (ret) {
usb_put_function_instance(fi);
return ERR_PTR(ret);
}
}
gi = container_of(group, struct gadget_info, functions_group);

View File

@ -951,7 +951,7 @@ static void init_dummy_udc_hw(struct dummy *dum)
list_add_tail(&ep->ep.ep_list, &dum->gadget.ep_list);
ep->halted = ep->wedged = ep->already_seen =
ep->setup_stage = 0;
ep->ep.maxpacket = ~0;
usb_ep_set_maxpacket_limit(&ep->ep, ~0);
ep->ep.max_streams = 16;
ep->last_io = jiffies;
ep->gadget = &dum->gadget;

View File

@ -11,7 +11,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/device.h>
@ -58,7 +57,7 @@ ep_matches (
return 0;
/* only support ep0 for portable CONTROL traffic */
type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
type = usb_endpoint_type(desc);
if (USB_ENDPOINT_XFER_CONTROL == type)
return 0;
@ -129,7 +128,7 @@ ep_matches (
* and wants to know the maximum possible, provide the info.
*/
if (desc->wMaxPacketSize == 0)
desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket);
desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit);
/* endpoint maxpacket size is an input parameter, except for bulk
* where it's an output parameter representing the full speed limit.
@ -145,7 +144,7 @@ ep_matches (
case USB_ENDPOINT_XFER_ISOC:
/* ISO: limit 1023 bytes full speed, 1024 high/super speed */
if (ep->maxpacket < max)
if (ep->maxpacket_limit < max)
return 0;
if (!gadget_is_dualspeed(gadget) && max > 1023)
return 0;
@ -178,7 +177,7 @@ ep_matches (
/* report (variable) full speed bulk maxpacket */
if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) {
int size = ep->maxpacket;
int size = ep->maxpacket_limit;
/* min() doesn't work on bitfields with gcc-3.5 */
if (size > 64)

View File

@ -691,7 +691,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
int status;
struct usb_ep *ep;
#ifndef USBF_ECM_INCLUDED
struct f_ecm_opts *ecm_opts;
if (!can_support_ecm(cdev->gadget))
@ -715,7 +714,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
return status;
ecm_opts->bound = true;
}
#endif
us = usb_gstrings_attach(cdev, ecm_strings,
ARRAY_SIZE(ecm_string_defs));
if (IS_ERR(us))
@ -834,74 +833,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
return status;
}
#ifdef USBF_ECM_INCLUDED
static void
ecm_old_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_ecm *ecm = func_to_ecm(f);
DBG(c->cdev, "ecm unbind\n");
usb_free_all_descriptors(f);
kfree(ecm->notify_req->buf);
usb_ep_free_request(ecm->notify, ecm->notify_req);
kfree(ecm);
}
/**
* ecm_bind_config - add CDC Ethernet network link to a configuration
* @c: the configuration to support the network link
* @ethaddr: a buffer in which the ethernet address of the host side
* side of the link was recorded
* @dev: eth_dev structure
* Context: single threaded during gadget setup
*
* Returns zero on success, else negative errno.
*
* Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload.
*/
int
ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct eth_dev *dev)
{
struct f_ecm *ecm;
int status;
if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
return -EINVAL;
/* allocate and initialize one new instance */
ecm = kzalloc(sizeof *ecm, GFP_KERNEL);
if (!ecm)
return -ENOMEM;
/* export host's Ethernet address in CDC format */
snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr);
ecm_string_defs[1].s = ecm->ethaddr;
ecm->port.ioport = dev;
ecm->port.cdc_filter = DEFAULT_FILTER;
ecm->port.func.name = "cdc_ethernet";
/* descriptors are per-instance copies */
ecm->port.func.bind = ecm_bind;
ecm->port.func.unbind = ecm_old_unbind;
ecm->port.func.set_alt = ecm_set_alt;
ecm->port.func.get_alt = ecm_get_alt;
ecm->port.func.setup = ecm_setup;
ecm->port.func.disable = ecm_disable;
status = usb_add_function(c, &ecm->port.func);
if (status)
kfree(ecm);
return status;
}
#else
static inline struct f_ecm_opts *to_f_ecm_opts(struct config_item *item)
{
return container_of(to_config_group(item), struct f_ecm_opts,
@ -1040,5 +971,3 @@ static struct usb_function *ecm_alloc(struct usb_function_instance *fi)
DECLARE_USB_FUNCTION_INIT(ecm, ecm_alloc_inst, ecm_alloc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Brownell");
#endif

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,8 @@
#include <linux/sched.h>
#include <linux/usb/g_hid.h>
#include "u_f.h"
static int major, minors;
static struct class *hidg_class;
@ -334,20 +336,10 @@ static int f_hidg_open(struct inode *inode, struct file *fd)
/*-------------------------------------------------------------------------*/
/* usb_function */
static struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep, unsigned length)
static inline struct usb_request *hidg_alloc_ep_req(struct usb_ep *ep,
unsigned length)
{
struct usb_request *req;
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (req) {
req->length = length;
req->buf = kmalloc(length, GFP_ATOMIC);
if (!req->buf) {
usb_ep_free_request(ep, req);
req = NULL;
}
}
return req;
return alloc_ep_req(ep, length, length);
}
static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req)

View File

@ -20,6 +20,7 @@
#include <linux/usb/composite.h>
#include "g_zero.h"
#include "u_f.h"
/*
* LOOPBACK FUNCTION ... a testing vehicle for USB peripherals,
@ -119,7 +120,7 @@ static struct usb_endpoint_descriptor ss_loop_source_desc = {
.wMaxPacketSize = cpu_to_le16(1024),
};
struct usb_ss_ep_comp_descriptor ss_loop_source_comp_desc = {
static struct usb_ss_ep_comp_descriptor ss_loop_source_comp_desc = {
.bLength = USB_DT_SS_EP_COMP_SIZE,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
.bMaxBurst = 0,
@ -135,7 +136,7 @@ static struct usb_endpoint_descriptor ss_loop_sink_desc = {
.wMaxPacketSize = cpu_to_le16(1024),
};
struct usb_ss_ep_comp_descriptor ss_loop_sink_comp_desc = {
static struct usb_ss_ep_comp_descriptor ss_loop_sink_comp_desc = {
.bLength = USB_DT_SS_EP_COMP_SIZE,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
.bMaxBurst = 0,
@ -230,6 +231,14 @@ static int loopback_bind(struct usb_configuration *c, struct usb_function *f)
static void lb_free_func(struct usb_function *f)
{
struct f_lb_opts *opts;
opts = container_of(f->fi, struct f_lb_opts, func_inst);
mutex_lock(&opts->lock);
opts->refcnt--;
mutex_unlock(&opts->lock);
usb_free_all_descriptors(f);
kfree(func_to_loop(f));
}
@ -293,6 +302,11 @@ static void disable_loopback(struct f_loopback *loop)
VDBG(cdev, "%s disabled\n", loop->function.name);
}
static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len)
{
return alloc_ep_req(ep, len, buflen);
}
static int
enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
{
@ -332,7 +346,7 @@ enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
* than 'buflen' bytes each.
*/
for (i = 0; i < qlen && result == 0; i++) {
req = alloc_ep_req(ep, 0);
req = lb_alloc_ep_req(ep, 0);
if (req) {
req->complete = loopback_complete;
result = usb_ep_queue(ep, req, GFP_ATOMIC);
@ -380,6 +394,11 @@ static struct usb_function *loopback_alloc(struct usb_function_instance *fi)
return ERR_PTR(-ENOMEM);
lb_opts = container_of(fi, struct f_lb_opts, func_inst);
mutex_lock(&lb_opts->lock);
lb_opts->refcnt++;
mutex_unlock(&lb_opts->lock);
buflen = lb_opts->bulk_buflen;
qlen = lb_opts->qlen;
if (!qlen)
@ -396,6 +415,118 @@ static struct usb_function *loopback_alloc(struct usb_function_instance *fi)
return &loop->function;
}
static inline struct f_lb_opts *to_f_lb_opts(struct config_item *item)
{
return container_of(to_config_group(item), struct f_lb_opts,
func_inst.group);
}
CONFIGFS_ATTR_STRUCT(f_lb_opts);
CONFIGFS_ATTR_OPS(f_lb_opts);
static void lb_attr_release(struct config_item *item)
{
struct f_lb_opts *lb_opts = to_f_lb_opts(item);
usb_put_function_instance(&lb_opts->func_inst);
}
static struct configfs_item_operations lb_item_ops = {
.release = lb_attr_release,
.show_attribute = f_lb_opts_attr_show,
.store_attribute = f_lb_opts_attr_store,
};
static ssize_t f_lb_opts_qlen_show(struct f_lb_opts *opts, char *page)
{
int result;
mutex_lock(&opts->lock);
result = sprintf(page, "%d", opts->qlen);
mutex_unlock(&opts->lock);
return result;
}
static ssize_t f_lb_opts_qlen_store(struct f_lb_opts *opts,
const char *page, size_t len)
{
int ret;
u32 num;
mutex_lock(&opts->lock);
if (opts->refcnt) {
ret = -EBUSY;
goto end;
}
ret = kstrtou32(page, 0, &num);
if (ret)
goto end;
opts->qlen = num;
ret = len;
end:
mutex_unlock(&opts->lock);
return ret;
}
static struct f_lb_opts_attribute f_lb_opts_qlen =
__CONFIGFS_ATTR(qlen, S_IRUGO | S_IWUSR,
f_lb_opts_qlen_show,
f_lb_opts_qlen_store);
static ssize_t f_lb_opts_bulk_buflen_show(struct f_lb_opts *opts, char *page)
{
int result;
mutex_lock(&opts->lock);
result = sprintf(page, "%d", opts->bulk_buflen);
mutex_unlock(&opts->lock);
return result;
}
static ssize_t f_lb_opts_bulk_buflen_store(struct f_lb_opts *opts,
const char *page, size_t len)
{
int ret;
u32 num;
mutex_lock(&opts->lock);
if (opts->refcnt) {
ret = -EBUSY;
goto end;
}
ret = kstrtou32(page, 0, &num);
if (ret)
goto end;
opts->bulk_buflen = num;
ret = len;
end:
mutex_unlock(&opts->lock);
return ret;
}
static struct f_lb_opts_attribute f_lb_opts_bulk_buflen =
__CONFIGFS_ATTR(buflen, S_IRUGO | S_IWUSR,
f_lb_opts_bulk_buflen_show,
f_lb_opts_bulk_buflen_store);
static struct configfs_attribute *lb_attrs[] = {
&f_lb_opts_qlen.attr,
&f_lb_opts_bulk_buflen.attr,
NULL,
};
static struct config_item_type lb_func_type = {
.ct_item_ops = &lb_item_ops,
.ct_attrs = lb_attrs,
.ct_owner = THIS_MODULE,
};
static void lb_free_instance(struct usb_function_instance *fi)
{
struct f_lb_opts *lb_opts;
@ -411,7 +542,14 @@ static struct usb_function_instance *loopback_alloc_instance(void)
lb_opts = kzalloc(sizeof(*lb_opts), GFP_KERNEL);
if (!lb_opts)
return ERR_PTR(-ENOMEM);
mutex_init(&lb_opts->lock);
lb_opts->func_inst.free_func_inst = lb_free_instance;
lb_opts->bulk_buflen = GZERO_BULK_BUFLEN;
lb_opts->qlen = GZERO_QLEN;
config_group_init_type_name(&lb_opts->func_inst.group, "",
&lb_func_type);
return &lb_opts->func_inst;
}
DECLARE_USB_FUNCTION(Loopback, loopback_alloc_instance, loopback_alloc);

View File

@ -32,6 +32,8 @@
#include <linux/usb/audio.h>
#include <linux/usb/midi.h>
#include "u_f.h"
MODULE_AUTHOR("Ben Williamson");
MODULE_LICENSE("GPL v2");
@ -191,20 +193,10 @@ static struct usb_gadget_strings *midi_strings[] = {
NULL,
};
static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
static inline struct usb_request *midi_alloc_ep_req(struct usb_ep *ep,
unsigned length)
{
struct usb_request *req;
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (req) {
req->length = length;
req->buf = kmalloc(length, GFP_ATOMIC);
if (!req->buf) {
usb_ep_free_request(ep, req);
req = NULL;
}
}
return req;
return alloc_ep_req(ep, length, length);
}
static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
@ -365,7 +357,7 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* allocate a bunch of read buffers and queue them all at once. */
for (i = 0; i < midi->qlen && err == 0; i++) {
struct usb_request *req =
alloc_ep_req(midi->out_ep, midi->buflen);
midi_alloc_ep_req(midi->out_ep, midi->buflen);
if (req == NULL)
return -ENOMEM;
@ -546,7 +538,7 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req)
return;
if (!req)
req = alloc_ep_req(ep, midi->buflen);
req = midi_alloc_ep_req(ep, midi->buflen);
if (!req) {
ERROR(midi, "gmidi_transmit: alloc_ep_request failed\n");

View File

@ -1386,7 +1386,7 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f)
usb_ep_free_request(ncm->notify, ncm->notify_req);
}
struct usb_function *ncm_alloc(struct usb_function_instance *fi)
static struct usb_function *ncm_alloc(struct usb_function_instance *fi)
{
struct f_ncm *ncm;
struct f_ncm_opts *opts;

View File

@ -499,7 +499,7 @@ static void obex_unbind(struct usb_configuration *c, struct usb_function *f)
usb_free_all_descriptors(f);
}
struct usb_function *obex_alloc(struct usb_function_instance *fi)
static struct usb_function *obex_alloc(struct usb_function_instance *fi)
{
struct f_obex *obex;
struct f_serial_opts *opts;

View File

@ -689,7 +689,7 @@ static void pn_unbind(struct usb_configuration *c, struct usb_function *f)
usb_free_all_descriptors(f);
}
struct usb_function *phonet_alloc(struct usb_function_instance *fi)
static struct usb_function *phonet_alloc(struct usb_function_instance *fi)
{
struct f_phonet *fp;
struct f_phonet_opts *opts;

View File

@ -675,7 +675,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
int status;
struct usb_ep *ep;
#ifndef USB_FRNDIS_INCLUDED
struct f_rndis_opts *rndis_opts;
if (!can_support_rndis(c))
@ -697,7 +696,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
return status;
rndis_opts->bound = true;
}
#endif
us = usb_gstrings_attach(cdev, rndis_strings,
ARRAY_SIZE(rndis_string_defs));
if (IS_ERR(us))
@ -782,13 +781,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
rndis->port.open = rndis_open;
rndis->port.close = rndis_close;
#ifdef USB_FRNDIS_INCLUDED
status = rndis_register(rndis_response_available, rndis);
if (status < 0)
goto fail;
rndis->config = status;
#endif
rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0);
rndis_set_host_mac(rndis->config, rndis->ethaddr);
@ -830,66 +822,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
return status;
}
#ifdef USB_FRNDIS_INCLUDED
static void
rndis_old_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_rndis *rndis = func_to_rndis(f);
rndis_deregister(rndis->config);
usb_free_all_descriptors(f);
kfree(rndis->notify_req->buf);
usb_ep_free_request(rndis->notify, rndis->notify_req);
kfree(rndis);
}
int
rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
u32 vendorID, const char *manufacturer, struct eth_dev *dev)
{
struct f_rndis *rndis;
int status;
/* allocate and initialize one new instance */
status = -ENOMEM;
rndis = kzalloc(sizeof *rndis, GFP_KERNEL);
if (!rndis)
goto fail;
memcpy(rndis->ethaddr, ethaddr, ETH_ALEN);
rndis->vendorID = vendorID;
rndis->manufacturer = manufacturer;
rndis->port.ioport = dev;
/* RNDIS activates when the host changes this filter */
rndis->port.cdc_filter = 0;
/* RNDIS has special (and complex) framing */
rndis->port.header_len = sizeof(struct rndis_packet_msg_type);
rndis->port.wrap = rndis_add_header;
rndis->port.unwrap = rndis_rm_hdr;
rndis->port.func.name = "rndis";
/* descriptors are per-instance copies */
rndis->port.func.bind = rndis_bind;
rndis->port.func.unbind = rndis_old_unbind;
rndis->port.func.set_alt = rndis_set_alt;
rndis->port.func.setup = rndis_setup;
rndis->port.func.disable = rndis_disable;
status = usb_add_function(c, &rndis->port.func);
if (status)
kfree(rndis);
fail:
return status;
}
#else
void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net)
{
struct f_rndis_opts *opts;
@ -1047,8 +979,26 @@ static struct usb_function *rndis_alloc(struct usb_function_instance *fi)
return &rndis->port.func;
}
DECLARE_USB_FUNCTION_INIT(rndis, rndis_alloc_inst, rndis_alloc);
DECLARE_USB_FUNCTION(rndis, rndis_alloc_inst, rndis_alloc);
static int __init rndis_mod_init(void)
{
int ret;
ret = rndis_init();
if (ret)
return ret;
return usb_function_register(&rndisusb_func);
}
module_init(rndis_mod_init);
static void __exit rndis_mod_exit(void)
{
usb_function_unregister(&rndisusb_func);
rndis_exit();
}
module_exit(rndis_mod_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Brownell");
#endif

View File

@ -354,7 +354,7 @@ static void gser_unbind(struct usb_configuration *c, struct usb_function *f)
usb_free_all_descriptors(f);
}
struct usb_function *gser_alloc(struct usb_function_instance *fi)
static struct usb_function *gser_alloc(struct usb_function_instance *fi)
{
struct f_gser *gser;
struct f_serial_opts *opts;

View File

@ -21,6 +21,7 @@
#include "g_zero.h"
#include "gadget_chips.h"
#include "u_f.h"
/*
* SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral
@ -201,7 +202,7 @@ static struct usb_endpoint_descriptor ss_source_desc = {
.wMaxPacketSize = cpu_to_le16(1024),
};
struct usb_ss_ep_comp_descriptor ss_source_comp_desc = {
static struct usb_ss_ep_comp_descriptor ss_source_comp_desc = {
.bLength = USB_DT_SS_EP_COMP_SIZE,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
@ -218,7 +219,7 @@ static struct usb_endpoint_descriptor ss_sink_desc = {
.wMaxPacketSize = cpu_to_le16(1024),
};
struct usb_ss_ep_comp_descriptor ss_sink_comp_desc = {
static struct usb_ss_ep_comp_descriptor ss_sink_comp_desc = {
.bLength = USB_DT_SS_EP_COMP_SIZE,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
@ -236,7 +237,7 @@ static struct usb_endpoint_descriptor ss_iso_source_desc = {
.bInterval = 4,
};
struct usb_ss_ep_comp_descriptor ss_iso_source_comp_desc = {
static struct usb_ss_ep_comp_descriptor ss_iso_source_comp_desc = {
.bLength = USB_DT_SS_EP_COMP_SIZE,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
@ -254,7 +255,7 @@ static struct usb_endpoint_descriptor ss_iso_sink_desc = {
.bInterval = 4,
};
struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = {
static struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = {
.bLength = USB_DT_SS_EP_COMP_SIZE,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
@ -301,23 +302,9 @@ static struct usb_gadget_strings *sourcesink_strings[] = {
/*-------------------------------------------------------------------------*/
struct usb_request *alloc_ep_req(struct usb_ep *ep, int len)
static inline struct usb_request *ss_alloc_ep_req(struct usb_ep *ep, int len)
{
struct usb_request *req;
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (req) {
if (len)
req->length = len;
else
req->length = buflen;
req->buf = kmalloc(req->length, GFP_ATOMIC);
if (!req->buf) {
usb_ep_free_request(ep, req);
req = NULL;
}
}
return req;
return alloc_ep_req(ep, len, buflen);
}
void free_ep_req(struct usb_ep *ep, struct usb_request *req)
@ -490,6 +477,14 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
static void
sourcesink_free_func(struct usb_function *f)
{
struct f_ss_opts *opts;
opts = container_of(f->fi, struct f_ss_opts, func_inst);
mutex_lock(&opts->lock);
opts->refcnt--;
mutex_unlock(&opts->lock);
usb_free_all_descriptors(f);
kfree(func_to_ss(f));
}
@ -628,10 +623,10 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
break;
}
ep = is_in ? ss->iso_in_ep : ss->iso_out_ep;
req = alloc_ep_req(ep, size);
req = ss_alloc_ep_req(ep, size);
} else {
ep = is_in ? ss->in_ep : ss->out_ep;
req = alloc_ep_req(ep, 0);
req = ss_alloc_ep_req(ep, 0);
}
if (!req)
@ -878,6 +873,11 @@ static struct usb_function *source_sink_alloc_func(
return NULL;
ss_opts = container_of(fi, struct f_ss_opts, func_inst);
mutex_lock(&ss_opts->lock);
ss_opts->refcnt++;
mutex_unlock(&ss_opts->lock);
pattern = ss_opts->pattern;
isoc_interval = ss_opts->isoc_interval;
isoc_maxpacket = ss_opts->isoc_maxpacket;
@ -898,6 +898,303 @@ static struct usb_function *source_sink_alloc_func(
return &ss->function;
}
static inline struct f_ss_opts *to_f_ss_opts(struct config_item *item)
{
return container_of(to_config_group(item), struct f_ss_opts,
func_inst.group);
}
CONFIGFS_ATTR_STRUCT(f_ss_opts);
CONFIGFS_ATTR_OPS(f_ss_opts);
static void ss_attr_release(struct config_item *item)
{
struct f_ss_opts *ss_opts = to_f_ss_opts(item);
usb_put_function_instance(&ss_opts->func_inst);
}
static struct configfs_item_operations ss_item_ops = {
.release = ss_attr_release,
.show_attribute = f_ss_opts_attr_show,
.store_attribute = f_ss_opts_attr_store,
};
static ssize_t f_ss_opts_pattern_show(struct f_ss_opts *opts, char *page)
{
int result;
mutex_lock(&opts->lock);
result = sprintf(page, "%d", opts->pattern);
mutex_unlock(&opts->lock);
return result;
}
static ssize_t f_ss_opts_pattern_store(struct f_ss_opts *opts,
const char *page, size_t len)
{
int ret;
u8 num;
mutex_lock(&opts->lock);
if (opts->refcnt) {
ret = -EBUSY;
goto end;
}
ret = kstrtou8(page, 0, &num);
if (ret)
goto end;
if (num != 0 && num != 1 && num != 2) {
ret = -EINVAL;
goto end;
}
opts->pattern = num;
ret = len;
end:
mutex_unlock(&opts->lock);
return ret;
}
static struct f_ss_opts_attribute f_ss_opts_pattern =
__CONFIGFS_ATTR(pattern, S_IRUGO | S_IWUSR,
f_ss_opts_pattern_show,
f_ss_opts_pattern_store);
static ssize_t f_ss_opts_isoc_interval_show(struct f_ss_opts *opts, char *page)
{
int result;
mutex_lock(&opts->lock);
result = sprintf(page, "%d", opts->isoc_interval);
mutex_unlock(&opts->lock);
return result;
}
static ssize_t f_ss_opts_isoc_interval_store(struct f_ss_opts *opts,
const char *page, size_t len)
{
int ret;
u8 num;
mutex_lock(&opts->lock);
if (opts->refcnt) {
ret = -EBUSY;
goto end;
}
ret = kstrtou8(page, 0, &num);
if (ret)
goto end;
if (num > 16) {
ret = -EINVAL;
goto end;
}
opts->isoc_interval = num;
ret = len;
end:
mutex_unlock(&opts->lock);
return ret;
}
static struct f_ss_opts_attribute f_ss_opts_isoc_interval =
__CONFIGFS_ATTR(isoc_interval, S_IRUGO | S_IWUSR,
f_ss_opts_isoc_interval_show,
f_ss_opts_isoc_interval_store);
static ssize_t f_ss_opts_isoc_maxpacket_show(struct f_ss_opts *opts, char *page)
{
int result;
mutex_lock(&opts->lock);
result = sprintf(page, "%d", opts->isoc_maxpacket);
mutex_unlock(&opts->lock);
return result;
}
static ssize_t f_ss_opts_isoc_maxpacket_store(struct f_ss_opts *opts,
const char *page, size_t len)
{
int ret;
u16 num;
mutex_lock(&opts->lock);
if (opts->refcnt) {
ret = -EBUSY;
goto end;
}
ret = kstrtou16(page, 0, &num);
if (ret)
goto end;
if (num > 1024) {
ret = -EINVAL;
goto end;
}
opts->isoc_maxpacket = num;
ret = len;
end:
mutex_unlock(&opts->lock);
return ret;
}
static struct f_ss_opts_attribute f_ss_opts_isoc_maxpacket =
__CONFIGFS_ATTR(isoc_maxpacket, S_IRUGO | S_IWUSR,
f_ss_opts_isoc_maxpacket_show,
f_ss_opts_isoc_maxpacket_store);
static ssize_t f_ss_opts_isoc_mult_show(struct f_ss_opts *opts, char *page)
{
int result;
mutex_lock(&opts->lock);
result = sprintf(page, "%d", opts->isoc_mult);
mutex_unlock(&opts->lock);
return result;
}
static ssize_t f_ss_opts_isoc_mult_store(struct f_ss_opts *opts,
const char *page, size_t len)
{
int ret;
u8 num;
mutex_lock(&opts->lock);
if (opts->refcnt) {
ret = -EBUSY;
goto end;
}
ret = kstrtou8(page, 0, &num);
if (ret)
goto end;
if (num > 2) {
ret = -EINVAL;
goto end;
}
opts->isoc_mult = num;
ret = len;
end:
mutex_unlock(&opts->lock);
return ret;
}
static struct f_ss_opts_attribute f_ss_opts_isoc_mult =
__CONFIGFS_ATTR(isoc_mult, S_IRUGO | S_IWUSR,
f_ss_opts_isoc_mult_show,
f_ss_opts_isoc_mult_store);
static ssize_t f_ss_opts_isoc_maxburst_show(struct f_ss_opts *opts, char *page)
{
int result;
mutex_lock(&opts->lock);
result = sprintf(page, "%d", opts->isoc_maxburst);
mutex_unlock(&opts->lock);
return result;
}
static ssize_t f_ss_opts_isoc_maxburst_store(struct f_ss_opts *opts,
const char *page, size_t len)
{
int ret;
u8 num;
mutex_lock(&opts->lock);
if (opts->refcnt) {
ret = -EBUSY;
goto end;
}
ret = kstrtou8(page, 0, &num);
if (ret)
goto end;
if (num > 15) {
ret = -EINVAL;
goto end;
}
opts->isoc_maxburst = num;
ret = len;
end:
mutex_unlock(&opts->lock);
return ret;
}
static struct f_ss_opts_attribute f_ss_opts_isoc_maxburst =
__CONFIGFS_ATTR(isoc_maxburst, S_IRUGO | S_IWUSR,
f_ss_opts_isoc_maxburst_show,
f_ss_opts_isoc_maxburst_store);
static ssize_t f_ss_opts_bulk_buflen_show(struct f_ss_opts *opts, char *page)
{
int result;
mutex_lock(&opts->lock);
result = sprintf(page, "%d", opts->bulk_buflen);
mutex_unlock(&opts->lock);
return result;
}
static ssize_t f_ss_opts_bulk_buflen_store(struct f_ss_opts *opts,
const char *page, size_t len)
{
int ret;
u32 num;
mutex_lock(&opts->lock);
if (opts->refcnt) {
ret = -EBUSY;
goto end;
}
ret = kstrtou32(page, 0, &num);
if (ret)
goto end;
opts->bulk_buflen = num;
ret = len;
end:
mutex_unlock(&opts->lock);
return ret;
}
static struct f_ss_opts_attribute f_ss_opts_bulk_buflen =
__CONFIGFS_ATTR(buflen, S_IRUGO | S_IWUSR,
f_ss_opts_bulk_buflen_show,
f_ss_opts_bulk_buflen_store);
static struct configfs_attribute *ss_attrs[] = {
&f_ss_opts_pattern.attr,
&f_ss_opts_isoc_interval.attr,
&f_ss_opts_isoc_maxpacket.attr,
&f_ss_opts_isoc_mult.attr,
&f_ss_opts_isoc_maxburst.attr,
&f_ss_opts_bulk_buflen.attr,
NULL,
};
static struct config_item_type ss_func_type = {
.ct_item_ops = &ss_item_ops,
.ct_attrs = ss_attrs,
.ct_owner = THIS_MODULE,
};
static void source_sink_free_instance(struct usb_function_instance *fi)
{
struct f_ss_opts *ss_opts;
@ -913,7 +1210,15 @@ static struct usb_function_instance *source_sink_alloc_inst(void)
ss_opts = kzalloc(sizeof(*ss_opts), GFP_KERNEL);
if (!ss_opts)
return ERR_PTR(-ENOMEM);
mutex_init(&ss_opts->lock);
ss_opts->func_inst.free_func_inst = source_sink_free_instance;
ss_opts->isoc_interval = GZERO_ISOC_INTERVAL;
ss_opts->isoc_maxpacket = GZERO_ISOC_MAXPACKET;
ss_opts->bulk_buflen = GZERO_BULK_BUFLEN;
config_group_init_type_name(&ss_opts->func_inst.group, "",
&ss_func_type);
return &ss_opts->func_inst;
}
DECLARE_USB_FUNCTION(SourceSink, source_sink_alloc_inst,

View File

@ -301,7 +301,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
int status;
struct usb_ep *ep;
#ifndef USB_FSUBSET_INCLUDED
struct f_gether_opts *gether_opts;
gether_opts = container_of(f->fi, struct f_gether_opts, func_inst);
@ -322,7 +321,7 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
return status;
gether_opts->bound = true;
}
#endif
us = usb_gstrings_attach(cdev, geth_strings,
ARRAY_SIZE(geth_string_defs));
if (IS_ERR(us))
@ -393,61 +392,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
return status;
}
#ifdef USB_FSUBSET_INCLUDED
static void
geth_old_unbind(struct usb_configuration *c, struct usb_function *f)
{
geth_string_defs[0].id = 0;
usb_free_all_descriptors(f);
kfree(func_to_geth(f));
}
/**
* geth_bind_config - add CDC Subset network link to a configuration
* @c: the configuration to support the network link
* @ethaddr: a buffer in which the ethernet address of the host side
* side of the link was recorded
* @dev: eth_dev structure
* Context: single threaded during gadget setup
*
* Returns zero on success, else negative errno.
*
* Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload.
*/
int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct eth_dev *dev)
{
struct f_gether *geth;
int status;
/* allocate and initialize one new instance */
geth = kzalloc(sizeof *geth, GFP_KERNEL);
if (!geth)
return -ENOMEM;
/* export host's Ethernet address in CDC format */
snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr);
geth_string_defs[1].s = geth->ethaddr;
geth->port.ioport = dev;
geth->port.cdc_filter = DEFAULT_FILTER;
geth->port.func.name = "cdc_subset";
geth->port.func.bind = geth_bind;
geth->port.func.unbind = geth_old_unbind;
geth->port.func.set_alt = geth_set_alt;
geth->port.func.disable = geth_disable;
status = usb_add_function(c, &geth->port.func);
if (status)
kfree(geth);
return status;
}
#else
static inline struct f_gether_opts *to_f_gether_opts(struct config_item *item)
{
return container_of(to_config_group(item), struct f_gether_opts,
@ -573,5 +517,3 @@ static struct usb_function *geth_alloc(struct usb_function_instance *fi)
DECLARE_USB_FUNCTION_INIT(geth, geth_alloc_inst, geth_alloc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Brownell");
#endif

View File

@ -1157,8 +1157,9 @@ static int fotg210_udc_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&ep->queue);
ep->ep.name = fotg210_ep_name[i];
ep->ep.ops = &fotg210_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
}
fotg210->ep[0]->ep.maxpacket = 0x40;
usb_ep_set_maxpacket_limit(&fotg210->ep[0]->ep, 0x40);
fotg210->gadget.ep0 = &fotg210->ep[0]->ep;
INIT_LIST_HEAD(&fotg210->gadget.ep0->ep_list);

View File

@ -22,7 +22,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/types.h>
#include <linux/errno.h>
@ -2429,7 +2428,7 @@ static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
ep->ep.ops = &qe_ep_ops;
ep->stopped = 1;
ep->ep.maxpacket = (unsigned short) ~0;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
ep->ep.desc = NULL;
ep->dir = 0xff;
ep->epnum = (u8)pipe_num;
@ -2717,7 +2716,7 @@ MODULE_DEVICE_TABLE(of, qe_udc_match);
static struct platform_driver udc_driver = {
.driver = {
.name = (char *)driver_name,
.name = driver_name,
.owner = THIS_MODULE,
.of_match_table = qe_udc_match,
},

View File

@ -2311,7 +2311,7 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
/* for ep0: maxP defined in desc
* for other eps, maxP is set by epautoconfig() called by gadget layer
*/
ep->ep.maxpacket = (unsigned short) ~0;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
/* the queue lists any req for this ep */
INIT_LIST_HEAD(&ep->queue);
@ -2469,7 +2469,8 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
* for other eps, gadget layer called ep_enable with defined desc
*/
udc_controller->eps[0].ep.desc = &fsl_ep0_desc;
udc_controller->eps[0].ep.maxpacket = USB_MAX_CTRL_PAYLOAD;
usb_ep_set_maxpacket_limit(&udc_controller->eps[0].ep,
USB_MAX_CTRL_PAYLOAD);
/* setup the udc->eps[] for non-control endpoints and link
* to gadget.ep_list */
@ -2666,7 +2667,7 @@ static struct platform_driver udc_driver = {
.suspend = fsl_udc_suspend,
.resume = fsl_udc_resume,
.driver = {
.name = (char *)driver_name,
.name = driver_name,
.owner = THIS_MODULE,
/* udc suspend/resume called from OTG driver */
.suspend = fsl_udc_otg_suspend,

View File

@ -1452,9 +1452,9 @@ static int __init fusb300_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&ep->queue);
ep->ep.name = fusb300_ep_name[i];
ep->ep.ops = &fusb300_ep_ops;
ep->ep.maxpacket = HS_BULK_MAX_PACKET_SIZE;
usb_ep_set_maxpacket_limit(&ep->ep, HS_BULK_MAX_PACKET_SIZE);
}
fusb300->ep[0]->ep.maxpacket = HS_CTL_MAX_PACKET_SIZE;
usb_ep_set_maxpacket_limit(&fusb300->ep[0]->ep, HS_CTL_MAX_PACKET_SIZE);
fusb300->ep[0]->epnum = 0;
fusb300->gadget.ep0 = &fusb300->ep[0]->ep;
INIT_LIST_HEAD(&fusb300->gadget.ep0->ep_list);

View File

@ -13,14 +13,10 @@
#define pr_fmt(fmt) "g_ffs: " fmt
#include <linux/module.h>
/*
* kbuild is not very cooperative with respect to linking separately
* compiled library objects into one module. So for now we won't use
* separate compilation ... ensuring init/exit sections work to shrink
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
#include <linux/netdevice.h>
# if defined USB_ETH_RNDIS
# undef USB_ETH_RNDIS
# endif
@ -28,31 +24,31 @@
# define USB_ETH_RNDIS y
# endif
#define USBF_ECM_INCLUDED
# include "f_ecm.c"
#define USB_FSUBSET_INCLUDED
# include "f_subset.c"
# include "u_ecm.h"
# include "u_gether.h"
# ifdef USB_ETH_RNDIS
# define USB_FRNDIS_INCLUDED
# include "f_rndis.c"
# include "u_rndis.h"
# include "rndis.h"
# endif
# include "u_ether.h"
static u8 gfs_host_mac[ETH_ALEN];
static struct eth_dev *the_dev;
USB_ETHERNET_MODULE_PARAMETERS();
# ifdef CONFIG_USB_FUNCTIONFS_ETH
static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct eth_dev *dev);
static int eth_bind_config(struct usb_configuration *c);
static struct usb_function_instance *fi_ecm;
static struct usb_function *f_ecm;
static struct usb_function_instance *fi_geth;
static struct usb_function *f_geth;
# endif
# ifdef CONFIG_USB_FUNCTIONFS_RNDIS
static int bind_rndis_config(struct usb_configuration *c);
static struct usb_function_instance *fi_rndis;
static struct usb_function *f_rndis;
# endif
#else
# define the_dev NULL
# define gether_cleanup(dev) do { } while (0)
# define gfs_host_mac NULL
struct eth_dev;
#endif
#include "f_fs.c"
#include "u_fs.h"
#define DRIVER_NAME "g_ffs"
#define DRIVER_DESC "USB Function Filesystem"
@ -67,19 +63,8 @@ MODULE_LICENSE("GPL");
#define GFS_MAX_DEVS 10
struct gfs_ffs_obj {
const char *name;
bool mounted;
bool desc_ready;
struct ffs_data *ffs_data;
};
USB_GADGET_COMPOSITE_OPTIONS();
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
USB_ETHERNET_MODULE_PARAMETERS();
#endif
static struct usb_device_descriptor gfs_dev_desc = {
.bLength = sizeof gfs_dev_desc,
.bDescriptorType = USB_DT_DEVICE,
@ -146,12 +131,12 @@ static struct usb_gadget_strings *gfs_dev_strings[] = {
struct gfs_configuration {
struct usb_configuration c;
int (*eth)(struct usb_configuration *c, u8 *ethaddr,
struct eth_dev *dev);
int (*eth)(struct usb_configuration *c);
int num;
} gfs_configurations[] = {
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
{
.eth = rndis_bind_config,
.eth = bind_rndis_config,
},
#endif
@ -167,10 +152,15 @@ struct gfs_configuration {
#endif
};
static void *functionfs_acquire_dev(struct ffs_dev *dev);
static void functionfs_release_dev(struct ffs_dev *dev);
static int functionfs_ready_callback(struct ffs_data *ffs);
static void functionfs_closed_callback(struct ffs_data *ffs);
static int gfs_bind(struct usb_composite_dev *cdev);
static int gfs_unbind(struct usb_composite_dev *cdev);
static int gfs_do_config(struct usb_configuration *c);
static __refdata struct usb_composite_driver gfs_driver = {
.name = DRIVER_NAME,
.dev = &gfs_dev_desc,
@ -180,205 +170,243 @@ static __refdata struct usb_composite_driver gfs_driver = {
.unbind = gfs_unbind,
};
static DEFINE_MUTEX(gfs_lock);
static unsigned int missing_funcs;
static bool gfs_ether_setup;
static bool gfs_registered;
static bool gfs_single_func;
static struct gfs_ffs_obj *ffs_tab;
static struct usb_function_instance **fi_ffs;
static struct usb_function **f_ffs[] = {
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
NULL,
#endif
#ifdef CONFIG_USB_FUNCTIONFS_ETH
NULL,
#endif
#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
NULL,
#endif
};
#define N_CONF ARRAY_SIZE(f_ffs)
static int __init gfs_init(void)
{
struct f_fs_opts *opts;
int i;
int ret = 0;
ENTER();
if (!func_num) {
if (func_num < 2) {
gfs_single_func = true;
func_num = 1;
}
ffs_tab = kcalloc(func_num, sizeof *ffs_tab, GFP_KERNEL);
if (!ffs_tab)
return -ENOMEM;
/*
* Allocate in one chunk for easier maintenance
*/
f_ffs[0] = kcalloc(func_num * N_CONF, sizeof(*f_ffs), GFP_KERNEL);
if (!f_ffs[0]) {
ret = -ENOMEM;
goto no_func;
}
for (i = 1; i < N_CONF; ++i)
f_ffs[i] = f_ffs[0] + i * func_num;
if (!gfs_single_func)
for (i = 0; i < func_num; i++)
ffs_tab[i].name = func_names[i];
fi_ffs = kcalloc(func_num, sizeof(*fi_ffs), GFP_KERNEL);
if (!fi_ffs) {
ret = -ENOMEM;
goto no_func;
}
for (i = 0; i < func_num; i++) {
fi_ffs[i] = usb_get_function_instance("ffs");
if (IS_ERR(fi_ffs[i])) {
ret = PTR_ERR(fi_ffs[i]);
--i;
goto no_dev;
}
opts = to_f_fs_opts(fi_ffs[i]);
if (gfs_single_func)
ret = ffs_single_dev(opts->dev);
else
ret = ffs_name_dev(opts->dev, func_names[i]);
if (ret)
goto no_dev;
opts->dev->ffs_ready_callback = functionfs_ready_callback;
opts->dev->ffs_closed_callback = functionfs_closed_callback;
opts->dev->ffs_acquire_dev_callback = functionfs_acquire_dev;
opts->dev->ffs_release_dev_callback = functionfs_release_dev;
opts->no_configfs = true;
}
missing_funcs = func_num;
return functionfs_init();
return 0;
no_dev:
while (i >= 0)
usb_put_function_instance(fi_ffs[i--]);
kfree(fi_ffs);
no_func:
kfree(f_ffs[0]);
return ret;
}
module_init(gfs_init);
static void __exit gfs_exit(void)
{
int i;
ENTER();
mutex_lock(&gfs_lock);
if (gfs_registered)
usb_composite_unregister(&gfs_driver);
gfs_registered = false;
functionfs_cleanup();
kfree(f_ffs[0]);
mutex_unlock(&gfs_lock);
kfree(ffs_tab);
for (i = 0; i < func_num; i++)
usb_put_function_instance(fi_ffs[i]);
kfree(fi_ffs);
}
module_exit(gfs_exit);
static struct gfs_ffs_obj *gfs_find_dev(const char *dev_name)
static void *functionfs_acquire_dev(struct ffs_dev *dev)
{
int i;
ENTER();
if (gfs_single_func)
return &ffs_tab[0];
for (i = 0; i < func_num; i++)
if (strcmp(ffs_tab[i].name, dev_name) == 0)
return &ffs_tab[i];
return NULL;
if (!try_module_get(THIS_MODULE))
return ERR_PTR(-ENODEV);
return 0;
}
static void functionfs_release_dev(struct ffs_dev *dev)
{
module_put(THIS_MODULE);
}
/*
* The caller of this function takes ffs_lock
*/
static int functionfs_ready_callback(struct ffs_data *ffs)
{
struct gfs_ffs_obj *ffs_obj;
int ret;
int ret = 0;
ENTER();
mutex_lock(&gfs_lock);
if (--missing_funcs)
return 0;
ffs_obj = ffs->private_data;
if (!ffs_obj) {
ret = -EINVAL;
goto done;
}
if (gfs_registered)
return -EBUSY;
if (WARN_ON(ffs_obj->desc_ready)) {
ret = -EBUSY;
goto done;
}
ffs_obj->desc_ready = true;
ffs_obj->ffs_data = ffs;
if (--missing_funcs) {
ret = 0;
goto done;
}
if (gfs_registered) {
ret = -EBUSY;
goto done;
}
gfs_registered = true;
ret = usb_composite_probe(&gfs_driver);
if (unlikely(ret < 0))
gfs_registered = false;
done:
mutex_unlock(&gfs_lock);
return ret;
}
/*
* The caller of this function takes ffs_lock
*/
static void functionfs_closed_callback(struct ffs_data *ffs)
{
struct gfs_ffs_obj *ffs_obj;
ENTER();
mutex_lock(&gfs_lock);
ffs_obj = ffs->private_data;
if (!ffs_obj)
goto done;
ffs_obj->desc_ready = false;
missing_funcs++;
if (gfs_registered)
usb_composite_unregister(&gfs_driver);
gfs_registered = false;
done:
mutex_unlock(&gfs_lock);
}
static void *functionfs_acquire_dev_callback(const char *dev_name)
{
struct gfs_ffs_obj *ffs_dev;
ENTER();
mutex_lock(&gfs_lock);
ffs_dev = gfs_find_dev(dev_name);
if (!ffs_dev) {
ffs_dev = ERR_PTR(-ENODEV);
goto done;
}
if (ffs_dev->mounted) {
ffs_dev = ERR_PTR(-EBUSY);
goto done;
}
ffs_dev->mounted = true;
done:
mutex_unlock(&gfs_lock);
return ffs_dev;
}
static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
{
struct gfs_ffs_obj *ffs_dev;
ENTER();
mutex_lock(&gfs_lock);
ffs_dev = ffs_data->private_data;
if (ffs_dev)
ffs_dev->mounted = false;
mutex_unlock(&gfs_lock);
}
/*
* It is assumed that gfs_bind is called from a context where gfs_lock is held
* It is assumed that gfs_bind is called from a context where ffs_lock is held
*/
static int gfs_bind(struct usb_composite_dev *cdev)
{
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
struct net_device *net;
#endif
int ret, i;
ENTER();
if (missing_funcs)
return -ENODEV;
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
the_dev = gether_setup(cdev->gadget, dev_addr, host_addr, gfs_host_mac,
qmult);
#endif
if (IS_ERR(the_dev)) {
ret = PTR_ERR(the_dev);
goto error_quick;
#if defined CONFIG_USB_FUNCTIONFS_ETH
if (can_support_ecm(cdev->gadget)) {
struct f_ecm_opts *ecm_opts;
fi_ecm = usb_get_function_instance("ecm");
if (IS_ERR(fi_ecm))
return PTR_ERR(fi_ecm);
ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
net = ecm_opts->net;
} else {
struct f_gether_opts *geth_opts;
fi_geth = usb_get_function_instance("geth");
if (IS_ERR(fi_geth))
return PTR_ERR(fi_geth);
geth_opts = container_of(fi_geth, struct f_gether_opts,
func_inst);
net = geth_opts->net;
}
gfs_ether_setup = true;
#endif
ret = usb_string_ids_tab(cdev, gfs_strings);
if (unlikely(ret < 0))
goto error;
gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
{
struct f_rndis_opts *rndis_opts;
for (i = func_num; i--; ) {
ret = functionfs_bind(ffs_tab[i].ffs_data, cdev);
if (unlikely(ret < 0)) {
while (++i < func_num)
functionfs_unbind(ffs_tab[i].ffs_data);
fi_rndis = usb_get_function_instance("rndis");
if (IS_ERR(fi_rndis)) {
ret = PTR_ERR(fi_rndis);
goto error;
}
rndis_opts = container_of(fi_rndis, struct f_rndis_opts,
func_inst);
#ifndef CONFIG_USB_FUNCTIONFS_ETH
net = rndis_opts->net;
#endif
}
#endif
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
gether_set_qmult(net, qmult);
if (!gether_set_host_addr(net, host_addr))
pr_info("using host ethernet address: %s", host_addr);
if (!gether_set_dev_addr(net, dev_addr))
pr_info("using self ethernet address: %s", dev_addr);
#endif
#if defined CONFIG_USB_FUNCTIONFS_RNDIS && defined CONFIG_USB_FUNCTIONFS_ETH
gether_set_gadget(net, cdev->gadget);
ret = gether_register_netdev(net);
if (ret)
goto error_rndis;
if (can_support_ecm(cdev->gadget)) {
struct f_ecm_opts *ecm_opts;
ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
ecm_opts->bound = true;
} else {
struct f_gether_opts *geth_opts;
geth_opts = container_of(fi_geth, struct f_gether_opts,
func_inst);
geth_opts->bound = true;
}
rndis_borrow_net(fi_rndis, net);
#endif
/* TODO: gstrings_attach? */
ret = usb_string_ids_tab(cdev, gfs_strings);
if (unlikely(ret < 0))
goto error_rndis;
gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
struct gfs_configuration *c = gfs_configurations + i;
@ -389,6 +417,8 @@ static int gfs_bind(struct usb_composite_dev *cdev)
c->c.bConfigurationValue = 1 + i;
c->c.bmAttributes = USB_CONFIG_ATT_SELFPOWER;
c->num = i;
ret = usb_add_config(cdev, &c->c, gfs_do_config);
if (unlikely(ret < 0))
goto error_unbind;
@ -396,18 +426,24 @@ static int gfs_bind(struct usb_composite_dev *cdev)
usb_composite_overwrite_options(cdev, &coverwrite);
return 0;
/* TODO */
error_unbind:
for (i = 0; i < func_num; i++)
functionfs_unbind(ffs_tab[i].ffs_data);
error_rndis:
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
usb_put_function_instance(fi_rndis);
error:
gether_cleanup(the_dev);
error_quick:
gfs_ether_setup = false;
#endif
#if defined CONFIG_USB_FUNCTIONFS_ETH
if (can_support_ecm(cdev->gadget))
usb_put_function_instance(fi_ecm);
else
usb_put_function_instance(fi_geth);
#endif
return ret;
}
/*
* It is assumed that gfs_unbind is called from a context where gfs_lock is held
* It is assumed that gfs_unbind is called from a context where ffs_lock is held
*/
static int gfs_unbind(struct usb_composite_dev *cdev)
{
@ -415,28 +451,30 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
ENTER();
/*
* We may have been called in an error recovery from
* composite_bind() after gfs_unbind() failure so we need to
* check if gfs_ffs_data is not NULL since gfs_bind() handles
* all error recovery itself. I'd rather we werent called
* from composite on orror recovery, but what you're gonna
* do...?
*/
if (gfs_ether_setup)
gether_cleanup(the_dev);
gfs_ether_setup = false;
for (i = func_num; i--; )
if (ffs_tab[i].ffs_data)
functionfs_unbind(ffs_tab[i].ffs_data);
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
usb_put_function(f_rndis);
usb_put_function_instance(fi_rndis);
#endif
#if defined CONFIG_USB_FUNCTIONFS_ETH
if (can_support_ecm(cdev->gadget)) {
usb_put_function(f_ecm);
usb_put_function_instance(fi_ecm);
} else {
usb_put_function(f_geth);
usb_put_function_instance(fi_geth);
}
#endif
for (i = 0; i < N_CONF * func_num; ++i)
usb_put_function(*(f_ffs[0] + i));
return 0;
}
/*
* It is assumed that gfs_do_config is called from a context where
* gfs_lock is held
* ffs_lock is held
*/
static int gfs_do_config(struct usb_configuration *c)
{
@ -454,15 +492,22 @@ static int gfs_do_config(struct usb_configuration *c)
}
if (gc->eth) {
ret = gc->eth(c, gfs_host_mac, the_dev);
ret = gc->eth(c);
if (unlikely(ret < 0))
return ret;
}
for (i = 0; i < func_num; i++) {
ret = functionfs_bind_config(c->cdev, c, ffs_tab[i].ffs_data);
if (unlikely(ret < 0))
return ret;
f_ffs[gc->num][i] = usb_get_function(fi_ffs[i]);
if (IS_ERR(f_ffs[gc->num][i])) {
ret = PTR_ERR(f_ffs[gc->num][i]);
goto error;
}
ret = usb_add_function(c, f_ffs[gc->num][i]);
if (ret < 0) {
usb_put_function(f_ffs[gc->num][i]);
goto error;
}
}
/*
@ -479,16 +524,59 @@ static int gfs_do_config(struct usb_configuration *c)
c->interface[c->next_interface_id] = NULL;
return 0;
error:
while (--i >= 0) {
if (!IS_ERR(f_ffs[gc->num][i]))
usb_remove_function(c, f_ffs[gc->num][i]);
usb_put_function(f_ffs[gc->num][i]);
}
return ret;
}
#ifdef CONFIG_USB_FUNCTIONFS_ETH
static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct eth_dev *dev)
static int eth_bind_config(struct usb_configuration *c)
{
return can_support_ecm(c->cdev->gadget)
? ecm_bind_config(c, ethaddr, dev)
: geth_bind_config(c, ethaddr, dev);
int status = 0;
if (can_support_ecm(c->cdev->gadget)) {
f_ecm = usb_get_function(fi_ecm);
if (IS_ERR(f_ecm))
return PTR_ERR(f_ecm);
status = usb_add_function(c, f_ecm);
if (status < 0)
usb_put_function(f_ecm);
} else {
f_geth = usb_get_function(fi_geth);
if (IS_ERR(f_geth))
return PTR_ERR(f_geth);
status = usb_add_function(c, f_geth);
if (status < 0)
usb_put_function(f_geth);
}
return status;
}
#endif
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
static int bind_rndis_config(struct usb_configuration *c)
{
int status = 0;
f_rndis = usb_get_function(fi_rndis);
if (IS_ERR(f_rndis))
return PTR_ERR(f_rndis);
status = usb_add_function(c, f_rndis);
if (status < 0)
usb_put_function(f_rndis);
return status;
}
#endif

View File

@ -6,6 +6,11 @@
#ifndef __G_ZERO_H
#define __G_ZERO_H
#define GZERO_BULK_BUFLEN 4096
#define GZERO_QLEN 32
#define GZERO_ISOC_INTERVAL 4
#define GZERO_ISOC_MAXPACKET 1024
struct usb_zero_options {
unsigned pattern;
unsigned isoc_interval;
@ -24,19 +29,36 @@ struct f_ss_opts {
unsigned isoc_mult;
unsigned isoc_maxburst;
unsigned bulk_buflen;
/*
* Read/write access to configfs attributes is handled by configfs.
*
* This is to protect the data from concurrent access by read/write
* and create symlink/remove symlink.
*/
struct mutex lock;
int refcnt;
};
struct f_lb_opts {
struct usb_function_instance func_inst;
unsigned bulk_buflen;
unsigned qlen;
/*
* Read/write access to configfs attributes is handled by configfs.
*
* This is to protect the data from concurrent access by read/write
* and create symlink/remove symlink.
*/
struct mutex lock;
int refcnt;
};
void lb_modexit(void);
int lb_modinit(void);
/* common utilities */
struct usb_request *alloc_ep_req(struct usb_ep *ep, int len);
void free_ep_req(struct usb_ep *ep, struct usb_request *req);
void disable_endpoints(struct usb_composite_dev *cdev,
struct usb_ep *in, struct usb_ep *out,

View File

@ -30,7 +30,6 @@
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
@ -231,7 +230,7 @@ static void ep_reset(struct goku_udc_regs __iomem *regs, struct goku_ep *ep)
}
}
ep->ep.maxpacket = MAX_FIFO_SIZE;
usb_ep_set_maxpacket_limit(&ep->ep, MAX_FIFO_SIZE);
ep->ep.desc = NULL;
ep->stopped = 1;
ep->irqs = 0;
@ -1251,7 +1250,7 @@ static void udc_reinit (struct goku_udc *dev)
}
dev->ep[0].reg_mode = NULL;
dev->ep[0].ep.maxpacket = MAX_EP0_SIZE;
usb_ep_set_maxpacket_limit(&dev->ep[0].ep, MAX_EP0_SIZE);
list_del_init (&dev->ep[0].ep.ep_list);
}
@ -1350,16 +1349,12 @@ static int goku_udc_start(struct usb_gadget *g,
return 0;
}
static void
stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
static void stop_activity(struct goku_udc *dev)
{
unsigned i;
DBG (dev, "%s\n", __func__);
if (dev->gadget.speed == USB_SPEED_UNKNOWN)
driver = NULL;
/* disconnect gadget driver after quiesceing hw and the driver */
udc_reset (dev);
for (i = 0; i < 4; i++)
@ -1377,7 +1372,7 @@ static int goku_udc_stop(struct usb_gadget *g,
spin_lock_irqsave(&dev->lock, flags);
dev->driver = NULL;
stop_activity(dev, driver);
stop_activity(dev);
spin_unlock_irqrestore(&dev->lock, flags);
return 0;
@ -1521,7 +1516,7 @@ static irqreturn_t goku_irq(int irq, void *_dev)
if (unlikely(stat & INT_DEVWIDE)) {
if (stat & INT_SYSERROR) {
ERROR(dev, "system error\n");
stop_activity(dev, dev->driver);
stop_activity(dev);
stat = 0;
handled = 1;
// FIXME have a neater way to prevent re-enumeration
@ -1536,7 +1531,7 @@ static irqreturn_t goku_irq(int irq, void *_dev)
} else {
DBG(dev, "disconnect\n");
if (dev->gadget.speed == USB_SPEED_FULL)
stop_activity(dev, dev->driver);
stop_activity(dev);
dev->ep0state = EP0_DISCONNECT;
dev->int_enable = INT_DEVWIDE;
writel(dev->int_enable, &dev->regs->int_enable);

2238
drivers/usb/gadget/gr_udc.c Normal file

File diff suppressed because it is too large Load Diff

220
drivers/usb/gadget/gr_udc.h Normal file
View File

@ -0,0 +1,220 @@
/*
* USB Peripheral Controller driver for Aeroflex Gaisler GRUSBDC.
*
* 2013 (c) Aeroflex Gaisler AB
*
* This driver supports GRUSBDC USB Device Controller cores available in the
* GRLIB VHDL IP core library.
*
* Full documentation of the GRUSBDC core can be found here:
* http://www.gaisler.com/products/grlib/grip.pdf
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* Contributors:
* - Andreas Larsson <andreas@gaisler.com>
* - Marko Isomaki
*/
/* Control registers on the AMBA bus */
#define GR_MAXEP 16 /* Max # endpoints for *each* direction */
struct gr_epregs {
u32 epctrl;
union {
struct { /* Slave mode*/
u32 slvctrl;
u32 slvdata;
};
struct { /* DMA mode*/
u32 dmactrl;
u32 dmaaddr;
};
};
u32 epstat;
};
struct gr_regs {
struct gr_epregs epo[GR_MAXEP]; /* 0x000 - 0x0fc */
struct gr_epregs epi[GR_MAXEP]; /* 0x100 - 0x1fc */
u32 control; /* 0x200 */
u32 status; /* 0x204 */
};
#define GR_EPCTRL_BUFSZ_SCALER 8
#define GR_EPCTRL_BUFSZ_MASK 0xffe00000
#define GR_EPCTRL_BUFSZ_POS 21
#define GR_EPCTRL_PI BIT(20)
#define GR_EPCTRL_CB BIT(19)
#define GR_EPCTRL_CS BIT(18)
#define GR_EPCTRL_MAXPL_MASK 0x0003ff80
#define GR_EPCTRL_MAXPL_POS 7
#define GR_EPCTRL_NT_MASK 0x00000060
#define GR_EPCTRL_NT_POS 5
#define GR_EPCTRL_TT_MASK 0x00000018
#define GR_EPCTRL_TT_POS 3
#define GR_EPCTRL_EH BIT(2)
#define GR_EPCTRL_ED BIT(1)
#define GR_EPCTRL_EV BIT(0)
#define GR_DMACTRL_AE BIT(10)
#define GR_DMACTRL_AD BIT(3)
#define GR_DMACTRL_AI BIT(2)
#define GR_DMACTRL_IE BIT(1)
#define GR_DMACTRL_DA BIT(0)
#define GR_EPSTAT_PT BIT(29)
#define GR_EPSTAT_PR BIT(29)
#define GR_EPSTAT_B1CNT_MASK 0x1fff0000
#define GR_EPSTAT_B1CNT_POS 16
#define GR_EPSTAT_B0CNT_MASK 0x0000fff8
#define GR_EPSTAT_B0CNT_POS 3
#define GR_EPSTAT_B1 BIT(2)
#define GR_EPSTAT_B0 BIT(1)
#define GR_EPSTAT_BS BIT(0)
#define GR_CONTROL_SI BIT(31)
#define GR_CONTROL_UI BIT(30)
#define GR_CONTROL_VI BIT(29)
#define GR_CONTROL_SP BIT(28)
#define GR_CONTROL_FI BIT(27)
#define GR_CONTROL_EP BIT(14)
#define GR_CONTROL_DH BIT(13)
#define GR_CONTROL_RW BIT(12)
#define GR_CONTROL_TS_MASK 0x00000e00
#define GR_CONTROL_TS_POS 9
#define GR_CONTROL_TM BIT(8)
#define GR_CONTROL_UA_MASK 0x000000fe
#define GR_CONTROL_UA_POS 1
#define GR_CONTROL_SU BIT(0)
#define GR_STATUS_NEPI_MASK 0xf0000000
#define GR_STATUS_NEPI_POS 28
#define GR_STATUS_NEPO_MASK 0x0f000000
#define GR_STATUS_NEPO_POS 24
#define GR_STATUS_DM BIT(23)
#define GR_STATUS_SU BIT(17)
#define GR_STATUS_UR BIT(16)
#define GR_STATUS_VB BIT(15)
#define GR_STATUS_SP BIT(14)
#define GR_STATUS_AF_MASK 0x00003800
#define GR_STATUS_AF_POS 11
#define GR_STATUS_FN_MASK 0x000007ff
#define GR_STATUS_FN_POS 0
#define MAX_CTRL_PL_SIZE 64 /* As per USB standard for full and high speed */
/*-------------------------------------------------------------------------*/
/* Driver data structures and utilities */
struct gr_dma_desc {
u32 ctrl;
u32 data;
u32 next;
/* These must be last because hw uses the previous three */
u32 paddr;
struct gr_dma_desc *next_desc;
};
#define GR_DESC_OUT_CTRL_SE BIT(17)
#define GR_DESC_OUT_CTRL_IE BIT(15)
#define GR_DESC_OUT_CTRL_NX BIT(14)
#define GR_DESC_OUT_CTRL_EN BIT(13)
#define GR_DESC_OUT_CTRL_LEN_MASK 0x00001fff
#define GR_DESC_IN_CTRL_MO BIT(18)
#define GR_DESC_IN_CTRL_PI BIT(17)
#define GR_DESC_IN_CTRL_ML BIT(16)
#define GR_DESC_IN_CTRL_IE BIT(15)
#define GR_DESC_IN_CTRL_NX BIT(14)
#define GR_DESC_IN_CTRL_EN BIT(13)
#define GR_DESC_IN_CTRL_LEN_MASK 0x00001fff
#define GR_DESC_DMAADDR_MASK 0xfffffffc
struct gr_ep {
struct usb_ep ep;
struct gr_udc *dev;
u16 bytes_per_buffer;
unsigned int dma_start;
struct gr_epregs __iomem *regs;
unsigned num:8;
unsigned is_in:1;
unsigned stopped:1;
unsigned wedged:1;
unsigned callback:1;
/* analogous to a host-side qh */
struct list_head queue;
struct list_head ep_list;
};
struct gr_request {
struct usb_request req;
struct list_head queue;
/* Chain of dma descriptors */
struct gr_dma_desc *first_desc; /* First in the chain */
struct gr_dma_desc *curr_desc; /* Current descriptor */
struct gr_dma_desc *last_desc; /* Last in the chain */
u8 setup; /* Setup packet */
};
enum gr_ep0state {
GR_EP0_DISCONNECT = 0, /* No host */
GR_EP0_SETUP, /* Between STATUS ack and SETUP report */
GR_EP0_IDATA, /* IN data stage */
GR_EP0_ODATA, /* OUT data stage */
GR_EP0_ISTATUS, /* Status stage after IN data stage */
GR_EP0_OSTATUS, /* Status stage after OUT data stage */
GR_EP0_STALL, /* Data or status stages */
GR_EP0_SUSPEND, /* USB suspend */
};
struct gr_udc {
struct usb_gadget gadget;
struct gr_ep epi[GR_MAXEP];
struct gr_ep epo[GR_MAXEP];
struct usb_gadget_driver *driver;
struct dma_pool *desc_pool;
struct device *dev;
enum gr_ep0state ep0state;
struct gr_request *ep0reqo;
struct gr_request *ep0reqi;
struct gr_regs __iomem *regs;
int irq;
int irqi;
int irqo;
unsigned added:1;
unsigned irq_enabled:1;
unsigned remote_wakeup:1;
u8 test_mode;
enum usb_device_state suspended_from;
unsigned int nepi;
unsigned int nepo;
struct list_head ep_list;
spinlock_t lock; /* General lock, a.k.a. "dev->lock" in comments */
struct dentry *dfs_root;
struct dentry *dfs_state;
};
#define to_gr_udc(gadget) (container_of((gadget), struct gr_udc, gadget))

View File

@ -1449,7 +1449,7 @@ static void udc_reinit(struct lpc32xx_udc *udc)
if (i != 0)
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
ep->ep.maxpacket = ep->maxpacket;
usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
INIT_LIST_HEAD(&ep->queue);
ep->req_pending = 0;
}

View File

@ -1647,9 +1647,9 @@ static int __init m66592_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&ep->queue);
ep->ep.name = m66592_ep_name[i];
ep->ep.ops = &m66592_ep_ops;
ep->ep.maxpacket = 512;
usb_ep_set_maxpacket_limit(&ep->ep, 512);
}
m66592->ep[0].ep.maxpacket = 64;
usb_ep_set_maxpacket_limit(&m66592->ep[0].ep, 64);
m66592->ep[0].pipenum = 0;
m66592->ep[0].fifoaddr = M66592_CFIFO;
m66592->ep[0].fifosel = M66592_CFIFOSEL;

View File

@ -134,7 +134,7 @@ static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
*/
#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
#endif /* CONFIG_USB_DEBUG */
#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);

View File

@ -15,7 +15,6 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/notifier.h>
@ -1336,7 +1335,7 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d)
ep->ep.name = ep->name;
ep->ep.ops = &mv_u3d_ep_ops;
ep->wedge = 0;
ep->ep.maxpacket = MV_U3D_EP0_MAX_PKT_SIZE;
usb_ep_set_maxpacket_limit(&ep->ep, MV_U3D_EP0_MAX_PKT_SIZE);
ep->ep_num = 0;
ep->ep.desc = &mv_u3d_ep0_desc;
INIT_LIST_HEAD(&ep->queue);
@ -1361,7 +1360,7 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d)
ep->ep.name = ep->name;
ep->ep.ops = &mv_u3d_ep_ops;
ep->ep.maxpacket = (unsigned short) ~0;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
ep->ep_num = i / 2;
INIT_LIST_HEAD(&ep->queue);

View File

@ -20,7 +20,6 @@
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
@ -1261,7 +1260,7 @@ static int eps_init(struct mv_udc *udc)
ep->ep.ops = &mv_ep_ops;
ep->wedge = 0;
ep->stopped = 0;
ep->ep.maxpacket = EP0_MAX_PKT_SIZE;
usb_ep_set_maxpacket_limit(&ep->ep, EP0_MAX_PKT_SIZE);
ep->ep_num = 0;
ep->ep.desc = &mv_ep0_desc;
INIT_LIST_HEAD(&ep->queue);
@ -1284,7 +1283,7 @@ static int eps_init(struct mv_udc *udc)
ep->ep.ops = &mv_ep_ops;
ep->stopped = 0;
ep->ep.maxpacket = (unsigned short) ~0;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
ep->ep_num = i / 2;
INIT_LIST_HEAD(&ep->queue);

Some files were not shown because too many files have changed in this diff Show More