提交 73ad0adc 编写于 作者: G Greg Kroah-Hartman

Merge tag 'usb-for-v3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

Felipe writes:

usb: changes for v3.14 merge window

This pull request is quite extensive, containing
105 non-merge commits. Because of that, we describe
the changes in sections below:

New drivers:
	- Keystone PHY driver and DWC3 Glue Layer
	- Aeroflex Gaisler GRUSBDC
	- Tahvo PHY driver for N770
	- JZ4740 MUSB gluer Layer
	- Broadcom PHY Driver

Important new features:
	- MUSB DSPS learned about suspend/resume
	- New quirk_ep_out_aligned_size flag added to struct usb_gadget
	- DWC3 initializes the new quirk flag so gadget drivers can use it.
	- AM335x PHY Driver learns about remote wakeup
	- Renesas USBHS now requests DMA Engine only once
	- s3c-hsotg is now re-used on Broadcom devices
	- USB PHY layer now makes sure to initialize the notifier for all
		drivers
	- omap-control learned about TI's new AM437x devices
	- few other usb gadget/function drivers learned about the new
		configfs-based binding.

Misc Fixes and Clean Ups:
	- Several sparse fixes all over the place
	- Removal of redundant of_match_ptr()
	- r-car gen2 phy now uses usb_add_phy_dev()
	- removal of DEFINE_PCI_DEVICE_TABLE() from a few drivers
	- conversion to clk_prepare/clk_unprepare on r8a66597-udc
	- some randconfig errors and build warnings were fixed
	- removal of unnecessary lock on dwc3-omap.c
Signed-of-by: NFelipe Balbi <balbi@ti.com>
无相关合并请求
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.
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
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
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".
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>;
};
......@@ -5,6 +5,14 @@ Required properties:
- compatible : "snps,dwc2"
- 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:
......@@ -12,4 +20,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";
};
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
......@@ -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.
......
......@@ -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);
......
......@@ -51,4 +51,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
......@@ -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_OMAP_USB2) += phy-omap-usb2.o
......
/*
* 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");
......@@ -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/chipidea/Kconfig"
......
......@@ -1566,7 +1566,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 +1586,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;
}
......
......@@ -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
......
......@@ -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
......@@ -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)
......
/**
* 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");
......@@ -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;
}
......
......@@ -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)
......
......@@ -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.
......
......@@ -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
......
......@@ -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
......
......@@ -446,7 +446,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 +1564,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);
}
/*
......
......@@ -834,7 +834,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 +1759,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));
......
......@@ -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;
}
......
......@@ -549,7 +549,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 +943,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);
......
......@@ -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?
......
......@@ -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);
......
......@@ -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;
......
......@@ -58,7 +58,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 +129,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 +145,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 +178,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)
......
......@@ -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
此差异已折叠。
......@@ -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)
......
......@@ -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);
......
......@@ -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");
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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
......@@ -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;
......
......@@ -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,
......
......@@ -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
......@@ -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);
......
......@@ -2429,7 +2429,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;
......
......@@ -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 */
......
......@@ -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);
......
......@@ -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,206 +170,244 @@ 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]);
for (i = 0; i < func_num; i++)
usb_put_function_instance(fi_ffs[i]);
mutex_unlock(&gfs_lock);
kfree(ffs_tab);
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];
if (!try_module_get(THIS_MODULE))
return ERR_PTR(-ENODEV);
return 0;
}
return NULL;
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;
ENTER();
mutex_lock(&gfs_lock);
int ret = 0;
ffs_obj = ffs->private_data;
if (!ffs_obj) {
ret = -EINVAL;
goto done;
}
if (--missing_funcs)
return 0;
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)
return -EBUSY;
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)
/*
* 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)
{
struct gfs_ffs_obj *ffs_dev;
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
struct net_device *net;
#endif
int ret, i;
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;
if (missing_funcs)
return -ENODEV;
#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;
}
ffs_dev->mounted = true;
#endif
done:
mutex_unlock(&gfs_lock);
return ffs_dev;
}
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
{
struct f_rndis_opts *rndis_opts;
static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
{
struct gfs_ffs_obj *ffs_dev;
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
ENTER();
mutex_lock(&gfs_lock);
#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
ffs_dev = ffs_data->private_data;
if (ffs_dev)
ffs_dev->mounted = false;
#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;
mutex_unlock(&gfs_lock);
}
if (can_support_ecm(cdev->gadget)) {
struct f_ecm_opts *ecm_opts;
/*
* It is assumed that gfs_bind is called from a context where gfs_lock is held
*/
static int gfs_bind(struct usb_composite_dev *cdev)
{
int ret, i;
ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
ecm_opts->bound = true;
} else {
struct f_gether_opts *geth_opts;
ENTER();
geth_opts = container_of(fi_geth, struct f_gether_opts,
func_inst);
geth_opts->bound = true;
}
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);
rndis_borrow_net(fi_rndis, net);
#endif
if (IS_ERR(the_dev)) {
ret = PTR_ERR(the_dev);
goto error_quick;
}
gfs_ether_setup = true;
/* TODO: gstrings_attach? */
ret = usb_string_ids_tab(cdev, gfs_strings);
if (unlikely(ret < 0))
goto error;
goto error_rndis;
gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
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);
goto error;
}
}
for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
struct gfs_configuration *c = gfs_configurations + i;
int sid = USB_GADGET_FIRST_AVAIL_IDX + 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)
{
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)
{
return can_support_ecm(c->cdev->gadget)
? ecm_bind_config(c, ethaddr, dev)
: geth_bind_config(c, ethaddr, dev);
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
......@@ -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,
......
......@@ -231,7 +231,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 +1251,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 +1350,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 +1373,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 +1517,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 +1532,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);
......
此差异已折叠。
/*
* 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))
......@@ -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;
}
......
......@@ -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;
......
......@@ -1336,7 +1336,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 +1361,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);
......
......@@ -1261,7 +1261,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 +1284,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);
......
......@@ -266,7 +266,7 @@ static void net2272_ep_reset(struct net2272_ep *ep)
ep->desc = NULL;
INIT_LIST_HEAD(&ep->queue);
ep->ep.maxpacket = ~0;
usb_ep_set_maxpacket_limit(&ep->ep, ~0);
ep->ep.ops = &net2272_ep_ops;
/* disable irqs, endpoint */
......@@ -1409,7 +1409,7 @@ net2272_usb_reinit(struct net2272 *dev)
ep->fifo_size = 64;
net2272_ep_reset(ep);
}
dev->ep[0].ep.maxpacket = 64;
usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 64);
dev->gadget.ep0 = &dev->ep[0].ep;
dev->ep[0].stopped = 0;
......
......@@ -293,7 +293,7 @@ static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
ep->desc = NULL;
INIT_LIST_HEAD (&ep->queue);
ep->ep.maxpacket = ~0;
usb_ep_set_maxpacket_limit(&ep->ep, ~0);
ep->ep.ops = &net2280_ep_ops;
/* disable the dma, irqs, endpoint... */
......@@ -1805,9 +1805,9 @@ static void usb_reinit (struct net2280 *dev)
ep->regs = &dev->epregs [tmp];
ep_reset (dev->regs, ep);
}
dev->ep [0].ep.maxpacket = 64;
dev->ep [5].ep.maxpacket = 64;
dev->ep [6].ep.maxpacket = 64;
usb_ep_set_maxpacket_limit(&dev->ep [0].ep, 64);
usb_ep_set_maxpacket_limit(&dev->ep [5].ep, 64);
usb_ep_set_maxpacket_limit(&dev->ep [6].ep, 64);
dev->gadget.ep0 = &dev->ep [0].ep;
dev->ep [0].stopped = 0;
......
......@@ -126,9 +126,9 @@ static int __init nokia_bind_config(struct usb_configuration *c)
struct usb_function *f_ecm;
struct usb_function *f_obex2 = NULL;
int status = 0;
int obex1_stat = 0;
int obex2_stat = 0;
int phonet_stat = 0;
int obex1_stat = -1;
int obex2_stat = -1;
int phonet_stat = -1;
if (!IS_ERR(fi_phonet)) {
f_phonet = usb_get_function(fi_phonet);
......
......@@ -2586,7 +2586,8 @@ omap_ep_setup(char *name, u8 addr, u8 type,
ep->ep.name = ep->name;
ep->ep.ops = &omap_ep_ops;
ep->ep.maxpacket = ep->maxpacket = maxp;
ep->maxpacket = maxp;
usb_ep_set_maxpacket_limit(&ep->ep, ep->maxpacket);
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
return buf;
......
......@@ -2896,12 +2896,12 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev)
ep->offset_addr = (UDC_EPINT_OUT_SHIFT + ep->num) *
UDC_EP_REG_SHIFT;
/* need to set ep->ep.maxpacket and set Default Configuration?*/
ep->ep.maxpacket = UDC_BULK_MAX_PKT_SIZE;
usb_ep_set_maxpacket_limit(&ep->ep, UDC_BULK_MAX_PKT_SIZE);
list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
INIT_LIST_HEAD(&ep->queue);
}
dev->ep[UDC_EP0IN_IDX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE;
dev->ep[UDC_EP0OUT_IDX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE;
usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0IN_IDX].ep, UDC_EP0IN_MAX_PKT_SIZE);
usb_ep_set_maxpacket_limit(&dev->ep[UDC_EP0OUT_IDX].ep, UDC_EP0OUT_MAX_PKT_SIZE);
/* remove ep0 in and out from the list. They have own pointer */
list_del_init(&dev->ep[UDC_EP0IN_IDX].ep.ep_list);
......
......@@ -1194,6 +1194,7 @@ static void udc_reinit(struct pxa25x_udc *dev)
ep->stopped = 0;
INIT_LIST_HEAD (&ep->queue);
ep->pio_irqs = 0;
usb_ep_set_maxpacket_limit(&ep->ep, ep->ep.maxpacket);
}
/* the rest was statically initialized, and is read-only */
......
......@@ -1737,9 +1737,12 @@ static void udc_init_data(struct pxa_udc *dev)
}
/* USB endpoints init */
for (i = 1; i < NR_USB_ENDPOINTS; i++)
for (i = 1; i < NR_USB_ENDPOINTS; i++) {
list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list,
&dev->gadget.ep_list);
usb_ep_set_maxpacket_limit(&dev->udc_usb_ep[i].usb_ep,
dev->udc_usb_ep[i].usb_ep.maxpacket);
}
}
/**
......
......@@ -1833,7 +1833,7 @@ static int __exit r8a66597_remove(struct platform_device *pdev)
r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
if (r8a66597->pdata->on_chip) {
clk_disable(r8a66597->clk);
clk_disable_unprepare(r8a66597->clk);
clk_put(r8a66597->clk);
}
......@@ -1931,7 +1931,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
ret = PTR_ERR(r8a66597->clk);
goto clean_up;
}
clk_enable(r8a66597->clk);
clk_prepare_enable(r8a66597->clk);
}
if (r8a66597->pdata->sudmac) {
......@@ -1964,9 +1964,9 @@ static int __init r8a66597_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&ep->queue);
ep->ep.name = r8a66597_ep_name[i];
ep->ep.ops = &r8a66597_ep_ops;
ep->ep.maxpacket = 512;
usb_ep_set_maxpacket_limit(&ep->ep, 512);
}
r8a66597->ep[0].ep.maxpacket = 64;
usb_ep_set_maxpacket_limit(&r8a66597->ep[0].ep, 64);
r8a66597->ep[0].pipenum = 0;
r8a66597->ep[0].fifoaddr = CFIFO;
r8a66597->ep[0].fifosel = CFIFOSEL;
......@@ -1996,7 +1996,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
free_irq(irq, r8a66597);
clean_up2:
if (r8a66597->pdata->on_chip) {
clk_disable(r8a66597->clk);
clk_disable_unprepare(r8a66597->clk);
clk_put(r8a66597->clk);
}
clean_up:
......
......@@ -1142,7 +1142,7 @@ static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
static int rndis_init(void)
int rndis_init(void)
{
u8 i;
......@@ -1174,9 +1174,8 @@ static int rndis_init(void)
return 0;
}
module_init(rndis_init);
static void rndis_exit(void)
void rndis_exit(void)
{
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
u8 i;
......@@ -1188,6 +1187,4 @@ static void rndis_exit(void)
}
#endif
}
module_exit(rndis_exit);
MODULE_LICENSE("GPL");
......@@ -30,14 +30,14 @@
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/of_platform.h>
#include <linux/phy/phy.h>
#include <linux/usb/phy.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/phy.h>
#include <linux/platform_data/s3c-hsotg.h>
#include <mach/map.h>
#include "s3c-hsotg.h"
static const char * const s3c_hsotg_supply_names[] = {
......@@ -140,11 +140,13 @@ struct s3c_hsotg_ep {
* @dev: The parent device supplied to the probe function
* @driver: USB gadget driver
* @phy: The otg phy transceiver structure for phy control.
* @uphy: The otg phy transceiver structure for old USB phy control.
* @plat: The platform specific configuration data. This can be removed once
* all SoCs support usb transceiver.
* @regs: The memory area mapped for accessing registers.
* @irq: The IRQ number we are using
* @supplies: Definition of USB power supplies
* @phyif: PHY interface width
* @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
* @num_of_eps: Number of available EPs (excluding EP0)
* @debug_root: root directrory for debugfs.
......@@ -161,7 +163,8 @@ struct s3c_hsotg_ep {
struct s3c_hsotg {
struct device *dev;
struct usb_gadget_driver *driver;
struct usb_phy *phy;
struct phy *phy;
struct usb_phy *uphy;
struct s3c_hsotg_plat *plat;
spinlock_t lock;
......@@ -172,6 +175,7 @@ struct s3c_hsotg {
struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)];
u32 phyif;
unsigned int dedicated_fifos:1;
unsigned char num_of_eps;
......@@ -2086,13 +2090,13 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg)
case DSTS_EnumSpd_FS48:
hsotg->gadget.speed = USB_SPEED_FULL;
ep0_mps = EP0_MPS_LIMIT;
ep_mps = 64;
ep_mps = 1023;
break;
case DSTS_EnumSpd_HS:
hsotg->gadget.speed = USB_SPEED_HIGH;
ep0_mps = EP0_MPS_LIMIT;
ep_mps = 512;
ep_mps = 1024;
break;
case DSTS_EnumSpd_LS:
......@@ -2156,6 +2160,9 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
s3c_hsotg_complete_request(hsotg, ep, req,
result);
}
if(hsotg->dedicated_fifos)
if ((readl(hsotg->regs + DTXFSTS(ep->index)) & 0xffff) * 4 < 3072)
s3c_hsotg_txfifo_flush(hsotg, ep->index);
}
#define call_gadget(_hs, _entry) \
......@@ -2283,7 +2290,7 @@ static void s3c_hsotg_core_init(struct s3c_hsotg *hsotg)
*/
/* set the PLL on, remove the HNP/SRP and set the PHY */
writel(GUSBCFG_PHYIf16 | GUSBCFG_TOutCal(7) |
writel(hsotg->phyif | GUSBCFG_TOutCal(7) |
(0x5 << 10), hsotg->regs + GUSBCFG);
s3c_hsotg_init_fifo(hsotg);
......@@ -2908,8 +2915,11 @@ static void s3c_hsotg_phy_enable(struct s3c_hsotg *hsotg)
dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev);
if (hsotg->phy)
usb_phy_init(hsotg->phy);
if (hsotg->phy) {
phy_init(hsotg->phy);
phy_power_on(hsotg->phy);
} else if (hsotg->uphy)
usb_phy_init(hsotg->uphy);
else if (hsotg->plat->phy_init)
hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
}
......@@ -2925,8 +2935,11 @@ static void s3c_hsotg_phy_disable(struct s3c_hsotg *hsotg)
{
struct platform_device *pdev = to_platform_device(hsotg->dev);
if (hsotg->phy)
usb_phy_shutdown(hsotg->phy);
if (hsotg->phy) {
phy_power_off(hsotg->phy);
phy_exit(hsotg->phy);
} else if (hsotg->uphy)
usb_phy_shutdown(hsotg->uphy);
else if (hsotg->plat->phy_exit)
hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
}
......@@ -3152,7 +3165,7 @@ static void s3c_hsotg_initep(struct s3c_hsotg *hsotg,
hs_ep->parent = hsotg;
hs_ep->ep.name = hs_ep->name;
hs_ep->ep.maxpacket = epnum ? 1024 : EP0_MPS_LIMIT;
usb_ep_set_maxpacket_limit(&hs_ep->ep, epnum ? 1024 : EP0_MPS_LIMIT);
hs_ep->ep.ops = &s3c_hsotg_ep_ops;
/*
......@@ -3533,7 +3546,8 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
static int s3c_hsotg_probe(struct platform_device *pdev)
{
struct s3c_hsotg_plat *plat = dev_get_platdata(&pdev->dev);
struct usb_phy *phy;
struct phy *phy;
struct usb_phy *uphy;
struct device *dev = &pdev->dev;
struct s3c_hsotg_ep *eps;
struct s3c_hsotg *hsotg;
......@@ -3548,19 +3562,26 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
return -ENOMEM;
}
phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
/*
* Attempt to find a generic PHY, then look for an old style
* USB PHY, finally fall back to pdata
*/
phy = devm_phy_get(&pdev->dev, "usb2-phy");
if (IS_ERR(phy)) {
/* Fallback for pdata */
plat = dev_get_platdata(&pdev->dev);
if (!plat) {
dev_err(&pdev->dev, "no platform data or transceiver defined\n");
return -EPROBE_DEFER;
} else {
uphy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
if (IS_ERR(uphy)) {
/* Fallback for pdata */
plat = dev_get_platdata(&pdev->dev);
if (!plat) {
dev_err(&pdev->dev,
"no platform data or transceiver defined\n");
return -EPROBE_DEFER;
}
hsotg->plat = plat;
}
} else {
} else
hsotg->uphy = uphy;
} else
hsotg->phy = phy;
}
hsotg->dev = dev;
......@@ -3627,6 +3648,19 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
goto err_supplies;
}
/* Set default UTMI width */
hsotg->phyif = GUSBCFG_PHYIf16;
/*
* If using the generic PHY framework, check if the PHY bus
* width is 8-bit and set the phyif appropriately.
*/
if (hsotg->phy && (phy_get_bus_width(phy) == 8))
hsotg->phyif = GUSBCFG_PHYIf8;
if (hsotg->phy)
phy_init(hsotg->phy);
/* usb phy enable */
s3c_hsotg_phy_enable(hsotg);
......@@ -3720,6 +3754,8 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
}
s3c_hsotg_phy_disable(hsotg);
if (hsotg->phy)
phy_exit(hsotg->phy);
clk_disable_unprepare(hsotg->clk);
return 0;
......@@ -3733,6 +3769,7 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
#ifdef CONFIG_OF
static const struct of_device_id s3c_hsotg_of_ids[] = {
{ .compatible = "samsung,s3c6400-hsotg", },
{ .compatible = "snps,dwc2", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, s3c_hsotg_of_ids);
......
......@@ -55,6 +55,7 @@
#define GUSBCFG_HNPCap (1 << 9)
#define GUSBCFG_SRPCap (1 << 8)
#define GUSBCFG_PHYIf16 (1 << 3)
#define GUSBCFG_PHYIf8 (0 << 3)
#define GUSBCFG_TOutCal_MASK (0x7 << 0)
#define GUSBCFG_TOutCal_SHIFT (0)
#define GUSBCFG_TOutCal_LIMIT (0x7)
......
......@@ -999,7 +999,7 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc,
hsep->dev = hsudc;
hsep->ep.name = hsep->name;
hsep->ep.maxpacket = epnum ? 512 : 64;
usb_ep_set_maxpacket_limit(&hsep->ep, epnum ? 512 : 64);
hsep->ep.ops = &s3c_hsudc_ep_ops;
hsep->fifo = hsudc->regs + S3C_BR(epnum);
hsep->ep.desc = NULL;
......
......@@ -1629,6 +1629,7 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
ep->ep.desc = NULL;
ep->halted = 0;
INIT_LIST_HEAD(&ep->queue);
usb_ep_set_maxpacket_limit(&ep->ep, &ep->ep.maxpacket);
}
}
......
......@@ -753,7 +753,7 @@ static struct device_type gadget_type = {
* gadget driver using this framework. The link layer addresses are
* set up using module parameters.
*
* Returns negative errno, or zero on success
* Returns an eth_dev pointer on success, or an ERR_PTR on failure.
*/
struct eth_dev *gether_setup_name(struct usb_gadget *g,
const char *dev_addr, const char *host_addr,
......
......@@ -106,7 +106,7 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g,
* gadget driver using this framework. The link layer addresses are
* set up using module parameters.
*
* Returns negative errno, or zero on success
* Returns a eth_dev pointer on success, or an ERR_PTR on failure
*/
static inline struct eth_dev *gether_setup(struct usb_gadget *g,
const char *dev_addr, const char *host_addr,
......@@ -267,45 +267,4 @@ static inline bool can_support_ecm(struct usb_gadget *gadget)
return true;
}
/* each configuration may bind one instance of an ethernet link */
int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct eth_dev *dev);
int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct eth_dev *dev);
#ifdef USB_ETH_RNDIS
int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
u32 vendorID, const char *manufacturer, struct eth_dev *dev);
#else
static inline int
rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
u32 vendorID, const char *manufacturer, struct eth_dev *dev)
{
return 0;
}
#endif
/**
* rndis_bind_config - add RNDIS 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
* 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.
*/
static inline int rndis_bind_config(struct usb_configuration *c,
u8 ethaddr[ETH_ALEN], struct eth_dev *dev)
{
return rndis_bind_config_vendor(c, ethaddr, 0, NULL, dev);
}
#endif /* __U_ETHER_H */
/*
* u_f.c -- USB function utilities for Gadget stack
*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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 as
* published by the Free Software Foundation.
*/
#include <linux/usb/gadget.h>
#include "u_f.h"
struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len)
{
struct usb_request *req;
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (req) {
req->length = len ?: default_len;
req->buf = kmalloc(req->length, GFP_ATOMIC);
if (!req->buf) {
usb_ep_free_request(ep, req);
req = NULL;
}
}
return req;
}
EXPORT_SYMBOL(alloc_ep_req);
/*
* u_f.h
*
* Utility definitions for USB functions
*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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 as
* published by the Free Software Foundation.
*/
#ifndef __U_F_H__
#define __U_F_H__
struct usb_ep;
struct usb_request;
struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len);
#endif /* __U_F_H__ */
此差异已折叠。
......@@ -36,6 +36,8 @@ struct f_rndis_opts {
int refcnt;
};
int rndis_init(void);
void rndis_exit(void);
void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net);
#endif /* U_RNDIS_H */
......@@ -64,10 +64,10 @@ static bool loopdefault = 0;
module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
static struct usb_zero_options gzero_options = {
.isoc_interval = 4,
.isoc_maxpacket = 1024,
.bulk_buflen = 4096,
.qlen = 32,
.isoc_interval = GZERO_ISOC_INTERVAL,
.isoc_maxpacket = GZERO_ISOC_MAXPACKET,
.bulk_buflen = GZERO_BULK_BUFLEN,
.qlen = GZERO_QLEN,
};
/*-------------------------------------------------------------------------*/
......
此差异已折叠。
......@@ -19,6 +19,7 @@ obj-$(CONFIG_USB_MUSB_DAVINCI) += davinci.o
obj-$(CONFIG_USB_MUSB_DA8XX) += da8xx.o
obj-$(CONFIG_USB_MUSB_BLACKFIN) += blackfin.o
obj-$(CONFIG_USB_MUSB_UX500) += ux500.o
obj-$(CONFIG_USB_MUSB_JZ4740) += jz4740.o
obj-$(CONFIG_USB_MUSB_AM335X_CHILD) += musb_am335x.o
......
此差异已折叠。
此差异已折叠。
......@@ -47,6 +47,7 @@
#include <linux/usb/otg.h>
#include <linux/usb/musb.h>
#include <linux/phy/phy.h>
#include <linux/workqueue.h>
struct musb;
struct musb_hw_ep;
......@@ -295,6 +296,8 @@ struct musb {
irqreturn_t (*isr)(int, void *);
struct work_struct irq_work;
struct delayed_work deassert_reset_work;
struct delayed_work finish_resume_work;
u16 hwvers;
u16 intrrxe;
......
此差异已折叠。
此差异已折叠。
......@@ -2433,6 +2433,8 @@ static int musb_bus_suspend(struct usb_hcd *hcd)
struct musb *musb = hcd_to_musb(hcd);
u8 devctl;
musb_port_suspend(musb, true);
if (!is_host_active(musb))
return 0;
......@@ -2462,7 +2464,12 @@ static int musb_bus_suspend(struct usb_hcd *hcd)
static int musb_bus_resume(struct usb_hcd *hcd)
{
/* resuming child port does the work */
struct musb *musb = hcd_to_musb(hcd);
if (musb->config &&
musb->config->host_port_deassert_reset_at_resume)
musb_port_reset(musb, false);
return 0;
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -241,7 +241,6 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
nop->phy.otg->set_host = nop_set_host;
nop->phy.otg->set_peripheral = nop_set_peripheral;
ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
return 0;
}
EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部