From f0ae849df1cd6b597130d890f2107ee31bf02c19 Mon Sep 17 00:00:00 2001 From: Hao Wu Date: Thu, 5 Aug 2010 14:17:28 +0100 Subject: [PATCH 001/141] usb: Add Intel Langwell USB OTG Transceiver Driver This adds support for the USB transceiver driver in the Langwell chipset used on the Intel MID platforms. It folds up the original patch set which includes basic support for the device, PHY low power mode (Please notice that there is a limitation, after we drive VBus down, 2ms delay is required from SCU FW to sync up OTGSC register with USBCFG register), software timers (the hardware timers do not work in low power mode), HNP, SRP. Signed-off-by: Hao Wu Signed-off-by: Alek Du Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/Kconfig | 14 + drivers/usb/otg/Makefile | 1 + drivers/usb/otg/langwell_otg.c | 2408 ++++++++++++++++++++++++++++++ include/linux/usb/langwell_otg.h | 139 ++ 4 files changed, 2562 insertions(+) create mode 100644 drivers/usb/otg/langwell_otg.c create mode 100644 include/linux/usb/langwell_otg.h diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 3b1289572d72..299dfd2510cb 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -67,4 +67,18 @@ config NOP_USB_XCEIV built-in with usb ip or which are autonomous and doesn't require any phy programming such as ISP1x04 etc. +config USB_LANGWELL_OTG + tristate "Intel Langwell USB OTG dual-role support" + depends on USB && X86_MRST + select USB_OTG + select USB_OTG_UTILS + help + Say Y here if you want to build Intel Langwell USB OTG + transciever driver in kernel. This driver implements role + switch between EHCI host driver and Langwell USB OTG + client driver. + + To compile this driver as a module, choose M here: the + module will be called langwell_otg. + endif # USB || OTG diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index aeb49a8ec412..b6609db3a849 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o +obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o obj-$(CONFIG_USB_ULPI) += ulpi.o diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c new file mode 100644 index 000000000000..879188086daf --- /dev/null +++ b/drivers/usb/otg/langwell_otg.c @@ -0,0 +1,2408 @@ +/* + * Intel Langwell USB OTG transceiver driver + * Copyright (C) 2008 - 2009, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +/* This driver helps to switch Langwell OTG controller function between host + * and peripheral. It works with EHCI driver and Langwell client controller + * driver together. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRIVER_DESC "Intel Langwell USB OTG transceiver driver" +#define DRIVER_VERSION "3.0.0.32L.0003" + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Henry Yuan , Hao Wu "); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); + +static const char driver_name[] = "langwell_otg"; + +static int langwell_otg_probe(struct pci_dev *pdev, + const struct pci_device_id *id); +static void langwell_otg_remove(struct pci_dev *pdev); +static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message); +static int langwell_otg_resume(struct pci_dev *pdev); + +static int langwell_otg_set_host(struct otg_transceiver *otg, + struct usb_bus *host); +static int langwell_otg_set_peripheral(struct otg_transceiver *otg, + struct usb_gadget *gadget); +static int langwell_otg_start_srp(struct otg_transceiver *otg); + +static const struct pci_device_id pci_ids[] = {{ + .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), + .class_mask = ~0, + .vendor = 0x8086, + .device = 0x0811, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, +}, { /* end: all zeroes */ } +}; + +static struct pci_driver otg_pci_driver = { + .name = (char *) driver_name, + .id_table = pci_ids, + + .probe = langwell_otg_probe, + .remove = langwell_otg_remove, + + .suspend = langwell_otg_suspend, + .resume = langwell_otg_resume, +}; + +static const char *state_string(enum usb_otg_state state) +{ + switch (state) { + case OTG_STATE_A_IDLE: + return "a_idle"; + case OTG_STATE_A_WAIT_VRISE: + return "a_wait_vrise"; + case OTG_STATE_A_WAIT_BCON: + return "a_wait_bcon"; + case OTG_STATE_A_HOST: + return "a_host"; + case OTG_STATE_A_SUSPEND: + return "a_suspend"; + case OTG_STATE_A_PERIPHERAL: + return "a_peripheral"; + case OTG_STATE_A_WAIT_VFALL: + return "a_wait_vfall"; + case OTG_STATE_A_VBUS_ERR: + return "a_vbus_err"; + case OTG_STATE_B_IDLE: + return "b_idle"; + case OTG_STATE_B_SRP_INIT: + return "b_srp_init"; + case OTG_STATE_B_PERIPHERAL: + return "b_peripheral"; + case OTG_STATE_B_WAIT_ACON: + return "b_wait_acon"; + case OTG_STATE_B_HOST: + return "b_host"; + default: + return "UNDEFINED"; + } +} + +/* HSM timers */ +static inline struct langwell_otg_timer *otg_timer_initializer +(void (*function)(unsigned long), unsigned long expires, unsigned long data) +{ + struct langwell_otg_timer *timer; + timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL); + if (timer == NULL) + return timer; + + timer->function = function; + timer->expires = expires; + timer->data = data; + return timer; +} + +static struct langwell_otg_timer *a_wait_vrise_tmr, *a_aidl_bdis_tmr, + *b_se0_srp_tmr, *b_srp_init_tmr; + +static struct list_head active_timers; + +static struct langwell_otg *the_transceiver; + +/* host/client notify transceiver when event affects HNP state */ +void langwell_update_transceiver(void) +{ + struct langwell_otg *lnw = the_transceiver; + + dev_dbg(lnw->dev, "transceiver is updated\n"); + + if (!lnw->qwork) + return ; + + queue_work(lnw->qwork, &lnw->work); +} +EXPORT_SYMBOL(langwell_update_transceiver); + +static int langwell_otg_set_host(struct otg_transceiver *otg, + struct usb_bus *host) +{ + otg->host = host; + + return 0; +} + +static int langwell_otg_set_peripheral(struct otg_transceiver *otg, + struct usb_gadget *gadget) +{ + otg->gadget = gadget; + + return 0; +} + +static int langwell_otg_set_power(struct otg_transceiver *otg, + unsigned mA) +{ + return 0; +} + +/* A-device drives vbus, controlled through PMIC CHRGCNTL register*/ +static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled) +{ + struct langwell_otg *lnw = the_transceiver; + u8 r; + + dev_dbg(lnw->dev, "%s <--- %s\n", __func__, enabled ? "on" : "off"); + + /* FIXME: surely we should cache this on the first read. If not use + readv to avoid two transactions */ + if (intel_scu_ipc_ioread8(0x00, &r) < 0) { + dev_dbg(lnw->dev, "Failed to read PMIC register 0xD2"); + return -EBUSY; + } + if ((r & 0x03) != 0x02) { + dev_dbg(lnw->dev, "not NEC PMIC attached\n"); + return -EBUSY; + } + + if (intel_scu_ipc_ioread8(0x20, &r) < 0) { + dev_dbg(lnw->dev, "Failed to read PMIC register 0xD2"); + return -EBUSY; + } + + if ((r & 0x20) == 0) { + dev_dbg(lnw->dev, "no battery attached\n"); + return -EBUSY; + } + + /* Workaround for battery attachment issue */ + if (r == 0x34) { + dev_dbg(lnw->dev, "no battery attached on SH\n"); + return -EBUSY; + } + + dev_dbg(lnw->dev, "battery attached. 2 reg = %x\n", r); + + /* workaround: FW detect writing 0x20/0xc0 to d4 event. + * this is only for NEC PMIC. + */ + + if (intel_scu_ipc_iowrite8(0xD4, enabled ? 0x20 : 0xC0)) + dev_dbg(lnw->dev, "Failed to write PMIC.\n"); + + dev_dbg(lnw->dev, "%s --->\n", __func__); + + return 0; +} + +/* charge vbus or discharge vbus through a resistor to ground */ +static void langwell_otg_chrg_vbus(int on) +{ + struct langwell_otg *lnw = the_transceiver; + u32 val; + + val = readl(lnw->iotg.base + CI_OTGSC); + + if (on) + writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC, + lnw->iotg.base + CI_OTGSC); + else + writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD, + lnw->iotg.base + CI_OTGSC); +} + +/* Start SRP */ +static int langwell_otg_start_srp(struct otg_transceiver *otg) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u32 val; + + dev_dbg(lnw->dev, "%s --->\n", __func__); + + val = readl(iotg->base + CI_OTGSC); + + writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP, + iotg->base + CI_OTGSC); + + /* Check if the data plus is finished or not */ + msleep(8); + val = readl(iotg->base + CI_OTGSC); + if (val & (OTGSC_HADP | OTGSC_DP)) + dev_dbg(lnw->dev, "DataLine SRP Error\n"); + + /* Disable interrupt - b_sess_vld */ + val = readl(iotg->base + CI_OTGSC); + val &= (~(OTGSC_BSVIE | OTGSC_BSEIE)); + writel(val, iotg->base + CI_OTGSC); + + /* Start VBus SRP, drive vbus to generate VBus pulse */ + iotg->otg.set_vbus(&iotg->otg, true); + msleep(15); + iotg->otg.set_vbus(&iotg->otg, false); + + /* Enable interrupt - b_sess_vld*/ + val = readl(iotg->base + CI_OTGSC); + dev_dbg(lnw->dev, "after VBUS pulse otgsc = %x\n", val); + + val |= (OTGSC_BSVIE | OTGSC_BSEIE); + writel(val, iotg->base + CI_OTGSC); + + /* If Vbus is valid, then update the hsm */ + if (val & OTGSC_BSV) { + dev_dbg(lnw->dev, "no b_sess_vld interrupt\n"); + + lnw->iotg.hsm.b_sess_vld = 1; + langwell_update_transceiver(); + } + + dev_dbg(lnw->dev, "%s <---\n", __func__); + return 0; +} + +/* stop SOF via bus_suspend */ +static void langwell_otg_loc_sof(int on) +{ + struct langwell_otg *lnw = the_transceiver; + struct usb_hcd *hcd; + int err; + + dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "suspend" : "resume"); + + hcd = bus_to_hcd(lnw->iotg.otg.host); + if (on) + err = hcd->driver->bus_resume(hcd); + else + err = hcd->driver->bus_suspend(hcd); + + if (err) + dev_dbg(lnw->dev, "Fail to resume/suspend USB bus - %d\n", err); + + dev_dbg(lnw->dev, "%s <---\n", __func__); +} + +static int langwell_otg_check_otgsc(void) +{ + struct langwell_otg *lnw = the_transceiver; + u32 otgsc, usbcfg; + + dev_dbg(lnw->dev, "check sync OTGSC and USBCFG registers\n"); + + otgsc = readl(lnw->iotg.base + CI_OTGSC); + usbcfg = readl(lnw->usbcfg); + + dev_dbg(lnw->dev, "OTGSC = %08x, USBCFG = %08x\n", + otgsc, usbcfg); + dev_dbg(lnw->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV)); + dev_dbg(lnw->dev, "USBCFG.VBUSVAL = %d\n", + !!(usbcfg & USBCFG_VBUSVAL)); + dev_dbg(lnw->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV)); + dev_dbg(lnw->dev, "USBCFG.AVALID = %d\n", + !!(usbcfg & USBCFG_AVALID)); + dev_dbg(lnw->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV)); + dev_dbg(lnw->dev, "USBCFG.BVALID = %d\n", + !!(usbcfg & USBCFG_BVALID)); + dev_dbg(lnw->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE)); + dev_dbg(lnw->dev, "USBCFG.SESEND = %d\n", + !!(usbcfg & USBCFG_SESEND)); + + /* Check USBCFG VBusValid/AValid/BValid/SessEnd */ + if (!!(otgsc & OTGSC_AVV) ^ !!(usbcfg & USBCFG_VBUSVAL)) { + dev_dbg(lnw->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n"); + goto err; + } + if (!!(otgsc & OTGSC_ASV) ^ !!(usbcfg & USBCFG_AVALID)) { + dev_dbg(lnw->dev, "OTGSC.ASV != USBCFG.AVALID\n"); + goto err; + } + if (!!(otgsc & OTGSC_BSV) ^ !!(usbcfg & USBCFG_BVALID)) { + dev_dbg(lnw->dev, "OTGSC.BSV != USBCFG.BVALID\n"); + goto err; + } + if (!!(otgsc & OTGSC_BSE) ^ !!(usbcfg & USBCFG_SESEND)) { + dev_dbg(lnw->dev, "OTGSC.BSE != USBCFG.SESSEN\n"); + goto err; + } + + dev_dbg(lnw->dev, "OTGSC and USBCFG are synced\n"); + + return 0; + +err: + dev_warn(lnw->dev, "OTGSC isn't equal to USBCFG\n"); + return -EPIPE; +} + + +static void langwell_otg_phy_low_power(int on) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u8 val, phcd; + int retval; + + dev_dbg(lnw->dev, "%s ---> %s mode\n", + __func__, on ? "Low power" : "Normal"); + + phcd = 0x40; + + val = readb(iotg->base + CI_HOSTPC1 + 2); + + if (on) { + /* Due to hardware issue, after set PHCD, sync will failed + * between USBCFG and OTGSC, so before set PHCD, check if + * sync is in process now. If the answer is "yes", then do + * not touch PHCD bit */ + retval = langwell_otg_check_otgsc(); + if (retval) { + dev_dbg(lnw->dev, "Skip PHCD programming..\n"); + return ; + } + + writeb(val | phcd, iotg->base + CI_HOSTPC1 + 2); + } else + writeb(val & ~phcd, iotg->base + CI_HOSTPC1 + 2); + + dev_dbg(lnw->dev, "%s <--- done\n", __func__); +} + +/* After drv vbus, add 2 ms delay to set PHCD */ +static void langwell_otg_phy_low_power_wait(int on) +{ + struct langwell_otg *lnw = the_transceiver; + + dev_dbg(lnw->dev, "add 2ms delay before programing PHCD\n"); + + mdelay(2); + langwell_otg_phy_low_power(on); +} + +/* Enable/Disable OTG interrupt */ +static void langwell_otg_intr(int on) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u32 val; + + dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); + + val = readl(iotg->base + CI_OTGSC); + + /* OTGSC_INT_MASK doesn't contains 1msInt */ + if (on) { + val = val | (OTGSC_INT_MASK); + writel(val, iotg->base + CI_OTGSC); + } else { + val = val & ~(OTGSC_INT_MASK); + writel(val, iotg->base + CI_OTGSC); + } + + dev_dbg(lnw->dev, "%s <---\n", __func__); +} + +/* set HAAR: Hardware Assist Auto-Reset */ +static void langwell_otg_HAAR(int on) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u32 val; + + dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); + + val = readl(iotg->base + CI_OTGSC); + if (on) + writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR, + iotg->base + CI_OTGSC); + else + writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR, + iotg->base + CI_OTGSC); + + dev_dbg(lnw->dev, "%s <---\n", __func__); +} + +/* set HABA: Hardware Assist B-Disconnect to A-Connect */ +static void langwell_otg_HABA(int on) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u32 val; + + dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off"); + + val = readl(iotg->base + CI_OTGSC); + if (on) + writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA, + iotg->base + CI_OTGSC); + else + writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA, + iotg->base + CI_OTGSC); + + dev_dbg(lnw->dev, "%s <---\n", __func__); +} + +static int langwell_otg_check_se0_srp(int on) +{ + struct langwell_otg *lnw = the_transceiver; + int delay_time = TB_SE0_SRP * 10; + u32 val; + + dev_dbg(lnw->dev, "%s --->\n", __func__); + + do { + udelay(100); + if (!delay_time--) + break; + val = readl(lnw->iotg.base + CI_PORTSC1); + val &= PORTSC_LS; + } while (!val); + + dev_dbg(lnw->dev, "%s <---\n", __func__); + return val; +} + +/* The timeout callback function to set time out bit */ +static void set_tmout(unsigned long indicator) +{ + *(int *)indicator = 1; +} + +void langwell_otg_nsf_msg(unsigned long indicator) +{ + struct langwell_otg *lnw = the_transceiver; + + switch (indicator) { + case 2: + case 4: + case 6: + case 7: + dev_warn(lnw->dev, + "OTG:NSF-%lu - deivce not responding\n", indicator); + break; + case 3: + dev_warn(lnw->dev, + "OTG:NSF-%lu - deivce not supported\n", indicator); + break; + default: + dev_warn(lnw->dev, "Do not have this kind of NSF\n"); + break; + } +} + +/* Initialize timers */ +static int langwell_otg_init_timers(struct otg_hsm *hsm) +{ + /* HSM used timers */ + a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE, + (unsigned long)&hsm->a_wait_vrise_tmout); + if (a_wait_vrise_tmr == NULL) + return -ENOMEM; + a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS, + (unsigned long)&hsm->a_aidl_bdis_tmout); + if (a_aidl_bdis_tmr == NULL) + return -ENOMEM; + b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP, + (unsigned long)&hsm->b_se0_srp); + if (b_se0_srp_tmr == NULL) + return -ENOMEM; + b_srp_init_tmr = otg_timer_initializer(&set_tmout, TB_SRP_INIT, + (unsigned long)&hsm->b_srp_init_tmout); + if (b_srp_init_tmr == NULL) + return -ENOMEM; + + return 0; +} + +/* Free timers */ +static void langwell_otg_free_timers(void) +{ + kfree(a_wait_vrise_tmr); + kfree(a_aidl_bdis_tmr); + kfree(b_se0_srp_tmr); + kfree(b_srp_init_tmr); +} + +/* The timeout callback function to set time out bit */ +static void langwell_otg_timer_fn(unsigned long indicator) +{ + struct langwell_otg *lnw = the_transceiver; + + *(int *)indicator = 1; + + dev_dbg(lnw->dev, "kernel timer - timeout\n"); + + langwell_update_transceiver(); +} + +/* kernel timer used instead of HW based interrupt */ +static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + unsigned long j = jiffies; + unsigned long data, time; + + switch (timers) { + case TA_WAIT_VRISE_TMR: + iotg->hsm.a_wait_vrise_tmout = 0; + data = (unsigned long)&iotg->hsm.a_wait_vrise_tmout; + time = TA_WAIT_VRISE; + break; + case TA_WAIT_BCON_TMR: + iotg->hsm.a_wait_bcon_tmout = 0; + data = (unsigned long)&iotg->hsm.a_wait_bcon_tmout; + time = TA_WAIT_BCON; + break; + case TA_AIDL_BDIS_TMR: + iotg->hsm.a_aidl_bdis_tmout = 0; + data = (unsigned long)&iotg->hsm.a_aidl_bdis_tmout; + time = TA_AIDL_BDIS; + break; + case TB_ASE0_BRST_TMR: + iotg->hsm.b_ase0_brst_tmout = 0; + data = (unsigned long)&iotg->hsm.b_ase0_brst_tmout; + time = TB_ASE0_BRST; + break; + case TB_SRP_INIT_TMR: + iotg->hsm.b_srp_init_tmout = 0; + data = (unsigned long)&iotg->hsm.b_srp_init_tmout; + time = TB_SRP_INIT; + break; + case TB_SRP_FAIL_TMR: + iotg->hsm.b_srp_fail_tmout = 0; + data = (unsigned long)&iotg->hsm.b_srp_fail_tmout; + time = TB_SRP_FAIL; + break; + case TB_BUS_SUSPEND_TMR: + iotg->hsm.b_bus_suspend_tmout = 0; + data = (unsigned long)&iotg->hsm.b_bus_suspend_tmout; + time = TB_BUS_SUSPEND; + break; + default: + dev_dbg(lnw->dev, "unkown timer, cannot enable it\n"); + return; + } + + lnw->hsm_timer.data = data; + lnw->hsm_timer.function = langwell_otg_timer_fn; + lnw->hsm_timer.expires = j + time * HZ / 1000; /* milliseconds */ + + add_timer(&lnw->hsm_timer); + + dev_dbg(lnw->dev, "add timer successfully\n"); +} + +/* Add timer to timer list */ +static void langwell_otg_add_timer(void *gtimer) +{ + struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; + struct langwell_otg_timer *tmp_timer; + struct intel_mid_otg_xceiv *iotg = &the_transceiver->iotg; + u32 val32; + + /* Check if the timer is already in the active list, + * if so update timer count + */ + list_for_each_entry(tmp_timer, &active_timers, list) + if (tmp_timer == timer) { + timer->count = timer->expires; + return; + } + timer->count = timer->expires; + + if (list_empty(&active_timers)) { + val32 = readl(iotg->base + CI_OTGSC); + writel(val32 | OTGSC_1MSE, iotg->base + CI_OTGSC); + } + + list_add_tail(&timer->list, &active_timers); +} + +/* Remove timer from the timer list; clear timeout status */ +static void langwell_otg_del_timer(void *gtimer) +{ + struct langwell_otg *lnw = the_transceiver; + struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer; + struct langwell_otg_timer *tmp_timer, *del_tmp; + u32 val32; + + list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) + if (tmp_timer == timer) + list_del(&timer->list); + + if (list_empty(&active_timers)) { + val32 = readl(lnw->iotg.base + CI_OTGSC); + writel(val32 & ~OTGSC_1MSE, lnw->iotg.base + CI_OTGSC); + } +} + +/* Reduce timer count by 1, and find timeout conditions.*/ +static int langwell_otg_tick_timer(u32 *int_sts) +{ + struct langwell_otg *lnw = the_transceiver; + struct langwell_otg_timer *tmp_timer, *del_tmp; + int expired = 0; + + list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) { + tmp_timer->count--; + /* check if timer expires */ + if (!tmp_timer->count) { + list_del(&tmp_timer->list); + tmp_timer->function(tmp_timer->data); + expired = 1; + } + } + + if (list_empty(&active_timers)) { + dev_dbg(lnw->dev, "tick timer: disable 1ms int\n"); + *int_sts = *int_sts & ~OTGSC_1MSE; + } + return expired; +} + +static void reset_otg(void) +{ + struct langwell_otg *lnw = the_transceiver; + int delay_time = 1000; + u32 val; + + dev_dbg(lnw->dev, "reseting OTG controller ...\n"); + val = readl(lnw->iotg.base + CI_USBCMD); + writel(val | USBCMD_RST, lnw->iotg.base + CI_USBCMD); + do { + udelay(100); + if (!delay_time--) + dev_dbg(lnw->dev, "reset timeout\n"); + val = readl(lnw->iotg.base + CI_USBCMD); + val &= USBCMD_RST; + } while (val != 0); + dev_dbg(lnw->dev, "reset done.\n"); +} + +static void set_host_mode(void) +{ + struct langwell_otg *lnw = the_transceiver; + u32 val; + + reset_otg(); + val = readl(lnw->iotg.base + CI_USBMODE); + val = (val & (~USBMODE_CM)) | USBMODE_HOST; + writel(val, lnw->iotg.base + CI_USBMODE); +} + +static void set_client_mode(void) +{ + struct langwell_otg *lnw = the_transceiver; + u32 val; + + reset_otg(); + val = readl(lnw->iotg.base + CI_USBMODE); + val = (val & (~USBMODE_CM)) | USBMODE_DEVICE; + writel(val, lnw->iotg.base + CI_USBMODE); +} + +static void init_hsm(void) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u32 val32; + + /* read OTGSC after reset */ + val32 = readl(lnw->iotg.base + CI_OTGSC); + dev_dbg(lnw->dev, "%s: OTGSC init value = 0x%x\n", __func__, val32); + + /* set init state */ + if (val32 & OTGSC_ID) { + iotg->hsm.id = 1; + iotg->otg.default_a = 0; + set_client_mode(); + iotg->otg.state = OTG_STATE_B_IDLE; + } else { + iotg->hsm.id = 0; + iotg->otg.default_a = 1; + set_host_mode(); + iotg->otg.state = OTG_STATE_A_IDLE; + } + + /* set session indicator */ + if (val32 & OTGSC_BSE) + iotg->hsm.b_sess_end = 1; + if (val32 & OTGSC_BSV) + iotg->hsm.b_sess_vld = 1; + if (val32 & OTGSC_ASV) + iotg->hsm.a_sess_vld = 1; + if (val32 & OTGSC_AVV) + iotg->hsm.a_vbus_vld = 1; + + /* defautly power the bus */ + iotg->hsm.a_bus_req = 1; + iotg->hsm.a_bus_drop = 0; + /* defautly don't request bus as B device */ + iotg->hsm.b_bus_req = 0; + /* no system error */ + iotg->hsm.a_clr_err = 0; + + langwell_otg_phy_low_power_wait(1); +} + +static void update_hsm(void) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u32 val32; + + /* read OTGSC */ + val32 = readl(lnw->iotg.base + CI_OTGSC); + dev_dbg(lnw->dev, "%s: OTGSC value = 0x%x\n", __func__, val32); + + iotg->hsm.id = !!(val32 & OTGSC_ID); + iotg->hsm.b_sess_end = !!(val32 & OTGSC_BSE); + iotg->hsm.b_sess_vld = !!(val32 & OTGSC_BSV); + iotg->hsm.a_sess_vld = !!(val32 & OTGSC_ASV); + iotg->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV); +} + +static irqreturn_t otg_dummy_irq(int irq, void *_dev) +{ + struct langwell_otg *lnw = the_transceiver; + void __iomem *reg_base = _dev; + u32 val; + u32 int_mask = 0; + + val = readl(reg_base + CI_USBMODE); + if ((val & USBMODE_CM) != USBMODE_DEVICE) + return IRQ_NONE; + + val = readl(reg_base + CI_USBSTS); + int_mask = val & INTR_DUMMY_MASK; + + if (int_mask == 0) + return IRQ_NONE; + + /* clear hsm.b_conn here since host driver can't detect it + * otg_dummy_irq called means B-disconnect happened. + */ + if (lnw->iotg.hsm.b_conn) { + lnw->iotg.hsm.b_conn = 0; + if (spin_trylock(&lnw->wq_lock)) { + langwell_update_transceiver(); + spin_unlock(&lnw->wq_lock); + } + } + + /* Clear interrupts */ + writel(int_mask, reg_base + CI_USBSTS); + return IRQ_HANDLED; +} + +static irqreturn_t otg_irq(int irq, void *_dev) +{ + struct langwell_otg *lnw = _dev; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + u32 int_sts, int_en; + u32 int_mask = 0; + int flag = 0; + + int_sts = readl(lnw->iotg.base + CI_OTGSC); + int_en = (int_sts & OTGSC_INTEN_MASK) >> 8; + int_mask = int_sts & int_en; + if (int_mask == 0) + return IRQ_NONE; + + if (int_mask & OTGSC_IDIS) { + dev_dbg(lnw->dev, "%s: id change int\n", __func__); + iotg->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0; + dev_dbg(lnw->dev, "id = %d\n", iotg->hsm.id); + flag = 1; + } + if (int_mask & OTGSC_DPIS) { + dev_dbg(lnw->dev, "%s: data pulse int\n", __func__); + iotg->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0; + dev_dbg(lnw->dev, "data pulse = %d\n", iotg->hsm.a_srp_det); + flag = 1; + } + if (int_mask & OTGSC_BSEIS) { + dev_dbg(lnw->dev, "%s: b session end int\n", __func__); + iotg->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0; + dev_dbg(lnw->dev, "b_sess_end = %d\n", iotg->hsm.b_sess_end); + flag = 1; + } + if (int_mask & OTGSC_BSVIS) { + dev_dbg(lnw->dev, "%s: b session valid int\n", __func__); + iotg->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0; + dev_dbg(lnw->dev, "b_sess_vld = %d\n", iotg->hsm.b_sess_end); + flag = 1; + } + if (int_mask & OTGSC_ASVIS) { + dev_dbg(lnw->dev, "%s: a session valid int\n", __func__); + iotg->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0; + dev_dbg(lnw->dev, "a_sess_vld = %d\n", iotg->hsm.a_sess_vld); + flag = 1; + } + if (int_mask & OTGSC_AVVIS) { + dev_dbg(lnw->dev, "%s: a vbus valid int\n", __func__); + iotg->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0; + dev_dbg(lnw->dev, "a_vbus_vld = %d\n", iotg->hsm.a_vbus_vld); + flag = 1; + } + + if (int_mask & OTGSC_1MSS) { + /* need to schedule otg_work if any timer is expired */ + if (langwell_otg_tick_timer(&int_sts)) + flag = 1; + } + + writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask, + lnw->iotg.base + CI_OTGSC); + if (flag) + langwell_update_transceiver(); + + return IRQ_HANDLED; +} + +static int langwell_otg_iotg_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = data; + int flag = 0; + + if (iotg == NULL) + return NOTIFY_BAD; + + if (lnw == NULL) + return NOTIFY_BAD; + + switch (action) { + case MID_OTG_NOTIFY_CONNECT: + dev_dbg(lnw->dev, "Lnw OTG Notify Connect Event\n"); + if (iotg->otg.default_a == 1) + iotg->hsm.b_conn = 1; + else + iotg->hsm.a_conn = 1; + flag = 1; + break; + case MID_OTG_NOTIFY_DISCONN: + dev_dbg(lnw->dev, "Lnw OTG Notify Disconnect Event\n"); + if (iotg->otg.default_a == 1) + iotg->hsm.b_conn = 0; + else + iotg->hsm.a_conn = 0; + flag = 1; + break; + case MID_OTG_NOTIFY_HSUSPEND: + dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus suspend Event\n"); + if (iotg->otg.default_a == 1) + iotg->hsm.a_suspend_req = 1; + else + iotg->hsm.b_bus_req = 0; + flag = 1; + break; + case MID_OTG_NOTIFY_HRESUME: + dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus resume Event\n"); + if (iotg->otg.default_a == 1) + iotg->hsm.b_bus_resume = 1; + flag = 1; + break; + case MID_OTG_NOTIFY_CSUSPEND: + dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus suspend Event\n"); + if (iotg->otg.default_a == 1) { + if (iotg->hsm.b_bus_suspend_vld == 2) { + iotg->hsm.b_bus_suspend = 1; + iotg->hsm.b_bus_suspend_vld = 0; + flag = 1; + } else { + iotg->hsm.b_bus_suspend_vld++; + flag = 0; + } + } else { + if (iotg->hsm.a_bus_suspend == 0) { + iotg->hsm.a_bus_suspend = 1; + flag = 1; + } + } + break; + case MID_OTG_NOTIFY_CRESUME: + dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus resume Event\n"); + if (iotg->otg.default_a == 0) + iotg->hsm.a_bus_suspend = 0; + flag = 0; + break; + case MID_OTG_NOTIFY_HOSTADD: + dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver Add\n"); + flag = 1; + break; + case MID_OTG_NOTIFY_HOSTREMOVE: + dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver remove\n"); + flag = 1; + break; + case MID_OTG_NOTIFY_CLIENTADD: + dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver Add\n"); + flag = 1; + break; + case MID_OTG_NOTIFY_CLIENTREMOVE: + dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver remove\n"); + flag = 1; + break; + default: + dev_dbg(lnw->dev, "Lnw OTG Nofity unknown notify message\n"); + return NOTIFY_DONE; + } + + if (flag) + langwell_update_transceiver(); + + return NOTIFY_OK; +} + +static void langwell_otg_work(struct work_struct *work) +{ + struct langwell_otg *lnw; + struct intel_mid_otg_xceiv *iotg; + int retval; + struct pci_dev *pdev; + + lnw = container_of(work, struct langwell_otg, work); + iotg = &lnw->iotg; + pdev = to_pci_dev(lnw->dev); + + dev_dbg(lnw->dev, "%s: old state = %s\n", __func__, + state_string(iotg->otg.state)); + + switch (iotg->otg.state) { + case OTG_STATE_UNDEFINED: + case OTG_STATE_B_IDLE: + if (!iotg->hsm.id) { + langwell_otg_del_timer(b_srp_init_tmr); + del_timer_sync(&lnw->hsm_timer); + + iotg->otg.default_a = 1; + iotg->hsm.a_srp_det = 0; + + langwell_otg_chrg_vbus(0); + set_host_mode(); + langwell_otg_phy_low_power(1); + + iotg->otg.state = OTG_STATE_A_IDLE; + langwell_update_transceiver(); + } else if (iotg->hsm.b_sess_vld) { + langwell_otg_del_timer(b_srp_init_tmr); + del_timer_sync(&lnw->hsm_timer); + iotg->hsm.b_sess_end = 0; + iotg->hsm.a_bus_suspend = 0; + langwell_otg_chrg_vbus(0); + + if (lnw->iotg.start_peripheral) { + lnw->iotg.start_peripheral(&lnw->iotg); + iotg->otg.state = OTG_STATE_B_PERIPHERAL; + } else + dev_dbg(lnw->dev, "client driver not loaded\n"); + + } else if (iotg->hsm.b_srp_init_tmout) { + iotg->hsm.b_srp_init_tmout = 0; + dev_warn(lnw->dev, "SRP init timeout\n"); + } else if (iotg->hsm.b_srp_fail_tmout) { + iotg->hsm.b_srp_fail_tmout = 0; + iotg->hsm.b_bus_req = 0; + + /* No silence failure */ + langwell_otg_nsf_msg(6); + } else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) { + del_timer_sync(&lnw->hsm_timer); + /* workaround for b_se0_srp detection */ + retval = langwell_otg_check_se0_srp(0); + if (retval) { + iotg->hsm.b_bus_req = 0; + dev_dbg(lnw->dev, "LS isn't SE0, try later\n"); + } else { + /* clear the PHCD before start srp */ + langwell_otg_phy_low_power(0); + + /* Start SRP */ + langwell_otg_add_timer(b_srp_init_tmr); + iotg->otg.start_srp(&iotg->otg); + langwell_otg_del_timer(b_srp_init_tmr); + langwell_otg_add_ktimer(TB_SRP_FAIL_TMR); + + /* reset PHY low power mode here */ + langwell_otg_phy_low_power_wait(1); + } + } + break; + case OTG_STATE_B_SRP_INIT: + if (!iotg->hsm.id) { + iotg->otg.default_a = 1; + iotg->hsm.a_srp_det = 0; + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + langwell_otg_chrg_vbus(0); + set_host_mode(); + langwell_otg_phy_low_power(1); + iotg->otg.state = OTG_STATE_A_IDLE; + langwell_update_transceiver(); + } else if (iotg->hsm.b_sess_vld) { + langwell_otg_chrg_vbus(0); + if (lnw->iotg.start_peripheral) { + lnw->iotg.start_peripheral(&lnw->iotg); + iotg->otg.state = OTG_STATE_B_PERIPHERAL; + } else + dev_dbg(lnw->dev, "client driver not loaded\n"); + } + break; + case OTG_STATE_B_PERIPHERAL: + if (!iotg->hsm.id) { + iotg->otg.default_a = 1; + iotg->hsm.a_srp_det = 0; + + langwell_otg_chrg_vbus(0); + + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); + else + dev_dbg(lnw->dev, + "client driver has been removed.\n"); + + set_host_mode(); + langwell_otg_phy_low_power(1); + iotg->otg.state = OTG_STATE_A_IDLE; + langwell_update_transceiver(); + } else if (!iotg->hsm.b_sess_vld) { + iotg->hsm.b_hnp_enable = 0; + + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); + else + dev_dbg(lnw->dev, + "client driver has been removed.\n"); + + iotg->otg.state = OTG_STATE_B_IDLE; + } else if (iotg->hsm.b_bus_req && iotg->otg.gadget && + iotg->otg.gadget->b_hnp_enable && + iotg->hsm.a_bus_suspend) { + + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); + else + dev_dbg(lnw->dev, + "client driver has been removed.\n"); + + langwell_otg_HAAR(1); + iotg->hsm.a_conn = 0; + + if (lnw->iotg.start_host) { + lnw->iotg.start_host(&lnw->iotg); + iotg->otg.state = OTG_STATE_B_WAIT_ACON; + } else + dev_dbg(lnw->dev, + "host driver not loaded.\n"); + + iotg->hsm.a_bus_resume = 0; + langwell_otg_add_ktimer(TB_ASE0_BRST_TMR); + } + break; + + case OTG_STATE_B_WAIT_ACON: + if (!iotg->hsm.id) { + /* delete hsm timer for b_ase0_brst_tmr */ + del_timer_sync(&lnw->hsm_timer); + + iotg->otg.default_a = 1; + iotg->hsm.a_srp_det = 0; + + langwell_otg_chrg_vbus(0); + + langwell_otg_HAAR(0); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + set_host_mode(); + langwell_otg_phy_low_power(1); + iotg->otg.state = OTG_STATE_A_IDLE; + langwell_update_transceiver(); + } else if (!iotg->hsm.b_sess_vld) { + /* delete hsm timer for b_ase0_brst_tmr */ + del_timer_sync(&lnw->hsm_timer); + + iotg->hsm.b_hnp_enable = 0; + iotg->hsm.b_bus_req = 0; + + langwell_otg_chrg_vbus(0); + langwell_otg_HAAR(0); + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + set_client_mode(); + langwell_otg_phy_low_power(1); + iotg->otg.state = OTG_STATE_B_IDLE; + } else if (iotg->hsm.a_conn) { + /* delete hsm timer for b_ase0_brst_tmr */ + del_timer_sync(&lnw->hsm_timer); + + langwell_otg_HAAR(0); + iotg->otg.state = OTG_STATE_B_HOST; + langwell_update_transceiver(); + } else if (iotg->hsm.a_bus_resume || + iotg->hsm.b_ase0_brst_tmout) { + /* delete hsm timer for b_ase0_brst_tmr */ + del_timer_sync(&lnw->hsm_timer); + + langwell_otg_HAAR(0); + langwell_otg_nsf_msg(7); + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + iotg->hsm.a_bus_suspend = 0; + iotg->hsm.b_bus_req = 0; + + if (lnw->iotg.start_peripheral) + lnw->iotg.start_peripheral(&lnw->iotg); + else + dev_dbg(lnw->dev, + "client driver not loaded.\n"); + + iotg->otg.state = OTG_STATE_B_PERIPHERAL; + } + break; + + case OTG_STATE_B_HOST: + if (!iotg->hsm.id) { + iotg->otg.default_a = 1; + iotg->hsm.a_srp_det = 0; + + langwell_otg_chrg_vbus(0); + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + set_host_mode(); + langwell_otg_phy_low_power(1); + iotg->otg.state = OTG_STATE_A_IDLE; + langwell_update_transceiver(); + } else if (!iotg->hsm.b_sess_vld) { + iotg->hsm.b_hnp_enable = 0; + iotg->hsm.b_bus_req = 0; + + langwell_otg_chrg_vbus(0); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + set_client_mode(); + langwell_otg_phy_low_power(1); + iotg->otg.state = OTG_STATE_B_IDLE; + } else if ((!iotg->hsm.b_bus_req) || + (!iotg->hsm.a_conn)) { + iotg->hsm.b_bus_req = 0; + langwell_otg_loc_sof(0); + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + iotg->hsm.a_bus_suspend = 0; + + if (lnw->iotg.start_peripheral) + lnw->iotg.start_peripheral(&lnw->iotg); + else + dev_dbg(lnw->dev, + "client driver not loaded.\n"); + + iotg->otg.state = OTG_STATE_B_PERIPHERAL; + } + break; + + case OTG_STATE_A_IDLE: + iotg->otg.default_a = 1; + if (iotg->hsm.id) { + iotg->otg.default_a = 0; + iotg->hsm.b_bus_req = 0; + iotg->hsm.vbus_srp_up = 0; + + langwell_otg_chrg_vbus(0); + set_client_mode(); + langwell_otg_phy_low_power(1); + iotg->otg.state = OTG_STATE_B_IDLE; + langwell_update_transceiver(); + } else if (!iotg->hsm.a_bus_drop && + (iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) { + langwell_otg_phy_low_power(0); + + /* Turn on VBus */ + iotg->otg.set_vbus(&iotg->otg, true); + + iotg->hsm.vbus_srp_up = 0; + iotg->hsm.a_wait_vrise_tmout = 0; + langwell_otg_add_timer(a_wait_vrise_tmr); + iotg->otg.state = OTG_STATE_A_WAIT_VRISE; + langwell_update_transceiver(); + } else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) { + iotg->hsm.vbus_srp_up = 1; + } else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) { + msleep(10); + langwell_otg_phy_low_power(0); + + /* Turn on VBus */ + iotg->otg.set_vbus(&iotg->otg, true); + iotg->hsm.a_srp_det = 1; + iotg->hsm.vbus_srp_up = 0; + iotg->hsm.a_wait_vrise_tmout = 0; + langwell_otg_add_timer(a_wait_vrise_tmr); + iotg->otg.state = OTG_STATE_A_WAIT_VRISE; + langwell_update_transceiver(); + } else if (!iotg->hsm.a_sess_vld && + !iotg->hsm.vbus_srp_up) { + langwell_otg_phy_low_power(1); + } + break; + case OTG_STATE_A_WAIT_VRISE: + if (iotg->hsm.id) { + langwell_otg_del_timer(a_wait_vrise_tmr); + iotg->hsm.b_bus_req = 0; + iotg->otg.default_a = 0; + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + set_client_mode(); + langwell_otg_phy_low_power_wait(1); + iotg->otg.state = OTG_STATE_B_IDLE; + } else if (iotg->hsm.a_vbus_vld) { + langwell_otg_del_timer(a_wait_vrise_tmr); + iotg->hsm.b_conn = 0; + if (lnw->iotg.start_host) + lnw->iotg.start_host(&lnw->iotg); + else { + dev_dbg(lnw->dev, "host driver not loaded.\n"); + break; + } + + langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); + iotg->otg.state = OTG_STATE_A_WAIT_BCON; + } else if (iotg->hsm.a_wait_vrise_tmout) { + iotg->hsm.b_conn = 0; + if (iotg->hsm.a_vbus_vld) { + if (lnw->iotg.start_host) + lnw->iotg.start_host(&lnw->iotg); + else { + dev_dbg(lnw->dev, + "host driver not loaded.\n"); + break; + } + langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); + iotg->otg.state = OTG_STATE_A_WAIT_BCON; + } else { + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + langwell_otg_phy_low_power_wait(1); + iotg->otg.state = OTG_STATE_A_VBUS_ERR; + } + } + break; + case OTG_STATE_A_WAIT_BCON: + if (iotg->hsm.id) { + /* delete hsm timer for a_wait_bcon_tmr */ + del_timer_sync(&lnw->hsm_timer); + + iotg->otg.default_a = 0; + iotg->hsm.b_bus_req = 0; + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + set_client_mode(); + langwell_otg_phy_low_power_wait(1); + iotg->otg.state = OTG_STATE_B_IDLE; + langwell_update_transceiver(); + } else if (!iotg->hsm.a_vbus_vld) { + /* delete hsm timer for a_wait_bcon_tmr */ + del_timer_sync(&lnw->hsm_timer); + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + langwell_otg_phy_low_power_wait(1); + iotg->otg.state = OTG_STATE_A_VBUS_ERR; + } else if (iotg->hsm.a_bus_drop || + (iotg->hsm.a_wait_bcon_tmout && + !iotg->hsm.a_bus_req)) { + /* delete hsm timer for a_wait_bcon_tmr */ + del_timer_sync(&lnw->hsm_timer); + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_WAIT_VFALL; + } else if (iotg->hsm.b_conn) { + /* delete hsm timer for a_wait_bcon_tmr */ + del_timer_sync(&lnw->hsm_timer); + + iotg->hsm.a_suspend_req = 0; + iotg->otg.state = OTG_STATE_A_HOST; + if (iotg->hsm.a_srp_det && iotg->otg.host && + !iotg->otg.host->b_hnp_enable) { + /* SRP capable peripheral-only device */ + iotg->hsm.a_bus_req = 1; + iotg->hsm.a_srp_det = 0; + } else if (!iotg->hsm.a_bus_req && iotg->otg.host && + iotg->otg.host->b_hnp_enable) { + /* It is not safe enough to do a fast + * transistion from A_WAIT_BCON to + * A_SUSPEND */ + msleep(10000); + if (iotg->hsm.a_bus_req) + break; + + if (request_irq(pdev->irq, + otg_dummy_irq, IRQF_SHARED, + driver_name, iotg->base) != 0) { + dev_dbg(lnw->dev, + "request interrupt %d fail\n", + pdev->irq); + } + + langwell_otg_HABA(1); + iotg->hsm.b_bus_resume = 0; + iotg->hsm.a_aidl_bdis_tmout = 0; + + langwell_otg_loc_sof(0); + /* clear PHCD to enable HW timer */ + langwell_otg_phy_low_power(0); + langwell_otg_add_timer(a_aidl_bdis_tmr); + iotg->otg.state = OTG_STATE_A_SUSPEND; + } else if (!iotg->hsm.a_bus_req && iotg->otg.host && + !iotg->otg.host->b_hnp_enable) { + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver removed.\n"); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_WAIT_VFALL; + } + } + break; + case OTG_STATE_A_HOST: + if (iotg->hsm.id) { + iotg->otg.default_a = 0; + iotg->hsm.b_bus_req = 0; + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + set_client_mode(); + langwell_otg_phy_low_power_wait(1); + iotg->otg.state = OTG_STATE_B_IDLE; + langwell_update_transceiver(); + } else if (iotg->hsm.a_bus_drop || + (iotg->otg.host && + !iotg->otg.host->b_hnp_enable && + !iotg->hsm.a_bus_req)) { + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_WAIT_VFALL; + } else if (!iotg->hsm.a_vbus_vld) { + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + langwell_otg_phy_low_power_wait(1); + iotg->otg.state = OTG_STATE_A_VBUS_ERR; + } else if (iotg->otg.host && + iotg->otg.host->b_hnp_enable && + !iotg->hsm.a_bus_req) { + /* Set HABA to enable hardware assistance to signal + * A-connect after receiver B-disconnect. Hardware + * will then set client mode and enable URE, SLE and + * PCE after the assistance. otg_dummy_irq is used to + * clean these ints when client driver is not resumed. + */ + if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED, + driver_name, iotg->base) != 0) { + dev_dbg(lnw->dev, + "request interrupt %d failed\n", + pdev->irq); + } + + /* set HABA */ + langwell_otg_HABA(1); + iotg->hsm.b_bus_resume = 0; + iotg->hsm.a_aidl_bdis_tmout = 0; + langwell_otg_loc_sof(0); + /* clear PHCD to enable HW timer */ + langwell_otg_phy_low_power(0); + langwell_otg_add_timer(a_aidl_bdis_tmr); + iotg->otg.state = OTG_STATE_A_SUSPEND; + } else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) { + langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); + iotg->otg.state = OTG_STATE_A_WAIT_BCON; + } + break; + case OTG_STATE_A_SUSPEND: + if (iotg->hsm.id) { + langwell_otg_del_timer(a_aidl_bdis_tmr); + langwell_otg_HABA(0); + free_irq(pdev->irq, iotg->base); + iotg->otg.default_a = 0; + iotg->hsm.b_bus_req = 0; + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + set_client_mode(); + langwell_otg_phy_low_power(1); + iotg->otg.state = OTG_STATE_B_IDLE; + langwell_update_transceiver(); + } else if (iotg->hsm.a_bus_req || + iotg->hsm.b_bus_resume) { + langwell_otg_del_timer(a_aidl_bdis_tmr); + langwell_otg_HABA(0); + free_irq(pdev->irq, iotg->base); + iotg->hsm.a_suspend_req = 0; + langwell_otg_loc_sof(1); + iotg->otg.state = OTG_STATE_A_HOST; + } else if (iotg->hsm.a_aidl_bdis_tmout || + iotg->hsm.a_bus_drop) { + langwell_otg_del_timer(a_aidl_bdis_tmr); + langwell_otg_HABA(0); + free_irq(pdev->irq, iotg->base); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_WAIT_VFALL; + } else if (!iotg->hsm.b_conn && iotg->otg.host && + iotg->otg.host->b_hnp_enable) { + langwell_otg_del_timer(a_aidl_bdis_tmr); + langwell_otg_HABA(0); + free_irq(pdev->irq, iotg->base); + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + iotg->hsm.b_bus_suspend = 0; + iotg->hsm.b_bus_suspend_vld = 0; + + /* msleep(200); */ + if (lnw->iotg.start_peripheral) + lnw->iotg.start_peripheral(&lnw->iotg); + else + dev_dbg(lnw->dev, + "client driver not loaded.\n"); + + langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR); + iotg->otg.state = OTG_STATE_A_PERIPHERAL; + break; + } else if (!iotg->hsm.a_vbus_vld) { + langwell_otg_del_timer(a_aidl_bdis_tmr); + langwell_otg_HABA(0); + free_irq(pdev->irq, iotg->base); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver has been removed.\n"); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + langwell_otg_phy_low_power_wait(1); + iotg->otg.state = OTG_STATE_A_VBUS_ERR; + } + break; + case OTG_STATE_A_PERIPHERAL: + if (iotg->hsm.id) { + /* delete hsm timer for b_bus_suspend_tmr */ + del_timer_sync(&lnw->hsm_timer); + iotg->otg.default_a = 0; + iotg->hsm.b_bus_req = 0; + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); + else + dev_dbg(lnw->dev, + "client driver has been removed.\n"); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + set_client_mode(); + langwell_otg_phy_low_power_wait(1); + iotg->otg.state = OTG_STATE_B_IDLE; + langwell_update_transceiver(); + } else if (!iotg->hsm.a_vbus_vld) { + /* delete hsm timer for b_bus_suspend_tmr */ + del_timer_sync(&lnw->hsm_timer); + + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); + else + dev_dbg(lnw->dev, + "client driver has been removed.\n"); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + langwell_otg_phy_low_power_wait(1); + iotg->otg.state = OTG_STATE_A_VBUS_ERR; + } else if (iotg->hsm.a_bus_drop) { + /* delete hsm timer for b_bus_suspend_tmr */ + del_timer_sync(&lnw->hsm_timer); + + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); + else + dev_dbg(lnw->dev, + "client driver has been removed.\n"); + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_WAIT_VFALL; + } else if (iotg->hsm.b_bus_suspend) { + /* delete hsm timer for b_bus_suspend_tmr */ + del_timer_sync(&lnw->hsm_timer); + + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); + else + dev_dbg(lnw->dev, + "client driver has been removed.\n"); + + if (lnw->iotg.start_host) + lnw->iotg.start_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver not loaded.\n"); + langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); + iotg->otg.state = OTG_STATE_A_WAIT_BCON; + } else if (iotg->hsm.b_bus_suspend_tmout) { + u32 val; + val = readl(lnw->iotg.base + CI_PORTSC1); + if (!(val & PORTSC_SUSP)) + break; + + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); + else + dev_dbg(lnw->dev, + "client driver has been removed.\n"); + + if (lnw->iotg.start_host) + lnw->iotg.start_host(&lnw->iotg); + else + dev_dbg(lnw->dev, + "host driver not loaded.\n"); + langwell_otg_add_ktimer(TA_WAIT_BCON_TMR); + iotg->otg.state = OTG_STATE_A_WAIT_BCON; + } + break; + case OTG_STATE_A_VBUS_ERR: + if (iotg->hsm.id) { + iotg->otg.default_a = 0; + iotg->hsm.a_clr_err = 0; + iotg->hsm.a_srp_det = 0; + set_client_mode(); + langwell_otg_phy_low_power(1); + iotg->otg.state = OTG_STATE_B_IDLE; + langwell_update_transceiver(); + } else if (iotg->hsm.a_clr_err) { + iotg->hsm.a_clr_err = 0; + iotg->hsm.a_srp_det = 0; + reset_otg(); + init_hsm(); + if (iotg->otg.state == OTG_STATE_A_IDLE) + langwell_update_transceiver(); + } else { + /* FW will clear PHCD bit when any VBus + * event detected. Reset PHCD to 1 again */ + langwell_otg_phy_low_power(1); + } + break; + case OTG_STATE_A_WAIT_VFALL: + if (iotg->hsm.id) { + iotg->otg.default_a = 0; + set_client_mode(); + langwell_otg_phy_low_power(1); + iotg->otg.state = OTG_STATE_B_IDLE; + langwell_update_transceiver(); + } else if (iotg->hsm.a_bus_req) { + + /* Turn on VBus */ + iotg->otg.set_vbus(&iotg->otg, true); + iotg->hsm.a_wait_vrise_tmout = 0; + langwell_otg_add_timer(a_wait_vrise_tmr); + iotg->otg.state = OTG_STATE_A_WAIT_VRISE; + } else if (!iotg->hsm.a_sess_vld) { + iotg->hsm.a_srp_det = 0; + set_host_mode(); + langwell_otg_phy_low_power(1); + iotg->otg.state = OTG_STATE_A_IDLE; + } + break; + default: + ; + } + + dev_dbg(lnw->dev, "%s: new state = %s\n", __func__, + state_string(iotg->otg.state)); +} + +static ssize_t +show_registers(struct device *_dev, struct device_attribute *attr, char *buf) +{ + struct langwell_otg *lnw = the_transceiver; + char *next; + unsigned size, t; + + next = buf; + size = PAGE_SIZE; + + t = scnprintf(next, size, + "\n" + "USBCMD = 0x%08x\n" + "USBSTS = 0x%08x\n" + "USBINTR = 0x%08x\n" + "ASYNCLISTADDR = 0x%08x\n" + "PORTSC1 = 0x%08x\n" + "HOSTPC1 = 0x%08x\n" + "OTGSC = 0x%08x\n" + "USBMODE = 0x%08x\n", + readl(lnw->iotg.base + 0x30), + readl(lnw->iotg.base + 0x34), + readl(lnw->iotg.base + 0x38), + readl(lnw->iotg.base + 0x48), + readl(lnw->iotg.base + 0x74), + readl(lnw->iotg.base + 0xb4), + readl(lnw->iotg.base + 0xf4), + readl(lnw->iotg.base + 0xf8) + ); + size -= t; + next += t; + + return PAGE_SIZE - size; +} +static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); + +static ssize_t +show_hsm(struct device *_dev, struct device_attribute *attr, char *buf) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + char *next; + unsigned size, t; + + next = buf; + size = PAGE_SIZE; + + if (iotg->otg.host) + iotg->hsm.a_set_b_hnp_en = iotg->otg.host->b_hnp_enable; + + if (iotg->otg.gadget) + iotg->hsm.b_hnp_enable = iotg->otg.gadget->b_hnp_enable; + + t = scnprintf(next, size, + "\n" + "current state = %s\n" + "a_bus_resume = \t%d\n" + "a_bus_suspend = \t%d\n" + "a_conn = \t%d\n" + "a_sess_vld = \t%d\n" + "a_srp_det = \t%d\n" + "a_vbus_vld = \t%d\n" + "b_bus_resume = \t%d\n" + "b_bus_suspend = \t%d\n" + "b_conn = \t%d\n" + "b_se0_srp = \t%d\n" + "b_sess_end = \t%d\n" + "b_sess_vld = \t%d\n" + "id = \t%d\n" + "a_set_b_hnp_en = \t%d\n" + "b_srp_done = \t%d\n" + "b_hnp_enable = \t%d\n" + "a_wait_vrise_tmout = \t%d\n" + "a_wait_bcon_tmout = \t%d\n" + "a_aidl_bdis_tmout = \t%d\n" + "b_ase0_brst_tmout = \t%d\n" + "a_bus_drop = \t%d\n" + "a_bus_req = \t%d\n" + "a_clr_err = \t%d\n" + "a_suspend_req = \t%d\n" + "b_bus_req = \t%d\n" + "b_bus_suspend_tmout = \t%d\n" + "b_bus_suspend_vld = \t%d\n", + state_string(iotg->otg.state), + iotg->hsm.a_bus_resume, + iotg->hsm.a_bus_suspend, + iotg->hsm.a_conn, + iotg->hsm.a_sess_vld, + iotg->hsm.a_srp_det, + iotg->hsm.a_vbus_vld, + iotg->hsm.b_bus_resume, + iotg->hsm.b_bus_suspend, + iotg->hsm.b_conn, + iotg->hsm.b_se0_srp, + iotg->hsm.b_sess_end, + iotg->hsm.b_sess_vld, + iotg->hsm.id, + iotg->hsm.a_set_b_hnp_en, + iotg->hsm.b_srp_done, + iotg->hsm.b_hnp_enable, + iotg->hsm.a_wait_vrise_tmout, + iotg->hsm.a_wait_bcon_tmout, + iotg->hsm.a_aidl_bdis_tmout, + iotg->hsm.b_ase0_brst_tmout, + iotg->hsm.a_bus_drop, + iotg->hsm.a_bus_req, + iotg->hsm.a_clr_err, + iotg->hsm.a_suspend_req, + iotg->hsm.b_bus_req, + iotg->hsm.b_bus_suspend_tmout, + iotg->hsm.b_bus_suspend_vld + ); + size -= t; + next += t; + + return PAGE_SIZE - size; +} +static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL); + +static ssize_t +get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct langwell_otg *lnw = the_transceiver; + char *next; + unsigned size, t; + + next = buf; + size = PAGE_SIZE; + + t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_req); + size -= t; + next += t; + + return PAGE_SIZE - size; +} + +static ssize_t +set_a_bus_req(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + + if (!iotg->otg.default_a) + return -1; + if (count > 2) + return -1; + + if (buf[0] == '0') { + iotg->hsm.a_bus_req = 0; + dev_dbg(lnw->dev, "User request: a_bus_req = 0\n"); + } else if (buf[0] == '1') { + /* If a_bus_drop is TRUE, a_bus_req can't be set */ + if (iotg->hsm.a_bus_drop) + return -1; + iotg->hsm.a_bus_req = 1; + dev_dbg(lnw->dev, "User request: a_bus_req = 1\n"); + } + if (spin_trylock(&lnw->wq_lock)) { + langwell_update_transceiver(); + spin_unlock(&lnw->wq_lock); + } + return count; +} +static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUGO, get_a_bus_req, set_a_bus_req); + +static ssize_t +get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct langwell_otg *lnw = the_transceiver; + char *next; + unsigned size, t; + + next = buf; + size = PAGE_SIZE; + + t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_drop); + size -= t; + next += t; + + return PAGE_SIZE - size; +} + +static ssize_t +set_a_bus_drop(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + + if (!iotg->otg.default_a) + return -1; + if (count > 2) + return -1; + + if (buf[0] == '0') { + iotg->hsm.a_bus_drop = 0; + dev_dbg(lnw->dev, "User request: a_bus_drop = 0\n"); + } else if (buf[0] == '1') { + iotg->hsm.a_bus_drop = 1; + iotg->hsm.a_bus_req = 0; + dev_dbg(lnw->dev, "User request: a_bus_drop = 1\n"); + dev_dbg(lnw->dev, "User request: and a_bus_req = 0\n"); + } + if (spin_trylock(&lnw->wq_lock)) { + langwell_update_transceiver(); + spin_unlock(&lnw->wq_lock); + } + return count; +} +static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUGO, + get_a_bus_drop, set_a_bus_drop); + +static ssize_t +get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct langwell_otg *lnw = the_transceiver; + char *next; + unsigned size, t; + + next = buf; + size = PAGE_SIZE; + + t = scnprintf(next, size, "%d", lnw->iotg.hsm.b_bus_req); + size -= t; + next += t; + + return PAGE_SIZE - size; +} + +static ssize_t +set_b_bus_req(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + + if (iotg->otg.default_a) + return -1; + + if (count > 2) + return -1; + + if (buf[0] == '0') { + iotg->hsm.b_bus_req = 0; + dev_dbg(lnw->dev, "User request: b_bus_req = 0\n"); + } else if (buf[0] == '1') { + iotg->hsm.b_bus_req = 1; + dev_dbg(lnw->dev, "User request: b_bus_req = 1\n"); + } + if (spin_trylock(&lnw->wq_lock)) { + langwell_update_transceiver(); + spin_unlock(&lnw->wq_lock); + } + return count; +} +static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUGO, get_b_bus_req, set_b_bus_req); + +static ssize_t +set_a_clr_err(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + + if (!iotg->otg.default_a) + return -1; + if (count > 2) + return -1; + + if (buf[0] == '1') { + iotg->hsm.a_clr_err = 1; + dev_dbg(lnw->dev, "User request: a_clr_err = 1\n"); + } + if (spin_trylock(&lnw->wq_lock)) { + langwell_update_transceiver(); + spin_unlock(&lnw->wq_lock); + } + return count; +} +static DEVICE_ATTR(a_clr_err, S_IWUGO, NULL, set_a_clr_err); + +static struct attribute *inputs_attrs[] = { + &dev_attr_a_bus_req.attr, + &dev_attr_a_bus_drop.attr, + &dev_attr_b_bus_req.attr, + &dev_attr_a_clr_err.attr, + NULL, +}; + +static struct attribute_group debug_dev_attr_group = { + .name = "inputs", + .attrs = inputs_attrs, +}; + +static int langwell_otg_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + unsigned long resource, len; + void __iomem *base = NULL; + int retval; + u32 val32; + struct langwell_otg *lnw; + char qname[] = "langwell_otg_queue"; + + retval = 0; + dev_dbg(&pdev->dev, "\notg controller is detected.\n"); + if (pci_enable_device(pdev) < 0) { + retval = -ENODEV; + goto done; + } + + lnw = kzalloc(sizeof *lnw, GFP_KERNEL); + if (lnw == NULL) { + retval = -ENOMEM; + goto done; + } + the_transceiver = lnw; + + /* control register: BAR 0 */ + resource = pci_resource_start(pdev, 0); + len = pci_resource_len(pdev, 0); + if (!request_mem_region(resource, len, driver_name)) { + retval = -EBUSY; + goto err; + } + lnw->region = 1; + + base = ioremap_nocache(resource, len); + if (base == NULL) { + retval = -EFAULT; + goto err; + } + lnw->iotg.base = base; + + if (!request_mem_region(USBCFG_ADDR, USBCFG_LEN, driver_name)) { + retval = -EBUSY; + goto err; + } + lnw->cfg_region = 1; + + /* For the SCCB.USBCFG register */ + base = ioremap_nocache(USBCFG_ADDR, USBCFG_LEN); + if (base == NULL) { + retval = -EFAULT; + goto err; + } + lnw->usbcfg = base; + + if (!pdev->irq) { + dev_dbg(&pdev->dev, "No IRQ.\n"); + retval = -ENODEV; + goto err; + } + + lnw->qwork = create_singlethread_workqueue(qname); + if (!lnw->qwork) { + dev_dbg(&pdev->dev, "cannot create workqueue %s\n", qname); + retval = -ENOMEM; + goto err; + } + INIT_WORK(&lnw->work, langwell_otg_work); + + /* OTG common part */ + lnw->dev = &pdev->dev; + lnw->iotg.otg.dev = lnw->dev; + lnw->iotg.otg.label = driver_name; + lnw->iotg.otg.set_host = langwell_otg_set_host; + lnw->iotg.otg.set_peripheral = langwell_otg_set_peripheral; + lnw->iotg.otg.set_power = langwell_otg_set_power; + lnw->iotg.otg.set_vbus = langwell_otg_set_vbus; + lnw->iotg.otg.start_srp = langwell_otg_start_srp; + lnw->iotg.otg.state = OTG_STATE_UNDEFINED; + + if (otg_set_transceiver(&lnw->iotg.otg)) { + dev_dbg(lnw->dev, "can't set transceiver\n"); + retval = -EBUSY; + goto err; + } + + reset_otg(); + init_hsm(); + + spin_lock_init(&lnw->lock); + spin_lock_init(&lnw->wq_lock); + INIT_LIST_HEAD(&active_timers); + retval = langwell_otg_init_timers(&lnw->iotg.hsm); + if (retval) { + dev_dbg(&pdev->dev, "Failed to init timers\n"); + goto err; + } + + init_timer(&lnw->hsm_timer); + ATOMIC_INIT_NOTIFIER_HEAD(&lnw->iotg.iotg_notifier); + + lnw->iotg_notifier.notifier_call = langwell_otg_iotg_notify; + + retval = intel_mid_otg_register_notifier(&lnw->iotg, + &lnw->iotg_notifier); + if (retval) { + dev_dbg(lnw->dev, "Failed to register notifier\n"); + goto err; + } + + if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, + driver_name, lnw) != 0) { + dev_dbg(lnw->dev, "request interrupt %d failed\n", pdev->irq); + retval = -EBUSY; + goto err; + } + + /* enable OTGSC int */ + val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE | + OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU; + writel(val32, lnw->iotg.base + CI_OTGSC); + + retval = device_create_file(&pdev->dev, &dev_attr_registers); + if (retval < 0) { + dev_dbg(lnw->dev, + "Can't register sysfs attribute: %d\n", retval); + goto err; + } + + retval = device_create_file(&pdev->dev, &dev_attr_hsm); + if (retval < 0) { + dev_dbg(lnw->dev, "Can't hsm sysfs attribute: %d\n", retval); + goto err; + } + + retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group); + if (retval < 0) { + dev_dbg(lnw->dev, + "Can't register sysfs attr group: %d\n", retval); + goto err; + } + + if (lnw->iotg.otg.state == OTG_STATE_A_IDLE) + langwell_update_transceiver(); + + return 0; + +err: + if (the_transceiver) + langwell_otg_remove(pdev); +done: + return retval; +} + +static void langwell_otg_remove(struct pci_dev *pdev) +{ + struct langwell_otg *lnw = the_transceiver; + + if (lnw->qwork) { + flush_workqueue(lnw->qwork); + destroy_workqueue(lnw->qwork); + } + intel_mid_otg_unregister_notifier(&lnw->iotg, &lnw->iotg_notifier); + langwell_otg_free_timers(); + + /* disable OTGSC interrupt as OTGSC doesn't change in reset */ + writel(0, lnw->iotg.base + CI_OTGSC); + + if (pdev->irq) + free_irq(pdev->irq, lnw); + if (lnw->usbcfg) + iounmap(lnw->usbcfg); + if (lnw->cfg_region) + release_mem_region(USBCFG_ADDR, USBCFG_LEN); + if (lnw->iotg.base) + iounmap(lnw->iotg.base); + if (lnw->region) + release_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + + otg_set_transceiver(NULL); + pci_disable_device(pdev); + sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group); + device_remove_file(&pdev->dev, &dev_attr_hsm); + device_remove_file(&pdev->dev, &dev_attr_registers); + kfree(lnw); + lnw = NULL; +} + +static void transceiver_suspend(struct pci_dev *pdev) +{ + pci_save_state(pdev); + pci_set_power_state(pdev, PCI_D3hot); + langwell_otg_phy_low_power(1); +} + +static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message) +{ + struct langwell_otg *lnw = the_transceiver; + struct intel_mid_otg_xceiv *iotg = &lnw->iotg; + int ret = 0; + + /* Disbale OTG interrupts */ + langwell_otg_intr(0); + + if (pdev->irq) + free_irq(pdev->irq, lnw); + + /* Prevent more otg_work */ + flush_workqueue(lnw->qwork); + destroy_workqueue(lnw->qwork); + lnw->qwork = NULL; + + /* start actions */ + switch (iotg->otg.state) { + case OTG_STATE_A_WAIT_VFALL: + iotg->otg.state = OTG_STATE_A_IDLE; + case OTG_STATE_A_IDLE: + case OTG_STATE_B_IDLE: + case OTG_STATE_A_VBUS_ERR: + transceiver_suspend(pdev); + break; + case OTG_STATE_A_WAIT_VRISE: + langwell_otg_del_timer(a_wait_vrise_tmr); + iotg->hsm.a_srp_det = 0; + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_IDLE; + transceiver_suspend(pdev); + break; + case OTG_STATE_A_WAIT_BCON: + del_timer_sync(&lnw->hsm_timer); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(&pdev->dev, "host driver has been removed.\n"); + + iotg->hsm.a_srp_det = 0; + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_IDLE; + transceiver_suspend(pdev); + break; + case OTG_STATE_A_HOST: + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(&pdev->dev, "host driver has been removed.\n"); + + iotg->hsm.a_srp_det = 0; + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + + iotg->otg.state = OTG_STATE_A_IDLE; + transceiver_suspend(pdev); + break; + case OTG_STATE_A_SUSPEND: + langwell_otg_del_timer(a_aidl_bdis_tmr); + langwell_otg_HABA(0); + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(lnw->dev, "host driver has been removed.\n"); + iotg->hsm.a_srp_det = 0; + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_IDLE; + transceiver_suspend(pdev); + break; + case OTG_STATE_A_PERIPHERAL: + del_timer_sync(&lnw->hsm_timer); + + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); + else + dev_dbg(&pdev->dev, + "client driver has been removed.\n"); + iotg->hsm.a_srp_det = 0; + + /* Turn off VBus */ + iotg->otg.set_vbus(&iotg->otg, false); + iotg->otg.state = OTG_STATE_A_IDLE; + transceiver_suspend(pdev); + break; + case OTG_STATE_B_HOST: + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(&pdev->dev, "host driver has been removed.\n"); + iotg->hsm.b_bus_req = 0; + iotg->otg.state = OTG_STATE_B_IDLE; + transceiver_suspend(pdev); + break; + case OTG_STATE_B_PERIPHERAL: + if (lnw->iotg.stop_peripheral) + lnw->iotg.stop_peripheral(&lnw->iotg); + else + dev_dbg(&pdev->dev, + "client driver has been removed.\n"); + iotg->otg.state = OTG_STATE_B_IDLE; + transceiver_suspend(pdev); + break; + case OTG_STATE_B_WAIT_ACON: + /* delete hsm timer for b_ase0_brst_tmr */ + del_timer_sync(&lnw->hsm_timer); + + langwell_otg_HAAR(0); + + if (lnw->iotg.stop_host) + lnw->iotg.stop_host(&lnw->iotg); + else + dev_dbg(&pdev->dev, "host driver has been removed.\n"); + iotg->hsm.b_bus_req = 0; + iotg->otg.state = OTG_STATE_B_IDLE; + transceiver_suspend(pdev); + break; + default: + dev_dbg(lnw->dev, "error state before suspend\n"); + break; + } + + return ret; +} + +static void transceiver_resume(struct pci_dev *pdev) +{ + pci_restore_state(pdev); + pci_set_power_state(pdev, PCI_D0); +} + +static int langwell_otg_resume(struct pci_dev *pdev) +{ + struct langwell_otg *lnw = the_transceiver; + int ret = 0; + + transceiver_resume(pdev); + + lnw->qwork = create_singlethread_workqueue("langwell_otg_queue"); + if (!lnw->qwork) { + dev_dbg(&pdev->dev, "cannot create langwell otg workqueuen"); + ret = -ENOMEM; + goto error; + } + + if (request_irq(pdev->irq, otg_irq, IRQF_SHARED, + driver_name, lnw) != 0) { + dev_dbg(&pdev->dev, "request interrupt %d failed\n", pdev->irq); + ret = -EBUSY; + goto error; + } + + /* enable OTG interrupts */ + langwell_otg_intr(1); + + update_hsm(); + + langwell_update_transceiver(); + + return ret; +error: + langwell_otg_intr(0); + transceiver_suspend(pdev); + return ret; +} + +static int __init langwell_otg_init(void) +{ + return pci_register_driver(&otg_pci_driver); +} +module_init(langwell_otg_init); + +static void __exit langwell_otg_cleanup(void) +{ + pci_unregister_driver(&otg_pci_driver); +} +module_exit(langwell_otg_cleanup); diff --git a/include/linux/usb/langwell_otg.h b/include/linux/usb/langwell_otg.h new file mode 100644 index 000000000000..a6562f1d4e2b --- /dev/null +++ b/include/linux/usb/langwell_otg.h @@ -0,0 +1,139 @@ +/* + * Intel Langwell USB OTG transceiver driver + * Copyright (C) 2008, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef __LANGWELL_OTG_H +#define __LANGWELL_OTG_H + +#include + +#define CI_USBCMD 0x30 +# define USBCMD_RST BIT(1) +# define USBCMD_RS BIT(0) +#define CI_USBSTS 0x34 +# define USBSTS_SLI BIT(8) +# define USBSTS_URI BIT(6) +# define USBSTS_PCI BIT(2) +#define CI_PORTSC1 0x74 +# define PORTSC_PP BIT(12) +# define PORTSC_LS (BIT(11) | BIT(10)) +# define PORTSC_SUSP BIT(7) +# define PORTSC_CCS BIT(0) +#define CI_HOSTPC1 0xb4 +# define HOSTPC1_PHCD BIT(22) +#define CI_OTGSC 0xf4 +# define OTGSC_DPIE BIT(30) +# define OTGSC_1MSE BIT(29) +# define OTGSC_BSEIE BIT(28) +# define OTGSC_BSVIE BIT(27) +# define OTGSC_ASVIE BIT(26) +# define OTGSC_AVVIE BIT(25) +# define OTGSC_IDIE BIT(24) +# define OTGSC_DPIS BIT(22) +# define OTGSC_1MSS BIT(21) +# define OTGSC_BSEIS BIT(20) +# define OTGSC_BSVIS BIT(19) +# define OTGSC_ASVIS BIT(18) +# define OTGSC_AVVIS BIT(17) +# define OTGSC_IDIS BIT(16) +# define OTGSC_DPS BIT(14) +# define OTGSC_1MST BIT(13) +# define OTGSC_BSE BIT(12) +# define OTGSC_BSV BIT(11) +# define OTGSC_ASV BIT(10) +# define OTGSC_AVV BIT(9) +# define OTGSC_ID BIT(8) +# define OTGSC_HABA BIT(7) +# define OTGSC_HADP BIT(6) +# define OTGSC_IDPU BIT(5) +# define OTGSC_DP BIT(4) +# define OTGSC_OT BIT(3) +# define OTGSC_HAAR BIT(2) +# define OTGSC_VC BIT(1) +# define OTGSC_VD BIT(0) +# define OTGSC_INTEN_MASK (0x7f << 24) +# define OTGSC_INT_MASK (0x5f << 24) +# define OTGSC_INTSTS_MASK (0x7f << 16) +#define CI_USBMODE 0xf8 +# define USBMODE_CM (BIT(1) | BIT(0)) +# define USBMODE_IDLE 0 +# define USBMODE_DEVICE 0x2 +# define USBMODE_HOST 0x3 +#define USBCFG_ADDR 0xff10801c +#define USBCFG_LEN 4 +# define USBCFG_VBUSVAL BIT(14) +# define USBCFG_AVALID BIT(13) +# define USBCFG_BVALID BIT(12) +# define USBCFG_SESEND BIT(11) + +#define INTR_DUMMY_MASK (USBSTS_SLI | USBSTS_URI | USBSTS_PCI) + +enum langwell_otg_timer_type { + TA_WAIT_VRISE_TMR, + TA_WAIT_BCON_TMR, + TA_AIDL_BDIS_TMR, + TB_ASE0_BRST_TMR, + TB_SE0_SRP_TMR, + TB_SRP_INIT_TMR, + TB_SRP_FAIL_TMR, + TB_BUS_SUSPEND_TMR +}; + +#define TA_WAIT_VRISE 100 +#define TA_WAIT_BCON 30000 +#define TA_AIDL_BDIS 15000 +#define TB_ASE0_BRST 5000 +#define TB_SE0_SRP 2 +#define TB_SRP_INIT 100 +#define TB_SRP_FAIL 5500 +#define TB_BUS_SUSPEND 500 + +struct langwell_otg_timer { + unsigned long expires; /* Number of count increase to timeout */ + unsigned long count; /* Tick counter */ + void (*function)(unsigned long); /* Timeout function */ + unsigned long data; /* Data passed to function */ + struct list_head list; +}; + +struct langwell_otg { + struct intel_mid_otg_xceiv iotg; + struct device *dev; + + void __iomem *usbcfg; /* SCCBUSB config Reg */ + + unsigned region; + unsigned cfg_region; + + struct work_struct work; + struct workqueue_struct *qwork; + struct timer_list hsm_timer; + + spinlock_t lock; + spinlock_t wq_lock; + + struct notifier_block iotg_notifier; +}; + +static inline +struct langwell_otg *mid_xceiv_to_lnw(struct intel_mid_otg_xceiv *iotg) +{ + return container_of(iotg, struct langwell_otg, iotg); +} + +#endif /* __LANGWELL_OTG_H__ */ From 5f81f4b0c0a3db9e46a0e8041d7721117ac41956 Mon Sep 17 00:00:00 2001 From: JiebingLi Date: Thu, 5 Aug 2010 14:17:54 +0100 Subject: [PATCH 002/141] USB: langwell: USB Client driver code cleanup Code cleanup by using standard debugging API's and USB inline functions Signed-off-by: JiebingLi Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/langwell_udc.c | 738 +++++++++++++++--------------- 1 file changed, 375 insertions(+), 363 deletions(-) diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index c2d2a201f84b..8b332dd21dcd 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -19,7 +19,7 @@ /* #undef DEBUG */ -/* #undef VERBOSE */ +/* #undef VERBOSE_DEBUG */ #if defined(CONFIG_USB_LANGWELL_OTG) #define OTG_TRANSCEIVER @@ -77,141 +77,110 @@ langwell_ep0_desc = { /*-------------------------------------------------------------------------*/ /* debugging */ -#ifdef DEBUG -#define DBG(dev, fmt, args...) \ - pr_debug("%s %s: " fmt , driver_name, \ - pci_name(dev->pdev), ## args) -#else -#define DBG(dev, fmt, args...) \ - do { } while (0) -#endif /* DEBUG */ - - -#ifdef VERBOSE -#define VDBG DBG -#else -#define VDBG(dev, fmt, args...) \ - do { } while (0) -#endif /* VERBOSE */ - - -#define ERROR(dev, fmt, args...) \ - pr_err("%s %s: " fmt , driver_name, \ - pci_name(dev->pdev), ## args) - -#define WARNING(dev, fmt, args...) \ - pr_warning("%s %s: " fmt , driver_name, \ - pci_name(dev->pdev), ## args) - -#define INFO(dev, fmt, args...) \ - pr_info("%s %s: " fmt , driver_name, \ - pci_name(dev->pdev), ## args) - - -#ifdef VERBOSE +#ifdef VERBOSE_DEBUG static inline void print_all_registers(struct langwell_udc *dev) { int i; /* Capability Registers */ - printk(KERN_DEBUG "Capability Registers (offset: " - "0x%04x, length: 0x%08x)\n", - CAP_REG_OFFSET, - (u32)sizeof(struct langwell_cap_regs)); - printk(KERN_DEBUG "caplength=0x%02x\n", + dev_dbg(&dev->pdev->dev, + "Capability Registers (offset: 0x%04x, length: 0x%08x)\n", + CAP_REG_OFFSET, (u32)sizeof(struct langwell_cap_regs)); + dev_dbg(&dev->pdev->dev, "caplength=0x%02x\n", readb(&dev->cap_regs->caplength)); - printk(KERN_DEBUG "hciversion=0x%04x\n", + dev_dbg(&dev->pdev->dev, "hciversion=0x%04x\n", readw(&dev->cap_regs->hciversion)); - printk(KERN_DEBUG "hcsparams=0x%08x\n", + dev_dbg(&dev->pdev->dev, "hcsparams=0x%08x\n", readl(&dev->cap_regs->hcsparams)); - printk(KERN_DEBUG "hccparams=0x%08x\n", + dev_dbg(&dev->pdev->dev, "hccparams=0x%08x\n", readl(&dev->cap_regs->hccparams)); - printk(KERN_DEBUG "dciversion=0x%04x\n", + dev_dbg(&dev->pdev->dev, "dciversion=0x%04x\n", readw(&dev->cap_regs->dciversion)); - printk(KERN_DEBUG "dccparams=0x%08x\n", + dev_dbg(&dev->pdev->dev, "dccparams=0x%08x\n", readl(&dev->cap_regs->dccparams)); /* Operational Registers */ - printk(KERN_DEBUG "Operational Registers (offset: " - "0x%04x, length: 0x%08x)\n", - OP_REG_OFFSET, - (u32)sizeof(struct langwell_op_regs)); - printk(KERN_DEBUG "extsts=0x%08x\n", + dev_dbg(&dev->pdev->dev, + "Operational Registers (offset: 0x%04x, length: 0x%08x)\n", + OP_REG_OFFSET, (u32)sizeof(struct langwell_op_regs)); + dev_dbg(&dev->pdev->dev, "extsts=0x%08x\n", readl(&dev->op_regs->extsts)); - printk(KERN_DEBUG "extintr=0x%08x\n", + dev_dbg(&dev->pdev->dev, "extintr=0x%08x\n", readl(&dev->op_regs->extintr)); - printk(KERN_DEBUG "usbcmd=0x%08x\n", + dev_dbg(&dev->pdev->dev, "usbcmd=0x%08x\n", readl(&dev->op_regs->usbcmd)); - printk(KERN_DEBUG "usbsts=0x%08x\n", + dev_dbg(&dev->pdev->dev, "usbsts=0x%08x\n", readl(&dev->op_regs->usbsts)); - printk(KERN_DEBUG "usbintr=0x%08x\n", + dev_dbg(&dev->pdev->dev, "usbintr=0x%08x\n", readl(&dev->op_regs->usbintr)); - printk(KERN_DEBUG "frindex=0x%08x\n", + dev_dbg(&dev->pdev->dev, "frindex=0x%08x\n", readl(&dev->op_regs->frindex)); - printk(KERN_DEBUG "ctrldssegment=0x%08x\n", + dev_dbg(&dev->pdev->dev, "ctrldssegment=0x%08x\n", readl(&dev->op_regs->ctrldssegment)); - printk(KERN_DEBUG "deviceaddr=0x%08x\n", + dev_dbg(&dev->pdev->dev, "deviceaddr=0x%08x\n", readl(&dev->op_regs->deviceaddr)); - printk(KERN_DEBUG "endpointlistaddr=0x%08x\n", + dev_dbg(&dev->pdev->dev, "endpointlistaddr=0x%08x\n", readl(&dev->op_regs->endpointlistaddr)); - printk(KERN_DEBUG "ttctrl=0x%08x\n", + dev_dbg(&dev->pdev->dev, "ttctrl=0x%08x\n", readl(&dev->op_regs->ttctrl)); - printk(KERN_DEBUG "burstsize=0x%08x\n", + dev_dbg(&dev->pdev->dev, "burstsize=0x%08x\n", readl(&dev->op_regs->burstsize)); - printk(KERN_DEBUG "txfilltuning=0x%08x\n", + dev_dbg(&dev->pdev->dev, "txfilltuning=0x%08x\n", readl(&dev->op_regs->txfilltuning)); - printk(KERN_DEBUG "txttfilltuning=0x%08x\n", + dev_dbg(&dev->pdev->dev, "txttfilltuning=0x%08x\n", readl(&dev->op_regs->txttfilltuning)); - printk(KERN_DEBUG "ic_usb=0x%08x\n", + dev_dbg(&dev->pdev->dev, "ic_usb=0x%08x\n", readl(&dev->op_regs->ic_usb)); - printk(KERN_DEBUG "ulpi_viewport=0x%08x\n", + dev_dbg(&dev->pdev->dev, "ulpi_viewport=0x%08x\n", readl(&dev->op_regs->ulpi_viewport)); - printk(KERN_DEBUG "configflag=0x%08x\n", + dev_dbg(&dev->pdev->dev, "configflag=0x%08x\n", readl(&dev->op_regs->configflag)); - printk(KERN_DEBUG "portsc1=0x%08x\n", + dev_dbg(&dev->pdev->dev, "portsc1=0x%08x\n", readl(&dev->op_regs->portsc1)); - printk(KERN_DEBUG "devlc=0x%08x\n", + dev_dbg(&dev->pdev->dev, "devlc=0x%08x\n", readl(&dev->op_regs->devlc)); - printk(KERN_DEBUG "otgsc=0x%08x\n", + dev_dbg(&dev->pdev->dev, "otgsc=0x%08x\n", readl(&dev->op_regs->otgsc)); - printk(KERN_DEBUG "usbmode=0x%08x\n", + dev_dbg(&dev->pdev->dev, "usbmode=0x%08x\n", readl(&dev->op_regs->usbmode)); - printk(KERN_DEBUG "endptnak=0x%08x\n", + dev_dbg(&dev->pdev->dev, "endptnak=0x%08x\n", readl(&dev->op_regs->endptnak)); - printk(KERN_DEBUG "endptnaken=0x%08x\n", + dev_dbg(&dev->pdev->dev, "endptnaken=0x%08x\n", readl(&dev->op_regs->endptnaken)); - printk(KERN_DEBUG "endptsetupstat=0x%08x\n", + dev_dbg(&dev->pdev->dev, "endptsetupstat=0x%08x\n", readl(&dev->op_regs->endptsetupstat)); - printk(KERN_DEBUG "endptprime=0x%08x\n", + dev_dbg(&dev->pdev->dev, "endptprime=0x%08x\n", readl(&dev->op_regs->endptprime)); - printk(KERN_DEBUG "endptflush=0x%08x\n", + dev_dbg(&dev->pdev->dev, "endptflush=0x%08x\n", readl(&dev->op_regs->endptflush)); - printk(KERN_DEBUG "endptstat=0x%08x\n", + dev_dbg(&dev->pdev->dev, "endptstat=0x%08x\n", readl(&dev->op_regs->endptstat)); - printk(KERN_DEBUG "endptcomplete=0x%08x\n", + dev_dbg(&dev->pdev->dev, "endptcomplete=0x%08x\n", readl(&dev->op_regs->endptcomplete)); for (i = 0; i < dev->ep_max / 2; i++) { - printk(KERN_DEBUG "endptctrl[%d]=0x%08x\n", + dev_dbg(&dev->pdev->dev, "endptctrl[%d]=0x%08x\n", i, readl(&dev->op_regs->endptctrl[i])); } } -#endif /* VERBOSE */ +#else + +#define print_all_registers(dev) do { } while (0) + +#endif /* VERBOSE_DEBUG */ /*-------------------------------------------------------------------------*/ -#define DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out") +#define is_in(ep) (((ep)->ep_num == 0) ? ((ep)->dev->ep0_dir == \ + USB_DIR_IN) : (usb_endpoint_dir_in((ep)->desc))) -#define is_in(ep) (((ep)->ep_num == 0) ? ((ep)->dev->ep0_dir == \ - USB_DIR_IN) : ((ep)->desc->bEndpointAddress \ - & USB_DIR_IN) == USB_DIR_IN) +#define DIR_STRING(ep) (is_in(ep) ? "in" : "out") -#ifdef DEBUG -static char *type_string(u8 bmAttributes) +static char *type_string(const struct usb_endpoint_descriptor *desc) { - switch ((bmAttributes) & USB_ENDPOINT_XFERTYPE_MASK) { + switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_BULK: return "bulk"; case USB_ENDPOINT_XFER_ISOC: @@ -222,7 +191,6 @@ static char *type_string(u8 bmAttributes) return "control"; } -#endif /* configure endpoint control registers */ @@ -233,7 +201,7 @@ static void ep_reset(struct langwell_ep *ep, unsigned char ep_num, u32 endptctrl; dev = ep->dev; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); endptctrl = readl(&dev->op_regs->endptctrl[ep_num]); if (is_in) { /* TX */ @@ -250,7 +218,7 @@ static void ep_reset(struct langwell_ep *ep, unsigned char ep_num, writel(endptctrl, &dev->op_regs->endptctrl[ep_num]); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -260,7 +228,7 @@ static void ep0_reset(struct langwell_udc *dev) struct langwell_ep *ep; int i; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); /* ep0 in and out */ for (i = 0; i < 2; i++) { @@ -283,7 +251,7 @@ static void ep0_reset(struct langwell_udc *dev) ep_reset(&dev->ep[0], 0, i, USB_ENDPOINT_XFER_CONTROL); } - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return; } @@ -305,7 +273,7 @@ static int langwell_ep_enable(struct usb_ep *_ep, ep = container_of(_ep, struct langwell_ep, ep); dev = ep->dev; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if (!_ep || !desc || ep->desc || desc->bDescriptorType != USB_DT_ENDPOINT) @@ -326,7 +294,7 @@ static int langwell_ep_enable(struct usb_ep *_ep, * sanity check type, direction, address, and then * initialize the endpoint capabilities fields in dQH */ - switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_CONTROL: ios = 1; break; @@ -395,24 +363,24 @@ static int langwell_ep_enable(struct usb_ep *_ep, ep->ep.maxpacket = max; ep->desc = desc; ep->stopped = 0; - ep->ep_num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + ep->ep_num = usb_endpoint_num(desc); /* ep_type */ - ep->ep_type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + ep->ep_type = usb_endpoint_type(desc); /* configure endpoint control registers */ ep_reset(ep, ep->ep_num, is_in(ep), ep->ep_type); - DBG(dev, "enabled %s (ep%d%s-%s), max %04x\n", + dev_dbg(&dev->pdev->dev, "enabled %s (ep%d%s-%s), max %04x\n", _ep->name, ep->ep_num, - DIR_STRING(desc->bEndpointAddress), - type_string(desc->bmAttributes), + DIR_STRING(ep), + type_string(desc), max); spin_unlock_irqrestore(&dev->lock, flags); done: - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return retval; } @@ -428,7 +396,7 @@ static void done(struct langwell_ep *ep, struct langwell_request *req, struct langwell_dtd *curr_dtd, *next_dtd; int i; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); /* remove the req from ep->queue */ list_del_init(&req->queue); @@ -448,7 +416,8 @@ static void done(struct langwell_ep *ep, struct langwell_request *req, } if (req->mapped) { - dma_unmap_single(&dev->pdev->dev, req->req.dma, req->req.length, + dma_unmap_single(&dev->pdev->dev, + req->req.dma, req->req.length, is_in(ep) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); req->req.dma = DMA_ADDR_INVALID; req->mapped = 0; @@ -458,9 +427,10 @@ static void done(struct langwell_ep *ep, struct langwell_request *req, is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); if (status != -ESHUTDOWN) - DBG(dev, "complete %s, req %p, stat %d, len %u/%u\n", - ep->ep.name, &req->req, status, - req->req.actual, req->req.length); + dev_dbg(&dev->pdev->dev, + "complete %s, req %p, stat %d, len %u/%u\n", + ep->ep.name, &req->req, status, + req->req.actual, req->req.length); /* don't modify queue heads during completion callback */ ep->stopped = 1; @@ -473,7 +443,7 @@ static void done(struct langwell_ep *ep, struct langwell_request *req, spin_lock(&dev->lock); ep->stopped = stopped; - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -511,7 +481,7 @@ static int langwell_ep_disable(struct usb_ep *_ep) ep = container_of(_ep, struct langwell_ep, ep); dev = ep->dev; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if (!_ep || !ep->desc) return -EINVAL; @@ -535,8 +505,8 @@ static int langwell_ep_disable(struct usb_ep *_ep) spin_unlock_irqrestore(&dev->lock, flags); - DBG(dev, "disabled %s\n", _ep->name); - VDBG(dev, "<--- %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "disabled %s\n", _ep->name); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; } @@ -555,7 +525,7 @@ static struct usb_request *langwell_alloc_request(struct usb_ep *_ep, ep = container_of(_ep, struct langwell_ep, ep); dev = ep->dev; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); req = kzalloc(sizeof(*req), gfp_flags); if (!req) @@ -564,8 +534,8 @@ static struct usb_request *langwell_alloc_request(struct usb_ep *_ep, req->req.dma = DMA_ADDR_INVALID; INIT_LIST_HEAD(&req->queue); - VDBG(dev, "alloc request for %s\n", _ep->name); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "alloc request for %s\n", _ep->name); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return &req->req; } @@ -580,7 +550,7 @@ static void langwell_free_request(struct usb_ep *_ep, ep = container_of(_ep, struct langwell_ep, ep); dev = ep->dev; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if (!_ep || !_req) return; @@ -591,8 +561,8 @@ static void langwell_free_request(struct usb_ep *_ep, if (_req) kfree(req); - VDBG(dev, "free request for %s\n", _ep->name); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "free request for %s\n", _ep->name); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -608,23 +578,24 @@ static int queue_dtd(struct langwell_ep *ep, struct langwell_request *req) struct langwell_udc *dev; dev = ep->dev; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); i = ep->ep_num * 2 + is_in(ep); dqh = &dev->ep_dqh[i]; if (ep->ep_num) - VDBG(dev, "%s\n", ep->name); + dev_vdbg(&dev->pdev->dev, "%s\n", ep->name); else /* ep0 */ - VDBG(dev, "%s-%s\n", ep->name, is_in(ep) ? "in" : "out"); + dev_vdbg(&dev->pdev->dev, "%s-%s\n", ep->name, DIR_STRING(ep)); - VDBG(dev, "ep_dqh[%d] addr: 0x%08x\n", i, (u32)&(dev->ep_dqh[i])); + dev_vdbg(&dev->pdev->dev, "ep_dqh[%d] addr: 0x%08x\n", + i, (u32)&(dev->ep_dqh[i])); bit_mask = is_in(ep) ? (1 << (ep->ep_num + 16)) : (1 << (ep->ep_num)); - VDBG(dev, "bit_mask = 0x%08x\n", bit_mask); + dev_vdbg(&dev->pdev->dev, "bit_mask = 0x%08x\n", bit_mask); /* check if the pipe is empty */ if (!(list_empty(&ep->queue))) { @@ -665,14 +636,17 @@ static int queue_dtd(struct langwell_ep *ep, struct langwell_request *req) /* clear active and halt bit */ dtd_status = (u8) ~(DTD_STS_ACTIVE | DTD_STS_HALTED); dqh->dtd_status &= dtd_status; - VDBG(dev, "dqh->dtd_status = 0x%x\n", dqh->dtd_status); + dev_vdbg(&dev->pdev->dev, "dqh->dtd_status = 0x%x\n", dqh->dtd_status); + + /* ensure that updates to the dQH will occure before priming */ + wmb(); /* write 1 to endptprime register to PRIME endpoint */ bit_mask = is_in(ep) ? (1 << (ep->ep_num + 16)) : (1 << ep->ep_num); - VDBG(dev, "endprime bit_mask = 0x%08x\n", bit_mask); + dev_vdbg(&dev->pdev->dev, "endprime bit_mask = 0x%08x\n", bit_mask); writel(bit_mask, &dev->op_regs->endptprime); out: - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; } @@ -687,7 +661,7 @@ static struct langwell_dtd *build_dtd(struct langwell_request *req, int i; dev = req->ep->dev; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); /* the maximum transfer length, up to 16k bytes */ *length = min(req->req.length - req->req.actual, @@ -708,7 +682,7 @@ static struct langwell_dtd *build_dtd(struct langwell_request *req, /* fill in total bytes with transfer size */ dtd->dtd_total = cpu_to_le16(*length); - VDBG(dev, "dtd->dtd_total = %d\n", dtd->dtd_total); + dev_vdbg(&dev->pdev->dev, "dtd->dtd_total = %d\n", dtd->dtd_total); /* set is_last flag if req->req.zero is set or not */ if (req->req.zero) { @@ -722,7 +696,7 @@ static struct langwell_dtd *build_dtd(struct langwell_request *req, *is_last = 0; if (*is_last == 0) - VDBG(dev, "multi-dtd request!\n"); + dev_vdbg(&dev->pdev->dev, "multi-dtd request!\n"); /* set interrupt on complete bit for the last dTD */ if (*is_last && !req->req.no_interrupt) @@ -733,10 +707,12 @@ static struct langwell_dtd *build_dtd(struct langwell_request *req, /* set the active bit of status field to 1 */ dtd->dtd_status = DTD_STS_ACTIVE; - VDBG(dev, "dtd->dtd_status = 0x%02x\n", dtd->dtd_status); + dev_vdbg(&dev->pdev->dev, "dtd->dtd_status = 0x%02x\n", + dtd->dtd_status); - VDBG(dev, "length = %d, dma addr= 0x%08x\n", *length, (int)*dma); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "length = %d, dma addr= 0x%08x\n", + *length, (int)*dma); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return dtd; } @@ -751,7 +727,7 @@ static int req_to_dtd(struct langwell_request *req) dma_addr_t dma; dev = req->ep->dev; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); do { dtd = build_dtd(req, &count, &dma, &is_last); if (dtd == NULL) @@ -773,7 +749,7 @@ static int req_to_dtd(struct langwell_request *req) req->tail = dtd; - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; } @@ -803,9 +779,9 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req, dev = ep->dev; req->ep = ep; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { + if (usb_endpoint_xfer_isoc(ep->desc)) { if (req->req.length > ep->ep.maxpacket) return -EMSGSIZE; is_iso = 1; @@ -818,7 +794,7 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req, if (_req->dma == DMA_ADDR_INVALID) { /* WORKAROUND: WARN_ON(size == 0) */ if (_req->length == 0) { - VDBG(dev, "req->length: 0->1\n"); + dev_vdbg(&dev->pdev->dev, "req->length: 0->1\n"); zlflag = 1; _req->length++; } @@ -827,24 +803,25 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req, _req->buf, _req->length, is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); if (zlflag && (_req->length == 1)) { - VDBG(dev, "req->length: 1->0\n"); + dev_vdbg(&dev->pdev->dev, "req->length: 1->0\n"); zlflag = 0; _req->length = 0; } req->mapped = 1; - VDBG(dev, "req->mapped = 1\n"); + dev_vdbg(&dev->pdev->dev, "req->mapped = 1\n"); } else { dma_sync_single_for_device(&dev->pdev->dev, _req->dma, _req->length, is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); req->mapped = 0; - VDBG(dev, "req->mapped = 0\n"); + dev_vdbg(&dev->pdev->dev, "req->mapped = 0\n"); } - DBG(dev, "%s queue req %p, len %u, buf %p, dma 0x%08llx\n", - _ep->name, - _req, _req->length, _req->buf, (unsigned long long)_req->dma); + dev_dbg(&dev->pdev->dev, + "%s queue req %p, len %u, buf %p, dma 0x%08x\n", + _ep->name, + _req, _req->length, _req->buf, (int)_req->dma); _req->status = -EINPROGRESS; _req->actual = 0; @@ -866,12 +843,12 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req, if (likely(req != NULL)) { list_add_tail(&req->queue, &ep->queue); - VDBG(dev, "list_add_tail() \n"); + dev_vdbg(&dev->pdev->dev, "list_add_tail()\n"); } spin_unlock_irqrestore(&dev->lock, flags); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; } @@ -888,7 +865,7 @@ static int langwell_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) ep = container_of(_ep, struct langwell_ep, ep); dev = ep->dev; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if (!_ep || !ep->desc || !_req) return -EINVAL; @@ -924,7 +901,7 @@ static int langwell_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) /* queue head may be partially complete. */ if (ep->queue.next == &req->queue) { - DBG(dev, "unlink (%s) dma\n", _ep->name); + dev_dbg(&dev->pdev->dev, "unlink (%s) dma\n", _ep->name); _req->status = -ECONNRESET; langwell_ep_fifo_flush(&ep->ep); @@ -963,7 +940,7 @@ done: ep->stopped = stopped; spin_unlock_irqrestore(&dev->lock, flags); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return retval; } @@ -976,7 +953,7 @@ static void ep_set_halt(struct langwell_ep *ep, int value) u32 endptctrl = 0; int ep_num; struct langwell_udc *dev = ep->dev; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); ep_num = ep->ep_num; endptctrl = readl(&dev->op_regs->endptctrl[ep_num]); @@ -1001,7 +978,7 @@ static void ep_set_halt(struct langwell_ep *ep, int value) writel(endptctrl, &dev->op_regs->endptctrl[ep_num]); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -1016,7 +993,7 @@ static int langwell_ep_set_halt(struct usb_ep *_ep, int value) ep = container_of(_ep, struct langwell_ep, ep); dev = ep->dev; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if (!_ep || !ep->desc) return -EINVAL; @@ -1024,8 +1001,7 @@ static int langwell_ep_set_halt(struct usb_ep *_ep, int value) if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; - if (ep->desc && (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_ISOC) + if (usb_endpoint_xfer_isoc(ep->desc)) return -EOPNOTSUPP; spin_lock_irqsave(&dev->lock, flags); @@ -1036,7 +1012,7 @@ static int langwell_ep_set_halt(struct usb_ep *_ep, int value) */ if (!list_empty(&ep->queue) && is_in(ep) && value) { /* IN endpoint FIFO holds bytes */ - DBG(dev, "%s FIFO holds bytes\n", _ep->name); + dev_dbg(&dev->pdev->dev, "%s FIFO holds bytes\n", _ep->name); retval = -EAGAIN; goto done; } @@ -1050,8 +1026,9 @@ static int langwell_ep_set_halt(struct usb_ep *_ep, int value) } done: spin_unlock_irqrestore(&dev->lock, flags); - DBG(dev, "%s %s halt\n", _ep->name, value ? "set" : "clear"); - VDBG(dev, "<--- %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "%s %s halt\n", + _ep->name, value ? "set" : "clear"); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return retval; } @@ -1065,12 +1042,12 @@ static int langwell_ep_set_wedge(struct usb_ep *_ep) ep = container_of(_ep, struct langwell_ep, ep); dev = ep->dev; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if (!_ep || !ep->desc) return -EINVAL; - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return usb_ep_set_halt(_ep); } @@ -1086,15 +1063,16 @@ static void langwell_ep_fifo_flush(struct usb_ep *_ep) ep = container_of(_ep, struct langwell_ep, ep); dev = ep->dev; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if (!_ep || !ep->desc) { - VDBG(dev, "ep or ep->desc is NULL\n"); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "ep or ep->desc is NULL\n"); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return; } - VDBG(dev, "%s-%s fifo flush\n", _ep->name, is_in(ep) ? "in" : "out"); + dev_vdbg(&dev->pdev->dev, "%s-%s fifo flush\n", + _ep->name, DIR_STRING(ep)); /* flush endpoint buffer */ if (ep->ep_num == 0) @@ -1110,14 +1088,14 @@ static void langwell_ep_fifo_flush(struct usb_ep *_ep) writel(flush_bit, &dev->op_regs->endptflush); while (readl(&dev->op_regs->endptflush)) { if (time_after(jiffies, timeout)) { - ERROR(dev, "ep flush timeout\n"); + dev_err(&dev->pdev->dev, "ep flush timeout\n"); goto done; } cpu_relax(); } } while (readl(&dev->op_regs->endptstat) & flush_bit); done: - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -1167,11 +1145,11 @@ static int langwell_get_frame(struct usb_gadget *_gadget) return -ENODEV; dev = container_of(_gadget, struct langwell_udc, gadget); - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); retval = readl(&dev->op_regs->frindex) & FRINDEX_MASK; - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return retval; } @@ -1180,18 +1158,20 @@ static int langwell_get_frame(struct usb_gadget *_gadget) static int langwell_wakeup(struct usb_gadget *_gadget) { struct langwell_udc *dev; - u32 portsc1, devlc; - unsigned long flags; + u32 portsc1, devlc; + unsigned long flags; if (!_gadget) return 0; dev = container_of(_gadget, struct langwell_udc, gadget); - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); - /* Remote Wakeup feature not enabled by host */ - if (!dev->remote_wakeup) + /* remote wakeup feature not enabled by host */ + if (!dev->remote_wakeup) { + dev_info(&dev->pdev->dev, "remote wakeup is disabled\n"); return -ENOTSUPP; + } spin_lock_irqsave(&dev->lock, flags); @@ -1215,13 +1195,12 @@ static int langwell_wakeup(struct usb_gadget *_gadget) /* exit PHY low power suspend */ devlc = readl(&dev->op_regs->devlc); - VDBG(dev, "devlc = 0x%08x\n", devlc); devlc &= ~LPM_PHCD; writel(devlc, &dev->op_regs->devlc); spin_unlock_irqrestore(&dev->lock, flags); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; } @@ -1231,16 +1210,17 @@ static int langwell_vbus_session(struct usb_gadget *_gadget, int is_active) { struct langwell_udc *dev; unsigned long flags; - u32 usbcmd; + u32 usbcmd; if (!_gadget) return -ENODEV; dev = container_of(_gadget, struct langwell_udc, gadget); - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); spin_lock_irqsave(&dev->lock, flags); - VDBG(dev, "VBUS status: %s\n", is_active ? "on" : "off"); + dev_vdbg(&dev->pdev->dev, "VBUS status: %s\n", + is_active ? "on" : "off"); dev->vbus_active = (is_active != 0); if (dev->driver && dev->softconnected && dev->vbus_active) { @@ -1255,7 +1235,7 @@ static int langwell_vbus_session(struct usb_gadget *_gadget, int is_active) spin_unlock_irqrestore(&dev->lock, flags); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; } @@ -1269,15 +1249,15 @@ static int langwell_vbus_draw(struct usb_gadget *_gadget, unsigned mA) return -ENODEV; dev = container_of(_gadget, struct langwell_udc, gadget); - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if (dev->transceiver) { - VDBG(dev, "otg_set_power\n"); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "otg_set_power\n"); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return otg_set_power(dev->transceiver, mA); } - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return -ENOTSUPP; } @@ -1286,15 +1266,15 @@ static int langwell_vbus_draw(struct usb_gadget *_gadget, unsigned mA) static int langwell_pullup(struct usb_gadget *_gadget, int is_on) { struct langwell_udc *dev; - u32 usbcmd; - unsigned long flags; + u32 usbcmd; + unsigned long flags; if (!_gadget) return -ENODEV; dev = container_of(_gadget, struct langwell_udc, gadget); - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); spin_lock_irqsave(&dev->lock, flags); dev->softconnected = (is_on != 0); @@ -1310,7 +1290,7 @@ static int langwell_pullup(struct usb_gadget *_gadget, int is_on) } spin_unlock_irqrestore(&dev->lock, flags); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; } @@ -1351,7 +1331,7 @@ static int langwell_udc_reset(struct langwell_udc *dev) if (!dev) return -EINVAL; - DBG(dev, "---> %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); /* set controller to stop state */ usbcmd = readl(&dev->op_regs->usbcmd); @@ -1367,7 +1347,7 @@ static int langwell_udc_reset(struct langwell_udc *dev) timeout = jiffies + RESET_TIMEOUT; while (readl(&dev->op_regs->usbcmd) & CMD_RST) { if (time_after(jiffies, timeout)) { - ERROR(dev, "device reset timeout\n"); + dev_err(&dev->pdev->dev, "device reset timeout\n"); return -ETIMEDOUT; } cpu_relax(); @@ -1382,7 +1362,7 @@ static int langwell_udc_reset(struct langwell_udc *dev) writel(usbmode, &dev->op_regs->usbmode); usbmode = readl(&dev->op_regs->usbmode); - VDBG(dev, "usbmode=0x%08x\n", usbmode); + dev_vdbg(&dev->pdev->dev, "usbmode=0x%08x\n", usbmode); /* Write-Clear setup status */ writel(0, &dev->op_regs->usbsts); @@ -1400,10 +1380,11 @@ static int langwell_udc_reset(struct langwell_udc *dev) endpointlistaddr &= ENDPOINTLISTADDR_MASK; writel(endpointlistaddr, &dev->op_regs->endpointlistaddr); - VDBG(dev, "dQH base (vir: %p, phy: 0x%08x), endpointlistaddr=0x%08x\n", - dev->ep_dqh, endpointlistaddr, - readl(&dev->op_regs->endpointlistaddr)); - DBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, + "dQH base (vir: %p, phy: 0x%08x), endpointlistaddr=0x%08x\n", + dev->ep_dqh, endpointlistaddr, + readl(&dev->op_regs->endpointlistaddr)); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; } @@ -1415,7 +1396,7 @@ static int eps_reinit(struct langwell_udc *dev) char name[14]; int i; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); /* initialize ep0 */ ep = &dev->ep[0]; @@ -1453,7 +1434,7 @@ static int eps_reinit(struct langwell_udc *dev) ep->dqh = &dev->ep_dqh[i]; } - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; } @@ -1462,7 +1443,7 @@ static int eps_reinit(struct langwell_udc *dev) static void langwell_udc_start(struct langwell_udc *dev) { u32 usbintr, usbcmd; - DBG(dev, "---> %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); /* enable interrupts */ usbintr = INTR_ULPIE /* ULPI */ @@ -1485,7 +1466,7 @@ static void langwell_udc_start(struct langwell_udc *dev) usbcmd |= CMD_RUNSTOP; writel(usbcmd, &dev->op_regs->usbcmd); - DBG(dev, "<--- %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); return; } @@ -1495,7 +1476,7 @@ static void langwell_udc_stop(struct langwell_udc *dev) { u32 usbcmd; - DBG(dev, "---> %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); /* disable all interrupts */ writel(0, &dev->op_regs->usbintr); @@ -1508,7 +1489,7 @@ static void langwell_udc_stop(struct langwell_udc *dev) usbcmd &= ~CMD_RUNSTOP; writel(usbcmd, &dev->op_regs->usbcmd); - DBG(dev, "<--- %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); return; } @@ -1518,7 +1499,7 @@ static void stop_activity(struct langwell_udc *dev, struct usb_gadget_driver *driver) { struct langwell_ep *ep; - DBG(dev, "---> %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); nuke(&dev->ep[0], -ESHUTDOWN); @@ -1533,7 +1514,7 @@ static void stop_activity(struct langwell_udc *dev, spin_lock(&dev->lock); } - DBG(dev, "<--- %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -1659,13 +1640,15 @@ static ssize_t show_langwell_udc(struct device *_dev, "Over-current Change: %s\n" "Port Enable/Disable Change: %s\n" "Port Enabled/Disabled: %s\n" - "Current Connect Status: %s\n\n", + "Current Connect Status: %s\n" + "LPM Suspend Status: %s\n\n", (tmp_reg & PORTS_PR) ? "Reset" : "Not Reset", (tmp_reg & PORTS_SUSP) ? "Suspend " : "Not Suspend", (tmp_reg & PORTS_OCC) ? "Detected" : "No", (tmp_reg & PORTS_PEC) ? "Changed" : "Not Changed", (tmp_reg & PORTS_PE) ? "Enable" : "Not Correct", - (tmp_reg & PORTS_CCS) ? "Attached" : "Not Attached"); + (tmp_reg & PORTS_CCS) ? "Attached" : "Not Attached", + (tmp_reg & PORTS_SLP) ? "LPM L1" : "LPM L0"); size -= t; next += t; @@ -1676,7 +1659,7 @@ static ssize_t show_langwell_udc(struct device *_dev, "Serial Transceiver : %d\n" "Port Speed: %s\n" "Port Force Full Speed Connenct: %s\n" - "PHY Low Power Suspend Clock Disable: %s\n" + "PHY Low Power Suspend Clock: %s\n" "BmAttributes: %d\n\n", LPM_PTS(tmp_reg), (tmp_reg & LPM_STS) ? 1 : 0, @@ -1816,7 +1799,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) if (!dev) return -ENODEV; - DBG(dev, "---> %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); if (dev->driver) return -EBUSY; @@ -1832,7 +1815,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) retval = driver->bind(&dev->gadget); if (retval) { - DBG(dev, "bind to driver %s --> %d\n", + dev_dbg(&dev->pdev->dev, "bind to driver %s --> %d\n", driver->driver.name, retval); dev->driver = NULL; dev->gadget.dev.driver = NULL; @@ -1851,13 +1834,13 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) if (dev->got_irq) langwell_udc_start(dev); - VDBG(dev, "After langwell_udc_start(), print all registers:\n"); -#ifdef VERBOSE + dev_vdbg(&dev->pdev->dev, + "After langwell_udc_start(), print all registers:\n"); print_all_registers(dev); -#endif - INFO(dev, "register driver: %s\n", driver->driver.name); - VDBG(dev, "<--- %s()\n", __func__); + dev_info(&dev->pdev->dev, "register driver: %s\n", + driver->driver.name); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; err_unbind: @@ -1865,7 +1848,7 @@ err_unbind: dev->gadget.dev.driver = NULL; dev->driver = NULL; - DBG(dev, "<--- %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); return retval; } EXPORT_SYMBOL(usb_gadget_register_driver); @@ -1880,7 +1863,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) if (!dev) return -ENODEV; - DBG(dev, "---> %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); if (unlikely(!driver || !driver->bind || !driver->unbind)) return -EINVAL; @@ -1910,8 +1893,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) device_remove_file(&dev->pdev->dev, &dev_attr_function); - INFO(dev, "unregistered driver '%s'\n", driver->driver.name); - DBG(dev, "<--- %s()\n", __func__); + dev_info(&dev->pdev->dev, "unregistered driver '%s'\n", + driver->driver.name); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; } EXPORT_SYMBOL(usb_gadget_unregister_driver); @@ -1930,7 +1914,7 @@ static void setup_tripwire(struct langwell_udc *dev) unsigned long timeout; struct langwell_dqh *dqh; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); /* ep0 OUT dQH */ dqh = &dev->ep_dqh[EP_DIR_OUT]; @@ -1943,7 +1927,7 @@ static void setup_tripwire(struct langwell_udc *dev) timeout = jiffies + SETUPSTAT_TIMEOUT; while (readl(&dev->op_regs->endptsetupstat)) { if (time_after(jiffies, timeout)) { - ERROR(dev, "setup_tripwire timeout\n"); + dev_err(&dev->pdev->dev, "setup_tripwire timeout\n"); break; } cpu_relax(); @@ -1963,7 +1947,7 @@ static void setup_tripwire(struct langwell_udc *dev) usbcmd = readl(&dev->op_regs->usbcmd); writel(usbcmd & ~CMD_SUTW, &dev->op_regs->usbcmd); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -1972,7 +1956,7 @@ static void ep0_stall(struct langwell_udc *dev) { u32 endptctrl; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); /* set TX and RX to stall */ endptctrl = readl(&dev->op_regs->endptctrl[0]); @@ -1983,7 +1967,7 @@ static void ep0_stall(struct langwell_udc *dev) dev->ep0_state = WAIT_FOR_SETUP; dev->ep0_dir = USB_DIR_OUT; - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -1994,7 +1978,7 @@ static int prime_status_phase(struct langwell_udc *dev, int dir) struct langwell_ep *ep; int status = 0; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if (dir == EP_DIR_IN) dev->ep0_dir = USB_DIR_IN; @@ -2019,11 +2003,11 @@ static int prime_status_phase(struct langwell_udc *dev, int dir) return -ENOMEM; if (status) - ERROR(dev, "can't queue ep0 status request\n"); + dev_err(&dev->pdev->dev, "can't queue ep0 status request\n"); list_add_tail(&req->queue, &ep->queue); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return status; } @@ -2032,11 +2016,11 @@ static int prime_status_phase(struct langwell_udc *dev, int dir) static void set_address(struct langwell_udc *dev, u16 value, u16 index, u16 length) { - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); /* save the new address to device struct */ dev->dev_addr = (u8) value; - VDBG(dev, "dev->dev_addr = %d\n", dev->dev_addr); + dev_vdbg(&dev->pdev->dev, "dev->dev_addr = %d\n", dev->dev_addr); /* update usb state */ dev->usb_state = USB_STATE_ADDRESS; @@ -2045,7 +2029,7 @@ static void set_address(struct langwell_udc *dev, u16 value, if (prime_status_phase(dev, EP_DIR_IN)) ep0_stall(dev); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -2054,7 +2038,7 @@ static struct langwell_ep *get_ep_by_windex(struct langwell_udc *dev, u16 wIndex) { struct langwell_ep *ep; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0) return &dev->ep[0]; @@ -2073,7 +2057,7 @@ static struct langwell_ep *get_ep_by_windex(struct langwell_udc *dev, return ep; } - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return NULL; } @@ -2085,7 +2069,7 @@ static int ep_is_stall(struct langwell_ep *ep) u32 endptctrl; int retval; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); endptctrl = readl(&dev->op_regs->endptctrl[ep->ep_num]); if (is_in(ep)) @@ -2093,7 +2077,7 @@ static int ep_is_stall(struct langwell_ep *ep) else retval = endptctrl & EPCTRL_RXS ? 1 : 0; - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return retval; } @@ -2107,7 +2091,7 @@ static void get_status(struct langwell_udc *dev, u8 request_type, u16 value, u16 status_data = 0; /* 16 bits cpu view status data */ int status = 0; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); ep = &dev->ep[0]; @@ -2129,6 +2113,8 @@ static void get_status(struct langwell_udc *dev, u8 request_type, u16 value, status_data = ep_is_stall(epn) << USB_ENDPOINT_HALT; } + dev_dbg(&dev->pdev->dev, "get status data: 0x%04x\n", status_data); + dev->ep0_dir = USB_DIR_IN; /* borrow the per device status_req */ @@ -2150,18 +2136,19 @@ static void get_status(struct langwell_udc *dev, u8 request_type, u16 value, goto stall; if (status) { - ERROR(dev, "response error on GET_STATUS request\n"); + dev_err(&dev->pdev->dev, + "response error on GET_STATUS request\n"); goto stall; } list_add_tail(&req->queue, &ep->queue); dev->ep0_state = DATA_STATE_XMIT; - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return; stall: ep0_stall(dev); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -2173,12 +2160,12 @@ static void handle_setup_packet(struct langwell_udc *dev, u16 wIndex = le16_to_cpu(setup->wIndex); u16 wLength = le16_to_cpu(setup->wLength); - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); /* ep0 fifo flush */ nuke(&dev->ep[0], -ESHUTDOWN); - DBG(dev, "SETUP %02x.%02x v%04x i%04x l%04x\n", + dev_dbg(&dev->pdev->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n", setup->bRequestType, setup->bRequest, wValue, wIndex, wLength); @@ -2197,7 +2184,7 @@ static void handle_setup_packet(struct langwell_udc *dev, /* We process some stardard setup requests here */ switch (setup->bRequest) { case USB_REQ_GET_STATUS: - DBG(dev, "SETUP: USB_REQ_GET_STATUS\n"); + dev_dbg(&dev->pdev->dev, "SETUP: USB_REQ_GET_STATUS\n"); /* get status, DATA and STATUS phase */ if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK)) != (USB_DIR_IN | USB_TYPE_STANDARD)) @@ -2206,7 +2193,7 @@ static void handle_setup_packet(struct langwell_udc *dev, goto end; case USB_REQ_SET_ADDRESS: - DBG(dev, "SETUP: USB_REQ_SET_ADDRESS\n"); + dev_dbg(&dev->pdev->dev, "SETUP: USB_REQ_SET_ADDRESS\n"); /* STATUS phase */ if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE)) @@ -2220,9 +2207,11 @@ static void handle_setup_packet(struct langwell_udc *dev, { int rc = -EOPNOTSUPP; if (setup->bRequest == USB_REQ_SET_FEATURE) - DBG(dev, "SETUP: USB_REQ_SET_FEATURE\n"); + dev_dbg(&dev->pdev->dev, + "SETUP: USB_REQ_SET_FEATURE\n"); else if (setup->bRequest == USB_REQ_CLEAR_FEATURE) - DBG(dev, "SETUP: USB_REQ_CLEAR_FEATURE\n"); + dev_dbg(&dev->pdev->dev, + "SETUP: USB_REQ_CLEAR_FEATURE\n"); if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) == (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) { @@ -2240,8 +2229,8 @@ static void handle_setup_packet(struct langwell_udc *dev, spin_unlock(&dev->lock); rc = langwell_ep_set_halt(&epn->ep, - (setup->bRequest == USB_REQ_SET_FEATURE) - ? 1 : 0); + (setup->bRequest == USB_REQ_SET_FEATURE) + ? 1 : 0); spin_lock(&dev->lock); } else if ((setup->bRequestType & (USB_RECIP_MASK @@ -2274,31 +2263,38 @@ static void handle_setup_packet(struct langwell_udc *dev, } case USB_REQ_GET_DESCRIPTOR: - DBG(dev, "SETUP: USB_REQ_GET_DESCRIPTOR\n"); + dev_dbg(&dev->pdev->dev, + "SETUP: USB_REQ_GET_DESCRIPTOR\n"); goto delegate; case USB_REQ_SET_DESCRIPTOR: - DBG(dev, "SETUP: USB_REQ_SET_DESCRIPTOR unsupported\n"); + dev_dbg(&dev->pdev->dev, + "SETUP: USB_REQ_SET_DESCRIPTOR unsupported\n"); goto delegate; case USB_REQ_GET_CONFIGURATION: - DBG(dev, "SETUP: USB_REQ_GET_CONFIGURATION\n"); + dev_dbg(&dev->pdev->dev, + "SETUP: USB_REQ_GET_CONFIGURATION\n"); goto delegate; case USB_REQ_SET_CONFIGURATION: - DBG(dev, "SETUP: USB_REQ_SET_CONFIGURATION\n"); + dev_dbg(&dev->pdev->dev, + "SETUP: USB_REQ_SET_CONFIGURATION\n"); goto delegate; case USB_REQ_GET_INTERFACE: - DBG(dev, "SETUP: USB_REQ_GET_INTERFACE\n"); + dev_dbg(&dev->pdev->dev, + "SETUP: USB_REQ_GET_INTERFACE\n"); goto delegate; case USB_REQ_SET_INTERFACE: - DBG(dev, "SETUP: USB_REQ_SET_INTERFACE\n"); + dev_dbg(&dev->pdev->dev, + "SETUP: USB_REQ_SET_INTERFACE\n"); goto delegate; case USB_REQ_SYNCH_FRAME: - DBG(dev, "SETUP: USB_REQ_SYNCH_FRAME unsupported\n"); + dev_dbg(&dev->pdev->dev, + "SETUP: USB_REQ_SYNCH_FRAME unsupported\n"); goto delegate; default: @@ -2310,7 +2306,8 @@ delegate: /* DATA phase from gadget, STATUS phase from udc */ dev->ep0_dir = (setup->bRequestType & USB_DIR_IN) ? USB_DIR_IN : USB_DIR_OUT; - VDBG(dev, "dev->ep0_dir = 0x%x, wLength = %d\n", + dev_vdbg(&dev->pdev->dev, + "dev->ep0_dir = 0x%x, wLength = %d\n", dev->ep0_dir, wLength); spin_unlock(&dev->lock); if (dev->driver->setup(&dev->gadget, @@ -2322,7 +2319,8 @@ delegate: } else { /* no DATA phase, IN STATUS phase from gadget */ dev->ep0_dir = USB_DIR_IN; - VDBG(dev, "dev->ep0_dir = 0x%x, wLength = %d\n", + dev_vdbg(&dev->pdev->dev, + "dev->ep0_dir = 0x%x, wLength = %d\n", dev->ep0_dir, wLength); spin_unlock(&dev->lock); if (dev->driver->setup(&dev->gadget, @@ -2334,7 +2332,7 @@ delegate: break; } end: - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return; } @@ -2359,7 +2357,7 @@ static int process_ep_req(struct langwell_udc *dev, int index, td_complete = 0; actual = curr_req->req.length; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); for (i = 0; i < curr_req->dtd_count; i++) { remaining_length = le16_to_cpu(curr_dtd->dtd_total); @@ -2372,10 +2370,12 @@ static int process_ep_req(struct langwell_udc *dev, int index, /* transfers completed successfully */ if (!remaining_length) { td_complete++; - VDBG(dev, "dTD transmitted successfully\n"); + dev_vdbg(&dev->pdev->dev, + "dTD transmitted successfully\n"); } else { if (dir) { - VDBG(dev, "TX dTD remains data\n"); + dev_vdbg(&dev->pdev->dev, + "TX dTD remains data\n"); retval = -EPROTO; break; @@ -2387,27 +2387,32 @@ static int process_ep_req(struct langwell_udc *dev, int index, } else { /* transfers completed with errors */ if (dtd_status & DTD_STS_ACTIVE) { - DBG(dev, "request not completed\n"); + dev_dbg(&dev->pdev->dev, + "dTD status ACTIVE dQH[%d]\n", index); retval = 1; return retval; } else if (dtd_status & DTD_STS_HALTED) { - ERROR(dev, "dTD error %08x dQH[%d]\n", - dtd_status, index); + dev_err(&dev->pdev->dev, + "dTD error %08x dQH[%d]\n", + dtd_status, index); /* clear the errors and halt condition */ curr_dqh->dtd_status = 0; retval = -EPIPE; break; } else if (dtd_status & DTD_STS_DBE) { - DBG(dev, "data buffer (overflow) error\n"); + dev_dbg(&dev->pdev->dev, + "data buffer (overflow) error\n"); retval = -EPROTO; break; } else if (dtd_status & DTD_STS_TRE) { - DBG(dev, "transaction(ISO) error\n"); + dev_dbg(&dev->pdev->dev, + "transaction(ISO) error\n"); retval = -EILSEQ; break; } else - ERROR(dev, "unknown error (0x%x)!\n", - dtd_status); + dev_err(&dev->pdev->dev, + "unknown error (0x%x)!\n", + dtd_status); } if (i != curr_req->dtd_count - 1) @@ -2420,7 +2425,7 @@ static int process_ep_req(struct langwell_udc *dev, int index, curr_req->req.actual = actual; - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; } @@ -2430,7 +2435,7 @@ static void ep0_req_complete(struct langwell_udc *dev, struct langwell_ep *ep0, struct langwell_request *req) { u32 new_addr; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if (dev->usb_state == USB_STATE_ADDRESS) { /* set the new address */ @@ -2438,7 +2443,7 @@ static void ep0_req_complete(struct langwell_udc *dev, writel(new_addr << USBADR_SHIFT, &dev->op_regs->deviceaddr); new_addr = USBADR(readl(&dev->op_regs->deviceaddr)); - VDBG(dev, "new_addr = %d\n", new_addr); + dev_vdbg(&dev->pdev->dev, "new_addr = %d\n", new_addr); } done(ep0, req, 0); @@ -2458,14 +2463,14 @@ static void ep0_req_complete(struct langwell_udc *dev, dev->ep0_state = WAIT_FOR_SETUP; break; case WAIT_FOR_SETUP: - ERROR(dev, "unexpect ep0 packets\n"); + dev_err(&dev->pdev->dev, "unexpect ep0 packets\n"); break; default: ep0_stall(dev); break; } - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -2477,16 +2482,17 @@ static void handle_trans_complete(struct langwell_udc *dev) struct langwell_ep *epn; struct langwell_request *curr_req, *temp_req; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); complete_bits = readl(&dev->op_regs->endptcomplete); - VDBG(dev, "endptcomplete register: 0x%08x\n", complete_bits); + dev_vdbg(&dev->pdev->dev, "endptcomplete register: 0x%08x\n", + complete_bits); /* Write-Clear the bits in endptcomplete register */ writel(complete_bits, &dev->op_regs->endptcomplete); if (!complete_bits) { - DBG(dev, "complete_bits = 0\n"); + dev_dbg(&dev->pdev->dev, "complete_bits = 0\n"); goto done; } @@ -2506,23 +2512,25 @@ static void handle_trans_complete(struct langwell_udc *dev) epn = &dev->ep[i]; if (epn->name == NULL) { - WARNING(dev, "invalid endpoint\n"); + dev_warn(&dev->pdev->dev, "invalid endpoint\n"); continue; } if (i < 2) /* ep0 in and out */ - DBG(dev, "%s-%s transfer completed\n", + dev_dbg(&dev->pdev->dev, "%s-%s transfer completed\n", epn->name, is_in(epn) ? "in" : "out"); else - DBG(dev, "%s transfer completed\n", epn->name); + dev_dbg(&dev->pdev->dev, "%s transfer completed\n", + epn->name); /* process the req queue until an uncomplete request */ list_for_each_entry_safe(curr_req, temp_req, &epn->queue, queue) { status = process_ep_req(dev, i, curr_req); - VDBG(dev, "%s req status: %d\n", epn->name, status); + dev_vdbg(&dev->pdev->dev, "%s req status: %d\n", + epn->name, status); if (status) break; @@ -2540,7 +2548,7 @@ static void handle_trans_complete(struct langwell_udc *dev) } } done: - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return; } @@ -2551,14 +2559,14 @@ static void handle_port_change(struct langwell_udc *dev) u32 portsc1, devlc; u32 speed; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if (dev->bus_reset) dev->bus_reset = 0; portsc1 = readl(&dev->op_regs->portsc1); devlc = readl(&dev->op_regs->devlc); - VDBG(dev, "portsc1 = 0x%08x, devlc = 0x%08x\n", + dev_vdbg(&dev->pdev->dev, "portsc1 = 0x%08x, devlc = 0x%08x\n", portsc1, devlc); /* bus reset is finished */ @@ -2579,25 +2587,22 @@ static void handle_port_change(struct langwell_udc *dev) dev->gadget.speed = USB_SPEED_UNKNOWN; break; } - VDBG(dev, "speed = %d, dev->gadget.speed = %d\n", + dev_vdbg(&dev->pdev->dev, + "speed = %d, dev->gadget.speed = %d\n", speed, dev->gadget.speed); } /* LPM L0 to L1 */ if (dev->lpm && dev->lpm_state == LPM_L0) if (portsc1 & PORTS_SUSP && portsc1 & PORTS_SLP) { - INFO(dev, "LPM L0 to L1\n"); - dev->lpm_state = LPM_L1; + dev_info(&dev->pdev->dev, "LPM L0 to L1\n"); + dev->lpm_state = LPM_L1; } /* LPM L1 to L0, force resume or remote wakeup finished */ if (dev->lpm && dev->lpm_state == LPM_L1) if (!(portsc1 & PORTS_SUSP)) { - if (portsc1 & PORTS_SLP) - INFO(dev, "LPM L1 to L0, force resume\n"); - else - INFO(dev, "LPM L1 to L0, remote wakeup\n"); - + dev_info(&dev->pdev->dev, "LPM L1 to L0\n"); dev->lpm_state = LPM_L0; } @@ -2605,7 +2610,7 @@ static void handle_port_change(struct langwell_udc *dev) if (!dev->resume_state) dev->usb_state = USB_STATE_DEFAULT; - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -2617,7 +2622,7 @@ static void handle_usb_reset(struct langwell_udc *dev) endptcomplete; unsigned long timeout; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); /* Write-Clear the device address */ deviceaddr = readl(&dev->op_regs->deviceaddr); @@ -2651,7 +2656,7 @@ static void handle_usb_reset(struct langwell_udc *dev) timeout = jiffies + PRIME_TIMEOUT; while (readl(&dev->op_regs->endptprime)) { if (time_after(jiffies, timeout)) { - ERROR(dev, "USB reset timeout\n"); + dev_err(&dev->pdev->dev, "USB reset timeout\n"); break; } cpu_relax(); @@ -2661,7 +2666,7 @@ static void handle_usb_reset(struct langwell_udc *dev) writel((u32) ~0, &dev->op_regs->endptflush); if (readl(&dev->op_regs->portsc1) & PORTS_PR) { - VDBG(dev, "USB bus reset\n"); + dev_vdbg(&dev->pdev->dev, "USB bus reset\n"); /* bus is reseting */ dev->bus_reset = 1; @@ -2669,7 +2674,7 @@ static void handle_usb_reset(struct langwell_udc *dev) stop_activity(dev, dev->driver); dev->usb_state = USB_STATE_DEFAULT; } else { - VDBG(dev, "device controller reset\n"); + dev_vdbg(&dev->pdev->dev, "device controller reset\n"); /* controller reset */ langwell_udc_reset(dev); @@ -2691,7 +2696,7 @@ static void handle_usb_reset(struct langwell_udc *dev) dev->lotg->hsm.b_hnp_enable = 0; #endif - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -2699,7 +2704,7 @@ static void handle_usb_reset(struct langwell_udc *dev) static void handle_bus_suspend(struct langwell_udc *dev) { u32 devlc; - DBG(dev, "---> %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); dev->resume_state = dev->usb_state; dev->usb_state = USB_STATE_SUSPENDED; @@ -2733,31 +2738,30 @@ static void handle_bus_suspend(struct langwell_udc *dev) spin_unlock(&dev->lock); dev->driver->suspend(&dev->gadget); spin_lock(&dev->lock); - DBG(dev, "suspend %s\n", dev->driver->driver.name); + dev_dbg(&dev->pdev->dev, "suspend %s\n", + dev->driver->driver.name); } } /* enter PHY low power suspend */ devlc = readl(&dev->op_regs->devlc); - VDBG(dev, "devlc = 0x%08x\n", devlc); devlc |= LPM_PHCD; writel(devlc, &dev->op_regs->devlc); - DBG(dev, "<--- %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); } static void handle_bus_resume(struct langwell_udc *dev) { u32 devlc; - DBG(dev, "---> %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); dev->usb_state = dev->resume_state; dev->resume_state = 0; /* exit PHY low power suspend */ devlc = readl(&dev->op_regs->devlc); - VDBG(dev, "devlc = 0x%08x\n", devlc); devlc &= ~LPM_PHCD; writel(devlc, &dev->op_regs->devlc); @@ -2772,11 +2776,12 @@ static void handle_bus_resume(struct langwell_udc *dev) spin_unlock(&dev->lock); dev->driver->resume(&dev->gadget); spin_lock(&dev->lock); - DBG(dev, "resume %s\n", dev->driver->driver.name); + dev_dbg(&dev->pdev->dev, "resume %s\n", + dev->driver->driver.name); } } - DBG(dev, "<--- %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -2789,11 +2794,11 @@ static irqreturn_t langwell_irq(int irq, void *_dev) irq_sts, portsc1; - VDBG(dev, "---> %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); if (dev->stopped) { - VDBG(dev, "handle IRQ_NONE\n"); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "handle IRQ_NONE\n"); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return IRQ_NONE; } @@ -2806,12 +2811,13 @@ static irqreturn_t langwell_irq(int irq, void *_dev) usbintr = readl(&dev->op_regs->usbintr); irq_sts = usbsts & usbintr; - VDBG(dev, "usbsts = 0x%08x, usbintr = 0x%08x, irq_sts = 0x%08x\n", + dev_vdbg(&dev->pdev->dev, + "usbsts = 0x%08x, usbintr = 0x%08x, irq_sts = 0x%08x\n", usbsts, usbintr, irq_sts); if (!irq_sts) { - VDBG(dev, "handle IRQ_NONE\n"); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "handle IRQ_NONE\n"); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); spin_unlock(&dev->lock); return IRQ_NONE; } @@ -2827,12 +2833,13 @@ static irqreturn_t langwell_irq(int irq, void *_dev) /* USB interrupt */ if (irq_sts & STS_UI) { - VDBG(dev, "USB interrupt\n"); + dev_vdbg(&dev->pdev->dev, "USB interrupt\n"); /* setup packet received from ep0 */ if (readl(&dev->op_regs->endptsetupstat) & EP0SETUPSTAT_MASK) { - VDBG(dev, "USB SETUP packet received interrupt\n"); + dev_vdbg(&dev->pdev->dev, + "USB SETUP packet received interrupt\n"); /* setup tripwire semaphone */ setup_tripwire(dev); handle_setup_packet(dev, &dev->local_setup_buff); @@ -2840,7 +2847,8 @@ static irqreturn_t langwell_irq(int irq, void *_dev) /* USB transfer completion */ if (readl(&dev->op_regs->endptcomplete)) { - VDBG(dev, "USB transfer completion interrupt\n"); + dev_vdbg(&dev->pdev->dev, + "USB transfer completion interrupt\n"); handle_trans_complete(dev); } } @@ -2848,36 +2856,36 @@ static irqreturn_t langwell_irq(int irq, void *_dev) /* SOF received interrupt (for ISO transfer) */ if (irq_sts & STS_SRI) { /* FIXME */ - /* VDBG(dev, "SOF received interrupt\n"); */ + /* dev_vdbg(&dev->pdev->dev, "SOF received interrupt\n"); */ } /* port change detect interrupt */ if (irq_sts & STS_PCI) { - VDBG(dev, "port change detect interrupt\n"); + dev_vdbg(&dev->pdev->dev, "port change detect interrupt\n"); handle_port_change(dev); } /* suspend interrrupt */ if (irq_sts & STS_SLI) { - VDBG(dev, "suspend interrupt\n"); + dev_vdbg(&dev->pdev->dev, "suspend interrupt\n"); handle_bus_suspend(dev); } /* USB reset interrupt */ if (irq_sts & STS_URI) { - VDBG(dev, "USB reset interrupt\n"); + dev_vdbg(&dev->pdev->dev, "USB reset interrupt\n"); handle_usb_reset(dev); } /* USB error or system error interrupt */ if (irq_sts & (STS_UEI | STS_SEI)) { /* FIXME */ - WARNING(dev, "error IRQ, irq_sts: %x\n", irq_sts); + dev_warn(&dev->pdev->dev, "error IRQ, irq_sts: %x\n", irq_sts); } spin_unlock(&dev->lock); - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return IRQ_HANDLED; } @@ -2889,11 +2897,11 @@ static void gadget_release(struct device *_dev) { struct langwell_udc *dev = the_controller; - DBG(dev, "---> %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); complete(dev->done); - DBG(dev, "<--- %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); kfree(dev); } @@ -2906,7 +2914,7 @@ static void langwell_udc_remove(struct pci_dev *pdev) DECLARE_COMPLETION(done); BUG_ON(dev->driver); - DBG(dev, "---> %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); dev->done = &done; @@ -2949,8 +2957,8 @@ static void langwell_udc_remove(struct pci_dev *pdev) dev->cap_regs = NULL; - INFO(dev, "unbind\n"); - DBG(dev, "<--- %s()\n", __func__); + dev_info(&dev->pdev->dev, "unbind\n"); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); device_unregister(&dev->gadget.dev); device_remove_file(&pdev->dev, &dev_attr_langwell_udc); @@ -2997,7 +3005,7 @@ static int langwell_udc_probe(struct pci_dev *pdev, spin_lock_init(&dev->lock); dev->pdev = pdev; - DBG(dev, "---> %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); #ifdef OTG_TRANSCEIVER /* PCI device is already enabled by otg_transceiver driver */ @@ -3022,7 +3030,7 @@ static int langwell_udc_probe(struct pci_dev *pdev, resource = pci_resource_start(pdev, 0); len = pci_resource_len(pdev, 0); if (!request_mem_region(resource, len, driver_name)) { - ERROR(dev, "controller already in use\n"); + dev_err(&dev->pdev->dev, "controller already in use\n"); retval = -EBUSY; goto error; } @@ -3031,33 +3039,35 @@ static int langwell_udc_probe(struct pci_dev *pdev, base = ioremap_nocache(resource, len); #endif if (base == NULL) { - ERROR(dev, "can't map memory\n"); + dev_err(&dev->pdev->dev, "can't map memory\n"); retval = -EFAULT; goto error; } dev->cap_regs = (struct langwell_cap_regs __iomem *) base; - VDBG(dev, "dev->cap_regs: %p\n", dev->cap_regs); + dev_vdbg(&dev->pdev->dev, "dev->cap_regs: %p\n", dev->cap_regs); dev->op_regs = (struct langwell_op_regs __iomem *) (base + OP_REG_OFFSET); - VDBG(dev, "dev->op_regs: %p\n", dev->op_regs); + dev_vdbg(&dev->pdev->dev, "dev->op_regs: %p\n", dev->op_regs); /* irq setup after old hardware is cleaned up */ if (!pdev->irq) { - ERROR(dev, "No IRQ. Check PCI setup!\n"); + dev_err(&dev->pdev->dev, "No IRQ. Check PCI setup!\n"); retval = -ENODEV; goto error; } #ifndef OTG_TRANSCEIVER - INFO(dev, "irq %d, io mem: 0x%08lx, len: 0x%08lx, pci mem 0x%p\n", + dev_info(&dev->pdev->dev, + "irq %d, io mem: 0x%08lx, len: 0x%08lx, pci mem 0x%p\n", pdev->irq, resource, len, base); /* enables bus-mastering for device dev */ pci_set_master(pdev); if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED, driver_name, dev) != 0) { - ERROR(dev, "request interrupt %d failed\n", pdev->irq); + dev_err(&dev->pdev->dev, + "request interrupt %d failed\n", pdev->irq); retval = -EBUSY; goto error; } @@ -3071,32 +3081,34 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->lpm = (readl(&dev->cap_regs->hccparams) & HCC_LEN) ? 1 : 0; dev->dciversion = readw(&dev->cap_regs->dciversion); dev->devcap = (readl(&dev->cap_regs->dccparams) & DEVCAP) ? 1 : 0; - VDBG(dev, "dev->lpm: %d\n", dev->lpm); - VDBG(dev, "dev->dciversion: 0x%04x\n", dev->dciversion); - VDBG(dev, "dccparams: 0x%08x\n", readl(&dev->cap_regs->dccparams)); - VDBG(dev, "dev->devcap: %d\n", dev->devcap); + dev_vdbg(&dev->pdev->dev, "dev->lpm: %d\n", dev->lpm); + dev_vdbg(&dev->pdev->dev, "dev->dciversion: 0x%04x\n", + dev->dciversion); + dev_vdbg(&dev->pdev->dev, "dccparams: 0x%08x\n", + readl(&dev->cap_regs->dccparams)); + dev_vdbg(&dev->pdev->dev, "dev->devcap: %d\n", dev->devcap); if (!dev->devcap) { - ERROR(dev, "can't support device mode\n"); + dev_err(&dev->pdev->dev, "can't support device mode\n"); retval = -ENODEV; goto error; } /* a pair of endpoints (out/in) for each address */ dev->ep_max = DEN(readl(&dev->cap_regs->dccparams)) * 2; - VDBG(dev, "dev->ep_max: %d\n", dev->ep_max); + dev_vdbg(&dev->pdev->dev, "dev->ep_max: %d\n", dev->ep_max); /* allocate endpoints memory */ dev->ep = kzalloc(sizeof(struct langwell_ep) * dev->ep_max, GFP_KERNEL); if (!dev->ep) { - ERROR(dev, "allocate endpoints memory failed\n"); + dev_err(&dev->pdev->dev, "allocate endpoints memory failed\n"); retval = -ENOMEM; goto error; } /* allocate device dQH memory */ size = dev->ep_max * sizeof(struct langwell_dqh); - VDBG(dev, "orig size = %d\n", size); + dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size); if (size < DQH_ALIGNMENT) size = DQH_ALIGNMENT; else if ((size % DQH_ALIGNMENT) != 0) { @@ -3106,17 +3118,18 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->ep_dqh = dma_alloc_coherent(&pdev->dev, size, &dev->ep_dqh_dma, GFP_KERNEL); if (!dev->ep_dqh) { - ERROR(dev, "allocate dQH memory failed\n"); + dev_err(&dev->pdev->dev, "allocate dQH memory failed\n"); retval = -ENOMEM; goto error; } dev->ep_dqh_size = size; - VDBG(dev, "ep_dqh_size = %d\n", dev->ep_dqh_size); + dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size); /* initialize ep0 status request structure */ dev->status_req = kzalloc(sizeof(struct langwell_request), GFP_KERNEL); if (!dev->status_req) { - ERROR(dev, "allocate status_req memory failed\n"); + dev_err(&dev->pdev->dev, + "allocate status_req memory failed\n"); retval = -ENOMEM; goto error; } @@ -3174,18 +3187,20 @@ static int langwell_udc_probe(struct pci_dev *pdev, } /* done */ - INFO(dev, "%s\n", driver_desc); - INFO(dev, "irq %d, pci mem %p\n", pdev->irq, base); - INFO(dev, "Driver version: " DRIVER_VERSION "\n"); - INFO(dev, "Support (max) %d endpoints\n", dev->ep_max); - INFO(dev, "Device interface version: 0x%04x\n", dev->dciversion); - INFO(dev, "Controller mode: %s\n", dev->devcap ? "Device" : "Host"); - INFO(dev, "Support USB LPM: %s\n", dev->lpm ? "Yes" : "No"); + dev_info(&dev->pdev->dev, "%s\n", driver_desc); + dev_info(&dev->pdev->dev, "irq %d, pci mem %p\n", pdev->irq, base); + dev_info(&dev->pdev->dev, "Driver version: " DRIVER_VERSION "\n"); + dev_info(&dev->pdev->dev, "Support (max) %d endpoints\n", dev->ep_max); + dev_info(&dev->pdev->dev, "Device interface version: 0x%04x\n", + dev->dciversion); + dev_info(&dev->pdev->dev, "Controller mode: %s\n", + dev->devcap ? "Device" : "Host"); + dev_info(&dev->pdev->dev, "Support USB LPM: %s\n", + dev->lpm ? "Yes" : "No"); - VDBG(dev, "After langwell_udc_probe(), print all registers:\n"); -#ifdef VERBOSE + dev_vdbg(&dev->pdev->dev, + "After langwell_udc_probe(), print all registers:\n"); print_all_registers(dev); -#endif the_controller = dev; @@ -3197,12 +3212,12 @@ static int langwell_udc_probe(struct pci_dev *pdev, if (retval) goto error; - VDBG(dev, "<--- %s()\n", __func__); + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; error: if (dev) { - DBG(dev, "<--- %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); langwell_udc_remove(pdev); } @@ -3216,7 +3231,7 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) struct langwell_udc *dev = the_controller; u32 devlc; - DBG(dev, "---> %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); /* disable interrupt and set controller to stop state */ langwell_udc_stop(dev); @@ -3226,7 +3241,6 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) free_irq(pdev->irq, dev); dev->got_irq = 0; - /* save PCI state */ pci_save_state(pdev); @@ -3235,11 +3249,10 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) /* enter PHY low power suspend */ devlc = readl(&dev->op_regs->devlc); - VDBG(dev, "devlc = 0x%08x\n", devlc); devlc |= LPM_PHCD; writel(devlc, &dev->op_regs->devlc); - DBG(dev, "<--- %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; } @@ -3250,11 +3263,10 @@ static int langwell_udc_resume(struct pci_dev *pdev) struct langwell_udc *dev = the_controller; u32 devlc; - DBG(dev, "---> %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); /* exit PHY low power suspend */ devlc = readl(&dev->op_regs->devlc); - VDBG(dev, "devlc = 0x%08x\n", devlc); devlc &= ~LPM_PHCD; writel(devlc, &dev->op_regs->devlc); @@ -3265,10 +3277,11 @@ static int langwell_udc_resume(struct pci_dev *pdev) pci_restore_state(pdev); /* enable IRQ handler */ - if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED, driver_name, dev) - != 0) { - ERROR(dev, "request interrupt %d failed\n", pdev->irq); - return -1; + if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED, + driver_name, dev) != 0) { + dev_err(&dev->pdev->dev, "request interrupt %d failed\n", + pdev->irq); + return -EBUSY; } dev->got_irq = 1; @@ -3290,7 +3303,7 @@ static int langwell_udc_resume(struct pci_dev *pdev) dev->ep0_state = WAIT_FOR_SETUP; dev->ep0_dir = USB_DIR_OUT; - DBG(dev, "<--- %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; } @@ -3301,15 +3314,15 @@ static void langwell_udc_shutdown(struct pci_dev *pdev) struct langwell_udc *dev = the_controller; u32 usbmode; - DBG(dev, "---> %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); /* reset controller mode to IDLE */ usbmode = readl(&dev->op_regs->usbmode); - DBG(dev, "usbmode = 0x%08x\n", usbmode); + dev_dbg(&dev->pdev->dev, "usbmode = 0x%08x\n", usbmode); usbmode &= (~3 | MODE_IDLE); writel(usbmode, &dev->op_regs->usbmode); - DBG(dev, "<--- %s()\n", __func__); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); } /*-------------------------------------------------------------------------*/ @@ -3324,7 +3337,6 @@ static const struct pci_device_id pci_ids[] = { { }, { /* end: all zeroes */ } }; - MODULE_DEVICE_TABLE(pci, pci_ids); @@ -3343,12 +3355,6 @@ static struct pci_driver langwell_pci_driver = { }; -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR("Xiaochen Shen "); -MODULE_VERSION(DRIVER_VERSION); -MODULE_LICENSE("GPL"); - - static int __init init(void) { #ifdef OTG_TRANSCEIVER @@ -3370,3 +3376,9 @@ static void __exit cleanup(void) } module_exit(cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Xiaochen Shen "); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); + From 3eed298ffa94d77901cfda269c4368de83d133fb Mon Sep 17 00:00:00 2001 From: JiebingLi Date: Thu, 5 Aug 2010 14:18:05 +0100 Subject: [PATCH 003/141] USB: langwell: USB Client Endpoint initialization Endpoint software structure initialization Signed-off-by: JiebingLi Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/langwell_udc.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index 8b332dd21dcd..599ad8a1f5fe 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -242,11 +242,13 @@ static void ep0_reset(struct langwell_udc *dev) ep->dqh->dqh_ios = 1; ep->dqh->dqh_mpl = EP0_MAX_PKT_SIZE; - /* FIXME: enable ep0-in HW zero length termination select */ + /* enable ep0-in HW zero length termination select */ if (is_in(ep)) ep->dqh->dqh_zlt = 0; ep->dqh->dqh_mult = 0; + ep->dqh->dtd_next = DTD_TERM; + /* configure ep0 control registers */ ep_reset(&dev->ep[0], 0, i, USB_ENDPOINT_XFER_CONTROL); } @@ -268,7 +270,7 @@ static int langwell_ep_enable(struct usb_ep *_ep, struct langwell_ep *ep; u16 max = 0; unsigned long flags; - int retval = 0; + int i, retval = 0; unsigned char zlt, ios = 0, mult = 0; ep = container_of(_ep, struct langwell_ep, ep); @@ -354,12 +356,6 @@ static int langwell_ep_enable(struct usb_ep *_ep, spin_lock_irqsave(&dev->lock, flags); - /* configure endpoint capabilities in dQH */ - ep->dqh->dqh_ios = ios; - ep->dqh->dqh_mpl = cpu_to_le16(max); - ep->dqh->dqh_zlt = zlt; - ep->dqh->dqh_mult = mult; - ep->ep.maxpacket = max; ep->desc = desc; ep->stopped = 0; @@ -371,6 +367,15 @@ static int langwell_ep_enable(struct usb_ep *_ep, /* configure endpoint control registers */ ep_reset(ep, ep->ep_num, is_in(ep), ep->ep_type); + /* configure endpoint capabilities in dQH */ + i = ep->ep_num * 2 + is_in(ep); + ep->dqh = &dev->ep_dqh[i]; + ep->dqh->dqh_ios = ios; + ep->dqh->dqh_mpl = cpu_to_le16(max); + ep->dqh->dqh_zlt = zlt; + ep->dqh->dqh_mult = mult; + ep->dqh->dtd_next = DTD_TERM; + dev_dbg(&dev->pdev->dev, "enabled %s (ep%d%s-%s), max %04x\n", _ep->name, ep->ep_num, @@ -1430,8 +1435,6 @@ static int eps_reinit(struct langwell_udc *dev) INIT_LIST_HEAD(&ep->queue); list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); - - ep->dqh = &dev->ep_dqh[i]; } dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); From 513b91b688f527766bfe335d1ffd145257ad1624 Mon Sep 17 00:00:00 2001 From: JiebingLi Date: Thu, 5 Aug 2010 14:18:13 +0100 Subject: [PATCH 004/141] USB: langwell: USB Client PHY low power mode setting PHY low power mode setting with a static function Signed-off-by: JiebingLi Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/langwell_udc.c | 92 ++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 32 deletions(-) diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index 599ad8a1f5fe..8b92e2208dad 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -1159,11 +1159,37 @@ static int langwell_get_frame(struct usb_gadget *_gadget) } +/* enter or exit PHY low power state */ +static void langwell_phy_low_power(struct langwell_udc *dev, bool flag) +{ + u32 devlc; + u8 devlc_byte2; + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + devlc = readl(&dev->op_regs->devlc); + dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc); + + if (flag) + devlc |= LPM_PHCD; + else + devlc &= ~LPM_PHCD; + + /* FIXME: workaround for Langwell A1/A2/A3 sighting */ + devlc_byte2 = (devlc >> 16) & 0xff; + writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2); + + devlc = readl(&dev->op_regs->devlc); + dev_vdbg(&dev->pdev->dev, + "%s PHY low power suspend, devlc = 0x%08x\n", + flag ? "enter" : "exit", devlc); +} + + /* tries to wake up the host connected to this gadget */ static int langwell_wakeup(struct usb_gadget *_gadget) { struct langwell_udc *dev; - u32 portsc1, devlc; + u32 portsc1; unsigned long flags; if (!_gadget) @@ -1186,22 +1212,19 @@ static int langwell_wakeup(struct usb_gadget *_gadget) return 0; } - /* LPM L1 to L0, remote wakeup */ - if (dev->lpm && dev->lpm_state == LPM_L1) { - portsc1 |= PORTS_SLP; - writel(portsc1, &dev->op_regs->portsc1); - } - - /* force port resume */ - if (dev->usb_state == USB_STATE_SUSPENDED) { - portsc1 |= PORTS_FPR; - writel(portsc1, &dev->op_regs->portsc1); - } + /* LPM L1 to L0 or legacy remote wakeup */ + if (dev->lpm && dev->lpm_state == LPM_L1) + dev_info(&dev->pdev->dev, "LPM L1 to L0 remote wakeup\n"); + else + dev_info(&dev->pdev->dev, "device remote wakeup\n"); /* exit PHY low power suspend */ - devlc = readl(&dev->op_regs->devlc); - devlc &= ~LPM_PHCD; - writel(devlc, &dev->op_regs->devlc); + if (dev->pdev->device != 0x0829) + langwell_phy_low_power(dev, 0); + + /* force port resume */ + portsc1 |= PORTS_FPR; + writel(portsc1, &dev->op_regs->portsc1); spin_unlock_irqrestore(&dev->lock, flags); @@ -1331,6 +1354,7 @@ static const struct usb_gadget_ops langwell_ops = { static int langwell_udc_reset(struct langwell_udc *dev) { u32 usbcmd, usbmode, devlc, endpointlistaddr; + u8 devlc_byte0, devlc_byte2; unsigned long timeout; if (!dev) @@ -1375,9 +1399,17 @@ static int langwell_udc_reset(struct langwell_udc *dev) /* if support USB LPM, ACK all LPM token */ if (dev->lpm) { devlc = readl(&dev->op_regs->devlc); + dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc); + /* FIXME: workaround for Langwell A1/A2/A3 sighting */ devlc &= ~LPM_STL; /* don't STALL LPM token */ devlc &= ~LPM_NYT_ACK; /* ACK LPM token */ - writel(devlc, &dev->op_regs->devlc); + devlc_byte0 = devlc & 0xff; + devlc_byte2 = (devlc >> 16) & 0xff; + writeb(devlc_byte0, (u8 *)&dev->op_regs->devlc); + writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2); + devlc = readl(&dev->op_regs->devlc); + dev_vdbg(&dev->pdev->dev, + "ACK LPM token, devlc = 0x%08x\n", devlc); } /* fill endpointlistaddr register */ @@ -1871,6 +1903,10 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) if (unlikely(!driver || !driver->bind || !driver->unbind)) return -EINVAL; + /* exit PHY low power suspend */ + if (dev->pdev->device != 0x0829) + langwell_phy_low_power(dev, 0); + /* unbind OTG transceiver */ if (dev->transceiver) (void)otg_set_peripheral(dev->transceiver, 0); @@ -2706,7 +2742,6 @@ static void handle_usb_reset(struct langwell_udc *dev) /* USB bus suspend/resume interrupt */ static void handle_bus_suspend(struct langwell_udc *dev) { - u32 devlc; dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); dev->resume_state = dev->usb_state; @@ -2747,9 +2782,8 @@ static void handle_bus_suspend(struct langwell_udc *dev) } /* enter PHY low power suspend */ - devlc = readl(&dev->op_regs->devlc); - devlc |= LPM_PHCD; - writel(devlc, &dev->op_regs->devlc); + if (dev->pdev->device != 0x0829) + langwell_phy_low_power(dev, 0); dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); } @@ -2757,16 +2791,14 @@ static void handle_bus_suspend(struct langwell_udc *dev) static void handle_bus_resume(struct langwell_udc *dev) { - u32 devlc; dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); dev->usb_state = dev->resume_state; dev->resume_state = 0; /* exit PHY low power suspend */ - devlc = readl(&dev->op_regs->devlc); - devlc &= ~LPM_PHCD; - writel(devlc, &dev->op_regs->devlc); + if (dev->pdev->device != 0x0829) + langwell_phy_low_power(dev, 0); #ifdef OTG_TRANSCEIVER if (dev->lotg->otg.default_a == 0) @@ -3232,7 +3264,6 @@ error: static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) { struct langwell_udc *dev = the_controller; - u32 devlc; dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); @@ -3251,9 +3282,8 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) pci_set_power_state(pdev, PCI_D3hot); /* enter PHY low power suspend */ - devlc = readl(&dev->op_regs->devlc); - devlc |= LPM_PHCD; - writel(devlc, &dev->op_regs->devlc); + if (dev->pdev->device != 0x0829) + langwell_phy_low_power(dev, 1); dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; @@ -3264,14 +3294,12 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) static int langwell_udc_resume(struct pci_dev *pdev) { struct langwell_udc *dev = the_controller; - u32 devlc; dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); /* exit PHY low power suspend */ - devlc = readl(&dev->op_regs->devlc); - devlc &= ~LPM_PHCD; - writel(devlc, &dev->op_regs->devlc); + if (dev->pdev->device != 0x0829) + langwell_phy_low_power(dev, 0); /* set device D0 power state */ pci_set_power_state(pdev, PCI_D0); From 3211cbc20b406799423385cf62e1f1879b1ca8cc Mon Sep 17 00:00:00 2001 From: JiebingLi Date: Thu, 5 Aug 2010 14:18:21 +0100 Subject: [PATCH 005/141] USB: langwell: USB Client Remote Wakeup Support Remote wakeup support in client driver. Made non-debug only this time. Signed-off-by: JiebingLi Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/langwell_udc.c | 67 ++++++++++++++++++++++++++++--- drivers/usb/gadget/langwell_udc.h | 3 ++ 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index 8b92e2208dad..4b134abb1dbe 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -1815,6 +1815,36 @@ static ssize_t show_langwell_udc(struct device *_dev, static DEVICE_ATTR(langwell_udc, S_IRUGO, show_langwell_udc, NULL); +/* device "remote_wakeup" sysfs attribute file */ +static ssize_t store_remote_wakeup(struct device *_dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct langwell_udc *dev = the_controller; + unsigned long flags; + ssize_t rc = count; + + if (count > 2) + return -EINVAL; + + if (count > 0 && buf[count-1] == '\n') + ((char *) buf)[count-1] = 0; + + if (buf[0] != '1') + return -EINVAL; + + /* force remote wakeup enabled in case gadget driver doesn't support */ + spin_lock_irqsave(&dev->lock, flags); + dev->remote_wakeup = 1; + dev->dev_status |= (1 << USB_DEVICE_REMOTE_WAKEUP); + spin_unlock_irqrestore(&dev->lock, flags); + + langwell_wakeup(&dev->gadget); + + return rc; +} +static DEVICE_ATTR(remote_wakeup, S_IWUSR, NULL, store_remote_wakeup); + + /*-------------------------------------------------------------------------*/ /* @@ -2136,8 +2166,7 @@ static void get_status(struct langwell_udc *dev, u8 request_type, u16 value, if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) { /* get device status */ - status_data = 1 << USB_DEVICE_SELF_POWERED; - status_data |= dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP; + status_data = dev->dev_status; } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) { /* get interface status */ status_data = 0; @@ -2275,6 +2304,22 @@ static void handle_setup_packet(struct langwell_udc *dev, } else if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) == (USB_RECIP_DEVICE | USB_TYPE_STANDARD)) { + rc = 0; + switch (wValue) { + case USB_DEVICE_REMOTE_WAKEUP: + if (setup->bRequest == USB_REQ_SET_FEATURE) { + dev->remote_wakeup = 1; + dev->dev_status |= (1 << wValue); + } else { + dev->remote_wakeup = 0; + dev->dev_status &= ~(1 << wValue); + } + break; + default: + rc = -EOPNOTSUPP; + break; + } + if (!gadget_is_otg(&dev->gadget)) break; else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) { @@ -2290,7 +2335,6 @@ static void handle_setup_packet(struct langwell_udc *dev, dev->gadget.a_alt_hnp_support = 1; else break; - rc = 0; } else break; @@ -2678,7 +2722,10 @@ static void handle_usb_reset(struct langwell_udc *dev) dev->ep0_dir = USB_DIR_OUT; dev->ep0_state = WAIT_FOR_SETUP; - dev->remote_wakeup = 0; /* default to 0 on reset */ + + /* remote wakeup reset to 0 when the device is reset */ + dev->remote_wakeup = 0; + dev->dev_status = 1 << USB_DEVICE_SELF_POWERED; dev->gadget.b_hnp_enable = 0; dev->gadget.a_hnp_support = 0; dev->gadget.a_alt_hnp_support = 0; @@ -2997,6 +3044,7 @@ static void langwell_udc_remove(struct pci_dev *pdev) device_unregister(&dev->gadget.dev); device_remove_file(&pdev->dev, &dev_attr_langwell_udc); + device_remove_file(&pdev->dev, &dev_attr_remote_wakeup); #ifndef OTG_TRANSCEIVER pci_set_drvdata(pdev, NULL); @@ -3177,7 +3225,10 @@ static int langwell_udc_probe(struct pci_dev *pdev, dev->resume_state = USB_STATE_NOTATTACHED; dev->usb_state = USB_STATE_POWERED; dev->ep0_dir = USB_DIR_OUT; - dev->remote_wakeup = 0; /* default to 0 on reset */ + + /* remote wakeup reset to 0 when the device is reset */ + dev->remote_wakeup = 0; + dev->dev_status = 1 << USB_DEVICE_SELF_POWERED; #ifndef OTG_TRANSCEIVER /* reset device controller */ @@ -3247,9 +3298,15 @@ static int langwell_udc_probe(struct pci_dev *pdev, if (retval) goto error; + retval = device_create_file(&pdev->dev, &dev_attr_remote_wakeup); + if (retval) + goto error_attr1; + dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); return 0; +error_attr1: + device_remove_file(&pdev->dev, &dev_attr_langwell_udc); error: if (dev) { dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h index 9719934e1c08..3d3206eec544 100644 --- a/drivers/usb/gadget/langwell_udc.h +++ b/drivers/usb/gadget/langwell_udc.h @@ -224,5 +224,8 @@ struct langwell_udc { /* make sure release() is done */ struct completion *done; + + /* device status data for get_status request */ + u16 dev_status; }; From 912c93d1606f60932de3e2f31db3722a9f069ed9 Mon Sep 17 00:00:00 2001 From: JiebingLi Date: Thu, 5 Aug 2010 14:18:29 +0100 Subject: [PATCH 006/141] USB: langwell: USB Client driver memory handling SRAM Memory handling for USB client function Signed-off-by: JiebingLi Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/langwell_udc.c | 113 ++++++++++++++++++++++++++++-- drivers/usb/gadget/langwell_udc.h | 12 ++-- 2 files changed, 115 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index 4b134abb1dbe..ccc9c070a30d 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -2988,6 +2988,50 @@ static void gadget_release(struct device *_dev) } +/* enable SRAM caching if SRAM detected */ +static void sram_init(struct langwell_udc *dev) +{ + struct pci_dev *pdev = dev->pdev; + + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + dev->sram_addr = pci_resource_start(pdev, 1); + dev->sram_size = pci_resource_len(pdev, 1); + dev_info(&dev->pdev->dev, "Found private SRAM at %x size:%x\n", + dev->sram_addr, dev->sram_size); + dev->got_sram = 1; + + if (pci_request_region(pdev, 1, kobject_name(&pdev->dev.kobj))) { + dev_warn(&dev->pdev->dev, "SRAM request failed\n"); + dev->got_sram = 0; + } else if (!dma_declare_coherent_memory(&pdev->dev, dev->sram_addr, + dev->sram_addr, dev->sram_size, DMA_MEMORY_MAP)) { + dev_warn(&dev->pdev->dev, "SRAM DMA declare failed\n"); + pci_release_region(pdev, 1); + dev->got_sram = 0; + } + + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); +} + + +/* release SRAM caching */ +static void sram_deinit(struct langwell_udc *dev) +{ + struct pci_dev *pdev = dev->pdev; + + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); + + dma_release_declared_memory(&pdev->dev); + pci_release_region(pdev, 1); + + dev->got_sram = 0; + + dev_info(&dev->pdev->dev, "release SRAM caching\n"); + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); +} + + /* tear down the binding between this driver and the pci device */ static void langwell_udc_remove(struct pci_dev *pdev) { @@ -3000,19 +3044,25 @@ static void langwell_udc_remove(struct pci_dev *pdev) dev->done = &done; - /* free memory allocated in probe */ +#ifndef OTG_TRANSCEIVER + /* free dTD dma_pool and dQH */ if (dev->dtd_pool) dma_pool_destroy(dev->dtd_pool); + if (dev->ep_dqh) + dma_free_coherent(&pdev->dev, dev->ep_dqh_size, + dev->ep_dqh, dev->ep_dqh_dma); + + /* release SRAM caching */ + if (dev->has_sram && dev->got_sram) + sram_deinit(dev); +#endif + if (dev->status_req) { kfree(dev->status_req->req.buf); kfree(dev->status_req); } - if (dev->ep_dqh) - dma_free_coherent(&pdev->dev, dev->ep_dqh_size, - dev->ep_dqh, dev->ep_dqh_dma); - kfree(dev->ep); /* diable IRQ handler */ @@ -3140,7 +3190,15 @@ static int langwell_udc_probe(struct pci_dev *pdev, goto error; } + dev->has_sram = 1; + dev->got_sram = 0; + dev_vdbg(&dev->pdev->dev, "dev->has_sram: %d\n", dev->has_sram); + #ifndef OTG_TRANSCEIVER + /* enable SRAM caching if detected */ + if (dev->has_sram && !dev->got_sram) + sram_init(dev); + dev_info(&dev->pdev->dev, "irq %d, io mem: 0x%08lx, len: 0x%08lx, pci mem 0x%p\n", pdev->irq, resource, len, base); @@ -3335,6 +3393,18 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) /* save PCI state */ pci_save_state(pdev); + /* free dTD dma_pool and dQH */ + if (dev->dtd_pool) + dma_pool_destroy(dev->dtd_pool); + + if (dev->ep_dqh) + dma_free_coherent(&pdev->dev, dev->ep_dqh_size, + dev->ep_dqh, dev->ep_dqh_dma); + + /* release SRAM caching */ + if (dev->has_sram && dev->got_sram) + sram_deinit(dev); + /* set device power state */ pci_set_power_state(pdev, PCI_D3hot); @@ -3351,6 +3421,7 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) static int langwell_udc_resume(struct pci_dev *pdev) { struct langwell_udc *dev = the_controller; + size_t size; dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); @@ -3361,6 +3432,38 @@ static int langwell_udc_resume(struct pci_dev *pdev) /* set device D0 power state */ pci_set_power_state(pdev, PCI_D0); + /* enable SRAM caching if detected */ + if (dev->has_sram && !dev->got_sram) + sram_init(dev); + + /* allocate device dQH memory */ + size = dev->ep_max * sizeof(struct langwell_dqh); + dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size); + if (size < DQH_ALIGNMENT) + size = DQH_ALIGNMENT; + else if ((size % DQH_ALIGNMENT) != 0) { + size += DQH_ALIGNMENT + 1; + size &= ~(DQH_ALIGNMENT - 1); + } + dev->ep_dqh = dma_alloc_coherent(&pdev->dev, size, + &dev->ep_dqh_dma, GFP_KERNEL); + if (!dev->ep_dqh) { + dev_err(&dev->pdev->dev, "allocate dQH memory failed\n"); + return -ENOMEM; + } + dev->ep_dqh_size = size; + dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size); + + /* create dTD dma_pool resource */ + dev->dtd_pool = dma_pool_create("langwell_dtd", + &dev->pdev->dev, + sizeof(struct langwell_dtd), + DTD_ALIGNMENT, + DMA_BOUNDARY); + + if (!dev->dtd_pool) + return -ENOMEM; + /* restore PCI state */ pci_restore_state(pdev); diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h index 3d3206eec544..f1d9c1bb04f3 100644 --- a/drivers/usb/gadget/langwell_udc.h +++ b/drivers/usb/gadget/langwell_udc.h @@ -18,11 +18,7 @@ */ #include - -#if defined(CONFIG_USB_LANGWELL_OTG) #include -#endif - /*-------------------------------------------------------------------------*/ @@ -199,7 +195,9 @@ struct langwell_udc { vbus_active:1, suspended:1, stopped:1, - lpm:1; /* LPM capability */ + lpm:1, /* LPM capability */ + has_sram:1, /* SRAM caching */ + got_sram:1; /* pci state used to access those endpoints */ struct pci_dev *pdev; @@ -225,6 +223,10 @@ struct langwell_udc { /* make sure release() is done */ struct completion *done; + /* for private SRAM caching */ + unsigned int sram_addr; + unsigned int sram_size; + /* device status data for get_status request */ u16 dev_status; }; From c6a76781da6b7ee2589a6ec87be30abdbc303384 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 12 Aug 2010 09:40:30 +0200 Subject: [PATCH 007/141] USB: gadget: dbgp: cleanup: remove unneeded check len is always greater than or equal to zero here. First of all, it's type is unsigned and also we only assign it numbers which are greater than or equal to zero. Removing the check lets us pull everything in an indent level. Signed-off-by: Dan Carpenter Acked-by: Stephane duverger Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/dbgp.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/dbgp.c b/drivers/usb/gadget/dbgp.c index 0ed50a2c0a36..abe4a2ec5625 100644 --- a/drivers/usb/gadget/dbgp.c +++ b/drivers/usb/gadget/dbgp.c @@ -386,15 +386,13 @@ static int dbgp_setup(struct usb_gadget *gadget, } else goto fail; - if (len >= 0) { - req->length = min(length, len); - req->zero = len < req->length; - if (data && req->length) - memcpy(req->buf, data, req->length); + req->length = min(length, len); + req->zero = len < req->length; + if (data && req->length) + memcpy(req->buf, data, req->length); - req->complete = dbgp_setup_complete; - return usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); - } + req->complete = dbgp_setup_complete; + return usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); fail: dev_dbg(&dbgp.gadget->dev, From 90593899de83a6e6fdea563d058acd2f4334e3f9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 19 Aug 2010 00:13:48 +0200 Subject: [PATCH 008/141] USB: sam-ba: add driver for Atmel SAM Boot Assistant (SAM-BA) Add new driver to access the SAM-BA boot application of Atmel AT91SAM devices. The SAM-BA firmware cannot handle merged write requests so we cannot use the generic write implementation (which uses the port write fifo). Tested with the SAM-BA 2.10 tools and an Atmel at91sam9260-ek. Signed-off-by: Johan Hovold Tested-by: Peter Korsgaard Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 9 ++ drivers/usb/serial/Makefile | 1 + drivers/usb/serial/sam-ba.c | 206 ++++++++++++++++++++++++++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 drivers/usb/serial/sam-ba.c diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 916b2b6d765f..95058109f9fa 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -527,6 +527,15 @@ config USB_SERIAL_SAFE_PADDED bool "USB Secure Encapsulated Driver - Padded" depends on USB_SERIAL_SAFE +config USB_SERIAL_SAMBA + tristate "USB Atmel SAM Boot Assistant (SAM-BA) driver" + help + Say Y here if you want to access the SAM-BA boot application of an + Atmel AT91SAM device. + + To compile this driver as a module, choose M here: the + module will be called sam-ba. + config USB_SERIAL_SIEMENS_MPI tristate "USB Siemens MPI driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 40ebe17b6ea8..cf41b6209c74 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o obj-$(CONFIG_USB_SERIAL_QCAUX) += qcaux.o obj-$(CONFIG_USB_SERIAL_QUALCOMM) += qcserial.o obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o +obj-$(CONFIG_USB_SERIAL_SAMBA) += sam-ba.o obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o diff --git a/drivers/usb/serial/sam-ba.c b/drivers/usb/serial/sam-ba.c new file mode 100644 index 000000000000..e3bba64afc57 --- /dev/null +++ b/drivers/usb/serial/sam-ba.c @@ -0,0 +1,206 @@ +/* + * Atmel SAM Boot Assistant (SAM-BA) driver + * + * Copyright (C) 2010 Johan Hovold + * + * 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 +#include +#include +#include +#include +#include + + +#define DRIVER_VERSION "v1.0" +#define DRIVER_AUTHOR "Johan Hovold " +#define DRIVER_DESC "Atmel SAM Boot Assistant (SAM-BA) driver" + +#define SAMBA_VENDOR_ID 0x3eb +#define SAMBA_PRODUCT_ID 0x6124 + + +static int debug; + +static const struct usb_device_id id_table[] = { + /* + * NOTE: Only match the CDC Data interface. + */ + { USB_DEVICE_AND_INTERFACE_INFO(SAMBA_VENDOR_ID, SAMBA_PRODUCT_ID, + USB_CLASS_CDC_DATA, 0, 0) }, + { } +}; +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_driver samba_driver = { + .name = "sam-ba", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .no_dynamic_id = 1, +}; + + +/* + * NOTE: The SAM-BA firmware cannot handle merged write requests so we cannot + * use the generic write implementation (which uses the port write fifo). + */ +static int samba_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) +{ + struct urb *urb; + unsigned long flags; + int result; + int i; + + if (!count) + return 0; + + count = min_t(int, count, port->bulk_out_size); + + spin_lock_irqsave(&port->lock, flags); + if (!port->write_urbs_free) { + spin_unlock_irqrestore(&port->lock, flags); + return 0; + } + i = find_first_bit(&port->write_urbs_free, + ARRAY_SIZE(port->write_urbs)); + __clear_bit(i, &port->write_urbs_free); + port->tx_bytes += count; + spin_unlock_irqrestore(&port->lock, flags); + + urb = port->write_urbs[i]; + memcpy(urb->transfer_buffer, buf, count); + urb->transfer_buffer_length = count; + usb_serial_debug_data(debug, &port->dev, __func__, count, + urb->transfer_buffer); + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) { + dev_err(&port->dev, "%s - error submitting urb: %d\n", + __func__, result); + spin_lock_irqsave(&port->lock, flags); + __set_bit(i, &port->write_urbs_free); + port->tx_bytes -= count; + spin_unlock_irqrestore(&port->lock, flags); + + return result; + } + + return count; +} + +static int samba_write_room(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + unsigned long flags; + unsigned long free; + int count; + int room; + + spin_lock_irqsave(&port->lock, flags); + free = port->write_urbs_free; + spin_unlock_irqrestore(&port->lock, flags); + + count = hweight_long(free); + room = count * port->bulk_out_size; + + dbg("%s - returns %d", __func__, room); + + return room; +} + +static int samba_chars_in_buffer(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + unsigned long flags; + int chars; + + spin_lock_irqsave(&port->lock, flags); + chars = port->tx_bytes; + spin_unlock_irqrestore(&port->lock, flags); + + dbg("%s - returns %d", __func__, chars); + + return chars; +} + +static void samba_write_bulk_callback(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + unsigned long flags; + int i; + + dbg("%s - port %d", __func__, port->number); + + for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) { + if (port->write_urbs[i] == urb) + break; + } + spin_lock_irqsave(&port->lock, flags); + __set_bit(i, &port->write_urbs_free); + port->tx_bytes -= urb->transfer_buffer_length; + spin_unlock_irqrestore(&port->lock, flags); + + if (urb->status) + dbg("%s - non-zero urb status: %d", __func__, urb->status); + + usb_serial_port_softint(port); +} + +static struct usb_serial_driver samba_device = { + .driver = { + .owner = THIS_MODULE, + .name = "sam-ba", + }, + .usb_driver = &samba_driver, + .id_table = id_table, + .num_ports = 1, + .bulk_in_size = 512, + .bulk_out_size = 2048, + .write = samba_write, + .write_room = samba_write_room, + .chars_in_buffer = samba_chars_in_buffer, + .write_bulk_callback = samba_write_bulk_callback, + .throttle = usb_serial_generic_throttle, + .unthrottle = usb_serial_generic_unthrottle, +}; + +static int __init samba_init(void) +{ + int retval; + + retval = usb_serial_register(&samba_device); + if (retval) + return retval; + + retval = usb_register(&samba_driver); + if (retval) { + usb_serial_deregister(&samba_device); + return retval; + } + + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ": " + DRIVER_DESC "\n"); + return 0; +} + +static void __exit samba_exit(void) +{ + usb_deregister(&samba_driver); + usb_serial_deregister(&samba_device); +} + +module_init(samba_init); +module_exit(samba_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable verbose debugging messages"); From 37b5801e16d2e192fe2b20f4af33aa8c6e8786f3 Mon Sep 17 00:00:00 2001 From: Parirajan Muthalagu Date: Wed, 25 Aug 2010 16:33:26 +0530 Subject: [PATCH 009/141] USB Gadget: Verify VBUS current before setting the device self-powered bit Acked-by: David Brownell Acked-by: Linus Walleij Signed-off-by: Praveena Nadahally Signed-off-by: Parirajan Muthalagu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/composite.c | 8 +++++++- include/linux/usb/ch9.h | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 1160c55de7f2..eaa9a599df63 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1074,7 +1074,13 @@ static int composite_bind(struct usb_gadget *gadget) cdev->bufsiz = USB_BUFSIZ; cdev->driver = composite; - usb_gadget_set_selfpowered(gadget); + /* + * As per USB compliance update, a device that is actively drawing + * more than 100mA from USB must report itself as bus-powered in + * the GetStatus(DEVICE) call. + */ + if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW) + usb_gadget_set_selfpowered(gadget); /* interface and string IDs start at zero via kzalloc. * we force endpoints to start unassigned; few controller diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index da2ed77d3e8d..b0f7e9f57176 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -808,4 +808,14 @@ enum usb_device_state { */ }; +/*-------------------------------------------------------------------------*/ + +/* + * As per USB compliance update, a device that is actively drawing + * more than 100mA from USB must report itself as bus-powered in + * the GetStatus(DEVICE) call. + * http://compliance.usb.org/index.asp?UpdateFile=Electrical&Format=Standard#34 + */ +#define USB_SELF_POWER_VBUS_MAX_DRAW 100 + #endif /* __LINUX_USB_CH9_H */ From 4bec99174a5911457cddd87ceab4f5e038cc8141 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 29 Aug 2010 18:17:14 +0200 Subject: [PATCH 010/141] USB: core: update comment to match current function name Found while debugging a USB problem and trying to find the mentioned function. Signed-off-by: Wolfram Sang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 84c1897188d2..5da546c4fd79 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3629,7 +3629,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) } if (!parent_hdev) { - /* this requires hcd-specific logic; see OHCI hc_restart() */ + /* this requires hcd-specific logic; see ohci_restart() */ dev_dbg(&udev->dev, "%s for root hub!\n", __func__); return -EISDIR; } From 1c6529e92b7682573837e9c9eb7b5ba7a8216a88 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 12 Aug 2010 17:43:44 +0200 Subject: [PATCH 011/141] USB: gadget: g_multi: fixed vendor and product ID This patch fixes the vendor and product ID the gadget uses by replacing the temporary IDs that were used during development (which should never get into mainline) with proper IDs. Signed-off-by: Michal Nazarewicz Signed-off-by: Kyungmin Park Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/multi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 795d76232167..36d67a32abef 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -74,8 +74,8 @@ MODULE_LICENSE("GPL"); /***************************** Device Descriptor ****************************/ -#define MULTI_VENDOR_NUM 0x0525 /* XXX NetChip */ -#define MULTI_PRODUCT_NUM 0xa4ab /* XXX */ +#define MULTI_VENDOR_NUM 0x1d6b /* Linux Foundation */ +#define MULTI_PRODUCT_NUM 0x0104 /* Multifunction Composite Gadget */ enum { From ba0534be935d7b24e5fdd6f82c443ee75abc9149 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 12 Aug 2010 17:43:45 +0200 Subject: [PATCH 012/141] USB: gadget: g_ffs: fixed vendor and product ID This patch fixes the vendor and product ID the gadget uses by replacing the temporary IDs that were used during development (which should never get into mainline) with proper IDs. Signed-off-by: Michal Nazarewicz Signed-off-by: Kyungmin Park Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/g_ffs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index a9474f8d5325..3c2f0a43c9c6 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -53,8 +53,8 @@ MODULE_AUTHOR("Michal Nazarewicz"); MODULE_LICENSE("GPL"); -static unsigned short gfs_vendor_id = 0x0525; /* XXX NetChip */ -static unsigned short gfs_product_id = 0xa4ac; /* XXX */ +static unsigned short gfs_vendor_id = 0x1d6b; /* Linux Foundation */ +static unsigned short gfs_product_id = 0x0105; /* FunctionFS Gadget */ static struct usb_device_descriptor gfs_dev_desc = { .bLength = sizeof gfs_dev_desc, From 452ee0eb10bd3581cf667a1db18cb684889ce446 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 12 Aug 2010 17:43:50 +0200 Subject: [PATCH 013/141] usb: gadget: storage: remove nofua file when unbinding The dev_attr_nofua file was created during fsg_bind() but was never removed. Made it a bit more symmetrical and added code to remove the file in fsg_unbind(). Signed-off-by: Michal Nazarewicz Acked-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/file_storage.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index a857b7ac238c..ab77792a4361 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -3178,6 +3178,7 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) for (i = 0; i < fsg->nluns; ++i) { curlun = &fsg->luns[i]; if (curlun->registered) { + device_remove_file(&curlun->dev, &dev_attr_nofua); device_remove_file(&curlun->dev, &dev_attr_ro); device_remove_file(&curlun->dev, &dev_attr_file); fsg_lun_close(curlun); From 9cfe745e652eacf57ffc7862b7b3ccbdf336ad19 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 12 Aug 2010 17:43:51 +0200 Subject: [PATCH 014/141] usb: gadget: mass_storage: optional SCSI WRITE FUA bit The nofua parameter (optionally ignore SCSI WRITE FUA) was added to the File Storage Gadget some time ago. This patch adds the same functionality to the Mass Storage Function. Signed-off-by: Michal Nazarewicz Cc: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_mass_storage.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 32cce029f65c..44e5ffed5c08 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -73,6 +73,8 @@ * being removable. * ->cdrom Flag specifying that LUN shall be reported as * being a CD-ROM. + * ->nofua Flag specifying that FUA flag in SCSI WRITE(10,12) + * commands for this LUN shall be ignored. * * lun_name_format A printf-like format for names of the LUN * devices. This determines how the @@ -127,6 +129,8 @@ * Default true, boolean for removable media. * cdrom=b[,b...] Default false, boolean for whether to emulate * a CD-ROM drive. + * nofua=b[,b...] Default false, booleans for ignore FUA flag + * in SCSI WRITE(10,12) commands * luns=N Default N = number of filenames, number of * LUNs to support. * stall Default determined according to the type of @@ -409,6 +413,7 @@ struct fsg_config { char ro; char removable; char cdrom; + char nofua; } luns[FSG_MAX_LUNS]; const char *lun_name_format; @@ -887,7 +892,7 @@ static int do_write(struct fsg_common *common) curlun->sense_data = SS_INVALID_FIELD_IN_CDB; return -EINVAL; } - if (common->cmnd[1] & 0x08) { /* FUA */ + if (!curlun->nofua && (common->cmnd[1] & 0x08)) { /* FUA */ spin_lock(&curlun->filp->f_lock); curlun->filp->f_flags |= O_SYNC; spin_unlock(&curlun->filp->f_lock); @@ -2662,6 +2667,7 @@ static int fsg_main_thread(void *common_) /* Write permission is checked per LUN in store_*() functions. */ static DEVICE_ATTR(ro, 0644, fsg_show_ro, fsg_store_ro); +static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, fsg_store_nofua); static DEVICE_ATTR(file, 0644, fsg_show_file, fsg_store_file); @@ -2766,6 +2772,9 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, if (rc) goto error_luns; rc = device_create_file(&curlun->dev, &dev_attr_file); + if (rc) + goto error_luns; + rc = device_create_file(&curlun->dev, &dev_attr_nofua); if (rc) goto error_luns; @@ -2911,6 +2920,7 @@ static void fsg_common_release(struct kref *ref) /* In error recovery common->nluns may be zero. */ for (; i; --i, ++lun) { + device_remove_file(&lun->dev, &dev_attr_nofua); device_remove_file(&lun->dev, &dev_attr_ro); device_remove_file(&lun->dev, &dev_attr_file); fsg_lun_close(lun); @@ -3069,8 +3079,10 @@ struct fsg_module_parameters { int ro[FSG_MAX_LUNS]; int removable[FSG_MAX_LUNS]; int cdrom[FSG_MAX_LUNS]; + int nofua[FSG_MAX_LUNS]; unsigned int file_count, ro_count, removable_count, cdrom_count; + unsigned int nofua_count; unsigned int luns; /* nluns */ int stall; /* can_stall */ }; @@ -3096,6 +3108,8 @@ struct fsg_module_parameters { "true to simulate removable media"); \ _FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool, \ "true to simulate CD-ROM instead of disk"); \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, nofua, bool, \ + "true to ignore SCSI WRITE(10,12) FUA bit"); \ _FSG_MODULE_PARAM(prefix, params, luns, uint, \ "number of LUNs"); \ _FSG_MODULE_PARAM(prefix, params, stall, bool, \ From fc19de61ef5c17b6e19766052c6ac85cf31de876 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 12 Aug 2010 17:43:48 +0200 Subject: [PATCH 015/141] USB: gadget: functionfs: code cleanup This patch removes some of the string registration from the FunctionFS Gadget as composite layer can handle the iManufacturer and iProduct for us. It also removes some of the module parameters which were redundant as well as changes the name of others to better much the module parameter of the composite layer. Other then that, it also fixes formatting of multiline comments to match the coding style. Signed-off-by: Michal Nazarewicz Signed-off-by: Kyungmin Park Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/g_ffs.c | 85 +++++++++++++------------------------- 1 file changed, 28 insertions(+), 57 deletions(-) diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 3c2f0a43c9c6..52fd3fa0d130 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -52,9 +52,8 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR("Michal Nazarewicz"); MODULE_LICENSE("GPL"); - -static unsigned short gfs_vendor_id = 0x1d6b; /* Linux Foundation */ -static unsigned short gfs_product_id = 0x0105; /* FunctionFS Gadget */ +#define GFS_VENDOR_ID 0x1d6b /* Linux Foundation */ +#define GFS_PRODUCT_ID 0x0105 /* FunctionFS Gadget */ static struct usb_device_descriptor gfs_dev_desc = { .bLength = sizeof gfs_dev_desc, @@ -63,29 +62,16 @@ static struct usb_device_descriptor gfs_dev_desc = { .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, - /* Vendor and product id can be overridden by module parameters. */ - /* .idVendor = cpu_to_le16(gfs_vendor_id), */ - /* .idProduct = cpu_to_le16(gfs_product_id), */ - /* .bcdDevice = f(hardware) */ - /* .iManufacturer = DYNAMIC */ - /* .iProduct = DYNAMIC */ - /* NO SERIAL NUMBER */ - .bNumConfigurations = 1, + .idVendor = cpu_to_le16(GFS_VENDOR_ID), + .idProduct = cpu_to_le16(GFS_PRODUCT_ID), }; -#define GFS_MODULE_PARAM_DESC(name, field) \ - MODULE_PARM_DESC(name, "Value of the " #field " field of the device descriptor sent to the host. Takes effect only prior to the user-space driver registering to the FunctionFS.") - -module_param_named(usb_class, gfs_dev_desc.bDeviceClass, byte, 0644); -GFS_MODULE_PARAM_DESC(usb_class, bDeviceClass); -module_param_named(usb_subclass, gfs_dev_desc.bDeviceSubClass, byte, 0644); -GFS_MODULE_PARAM_DESC(usb_subclass, bDeviceSubClass); -module_param_named(usb_protocol, gfs_dev_desc.bDeviceProtocol, byte, 0644); -GFS_MODULE_PARAM_DESC(usb_protocol, bDeviceProtocol); -module_param_named(usb_vendor, gfs_vendor_id, ushort, 0644); -GFS_MODULE_PARAM_DESC(usb_vendor, idVendor); -module_param_named(usb_product, gfs_product_id, ushort, 0644); -GFS_MODULE_PARAM_DESC(usb_product, idProduct); +module_param_named(bDeviceClass, gfs_dev_desc.bDeviceClass, byte, 0644); +MODULE_PARM_DESC(bDeviceClass, "USB Device class"); +module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte, 0644); +MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass"); +module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte, 0644); +MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol"); @@ -95,8 +81,10 @@ static const struct usb_descriptor_header *gfs_otg_desc[] = { .bLength = sizeof(struct usb_otg_descriptor), .bDescriptorType = USB_DT_OTG, - /* REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... */ + /* + * REVISIT SRP-only hardware is possible, although + * it would not be called "OTG" ... + */ .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, }, @@ -105,19 +93,7 @@ static const struct usb_descriptor_header *gfs_otg_desc[] = { /* string IDs are assigned dynamically */ -enum { - GFS_STRING_MANUFACTURER_IDX, - GFS_STRING_PRODUCT_IDX, - GFS_STRING_FIRST_CONFIG_IDX, -}; - -static char gfs_manufacturer[50]; -static const char gfs_driver_desc[] = DRIVER_DESC; -static const char gfs_short_name[] = DRIVER_NAME; - static struct usb_string gfs_strings[] = { - [GFS_STRING_MANUFACTURER_IDX].s = gfs_manufacturer, - [GFS_STRING_PRODUCT_IDX].s = gfs_driver_desc, #ifdef CONFIG_USB_FUNCTIONFS_RNDIS { .s = "FunctionFS + RNDIS" }, #endif @@ -168,11 +144,12 @@ static int gfs_unbind(struct usb_composite_dev *cdev); static int gfs_do_config(struct usb_configuration *c); static struct usb_composite_driver gfs_driver = { - .name = gfs_short_name, + .name = DRIVER_NAME, .dev = &gfs_dev_desc, .strings = gfs_dev_strings, .bind = gfs_bind, .unbind = gfs_unbind, + .iProduct = DRIVER_DESC, }; @@ -245,20 +222,10 @@ static int gfs_bind(struct usb_composite_dev *cdev) if (unlikely(ret < 0)) goto error_quick; - gfs_dev_desc.idVendor = cpu_to_le16(gfs_vendor_id); - gfs_dev_desc.idProduct = cpu_to_le16(gfs_product_id); - - snprintf(gfs_manufacturer, sizeof gfs_manufacturer, "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - cdev->gadget->name); - ret = usb_string_ids_tab(cdev, gfs_strings); if (unlikely(ret < 0)) goto error; - gfs_dev_desc.iManufacturer = gfs_strings[GFS_STRING_MANUFACTURER_IDX].id; - gfs_dev_desc.iProduct = gfs_strings[GFS_STRING_PRODUCT_IDX].id; - ret = functionfs_bind(gfs_ffs_data, cdev); if (unlikely(ret < 0)) goto error; @@ -266,9 +233,8 @@ static int gfs_bind(struct usb_composite_dev *cdev) for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) { struct gfs_configuration *c = gfs_configurations + i; - ret = GFS_STRING_FIRST_CONFIG_IDX + i; - c->c.label = gfs_strings[ret].s; - c->c.iConfiguration = gfs_strings[ret].id; + c->c.label = gfs_strings[i].s; + c->c.iConfiguration = gfs_strings[i].id; c->c.bind = gfs_do_config; c->c.bConfigurationValue = 1 + i; c->c.bmAttributes = USB_CONFIG_ATT_SELFPOWER; @@ -293,13 +259,14 @@ static int gfs_unbind(struct usb_composite_dev *cdev) { ENTER(); - /* We may have been called in an error recovery frem + /* + * 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...? */ - + * do...? + */ if (gfs_ffs_data) { gether_cleanup(); functionfs_unbind(gfs_ffs_data); @@ -334,14 +301,16 @@ static int gfs_do_config(struct usb_configuration *c) if (unlikely(ret < 0)) return ret; - /* After previous do_configs there may be some invalid + /* + * After previous do_configs there may be some invalid * pointers in c->interface array. This happens every time * a user space function with fewer interfaces than a user * space function that was run before the new one is run. The * compasit's set_config() assumes that if there is no more * then MAX_CONFIG_INTERFACES interfaces in a configuration * then there is a NULL pointer after the last interface in - * c->interface array. We need to make sure this is true. */ + * c->interface array. We need to make sure this is true. + */ if (c->next_interface_id < ARRAY_SIZE(c->interface)) c->interface[c->next_interface_id] = NULL; @@ -350,10 +319,12 @@ static int gfs_do_config(struct usb_configuration *c) #ifdef CONFIG_USB_FUNCTIONFS_ETH + static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) { return can_support_ecm(c->cdev->gadget) ? ecm_bind_config(c, ethaddr) : geth_bind_config(c, ethaddr); } + #endif From ad1a8102f957f4d25fc58cdc10736c5ade7557e1 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 12 Aug 2010 17:43:46 +0200 Subject: [PATCH 016/141] USB: gadget: composite: Better string override handling The iManufatcurer, iProduct and iSerialNumber composite module parameters were only used when the gadget driver registers strings for manufacturer, product and serial number. If the gadget never bothered to set corresponding fields in USB device descriptors those module parameters are ignored. This commit makes the parameters work even if the strings ID have not been assigned. It also changes the way IDs are overridden -- what IDs are overridden is now saved in usb_composite_dev structure -- which makes it unnecessary to modify the string tables the way previous code did. The commit also adds a iProduct and iManufatcurer fields to the usb_composite_device structure. If they are set, appropriate strings are reserved and added to device descriptor. This makes it unnecessary for gadget drivers to maintain code for setting those. If iProduct is not set it defaults to usb_composite_device::name; if iManufatcurer is not set a default " with " is used. The last thing is that if needs_serial field of usb_composite_device is set and user failed to provided iSerialNumber parameter a warning is issued. Signed-off-by: Michal Nazarewicz Signed-off-by: Kyungmin Park Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/composite.c | 96 ++++++++++++++++++++++------------ include/linux/usb/composite.h | 13 +++++ 2 files changed, 77 insertions(+), 32 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index eaa9a599df63..717de39627c7 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -69,6 +70,8 @@ static char *iSerialNumber; module_param(iSerialNumber, charp, 0); MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); +static char composite_manufacturer[50]; + /*-------------------------------------------------------------------------*/ /** @@ -599,6 +602,7 @@ static int get_string(struct usb_composite_dev *cdev, struct usb_configuration *c; struct usb_function *f; int len; + const char *str; /* Yes, not only is USB's I18N support probably more than most * folk will ever care about ... also, it's all supported here. @@ -638,9 +642,29 @@ static int get_string(struct usb_composite_dev *cdev, return s->bLength; } - /* Otherwise, look up and return a specified string. String IDs - * are device-scoped, so we look up each string table we're told - * about. These lookups are infrequent; simpler-is-better here. + /* Otherwise, look up and return a specified string. First + * check if the string has not been overridden. + */ + if (cdev->manufacturer_override == id) + str = iManufacturer ?: composite->iManufacturer ?: + composite_manufacturer; + else if (cdev->product_override == id) + str = iProduct ?: composite->iProduct; + else if (cdev->serial_override == id) + str = iSerialNumber; + else + str = NULL; + if (str) { + struct usb_gadget_strings strings = { + .language = language, + .strings = &(struct usb_string) { 0xff, str } + }; + return usb_gadget_get_string(&strings, 0xff, buf); + } + + /* String IDs are device-scoped, so we look up each string + * table we're told about. These lookups are infrequent; + * simpler-is-better here. */ if (composite->strings) { len = lookup_string(composite->strings, buf, language, id); @@ -1025,26 +1049,17 @@ composite_unbind(struct usb_gadget *gadget) composite = NULL; } -static void -string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s) +static u8 override_id(struct usb_composite_dev *cdev, u8 *desc) { - struct usb_string *str = tab->strings; - - for (str = tab->strings; str->s; str++) { - if (str->id == id) { - str->s = s; - return; - } + if (!*desc) { + int ret = usb_string_id(cdev); + if (unlikely(ret < 0)) + WARNING(cdev, "failed to override string ID\n"); + else + *desc = ret; } -} -static void -string_override(struct usb_gadget_strings **tab, u8 id, const char *s) -{ - while (*tab) { - string_override_one(*tab, id, s); - tab++; - } + return *desc; } static int composite_bind(struct usb_gadget *gadget) @@ -1107,19 +1122,34 @@ static int composite_bind(struct usb_gadget *gadget) cdev->desc = *composite->dev; cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket; - /* strings can't be assigned before bind() allocates the - * releavnt identifiers - */ - if (cdev->desc.iManufacturer && iManufacturer) - string_override(composite->strings, - cdev->desc.iManufacturer, iManufacturer); - if (cdev->desc.iProduct && iProduct) - string_override(composite->strings, - cdev->desc.iProduct, iProduct); - if (cdev->desc.iSerialNumber && iSerialNumber) - string_override(composite->strings, - cdev->desc.iSerialNumber, iSerialNumber); + /* stirng overrides */ + if (iManufacturer || !cdev->desc.iManufacturer) { + if (!iManufacturer && !composite->iManufacturer && + !*composite_manufacturer) + snprintf(composite_manufacturer, + sizeof composite_manufacturer, + "%s %s with %s", + init_utsname()->sysname, + init_utsname()->release, + gadget->name); + cdev->manufacturer_override = + override_id(cdev, &cdev->desc.iManufacturer); + } + + if (iProduct || (!cdev->desc.iProduct && composite->iProduct)) + cdev->product_override = + override_id(cdev, &cdev->desc.iProduct); + + if (iSerialNumber) + cdev->serial_override = + override_id(cdev, &cdev->desc.iSerialNumber); + + /* has userspace failed to provide a serial number? */ + if (composite->needs_serial && !cdev->desc.iSerialNumber) + WARNING(cdev, "userspace failed to provide iSerialNumber\n"); + + /* finish up */ status = device_create_file(&gadget->dev, &dev_attr_suspended); if (status) goto fail; @@ -1217,6 +1247,8 @@ int usb_composite_register(struct usb_composite_driver *driver) if (!driver || !driver->dev || !driver->bind || composite) return -EINVAL; + if (!driver->iProduct) + driver->iProduct = driver->name; if (!driver->name) driver->name = "composite"; composite_driver.function = (char *) driver->name; diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 617068134ae8..a78e813d27e4 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -237,10 +237,17 @@ int usb_add_config(struct usb_composite_dev *, /** * struct usb_composite_driver - groups configurations into a gadget * @name: For diagnostics, identifies the driver. + * @iProduct: Used as iProduct override if @dev->iProduct is not set. + * If NULL value of @name is taken. + * @iManufacturer: Used as iManufacturer override if @dev->iManufacturer is + * not set. If NULL a default " with " value + * will be used. * @dev: Template descriptor for the device, including default device * identifiers. * @strings: tables of strings, keyed by identifiers assigned during bind() * and language IDs provided in control requests + * @needs_serial: set to 1 if the gadget needs userspace to provide + * a serial number. If one is not provided, warning will be printed. * @bind: (REQUIRED) Used to allocate resources that are shared across the * whole device, such as string IDs, and add its configurations using * @usb_add_config(). This may fail by returning a negative errno @@ -266,8 +273,11 @@ int usb_add_config(struct usb_composite_dev *, */ struct usb_composite_driver { const char *name; + const char *iProduct; + const char *iManufacturer; const struct usb_device_descriptor *dev; struct usb_gadget_strings **strings; + unsigned needs_serial:1; /* REVISIT: bind() functions can be marked __init, which * makes trouble for section mismatch analysis. See if @@ -334,6 +344,9 @@ struct usb_composite_dev { struct list_head configs; struct usb_composite_driver *driver; u8 next_string_id; + u8 manufacturer_override; + u8 product_override; + u8 serial_override; /* the gadget driver won't enable the data pullup * while the deactivation count is nonzero. From 7c2b61d02c384a0d5867e524ae72ad98ec2d33fd Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 12 Aug 2010 17:43:47 +0200 Subject: [PATCH 017/141] USB: gadget: mass_storage: moved strings handling code to composite This patch removes string registration from the Mass Storage Gadget. With recent changes to the composite framework, all that we need is handled by the composite layer. This means composite registers a string ID for manufacturer and product. This also adds the "needs_serial" so that composite layer will issue a warning if user space fails to provide the iSerialNumber module parameter. Signed-off-by: Michal Nazarewicz Signed-off-by: Kyungmin Park Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/mass_storage.c | 72 +++---------------------------- 1 file changed, 6 insertions(+), 66 deletions(-) diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 585f2559484d..493d15339843 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -75,10 +75,6 @@ static struct usb_device_descriptor msg_device_desc = { /* Vendor and product id can be overridden by module parameters. */ .idVendor = cpu_to_le16(FSG_VENDOR_ID), .idProduct = cpu_to_le16(FSG_PRODUCT_ID), - /* .bcdDevice = f(hardware) */ - /* .iManufacturer = DYNAMIC */ - /* .iProduct = DYNAMIC */ - /* NO SERIAL NUMBER */ .bNumConfigurations = 1, }; @@ -86,7 +82,8 @@ static struct usb_otg_descriptor otg_descriptor = { .bLength = sizeof otg_descriptor, .bDescriptorType = USB_DT_OTG, - /* REVISIT SRP-only hardware is possible, although + /* + * REVISIT SRP-only hardware is possible, although * it would not be called "OTG" ... */ .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, @@ -98,33 +95,6 @@ static const struct usb_descriptor_header *otg_desc[] = { }; -/* string IDs are assigned dynamically */ - -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 -#define STRING_CONFIGURATION_IDX 2 - -static char manufacturer[50]; - -static struct usb_string strings_dev[] = { - [STRING_MANUFACTURER_IDX].s = manufacturer, - [STRING_PRODUCT_IDX].s = DRIVER_DESC, - [STRING_CONFIGURATION_IDX].s = "Self Powered", - { } /* end of list */ -}; - -static struct usb_gadget_strings stringtab_dev = { - .language = 0x0409, /* en-us */ - .strings = strings_dev, -}; - -static struct usb_gadget_strings *dev_strings[] = { - &stringtab_dev, - NULL, -}; - - - /****************************** Configurations ******************************/ static struct fsg_module_parameters mod_data = { @@ -173,52 +143,22 @@ static struct usb_configuration msg_config_driver = { .label = "Linux File-Backed Storage", .bind = msg_do_config, .bConfigurationValue = 1, - /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, }; - /****************************** Gadget Bind ******************************/ - static int __ref msg_bind(struct usb_composite_dev *cdev) { - struct usb_gadget *gadget = cdev->gadget; int status; - /* Allocate string descriptor numbers ... note that string - * contents can be overridden by the composite_dev glue. - */ - - /* device descriptor strings: manufacturer, product */ - snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - gadget->name); - status = usb_string_id(cdev); - if (status < 0) - return status; - strings_dev[STRING_MANUFACTURER_IDX].id = status; - msg_device_desc.iManufacturer = status; - - status = usb_string_id(cdev); - if (status < 0) - return status; - strings_dev[STRING_PRODUCT_IDX].id = status; - msg_device_desc.iProduct = status; - - status = usb_string_id(cdev); - if (status < 0) - return status; - strings_dev[STRING_CONFIGURATION_IDX].id = status; - msg_config_driver.iConfiguration = status; - - /* register our second configuration */ status = usb_add_config(cdev, &msg_config_driver); if (status < 0) return status; - dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); + dev_info(&cdev->gadget->dev, + DRIVER_DESC ", version: " DRIVER_VERSION "\n"); set_bit(0, &msg_registered); return 0; } @@ -226,12 +166,12 @@ static int __ref msg_bind(struct usb_composite_dev *cdev) /****************************** Some noise ******************************/ - static struct usb_composite_driver msg_driver = { .name = "g_mass_storage", .dev = &msg_device_desc, - .strings = dev_strings, .bind = msg_bind, + .iProduct = DRIVER_DESC, + .needs_serial = 1, }; MODULE_DESCRIPTION(DRIVER_DESC); From a99d8a45bc2f495be45b8d417b795d7282a69091 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 12 Aug 2010 17:43:49 +0200 Subject: [PATCH 018/141] USB: gadget: g_multi: moved strings handling code to composite This patch removes some of the string registration from the Multifunction Composite Gadget as composite layer can handle the iManufacturer and iProduct for us. This also adds the "needs_serial" so that composite layer will issue a warning if user space fails to provide the iSerialNumber module parameter. Signed-off-by: Michal Nazarewicz Signed-off-by: Kyungmin Park Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/multi.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 36d67a32abef..ca51661d71db 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -121,8 +121,6 @@ static const struct usb_descriptor_header *otg_desc[] = { enum { - MULTI_STRING_MANUFACTURER_IDX, - MULTI_STRING_PRODUCT_IDX, #ifdef CONFIG_USB_G_MULTI_RNDIS MULTI_STRING_RNDIS_CONFIG_IDX, #endif @@ -131,11 +129,7 @@ enum { #endif }; -static char manufacturer[50]; - static struct usb_string strings_dev[] = { - [MULTI_STRING_MANUFACTURER_IDX].s = manufacturer, - [MULTI_STRING_PRODUCT_IDX].s = DRIVER_DESC, #ifdef CONFIG_USB_G_MULTI_RNDIS [MULTI_STRING_RNDIS_CONFIG_IDX].s = "Multifunction with RNDIS", #endif @@ -314,20 +308,11 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099); } - /* allocate string descriptor numbers */ - snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - gadget->name); - + /* allocate string IDs */ status = usb_string_ids_tab(cdev, strings_dev); if (unlikely(status < 0)) goto fail2; - device_desc.iManufacturer = - strings_dev[MULTI_STRING_MANUFACTURER_IDX].id; - device_desc.iProduct = - strings_dev[MULTI_STRING_PRODUCT_IDX].id; - /* register configurations */ status = rndis_config_register(cdev); if (unlikely(status < 0)) @@ -370,6 +355,8 @@ static struct usb_composite_driver multi_driver = { .strings = dev_strings, .bind = multi_bind, .unbind = __exit_p(multi_unbind), + .iProduct = DRIVER_DESC, + .needs_serial = 1, }; From e12995ec8f8d99f2a339541fc28998af2d60af0f Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 12 Aug 2010 17:43:52 +0200 Subject: [PATCH 019/141] USB: Revert "USB: gadget: section mismatch warning fixed" This reverts a commit which proposed an invalid solution for a section mismatch. Next 3 commits will fix it correctly. Conflicts: drivers/usb/gadget/mass_storage.c Signed-off-by: Michal Nazarewicz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/audio.c | 4 ++-- drivers/usb/gadget/cdc2.c | 4 ++-- drivers/usb/gadget/ether.c | 6 +++--- drivers/usb/gadget/f_loopback.c | 4 ++-- drivers/usb/gadget/f_sourcesink.c | 2 +- drivers/usb/gadget/file_storage.c | 2 +- drivers/usb/gadget/gmidi.c | 2 +- drivers/usb/gadget/hid.c | 4 ++-- drivers/usb/gadget/mass_storage.c | 4 ++-- drivers/usb/gadget/printer.c | 2 +- drivers/usb/gadget/serial.c | 4 ++-- drivers/usb/gadget/webcam.c | 4 ++-- drivers/usb/gadget/zero.c | 2 +- 13 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index b744ccd0f34d..a62af7b59094 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -89,7 +89,7 @@ static const struct usb_descriptor_header *otg_desc[] = { /*-------------------------------------------------------------------------*/ -static int __ref audio_do_config(struct usb_configuration *c) +static int __init audio_do_config(struct usb_configuration *c) { /* FIXME alloc iConfiguration string, set it in c->strings */ @@ -113,7 +113,7 @@ static struct usb_configuration audio_config_driver = { /*-------------------------------------------------------------------------*/ -static int __ref audio_bind(struct usb_composite_dev *cdev) +static int __init audio_bind(struct usb_composite_dev *cdev) { int gcnum; int status; diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 1f5ba2fd4c1f..928137d3dbdc 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -129,7 +129,7 @@ static u8 hostaddr[ETH_ALEN]; /* * We _always_ have both CDC ECM and CDC ACM functions. */ -static int __ref cdc_do_config(struct usb_configuration *c) +static int __init cdc_do_config(struct usb_configuration *c) { int status; @@ -159,7 +159,7 @@ static struct usb_configuration cdc_config_driver = { /*-------------------------------------------------------------------------*/ -static int __ref cdc_bind(struct usb_composite_dev *cdev) +static int __init cdc_bind(struct usb_composite_dev *cdev) { int gcnum; struct usb_gadget *gadget = cdev->gadget; diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 114fa024c22c..400f80372d93 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -237,7 +237,7 @@ static u8 hostaddr[ETH_ALEN]; * the first one present. That's to make Microsoft's drivers happy, * and to follow DOCSIS 1.0 (cable modem standard). */ -static int __ref rndis_do_config(struct usb_configuration *c) +static int __init rndis_do_config(struct usb_configuration *c) { /* FIXME alloc iConfiguration string, set it in c->strings */ @@ -270,7 +270,7 @@ MODULE_PARM_DESC(use_eem, "use CDC EEM mode"); /* * We _always_ have an ECM, CDC Subset, or EEM configuration. */ -static int __ref eth_do_config(struct usb_configuration *c) +static int __init eth_do_config(struct usb_configuration *c) { /* FIXME alloc iConfiguration string, set it in c->strings */ @@ -297,7 +297,7 @@ static struct usb_configuration eth_config_driver = { /*-------------------------------------------------------------------------*/ -static int __ref eth_bind(struct usb_composite_dev *cdev) +static int __init eth_bind(struct usb_composite_dev *cdev) { int gcnum; struct usb_gadget *gadget = cdev->gadget; diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 43225879c3cd..e91d1b16d9be 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -324,7 +324,7 @@ static void loopback_disable(struct usb_function *f) /*-------------------------------------------------------------------------*/ -static int __ref loopback_bind_config(struct usb_configuration *c) +static int __init loopback_bind_config(struct usb_configuration *c) { struct f_loopback *loop; int status; @@ -346,7 +346,7 @@ static int __ref loopback_bind_config(struct usb_configuration *c) return status; } -static struct usb_configuration loopback_driver = { +static struct usb_configuration loopback_driver = { .label = "loopback", .strings = loopback_strings, .bind = loopback_bind_config, diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index 685d768f336e..6d3cc443d914 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -404,7 +404,7 @@ static void sourcesink_disable(struct usb_function *f) /*-------------------------------------------------------------------------*/ -static int __ref sourcesink_bind_config(struct usb_configuration *c) +static int __init sourcesink_bind_config(struct usb_configuration *c) { struct f_sourcesink *ss; int status; diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index ab77792a4361..aae04c20b0ea 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -3348,7 +3348,7 @@ fill_serial: } -static int __ref fsg_bind(struct usb_gadget *gadget) +static int __init fsg_bind(struct usb_gadget *gadget) { struct fsg_dev *fsg = the_fsg; int rc; diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 1b413a5cc3f6..b7bf88019b06 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -1157,7 +1157,7 @@ fail: /* * Creates an output endpoint, and initializes output ports. */ -static int __ref gmidi_bind(struct usb_gadget *gadget) +static int __init gmidi_bind(struct usb_gadget *gadget) { struct gmidi_device *dev; struct usb_ep *in_ep, *out_ep; diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 735495bf8411..775722686ed8 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -127,7 +127,7 @@ static struct usb_gadget_strings *dev_strings[] = { /****************************** Configurations ******************************/ -static int __ref do_config(struct usb_configuration *c) +static int __init do_config(struct usb_configuration *c) { struct hidg_func_node *e; int func = 0, status = 0; @@ -156,7 +156,7 @@ static struct usb_configuration config_driver = { /****************************** Gadget Bind ******************************/ -static int __ref hid_bind(struct usb_composite_dev *cdev) +static int __init hid_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; struct list_head *tmp; diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 493d15339843..05e9bd330348 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -111,7 +111,7 @@ static int msg_thread_exits(struct fsg_common *common) return 0; } -static int __ref msg_do_config(struct usb_configuration *c) +static int __init msg_do_config(struct usb_configuration *c) { static const struct fsg_operations ops = { .thread_exits = msg_thread_exits, @@ -149,7 +149,7 @@ static struct usb_configuration msg_config_driver = { /****************************** Gadget Bind ******************************/ -static int __ref msg_bind(struct usb_composite_dev *cdev) +static int __init msg_bind(struct usb_composite_dev *cdev) { int status; diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index cf241c371a71..04c7bbf121af 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -1347,7 +1347,7 @@ printer_unbind(struct usb_gadget *gadget) set_gadget_data(gadget, NULL); } -static int __ref +static int __init printer_bind(struct usb_gadget *gadget) { struct printer_dev *dev; diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index b22eedbc7dc5..f46a60962dab 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -137,7 +137,7 @@ MODULE_PARM_DESC(n_ports, "number of ports to create, default=1"); /*-------------------------------------------------------------------------*/ -static int __ref serial_bind_config(struct usb_configuration *c) +static int __init serial_bind_config(struct usb_configuration *c) { unsigned i; int status = 0; @@ -161,7 +161,7 @@ static struct usb_configuration serial_config_driver = { .bmAttributes = USB_CONFIG_ATT_SELFPOWER, }; -static int __ref gs_bind(struct usb_composite_dev *cdev) +static int __init gs_bind(struct usb_composite_dev *cdev) { int gcnum; struct usb_gadget *gadget = cdev->gadget; diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index de1deb7a3c63..288d21155abe 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -308,7 +308,7 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = { * USB configuration */ -static int __ref +static int __init webcam_config_bind(struct usb_configuration *c) { return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls, @@ -330,7 +330,7 @@ webcam_unbind(struct usb_composite_dev *cdev) return 0; } -static int __ref +static int __init webcam_bind(struct usb_composite_dev *cdev) { int ret; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index cf353920bb1c..807280d069f9 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -264,7 +264,7 @@ static void zero_resume(struct usb_composite_dev *cdev) /*-------------------------------------------------------------------------*/ -static int __ref zero_bind(struct usb_composite_dev *cdev) +static int __init zero_bind(struct usb_composite_dev *cdev) { int gcnum; struct usb_gadget *gadget = cdev->gadget; From b0fca50f5a94a268ed02cfddf44448051ed9343f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 12 Aug 2010 17:43:53 +0200 Subject: [PATCH 020/141] usb gadget: don't save bind callback in struct usb_gadget_driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To accomplish this the function to register a gadget driver takes the bind function as a second argument. To make things clearer rename the function to resemble platform_driver_probe. This fixes many section mismatches like WARNING: drivers/usb/gadget/g_printer.o(.data+0xc): Section mismatch in reference from the variable printer_driver to the function .init.text:printer_bind() The variable printer_driver references the function __init printer_bind() All callers are fixed. Signed-off-by: Uwe Kleine-König [m.nazarewicz@samsung.com: added dbgp] Signed-off-by: MichaÅ‚ Nazarewicz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/amd5536udc.c | 9 +++++---- drivers/usb/gadget/at91_udc.c | 11 ++++++----- drivers/usb/gadget/atmel_usba_udc.c | 7 ++++--- drivers/usb/gadget/ci13xxx_udc.c | 18 ++++++++++-------- drivers/usb/gadget/composite.c | 3 +-- drivers/usb/gadget/dbgp.c | 3 +-- drivers/usb/gadget/dummy_hcd.c | 10 +++++----- drivers/usb/gadget/file_storage.c | 3 +-- drivers/usb/gadget/fsl_qe_udc.c | 12 ++++++------ drivers/usb/gadget/fsl_udc_core.c | 10 +++++----- drivers/usb/gadget/gmidi.c | 3 +-- drivers/usb/gadget/goku_udc.c | 9 +++++---- drivers/usb/gadget/imx_udc.c | 9 +++++---- drivers/usb/gadget/inode.c | 6 ++---- drivers/usb/gadget/langwell_udc.c | 9 +++++---- drivers/usb/gadget/lh7a40x_udc.c | 10 +++++----- drivers/usb/gadget/m66592-udc.c | 9 +++++---- drivers/usb/gadget/net2280.c | 10 +++++----- drivers/usb/gadget/omap_udc.c | 10 +++++----- drivers/usb/gadget/printer.c | 5 ++--- drivers/usb/gadget/pxa25x_udc.c | 9 +++++---- drivers/usb/gadget/pxa27x_udc.c | 12 +++++++----- drivers/usb/gadget/r8a66597-udc.c | 9 +++++---- drivers/usb/gadget/s3c-hsotg.c | 9 +++++---- drivers/usb/gadget/s3c2410_udc.c | 17 ++++++++--------- drivers/usb/musb/musb_gadget.c | 11 ++++++----- include/linux/usb/gadget.h | 20 ++++++++------------ 27 files changed, 128 insertions(+), 125 deletions(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 731150d4b1d9..fadebfd53b47 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -1954,13 +1954,14 @@ static int setup_ep0(struct udc *dev) } /* Called by gadget driver to register itself */ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct udc *dev = udc; int retval; u32 tmp; - if (!driver || !driver->bind || !driver->setup + if (!driver || !bind || !driver->setup || driver->speed != USB_SPEED_HIGH) return -EINVAL; if (!dev) @@ -1972,7 +1973,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) dev->driver = driver; dev->gadget.dev.driver = &driver->driver; - retval = driver->bind(&dev->gadget); + retval = bind(&dev->gadget); /* Some gadget drivers use both ep0 directions. * NOTE: to gadget driver, ep0 is just one endpoint... @@ -2000,7 +2001,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) return 0; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); /* shutdown requests and disconnect from gadget */ static void diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 93ead19507b6..387e503b9d14 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1628,7 +1628,8 @@ static void at91_vbus_timer(unsigned long data) schedule_work(&udc->vbus_timer_work); } -int usb_gadget_register_driver (struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct at91_udc *udc = &controller; int retval; @@ -1636,7 +1637,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) if (!driver || driver->speed < USB_SPEED_FULL - || !driver->bind + || !bind || !driver->setup) { DBG("bad parameter.\n"); return -EINVAL; @@ -1653,9 +1654,9 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) udc->enabled = 1; udc->selfpowered = 1; - retval = driver->bind(&udc->gadget); + retval = bind(&udc->gadget); if (retval) { - DBG("driver->bind() returned %d\n", retval); + DBG("bind() returned %d\n", retval); udc->driver = NULL; udc->gadget.dev.driver = NULL; dev_set_drvdata(&udc->gadget.dev, NULL); @@ -1671,7 +1672,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) DBG("bound to %s\n", driver->driver.name); return 0; } -EXPORT_SYMBOL (usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) { diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index d623c7bda1f6..e4810c6a0b1f 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -1789,7 +1789,8 @@ out: return IRQ_HANDLED; } -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct usba_udc *udc = &the_udc; unsigned long flags; @@ -1812,7 +1813,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) clk_enable(udc->pclk); clk_enable(udc->hclk); - ret = driver->bind(&udc->gadget); + ret = bind(&udc->gadget); if (ret) { DBG(DBG_ERR, "Could not bind to driver %s: error %d\n", driver->driver.name, ret); @@ -1841,7 +1842,7 @@ err_driver_bind: udc->gadget.dev.driver = NULL; return ret; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) { diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 699695128e33..98b36fc88c77 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -2340,12 +2340,15 @@ static const struct usb_ep_ops usb_ep_ops = { static const struct usb_gadget_ops usb_gadget_ops; /** - * usb_gadget_register_driver: register a gadget driver + * usb_gadget_probe_driver: register a gadget driver + * @driver: the driver being registered + * @bind: the driver's bind callback * - * Check usb_gadget_register_driver() at "usb_gadget.h" for details - * Interrupts are enabled here + * Check usb_gadget_probe_driver() at for details. + * Interrupts are enabled here. */ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct ci13xxx *udc = _udc; unsigned long i, k, flags; @@ -2354,7 +2357,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) trace("%p", driver); if (driver == NULL || - driver->bind == NULL || + bind == NULL || driver->unbind == NULL || driver->setup == NULL || driver->disconnect == NULL || @@ -2430,7 +2433,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) udc->gadget.dev.driver = &driver->driver; spin_unlock_irqrestore(udc->lock, flags); - retval = driver->bind(&udc->gadget); /* MAY SLEEP */ + retval = bind(&udc->gadget); /* MAY SLEEP */ spin_lock_irqsave(udc->lock, flags); if (retval) { @@ -2447,7 +2450,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) usb_gadget_unregister_driver(driver); return retval; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); /** * usb_gadget_unregister_driver: unregister a gadget driver @@ -2462,7 +2465,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) trace("%p", driver); if (driver == NULL || - driver->bind == NULL || driver->unbind == NULL || driver->setup == NULL || driver->disconnect == NULL || diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 717de39627c7..a3009bf01229 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1213,7 +1213,6 @@ composite_resume(struct usb_gadget *gadget) static struct usb_gadget_driver composite_driver = { .speed = USB_SPEED_HIGH, - .bind = composite_bind, .unbind = composite_unbind, .setup = composite_setup, @@ -1255,7 +1254,7 @@ int usb_composite_register(struct usb_composite_driver *driver) composite_driver.driver.name = driver->name; composite = driver; - return usb_gadget_register_driver(&composite_driver); + return usb_gadget_probe_driver(&composite_driver, composite_bind); } /** diff --git a/drivers/usb/gadget/dbgp.c b/drivers/usb/gadget/dbgp.c index abe4a2ec5625..e5ac8a316fec 100644 --- a/drivers/usb/gadget/dbgp.c +++ b/drivers/usb/gadget/dbgp.c @@ -403,7 +403,6 @@ fail: static struct usb_gadget_driver dbgp_driver = { .function = "dbgp", .speed = USB_SPEED_HIGH, - .bind = dbgp_bind, .unbind = dbgp_unbind, .setup = dbgp_setup, .disconnect = dbgp_disconnect, @@ -415,7 +414,7 @@ static struct usb_gadget_driver dbgp_driver = { static int __init dbgp_init(void) { - return usb_gadget_register_driver(&dbgp_driver); + return usb_gadget_probe_driver(&dbgp_driver, dbgp_bind); } static void __exit dbgp_exit(void) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index dc6546248ed9..7bb9d78aac27 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -748,7 +748,8 @@ static DEVICE_ATTR (function, S_IRUGO, show_function, NULL); */ int -usb_gadget_register_driver (struct usb_gadget_driver *driver) +usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct dummy *dum = the_controller; int retval, i; @@ -757,8 +758,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) return -EINVAL; if (dum->driver) return -EBUSY; - if (!driver->bind || !driver->setup - || driver->speed == USB_SPEED_UNKNOWN) + if (!bind || !driver->setup || driver->speed == USB_SPEED_UNKNOWN) return -EINVAL; /* @@ -796,7 +796,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) dum->gadget.dev.driver = &driver->driver; dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n", driver->driver.name); - retval = driver->bind(&dum->gadget); + retval = bind(&dum->gadget); if (retval) { dum->driver = NULL; dum->gadget.dev.driver = NULL; @@ -812,7 +812,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) usb_hcd_poll_rh_status (dummy_to_hcd (dum)); return 0; } -EXPORT_SYMBOL (usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index aae04c20b0ea..132a1c0877bd 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -3608,7 +3608,6 @@ static struct usb_gadget_driver fsg_driver = { .speed = USB_SPEED_FULL, #endif .function = (char *) fsg_string_product, - .bind = fsg_bind, .unbind = fsg_unbind, .disconnect = fsg_disconnect, .setup = fsg_setup, @@ -3650,7 +3649,7 @@ static int __init fsg_init(void) if ((rc = fsg_alloc()) != 0) return rc; fsg = the_fsg; - if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0) + if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0) kref_put(&fsg->ref, fsg_release); return rc; } diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index a5ea2c1d8c93..792d5ef40137 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -2302,9 +2302,10 @@ static irqreturn_t qe_udc_irq(int irq, void *_udc) } /*------------------------------------------------------------------------- - Gadget driver register and unregister. + Gadget driver probe and unregister. --------------------------------------------------------------------------*/ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { int retval; unsigned long flags = 0; @@ -2315,8 +2316,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) if (!driver || (driver->speed != USB_SPEED_FULL && driver->speed != USB_SPEED_HIGH) - || !driver->bind || !driver->disconnect - || !driver->setup) + || !bind || !driver->disconnect || !driver->setup) return -EINVAL; if (udc_controller->driver) @@ -2332,7 +2332,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) udc_controller->gadget.speed = (enum usb_device_speed)(driver->speed); spin_unlock_irqrestore(&udc_controller->lock, flags); - retval = driver->bind(&udc_controller->gadget); + retval = bind(&udc_controller->gadget); if (retval) { dev_err(udc_controller->dev, "bind to %s --> %d", driver->driver.name, retval); @@ -2353,7 +2353,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) udc_controller->gadget.name, driver->driver.name); return 0; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) { diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 08a9a62a39e3..c16b402a876b 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1765,7 +1765,8 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc) * Hook to gadget drivers * Called by initialization code of gadget drivers *----------------------------------------------------------------*/ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { int retval = -ENODEV; unsigned long flags = 0; @@ -1775,8 +1776,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) if (!driver || (driver->speed != USB_SPEED_FULL && driver->speed != USB_SPEED_HIGH) - || !driver->bind || !driver->disconnect - || !driver->setup) + || !bind || !driver->disconnect || !driver->setup) return -EINVAL; if (udc_controller->driver) @@ -1792,7 +1792,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) spin_unlock_irqrestore(&udc_controller->lock, flags); /* bind udc driver to gadget driver */ - retval = driver->bind(&udc_controller->gadget); + retval = bind(&udc_controller->gadget); if (retval) { VDBG("bind to %s --> %d", driver->driver.name, retval); udc_controller->gadget.dev.driver = NULL; @@ -1814,7 +1814,7 @@ out: retval); return retval; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); /* Disconnect from gadget driver */ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index b7bf88019b06..0ab7e141d494 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -1292,7 +1292,6 @@ static void gmidi_resume(struct usb_gadget *gadget) static struct usb_gadget_driver gmidi_driver = { .speed = USB_SPEED_FULL, .function = (char *)longname, - .bind = gmidi_bind, .unbind = gmidi_unbind, .setup = gmidi_setup, @@ -1309,7 +1308,7 @@ static struct usb_gadget_driver gmidi_driver = { static int __init gmidi_init(void) { - return usb_gadget_register_driver(&gmidi_driver); + return usb_gadget_probe_driver(&gmidi_driver, gmidi_bind); } module_init(gmidi_init); diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 1088d08c7ed8..49fbd4dbeb94 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1343,14 +1343,15 @@ static struct goku_udc *the_controller; * disconnect is reported. then a host may connect again, or * the driver might get unbound. */ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct goku_udc *dev = the_controller; int retval; if (!driver || driver->speed < USB_SPEED_FULL - || !driver->bind + || !bind || !driver->disconnect || !driver->setup) return -EINVAL; @@ -1363,7 +1364,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) driver->driver.bus = NULL; dev->driver = driver; dev->gadget.dev.driver = &driver->driver; - retval = driver->bind(&dev->gadget); + retval = bind(&dev->gadget); if (retval) { DBG(dev, "bind to driver %s --> error %d\n", driver->driver.name, retval); @@ -1380,7 +1381,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) DBG(dev, "registered gadget driver '%s'\n", driver->driver.name); return 0; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); static void stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver) diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index e743122fcd93..ed0266462c57 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1319,14 +1319,15 @@ static struct imx_udc_struct controller = { * USB gadged driver functions ******************************************************************************* */ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct imx_udc_struct *imx_usb = &controller; int retval; if (!driver || driver->speed < USB_SPEED_FULL - || !driver->bind + || !bind || !driver->disconnect || !driver->setup) return -EINVAL; @@ -1342,7 +1343,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) retval = device_add(&imx_usb->gadget.dev); if (retval) goto fail; - retval = driver->bind(&imx_usb->gadget); + retval = bind(&imx_usb->gadget); if (retval) { D_ERR(imx_usb->dev, "<%s> bind to driver %s --> error %d\n", __func__, driver->driver.name, retval); @@ -1362,7 +1363,7 @@ fail: imx_usb->gadget.dev.driver = NULL; return retval; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) { diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index fc35406fc80c..e2e8eda83f0d 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1775,7 +1775,6 @@ static struct usb_gadget_driver gadgetfs_driver = { .speed = USB_SPEED_FULL, #endif .function = (char *) driver_desc, - .bind = gadgetfs_bind, .unbind = gadgetfs_unbind, .setup = gadgetfs_setup, .disconnect = gadgetfs_disconnect, @@ -1798,7 +1797,6 @@ static int gadgetfs_probe (struct usb_gadget *gadget) static struct usb_gadget_driver probe_driver = { .speed = USB_SPEED_HIGH, - .bind = gadgetfs_probe, .unbind = gadgetfs_nop, .setup = (void *)gadgetfs_nop, .disconnect = gadgetfs_nop, @@ -1908,7 +1906,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) /* triggers gadgetfs_bind(); then we can enumerate. */ spin_unlock_irq (&dev->lock); - value = usb_gadget_register_driver (&gadgetfs_driver); + value = usb_gadget_probe_driver(&gadgetfs_driver, gadgetfs_bind); if (value != 0) { kfree (dev->buf); dev->buf = NULL; @@ -2047,7 +2045,7 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent) return -ESRCH; /* fake probe to determine $CHIP */ - (void) usb_gadget_register_driver (&probe_driver); + (void) usb_gadget_probe_driver(&probe_driver, gadgetfs_probe); if (!CHIP) return -ENODEV; diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index ccc9c070a30d..1ef17a6dcb51 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -1855,7 +1855,8 @@ static DEVICE_ATTR(remote_wakeup, S_IWUSR, NULL, store_remote_wakeup); * the driver might get unbound. */ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct langwell_udc *dev = the_controller; unsigned long flags; @@ -1878,7 +1879,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) spin_unlock_irqrestore(&dev->lock, flags); - retval = driver->bind(&dev->gadget); + retval = bind(&dev->gadget); if (retval) { dev_dbg(&dev->pdev->dev, "bind to driver %s --> %d\n", driver->driver.name, retval); @@ -1916,7 +1917,7 @@ err_unbind: dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); return retval; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); /* unregister gadget driver */ @@ -1930,7 +1931,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); - if (unlikely(!driver || !driver->bind || !driver->unbind)) + if (unlikely(!driver || !driver->unbind)) return -EINVAL; /* exit PHY low power suspend */ diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c index fded3fca793b..6b58bd8ce623 100644 --- a/drivers/usb/gadget/lh7a40x_udc.c +++ b/drivers/usb/gadget/lh7a40x_udc.c @@ -408,7 +408,8 @@ static void udc_enable(struct lh7a40x_udc *dev) /* Register entry point for the peripheral controller driver. */ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct lh7a40x_udc *dev = the_controller; int retval; @@ -417,7 +418,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) if (!driver || driver->speed != USB_SPEED_FULL - || !driver->bind + || !bind || !driver->disconnect || !driver->setup) return -EINVAL; @@ -431,7 +432,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) dev->gadget.dev.driver = &driver->driver; device_add(&dev->gadget.dev); - retval = driver->bind(&dev->gadget); + retval = bind(&dev->gadget); if (retval) { printk(KERN_WARNING "%s: bind to driver %s --> error %d\n", dev->gadget.name, driver->driver.name, retval); @@ -453,8 +454,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) return 0; } - -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); /* Unregister entry point for the peripheral controller driver. diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index e03058fe23cb..51b19f3027e7 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1454,14 +1454,15 @@ static struct usb_ep_ops m66592_ep_ops = { /*-------------------------------------------------------------------------*/ static struct m66592 *the_controller; -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct m66592 *m66592 = the_controller; int retval; if (!driver || driver->speed != USB_SPEED_HIGH - || !driver->bind + || !bind || !driver->setup) return -EINVAL; if (!m66592) @@ -1480,7 +1481,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) goto error; } - retval = driver->bind (&m66592->gadget); + retval = bind(&m66592->gadget); if (retval) { pr_err("bind to driver error (%d)\n", retval); device_del(&m66592->gadget.dev); @@ -1505,7 +1506,7 @@ error: return retval; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) { diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 9498be87a724..d09155b25d73 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -1929,7 +1929,8 @@ static void ep0_start (struct net2280 *dev) * disconnect is reported. then a host may connect again, or * the driver might get unbound. */ -int usb_gadget_register_driver (struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct net2280 *dev = the_controller; int retval; @@ -1941,8 +1942,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) */ if (!driver || driver->speed != USB_SPEED_HIGH - || !driver->bind - || !driver->setup) + || !bind || !driver->setup) return -EINVAL; if (!dev) return -ENODEV; @@ -1957,7 +1957,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) driver->driver.bus = NULL; dev->driver = driver; dev->gadget.dev.driver = &driver->driver; - retval = driver->bind (&dev->gadget); + retval = bind(&dev->gadget); if (retval) { DEBUG (dev, "bind to driver %s --> %d\n", driver->driver.name, retval); @@ -1993,7 +1993,7 @@ err_unbind: dev->driver = NULL; return retval; } -EXPORT_SYMBOL (usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); static void stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index f81e4f025f23..61d3ca6619bb 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2102,7 +2102,8 @@ static inline int machine_without_vbus_sense(void) ); } -int usb_gadget_register_driver (struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { int status = -ENODEV; struct omap_ep *ep; @@ -2114,8 +2115,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) if (!driver // FIXME if otg, check: driver->is_otg || driver->speed < USB_SPEED_FULL - || !driver->bind - || !driver->setup) + || !bind || !driver->setup) return -EINVAL; spin_lock_irqsave(&udc->lock, flags); @@ -2145,7 +2145,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) if (udc->dc_clk != NULL) omap_udc_enable_clock(1); - status = driver->bind (&udc->gadget); + status = bind(&udc->gadget); if (status) { DBG("bind to %s --> %d\n", driver->driver.name, status); udc->gadget.dev.driver = NULL; @@ -2186,7 +2186,7 @@ done: omap_udc_enable_clock(0); return status; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) { diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 04c7bbf121af..ded080a1c8ce 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -1543,7 +1543,6 @@ static struct usb_gadget_driver printer_driver = { .speed = DEVSPEED, .function = (char *) driver_desc, - .bind = printer_bind, .unbind = printer_unbind, .setup = printer_setup, @@ -1579,11 +1578,11 @@ init(void) return status; } - status = usb_gadget_register_driver(&printer_driver); + status = usb_gadget_probe_driver(&printer_driver, printer_bind); if (status) { class_destroy(usb_gadget_class); unregister_chrdev_region(g_printer_devno, 1); - DBG(dev, "usb_gadget_register_driver %x\n", status); + DBG(dev, "usb_gadget_probe_driver %x\n", status); } return status; diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index be5fb34d9602..b37f92cb71bc 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -1280,14 +1280,15 @@ static void udc_enable (struct pxa25x_udc *dev) * disconnect is reported. then a host may connect again, or * the driver might get unbound. */ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct pxa25x_udc *dev = the_controller; int retval; if (!driver || driver->speed < USB_SPEED_FULL - || !driver->bind + || !bind || !driver->disconnect || !driver->setup) return -EINVAL; @@ -1308,7 +1309,7 @@ fail: dev->gadget.dev.driver = NULL; return retval; } - retval = driver->bind(&dev->gadget); + retval = bind(&dev->gadget); if (retval) { DMSG("bind to driver %s --> error %d\n", driver->driver.name, retval); @@ -1338,7 +1339,7 @@ fail: bind_fail: return retval; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); static void stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 980762453a9c..027d66f81620 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1792,8 +1792,9 @@ static void udc_enable(struct pxa_udc *udc) } /** - * usb_gadget_register_driver - Register gadget driver + * usb_gadget_probe_driver - Register gadget driver * @driver: gadget driver + * @bind: bind function * * When a driver is successfully registered, it will receive control requests * including set_configuration(), which enables non-control requests. Then @@ -1805,12 +1806,13 @@ static void udc_enable(struct pxa_udc *udc) * * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise */ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct pxa_udc *udc = the_controller; int retval; - if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind + if (!driver || driver->speed < USB_SPEED_FULL || !bind || !driver->disconnect || !driver->setup) return -EINVAL; if (!udc) @@ -1828,7 +1830,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) dev_err(udc->dev, "device_add error %d\n", retval); goto add_fail; } - retval = driver->bind(&udc->gadget); + retval = bind(&udc->gadget); if (retval) { dev_err(udc->dev, "bind to driver %s --> error %d\n", driver->driver.name, retval); @@ -1859,7 +1861,7 @@ add_fail: udc->gadget.dev.driver = NULL; return retval; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); /** diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index 2456ccd9965e..95092151f901 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -1405,14 +1405,15 @@ static struct usb_ep_ops r8a66597_ep_ops = { /*-------------------------------------------------------------------------*/ static struct r8a66597 *the_controller; -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct r8a66597 *r8a66597 = the_controller; int retval; if (!driver || driver->speed != USB_SPEED_HIGH - || !driver->bind + || !bind || !driver->setup) return -EINVAL; if (!r8a66597) @@ -1431,7 +1432,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) goto error; } - retval = driver->bind(&r8a66597->gadget); + retval = bind(&r8a66597->gadget); if (retval) { printk(KERN_ERR "bind to driver error (%d)\n", retval); device_del(&r8a66597->gadget.dev); @@ -1456,7 +1457,7 @@ error: return retval; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) { diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index a229744a8c7d..ef825c3baed9 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2523,7 +2523,8 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg) return 0; } -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct s3c_hsotg *hsotg = our_hsotg; int ret; @@ -2543,7 +2544,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) dev_err(hsotg->dev, "%s: bad speed\n", __func__); } - if (!driver->bind || !driver->setup) { + if (!bind || !driver->setup) { dev_err(hsotg->dev, "%s: missing entry points\n", __func__); return -EINVAL; } @@ -2562,7 +2563,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) goto err; } - ret = driver->bind(&hsotg->gadget); + ret = bind(&hsotg->gadget); if (ret) { dev_err(hsotg->dev, "failed bind %s\n", driver->driver.name); @@ -2687,7 +2688,7 @@ err: hsotg->gadget.dev.driver = NULL; return ret; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) { diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index ea2b3c7ebee5..c2448950a8d8 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1632,15 +1632,15 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev) } /* - * usb_gadget_register_driver + * usb_gadget_probe_driver */ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { struct s3c2410_udc *udc = the_controller; int retval; - dprintk(DEBUG_NORMAL, "usb_gadget_register_driver() '%s'\n", - driver->driver.name); + dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name); /* Sanity checks */ if (!udc) @@ -1649,10 +1649,9 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) if (udc->driver) return -EBUSY; - if (!driver->bind || !driver->setup - || driver->speed < USB_SPEED_FULL) { + if (!bind || !driver->setup || driver->speed < USB_SPEED_FULL) { printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n", - driver->bind, driver->setup, driver->speed); + bind, driver->setup, driver->speed); return -EINVAL; } #if defined(MODULE) @@ -1675,7 +1674,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n", driver->driver.name); - if ((retval = driver->bind (&udc->gadget)) != 0) { + if ((retval = bind(&udc->gadget)) != 0) { device_del(&udc->gadget.dev); goto register_error; } @@ -1690,6 +1689,7 @@ register_error: udc->gadget.dev.driver = NULL; return retval; } +EXPORT_SYMBOL(usb_gadget_probe_driver); /* * usb_gadget_unregister_driver @@ -2049,7 +2049,6 @@ static void __exit udc_exit(void) } EXPORT_SYMBOL(usb_gadget_unregister_driver); -EXPORT_SYMBOL(usb_gadget_register_driver); module_init(udc_init); module_exit(udc_exit); diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d065e23f123e..ecd5f8cffcbf 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1699,9 +1699,11 @@ void musb_gadget_cleanup(struct musb *musb) * -ENOMEM no memeory to perform the operation * * @param driver the gadget driver + * @param bind the driver's bind function * @return <0 if error, 0 if everything is fine */ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)) { int retval; unsigned long flags; @@ -1709,8 +1711,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) if (!driver || driver->speed != USB_SPEED_HIGH - || !driver->bind - || !driver->setup) + || !bind || !driver->setup) return -EINVAL; /* driver must be initialized to support peripheral mode */ @@ -1738,7 +1739,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) spin_unlock_irqrestore(&musb->lock, flags); if (retval == 0) { - retval = driver->bind(&musb->g); + retval = bind(&musb->g); if (retval != 0) { DBG(3, "bind to driver %s failed --> %d\n", driver->driver.name, retval); @@ -1786,7 +1787,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) return retval; } -EXPORT_SYMBOL(usb_gadget_register_driver); +EXPORT_SYMBOL(usb_gadget_probe_driver); static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver) { diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index d3ef42d7d2f0..006412ce2303 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -705,11 +705,6 @@ static inline int usb_gadget_disconnect(struct usb_gadget *gadget) * struct usb_gadget_driver - driver for usb 'slave' devices * @function: String describing the gadget's function * @speed: Highest speed the driver handles. - * @bind: Invoked when the driver is bound to a gadget, usually - * after registering the driver. - * At that point, ep0 is fully initialized, and ep_list holds - * the currently-available endpoints. - * Called in a context that permits sleeping. * @setup: Invoked for ep0 control requests that aren't handled by * the hardware level driver. Most calls must be handled by * the gadget driver, including descriptor and configuration @@ -774,7 +769,6 @@ static inline int usb_gadget_disconnect(struct usb_gadget *gadget) struct usb_gadget_driver { char *function; enum usb_device_speed speed; - int (*bind)(struct usb_gadget *); void (*unbind)(struct usb_gadget *); int (*setup)(struct usb_gadget *, const struct usb_ctrlrequest *); @@ -798,17 +792,19 @@ struct usb_gadget_driver { */ /** - * usb_gadget_register_driver - register a gadget driver - * @driver:the driver being registered + * usb_gadget_probe_driver - probe a gadget driver + * @driver: the driver being registered + * @bind: the driver's bind callback * Context: can sleep * * Call this in your gadget driver's module initialization function, * to tell the underlying usb controller driver about your driver. - * The driver's bind() function will be called to bind it to a - * gadget before this registration call returns. It's expected that - * the bind() functions will be in init sections. + * The @bind() function will be called to bind it to a gadget before this + * registration call returns. It's expected that the @bind() function will + * be in init sections. */ -int usb_gadget_register_driver(struct usb_gadget_driver *driver); +int usb_gadget_probe_driver(struct usb_gadget_driver *driver, + int (*bind)(struct usb_gadget *)); /** * usb_gadget_unregister_driver - unregister a gadget driver From 07a18bd716ed5dea336429404b132568cfaaef95 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 12 Aug 2010 17:43:54 +0200 Subject: [PATCH 021/141] usb gadget: don't save bind callback in struct usb_composite_driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bind function is most of the time only called at init time so there is no need to save a pointer to it in the composite driver structure. This fixes many section mismatches reported by modpost. Signed-off-by: MichaÅ‚ Nazarewicz Acked-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/audio.c | 3 +-- drivers/usb/gadget/cdc2.c | 3 +-- drivers/usb/gadget/composite.c | 15 +++++++++++---- drivers/usb/gadget/ether.c | 3 +-- drivers/usb/gadget/g_ffs.c | 3 +-- drivers/usb/gadget/hid.c | 3 +-- drivers/usb/gadget/mass_storage.c | 3 +-- drivers/usb/gadget/multi.c | 3 +-- drivers/usb/gadget/nokia.c | 3 +-- drivers/usb/gadget/serial.c | 3 +-- drivers/usb/gadget/webcam.c | 3 +-- drivers/usb/gadget/zero.c | 3 +-- include/linux/usb/composite.h | 19 +++++-------------- 13 files changed, 27 insertions(+), 40 deletions(-) diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index a62af7b59094..5a65fbb4e20b 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -166,13 +166,12 @@ static struct usb_composite_driver audio_driver = { .name = "g_audio", .dev = &device_desc, .strings = audio_strings, - .bind = audio_bind, .unbind = __exit_p(audio_unbind), }; static int __init init(void) { - return usb_composite_register(&audio_driver); + return usb_composite_probe(&audio_driver, audio_bind); } module_init(init); diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 928137d3dbdc..1f2a9b1e4f2d 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -245,7 +245,6 @@ static struct usb_composite_driver cdc_driver = { .name = "g_cdc", .dev = &device_desc, .strings = dev_strings, - .bind = cdc_bind, .unbind = __exit_p(cdc_unbind), }; @@ -255,7 +254,7 @@ MODULE_LICENSE("GPL"); static int __init init(void) { - return usb_composite_register(&cdc_driver); + return usb_composite_probe(&cdc_driver, cdc_bind); } module_init(init); diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index a3009bf01229..c531a7e05f1e 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -40,6 +40,7 @@ #define USB_BUFSIZ 1024 static struct usb_composite_driver *composite; +static int (*composite_gadget_bind)(struct usb_composite_dev *cdev); /* Some systems will need runtime overrides for the product identifers * published in the device descriptor, either numbers or strings or both. @@ -1115,7 +1116,7 @@ static int composite_bind(struct usb_gadget *gadget) * serial number), register function drivers, potentially update * power state and consumption, etc */ - status = composite->bind(cdev); + status = composite_gadget_bind(cdev); if (status < 0) goto fail; @@ -1227,8 +1228,12 @@ static struct usb_gadget_driver composite_driver = { }; /** - * usb_composite_register() - register a composite driver + * usb_composite_probe() - register a composite driver * @driver: the driver to register + * @bind: the callback used to allocate resources that are shared across the + * whole device, such as string IDs, and add its configurations using + * @usb_add_config(). This may fail by returning a negative errno + * value; it should return zero on successful initialization. * Context: single threaded during gadget setup * * This function is used to register drivers using the composite driver @@ -1241,9 +1246,10 @@ static struct usb_gadget_driver composite_driver = { * while it was binding. That would usually be done in order to wait for * some userspace participation. */ -int usb_composite_register(struct usb_composite_driver *driver) +extern int usb_composite_probe(struct usb_composite_driver *driver, + int (*bind)(struct usb_composite_dev *cdev)) { - if (!driver || !driver->dev || !driver->bind || composite) + if (!driver || !driver->dev || !bind || composite) return -EINVAL; if (!driver->iProduct) @@ -1253,6 +1259,7 @@ int usb_composite_register(struct usb_composite_driver *driver) composite_driver.function = (char *) driver->name; composite_driver.driver.name = driver->name; composite = driver; + composite_gadget_bind = bind; return usb_gadget_probe_driver(&composite_driver, composite_bind); } diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 400f80372d93..33076bca9936 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -402,7 +402,6 @@ static struct usb_composite_driver eth_driver = { .name = "g_ether", .dev = &device_desc, .strings = dev_strings, - .bind = eth_bind, .unbind = __exit_p(eth_unbind), }; @@ -412,7 +411,7 @@ MODULE_LICENSE("GPL"); static int __init init(void) { - return usb_composite_register(ð_driver); + return usb_composite_probe(ð_driver, eth_bind); } module_init(init); diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 52fd3fa0d130..9fcb15879506 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -147,7 +147,6 @@ static struct usb_composite_driver gfs_driver = { .name = DRIVER_NAME, .dev = &gfs_dev_desc, .strings = gfs_dev_strings, - .bind = gfs_bind, .unbind = gfs_unbind, .iProduct = DRIVER_DESC, }; @@ -187,7 +186,7 @@ static int functionfs_ready_callback(struct ffs_data *ffs) return -EBUSY; gfs_ffs_data = ffs; - ret = usb_composite_register(&gfs_driver); + ret = usb_composite_probe(&gfs_driver, gfs_bind); if (unlikely(ret < 0)) clear_bit(0, &gfs_registered); return ret; diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 775722686ed8..77f495212fb9 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -256,7 +256,6 @@ static struct usb_composite_driver hidg_driver = { .name = "g_hid", .dev = &device_desc, .strings = dev_strings, - .bind = hid_bind, .unbind = __exit_p(hid_unbind), }; @@ -282,7 +281,7 @@ static int __init hidg_init(void) if (status < 0) return status; - status = usb_composite_register(&hidg_driver); + status = usb_composite_probe(&hidg_driver, hid_bind); if (status < 0) platform_driver_unregister(&hidg_plat_driver); diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 05e9bd330348..a5e4a777d922 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -169,7 +169,6 @@ static int __init msg_bind(struct usb_composite_dev *cdev) static struct usb_composite_driver msg_driver = { .name = "g_mass_storage", .dev = &msg_device_desc, - .bind = msg_bind, .iProduct = DRIVER_DESC, .needs_serial = 1, }; @@ -180,7 +179,7 @@ MODULE_LICENSE("GPL"); static int __init msg_init(void) { - return usb_composite_register(&msg_driver); + return usb_composite_probe(&msg_driver, msg_bind); } module_init(msg_init); diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index ca51661d71db..91170a02a9a3 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -353,7 +353,6 @@ static struct usb_composite_driver multi_driver = { .name = "g_multi", .dev = &device_desc, .strings = dev_strings, - .bind = multi_bind, .unbind = __exit_p(multi_unbind), .iProduct = DRIVER_DESC, .needs_serial = 1, @@ -362,7 +361,7 @@ static struct usb_composite_driver multi_driver = { static int __init multi_init(void) { - return usb_composite_register(&multi_driver); + return usb_composite_probe(&multi_driver, multi_bind); } module_init(multi_init); diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index 7d6b66a85724..8aec728882a0 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -241,13 +241,12 @@ static struct usb_composite_driver nokia_driver = { .name = "g_nokia", .dev = &device_desc, .strings = dev_strings, - .bind = nokia_bind, .unbind = __exit_p(nokia_unbind), }; static int __init nokia_init(void) { - return usb_composite_register(&nokia_driver); + return usb_composite_probe(&nokia_driver, nokia_bind); } module_init(nokia_init); diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index f46a60962dab..0b81d7b741d1 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -242,7 +242,6 @@ static struct usb_composite_driver gserial_driver = { .name = "g_serial", .dev = &device_desc, .strings = dev_strings, - .bind = gs_bind, }; static int __init init(void) @@ -271,7 +270,7 @@ static int __init init(void) } strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label; - return usb_composite_register(&gserial_driver); + return usb_composite_probe(&gserial_driver, gs_bind); } module_init(init); diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index 288d21155abe..de65b8078e05 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -373,14 +373,13 @@ static struct usb_composite_driver webcam_driver = { .name = "g_webcam", .dev = &webcam_device_descriptor, .strings = webcam_device_strings, - .bind = webcam_bind, .unbind = webcam_unbind, }; static int __init webcam_init(void) { - return usb_composite_register(&webcam_driver); + return usb_composite_probe(&webcam_driver, webcam_bind); } static void __exit diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 807280d069f9..6d16db9d9d2d 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -340,7 +340,6 @@ static struct usb_composite_driver zero_driver = { .name = "zero", .dev = &device_desc, .strings = dev_strings, - .bind = zero_bind, .unbind = zero_unbind, .suspend = zero_suspend, .resume = zero_resume, @@ -351,7 +350,7 @@ MODULE_LICENSE("GPL"); static int __init init(void) { - return usb_composite_register(&zero_driver); + return usb_composite_probe(&zero_driver, zero_bind); } module_init(init); diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index a78e813d27e4..e28b6626802c 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -248,11 +248,7 @@ int usb_add_config(struct usb_composite_dev *, * and language IDs provided in control requests * @needs_serial: set to 1 if the gadget needs userspace to provide * a serial number. If one is not provided, warning will be printed. - * @bind: (REQUIRED) Used to allocate resources that are shared across the - * whole device, such as string IDs, and add its configurations using - * @usb_add_config(). This may fail by returning a negative errno - * value; it should return zero on successful initialization. - * @unbind: Reverses @bind(); called as a side effect of unregistering + * @unbind: Reverses bind; called as a side effect of unregistering * this driver. * @disconnect: optional driver disconnect method * @suspend: Notifies when the host stops sending USB traffic, @@ -263,7 +259,7 @@ int usb_add_config(struct usb_composite_dev *, * Devices default to reporting self powered operation. Devices which rely * on bus powered operation should report this in their @bind() method. * - * Before returning from @bind, various fields in the template descriptor + * Before returning from bind, various fields in the template descriptor * may be overridden. These include the idVendor/idProduct/bcdDevice values * normally to bind the appropriate host side driver, and the three strings * (iManufacturer, iProduct, iSerialNumber) normally used to provide user @@ -279,12 +275,6 @@ struct usb_composite_driver { struct usb_gadget_strings **strings; unsigned needs_serial:1; - /* REVISIT: bind() functions can be marked __init, which - * makes trouble for section mismatch analysis. See if - * we can't restructure things to avoid mismatching... - */ - - int (*bind)(struct usb_composite_dev *); int (*unbind)(struct usb_composite_dev *); void (*disconnect)(struct usb_composite_dev *); @@ -294,8 +284,9 @@ struct usb_composite_driver { void (*resume)(struct usb_composite_dev *); }; -extern int usb_composite_register(struct usb_composite_driver *); -extern void usb_composite_unregister(struct usb_composite_driver *); +extern int usb_composite_probe(struct usb_composite_driver *driver, + int (*bind)(struct usb_composite_dev *cdev)); +extern void usb_composite_unregister(struct usb_composite_driver *driver); /** From c9bfff9c98671ad50e4abbfe1ab606a9957f7539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 12 Aug 2010 17:43:55 +0200 Subject: [PATCH 022/141] usb gadget: don't save bind callback in struct usb_configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bind function is most of the time only called at init time so there is no need to save a pointer to it in the configuration structure. This fixes many section mismatches reported by modpost. Signed-off-by: Uwe Kleine-König [m.nazarewicz@samsung.com: updated for -next] Signed-off-by: MichaÅ‚ Nazarewicz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/audio.c | 3 +-- drivers/usb/gadget/cdc2.c | 3 +-- drivers/usb/gadget/composite.c | 14 ++++++++------ drivers/usb/gadget/ether.c | 7 +++---- drivers/usb/gadget/f_loopback.c | 3 +-- drivers/usb/gadget/f_sourcesink.c | 3 +-- drivers/usb/gadget/g_ffs.c | 3 +-- drivers/usb/gadget/hid.c | 3 +-- drivers/usb/gadget/mass_storage.c | 3 +-- drivers/usb/gadget/multi.c | 10 ++++------ drivers/usb/gadget/nokia.c | 8 ++++---- drivers/usb/gadget/serial.c | 4 ++-- drivers/usb/gadget/webcam.c | 4 ++-- include/linux/usb/composite.h | 8 +++----- 14 files changed, 33 insertions(+), 43 deletions(-) diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 5a65fbb4e20b..93b999e49ef3 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -105,7 +105,6 @@ static int __init audio_do_config(struct usb_configuration *c) static struct usb_configuration audio_config_driver = { .label = DRIVER_DESC, - .bind = audio_do_config, .bConfigurationValue = 1, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, @@ -145,7 +144,7 @@ static int __init audio_bind(struct usb_composite_dev *cdev) strings_dev[STRING_PRODUCT_IDX].id = status; device_desc.iProduct = status; - status = usb_add_config(cdev, &audio_config_driver); + status = usb_add_config(cdev, &audio_config_driver, audio_do_config); if (status < 0) goto fail; diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 1f2a9b1e4f2d..2720ab07ef1a 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -151,7 +151,6 @@ static int __init cdc_do_config(struct usb_configuration *c) static struct usb_configuration cdc_config_driver = { .label = "CDC Composite (ECM + ACM)", - .bind = cdc_do_config, .bConfigurationValue = 1, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, @@ -218,7 +217,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) device_desc.iProduct = status; /* register our configuration */ - status = usb_add_config(cdev, &cdc_config_driver); + status = usb_add_config(cdev, &cdc_config_driver, cdc_do_config); if (status < 0) goto fail1; diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index c531a7e05f1e..5e2bd7428424 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -474,18 +474,20 @@ done: * usb_add_config() - add a configuration to a device. * @cdev: wraps the USB gadget * @config: the configuration, with bConfigurationValue assigned + * @bind: the configuration's bind function * Context: single threaded during gadget setup * - * One of the main tasks of a composite driver's bind() routine is to + * One of the main tasks of a composite @bind() routine is to * add each of the configurations it supports, using this routine. * - * This function returns the value of the configuration's bind(), which + * This function returns the value of the configuration's @bind(), which * is zero for success else a negative errno value. Binding configurations * assigns global resources including string IDs, and per-configuration * resources such as interface IDs and endpoints. */ int usb_add_config(struct usb_composite_dev *cdev, - struct usb_configuration *config) + struct usb_configuration *config, + int (*bind)(struct usb_configuration *)) { int status = -EINVAL; struct usb_configuration *c; @@ -494,7 +496,7 @@ int usb_add_config(struct usb_composite_dev *cdev, config->bConfigurationValue, config->label, config); - if (!config->bConfigurationValue || !config->bind) + if (!config->bConfigurationValue || !bind) goto done; /* Prevent duplicate configuration identifiers */ @@ -511,7 +513,7 @@ int usb_add_config(struct usb_composite_dev *cdev, INIT_LIST_HEAD(&config->functions); config->next_interface_id = 0; - status = config->bind(config); + status = bind(config); if (status < 0) { list_del(&config->list); config->cdev = NULL; @@ -537,7 +539,7 @@ int usb_add_config(struct usb_composite_dev *cdev, } } - /* set_alt(), or next config->bind(), sets up + /* set_alt(), or next bind(), sets up * ep->driver_data as needed. */ usb_ep_autoconfig_reset(cdev->gadget); diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 33076bca9936..1690c9d68256 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -251,7 +251,6 @@ static int __init rndis_do_config(struct usb_configuration *c) static struct usb_configuration rndis_config_driver = { .label = "RNDIS", - .bind = rndis_do_config, .bConfigurationValue = 2, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, @@ -289,7 +288,6 @@ static int __init eth_do_config(struct usb_configuration *c) static struct usb_configuration eth_config_driver = { /* .label = f(hardware) */ - .bind = eth_do_config, .bConfigurationValue = 1, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, @@ -373,12 +371,13 @@ static int __init eth_bind(struct usb_composite_dev *cdev) /* register our configuration(s); RNDIS first, if it's used */ if (has_rndis()) { - status = usb_add_config(cdev, &rndis_config_driver); + status = usb_add_config(cdev, &rndis_config_driver, + rndis_do_config); if (status < 0) goto fail; } - status = usb_add_config(cdev, ð_config_driver); + status = usb_add_config(cdev, ð_config_driver, eth_do_config); if (status < 0) goto fail; diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index e91d1b16d9be..b37960f9e753 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -349,7 +349,6 @@ static int __init loopback_bind_config(struct usb_configuration *c) static struct usb_configuration loopback_driver = { .label = "loopback", .strings = loopback_strings, - .bind = loopback_bind_config, .bConfigurationValue = 2, .bmAttributes = USB_CONFIG_ATT_SELFPOWER, /* .iConfiguration = DYNAMIC */ @@ -382,5 +381,5 @@ int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume) loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - return usb_add_config(cdev, &loopback_driver); + return usb_add_config(cdev, &loopback_driver, loopback_bind_config); } diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index 6d3cc443d914..e403a534dd55 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -498,7 +498,6 @@ unknown: static struct usb_configuration sourcesink_driver = { .label = "source/sink", .strings = sourcesink_strings, - .bind = sourcesink_bind_config, .setup = sourcesink_setup, .bConfigurationValue = 3, .bmAttributes = USB_CONFIG_ATT_SELFPOWER, @@ -532,5 +531,5 @@ int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume) sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - return usb_add_config(cdev, &sourcesink_driver); + return usb_add_config(cdev, &sourcesink_driver, sourcesink_bind_config); } diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 9fcb15879506..af75e3620849 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -234,11 +234,10 @@ static int gfs_bind(struct usb_composite_dev *cdev) c->c.label = gfs_strings[i].s; c->c.iConfiguration = gfs_strings[i].id; - c->c.bind = gfs_do_config; c->c.bConfigurationValue = 1 + i; c->c.bmAttributes = USB_CONFIG_ATT_SELFPOWER; - ret = usb_add_config(cdev, &c->c); + ret = usb_add_config(cdev, &c->c, gfs_do_config); if (unlikely(ret < 0)) goto error_unbind; } diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 77f495212fb9..2523e54097bd 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -148,7 +148,6 @@ static int __init do_config(struct usb_configuration *c) static struct usb_configuration config_driver = { .label = "HID Gadget", - .bind = do_config, .bConfigurationValue = 1, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, @@ -201,7 +200,7 @@ static int __init hid_bind(struct usb_composite_dev *cdev) device_desc.iProduct = status; /* register our configuration */ - status = usb_add_config(cdev, &config_driver); + status = usb_add_config(cdev, &config_driver, do_config); if (status < 0) return status; diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index a5e4a777d922..0769179dbdb0 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -141,7 +141,6 @@ static int __init msg_do_config(struct usb_configuration *c) static struct usb_configuration msg_config_driver = { .label = "Linux File-Backed Storage", - .bind = msg_do_config, .bConfigurationValue = 1, .bmAttributes = USB_CONFIG_ATT_SELFPOWER, }; @@ -153,7 +152,7 @@ static int __init msg_bind(struct usb_composite_dev *cdev) { int status; - status = usb_add_config(cdev, &msg_config_driver); + status = usb_add_config(cdev, &msg_config_driver, msg_do_config); if (status < 0) return status; diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 91170a02a9a3..d9feced348e3 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -164,7 +164,7 @@ static u8 hostaddr[ETH_ALEN]; #ifdef USB_ETH_RNDIS -static __ref int rndis_do_config(struct usb_configuration *c) +static __init int rndis_do_config(struct usb_configuration *c) { int ret; @@ -191,7 +191,6 @@ static __ref int rndis_do_config(struct usb_configuration *c) static int rndis_config_register(struct usb_composite_dev *cdev) { static struct usb_configuration config = { - .bind = rndis_do_config, .bConfigurationValue = MULTI_RNDIS_CONFIG_NUM, .bmAttributes = USB_CONFIG_ATT_SELFPOWER, }; @@ -199,7 +198,7 @@ static int rndis_config_register(struct usb_composite_dev *cdev) config.label = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].s; config.iConfiguration = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].id; - return usb_add_config(cdev, &config); + return usb_add_config(cdev, &config, rndis_do_config); } #else @@ -216,7 +215,7 @@ static int rndis_config_register(struct usb_composite_dev *cdev) #ifdef CONFIG_USB_G_MULTI_CDC -static __ref int cdc_do_config(struct usb_configuration *c) +static __init int cdc_do_config(struct usb_configuration *c) { int ret; @@ -243,7 +242,6 @@ static __ref int cdc_do_config(struct usb_configuration *c) static int cdc_config_register(struct usb_composite_dev *cdev) { static struct usb_configuration config = { - .bind = cdc_do_config, .bConfigurationValue = MULTI_CDC_CONFIG_NUM, .bmAttributes = USB_CONFIG_ATT_SELFPOWER, }; @@ -251,7 +249,7 @@ static int cdc_config_register(struct usb_composite_dev *cdev) config.label = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].s; config.iConfiguration = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].id; - return usb_add_config(cdev, &config); + return usb_add_config(cdev, &config, cdc_do_config); } #else diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index 8aec728882a0..b5364f9d7cd2 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -135,7 +135,6 @@ static int __init nokia_bind_config(struct usb_configuration *c) static struct usb_configuration nokia_config_500ma_driver = { .label = "Bus Powered", - .bind = nokia_bind_config, .bConfigurationValue = 1, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_ONE, @@ -144,7 +143,6 @@ static struct usb_configuration nokia_config_500ma_driver = { static struct usb_configuration nokia_config_100ma_driver = { .label = "Self Powered", - .bind = nokia_bind_config, .bConfigurationValue = 2, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, @@ -206,11 +204,13 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) } /* finaly register the configuration */ - status = usb_add_config(cdev, &nokia_config_500ma_driver); + status = usb_add_config(cdev, &nokia_config_500ma_driver, + nokia_bind_config); if (status < 0) goto err_usb; - status = usb_add_config(cdev, &nokia_config_100ma_driver); + status = usb_add_config(cdev, &nokia_config_100ma_driver, + nokia_bind_config); if (status < 0) goto err_usb; diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 0b81d7b741d1..1ac57a973aa9 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -155,7 +155,6 @@ static int __init serial_bind_config(struct usb_configuration *c) static struct usb_configuration serial_config_driver = { /* .label = f(use_acm) */ - .bind = serial_bind_config, /* .bConfigurationValue = f(use_acm) */ /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, @@ -225,7 +224,8 @@ static int __init gs_bind(struct usb_composite_dev *cdev) } /* register our configuration */ - status = usb_add_config(cdev, &serial_config_driver); + status = usb_add_config(cdev, &serial_config_driver, + serial_bind_config); if (status < 0) goto fail; diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index de65b8078e05..a5a0fdb808c7 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -317,7 +317,6 @@ webcam_config_bind(struct usb_configuration *c) static struct usb_configuration webcam_config_driver = { .label = webcam_config_label, - .bind = webcam_config_bind, .bConfigurationValue = 1, .iConfiguration = 0, /* dynamic */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, @@ -354,7 +353,8 @@ webcam_bind(struct usb_composite_dev *cdev) webcam_config_driver.iConfiguration = ret; /* Register our configuration. */ - if ((ret = usb_add_config(cdev, &webcam_config_driver)) < 0) + if ((ret = usb_add_config(cdev, &webcam_config_driver, + webcam_config_bind)) < 0) goto error; INFO(cdev, "Webcam Video Gadget\n"); diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index e28b6626802c..3d29a7dcac2d 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -161,8 +161,6 @@ ep_choose(struct usb_gadget *g, struct usb_endpoint_descriptor *hs, * and by language IDs provided in control requests. * @descriptors: Table of descriptors preceding all function descriptors. * Examples include OTG and vendor-specific descriptors. - * @bind: Called from @usb_add_config() to allocate resources unique to this - * configuration and to call @usb_add_function() for each function used. * @unbind: Reverses @bind; called as a side effect of unregistering the * driver which added this configuration. * @setup: Used to delegate control requests that aren't handled by standard @@ -207,8 +205,7 @@ struct usb_configuration { * we can't restructure things to avoid mismatching... */ - /* configuration management: bind/unbind */ - int (*bind)(struct usb_configuration *); + /* configuration management: unbind/setup */ void (*unbind)(struct usb_configuration *); int (*setup)(struct usb_configuration *, const struct usb_ctrlrequest *); @@ -232,7 +229,8 @@ struct usb_configuration { }; int usb_add_config(struct usb_composite_dev *, - struct usb_configuration *); + struct usb_configuration *, + int (*)(struct usb_configuration *)); /** * struct usb_composite_driver - groups configurations into a gadget From 5ea081785dde6041eb2f4acc2369abbb9099a981 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 12 Aug 2010 17:43:56 +0200 Subject: [PATCH 023/141] init.h: add some more documentation to __ref* tags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The __ref* tags may have been confusing for new kernel developers (I was confused by them for sure) so adding a few more sentences to comment to clear things up for people who see those for the first time. Signed-off-by: Michal Nazarewicz Acked-by: Uwe Kleine-König Acked-by: Sam Ravnborg Signed-off-by: Greg Kroah-Hartman --- include/linux/init.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/include/linux/init.h b/include/linux/init.h index de994304e0bb..577671c55153 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -46,16 +46,23 @@ #define __exitdata __section(.exit.data) #define __exit_call __used __section(.exitcall.exit) -/* modpost check for section mismatches during the kernel build. +/* + * modpost check for section mismatches during the kernel build. * A section mismatch happens when there are references from a * code or data section to an init section (both code or data). * The init sections are (for most archs) discarded by the kernel * when early init has completed so all such references are potential bugs. * For exit sections the same issue exists. + * * The following markers are used for the cases where the reference to * the *init / *exit section (code or data) is valid and will teach - * modpost not to issue a warning. - * The markers follow same syntax rules as __init / __initdata. */ + * modpost not to issue a warning. Intended semantics is that a code or + * data tagged __ref* can reference code or data from init section without + * producing a warning (of course, no warning does not mean code is + * correct, so optimally document why the __ref is needed and why it's OK). + * + * The markers follow same syntax rules as __init / __initdata. + */ #define __ref __section(.ref.text) noinline #define __refdata __section(.ref.data) #define __refconst __section(.ref.rodata) From 0cf7a6338808d702c256778188516a16805e6145 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 28 Aug 2010 18:48:56 +0200 Subject: [PATCH 024/141] USB: gadget: amd5536udc.c: Remove double test The same expression is tested twice and the result is the same each time. Instead test for use_dma_ppb as in the test above. The sematic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @expression@ expression E; @@ ( * E || ... || E | * E && ... && E ) // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/amd5536udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index fadebfd53b47..2b361500af1e 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -203,7 +203,7 @@ static void print_regs(struct udc *dev) DBG(dev, "DMA mode = PPBNDU (packet per buffer " "WITHOUT desc. update)\n"); dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBNDU"); - } else if (use_dma && use_dma_ppb_du && use_dma_ppb_du) { + } else if (use_dma && use_dma_ppb && use_dma_ppb_du) { DBG(dev, "DMA mode = PPBDU (packet per buffer " "WITH desc. update)\n"); dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBDU"); From f7dd64916bb6cfae8c96eaa3c754c30b5046586f Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Mon, 30 Aug 2010 22:50:20 +0100 Subject: [PATCH 025/141] USB: output an error message when the pipe type doesn't match the endpoint type Commit f661c6f8c67bd55e93348f160d590ff9edf08904 adds a check of the pipe type if CONFIG_USB_DEBUG is enabled, but it doesn't output anything if this scenario occurs. Signed-off-by: Simon Arlott Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/urb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 419e6b34e2fe..c14fc082864f 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -401,8 +401,11 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) }; /* Check that the pipe's type matches the endpoint's type */ - if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) + if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) { + dev_err(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", + usb_pipetype(urb->pipe), pipetypes[xfertype]); return -EPIPE; /* The most suitable error code :-) */ + } /* enforce simple/standard policy */ allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK | From 10f47168721c0143f23e94eac2fc797aa643de39 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 2 Sep 2010 16:34:36 +0200 Subject: [PATCH 026/141] USB: langwell: Remove unnecessary return's from void functions There are about 2500 void functions in drivers/usb Only a few used return; at end of function. Standardize them a bit. Signed-off-by: Joe Perches Signed-off-by: Jiri Kosina Cc: Stephen Rothwell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/langwell_udc.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index 1ef17a6dcb51..d297f9eb92e4 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -254,7 +254,6 @@ static void ep0_reset(struct langwell_udc *dev) } dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); - return; } @@ -1502,7 +1501,6 @@ static void langwell_udc_start(struct langwell_udc *dev) writel(usbcmd, &dev->op_regs->usbcmd); dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); - return; } @@ -1525,7 +1523,6 @@ static void langwell_udc_stop(struct langwell_udc *dev) writel(usbcmd, &dev->op_regs->usbcmd); dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); - return; } @@ -2417,7 +2414,6 @@ delegate: } end: dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); - return; } @@ -2633,7 +2629,6 @@ static void handle_trans_complete(struct langwell_udc *dev) } done: dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); - return; } From d8087427ccefc0b3364735b96274375246fd452c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 3 Sep 2010 11:15:41 -0400 Subject: [PATCH 027/141] USB: g_file_storage: don't generate automatic serial string This patch (as1413) changes g_file_storage to avoid generating a bogus automatic serial-number string descriptor. If the user doesn't provide a valid serial number via a module parameter then a warning is logged and the gadget won't have any serial string descriptor at all. Signed-off-by: Alan Stern Acked-by: David Brownell CC: Michal Nazarewicz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/file_storage.c | 48 +++++++++-------------------- drivers/usb/gadget/storage_common.c | 3 +- 2 files changed, 15 insertions(+), 36 deletions(-) diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 132a1c0877bd..ce437f5dd674 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -89,6 +89,7 @@ * Required if "removable" is not set, names of * the files or block devices used for * backing storage + * serial=HHHH... Required serial number (string of hex chars) * ro=b[,b...] Default false, booleans for read-only access * removable Default false, boolean for removable media * luns=N Default N = number of filenames, number of @@ -108,12 +109,11 @@ * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID * release=0xRRRR Override the USB release number (bcdDevice) - * serial=HHHH... Override serial number (string of hex chars) * buflen=N Default N=16384, buffer size used (will be * rounded down to a multiple of * PAGE_CACHE_SIZE) * - * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro", + * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro", * "removable", "luns", "nofua", "stall", and "cdrom" options are available; * default values are used for everything else. * @@ -273,13 +273,10 @@ #define DRIVER_DESC "File-backed Storage Gadget" #define DRIVER_NAME "g_file_storage" -/* DRIVER_VERSION must be at least 6 characters long, as it is used - * to generate a fallback serial number. */ -#define DRIVER_VERSION "20 November 2008" +#define DRIVER_VERSION "1 September 2010" static char fsg_string_manufacturer[64]; static const char fsg_string_product[] = DRIVER_DESC; -static char fsg_string_serial[13]; static const char fsg_string_config[] = "Self-powered"; static const char fsg_string_interface[] = "Mass Storage"; @@ -305,6 +302,7 @@ MODULE_LICENSE("Dual BSD/GPL"); static struct { char *file[FSG_MAX_LUNS]; + char *serial; int ro[FSG_MAX_LUNS]; int nofua[FSG_MAX_LUNS]; unsigned int num_filenames; @@ -321,7 +319,6 @@ static struct { unsigned short vendor; unsigned short product; unsigned short release; - char *serial; unsigned int buflen; int transport_type; @@ -346,6 +343,9 @@ module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames, S_IRUGO); MODULE_PARM_DESC(file, "names of backing files or devices"); +module_param_named(serial, mod_data.serial, charp, S_IRUGO); +MODULE_PARM_DESC(serial, "USB serial number"); + module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO); MODULE_PARM_DESC(ro, "true to force read-only"); @@ -365,9 +365,6 @@ MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO); MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk"); -module_param_named(serial, mod_data.serial, charp, S_IRUGO); -MODULE_PARM_DESC(serial, "USB serial number"); - /* In the non-TEST version, only the module parameters listed above * are available. */ #ifdef CONFIG_USB_FILE_STORAGE_TEST @@ -3214,7 +3211,6 @@ static int __init check_parameters(struct fsg_dev *fsg) { int prot; int gcnum; - int i; /* Store the default values */ mod_data.transport_type = USB_PR_BULK; @@ -3310,38 +3306,22 @@ static int __init check_parameters(struct fsg_dev *fsg) if ((*ch < '0' || *ch > '9') && (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */ WARNING(fsg, - "Invalid serial string character: %c; " - "Failing back to default\n", + "Invalid serial string character: %c\n", *ch); - goto fill_serial; + goto no_serial; } } if (len > 126 || (mod_data.transport_type == USB_PR_BULK && len < 12) || (mod_data.transport_type != USB_PR_BULK && len > 12)) { - WARNING(fsg, - "Invalid serial string length; " - "Failing back to default\n"); - goto fill_serial; + WARNING(fsg, "Invalid serial string length!\n"); + goto no_serial; } fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial; } else { - WARNING(fsg, - "Userspace failed to provide serial number; " - "Failing back to default\n"); -fill_serial: - /* Serial number not specified or invalid, make our own. - * We just encode it from the driver version string, - * 12 characters to comply with both CB[I] and BBB spec. - * Warning : Two devices running the same kernel will have - * the same fallback serial number. */ - for (i = 0; i < 12; i += 2) { - unsigned char c = DRIVER_VERSION[i / 2]; - - if (!c) - break; - sprintf(&fsg_string_serial[i], "%02X", c); - } + WARNING(fsg, "No serial-number string provided!\n"); + no_serial: + device_desc.iSerialNumber = 0; } return 0; diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index 484acfb1a7c5..d7856c599d5a 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -26,7 +26,6 @@ * be defined (each of type pointer to char): * - fsg_string_manufacturer -- name of the manufacturer * - fsg_string_product -- name of the product - * - fsg_string_serial -- product's serial * - fsg_string_config -- name of the configuration * - fsg_string_interface -- name of the interface * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS @@ -552,7 +551,7 @@ static struct usb_string fsg_strings[] = { #ifndef FSG_NO_DEVICE_STRINGS {FSG_STRING_MANUFACTURER, fsg_string_manufacturer}, {FSG_STRING_PRODUCT, fsg_string_product}, - {FSG_STRING_SERIAL, fsg_string_serial}, + {FSG_STRING_SERIAL, ""}, {FSG_STRING_CONFIG, fsg_string_config}, #endif {FSG_STRING_INTERFACE, fsg_string_interface}, From eabf0f5f09b1f1538d22c14aa0a703c11791bd1e Mon Sep 17 00:00:00 2001 From: Michael Prokop Date: Mon, 6 Sep 2010 09:53:48 +0200 Subject: [PATCH 028/141] USB: Kconfig: fix typos in USB_FUNCTIONFS* description It's spelled "Function Filesystem" / "FunctionFS". This patch fixes some typos (FunctioFS->FunctionFS, Funcion->Function, funcion->function, redundant "as") in the Kconfig description of USB_FUNCTIONFS*. Signed-off-by: Michael Prokop Acked-by: Michal Nazarewicz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/Kconfig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index cd27f9bde2c8..fab765d387b8 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -716,8 +716,8 @@ config USB_FUNCTIONFS depends on EXPERIMENTAL select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS) help - The Function Filesystem (FunctioFS) lets one create USB - composite functions in user space in the same way as GadgetFS + 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 @@ -733,14 +733,14 @@ config USB_FUNCTIONFS_ETH bool "Include configuration with CDC ECM (Ethernet)" depends on USB_FUNCTIONFS && NET help - Include a configuration with CDC ECM funcion (Ethernet) and the - Funcion Filesystem. + Include a configuration with CDC ECM function (Ethernet) and the + Function Filesystem. config USB_FUNCTIONFS_RNDIS bool "Include configuration with RNDIS (Ethernet)" depends on USB_FUNCTIONFS && NET help - Include a configuration with RNDIS funcion (Ethernet) and the Filesystem. + Include a configuration with RNDIS function (Ethernet) and the Filesystem. config USB_FUNCTIONFS_GENERIC bool "Include 'pure' configuration" From 65fd42724aee31018b0bb53f4cb04971423be664 Mon Sep 17 00:00:00 2001 From: Matthieu CASTET Date: Mon, 6 Sep 2010 18:26:56 +0200 Subject: [PATCH 029/141] USB: ehci tdi : let's tdi_reset set host mode tdi_reset is already taking care of setting host mode for tdi devices. Don't duplicate code in platform driver. Make ehci_halt a nop if the controller is not in host mode (otherwise it will fail), and let's ehci_reset do the tdi_reset. We need to move hcd->has_tt flags before ehci_halt, in order ehci_halt knows we are a tdi device. Before the setup routine was doing : - put controller in host mode - ehci_halt - ehci_init - hcd->has_tt = 1; - ehci_reset Now we do : - hcd->has_tt = 1; - ehci_halt - ehci_init - ehci_reset PS : now we handle correctly the device -> host transition. Signed-off-by: Matthieu CASTET Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-fsl.c | 6 ++---- drivers/usb/host/ehci-fsl.h | 1 - drivers/usb/host/ehci-hcd.c | 15 +++++++++++++++ drivers/usb/host/ehci-mxc.c | 13 +++---------- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index a416421abfa2..8600317bd60b 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -233,8 +233,6 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd) mpc83xx_setup_phy(ehci, pdata->phy_mode, 1); } - /* put controller in host mode. */ - ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE); #ifdef CONFIG_PPC_85xx out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008); out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080); @@ -270,6 +268,8 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) /* cache this readonly data; minimize chip reads */ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); + hcd->has_tt = 1; + retval = ehci_halt(ehci); if (retval) return retval; @@ -279,8 +279,6 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) if (retval) return retval; - hcd->has_tt = 1; - ehci->sbrn = 0x20; ehci_reset(ehci); diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index b5e59db53347..eb537aa54610 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -27,7 +27,6 @@ #define PORT_PTS_SERIAL (3<<30) #define PORT_PTS_PTW (1<<28) #define FSL_SOC_USB_PORTSC2 0x188 -#define FSL_SOC_USB_USBMODE 0x1a8 #define FSL_SOC_USB_SNOOP1 0x400 /* NOTE: big-endian */ #define FSL_SOC_USB_SNOOP2 0x404 /* NOTE: big-endian */ #define FSL_SOC_USB_AGECNTTHRSH 0x408 /* NOTE: big-endian */ diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 34a928d3b7d2..15fe3ecd203b 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -194,6 +194,17 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, return -ETIMEDOUT; } +/* check TDI/ARC silicon is in host mode */ +static int tdi_in_host_mode (struct ehci_hcd *ehci) +{ + u32 __iomem *reg_ptr; + u32 tmp; + + reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE); + tmp = ehci_readl(ehci, reg_ptr); + return (tmp & 3) == USBMODE_CM_HC; +} + /* force HC to halt state from unknown (EHCI spec section 2.3) */ static int ehci_halt (struct ehci_hcd *ehci) { @@ -202,6 +213,10 @@ static int ehci_halt (struct ehci_hcd *ehci) /* disable any irqs left enabled by previous code */ ehci_writel(ehci, 0, &ehci->regs->intr_enable); + if (ehci_is_TDI(ehci) && tdi_in_host_mode(ehci) == 0) { + return 0; + } + if ((temp & STS_HALT) != 0) return 0; diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index a8ad8ac120a2..ac9c4d7c44af 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -26,9 +26,6 @@ #include #define ULPI_VIEWPORT_OFFSET 0x170 -#define PORTSC_OFFSET 0x184 -#define USBMODE_OFFSET 0x1a8 -#define USBMODE_CM_HOST 3 struct ehci_mxc_priv { struct clk *usbclk, *ahbclk; @@ -51,6 +48,8 @@ static int ehci_mxc_setup(struct usb_hcd *hcd) /* cache this readonly data; minimize chip reads */ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); + hcd->has_tt = 1; + retval = ehci_halt(ehci); if (retval) return retval; @@ -60,8 +59,6 @@ static int ehci_mxc_setup(struct usb_hcd *hcd) if (retval) return retval; - hcd->has_tt = 1; - ehci->sbrn = 0x20; ehci_reset(ehci); @@ -191,12 +188,8 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) clk_enable(priv->ahbclk); } - /* set USBMODE to host mode */ - temp = readl(hcd->regs + USBMODE_OFFSET); - writel(temp | USBMODE_CM_HOST, hcd->regs + USBMODE_OFFSET); - /* set up the PORTSCx register */ - writel(pdata->portsc, hcd->regs + PORTSC_OFFSET); + ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]); mdelay(10); /* setup specific usb hw */ From a1df4e45c81ec9ae6b537f845db48b82ab40ac4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihai=20Don=C8=9Bu?= Date: Wed, 8 Sep 2010 02:54:02 +0300 Subject: [PATCH 030/141] USB: gadget: rndis: fix up coding style issues in the file Corrected the coding style. Signed-off-by: Mihai Dontu Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/rndis.c | 492 ++++++++++++++++++------------------- 1 file changed, 244 insertions(+), 248 deletions(-) diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 972d5ddd1e18..5b314041dfa9 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -61,17 +61,17 @@ MODULE_PARM_DESC (rndis_debug, "enable debugging"); #define RNDIS_MAX_CONFIGS 1 -static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS]; +static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS]; /* Driver Version */ -static const __le32 rndis_driver_version = cpu_to_le32 (1); +static const __le32 rndis_driver_version = cpu_to_le32(1); /* Function Prototypes */ -static rndis_resp_t *rndis_add_response (int configNr, u32 length); +static rndis_resp_t *rndis_add_response(int configNr, u32 length); /* supported OIDs */ -static const u32 oid_supported_list [] = +static const u32 oid_supported_list[] = { /* the general stuff */ OID_GEN_SUPPORTED_LIST, @@ -161,21 +161,20 @@ static const u32 oid_supported_list [] = /* NDIS Functions */ -static int -gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, - rndis_resp_t *r) +static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf, + unsigned buf_len, rndis_resp_t *r) { - int retval = -ENOTSUPP; - u32 length = 4; /* usually */ - __le32 *outbuf; - int i, count; - rndis_query_cmplt_type *resp; - struct net_device *net; + int retval = -ENOTSUPP; + u32 length = 4; /* usually */ + __le32 *outbuf; + int i, count; + rndis_query_cmplt_type *resp; + struct net_device *net; struct rtnl_link_stats64 temp; const struct rtnl_link_stats64 *stats; if (!r) return -ENOMEM; - resp = (rndis_query_cmplt_type *) r->buf; + resp = (rndis_query_cmplt_type *)r->buf; if (!resp) return -ENOMEM; @@ -191,8 +190,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, } /* response goes here, right after the header */ - outbuf = (__le32 *) &resp[1]; - resp->InformationBufferOffset = cpu_to_le32 (16); + outbuf = (__le32 *)&resp[1]; + resp->InformationBufferOffset = cpu_to_le32(16); net = rndis_per_dev_params[configNr].dev; stats = dev_get_stats(net, &temp); @@ -204,10 +203,10 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_SUPPORTED_LIST: pr_debug("%s: OID_GEN_SUPPORTED_LIST\n", __func__); - length = sizeof (oid_supported_list); - count = length / sizeof (u32); + length = sizeof(oid_supported_list); + count = length / sizeof(u32); for (i = 0; i < count; i++) - outbuf[i] = cpu_to_le32 (oid_supported_list[i]); + outbuf[i] = cpu_to_le32(oid_supported_list[i]); retval = 0; break; @@ -220,14 +219,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, * reddite ergo quae sunt Caesaris Caesari * et quae sunt Dei Deo! */ - *outbuf = cpu_to_le32 (0); + *outbuf = cpu_to_le32(0); retval = 0; break; /* mandatory */ case OID_GEN_MEDIA_SUPPORTED: pr_debug("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__); - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); + *outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium); retval = 0; break; @@ -235,16 +234,16 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, case OID_GEN_MEDIA_IN_USE: pr_debug("%s: OID_GEN_MEDIA_IN_USE\n", __func__); /* one medium, one transport... (maybe you do it better) */ - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); + *outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium); retval = 0; break; /* mandatory */ case OID_GEN_MAXIMUM_FRAME_SIZE: pr_debug("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__); - if (rndis_per_dev_params [configNr].dev) { - *outbuf = cpu_to_le32 ( - rndis_per_dev_params [configNr].dev->mtu); + if (rndis_per_dev_params[configNr].dev) { + *outbuf = cpu_to_le32( + rndis_per_dev_params[configNr].dev->mtu); retval = 0; } break; @@ -253,21 +252,21 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, case OID_GEN_LINK_SPEED: if (rndis_debug > 1) pr_debug("%s: OID_GEN_LINK_SPEED\n", __func__); - if (rndis_per_dev_params [configNr].media_state + if (rndis_per_dev_params[configNr].media_state == NDIS_MEDIA_STATE_DISCONNECTED) - *outbuf = cpu_to_le32 (0); + *outbuf = cpu_to_le32(0); else - *outbuf = cpu_to_le32 ( - rndis_per_dev_params [configNr].speed); + *outbuf = cpu_to_le32( + rndis_per_dev_params[configNr].speed); retval = 0; break; /* mandatory */ case OID_GEN_TRANSMIT_BLOCK_SIZE: pr_debug("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__); - if (rndis_per_dev_params [configNr].dev) { - *outbuf = cpu_to_le32 ( - rndis_per_dev_params [configNr].dev->mtu); + if (rndis_per_dev_params[configNr].dev) { + *outbuf = cpu_to_le32( + rndis_per_dev_params[configNr].dev->mtu); retval = 0; } break; @@ -275,9 +274,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_RECEIVE_BLOCK_SIZE: pr_debug("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__); - if (rndis_per_dev_params [configNr].dev) { - *outbuf = cpu_to_le32 ( - rndis_per_dev_params [configNr].dev->mtu); + if (rndis_per_dev_params[configNr].dev) { + *outbuf = cpu_to_le32( + rndis_per_dev_params[configNr].dev->mtu); retval = 0; } break; @@ -285,18 +284,20 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_VENDOR_ID: pr_debug("%s: OID_GEN_VENDOR_ID\n", __func__); - *outbuf = cpu_to_le32 ( - rndis_per_dev_params [configNr].vendorID); + *outbuf = cpu_to_le32( + rndis_per_dev_params[configNr].vendorID); retval = 0; break; /* mandatory */ case OID_GEN_VENDOR_DESCRIPTION: pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__); - if ( rndis_per_dev_params [configNr].vendorDescr ) { - length = strlen (rndis_per_dev_params [configNr].vendorDescr); - memcpy (outbuf, - rndis_per_dev_params [configNr].vendorDescr, length); + if (rndis_per_dev_params[configNr].vendorDescr) { + length = strlen(rndis_per_dev_params[configNr]. + vendorDescr); + memcpy(outbuf, + rndis_per_dev_params[configNr].vendorDescr, + length); } else { outbuf[0] = 0; } @@ -313,7 +314,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_CURRENT_PACKET_FILTER: pr_debug("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__); - *outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter); + *outbuf = cpu_to_le32(*rndis_per_dev_params[configNr].filter); retval = 0; break; @@ -328,14 +329,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, case OID_GEN_MEDIA_CONNECT_STATUS: if (rndis_debug > 1) pr_debug("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__); - *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] + *outbuf = cpu_to_le32(rndis_per_dev_params[configNr] .media_state); retval = 0; break; case OID_GEN_PHYSICAL_MEDIUM: pr_debug("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__); - *outbuf = cpu_to_le32 (0); + *outbuf = cpu_to_le32(0); retval = 0; break; @@ -409,10 +410,10 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_802_3_PERMANENT_ADDRESS: pr_debug("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__); - if (rndis_per_dev_params [configNr].dev) { + if (rndis_per_dev_params[configNr].dev) { length = ETH_ALEN; - memcpy (outbuf, - rndis_per_dev_params [configNr].host_mac, + memcpy(outbuf, + rndis_per_dev_params[configNr].host_mac, length); retval = 0; } @@ -421,9 +422,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_802_3_CURRENT_ADDRESS: pr_debug("%s: OID_802_3_CURRENT_ADDRESS\n", __func__); - if (rndis_per_dev_params [configNr].dev) { + if (rndis_per_dev_params[configNr].dev) { length = ETH_ALEN; - memcpy (outbuf, + memcpy(outbuf, rndis_per_dev_params [configNr].host_mac, length); retval = 0; @@ -434,7 +435,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, case OID_802_3_MULTICAST_LIST: pr_debug("%s: OID_802_3_MULTICAST_LIST\n", __func__); /* Multicast base address only */ - *outbuf = cpu_to_le32 (0xE0000000); + *outbuf = cpu_to_le32(0xE0000000); retval = 0; break; @@ -442,7 +443,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, case OID_802_3_MAXIMUM_LIST_SIZE: pr_debug("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__); /* Multicast base address only */ - *outbuf = cpu_to_le32 (1); + *outbuf = cpu_to_le32(1); retval = 0; break; @@ -466,14 +467,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_802_3_XMIT_ONE_COLLISION: pr_debug("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__); - *outbuf = cpu_to_le32 (0); + *outbuf = cpu_to_le32(0); retval = 0; break; /* mandatory */ case OID_802_3_XMIT_MORE_COLLISIONS: pr_debug("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__); - *outbuf = cpu_to_le32 (0); + *outbuf = cpu_to_le32(0); retval = 0; break; @@ -484,22 +485,22 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, if (retval < 0) length = 0; - resp->InformationBufferLength = cpu_to_le32 (length); - r->length = length + sizeof *resp; - resp->MessageLength = cpu_to_le32 (r->length); + resp->InformationBufferLength = cpu_to_le32(length); + r->length = length + sizeof(*resp); + resp->MessageLength = cpu_to_le32(r->length); return retval; } -static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, - rndis_resp_t *r) +static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len, + rndis_resp_t *r) { - rndis_set_cmplt_type *resp; - int i, retval = -ENOTSUPP; - struct rndis_params *params; + rndis_set_cmplt_type *resp; + int i, retval = -ENOTSUPP; + struct rndis_params *params; if (!r) return -ENOMEM; - resp = (rndis_set_cmplt_type *) r->buf; + resp = (rndis_set_cmplt_type *)r->buf; if (!resp) return -ENOMEM; @@ -514,7 +515,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, } } - params = &rndis_per_dev_params [configNr]; + params = &rndis_per_dev_params[configNr]; switch (OID) { case OID_GEN_CURRENT_PACKET_FILTER: @@ -537,11 +538,11 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, params->state = RNDIS_DATA_INITIALIZED; netif_carrier_on(params->dev); if (netif_running(params->dev)) - netif_wake_queue (params->dev); + netif_wake_queue(params->dev); } else { params->state = RNDIS_INITIALIZED; - netif_carrier_off (params->dev); - netif_stop_queue (params->dev); + netif_carrier_off(params->dev); + netif_stop_queue(params->dev); } break; @@ -563,48 +564,47 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, * Response Functions */ -static int rndis_init_response (int configNr, rndis_init_msg_type *buf) +static int rndis_init_response(int configNr, rndis_init_msg_type *buf) { - rndis_init_cmplt_type *resp; - rndis_resp_t *r; - struct rndis_params *params = rndis_per_dev_params + configNr; + rndis_init_cmplt_type *resp; + rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; if (!params->dev) return -ENOTSUPP; - r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type)); + r = rndis_add_response(configNr, sizeof(rndis_init_cmplt_type)); if (!r) return -ENOMEM; - resp = (rndis_init_cmplt_type *) r->buf; + resp = (rndis_init_cmplt_type *)r->buf; - resp->MessageType = cpu_to_le32 ( - REMOTE_NDIS_INITIALIZE_CMPLT); - resp->MessageLength = cpu_to_le32 (52); + resp->MessageType = cpu_to_le32(REMOTE_NDIS_INITIALIZE_CMPLT); + resp->MessageLength = cpu_to_le32(52); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ - resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS); - resp->MajorVersion = cpu_to_le32 (RNDIS_MAJOR_VERSION); - resp->MinorVersion = cpu_to_le32 (RNDIS_MINOR_VERSION); - resp->DeviceFlags = cpu_to_le32 (RNDIS_DF_CONNECTIONLESS); - resp->Medium = cpu_to_le32 (RNDIS_MEDIUM_802_3); - resp->MaxPacketsPerTransfer = cpu_to_le32 (1); - resp->MaxTransferSize = cpu_to_le32 ( + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS); + resp->MajorVersion = cpu_to_le32(RNDIS_MAJOR_VERSION); + resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION); + resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS); + resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3); + resp->MaxPacketsPerTransfer = cpu_to_le32(1); + resp->MaxTransferSize = cpu_to_le32( params->dev->mtu - + sizeof (struct ethhdr) - + sizeof (struct rndis_packet_msg_type) + + sizeof(struct ethhdr) + + sizeof(struct rndis_packet_msg_type) + 22); - resp->PacketAlignmentFactor = cpu_to_le32 (0); - resp->AFListOffset = cpu_to_le32 (0); - resp->AFListSize = cpu_to_le32 (0); + resp->PacketAlignmentFactor = cpu_to_le32(0); + resp->AFListOffset = cpu_to_le32(0); + resp->AFListSize = cpu_to_le32(0); params->resp_avail(params->v); return 0; } -static int rndis_query_response (int configNr, rndis_query_msg_type *buf) +static int rndis_query_response(int configNr, rndis_query_msg_type *buf) { rndis_query_cmplt_type *resp; - rndis_resp_t *r; - struct rndis_params *params = rndis_per_dev_params + configNr; + rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; /* pr_debug("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID)); */ if (!params->dev) @@ -616,47 +616,46 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf) * rndis_query_cmplt_type followed by data. * oid_supported_list is the largest data reply */ - r = rndis_add_response (configNr, - sizeof (oid_supported_list) + sizeof(rndis_query_cmplt_type)); + r = rndis_add_response(configNr, + sizeof(oid_supported_list) + sizeof(rndis_query_cmplt_type)); if (!r) return -ENOMEM; - resp = (rndis_query_cmplt_type *) r->buf; + resp = (rndis_query_cmplt_type *)r->buf; - resp->MessageType = cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT); + resp->MessageType = cpu_to_le32(REMOTE_NDIS_QUERY_CMPLT); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ - if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), + if (gen_ndis_query_resp(configNr, le32_to_cpu(buf->OID), le32_to_cpu(buf->InformationBufferOffset) - + 8 + (u8 *) buf, + + 8 + (u8 *)buf, le32_to_cpu(buf->InformationBufferLength), r)) { /* OID not supported */ - resp->Status = cpu_to_le32 ( - RNDIS_STATUS_NOT_SUPPORTED); - resp->MessageLength = cpu_to_le32 (sizeof *resp); - resp->InformationBufferLength = cpu_to_le32 (0); - resp->InformationBufferOffset = cpu_to_le32 (0); + resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED); + resp->MessageLength = cpu_to_le32(sizeof *resp); + resp->InformationBufferLength = cpu_to_le32(0); + resp->InformationBufferOffset = cpu_to_le32(0); } else - resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS); + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS); params->resp_avail(params->v); return 0; } -static int rndis_set_response (int configNr, rndis_set_msg_type *buf) +static int rndis_set_response(int configNr, rndis_set_msg_type *buf) { - u32 BufLength, BufOffset; - rndis_set_cmplt_type *resp; - rndis_resp_t *r; - struct rndis_params *params = rndis_per_dev_params + configNr; + u32 BufLength, BufOffset; + rndis_set_cmplt_type *resp; + rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; - r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type)); + r = rndis_add_response(configNr, sizeof(rndis_set_cmplt_type)); if (!r) return -ENOMEM; - resp = (rndis_set_cmplt_type *) r->buf; + resp = (rndis_set_cmplt_type *)r->buf; - BufLength = le32_to_cpu (buf->InformationBufferLength); - BufOffset = le32_to_cpu (buf->InformationBufferOffset); + BufLength = le32_to_cpu(buf->InformationBufferLength); + BufOffset = le32_to_cpu(buf->InformationBufferOffset); #ifdef VERBOSE_DEBUG pr_debug("%s: Length: %d\n", __func__, BufLength); @@ -670,59 +669,59 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf) pr_debug("\n"); #endif - resp->MessageType = cpu_to_le32 (REMOTE_NDIS_SET_CMPLT); - resp->MessageLength = cpu_to_le32 (16); + resp->MessageType = cpu_to_le32(REMOTE_NDIS_SET_CMPLT); + resp->MessageLength = cpu_to_le32(16); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ - if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID), - ((u8 *) buf) + 8 + BufOffset, BufLength, r)) - resp->Status = cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED); + if (gen_ndis_set_resp(configNr, le32_to_cpu(buf->OID), + ((u8 *)buf) + 8 + BufOffset, BufLength, r)) + resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED); else - resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS); + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS); params->resp_avail(params->v); return 0; } -static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf) +static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf) { - rndis_reset_cmplt_type *resp; - rndis_resp_t *r; - struct rndis_params *params = rndis_per_dev_params + configNr; + rndis_reset_cmplt_type *resp; + rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; - r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type)); + r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type)); if (!r) return -ENOMEM; - resp = (rndis_reset_cmplt_type *) r->buf; + resp = (rndis_reset_cmplt_type *)r->buf; - resp->MessageType = cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT); - resp->MessageLength = cpu_to_le32 (16); - resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS); + resp->MessageType = cpu_to_le32(REMOTE_NDIS_RESET_CMPLT); + resp->MessageLength = cpu_to_le32(16); + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS); /* resent information */ - resp->AddressingReset = cpu_to_le32 (1); + resp->AddressingReset = cpu_to_le32(1); params->resp_avail(params->v); return 0; } -static int rndis_keepalive_response (int configNr, - rndis_keepalive_msg_type *buf) +static int rndis_keepalive_response(int configNr, + rndis_keepalive_msg_type *buf) { - rndis_keepalive_cmplt_type *resp; - rndis_resp_t *r; - struct rndis_params *params = rndis_per_dev_params + configNr; + rndis_keepalive_cmplt_type *resp; + rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; /* host "should" check only in RNDIS_DATA_INITIALIZED state */ - r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type)); + r = rndis_add_response(configNr, sizeof(rndis_keepalive_cmplt_type)); if (!r) return -ENOMEM; - resp = (rndis_keepalive_cmplt_type *) r->buf; + resp = (rndis_keepalive_cmplt_type *)r->buf; - resp->MessageType = cpu_to_le32 ( + resp->MessageType = cpu_to_le32( REMOTE_NDIS_KEEPALIVE_CMPLT); - resp->MessageLength = cpu_to_le32 (16); + resp->MessageLength = cpu_to_le32(16); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ - resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS); + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS); params->resp_avail(params->v); return 0; @@ -732,86 +731,85 @@ static int rndis_keepalive_response (int configNr, /* * Device to Host Comunication */ -static int rndis_indicate_status_msg (int configNr, u32 status) +static int rndis_indicate_status_msg(int configNr, u32 status) { - rndis_indicate_status_msg_type *resp; - rndis_resp_t *r; - struct rndis_params *params = rndis_per_dev_params + configNr; + rndis_indicate_status_msg_type *resp; + rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; if (params->state == RNDIS_UNINITIALIZED) return -ENOTSUPP; - r = rndis_add_response (configNr, - sizeof (rndis_indicate_status_msg_type)); + r = rndis_add_response(configNr, + sizeof(rndis_indicate_status_msg_type)); if (!r) return -ENOMEM; - resp = (rndis_indicate_status_msg_type *) r->buf; + resp = (rndis_indicate_status_msg_type *)r->buf; - resp->MessageType = cpu_to_le32 ( - REMOTE_NDIS_INDICATE_STATUS_MSG); - resp->MessageLength = cpu_to_le32 (20); - resp->Status = cpu_to_le32 (status); - resp->StatusBufferLength = cpu_to_le32 (0); - resp->StatusBufferOffset = cpu_to_le32 (0); + resp->MessageType = cpu_to_le32(REMOTE_NDIS_INDICATE_STATUS_MSG); + resp->MessageLength = cpu_to_le32(20); + resp->Status = cpu_to_le32(status); + resp->StatusBufferLength = cpu_to_le32(0); + resp->StatusBufferOffset = cpu_to_le32(0); params->resp_avail(params->v); return 0; } -int rndis_signal_connect (int configNr) +int rndis_signal_connect(int configNr) { - rndis_per_dev_params [configNr].media_state + rndis_per_dev_params[configNr].media_state = NDIS_MEDIA_STATE_CONNECTED; - return rndis_indicate_status_msg (configNr, + return rndis_indicate_status_msg(configNr, RNDIS_STATUS_MEDIA_CONNECT); } -int rndis_signal_disconnect (int configNr) +int rndis_signal_disconnect(int configNr) { - rndis_per_dev_params [configNr].media_state + rndis_per_dev_params[configNr].media_state = NDIS_MEDIA_STATE_DISCONNECTED; - return rndis_indicate_status_msg (configNr, + return rndis_indicate_status_msg(configNr, RNDIS_STATUS_MEDIA_DISCONNECT); } -void rndis_uninit (int configNr) +void rndis_uninit(int configNr) { u8 *buf; u32 length; if (configNr >= RNDIS_MAX_CONFIGS) return; - rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED; + rndis_per_dev_params[configNr].state = RNDIS_UNINITIALIZED; /* drain the response queue */ while ((buf = rndis_get_next_response(configNr, &length))) rndis_free_response(configNr, buf); } -void rndis_set_host_mac (int configNr, const u8 *addr) +void rndis_set_host_mac(int configNr, const u8 *addr) { - rndis_per_dev_params [configNr].host_mac = addr; + rndis_per_dev_params[configNr].host_mac = addr; } /* * Message Parser */ -int rndis_msg_parser (u8 configNr, u8 *buf) +int rndis_msg_parser(u8 configNr, u8 *buf) { u32 MsgType, MsgLength; __le32 *tmp; - struct rndis_params *params; + struct rndis_params *params; if (!buf) return -ENOMEM; - tmp = (__le32 *) buf; + tmp = (__le32 *)buf; MsgType = get_unaligned_le32(tmp++); MsgLength = get_unaligned_le32(tmp++); if (configNr >= RNDIS_MAX_CONFIGS) return -ENOTSUPP; - params = &rndis_per_dev_params [configNr]; + params = &rndis_per_dev_params[configNr]; /* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for * rx/tx statistics and link status, in addition to KEEPALIVE traffic @@ -822,41 +820,41 @@ int rndis_msg_parser (u8 configNr, u8 *buf) switch (MsgType) { case REMOTE_NDIS_INITIALIZE_MSG: pr_debug("%s: REMOTE_NDIS_INITIALIZE_MSG\n", - __func__ ); + __func__); params->state = RNDIS_INITIALIZED; - return rndis_init_response (configNr, - (rndis_init_msg_type *) buf); + return rndis_init_response(configNr, + (rndis_init_msg_type *)buf); case REMOTE_NDIS_HALT_MSG: pr_debug("%s: REMOTE_NDIS_HALT_MSG\n", - __func__ ); + __func__); params->state = RNDIS_UNINITIALIZED; if (params->dev) { - netif_carrier_off (params->dev); - netif_stop_queue (params->dev); + netif_carrier_off(params->dev); + netif_stop_queue(params->dev); } return 0; case REMOTE_NDIS_QUERY_MSG: - return rndis_query_response (configNr, - (rndis_query_msg_type *) buf); + return rndis_query_response(configNr, + (rndis_query_msg_type *)buf); case REMOTE_NDIS_SET_MSG: - return rndis_set_response (configNr, - (rndis_set_msg_type *) buf); + return rndis_set_response(configNr, + (rndis_set_msg_type *)buf); case REMOTE_NDIS_RESET_MSG: pr_debug("%s: REMOTE_NDIS_RESET_MSG\n", - __func__ ); - return rndis_reset_response (configNr, - (rndis_reset_msg_type *) buf); + __func__); + return rndis_reset_response(configNr, + (rndis_reset_msg_type *)buf); case REMOTE_NDIS_KEEPALIVE_MSG: /* For USB: host does this every 5 seconds */ if (rndis_debug > 1) pr_debug("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", - __func__ ); - return rndis_keepalive_response (configNr, + __func__); + return rndis_keepalive_response(configNr, (rndis_keepalive_msg_type *) buf); @@ -866,7 +864,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf) * suspending itself. */ pr_warning("%s: unknown RNDIS message 0x%08X len %d\n", - __func__ , MsgType, MsgLength); + __func__, MsgType, MsgLength); { unsigned i; for (i = 0; i < MsgLength; i += 16) { @@ -901,10 +899,10 @@ int rndis_register(void (*resp_avail)(void *v), void *v) return -EINVAL; for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { - if (!rndis_per_dev_params [i].used) { - rndis_per_dev_params [i].used = 1; - rndis_per_dev_params [i].resp_avail = resp_avail; - rndis_per_dev_params [i].v = v; + if (!rndis_per_dev_params[i].used) { + rndis_per_dev_params[i].used = 1; + rndis_per_dev_params[i].resp_avail = resp_avail; + rndis_per_dev_params[i].v = v; pr_debug("%s: configNr = %d\n", __func__, i); return i; } @@ -914,12 +912,12 @@ int rndis_register(void (*resp_avail)(void *v), void *v) return -ENODEV; } -void rndis_deregister (int configNr) +void rndis_deregister(int configNr) { - pr_debug("%s: \n", __func__); + pr_debug("%s:\n", __func__); if (configNr >= RNDIS_MAX_CONFIGS) return; - rndis_per_dev_params [configNr].used = 0; + rndis_per_dev_params[configNr].used = 0; return; } @@ -931,76 +929,76 @@ int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter) return -EINVAL; if (configNr >= RNDIS_MAX_CONFIGS) return -1; - rndis_per_dev_params [configNr].dev = dev; - rndis_per_dev_params [configNr].filter = cdc_filter; + rndis_per_dev_params[configNr].dev = dev; + rndis_per_dev_params[configNr].filter = cdc_filter; return 0; } -int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr) +int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr) { pr_debug("%s:\n", __func__); if (!vendorDescr) return -1; if (configNr >= RNDIS_MAX_CONFIGS) return -1; - rndis_per_dev_params [configNr].vendorID = vendorID; - rndis_per_dev_params [configNr].vendorDescr = vendorDescr; + rndis_per_dev_params[configNr].vendorID = vendorID; + rndis_per_dev_params[configNr].vendorDescr = vendorDescr; return 0; } -int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed) +int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed) { pr_debug("%s: %u %u\n", __func__, medium, speed); if (configNr >= RNDIS_MAX_CONFIGS) return -1; - rndis_per_dev_params [configNr].medium = medium; - rndis_per_dev_params [configNr].speed = speed; + rndis_per_dev_params[configNr].medium = medium; + rndis_per_dev_params[configNr].speed = speed; return 0; } -void rndis_add_hdr (struct sk_buff *skb) +void rndis_add_hdr(struct sk_buff *skb) { - struct rndis_packet_msg_type *header; + struct rndis_packet_msg_type *header; if (!skb) return; - header = (void *) skb_push (skb, sizeof *header); - memset (header, 0, sizeof *header); + header = (void *)skb_push(skb, sizeof(*header)); + memset(header, 0, sizeof *header); header->MessageType = cpu_to_le32(REMOTE_NDIS_PACKET_MSG); header->MessageLength = cpu_to_le32(skb->len); - header->DataOffset = cpu_to_le32 (36); - header->DataLength = cpu_to_le32(skb->len - sizeof *header); + header->DataOffset = cpu_to_le32(36); + header->DataLength = cpu_to_le32(skb->len - sizeof(*header)); } -void rndis_free_response (int configNr, u8 *buf) +void rndis_free_response(int configNr, u8 *buf) { - rndis_resp_t *r; - struct list_head *act, *tmp; + rndis_resp_t *r; + struct list_head *act, *tmp; - list_for_each_safe (act, tmp, - &(rndis_per_dev_params [configNr].resp_queue)) + list_for_each_safe(act, tmp, + &(rndis_per_dev_params[configNr].resp_queue)) { - r = list_entry (act, rndis_resp_t, list); + r = list_entry(act, rndis_resp_t, list); if (r && r->buf == buf) { - list_del (&r->list); - kfree (r); + list_del(&r->list); + kfree(r); } } } -u8 *rndis_get_next_response (int configNr, u32 *length) +u8 *rndis_get_next_response(int configNr, u32 *length) { - rndis_resp_t *r; - struct list_head *act, *tmp; + rndis_resp_t *r; + struct list_head *act, *tmp; if (!length) return NULL; - list_for_each_safe (act, tmp, - &(rndis_per_dev_params [configNr].resp_queue)) + list_for_each_safe(act, tmp, + &(rndis_per_dev_params[configNr].resp_queue)) { - r = list_entry (act, rndis_resp_t, list); + r = list_entry(act, rndis_resp_t, list); if (!r->send) { r->send = 1; *length = r->length; @@ -1011,20 +1009,20 @@ u8 *rndis_get_next_response (int configNr, u32 *length) return NULL; } -static rndis_resp_t *rndis_add_response (int configNr, u32 length) +static rndis_resp_t *rndis_add_response(int configNr, u32 length) { - rndis_resp_t *r; + rndis_resp_t *r; - /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */ - r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC); + /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */ + r = kmalloc(sizeof(rndis_resp_t) + length, GFP_ATOMIC); if (!r) return NULL; - r->buf = (u8 *) (r + 1); + r->buf = (u8 *)(r + 1); r->length = length; r->send = 0; - list_add_tail (&r->list, - &(rndis_per_dev_params [configNr].resp_queue)); + list_add_tail(&r->list, + &(rndis_per_dev_params[configNr].resp_queue)); return r; } @@ -1033,7 +1031,7 @@ int rndis_rm_hdr(struct gether *port, struct sk_buff_head *list) { /* tmp points to a struct rndis_packet_msg_type */ - __le32 *tmp = (void *) skb->data; + __le32 *tmp = (void *)skb->data; /* MessageType, MessageLength */ if (cpu_to_le32(REMOTE_NDIS_PACKET_MSG) @@ -1054,7 +1052,7 @@ int rndis_rm_hdr(struct gether *port, return 0; } -#ifdef CONFIG_USB_GADGET_DEBUG_FILES +#ifdef CONFIG_USB_GADGET_DEBUG_FILES static int rndis_proc_show(struct seq_file *m, void *v) { @@ -1087,7 +1085,7 @@ static int rndis_proc_show(struct seq_file *m, void *v) } static ssize_t rndis_proc_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { rndis_params *p = PDE(file->f_path.dentry->d_inode)->data; u32 speed = 0; @@ -1109,11 +1107,11 @@ static ssize_t rndis_proc_write(struct file *file, const char __user *buffer, case '8': case '9': fl_speed = 1; - speed = speed*10 + c - '0'; + speed = speed * 10 + c - '0'; break; case 'C': case 'c': - rndis_signal_connect (p->confignr); + rndis_signal_connect(p->confignr); break; case 'D': case 'd': @@ -1145,11 +1143,11 @@ static const struct file_operations rndis_proc_fops = { .write = rndis_proc_write, }; -#define NAME_TEMPLATE "driver/rndis-%03d" +#define NAME_TEMPLATE "driver/rndis-%03d" static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS]; -#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ +#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ int rndis_init(void) @@ -1160,42 +1158,40 @@ int rndis_init(void) #ifdef CONFIG_USB_GADGET_DEBUG_FILES char name [20]; - sprintf (name, NAME_TEMPLATE, i); - if (!(rndis_connect_state [i] - = proc_create_data(name, 0660, NULL, + sprintf(name, NAME_TEMPLATE, i); + rndis_connect_state[i] = proc_create_data(name, 0660, NULL, &rndis_proc_fops, - (void *)(rndis_per_dev_params + i)))) - { - pr_debug("%s :remove entries", __func__); + (void *)(rndis_per_dev_params + i)); + if (!rndis_connect_state[i]) { + pr_debug("%s: remove entries", __func__); while (i) { - sprintf (name, NAME_TEMPLATE, --i); - remove_proc_entry (name, NULL); + sprintf(name, NAME_TEMPLATE, --i); + remove_proc_entry(name, NULL); } pr_debug("\n"); return -EIO; } #endif - rndis_per_dev_params [i].confignr = i; - rndis_per_dev_params [i].used = 0; - rndis_per_dev_params [i].state = RNDIS_UNINITIALIZED; - rndis_per_dev_params [i].media_state + rndis_per_dev_params[i].confignr = i; + rndis_per_dev_params[i].used = 0; + rndis_per_dev_params[i].state = RNDIS_UNINITIALIZED; + rndis_per_dev_params[i].media_state = NDIS_MEDIA_STATE_DISCONNECTED; - INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue)); + INIT_LIST_HEAD(&(rndis_per_dev_params[i].resp_queue)); } return 0; } -void rndis_exit (void) +void rndis_exit(void) { -#ifdef CONFIG_USB_GADGET_DEBUG_FILES +#ifdef CONFIG_USB_GADGET_DEBUG_FILES u8 i; - char name [20]; + char name[20]; for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { - sprintf (name, NAME_TEMPLATE, i); - remove_proc_entry (name, NULL); + sprintf(name, NAME_TEMPLATE, i); + remove_proc_entry(name, NULL); } #endif } - From 5014b5e33a5485ab669ce536078c957ec221ade3 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 7 Sep 2010 14:32:43 +0000 Subject: [PATCH 031/141] usb: ftdi-elan: Convert "mutex" to semaphore The "mutex" ftdi->sw_lock is used as a lock and a completion. Convert it to a real semaphore which allows both. Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/ftdi-elan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index aecf380f6ecc..c8eec9c2d89e 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -2769,7 +2769,7 @@ static int ftdi_elan_probe(struct usb_interface *interface, ftdi->sequence_num = ++ftdi_instances; mutex_unlock(&ftdi_module_lock); ftdi_elan_init_kref(ftdi); - init_MUTEX(&ftdi->sw_lock); + sema_init(&ftdi->sw_lock, 1); ftdi->udev = usb_get_dev(interface_to_usbdev(interface)); ftdi->interface = interface; mutex_init(&ftdi->u132_lock); From d39a0edad60dc65cf4774ee732aa7a84cf35c27a Mon Sep 17 00:00:00 2001 From: Hao Wu Date: Thu, 9 Sep 2010 22:35:39 +0100 Subject: [PATCH 032/141] USB OTG: Add common data structure for Intel MID Platform (Langwell/Penwell) This patch adds one new header file for the common data structure used in Intel Penwell/Langwell MID Platform OTG Transceiver drivers. After switched to the common data structure, Langwell/Penwell OTG Transceiver driver will provide an unified interface to host/client driver. Reported-by: Randy Dunlap Signed-off-by: Hao Wu Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/intel_mid_otg.h | 180 ++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 include/linux/usb/intel_mid_otg.h diff --git a/include/linux/usb/intel_mid_otg.h b/include/linux/usb/intel_mid_otg.h new file mode 100644 index 000000000000..a0ccf795f362 --- /dev/null +++ b/include/linux/usb/intel_mid_otg.h @@ -0,0 +1,180 @@ +/* + * Intel MID (Langwell/Penwell) USB OTG Transceiver driver + * Copyright (C) 2008 - 2010, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef __INTEL_MID_OTG_H +#define __INTEL_MID_OTG_H + +#include +#include +#include + +struct intel_mid_otg_xceiv; + +/* This is a common data structure for Intel MID platform to + * save values of the OTG state machine */ +struct otg_hsm { + /* Input */ + int a_bus_resume; + int a_bus_suspend; + int a_conn; + int a_sess_vld; + int a_srp_det; + int a_vbus_vld; + int b_bus_resume; + int b_bus_suspend; + int b_conn; + int b_se0_srp; + int b_ssend_srp; + int b_sess_end; + int b_sess_vld; + int id; +/* id values */ +#define ID_B 0x05 +#define ID_A 0x04 +#define ID_ACA_C 0x03 +#define ID_ACA_B 0x02 +#define ID_ACA_A 0x01 + int power_up; + int adp_change; + int test_device; + + /* Internal variables */ + int a_set_b_hnp_en; + int b_srp_done; + int b_hnp_enable; + int hnp_poll_enable; + + /* Timeout indicator for timers */ + int a_wait_vrise_tmout; + int a_wait_bcon_tmout; + int a_aidl_bdis_tmout; + int a_bidl_adis_tmout; + int a_bidl_adis_tmr; + int a_wait_vfall_tmout; + int b_ase0_brst_tmout; + int b_bus_suspend_tmout; + int b_srp_init_tmout; + int b_srp_fail_tmout; + int b_srp_fail_tmr; + int b_adp_sense_tmout; + + /* Informative variables */ + int a_bus_drop; + int a_bus_req; + int a_clr_err; + int b_bus_req; + int a_suspend_req; + int b_bus_suspend_vld; + + /* Output */ + int drv_vbus; + int loc_conn; + int loc_sof; + + /* Others */ + int vbus_srp_up; +}; + +/* must provide ULPI access function to read/write registers implemented in + * ULPI address space */ +struct iotg_ulpi_access_ops { + int (*read)(struct intel_mid_otg_xceiv *iotg, u8 reg, u8 *val); + int (*write)(struct intel_mid_otg_xceiv *iotg, u8 reg, u8 val); +}; + +#define OTG_A_DEVICE 0x0 +#define OTG_B_DEVICE 0x1 + +/* + * the Intel MID (Langwell/Penwell) otg transceiver driver needs to interact + * with device and host drivers to implement the USB OTG related feature. More + * function members are added based on otg_transceiver data structure for this + * purpose. + */ +struct intel_mid_otg_xceiv { + struct otg_transceiver otg; + struct otg_hsm hsm; + + /* base address */ + void __iomem *base; + + /* ops to access ulpi */ + struct iotg_ulpi_access_ops ulpi_ops; + + /* atomic notifier for interrupt context */ + struct atomic_notifier_head iotg_notifier; + + /* start/stop USB Host function */ + int (*start_host)(struct intel_mid_otg_xceiv *iotg); + int (*stop_host)(struct intel_mid_otg_xceiv *iotg); + + /* start/stop USB Peripheral function */ + int (*start_peripheral)(struct intel_mid_otg_xceiv *iotg); + int (*stop_peripheral)(struct intel_mid_otg_xceiv *iotg); + + /* start/stop ADP sense/probe function */ + int (*set_adp_probe)(struct intel_mid_otg_xceiv *iotg, + bool enabled, int dev); + int (*set_adp_sense)(struct intel_mid_otg_xceiv *iotg, + bool enabled); + +#ifdef CONFIG_PM + /* suspend/resume USB host function */ + int (*suspend_host)(struct intel_mid_otg_xceiv *iotg, + pm_message_t message); + int (*resume_host)(struct intel_mid_otg_xceiv *iotg); + + int (*suspend_peripheral)(struct intel_mid_otg_xceiv *iotg, + pm_message_t message); + int (*resume_peripheral)(struct intel_mid_otg_xceiv *iotg); +#endif + +}; +static inline +struct intel_mid_otg_xceiv *otg_to_mid_xceiv(struct otg_transceiver *otg) +{ + return container_of(otg, struct intel_mid_otg_xceiv, otg); +} + +#define MID_OTG_NOTIFY_CONNECT 0x0001 +#define MID_OTG_NOTIFY_DISCONN 0x0002 +#define MID_OTG_NOTIFY_HSUSPEND 0x0003 +#define MID_OTG_NOTIFY_HRESUME 0x0004 +#define MID_OTG_NOTIFY_CSUSPEND 0x0005 +#define MID_OTG_NOTIFY_CRESUME 0x0006 +#define MID_OTG_NOTIFY_HOSTADD 0x0007 +#define MID_OTG_NOTIFY_HOSTREMOVE 0x0008 +#define MID_OTG_NOTIFY_CLIENTADD 0x0009 +#define MID_OTG_NOTIFY_CLIENTREMOVE 0x000a + +static inline int +intel_mid_otg_register_notifier(struct intel_mid_otg_xceiv *iotg, + struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&iotg->iotg_notifier, nb); +} + +static inline void +intel_mid_otg_unregister_notifier(struct intel_mid_otg_xceiv *iotg, + struct notifier_block *nb) +{ + atomic_notifier_chain_unregister(&iotg->iotg_notifier, nb); +} + +#endif /* __INTEL_MID_OTG_H */ From 56e9406ca22968e3c9dc27d6dc0f1825e13bfff9 Mon Sep 17 00:00:00 2001 From: Hao Wu Date: Thu, 9 Sep 2010 22:35:54 +0100 Subject: [PATCH 033/141] USB OTG Langwell: Update OTG Kconfig and driver version. This patch updated Kconfig for langwell otg transceiver driver. Add ipc driver(INTEL_SCU_IPC) as a dependency. Driver version is updated too. Signed-off-by: Hao Wu Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/Kconfig | 2 +- drivers/usb/otg/langwell_otg.c | 4 ++-- include/linux/usb/langwell_otg.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 299dfd2510cb..5ce07528cd0c 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -69,7 +69,7 @@ config NOP_USB_XCEIV config USB_LANGWELL_OTG tristate "Intel Langwell USB OTG dual-role support" - depends on USB && X86_MRST + depends on USB && PCI && INTEL_SCU_IPC select USB_OTG select USB_OTG_UTILS help diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c index 879188086daf..bdc3ea66be69 100644 --- a/drivers/usb/otg/langwell_otg.c +++ b/drivers/usb/otg/langwell_otg.c @@ -1,6 +1,6 @@ /* * Intel Langwell USB OTG transceiver driver - * Copyright (C) 2008 - 2009, Intel Corporation. + * Copyright (C) 2008 - 2010, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -40,7 +40,7 @@ #include #define DRIVER_DESC "Intel Langwell USB OTG transceiver driver" -#define DRIVER_VERSION "3.0.0.32L.0003" +#define DRIVER_VERSION "July 10, 2010" MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR("Henry Yuan , Hao Wu "); diff --git a/include/linux/usb/langwell_otg.h b/include/linux/usb/langwell_otg.h index a6562f1d4e2b..51f17b16d312 100644 --- a/include/linux/usb/langwell_otg.h +++ b/include/linux/usb/langwell_otg.h @@ -1,6 +1,6 @@ /* * Intel Langwell USB OTG transceiver driver - * Copyright (C) 2008, Intel Corporation. + * Copyright (C) 2008 - 2010, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, From 92d3489ec58b5897a407b07ad9954497a119d3d0 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 10 Sep 2010 08:42:08 -0400 Subject: [PATCH 034/141] USB: r8a66597-udc: Initialize uninitialized variable, fix compile warning In today linux-next I got a compile warning due a possible uninitialized variable This patch solves the issue initializing the variable Signed-off-by: Javier Martinez Canillas Cc: David Brownell Cc: Paul Mundt Cc: Magnus Damm Cc: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/r8a66597-udc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h index f763b5190afa..5fc22e09a0f1 100644 --- a/drivers/usb/gadget/r8a66597-udc.h +++ b/drivers/usb/gadget/r8a66597-udc.h @@ -136,7 +136,7 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, int len) { void __iomem *fifoaddr = r8a66597->reg + offset; - unsigned int data; + unsigned int data = 0; int i; if (r8a66597->pdata->on_chip) { From 5c8db070b4480c43394680d9dfd2ddb06b97d2ae Mon Sep 17 00:00:00 2001 From: Praveena Nadahally Date: Fri, 10 Sep 2010 23:05:03 +0530 Subject: [PATCH 035/141] USB: Change acm_iad_descriptor bFunctionProtocol to USB_CDC_ACM_PROTO_AT_V25TER The protocol code is set 00 in IAD and it's set to 01 in ACM control interface descriptor in f_acm.c file. Due to this, windows is unable to install the modem(ACM) driver based on class-subclass-protocol matching. This patch corrects the protocol code in ACM IAD to the same as in acm_control_interface_desc protocol code. Acked-by: Linus Walleij Signed-off-by: Praveena Nadahally Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_acm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index d47a123f15ab..bd6226cbae86 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -111,7 +111,7 @@ acm_iad_descriptor = { .bInterfaceCount = 2, // control + data .bFunctionClass = USB_CLASS_COMM, .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, - .bFunctionProtocol = USB_CDC_PROTO_NONE, + .bFunctionProtocol = USB_CDC_ACM_PROTO_AT_V25TER, /* .iFunction = DYNAMIC */ }; From 637ed74ff9e86d8c2979e430309a1fd28c921de9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 10 Sep 2010 21:35:15 +0200 Subject: [PATCH 036/141] USB: ohci-sm501: add iounmap on error path This ioremap() was leaked on an error path. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-sm501.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index cff23637cfcc..041d30f30c10 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -168,7 +168,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev) retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (retval) - goto err4; + goto err5; /* enable power and unmask interrupts */ @@ -176,6 +176,8 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev) sm501_modify_reg(dev->parent, SM501_IRQ_MASK, 1 << 6, 0); return 0; +err5: + iounmap(hcd->regs); err4: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err3: From 3df7169e73fc1d71a39cffeacc969f6840cdf52b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 10 Sep 2010 16:37:05 -0400 Subject: [PATCH 037/141] OHCI: work around for nVidia shutdown problem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch (as1417) fixes a problem affecting some (or all) nVidia chipsets. When the computer is shut down, the OHCI controllers continue to power the USB buses and evidently they drive a Reset signal out all their ports. This prevents attached devices from going to low power. Mouse LEDs stay on, for example, which is disconcerting for users and a drain on laptop batteries. The fix involves leaving each OHCI controller in the OPERATIONAL state during system shutdown rather than putting it in the RESET state. Although this nominally means the controller is running, in fact it's not doing very much since all the schedules are all disabled. However there is ongoing DMA to the Host Controller Communications Area, so the patch also disables the bus-master capability of all PCI USB controllers after the shutdown routine runs. The fix is applied only to nVidia-based PCI OHCI controllers, so it shouldn't cause problems on systems using other hardware. As an added safety measure, in case the kernel encounters one of these running controllers during boot, the patch changes quirk_usb_handoff_ohci() (which runs early on during PCI discovery) to reset the controller before anything bad can happen. Reported-by: Pali Rohár Signed-off-by: Alan Stern CC: David Brownell Tested-by: Pali Rohár CC: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd-pci.c | 4 +++- drivers/usb/host/ohci-hcd.c | 9 ++++++++- drivers/usb/host/ohci-pci.c | 18 ++++++++++++++++++ drivers/usb/host/ohci.h | 1 + drivers/usb/host/pci-quirks.c | 18 +++++++++++------- 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index c3f98543caaf..3799573bd385 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -329,8 +329,10 @@ void usb_hcd_pci_shutdown(struct pci_dev *dev) return; if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && - hcd->driver->shutdown) + hcd->driver->shutdown) { hcd->driver->shutdown(hcd); + pci_disable_device(dev); + } } EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index c3b4ccc7337b..8ef3c1944364 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -398,7 +398,14 @@ ohci_shutdown (struct usb_hcd *hcd) ohci = hcd_to_ohci (hcd); ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); - ohci_usb_reset (ohci); + ohci->hc_control = ohci_readl(ohci, &ohci->regs->control); + + /* If the SHUTDOWN quirk is set, don't put the controller in RESET */ + ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ? + OHCI_CTRL_RWC | OHCI_CTRL_HCFS : + OHCI_CTRL_RWC); + ohci_writel(ohci, ohci->hc_control, &ohci->regs->control); + /* flush the writes */ (void) ohci_readl (ohci, &ohci->regs->control); } diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 6bdc8b25a6a1..36ee9a666e93 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -201,6 +201,20 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd) return 0; } +/* nVidia controllers continue to drive Reset signalling on the bus + * even after system shutdown, wasting power. This flag tells the + * shutdown routine to leave the controller OPERATIONAL instead of RESET. + */ +static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + + ohci->flags |= OHCI_QUIRK_SHUTDOWN; + ohci_dbg(ohci, "enabled nVidia shutdown quirk\n"); + + return 0; +} + /* * The hardware normally enables the A-link power management feature, which * lets the system lower the power consumption in idle states. @@ -332,6 +346,10 @@ static const struct pci_device_id ohci_pci_quirks[] = { PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399), .driver_data = (unsigned long)ohci_quirk_amd700, }, + { + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), + .driver_data = (unsigned long) ohci_quirk_nvidia_shutdown, + }, /* FIXME for some of the early AMD 760 southbridges, OHCI * won't work at all. blacklist them. diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 5bf15fed0d9f..51facb985c84 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -403,6 +403,7 @@ struct ohci_hcd { #define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */ #define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/ #define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */ +#define OHCI_QUIRK_SHUTDOWN 0x800 /* nVidia power bug */ // there are also chip quirks/bugs in init logic struct work_struct nec_work; /* Worker for NEC quirk */ diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 83b5f9cea85a..464ed977b45d 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -169,6 +169,7 @@ static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx) static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) { void __iomem *base; + u32 control; if (!mmio_resource_enabled(pdev, 0)) return; @@ -177,10 +178,14 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) if (base == NULL) return; + control = readl(base + OHCI_CONTROL); + /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ -#ifndef __hppa__ -{ - u32 control = readl(base + OHCI_CONTROL); +#ifdef __hppa__ +#define OHCI_CTRL_MASK (OHCI_CTRL_RWC | OHCI_CTRL_IR) +#else +#define OHCI_CTRL_MASK OHCI_CTRL_RWC + if (control & OHCI_CTRL_IR) { int wait_time = 500; /* arbitrary; 5 seconds */ writel(OHCI_INTR_OC, base + OHCI_INTRENABLE); @@ -194,13 +199,12 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) dev_warn(&pdev->dev, "OHCI: BIOS handoff failed" " (BIOS bug?) %08x\n", readl(base + OHCI_CONTROL)); - - /* reset controller, preserving RWC */ - writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL); } -} #endif + /* reset controller, preserving RWC (and possibly IR) */ + writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL); + /* * disable interrupts */ From 5c836e4d583701a5eecb288b5f131da39115f5ec Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 8 Sep 2010 13:48:44 +0300 Subject: [PATCH 038/141] usb gadget: composite: prevent OOPS for non-standard control request The composite gadget will OOPS if the host sends a control request targetted to an interface of an un-configured composite device. This patch prevents this. The OOPS was observed during WHQL USB CV tests. With this patch, the device STALLs as per requirement. Failing test case: From host do the following. I used libusb-1.0 1) Set configuration to zero. libusb_control_transfer(device_handle, 0, /* standard OUT */ 0x9, /* setConfiguration */ 0, 0, NULL, 0, 0); 2) Query current configuratioan. libusb_control_transfer(device_handle, 0x80, /* standard IN*/ 0x8, /* getConfiguration */ 0, 0, data, 1, 0); 3) Send the non-standard ctrl transfer targetted to interface libusb_control_transfer(device_handle, 0x81, /* standard IN to interface*/ 0x6, /* getDescriptor */ 0x2300, 0, data, 0x12, 0); Signed-off-by: Roger Quadros Cc: stable Cc: David Brownell Cc: Michal Nazarewicz Cc: Robert Lukassen Cc: Kyungmin Park Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/composite.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 5e2bd7428424..7b5cc16e4a0b 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -928,7 +928,8 @@ unknown: */ switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_INTERFACE: - f = cdev->config->interface[intf]; + if (cdev->config) + f = cdev->config->interface[intf]; break; case USB_RECIP_ENDPOINT: From e9137c2e44116a1fcb82bb99dc84318e792c150b Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 9 Sep 2010 17:31:29 -0400 Subject: [PATCH 039/141] USB: isp1362-hcd: Removes CONFIG_USB_OTG dependent code, fix build breakage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In today linux-next I got a compile error on usb/host/isp1362-hcd: drivers/usb/host/isp1362-hcd.c: In function ‘isp1362_hub_control’: drivers/usb/host/isp1362-hcd.c:1680: error: ‘ohci’ undeclared (first use in this function) The problem is when the CONFIG_USB_OTG option is enabled. ohci variable is never declared and there isn't any CONFIG_USB_OTG dependent code besides the portion defined in isp1362_hub_control. So I think that maybe USB OTG support is not needed/supported. This patch removes the CONFIG_USB_OTG dependent block so the driver can compile cleanly. Signed-off-by: Javier Martinez Canillas Cc: Mike Frysinger Cc: Lothar Wassmann Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1362-hcd.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 0587ad4ce5c2..ae3044019382 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -1676,13 +1676,6 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, switch (wValue) { case USB_PORT_FEAT_SUSPEND: _DBG(0, "USB_PORT_FEAT_SUSPEND\n"); -#ifdef CONFIG_USB_OTG - if (ohci->hcd.self.otg_port == (wIndex + 1) && - ohci->hcd.self.b_hnp_enable) { - start_hnp(ohci); - break; - } -#endif spin_lock_irqsave(&isp1362_hcd->lock, flags); isp1362_write_reg32(isp1362_hcd, HCRHPORT1 + wIndex, RH_PS_PSS); isp1362_hcd->rhport[wIndex] = From c0109b8fd29d1e1623fc0455cdf00463052bb566 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 11 Sep 2010 22:10:58 -0700 Subject: [PATCH 040/141] USB: gadget: Remove pr_ uses of KERN_ Signed-off-by: Joe Perches Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/r8a66597-udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index 95092151f901..157640f7d2a8 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -274,7 +274,7 @@ static int pipe_buffer_setting(struct r8a66597 *r8a66597, } if (buf_bsize && ((bufnum + 16) >= R8A66597_MAX_BUFNUM)) { - pr_err(KERN_ERR "r8a66597 pipe memory is insufficient\n"); + pr_err("r8a66597 pipe memory is insufficient\n"); return -ENOMEM; } From ecfa153ef616b901e86d9a051b329fcda7a6ce7b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 12 Sep 2010 11:41:50 -0300 Subject: [PATCH 041/141] USB: option: Add more ZTE modem USB id's There are lots of ZTE USB id's currently not covered by usb/serial. Adds them, to allow those devices to work properly on Linux. While here, put the USB ID's for 0x2002/0x2003 at the sorted order. This patch is based on zte.c file found on MF645. PS.: The ZTE driver is commenting the USB ID for 0x0053. It also adds, commented, an USB ID for 0x0026. Not sure why, but I think that 0053 is used by their devices in storage mode only. So, I opted to keep the comment on this patch. Signed-off-by: Mauro Carvalho Chehab Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index c46911af282f..51de0ddefbf1 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -622,6 +622,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0011, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff) }, @@ -633,38 +634,52 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0023, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) }, + /* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) }, */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0034, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0037, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0038, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0039, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0040, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0042, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0043, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0044, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0048, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0049, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0050, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff) }, + /* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0053, 0xff, 0xff, 0xff) }, */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0056, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0064, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0065, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0067, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0077, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0079, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0082, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0083, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0087, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0105, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0106, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0108, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff) }, @@ -880,6 +895,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, From d3134c3b1a5d2a9dca2ddacacb5d08fad7941d8c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 13 Sep 2010 11:24:52 +0300 Subject: [PATCH 042/141] uwb: use '%pM' format to print MAC address Signed-off-by: Andy Shevchenko Cc: David Vrabel Signed-off-by: Greg Kroah-Hartman --- drivers/uwb/address.c | 5 +---- drivers/uwb/wlp/wss-lc.c | 7 ++----- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/uwb/address.c b/drivers/uwb/address.c index 973321327c44..8739c4f4d015 100644 --- a/drivers/uwb/address.c +++ b/drivers/uwb/address.c @@ -363,10 +363,7 @@ size_t __uwb_addr_print(char *buf, size_t buf_size, const unsigned char *addr, { size_t result; if (type) - result = scnprintf(buf, buf_size, - "%02x:%02x:%02x:%02x:%02x:%02x", - addr[0], addr[1], addr[2], - addr[3], addr[4], addr[5]); + result = scnprintf(buf, buf_size, "%pM", addr); else result = scnprintf(buf, buf_size, "%02x:%02x", addr[1], addr[0]); diff --git a/drivers/uwb/wlp/wss-lc.c b/drivers/uwb/wlp/wss-lc.c index a005d2a03b5d..67872c83b679 100644 --- a/drivers/uwb/wlp/wss-lc.c +++ b/drivers/uwb/wlp/wss-lc.c @@ -791,11 +791,8 @@ int wlp_wss_prep_hdr(struct wlp *wlp, struct wlp_eda_node *eda_entry, } else { if (printk_ratelimit()) dev_err(dev, "WLP: Destination neighbor (Ethernet: " - "%02x:%02x:%02x:%02x:%02x:%02x, Dev: " - "%02x:%02x) is not connected. \n", eth_addr[0], - eth_addr[1], eth_addr[2], eth_addr[3], - eth_addr[4], eth_addr[5], dev_addr->data[1], - dev_addr->data[0]); + "%pM, Dev: %02x:%02x) is not connected.\n", + eth_addr, dev_addr->data[1], dev_addr->data[0]); result = -EINVAL; } return result; From 834e2312e7a384877a876b0d34dffc3046c96bcb Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 13 Sep 2010 10:43:25 -0400 Subject: [PATCH 043/141] USB: teach "devices" file about Wireless and SuperSpeed USB The /sys/kernel/debug/usb/devices file doesn't know about Wireless or SuperSpeed USB. This patch (as1416b) teaches it, and updates the Documentation/usb/proc_sub_info.txt file accordingly. Signed-off-by: Alan Stern CC: David Vrabel CC: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/proc_usb_info.txt | 34 +++++++++++++++++++---------- drivers/usb/core/devices.c | 11 ++++++---- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt index fafcd4723260..afe596d5f201 100644 --- a/Documentation/usb/proc_usb_info.txt +++ b/Documentation/usb/proc_usb_info.txt @@ -1,12 +1,17 @@ /proc/bus/usb filesystem output =============================== -(version 2003.05.30) +(version 2010.09.13) The usbfs filesystem for USB devices is traditionally mounted at /proc/bus/usb. It provides the /proc/bus/usb/devices file, as well as the /proc/bus/usb/BBB/DDD files. +In many modern systems the usbfs filsystem isn't used at all. Instead +USB device nodes are created under /dev/usb/ or someplace similar. The +"devices" file is available in debugfs, typically as +/sys/kernel/debug/usb/devices. + **NOTE**: If /proc/bus/usb appears empty, and a host controller driver has been linked, then you need to mount the @@ -106,8 +111,8 @@ Legend: Topology info: -T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd -| | | | | | | | |__MaxChildren +T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd +| | | | | | | | |__MaxChildren | | | | | | | |__Device Speed in Mbps | | | | | | |__DeviceNumber | | | | | |__Count of devices at this level @@ -120,8 +125,13 @@ T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd Speed may be: 1.5 Mbit/s for low speed USB 12 Mbit/s for full speed USB - 480 Mbit/s for high speed USB (added for USB 2.0) + 480 Mbit/s for high speed USB (added for USB 2.0); + also used for Wireless USB, which has no fixed speed + 5000 Mbit/s for SuperSpeed USB (added for USB 3.0) + For reasons lost in the mists of time, the Port number is always + too low by 1. For example, a device plugged into port 4 will + show up with "Port=03". Bandwidth info: B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd @@ -291,7 +301,7 @@ Here's an example, from a system which has a UHCI root hub, an external hub connected to the root hub, and a mouse and a serial converter connected to the external hub. -T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 +T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 B: Alloc= 28/900 us ( 3%), #Int= 2, #Iso= 0 D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=0000 ProdID=0000 Rev= 0.00 @@ -301,21 +311,21 @@ C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms -T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 +T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=0451 ProdID=1446 Rev= 1.00 C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms -T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 +T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=04b4 ProdID=0001 Rev= 0.00 C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse E: Ad=81(I) Atr=03(Int.) MxPS= 3 Ivl= 10ms -T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 +T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=0565 ProdID=0001 Rev= 1.08 S: Manufacturer=Peracom Networks, Inc. @@ -330,12 +340,12 @@ E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl= 8ms Selecting only the "T:" and "I:" lines from this (for example, by using "procusb ti"), we have: -T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 -T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 +T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 +T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub -T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 +T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse -T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 +T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 I: If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 3449742c00e1..ddb4dc980923 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -66,8 +66,8 @@ #define ALLOW_SERIAL_NUMBER static const char *format_topo = -/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */ -"\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n"; +/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd */ +"\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%-4s MxCh=%2d\n"; static const char *format_string_manufacturer = /* S: Manufacturer=xxxx */ @@ -520,11 +520,14 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, speed = "1.5"; break; case USB_SPEED_UNKNOWN: /* usb 1.1 root hub code */ case USB_SPEED_FULL: - speed = "12 "; break; + speed = "12"; break; + case USB_SPEED_WIRELESS: /* Wireless has no real fixed speed */ case USB_SPEED_HIGH: speed = "480"; break; + case USB_SPEED_SUPER: + speed = "5000"; break; default: - speed = "?? "; + speed = "??"; } data_end = pages_start + sprintf(pages_start, format_topo, bus->busnum, level, parent_devnum, From 82cef0b8bf90047ee10d6b826ca16630e4e80fae Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 13 Sep 2010 21:23:58 -0700 Subject: [PATCH 044/141] usb: host: oxu210hp-hcd: Use static const char * const where possible Signed-off-by: Joe Perches Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/oxu210hp-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index d9c85a292737..d32c3eae99cb 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -3696,7 +3696,7 @@ static void oxu_configuration(struct platform_device *pdev, void *base) static int oxu_verify_id(struct platform_device *pdev, void *base) { u32 id; - char *bo[] = { + static const char * const bo[] = { "reserved", "128-pin LQFP", "84-pin TFBGA", From 3126d8236ca6f68eb8292c6af22c2e59afbeef24 Mon Sep 17 00:00:00 2001 From: Rich Mattes Date: Tue, 14 Sep 2010 00:35:40 -0400 Subject: [PATCH 045/141] USB: ftdi_sio: Add PID for accesio products Adds support for Accesio USB to Serial adapters, which are built around FTDI FT232 UARTs. Tested with the Accesio USB-COM-4SM. Signed-off-by: Rich Mattes Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 97cc87d654ce..6e6b0da59287 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -751,6 +751,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) }, + { USB_DEVICE(FTDI_VID, ACCESIO_COM4SM_PID) }, { USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_24_MASTER_WING_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 15a4583775ad..02659f5c79e2 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1063,3 +1063,9 @@ * Submitted by John G. Rogers */ #define SEGWAY_RMP200_PID 0xe729 + + +/* + * Accesio USB Data Acquisition products (http://www.accesio.com/) + */ +#define ACCESIO_COM4SM_PID 0xD578 From ffb6748fa988927270cafb4d0988e42545b35f82 Mon Sep 17 00:00:00 2001 From: Keshava Munegowda Date: Tue, 14 Sep 2010 04:40:01 +0530 Subject: [PATCH 046/141] usb: omap: ohci: Missing driver unregister in module exit The un-registration of OHCI driver was not done in the ohci_hcd_mod_exit function. This was affecting rmmod command not to work for OMAP3 platforms. The platform driver un-registration for OMAP3 platforms is perfomed while removing the OHCI module from kernel. Signed-off-by: Keshava Munegowda Signed-of-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hcd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 8ef3c1944364..3b5785032a10 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1277,6 +1277,9 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef PLATFORM_DRIVER platform_driver_unregister(&PLATFORM_DRIVER); #endif +#ifdef OMAP3_PLATFORM_DRIVER + platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); +#endif #ifdef PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); #endif From 2f1136d1d08a63dcdbcd462621373f30d8dfe590 Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Fri, 17 Sep 2010 11:09:06 -0400 Subject: [PATCH 047/141] USB: cp210x: Add Renesas RX-Stick device ID RX610 development board by Renesas Bus 001 Device 024: ID 045b:0053 Hitachi, Ltd Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x045b Hitachi, Ltd idProduct 0x0053 bcdDevice 1.00 iManufacturer 1 Silicon Labs iProduct 2 RX-Stick iSerial 3 0001 . . . http://am.renesas.com/rx610stick Signed-off-by: DJ Delorie Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 4f1744c5871f..f72afa970503 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -54,6 +54,7 @@ static int cp210x_carrier_raised(struct usb_serial_port *p); static int debug; static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */ { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ { USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ From c6991b6fd2b4201174dc4620d0c8c4f5ff27b36f Mon Sep 17 00:00:00 2001 From: Enrico Mioso Date: Fri, 17 Sep 2010 10:54:23 +0200 Subject: [PATCH 048/141] USB: option: Add new ONDA vendor id and product id for ONDA MT825UP This patch, adds to the option driver the Onda Communication (http://www.ondacommunication.com) vendor id, and the MT825UP modem device id. Note that many variants of this same device are being release here in Italy (at least one or two per telephony operator). These devices are perfectly equivalent except for some predefined settings (which can be changed of course). It should be noted that most ONDA devices are allready supported (they used other vendor's ids in the past). The patch seems working fine here, and the rest of the driver seems uninfluenced. Signed-off-by: Enrico Mioso Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 51de0ddefbf1..2297fb1bcf65 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -392,6 +392,12 @@ static void option_instat_callback(struct urb *urb); #define CELOT_VENDOR_ID 0x211f #define CELOT_PRODUCT_CT680M 0x6801 +/* ONDA Communication vendor id */ +#define ONDA_VENDOR_ID 0x1ee8 + +/* ONDA MT825UP HSDPA 14.2 modem */ +#define ONDA_MT825UP 0x000b + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -942,6 +948,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) }, { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ + { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); From 1f53c0e9bbf654ed93f63deee2bf5c9a1816966e Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Mon, 20 Sep 2010 15:40:26 +0300 Subject: [PATCH 049/141] USB: cdc.h: ncm: typo and style fixes Some typos were in the initial commit, make the spelling according to the spec. Add some more comments. Also change constant names according to the style of the rest of the file Signed-off-by: Yauheni Kaliuta Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/cdc.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h index c117a68d04a7..583264abca0c 100644 --- a/include/linux/usb/cdc.h +++ b/include/linux/usb/cdc.h @@ -274,13 +274,13 @@ struct usb_cdc_notification { /* * Class Specific structures and constants * - * CDC NCM parameter structure, CDC NCM subclass 6.2.1 + * CDC NCM NTB parameters structure, CDC NCM subclass 6.2.1 * */ -struct usb_cdc_ncm_ntb_parameter { +struct usb_cdc_ncm_ntb_parameters { __le16 wLength; - __le16 bmNtbFormatSupported; + __le16 bmNtbFormatsSupported; __le32 dwNtbInMaxSize; __le16 wNdpInDivisor; __le16 wNdpInPayloadRemainder; @@ -297,8 +297,8 @@ struct usb_cdc_ncm_ntb_parameter { * CDC NCM transfer headers, CDC NCM subclass 3.2 */ -#define NCM_NTH16_SIGN 0x484D434E /* NCMH */ -#define NCM_NTH32_SIGN 0x686D636E /* ncmh */ +#define USB_CDC_NCM_NTH16_SIGN 0x484D434E /* NCMH */ +#define USB_CDC_NCM_NTH32_SIGN 0x686D636E /* ncmh */ struct usb_cdc_ncm_nth16 { __le32 dwSignature; @@ -320,11 +320,12 @@ struct usb_cdc_ncm_nth32 { * CDC NCM datagram pointers, CDC NCM subclass 3.3 */ -#define NCM_NDP16_CRC_SIGN 0x314D434E /* NCM1 */ -#define NCM_NDP16_NOCRC_SIGN 0x304D434E /* NCM0 */ -#define NCM_NDP32_CRC_SIGN 0x316D636E /* ncm1 */ -#define NCM_NDP32_NOCRC_SIGN 0x306D636E /* ncm0 */ +#define USB_CDC_NCM_NDP16_CRC_SIGN 0x314D434E /* NCM1 */ +#define USB_CDC_NCM_NDP16_NOCRC_SIGN 0x304D434E /* NCM0 */ +#define USB_CDC_NCM_NDP32_CRC_SIGN 0x316D636E /* ncm1 */ +#define USB_CDC_NCM_NDP32_NOCRC_SIGN 0x306D636E /* ncm0 */ +/* 16-bit NCM Datagram Pointer Table */ struct usb_cdc_ncm_ndp16 { __le32 dwSignature; __le16 wLength; @@ -332,11 +333,12 @@ struct usb_cdc_ncm_ndp16 { __u8 data[0]; } __attribute__ ((packed)); +/* 32-bit NCM Datagram Pointer Table */ struct usb_cdc_ncm_ndp32 { __le32 dwSignature; __le16 wLength; __le16 wReserved6; - __le32 dwNextFpIndex; + __le32 dwNextNdpIndex; __le32 dwReserved12; __u8 data[0]; } __attribute__ ((packed)); From 7fc09170cedc329ad274433b4f1a653e603600b5 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Mon, 20 Sep 2010 15:40:27 +0300 Subject: [PATCH 050/141] Revert "USB: ncm: added ncm.h with auxiliary definitions" This reverts commit 65e0b499105ec8ff3bc4ab7680873dec20127f9d. Since the host and gadget implementations are different, there is no common code for the file, remove for now. Signed-off-by: Yauheni Kaliuta Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/ncm.h | 114 ---------------------------------------- 1 file changed, 114 deletions(-) delete mode 100644 include/linux/usb/ncm.h diff --git a/include/linux/usb/ncm.h b/include/linux/usb/ncm.h deleted file mode 100644 index 006d1064c8b2..000000000000 --- a/include/linux/usb/ncm.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * USB CDC NCM auxiliary definitions - */ - -#ifndef __LINUX_USB_NCM_H -#define __LINUX_USB_NCM_H - -#include -#include -#include - -#define NCM_NTB_MIN_IN_SIZE 2048 -#define NCM_NTB_MIN_OUT_SIZE 2048 - -#define NCM_CONTROL_TIMEOUT (5 * 1000) - -/* bmNetworkCapabilities */ - -#define NCM_NCAP_ETH_FILTER (1 << 0) -#define NCM_NCAP_NET_ADDRESS (1 << 1) -#define NCM_NCAP_ENCAP_COMM (1 << 2) -#define NCM_NCAP_MAX_DGRAM (1 << 3) -#define NCM_NCAP_CRC_MODE (1 << 4) - -/* - * Here are options for NCM Datagram Pointer table (NDP) parser. - * There are 2 different formats: NDP16 and NDP32 in the spec (ch. 3), - * in NDP16 offsets and sizes fields are 1 16bit word wide, - * in NDP32 -- 2 16bit words wide. Also signatures are different. - * To make the parser code the same, put the differences in the structure, - * and switch pointers to the structures when the format is changed. - */ - -struct ndp_parser_opts { - u32 nth_sign; - u32 ndp_sign; - unsigned nth_size; - unsigned ndp_size; - unsigned ndplen_align; - /* sizes in u16 units */ - unsigned dgram_item_len; /* index or length */ - unsigned block_length; - unsigned fp_index; - unsigned reserved1; - unsigned reserved2; - unsigned next_fp_index; -}; - -#define INIT_NDP16_OPTS { \ - .nth_sign = NCM_NTH16_SIGN, \ - .ndp_sign = NCM_NDP16_NOCRC_SIGN, \ - .nth_size = sizeof(struct usb_cdc_ncm_nth16), \ - .ndp_size = sizeof(struct usb_cdc_ncm_ndp16), \ - .ndplen_align = 4, \ - .dgram_item_len = 1, \ - .block_length = 1, \ - .fp_index = 1, \ - .reserved1 = 0, \ - .reserved2 = 0, \ - .next_fp_index = 1, \ - } - - -#define INIT_NDP32_OPTS { \ - .nth_sign = NCM_NTH32_SIGN, \ - .ndp_sign = NCM_NDP32_NOCRC_SIGN, \ - .nth_size = sizeof(struct usb_cdc_ncm_nth32), \ - .ndp_size = sizeof(struct usb_cdc_ncm_ndp32), \ - .ndplen_align = 8, \ - .dgram_item_len = 2, \ - .block_length = 2, \ - .fp_index = 2, \ - .reserved1 = 1, \ - .reserved2 = 2, \ - .next_fp_index = 2, \ - } - -static inline void put_ncm(__le16 **p, unsigned size, unsigned val) -{ - switch (size) { - case 1: - put_unaligned_le16((u16)val, *p); - break; - case 2: - put_unaligned_le32((u32)val, *p); - - break; - default: - BUG(); - } - - *p += size; -} - -static inline unsigned get_ncm(__le16 **p, unsigned size) -{ - unsigned tmp; - - switch (size) { - case 1: - tmp = get_unaligned_le16(*p); - break; - case 2: - tmp = get_unaligned_le32(*p); - break; - default: - BUG(); - } - - *p += size; - return tmp; -} - -#endif /* __LINUX_USB_NCM_H */ From e5dcd531ac7a040f1b4d35f58914a36ad6174e84 Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Mon, 20 Sep 2010 15:40:28 +0300 Subject: [PATCH 051/141] USB: cdc.h: ncm: add missed constants and structures Make a dedicated structure for datagram pointer entry. There is no explicit declaration in the spec, but it's used by the host implementation and makes the structure more clear. Add some missed constants from the spec Signed-off-by: Yauheni Kaliuta Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/cdc.h | 57 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h index 583264abca0c..2d5b6f296aa3 100644 --- a/include/linux/usb/cdc.h +++ b/include/linux/usb/cdc.h @@ -32,6 +32,8 @@ #define USB_CDC_PROTO_EEM 7 +#define USB_CDC_NCM_PROTO_NTB 1 + /*-------------------------------------------------------------------------*/ /* @@ -325,14 +327,26 @@ struct usb_cdc_ncm_nth32 { #define USB_CDC_NCM_NDP32_CRC_SIGN 0x316D636E /* ncm1 */ #define USB_CDC_NCM_NDP32_NOCRC_SIGN 0x306D636E /* ncm0 */ +/* 16-bit NCM Datagram Pointer Entry */ +struct usb_cdc_ncm_dpe16 { + __le16 wDatagramIndex; + __le16 wDatagramLength; +} __attribute__((__packed__)); + /* 16-bit NCM Datagram Pointer Table */ struct usb_cdc_ncm_ndp16 { __le32 dwSignature; __le16 wLength; __le16 wNextFpIndex; - __u8 data[0]; + struct usb_cdc_ncm_dpe16 dpe16[0]; } __attribute__ ((packed)); +/* 32-bit NCM Datagram Pointer Entry */ +struct usb_cdc_ncm_dpe32 { + __le32 wDatagramIndex; + __le32 wDatagramLength; +} __attribute__((__packed__)); + /* 32-bit NCM Datagram Pointer Table */ struct usb_cdc_ncm_ndp32 { __le32 dwSignature; @@ -340,7 +354,46 @@ struct usb_cdc_ncm_ndp32 { __le16 wReserved6; __le32 dwNextNdpIndex; __le32 dwReserved12; - __u8 data[0]; + struct usb_cdc_ncm_dpe32 dpe32[0]; } __attribute__ ((packed)); +/* CDC NCM subclass 3.2.1 and 3.2.2 */ +#define USB_CDC_NCM_NDP16_INDEX_MIN 0x000C +#define USB_CDC_NCM_NDP32_INDEX_MIN 0x0010 + +/* CDC NCM subclass 3.3.3 Datagram Formatting */ +#define USB_CDC_NCM_DATAGRAM_FORMAT_CRC 0x30 +#define USB_CDC_NCM_DATAGRAM_FORMAT_NOCRC 0X31 + +/* CDC NCM subclass 4.2 NCM Communications Interface Protocol Code */ +#define USB_CDC_NCM_PROTO_CODE_NO_ENCAP_COMMANDS 0x00 +#define USB_CDC_NCM_PROTO_CODE_EXTERN_PROTO 0xFE + +/* CDC NCM subclass 5.2.1 NCM Functional Descriptor, bmNetworkCapabilities */ +#define USB_CDC_NCM_NCAP_ETH_FILTER (1 << 0) +#define USB_CDC_NCM_NCAP_NET_ADDRESS (1 << 1) +#define USB_CDC_NCM_NCAP_ENCAP_COMMAND (1 << 2) +#define USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE (1 << 3) +#define USB_CDC_NCM_NCAP_CRC_MODE (1 << 4) + +/* CDC NCM subclass Table 6-3: NTB Parameter Structure */ +#define USB_CDC_NCM_NTB16_SUPPORTED (1 << 0) +#define USB_CDC_NCM_NTB32_SUPPORTED (1 << 1) + +/* CDC NCM subclass Table 6-3: NTB Parameter Structure */ +#define USB_CDC_NCM_NDP_ALIGN_MIN_SIZE 0x04 +#define USB_CDC_NCM_NTB_MAX_LENGTH 0x1C + +/* CDC NCM subclass 6.2.5 SetNtbFormat */ +#define USB_CDC_NCM_NTB16_FORMAT 0x00 +#define USB_CDC_NCM_NTB32_FORMAT 0x01 + +/* CDC NCM subclass 6.2.7 SetNtbInputSize */ +#define USB_CDC_NCM_NTB_MIN_IN_SIZE 2048 +#define USB_CDC_NCM_NTB_MIN_OUT_SIZE 2048 + +/* CDC NCM subclass 6.2.11 SetCrcMode */ +#define USB_CDC_NCM_CRC_NOT_APPENDED 0x00 +#define USB_CDC_NCM_CRC_APPENDED 0x01 + #endif /* __LINUX_USB_CDC_H */ From 969affff54702785330de553b790372e261e93f9 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Mon, 20 Sep 2010 18:31:07 +0200 Subject: [PATCH 052/141] USB: atmel_usba_udc: force vbus_pin at -EINVAL when gpio_request failled to ensure gpio_is_valid return false Signed-off-by: Nicolas Ferre Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/atmel_usba_udc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index e4810c6a0b1f..b5e20e873cba 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -2015,6 +2015,9 @@ static int __init usba_udc_probe(struct platform_device *pdev) } else { disable_irq(gpio_to_irq(udc->vbus_pin)); } + } else { + /* gpio_request fail so use -EINVAL for gpio_is_valid */ + ubc->vbus_pin = -EINVAL; } } From 1f8dd0154e09220be346819b85d195c791bb0f0b Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 16 Sep 2010 14:00:51 -0400 Subject: [PATCH 053/141] USB: serial: Enable USB autosuspend by default on qcserial Seems to work fine in my testing. Signed-off-by: Matthew Garrett Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcserial.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index cde67cacb2c3..2846ad8883ae 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -118,6 +118,8 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) spin_lock_init(&data->susp_lock); + usb_enable_autosuspend(serial->dev); + switch (nintf) { case 1: /* QDL mode */ From 677aeafe19e88c282af74564048243ccabb1c590 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Sun, 12 Sep 2010 16:31:45 +0200 Subject: [PATCH 054/141] USB: ftdi_sio: revert "USB: ftdi_sio: fix DTR/RTS line modes" This reverts commit 6a1a82df91fa0eb1cc76069a9efe5714d087eccd. RTS and DTR should not be modified based on CRTSCTS when calling set_termios. Modem control lines are raised at port open by the tty layer and should stay raised regardless of whether hardware flow control is enabled or not. This is in conformance with the way serial ports work today and many applications depend on this behaviour to be able to talk to hardware implementing hardware flow control (without the applications actually using it). Hardware which expects different behaviour on these lines can always use TIOCMSET/TIOCMBI[SC] after port open to change them. Reported-by: Daniel Mack Reported-by: Dave Mielke Signed-off-by: Johan Hovold Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 6e6b0da59287..42fea29637b3 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2029,8 +2029,6 @@ static void ftdi_set_termios(struct tty_struct *tty, "urb failed to set to rts/cts flow control\n"); } - /* raise DTR/RTS */ - set_mctrl(port, TIOCM_DTR | TIOCM_RTS); } else { /* * Xon/Xoff code @@ -2078,8 +2076,6 @@ static void ftdi_set_termios(struct tty_struct *tty, } } - /* lower DTR/RTS */ - clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } return; } From 6195e3c6aa84dbbf80a60731168118824bd58bba Mon Sep 17 00:00:00 2001 From: Yauheni Kaliuta Date: Fri, 24 Sep 2010 09:43:27 +0300 Subject: [PATCH 055/141] USB: cdc.h: ncm: fix one more typo In usb_cdc_ncm_dpe32 the fields are 32 bit long and according to usb style (hungarian notation) should be called dwDatagramIndex and dwDatagramLength (see CDC NCM subclass spec, 3.3.2). Actually, they were called wDatagramIndex, wDatagramLength. Signed-off-by: Yauheni Kaliuta Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/cdc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h index 2d5b6f296aa3..5e86dc771da4 100644 --- a/include/linux/usb/cdc.h +++ b/include/linux/usb/cdc.h @@ -343,8 +343,8 @@ struct usb_cdc_ncm_ndp16 { /* 32-bit NCM Datagram Pointer Entry */ struct usb_cdc_ncm_dpe32 { - __le32 wDatagramIndex; - __le32 wDatagramLength; + __le32 dwDatagramIndex; + __le32 dwDatagramLength; } __attribute__((__packed__)); /* 32-bit NCM Datagram Pointer Table */ From 1992de83e375acc789daf66b7b72a812a5235b75 Mon Sep 17 00:00:00 2001 From: "Matthias G. Eckermann" Date: Fri, 24 Sep 2010 18:12:01 +0200 Subject: [PATCH 056/141] USB: qcserial: Enable Diagnostics Monitor and GPS ports on Gobi 2000 this patch to qcserial.c enables the Diagnostics Monitor and NMEA GPS ports on Qualcomm Gobi 2000 devices. A Gobi 2000 device will provide 3 serial ports: # /dev/ttyUSB0 -> Diagnostics # /dev/ttyUSB1 -> 3G Modem # /dev/ttyUSB2 -> NMEA GPS port * The Diagnostics Monitor uses Qualcomm's DM protocol; I used libqcdm (ModemManager) to talk to it, found it working, but at least DM commands 12 and 64 are not implemented on my device (Gobi 2000 built into Thinkpad x100e). * Functionality of the 3G Modem port remains unchanged. * The GPS port and how to enable it has been confirmed now in the Gobi 3000 source code at: https://www.codeaurora.org/patches/quic/gobi/ Enable/disable GPS via: echo "\$GPS_START" > /dev/ttyUSB2 # use GPS echo "\$GPS_STOP" > /dev/ttyUSB2 Signed-off-by: Matthias G. Eckermann --- drivers/usb/serial/qcserial.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 2846ad8883ae..8858201eb1d3 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -152,7 +152,22 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) case 3: case 4: /* Composite mode */ - if (ifnum == 2) { + /* ifnum == 0 is a broadband network adapter */ + if (ifnum == 1) { + /* + * Diagnostics Monitor (serial line 9600 8N1) + * Qualcomm DM protocol + * use "libqcdm" (ModemManager) for communication + */ + dbg("Diagnostics Monitor found"); + retval = usb_set_interface(serial->dev, ifnum, 0); + if (retval < 0) { + dev_err(&serial->dev->dev, + "Could not set interface, error %d\n", + retval); + retval = -ENODEV; + } + } else if (ifnum == 2) { dbg("Modem port found"); retval = usb_set_interface(serial->dev, ifnum, 0); if (retval < 0) { @@ -163,6 +178,20 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) kfree(data); } return retval; + } else if (ifnum==3) { + /* + * NMEA (serial line 9600 8N1) + * # echo "\$GPS_START" > /dev/ttyUSBx + * # echo "\$GPS_STOP" > /dev/ttyUSBx + */ + dbg("NMEA GPS interface found"); + retval = usb_set_interface(serial->dev, ifnum, 0); + if (retval < 0) { + dev_err(&serial->dev->dev, + "Could not set interface, error %d\n", + retval); + retval = -ENODEV; + } } break; From 8fa7fd74ef398370383df276ca41082ba35aafd8 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 7 Oct 2010 13:05:21 +0200 Subject: [PATCH 057/141] USB: storage: Use USB_ prefix instead of US_ prefix This commit changes prefix for some of the USB mass storage class related macros (ie. USB_SC_ for subclass and USB_PR_ for class). Signed-off-by: Michal Nazarewicz Cc: Alan Stern Cc: Matthew Wilcox Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 2 +- drivers/usb/storage/scsiglue.c | 8 +- drivers/usb/storage/sddr09.c | 2 +- drivers/usb/storage/transport.c | 10 +- drivers/usb/storage/unusual_alauda.h | 4 +- drivers/usb/storage/unusual_cypress.h | 4 +- drivers/usb/storage/unusual_datafab.h | 20 +- drivers/usb/storage/unusual_devs.h | 572 ++++++++++++------------- drivers/usb/storage/unusual_freecom.h | 2 +- drivers/usb/storage/unusual_isd200.h | 12 +- drivers/usb/storage/unusual_jumpshot.h | 2 +- drivers/usb/storage/unusual_karma.h | 2 +- drivers/usb/storage/unusual_onetouch.h | 4 +- drivers/usb/storage/unusual_sddr09.h | 12 +- drivers/usb/storage/unusual_sddr55.h | 8 +- drivers/usb/storage/unusual_usbat.h | 8 +- drivers/usb/storage/usb.c | 30 +- include/linux/usb_usual.h | 49 +-- 18 files changed, 376 insertions(+), 375 deletions(-) diff --git a/drivers/block/ub.c b/drivers/block/ub.c index c48e14878582..f3fd454e28f9 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -396,7 +396,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum); #else static const struct usb_device_id ub_usb_ids[] = { - { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) }, { } }; diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index d8d98cfecada..e80362d148f3 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -113,7 +113,7 @@ static int slave_alloc (struct scsi_device *sdev) * Let the scanning code know if this target merely sets * Peripheral Device Type to 0x1f to indicate no LUN. */ - if (us->subclass == US_SC_UFI) + if (us->subclass == USB_SC_UFI) sdev->sdev_target->pdt_1f_for_no_lun = 1; return 0; @@ -176,7 +176,7 @@ static int slave_configure(struct scsi_device *sdev) /* Disk-type devices use MODE SENSE(6) if the protocol * (SubClass) is Transparent SCSI, otherwise they use * MODE SENSE(10). */ - if (us->subclass != US_SC_SCSI && us->subclass != US_SC_CYP_ATACB) + if (us->subclass != USB_SC_SCSI && us->subclass != USB_SC_CYP_ATACB) sdev->use_10_for_ms = 1; /* Many disks only accept MODE SENSE transfer lengths of @@ -245,7 +245,7 @@ static int slave_configure(struct scsi_device *sdev) * capacity will be decremented or is correct. */ if (!(us->fflags & (US_FL_FIX_CAPACITY | US_FL_CAPACITY_OK | US_FL_SCM_MULT_TARG)) && - us->protocol == US_PR_BULK) + us->protocol == USB_PR_BULK) us->use_last_sector_hacks = 1; } else { @@ -261,7 +261,7 @@ static int slave_configure(struct scsi_device *sdev) * scsi_level == 0 (UNKNOWN). Hence such devices must necessarily * be single-LUN. */ - if ((us->protocol == US_PR_CB || us->protocol == US_PR_CBI) && + if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_CBI) && sdev->scsi_level == SCSI_UNKNOWN) us->max_lun = 0; diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index ab5f9f37575a..bcb9a709d349 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -1760,7 +1760,7 @@ static int sddr09_probe(struct usb_interface *intf, if (result) return result; - if (us->protocol == US_PR_DPCM_USB) { + if (us->protocol == USB_PR_DPCM_USB) { us->transport_name = "Control/Bulk-EUSB/SDDR09"; us->transport = dpcm_transport; us->transport_reset = usb_stor_CB_reset; diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 64ec073e89de..00418995d8e9 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -642,7 +642,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) * unless the operation involved a data-in transfer. Devices * can signal most data-in errors by stalling the bulk-in pipe. */ - if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) && + if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_DPCM_USB) && srb->sc_data_direction != DMA_FROM_DEVICE) { US_DEBUGP("-- CB transport device requiring auto-sense\n"); need_auto_sense = 1; @@ -701,8 +701,8 @@ Retry_Sense: scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size); /* FIXME: we must do the protocol translation here */ - if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI || - us->subclass == US_SC_CYP_ATACB) + if (us->subclass == USB_SC_RBC || us->subclass == USB_SC_SCSI || + us->subclass == USB_SC_CYP_ATACB) srb->cmd_len = 6; else srb->cmd_len = 12; @@ -926,7 +926,7 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) /* NOTE: CB does not have a status stage. Silly, I know. So * we have to catch this at a higher level. */ - if (us->protocol != US_PR_CBI) + if (us->protocol != USB_PR_CBI) return USB_STOR_TRANSPORT_GOOD; result = usb_stor_intr_transfer(us, us->iobuf, 2); @@ -942,7 +942,7 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) * that this means we could be ignoring a real error on these * commands, but that can't be helped. */ - if (us->subclass == US_SC_UFI) { + if (us->subclass == USB_SC_UFI) { if (srb->cmnd[0] == REQUEST_SENSE || srb->cmnd[0] == INQUIRY) return USB_STOR_TRANSPORT_GOOD; diff --git a/drivers/usb/storage/unusual_alauda.h b/drivers/usb/storage/unusual_alauda.h index 8c412f885dd2..fa3e9edaa2cf 100644 --- a/drivers/usb/storage/unusual_alauda.h +++ b/drivers/usb/storage/unusual_alauda.h @@ -21,11 +21,11 @@ UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102, "Fujifilm", "DPC-R1 (Alauda)", - US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0), + USB_SC_SCSI, USB_PR_ALAUDA, init_alauda, 0), UNUSUAL_DEV( 0x07b4, 0x010a, 0x0102, 0x0102, "Olympus", "MAUSB-10 (Alauda)", - US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0), + USB_SC_SCSI, USB_PR_ALAUDA, init_alauda, 0), #endif /* defined(CONFIG_USB_STORAGE_ALAUDA) || ... */ diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h index 44be6d75dab6..c854fdebe0ae 100644 --- a/drivers/usb/storage/unusual_cypress.h +++ b/drivers/usb/storage/unusual_cypress.h @@ -23,12 +23,12 @@ UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999, "Cypress", "Cypress AT2LP", - US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0), + USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), /* CY7C68310 : support atacb and atacb2 */ UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, "Cypress", "Cypress ISD-300LP", - US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0), + USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), #endif /* defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || ... */ diff --git a/drivers/usb/storage/unusual_datafab.h b/drivers/usb/storage/unusual_datafab.h index c9298ce9f223..582a603c78be 100644 --- a/drivers/usb/storage/unusual_datafab.h +++ b/drivers/usb/storage/unusual_datafab.h @@ -21,7 +21,7 @@ UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015, "Datafab", "MDCFE-B USB CF Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, + USB_SC_SCSI, USB_PR_DATAFAB, NULL, 0), /* @@ -38,45 +38,45 @@ UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015, UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff, "SIIG/Datafab", "SIIG/Datafab Memory Stick+CF Reader/Writer", - US_SC_SCSI, US_PR_DATAFAB, NULL, + USB_SC_SCSI, USB_PR_DATAFAB, NULL, 0), /* Reported by Josef Reisinger */ UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff, "Datafab/Unknown", "MD2/MD3 Disk enclosure", - US_SC_SCSI, US_PR_DATAFAB, NULL, + USB_SC_SCSI, USB_PR_DATAFAB, NULL, US_FL_SINGLE_LUN), UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff, "Datafab/Unknown", "Datafab-based Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, + USB_SC_SCSI, USB_PR_DATAFAB, NULL, 0), UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff, "Datafab/Unknown", "Datafab-based Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, + USB_SC_SCSI, USB_PR_DATAFAB, NULL, 0), UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff, "PNY/Datafab", "PNY/Datafab CF+SM Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, + USB_SC_SCSI, USB_PR_DATAFAB, NULL, 0), UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff, "Simple Tech/Datafab", "Simple Tech/Datafab CF+SM Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, + USB_SC_SCSI, USB_PR_DATAFAB, NULL, 0), /* Submitted by Olaf Hering */ UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, "Datafab Systems, Inc.", "USB to CF + SM Combo (LC1)", - US_SC_SCSI, US_PR_DATAFAB, NULL, + USB_SC_SCSI, USB_PR_DATAFAB, NULL, 0), /* Reported by Felix Moeller @@ -86,13 +86,13 @@ UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, UNUSUAL_DEV( 0x07c4, 0xa10b, 0x0000, 0xffff, "DataFab Systems Inc.", "USB CF+MS", - US_SC_SCSI, US_PR_DATAFAB, NULL, + USB_SC_SCSI, USB_PR_DATAFAB, NULL, 0), UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, "Acomdata", "CF", - US_SC_SCSI, US_PR_DATAFAB, NULL, + USB_SC_SCSI, USB_PR_DATAFAB, NULL, US_FL_SINGLE_LUN), #endif /* defined(CONFIG_USB_STORAGE_DATAFAB) || ... */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 2c897eefadde..f43314a22ba4 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -63,26 +63,26 @@ UNUSUAL_DEV( 0x03eb, 0x2002, 0x0100, 0x0100, "ATMEL", "SND1 Storage", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE), /* Reported by Rodolfo Quesada */ UNUSUAL_DEV( 0x03ee, 0x6906, 0x0003, 0x0003, "VIA Technologies Inc.", "Mitsumi multi cardreader", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200, "HP", "CD-Writer+", - US_SC_8070, US_PR_CB, NULL, 0), + USB_SC_8070, USB_PR_CB, NULL, 0), /* Reported by Ben Efros */ UNUSUAL_DEV( 0x03f0, 0x070c, 0x0000, 0x0000, "HP", "Personal Media Drive", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SANE_SENSE ), /* Reported by Grant Grundler @@ -91,7 +91,7 @@ UNUSUAL_DEV( 0x03f0, 0x070c, 0x0000, 0x0000, UNUSUAL_DEV( 0x03f0, 0x4002, 0x0001, 0x0001, "HP", "PhotoSmart R707", - US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), /* Reported by Sebastian Kapfer * and Olaf Hering (different bcd's, same vendor/product) @@ -100,14 +100,14 @@ UNUSUAL_DEV( 0x03f0, 0x4002, 0x0001, 0x0001, UNUSUAL_DEV( 0x0409, 0x0040, 0x0000, 0x9999, "NEC", "NEC USB UF000x", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), /* Patch submitted by Mihnea-Costin Grigore */ UNUSUAL_DEV( 0x040d, 0x6205, 0x0003, 0x0003, "VIA Technologies Inc.", "USB 2.0 Card Reader", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Deduced by Jonathan Woithe @@ -117,40 +117,40 @@ UNUSUAL_DEV( 0x040d, 0x6205, 0x0003, 0x0003, UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113, "Buffalo", "DUB-P40G HDD", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), /* Submitted by Ernestas Vaiciukevicius */ UNUSUAL_DEV( 0x0419, 0x0100, 0x0100, 0x0100, "Samsung Info. Systems America, Inc.", "MP3 Player", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Orgad Shaneh */ UNUSUAL_DEV( 0x0419, 0xaace, 0x0100, 0x0100, "Samsung", "MP3 Player", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Christian Leber */ UNUSUAL_DEV( 0x0419, 0xaaf5, 0x0100, 0x0100, "TrekStor", "i.Beat 115 2.0", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_NOT_LOCKABLE ), /* Reported by Stefan Werner */ UNUSUAL_DEV( 0x0419, 0xaaf6, 0x0100, 0x0100, "TrekStor", "i.Beat Joy 2.0", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Pete Zaitcev , bz#176584 */ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, "GENERIC", "MP3 PLAYER", /* MyMusix PD-205 on the outside. */ - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Andrew Nayenko @@ -158,28 +158,28 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0610, "Nokia", "Nokia 6288", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64 ), /* Reported by Mario Rettig */ UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100, "Nokia", "Nokia 3250", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), /* Reported by */ UNUSUAL_DEV( 0x0421, 0x0433, 0x0100, 0x0100, "Nokia", "E70", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), /* Reported by Jon Hart */ UNUSUAL_DEV( 0x0421, 0x0434, 0x0100, 0x0100, "Nokia", "E60", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), /* Reported by Sumedha Swamy and @@ -187,7 +187,7 @@ UNUSUAL_DEV( 0x0421, 0x0434, 0x0100, 0x0100, UNUSUAL_DEV( 0x0421, 0x0444, 0x0100, 0x0100, "Nokia", "N91", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), /* Reported by Jiri Slaby and @@ -195,42 +195,42 @@ UNUSUAL_DEV( 0x0421, 0x0444, 0x0100, 0x0100, UNUSUAL_DEV( 0x0421, 0x0446, 0x0100, 0x0100, "Nokia", "N80", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), /* Reported by Matthew Bloch */ UNUSUAL_DEV( 0x0421, 0x044e, 0x0100, 0x0100, "Nokia", "E61", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), /* Reported by Bardur Arantsson */ UNUSUAL_DEV( 0x0421, 0x047c, 0x0370, 0x0610, "Nokia", "6131", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64 ), /* Reported by Manuel Osdoba */ UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x9999, "Nokia", "Nokia 6233", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64 ), /* Reported by Alex Corcoles */ UNUSUAL_DEV( 0x0421, 0x0495, 0x0370, 0x0370, "Nokia", "6234", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64 ), #ifdef NO_SDDR09 UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, "Microtech", "CameraMate", - US_SC_SCSI, US_PR_CB, NULL, + USB_SC_SCSI, USB_PR_CB, NULL, US_FL_SINGLE_LUN ), #endif @@ -239,7 +239,7 @@ UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100, "Neuros Audio", "USB 2.0 HD 2.5", - US_SC_DEVICE, US_PR_BULK, NULL, + USB_SC_DEVICE, USB_PR_BULK, NULL, US_FL_NEED_OVERRIDE ), /* @@ -250,7 +250,7 @@ UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100, UNUSUAL_DEV( 0x0457, 0x0150, 0x0100, 0x0100, "USBest Technology", /* sold by Transcend */ "USB Mass Storage Device", - US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), /* * Bohdan Linda @@ -260,7 +260,7 @@ UNUSUAL_DEV( 0x0457, 0x0150, 0x0100, 0x0100, UNUSUAL_DEV( 0x0457, 0x0151, 0x0100, 0x0100, "USB 2.0", "Flash Disk", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), /* Reported by Tamas Kerecsen @@ -272,7 +272,7 @@ UNUSUAL_DEV( 0x0457, 0x0151, 0x0100, 0x0100, UNUSUAL_DEV( 0x045e, 0xffff, 0x0000, 0x0000, "Mitac", "GPS", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64 ), /* @@ -284,32 +284,32 @@ UNUSUAL_DEV( 0x045e, 0xffff, 0x0000, 0x0000, UNUSUAL_DEV( 0x046b, 0xff40, 0x0100, 0x0100, "AMI", "Virtual Floppy", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_WP_DETECT), /* Patch submitted by Philipp Friedrich */ UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100, "Kyocera", "Finecam S3x", - US_SC_8070, US_PR_CB, NULL, US_FL_FIX_INQUIRY), + USB_SC_8070, USB_PR_CB, NULL, US_FL_FIX_INQUIRY), /* Patch submitted by Philipp Friedrich */ UNUSUAL_DEV( 0x0482, 0x0101, 0x0100, 0x0100, "Kyocera", "Finecam S4", - US_SC_8070, US_PR_CB, NULL, US_FL_FIX_INQUIRY), + USB_SC_8070, USB_PR_CB, NULL, US_FL_FIX_INQUIRY), /* Patch submitted by Stephane Galles */ UNUSUAL_DEV( 0x0482, 0x0103, 0x0100, 0x0100, "Kyocera", "Finecam S5", - US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), /* Patch submitted by Jens Taprogge */ UNUSUAL_DEV( 0x0482, 0x0107, 0x0100, 0x0100, "Kyocera", "CONTAX SL300R T*", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE), /* Reported by Paul Stewart @@ -317,7 +317,7 @@ UNUSUAL_DEV( 0x0482, 0x0107, 0x0100, 0x0100, UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, "Hitachi", "DVD-CAM DZ-MV100A Camcorder", - US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN), + USB_SC_SCSI, USB_PR_CB, NULL, US_FL_SINGLE_LUN), /* BENQ DC5330 * Reported by Manuel Fombuena and @@ -325,7 +325,7 @@ UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100, "Tekom Technologies, Inc", "300_CAMERA", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Patch for Nikon coolpix 2000 @@ -333,14 +333,14 @@ UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100, UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010, "NIKON", "NIKON DSC E2000", - US_SC_DEVICE, US_PR_DEVICE,NULL, + USB_SC_DEVICE, USB_PR_DEVICE,NULL, US_FL_NOT_LOCKABLE ), /* Reported by Doug Maxey (dwm@austin.ibm.com) */ UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110, "IBM", "IBM RSA2", - US_SC_DEVICE, US_PR_CB, NULL, + USB_SC_DEVICE, USB_PR_CB, NULL, US_FL_MAX_SECTORS_MIN), /* Reported by Simon Levitt @@ -348,14 +348,14 @@ UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110, UNUSUAL_DEV( 0x04b8, 0x0601, 0x0100, 0x0100, "Epson", "875DC Storage", - US_SC_SCSI, US_PR_CB, NULL, US_FL_FIX_INQUIRY), + USB_SC_SCSI, USB_PR_CB, NULL, US_FL_FIX_INQUIRY), /* Reported by Khalid Aziz * This entry is needed because the device reports Sub=ff */ UNUSUAL_DEV( 0x04b8, 0x0602, 0x0110, 0x0110, "Epson", "785EPX Storage", - US_SC_SCSI, US_PR_BULK, NULL, US_FL_SINGLE_LUN), + USB_SC_SCSI, USB_PR_BULK, NULL, US_FL_SINGLE_LUN), /* Not sure who reported this originally but * Pavel Machek reported that the extra US_FL_SINGLE_LUN @@ -363,7 +363,7 @@ UNUSUAL_DEV( 0x04b8, 0x0602, 0x0110, 0x0110, UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x2210, "Fujifilm", "FinePix 1400Zoom", - US_SC_UFI, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY | US_FL_SINGLE_LUN), + USB_SC_UFI, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY | US_FL_SINGLE_LUN), /* Reported by Ondrej Zary * The device reports one sector more and breaks when that sector is accessed @@ -371,7 +371,7 @@ UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x2210, UNUSUAL_DEV( 0x04ce, 0x0002, 0x026c, 0x026c, "ScanLogic", "SL11R-IDE", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), /* Reported by Kriston Fincher @@ -382,27 +382,27 @@ UNUSUAL_DEV( 0x04ce, 0x0002, 0x026c, 0x026c, UNUSUAL_DEV( 0x04da, 0x0901, 0x0100, 0x0200, "Panasonic", "LS-120 Camera", - US_SC_UFI, US_PR_DEVICE, NULL, 0), + USB_SC_UFI, USB_PR_DEVICE, NULL, 0), /* From Yukihiro Nakai, via zaitcev@yahoo.com. * This is needed for CB instead of CBI */ UNUSUAL_DEV( 0x04da, 0x0d05, 0x0000, 0x0000, "Sharp CE-CW05", "CD-R/RW Drive", - US_SC_8070, US_PR_CB, NULL, 0), + USB_SC_8070, USB_PR_CB, NULL, 0), /* Reported by Adriaan Penning */ UNUSUAL_DEV( 0x04da, 0x2372, 0x0000, 0x9999, "Panasonic", "DMC-LCx Camera", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ), /* Reported by Simeon Simeonov */ UNUSUAL_DEV( 0x04da, 0x2373, 0x0000, 0x9999, "LEICA", "D-LUX Camera", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ), /* Most of the following entries were developed with the help of @@ -411,19 +411,19 @@ UNUSUAL_DEV( 0x04da, 0x2373, 0x0000, 0x9999, UNUSUAL_DEV( 0x04e6, 0x0001, 0x0200, 0x0200, "Matshita", "LS-120", - US_SC_8020, US_PR_CB, NULL, 0), + USB_SC_8020, USB_PR_CB, NULL, 0), UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100, "Shuttle", "eUSCSI Bridge", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), #ifdef NO_SDDR09 UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, "SCM Microsystems", "eUSB CompactFlash Adapter", - US_SC_SCSI, US_PR_CB, NULL, + USB_SC_SCSI, USB_PR_CB, NULL, US_FL_SINGLE_LUN), #endif @@ -431,54 +431,54 @@ UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, UNUSUAL_DEV( 0x04e6, 0x0006, 0x0100, 0x0100, "SCM Microsystems Inc.", "eUSB MMC Adapter", - US_SC_SCSI, US_PR_CB, NULL, + USB_SC_SCSI, USB_PR_CB, NULL, US_FL_SINGLE_LUN), /* Reported by Daniel Nouri */ UNUSUAL_DEV( 0x04e6, 0x0006, 0x0205, 0x0205, "Shuttle", "eUSB MMC Adapter", - US_SC_SCSI, US_PR_DEVICE, NULL, + USB_SC_SCSI, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN), UNUSUAL_DEV( 0x04e6, 0x0007, 0x0100, 0x0200, "Sony", "Hifd", - US_SC_SCSI, US_PR_CB, NULL, + USB_SC_SCSI, USB_PR_CB, NULL, US_FL_SINGLE_LUN), UNUSUAL_DEV( 0x04e6, 0x0009, 0x0200, 0x0200, "Shuttle", "eUSB ATA/ATAPI Adapter", - US_SC_8020, US_PR_CB, NULL, 0), + USB_SC_8020, USB_PR_CB, NULL, 0), UNUSUAL_DEV( 0x04e6, 0x000a, 0x0200, 0x0200, "Shuttle", "eUSB CompactFlash Adapter", - US_SC_8020, US_PR_CB, NULL, 0), + USB_SC_8020, USB_PR_CB, NULL, 0), UNUSUAL_DEV( 0x04e6, 0x000B, 0x0100, 0x0100, "Shuttle", "eUSCSI Bridge", - US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, + USB_SC_SCSI, USB_PR_BULK, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), UNUSUAL_DEV( 0x04e6, 0x000C, 0x0100, 0x0100, "Shuttle", "eUSCSI Bridge", - US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, + USB_SC_SCSI, USB_PR_BULK, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200, "Shuttle", "CD-RW Device", - US_SC_8020, US_PR_CB, NULL, 0), + USB_SC_8020, USB_PR_CB, NULL, 0), /* Reported by Dmitry Khlystov */ UNUSUAL_DEV( 0x04e8, 0x507c, 0x0220, 0x0220, "Samsung", "YP-U3", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64), /* Entry and supporting patch by Theodore Kilgore . @@ -488,14 +488,14 @@ UNUSUAL_DEV( 0x04e8, 0x507c, 0x0220, 0x0220, UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x0100, "Kobian Mercury", "Binocam DCB-132", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BULK32), /* Reported by Bob Sass -- only rev 1.33 tested */ UNUSUAL_DEV( 0x050d, 0x0115, 0x0133, 0x0133, "Belkin", "USB SCSI Adaptor", - US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, + USB_SC_SCSI, USB_PR_BULK, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), /* Iomega Clik! Drive @@ -505,14 +505,14 @@ UNUSUAL_DEV( 0x050d, 0x0115, 0x0133, 0x0133, UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100, "Iomega", "USB Clik! 40", - US_SC_8070, US_PR_DEVICE, NULL, + USB_SC_8070, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), /* Added by Alan Stern */ COMPLIANT_DEV(0x0525, 0xa4a5, 0x0000, 0x9999, "Linux", "File-backed Storage Gadget", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_CAPACITY_OK ), /* Yakumo Mega Image 37 @@ -520,7 +520,7 @@ COMPLIANT_DEV(0x0525, 0xa4a5, 0x0000, 0x9999, UNUSUAL_DEV( 0x052b, 0x1801, 0x0100, 0x0100, "Tekom Technologies, Inc", "300_CAMERA", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Another Yakumo camera. @@ -528,14 +528,14 @@ UNUSUAL_DEV( 0x052b, 0x1801, 0x0100, 0x0100, UNUSUAL_DEV( 0x052b, 0x1804, 0x0100, 0x0100, "Tekom Technologies, Inc", "300_CAMERA", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Iacopo Spalletti */ UNUSUAL_DEV( 0x052b, 0x1807, 0x0100, 0x0100, "Tekom Technologies, Inc", "300_CAMERA", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Yakumo Mega Image 47 @@ -543,7 +543,7 @@ UNUSUAL_DEV( 0x052b, 0x1807, 0x0100, 0x0100, UNUSUAL_DEV( 0x052b, 0x1905, 0x0100, 0x0100, "Tekom Technologies, Inc", "400_CAMERA", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Paul Ortyl @@ -551,13 +551,13 @@ UNUSUAL_DEV( 0x052b, 0x1905, 0x0100, 0x0100, UNUSUAL_DEV( 0x052b, 0x1911, 0x0100, 0x0100, "Tekom Technologies, Inc", "400_CAMERA", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, "Sony", "DSC-S30/S70/S75/505V/F505/F707/F717/P8", - US_SC_SCSI, US_PR_DEVICE, NULL, + USB_SC_SCSI, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ), /* Submitted by Lars Jacob @@ -565,7 +565,7 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0610, "Sony", "DSC-T1/T5/H5", - US_SC_8070, US_PR_DEVICE, NULL, + USB_SC_8070, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), @@ -573,88 +573,88 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0610, UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100, "Sony", "Memorystick NW-MS7", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), /* Submitted by Olaf Hering, SuSE Bugzilla #49049 */ UNUSUAL_DEV( 0x054c, 0x002c, 0x0501, 0x2000, "Sony", "USB Floppy Drive", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100, "Sony", "Memorystick MSAC-US1", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), /* Submitted by Klaus Mueller */ UNUSUAL_DEV( 0x054c, 0x002e, 0x0106, 0x0310, "Sony", "Handycam", - US_SC_SCSI, US_PR_DEVICE, NULL, + USB_SC_SCSI, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), /* Submitted by Rajesh Kumble Nayak */ UNUSUAL_DEV( 0x054c, 0x002e, 0x0500, 0x0500, "Sony", "Handycam HC-85", - US_SC_UFI, US_PR_DEVICE, NULL, + USB_SC_UFI, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), UNUSUAL_DEV( 0x054c, 0x0032, 0x0000, 0x9999, "Sony", "Memorystick MSC-U01N", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), /* Submitted by Michal Mlotek */ UNUSUAL_DEV( 0x054c, 0x0058, 0x0000, 0x9999, "Sony", "PEG N760c Memorystick", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), UNUSUAL_DEV( 0x054c, 0x0069, 0x0000, 0x9999, "Sony", "Memorystick MSC-U03", - US_SC_UFI, US_PR_CB, NULL, + USB_SC_UFI, USB_PR_CB, NULL, US_FL_SINGLE_LUN ), /* Submitted by Nathan Babb */ UNUSUAL_DEV( 0x054c, 0x006d, 0x0000, 0x9999, "Sony", "PEG Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), /* Submitted by Frank Engel */ UNUSUAL_DEV( 0x054c, 0x0099, 0x0000, 0x9999, "Sony", "PEG Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), /* Submitted by Mike Alborn */ UNUSUAL_DEV( 0x054c, 0x016a, 0x0000, 0x9999, "Sony", "PEG Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), /* floppy reports multiple luns */ UNUSUAL_DEV( 0x055d, 0x2020, 0x0000, 0x0210, "SAMSUNG", "SFD-321U [FW 0C]", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), /* We keep this entry to force the transport; firmware 3.00 and later is ok. */ UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299, "Y-E Data", "Flashbuster-U", - US_SC_DEVICE, US_PR_CB, NULL, + USB_SC_DEVICE, USB_PR_CB, NULL, US_FL_SINGLE_LUN), /* Reported by Johann Cardon @@ -664,20 +664,20 @@ UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299, UNUSUAL_DEV( 0x057b, 0x0022, 0x0000, 0x9999, "Y-E Data", "Silicon Media R/W", - US_SC_DEVICE, US_PR_DEVICE, NULL, 0), + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0), /* Reported by RTE */ UNUSUAL_DEV( 0x058f, 0x6387, 0x0141, 0x0141, "JetFlash", "TS1GJF2A/120", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64 ), /* Fabrizio Fellini */ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, "Fujifilm", "Digital Camera EX-20 DSC", - US_SC_8070, US_PR_DEVICE, NULL, 0 ), + USB_SC_8070, USB_PR_DEVICE, NULL, 0 ), /* Reported by Andre Welter * This antique device predates the release of the Bulk-only Transport @@ -688,14 +688,14 @@ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, UNUSUAL_DEV( 0x059b, 0x0001, 0x0100, 0x0100, "Iomega", "ZIP 100", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), /* Reported by */ UNUSUAL_DEV( 0x059f, 0x0643, 0x0000, 0x0000, "LaCie", "DVD+-RW", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_GO_SLOW ), /* Submitted by Joel Bourquard @@ -705,7 +705,7 @@ UNUSUAL_DEV( 0x059f, 0x0643, 0x0000, 0x0000, UNUSUAL_DEV( 0x05ab, 0x0060, 0x1104, 0x1110, "In-System", "PyroGate External CD-ROM Enclosure (FCD-523)", - US_SC_SCSI, US_PR_BULK, NULL, + USB_SC_SCSI, USB_PR_BULK, NULL, US_FL_NEED_OVERRIDE ), /* Submitted by Sven Anderson @@ -717,26 +717,26 @@ UNUSUAL_DEV( 0x05ab, 0x0060, 0x1104, 0x1110, UNUSUAL_DEV( 0x05ac, 0x1202, 0x0000, 0x9999, "Apple", "iPod", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), /* Reported by Avi Kivity */ UNUSUAL_DEV( 0x05ac, 0x1203, 0x0000, 0x9999, "Apple", "iPod", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), UNUSUAL_DEV( 0x05ac, 0x1204, 0x0000, 0x9999, "Apple", "iPod", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ), UNUSUAL_DEV( 0x05ac, 0x1205, 0x0000, 0x9999, "Apple", "iPod", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), /* @@ -746,7 +746,7 @@ UNUSUAL_DEV( 0x05ac, 0x1205, 0x0000, 0x9999, UNUSUAL_DEV( 0x05ac, 0x120a, 0x0000, 0x9999, "Apple", "iPod", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), /* Reported by Dan Williams @@ -758,14 +758,14 @@ UNUSUAL_DEV( 0x05ac, 0x120a, 0x0000, 0x9999, UNUSUAL_DEV( 0x05c6, 0x1000, 0x0000, 0x9999, "Option N.V.", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, option_ms_init, + USB_SC_DEVICE, USB_PR_DEVICE, option_ms_init, 0), /* Reported by Blake Matheny */ UNUSUAL_DEV( 0x05dc, 0xb002, 0x0000, 0x0113, "Lexar", "USB CF Reader", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), /* The following two entries are for a Genesys USB to IDE @@ -782,20 +782,20 @@ UNUSUAL_DEV( 0x05dc, 0xb002, 0x0000, 0x0113, UNUSUAL_DEV( 0x05e3, 0x0701, 0x0000, 0xffff, "Genesys Logic", "USB to IDE Optical", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ), UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0xffff, "Genesys Logic", "USB to IDE Disk", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ), /* Reported by Ben Efros */ UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x9451, "Genesys Logic", "USB to SATA", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SANE_SENSE ), /* Reported by Hanno Boeck @@ -803,33 +803,33 @@ UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x9451, UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999, "Vivitar", "Vivicam 35Xx", - US_SC_SCSI, US_PR_BULK, NULL, + USB_SC_SCSI, USB_PR_BULK, NULL, US_FL_FIX_INQUIRY ), UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100, "TEAC", "Floppy Drive", - US_SC_UFI, US_PR_CB, NULL, 0 ), + USB_SC_UFI, USB_PR_CB, NULL, 0 ), /* Reported by Darsen Lu */ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001, "SigmaTel", "USBMSC Audio Player", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), /* Reported by Daniel Kukula */ UNUSUAL_DEV( 0x067b, 0x1063, 0x0100, 0x0100, "Prolific Technology, Inc.", "Prolific Storage Gadget", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BAD_SENSE ), /* Reported by Rogerio Brito */ UNUSUAL_DEV( 0x067b, 0x2317, 0x0001, 0x001, "Prolific Technology, Inc.", "Mass Storage Device", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), /* Reported by Richard -=[]=- */ @@ -838,45 +838,45 @@ UNUSUAL_DEV( 0x067b, 0x2317, 0x0001, 0x001, UNUSUAL_DEV( 0x067b, 0x2507, 0x0001, 0x0100, "Prolific Technology Inc.", "Mass Storage Device", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_GO_SLOW ), /* Reported by Alex Butcher */ UNUSUAL_DEV( 0x067b, 0x3507, 0x0001, 0x0101, "Prolific Technology Inc.", "ATAPI-6 Bridge Controller", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_GO_SLOW ), /* Submitted by Benny Sjostrand */ UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001, "Minolta", "Dimage F300", - US_SC_SCSI, US_PR_BULK, NULL, 0 ), + USB_SC_SCSI, USB_PR_BULK, NULL, 0 ), /* Reported by Miguel A. Fosas */ UNUSUAL_DEV( 0x0686, 0x4017, 0x0001, 0x0001, "Minolta", "DIMAGE E223", - US_SC_SCSI, US_PR_DEVICE, NULL, 0 ), + USB_SC_SCSI, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0693, 0x0005, 0x0100, 0x0100, "Hagiwara", "Flashgate", - US_SC_SCSI, US_PR_BULK, NULL, 0 ), + USB_SC_SCSI, USB_PR_BULK, NULL, 0 ), /* Reported by David Hamilton */ UNUSUAL_DEV( 0x069b, 0x3004, 0x0001, 0x0001, "Thomson Multimedia Inc.", "RCA RD1080 MP3 Player", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), /* Reported by Adrian Pilchowiec */ UNUSUAL_DEV( 0x071b, 0x3203, 0x0000, 0x0000, "RockChip", "MP3", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64), /* Reported by Jean-Baptiste Onofre @@ -886,7 +886,7 @@ UNUSUAL_DEV( 0x071b, 0x3203, 0x0000, 0x0000, UNUSUAL_DEV( 0x071b, 0x32bb, 0x0000, 0x0000, "RockChip", "MTP", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64), /* Reported by Massimiliano Ghilardi @@ -902,59 +902,59 @@ UNUSUAL_DEV( 0x071b, 0x32bb, 0x0000, 0x0000, UNUSUAL_DEV( 0x071b, 0x3203, 0x0100, 0x0100, "RockChip", "ROCK MP3", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64), /* Reported by Olivier Blondeau */ UNUSUAL_DEV( 0x0727, 0x0306, 0x0100, 0x0100, "ATMEL", "SND1 Storage", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE), /* Submitted by Roman Hodek */ UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200, "Sandisk", "ImageMate SDDR-05a", - US_SC_SCSI, US_PR_CB, NULL, + USB_SC_SCSI, USB_PR_CB, NULL, US_FL_SINGLE_LUN ), UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, "SanDisk Corporation", "ImageMate CompactFlash USB", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, "Sandisk", "ImageMate SDDR-12", - US_SC_SCSI, US_PR_CB, NULL, + USB_SC_SCSI, USB_PR_CB, NULL, US_FL_SINGLE_LUN ), /* Reported by Eero Volotinen */ UNUSUAL_DEV( 0x07ab, 0xfccd, 0x0000, 0x9999, "Freecom Technologies", "FHD-Classic", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0133, "Microtech", "USB-SCSI-DB25", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x0100, "Microtech", "USB-SCSI-HD50", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), #ifdef NO_SDDR09 UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, "Microtech", "CameraMate", - US_SC_SCSI, US_PR_CB, NULL, + USB_SC_SCSI, USB_PR_CB, NULL, US_FL_SINGLE_LUN ), #endif @@ -967,7 +967,7 @@ UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0xffff, "Datafab", "KECF-USB", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY ), /* Reported by Rauch Wolke @@ -976,7 +976,7 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0xffff, UNUSUAL_DEV( 0x07c4, 0xa4a5, 0x0000, 0xffff, "Simple Tech/Datafab", "CF+SM Reader", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_MAX_SECTORS_64 ), /* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant @@ -986,42 +986,42 @@ UNUSUAL_DEV( 0x07c4, 0xa4a5, 0x0000, 0xffff, * - They don't like the INQUIRY command. So we must handle this command * of the SCSI layer ourselves. * - Some cameras with idProduct=0x1001 and bcdDevice=0x1000 have - * bInterfaceProtocol=0x00 (US_PR_CBI) while others have 0x01 (US_PR_CB). - * So don't remove the US_PR_CB override! - * - Cameras with bcdDevice=0x9009 require the US_SC_8070 override. + * bInterfaceProtocol=0x00 (USB_PR_CBI) while others have 0x01 (USB_PR_CB). + * So don't remove the USB_PR_CB override! + * - Cameras with bcdDevice=0x9009 require the USB_SC_8070 override. */ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999, "Casio", "QV DigitalCamera", - US_SC_8070, US_PR_CB, NULL, + USB_SC_8070, USB_PR_CB, NULL, US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ), /* Submitted by Hartmut Wahl */ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001, "Samsung", "Digimax 410", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), /* Reported by Luciano Rocha */ UNUSUAL_DEV( 0x0840, 0x0082, 0x0001, 0x0001, "Argosy", "Storage", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), /* Reported and patched by Nguyen Anh Quynh */ UNUSUAL_DEV( 0x0840, 0x0084, 0x0001, 0x0001, "Argosy", "Storage", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), /* Reported by Martijn Hijdra */ UNUSUAL_DEV( 0x0840, 0x0085, 0x0001, 0x0001, "Argosy", "Storage", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), /* Entry and supporting patch by Theodore Kilgore . @@ -1033,7 +1033,7 @@ UNUSUAL_DEV( 0x0840, 0x0085, 0x0001, 0x0001, UNUSUAL_DEV( 0x084d, 0x0011, 0x0110, 0x0110, "Grandtech", "DC2MEGA", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BULK32), /* Andrew Lunn @@ -1044,14 +1044,14 @@ UNUSUAL_DEV( 0x084d, 0x0011, 0x0110, 0x0110, UNUSUAL_DEV( 0x0851, 0x1543, 0x0200, 0x0200, "PanDigital", "Photo Frame", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE), /* Submitted by Jan De Luyck */ UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000, "CITIZEN", "X1DE-USB", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN), /* Submitted by Dylan Taft @@ -1060,7 +1060,7 @@ UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000, UNUSUAL_DEV( 0x08ca, 0x3103, 0x0100, 0x0100, "AIPTEK", "Aiptek USB Keychain MP3 Player", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE), /* Entry needed for flags. Moreover, all devices with this ID use @@ -1071,7 +1071,7 @@ UNUSUAL_DEV( 0x08ca, 0x3103, 0x0100, 0x0100, UNUSUAL_DEV( 0x090a, 0x1001, 0x0100, 0x0100, "Trumpion", "t33520 USB Flash Card Controller", - US_SC_DEVICE, US_PR_BULK, NULL, + USB_SC_DEVICE, USB_PR_BULK, NULL, US_FL_NEED_OVERRIDE ), /* Reported by Filippo Bardelli @@ -1080,21 +1080,21 @@ UNUSUAL_DEV( 0x090a, 0x1001, 0x0100, 0x0100, UNUSUAL_DEV( 0x090a, 0x1050, 0x0100, 0x0100, "Trumpion Microelectronics, Inc.", "33520 USB Digital Voice Recorder", - US_SC_UFI, US_PR_DEVICE, NULL, + USB_SC_UFI, USB_PR_DEVICE, NULL, 0), /* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */ UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999, "Trumpion", "MP3 player", - US_SC_RBC, US_PR_BULK, NULL, + USB_SC_RBC, USB_PR_BULK, NULL, 0 ), /* aeb */ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, "Feiya", "5-in-1 Card Reader", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), /* This Pentax still camera is not conformant @@ -1107,7 +1107,7 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000, "Pentax", "Optio 2/3/400", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), /* These are virtual windows driver CDs, which the zd1211rw driver @@ -1115,13 +1115,13 @@ UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000, UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101, "ZyXEL", "G-220F USB-WLAN Install", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_DEVICE ), UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101, "SiteCom", "WL-117 USB-WLAN Install", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_DEVICE ), /* Reported by Dan Williams @@ -1133,7 +1133,7 @@ UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101, UNUSUAL_DEV( 0x0af0, 0x6971, 0x0000, 0x9999, "Option N.V.", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, option_ms_init, + USB_SC_DEVICE, USB_PR_DEVICE, option_ms_init, 0), /* Reported by F. Aben @@ -1143,7 +1143,7 @@ UNUSUAL_DEV( 0x0af0, 0x6971, 0x0000, 0x9999, UNUSUAL_DEV( 0x0af0, 0x7401, 0x0000, 0x0000, "Option", "GI 0401 SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), /* Reported by Jan Dumon @@ -1153,104 +1153,104 @@ UNUSUAL_DEV( 0x0af0, 0x7401, 0x0000, 0x0000, UNUSUAL_DEV( 0x0af0, 0x7501, 0x0000, 0x0000, "Option", "GI 0431 SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0af0, 0x7701, 0x0000, 0x0000, "Option", "GI 0451 SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0af0, 0x7706, 0x0000, 0x0000, "Option", "GI 0451 SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0af0, 0x7901, 0x0000, 0x0000, "Option", "GI 0452 SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0af0, 0x7A01, 0x0000, 0x0000, "Option", "GI 0461 SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0af0, 0x7A05, 0x0000, 0x0000, "Option", "GI 0461 SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0af0, 0x8300, 0x0000, 0x0000, "Option", "GI 033x SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0af0, 0x8302, 0x0000, 0x0000, "Option", "GI 033x SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0af0, 0x8304, 0x0000, 0x0000, "Option", "GI 033x SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0af0, 0xc100, 0x0000, 0x0000, "Option", "GI 070x SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0af0, 0xd057, 0x0000, 0x0000, "Option", "GI 1505 SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0af0, 0xd058, 0x0000, 0x0000, "Option", "GI 1509 SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0af0, 0xd157, 0x0000, 0x0000, "Option", "GI 1515 SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0af0, 0xd257, 0x0000, 0x0000, "Option", "GI 1215 SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), UNUSUAL_DEV( 0x0af0, 0xd357, 0x0000, 0x0000, "Option", "GI 1505 SD-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0 ), /* Reported by Ben Efros */ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, "Seagate", "FreeAgent Pro", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SANE_SENSE ), UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, "Maxtor", "USB to SATA", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SANE_SENSE), /* @@ -1260,14 +1260,14 @@ UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, UNUSUAL_DEV( 0x0c45, 0x1060, 0x0100, 0x0100, "Unknown", "Unknown", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), /* Submitted by Joris Struyve */ UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff, "Medion", "MD 7425", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), /* @@ -1278,13 +1278,13 @@ UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff, UNUSUAL_DEV( 0x0d96, 0x5200, 0x0001, 0x0200, "Jenoptik", "JD 5200 z3", - US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), /* Reported by Jason Johnston */ UNUSUAL_DEV( 0x0dc4, 0x0073, 0x0000, 0x0000, "Macpower Technology Co.LTD.", "USB 2.0 3.5\" DEVICE", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), /* Reported by Lubomir Blaha @@ -1295,7 +1295,7 @@ UNUSUAL_DEV( 0x0dc4, 0x0073, 0x0000, 0x0000, UNUSUAL_DEV( 0x0dd8, 0x1060, 0x0000, 0xffff, "Netac", "USB-CF-Card", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), /* Reported by Edward Chapman (taken from linux-usb mailing list) @@ -1303,7 +1303,7 @@ UNUSUAL_DEV( 0x0dd8, 0x1060, 0x0000, 0xffff, UNUSUAL_DEV( 0x0dd8, 0xd202, 0x0000, 0x9999, "Netac", "USB Flash Disk", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), @@ -1312,28 +1312,28 @@ UNUSUAL_DEV( 0x0dd8, 0xd202, 0x0000, 0x9999, UNUSUAL_DEV( 0x0dda, 0x0001, 0x0012, 0x0012, "WINWARD", "Music Disk", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Ian McConnell */ UNUSUAL_DEV( 0x0dda, 0x0301, 0x0012, 0x0012, "PNP_MP3", "PNP_MP3 PLAYER", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Jim McCloskey */ UNUSUAL_DEV( 0x0e21, 0x0520, 0x0100, 0x0100, "Cowon Systems", "iAUDIO M5", - US_SC_DEVICE, US_PR_BULK, NULL, + USB_SC_DEVICE, USB_PR_BULK, NULL, US_FL_NEED_OVERRIDE ), /* Submitted by Antoine Mairesse */ UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300, "USB", "Solid state disk", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), /* Submitted by Daniel Drake @@ -1341,14 +1341,14 @@ UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300, UNUSUAL_DEV( 0x0ea0, 0x2168, 0x0110, 0x0110, "Ours Technology", "Flash Disk", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Rastislav Stanik */ UNUSUAL_DEV( 0x0ea0, 0x6828, 0x0110, 0x0110, "USB", "Flash Disk", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Benjamin Schiller @@ -1356,7 +1356,7 @@ UNUSUAL_DEV( 0x0ea0, 0x6828, 0x0110, 0x0110, UNUSUAL_DEV( 0x0ed1, 0x7636, 0x0103, 0x0103, "Typhoon", "My DJ 1820", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64), /* Patch by Leonid Petrov mail at lpetrov.net @@ -1367,7 +1367,7 @@ UNUSUAL_DEV( 0x0ed1, 0x7636, 0x0103, 0x0103, UNUSUAL_DEV( 0x0f19, 0x0103, 0x0100, 0x0100, "Oracom Co., Ltd", "ORC-200M", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* David Kuehling : @@ -1377,21 +1377,21 @@ UNUSUAL_DEV( 0x0f19, 0x0103, 0x0100, 0x0100, UNUSUAL_DEV( 0x0f19, 0x0105, 0x0100, 0x0100, "C-MEX", "A-VOX", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Michael Stattmann */ UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, "Sony Ericsson", "V800-Vodafone 802", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_WP_DETECT ), /* Reported by The Solutor */ UNUSUAL_DEV( 0x0fce, 0xd0e1, 0x0000, 0x0000, "Sony Ericsson", "MD400", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_DEVICE), /* Reported by Jan Mate @@ -1399,21 +1399,21 @@ UNUSUAL_DEV( 0x0fce, 0xd0e1, 0x0000, 0x0000, UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, "Sony Ericsson", "P990i", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), /* Reported by Emmanuel Vasilakis */ UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, "Sony Ericsson", "M600i", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), /* Reported by Ricardo Barberis */ UNUSUAL_DEV( 0x0fce, 0xe092, 0x0000, 0x0000, "Sony Ericsson", "P1i", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Kevin Cernekee @@ -1425,13 +1425,13 @@ UNUSUAL_DEV( 0x0fce, 0xe092, 0x0000, 0x0000, UNUSUAL_DEV( 0x1019, 0x0c55, 0x0000, 0x0110, "Desknote", "UCR-61S2B", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_ucr61s2b_init, 0 ), UNUSUAL_DEV( 0x1058, 0x0704, 0x0000, 0x9999, "Western Digital", "External HDD", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SANE_SENSE), /* Reported by Fabio Venturi @@ -1440,7 +1440,7 @@ UNUSUAL_DEV( 0x1058, 0x0704, 0x0000, 0x9999, UNUSUAL_DEV( 0x10d6, 0x2200, 0x0100, 0x0100, "Actions Semiconductor", "Mtp device", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0), /* Reported by Pascal Terjan @@ -1449,7 +1449,7 @@ UNUSUAL_DEV( 0x10d6, 0x2200, 0x0100, 0x0100, UNUSUAL_DEV( 0x1186, 0x3e04, 0x0000, 0x0000, "D-Link", "USB Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, option_ms_init, US_FL_IGNORE_DEVICE), + USB_SC_DEVICE, USB_PR_DEVICE, option_ms_init, US_FL_IGNORE_DEVICE), /* Reported by Kevin Lloyd * Entry is needed for the initializer function override, @@ -1459,7 +1459,7 @@ UNUSUAL_DEV( 0x1186, 0x3e04, 0x0000, 0x0000, UNUSUAL_DEV( 0x1199, 0x0fff, 0x0000, 0x9999, "Sierra Wireless", "USB MMC Storage", - US_SC_DEVICE, US_PR_DEVICE, sierra_ms_init, + USB_SC_DEVICE, USB_PR_DEVICE, sierra_ms_init, 0), /* Reported by Jaco Kroon @@ -1469,7 +1469,7 @@ UNUSUAL_DEV( 0x1199, 0x0fff, 0x0000, 0x9999, UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100, "Digitech HMG", "DigiTech Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by fangxiaozhi @@ -1478,353 +1478,353 @@ UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100, UNUSUAL_DEV( 0x12d1, 0x1001, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1004, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1401, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1402, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1403, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1404, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1405, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1406, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1407, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1408, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1409, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x140A, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x140B, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x140C, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x140D, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x140E, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x140F, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1410, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1411, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1412, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1413, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1414, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1415, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1416, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1417, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1418, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1419, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x141A, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x141B, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x141C, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x141D, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x141E, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x141F, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1420, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1421, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1422, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1423, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1424, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1425, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1426, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1427, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1428, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1429, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x142A, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x142B, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x142C, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x142D, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x142E, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x142F, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1430, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1431, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1432, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1433, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1434, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1435, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1436, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1437, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1438, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x1439, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x143A, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x143B, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x143C, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x143D, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x143E, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), UNUSUAL_DEV( 0x12d1, 0x143F, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), /* Reported by Vilius Bilinkevicius */ UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110, "SWISSBIT", "Black Silver", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Francesco Foresti */ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201, "Super Top", "IDE DEVICE", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Alexandre Oliva @@ -1833,7 +1833,7 @@ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201, UNUSUAL_DEV( 0x152d, 0x2329, 0x0100, 0x0100, "JMicron", "USB to ATA/ATAPI Bridge", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ), /* Reported by Robert Schedel @@ -1841,7 +1841,7 @@ UNUSUAL_DEV( 0x152d, 0x2329, 0x0100, 0x0100, UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, "Teac", "HD-35PUK-B", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Hans de Goede @@ -1851,18 +1851,18 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, UNUSUAL_DEV( 0x1908, 0x1315, 0x0000, 0x0000, "BUILDWIN", "Photo Frame", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BAD_SENSE ), UNUSUAL_DEV( 0x1908, 0x1320, 0x0000, 0x0000, "BUILDWIN", "Photo Frame", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BAD_SENSE ), UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001, "ST", "2A", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), /* patch submitted by Davide Perini @@ -1871,7 +1871,7 @@ UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001, UNUSUAL_DEV( 0x22b8, 0x3010, 0x0001, 0x0001, "Motorola", "RAZR V3x", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), /* @@ -1882,14 +1882,14 @@ UNUSUAL_DEV( 0x22b8, 0x3010, 0x0001, 0x0001, UNUSUAL_DEV( 0x22b8, 0x6426, 0x0101, 0x0101, "Motorola", "MSnc.", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY | US_FL_BULK_IGNORE_TAG), /* Reported by Radovan Garabik */ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, "MPIO", "HS200", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_GO_SLOW ), /* Reported by Frederic Marchal @@ -1898,21 +1898,21 @@ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, UNUSUAL_DEV( 0x3340, 0xffff, 0x0000, 0x0000, "Mitac", "Mio DigiWalker USB Sync", - US_SC_DEVICE,US_PR_DEVICE,NULL, + USB_SC_DEVICE,USB_PR_DEVICE,NULL, US_FL_MAX_SECTORS_64 ), /* Reported by Andrey Rahmatullin */ UNUSUAL_DEV( 0x4102, 0x1020, 0x0100, 0x0100, "iRiver", "MP3 T10", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), /* Reported by Sergey Pinaev */ UNUSUAL_DEV( 0x4102, 0x1059, 0x0000, 0x0000, "iRiver", "P7K", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64 ), /* @@ -1922,41 +1922,41 @@ UNUSUAL_DEV( 0x4102, 0x1059, 0x0000, 0x0000, UNUSUAL_DEV( 0x4146, 0xba01, 0x0100, 0x0100, "Iomega", "Micro Mini 1GB", - US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), /* Reported by Andrew Simmons */ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001, "DataStor", "USB4500 FW1.04", - US_SC_DEVICE, US_PR_DEVICE, NULL, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_CAPACITY_HEURISTICS), /* Reported by Alessio Treglia */ UNUSUAL_DEV( 0xed10, 0x7636, 0x0001, 0x0001, "TGE", "Digital MP3 Audio Player", - US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), /* Control/Bulk transport for all SubClass values */ -USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_QIC, US_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_UFI, US_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_8070, US_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_SCSI, US_PR_CB, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_RBC, USB_PR_CB, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_8020, USB_PR_CB, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_QIC, USB_PR_CB, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_UFI, USB_PR_CB, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_8070, USB_PR_CB, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_SCSI, USB_PR_CB, USB_US_TYPE_STOR), /* Control/Bulk/Interrupt transport for all SubClass values */ -USUAL_DEV(US_SC_RBC, US_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_8020, US_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_QIC, US_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_UFI, US_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_8070, US_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_SCSI, US_PR_CBI, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_RBC, USB_PR_CBI, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_8020, USB_PR_CBI, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_QIC, USB_PR_CBI, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_UFI, USB_PR_CBI, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_8070, USB_PR_CBI, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_SCSI, USB_PR_CBI, USB_US_TYPE_STOR), /* Bulk-only transport for all SubClass values */ -USUAL_DEV(US_SC_RBC, US_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_8020, US_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_QIC, US_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_UFI, US_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_8070, US_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(US_SC_SCSI, US_PR_BULK, 0), +USUAL_DEV(USB_SC_RBC, USB_PR_BULK, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_8020, USB_PR_BULK, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_QIC, USB_PR_BULK, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_UFI, USB_PR_BULK, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_8070, USB_PR_BULK, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_SCSI, USB_PR_BULK, 0), diff --git a/drivers/usb/storage/unusual_freecom.h b/drivers/usb/storage/unusual_freecom.h index 375867942391..59a261155b98 100644 --- a/drivers/usb/storage/unusual_freecom.h +++ b/drivers/usb/storage/unusual_freecom.h @@ -21,6 +21,6 @@ UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999, "Freecom", "USB-IDE", - US_SC_QIC, US_PR_FREECOM, init_freecom, 0), + USB_SC_QIC, USB_PR_FREECOM, init_freecom, 0), #endif /* defined(CONFIG_USB_STORAGE_FREECOM) || ... */ diff --git a/drivers/usb/storage/unusual_isd200.h b/drivers/usb/storage/unusual_isd200.h index 0d99dde3382a..14cca0c48302 100644 --- a/drivers/usb/storage/unusual_isd200.h +++ b/drivers/usb/storage/unusual_isd200.h @@ -21,37 +21,37 @@ UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110, "Sony", "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, + USB_SC_ISD200, USB_PR_BULK, isd200_Initialization, 0), UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110, "In-System", "USB/IDE Bridge (ATA/ATAPI)", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, + USB_SC_ISD200, USB_PR_BULK, isd200_Initialization, 0), UNUSUAL_DEV( 0x05ab, 0x0301, 0x0100, 0x0110, "In-System", "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, + USB_SC_ISD200, USB_PR_BULK, isd200_Initialization, 0), UNUSUAL_DEV( 0x05ab, 0x0351, 0x0100, 0x0110, "In-System", "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, + USB_SC_ISD200, USB_PR_BULK, isd200_Initialization, 0), UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110, "In-System", "USB Storage Adapter V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, + USB_SC_ISD200, USB_PR_BULK, isd200_Initialization, 0), UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, "ATI", "USB Cable 205", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, + USB_SC_ISD200, USB_PR_BULK, isd200_Initialization, 0), #endif /* defined(CONFIG_USB_STORAGE_ISD200) || ... */ diff --git a/drivers/usb/storage/unusual_jumpshot.h b/drivers/usb/storage/unusual_jumpshot.h index 2e549b1c2c62..54be78b5d643 100644 --- a/drivers/usb/storage/unusual_jumpshot.h +++ b/drivers/usb/storage/unusual_jumpshot.h @@ -21,7 +21,7 @@ UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, "Lexar", "Jumpshot USB CF Reader", - US_SC_SCSI, US_PR_JUMPSHOT, NULL, + USB_SC_SCSI, USB_PR_JUMPSHOT, NULL, US_FL_NEED_OVERRIDE), #endif /* defined(CONFIG_USB_STORAGE_JUMPSHOT) || ... */ diff --git a/drivers/usb/storage/unusual_karma.h b/drivers/usb/storage/unusual_karma.h index 12ae3a03e802..6df03972a22c 100644 --- a/drivers/usb/storage/unusual_karma.h +++ b/drivers/usb/storage/unusual_karma.h @@ -21,6 +21,6 @@ UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, "Rio", "Rio Karma", - US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0), + USB_SC_SCSI, USB_PR_KARMA, rio_karma_init, 0), #endif /* defined(CONFIG_USB_STORAGE_KARMA) || ... */ diff --git a/drivers/usb/storage/unusual_onetouch.h b/drivers/usb/storage/unusual_onetouch.h index bd9306b637df..0abb819c7405 100644 --- a/drivers/usb/storage/unusual_onetouch.h +++ b/drivers/usb/storage/unusual_onetouch.h @@ -24,13 +24,13 @@ UNUSUAL_DEV( 0x0d49, 0x7000, 0x0000, 0x9999, "Maxtor", "OneTouch External Harddrive", - US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, + USB_SC_DEVICE, USB_PR_DEVICE, onetouch_connect_input, 0), UNUSUAL_DEV( 0x0d49, 0x7010, 0x0000, 0x9999, "Maxtor", "OneTouch External Harddrive", - US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, + USB_SC_DEVICE, USB_PR_DEVICE, onetouch_connect_input, 0), #endif /* defined(CONFIG_USB_STORAGE_ONETOUCH) || ... */ diff --git a/drivers/usb/storage/unusual_sddr09.h b/drivers/usb/storage/unusual_sddr09.h index 50cab511a4d7..59a7e37b6c11 100644 --- a/drivers/usb/storage/unusual_sddr09.h +++ b/drivers/usb/storage/unusual_sddr09.h @@ -21,36 +21,36 @@ UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, "Microtech", "CameraMate (DPCM_USB)", - US_SC_SCSI, US_PR_DPCM_USB, NULL, 0), + USB_SC_SCSI, USB_PR_DPCM_USB, NULL, 0), UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999, "Sandisk", "ImageMate SDDR09", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, + USB_SC_SCSI, USB_PR_EUSB_SDDR09, usb_stor_sddr09_init, 0), /* This entry is from Andries.Brouwer@cwi.nl */ UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, "SCM Microsystems", "eUSB SmartMedia / CompactFlash Adapter", - US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init, + USB_SC_SCSI, USB_PR_DPCM_USB, usb_stor_sddr09_dpcm_init, 0), UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, "Olympus", "Camedia MAUSB-2", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, + USB_SC_SCSI, USB_PR_EUSB_SDDR09, usb_stor_sddr09_init, 0), UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, "Sandisk", "ImageMate SDDR-09", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, + USB_SC_SCSI, USB_PR_EUSB_SDDR09, usb_stor_sddr09_init, 0), UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, "Microtech", "CameraMate (DPCM_USB)", - US_SC_SCSI, US_PR_DPCM_USB, NULL, 0), + USB_SC_SCSI, USB_PR_DPCM_USB, NULL, 0), #endif /* defined(CONFIG_USB_STORAGE_SDDR09) || ... */ diff --git a/drivers/usb/storage/unusual_sddr55.h b/drivers/usb/storage/unusual_sddr55.h index ae81ef7a1cfd..fcb7e12c598f 100644 --- a/drivers/usb/storage/unusual_sddr55.h +++ b/drivers/usb/storage/unusual_sddr55.h @@ -22,23 +22,23 @@ UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999, "Datafab", "MDSM-B reader", - US_SC_SCSI, US_PR_SDDR55, NULL, + USB_SC_SCSI, USB_PR_SDDR55, NULL, US_FL_FIX_INQUIRY), /* SM part - aeb */ UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, "Datafab Systems, Inc.", "USB to CF + SM Combo (LC1)", - US_SC_SCSI, US_PR_SDDR55, NULL, 0), + USB_SC_SCSI, USB_PR_SDDR55, NULL, 0), UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, "Acomdata", "SM", - US_SC_SCSI, US_PR_SDDR55, NULL, 0), + USB_SC_SCSI, USB_PR_SDDR55, NULL, 0), UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, "Sandisk", "ImageMate SDDR55", - US_SC_SCSI, US_PR_SDDR55, NULL, 0), + USB_SC_SCSI, USB_PR_SDDR55, NULL, 0), #endif /* defined(CONFIG_USB_STORAGE_SDDR55) || ... */ diff --git a/drivers/usb/storage/unusual_usbat.h b/drivers/usb/storage/unusual_usbat.h index 80e869f10180..38e79c4e6d6a 100644 --- a/drivers/usb/storage/unusual_usbat.h +++ b/drivers/usb/storage/unusual_usbat.h @@ -21,23 +21,23 @@ UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, "HP", "CD-Writer+ 8200e", - US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), + USB_SC_8070, USB_PR_USBAT, init_usbat_cd, 0), UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, "HP", "CD-Writer+ CD-4e", - US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), + USB_SC_8070, USB_PR_USBAT, init_usbat_cd, 0), UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, "Shuttle/SCM", "USBAT-02", - US_SC_SCSI, US_PR_USBAT, init_usbat_flash, + USB_SC_SCSI, USB_PR_USBAT, init_usbat_flash, US_FL_SINGLE_LUN), UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, "Sandisk", "ImageMate SDDR-05b", - US_SC_SCSI, US_PR_USBAT, init_usbat_flash, + USB_SC_SCSI, USB_PR_USBAT, init_usbat_flash, US_FL_SINGLE_LUN), #endif /* defined(CONFIG_USB_STORAGE_USBAT) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 90bb0175a152..4219c197cb08 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -512,10 +512,10 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id, /* Store the entries */ us->unusual_dev = unusual_dev; - us->subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ? + us->subclass = (unusual_dev->useProtocol == USB_SC_DEVICE) ? idesc->bInterfaceSubClass : unusual_dev->useProtocol; - us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ? + us->protocol = (unusual_dev->useTransport == USB_PR_DEVICE) ? idesc->bInterfaceProtocol : unusual_dev->useTransport; us->fflags = USB_US_ORIG_FLAGS(id->driver_info); @@ -552,10 +552,10 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id, struct usb_device_descriptor *ddesc = &dev->descriptor; int msg = -1; - if (unusual_dev->useProtocol != US_SC_DEVICE && + if (unusual_dev->useProtocol != USB_SC_DEVICE && us->subclass == idesc->bInterfaceSubClass) msg += 1; - if (unusual_dev->useTransport != US_PR_DEVICE && + if (unusual_dev->useTransport != USB_PR_DEVICE && us->protocol == idesc->bInterfaceProtocol) msg += 2; if (msg >= 0 && !(us->fflags & US_FL_NEED_OVERRIDE)) @@ -582,21 +582,21 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id, static void get_transport(struct us_data *us) { switch (us->protocol) { - case US_PR_CB: + case USB_PR_CB: us->transport_name = "Control/Bulk"; us->transport = usb_stor_CB_transport; us->transport_reset = usb_stor_CB_reset; us->max_lun = 7; break; - case US_PR_CBI: + case USB_PR_CBI: us->transport_name = "Control/Bulk/Interrupt"; us->transport = usb_stor_CB_transport; us->transport_reset = usb_stor_CB_reset; us->max_lun = 7; break; - case US_PR_BULK: + case USB_PR_BULK: us->transport_name = "Bulk"; us->transport = usb_stor_Bulk_transport; us->transport_reset = usb_stor_Bulk_reset; @@ -608,35 +608,35 @@ static void get_transport(struct us_data *us) static void get_protocol(struct us_data *us) { switch (us->subclass) { - case US_SC_RBC: + case USB_SC_RBC: us->protocol_name = "Reduced Block Commands (RBC)"; us->proto_handler = usb_stor_transparent_scsi_command; break; - case US_SC_8020: + case USB_SC_8020: us->protocol_name = "8020i"; us->proto_handler = usb_stor_pad12_command; us->max_lun = 0; break; - case US_SC_QIC: + case USB_SC_QIC: us->protocol_name = "QIC-157"; us->proto_handler = usb_stor_pad12_command; us->max_lun = 0; break; - case US_SC_8070: + case USB_SC_8070: us->protocol_name = "8070i"; us->proto_handler = usb_stor_pad12_command; us->max_lun = 0; break; - case US_SC_SCSI: + case USB_SC_SCSI: us->protocol_name = "Transparent SCSI"; us->proto_handler = usb_stor_transparent_scsi_command; break; - case US_SC_UFI: + case USB_SC_UFI: us->protocol_name = "Uniform Floppy Interface (UFI)"; us->proto_handler = usb_stor_ufi_command; break; @@ -679,7 +679,7 @@ static int get_pipes(struct us_data *us) } } - if (!ep_in || !ep_out || (us->protocol == US_PR_CBI && !ep_int)) { + if (!ep_in || !ep_out || (us->protocol == USB_PR_CBI && !ep_int)) { US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n"); return -EIO; } @@ -834,7 +834,7 @@ static int usb_stor_scan_thread(void * __us) if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) { /* For bulk-only devices, determine the max LUN value */ - if (us->protocol == US_PR_BULK && + if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) { mutex_lock(&us->dev_mutex); us->max_lun = usb_stor_Bulk_max_lun(us); diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index a4b947e470a5..f387c436042e 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -81,35 +81,36 @@ enum { US_DO_ALL_FLAGS }; /* Sub Classes */ -#define US_SC_RBC 0x01 /* Typically, flash devices */ -#define US_SC_8020 0x02 /* CD-ROM */ -#define US_SC_QIC 0x03 /* QIC-157 Tapes */ -#define US_SC_UFI 0x04 /* Floppy */ -#define US_SC_8070 0x05 /* Removable media */ -#define US_SC_SCSI 0x06 /* Transparent */ -#define US_SC_LOCKABLE 0x07 /* Password-protected */ +#define USB_SC_RBC 0x01 /* Typically, flash devices */ +#define USB_SC_8020 0x02 /* CD-ROM */ +#define USB_SC_QIC 0x03 /* QIC-157 Tapes */ +#define USB_SC_UFI 0x04 /* Floppy */ +#define USB_SC_8070 0x05 /* Removable media */ +#define USB_SC_SCSI 0x06 /* Transparent */ +#define USB_SC_LOCKABLE 0x07 /* Password-protected */ -#define US_SC_ISD200 0xf0 /* ISD200 ATA */ -#define US_SC_CYP_ATACB 0xf1 /* Cypress ATACB */ -#define US_SC_DEVICE 0xff /* Use device's value */ +#define USB_SC_ISD200 0xf0 /* ISD200 ATA */ +#define USB_SC_CYP_ATACB 0xf1 /* Cypress ATACB */ +#define USB_SC_DEVICE 0xff /* Use device's value */ -/* Protocols */ +/* Storage protocol codes */ -#define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */ -#define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */ -#define US_PR_BULK 0x50 /* bulk only */ +#define USB_PR_CBI 0x00 /* Control/Bulk/Interrupt */ +#define USB_PR_CB 0x01 /* Control/Bulk w/o interrupt */ +#define USB_PR_BULK 0x50 /* bulk only */ +#define USB_PR_UAS 0x62 /* USB Attached SCSI */ -#define US_PR_USBAT 0x80 /* SCM-ATAPI bridge */ -#define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */ -#define US_PR_SDDR55 0x82 /* SDDR-55 (made up) */ -#define US_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */ -#define US_PR_FREECOM 0xf1 /* Freecom */ -#define US_PR_DATAFAB 0xf2 /* Datafab chipsets */ -#define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */ -#define US_PR_ALAUDA 0xf4 /* Alauda chipsets */ -#define US_PR_KARMA 0xf5 /* Rio Karma */ +#define USB_PR_USBAT 0x80 /* SCM-ATAPI bridge */ +#define USB_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */ +#define USB_PR_SDDR55 0x82 /* SDDR-55 (made up) */ +#define USB_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */ +#define USB_PR_FREECOM 0xf1 /* Freecom */ +#define USB_PR_DATAFAB 0xf2 /* Datafab chipsets */ +#define USB_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */ +#define USB_PR_ALAUDA 0xf4 /* Alauda chipsets */ +#define USB_PR_KARMA 0xf5 /* Rio Karma */ -#define US_PR_DEVICE 0xff /* Use device's value */ +#define USB_PR_DEVICE 0xff /* Use device's value */ /* */ From ae6d22fe1812ce8d40add3eb74ede9cfd2eae44f Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 7 Oct 2010 13:05:22 +0200 Subject: [PATCH 058/141] USB: Move USB Storage definitions to their own header file The libusual header file is hard to use from code that isn't part of libusual. As the comment suggests, these definitions are moved to their own header file, paralleling other USB classes. Signed-off-by: Matthew Wilcox Cc: Alan Stern [mina86@mina86.com: updated to use USB_ prefix and added #include guard] Signed-off-by: Michal Nazarewicz Signed-off-by: Greg Kroah-Hartman index 0000000..d7fc910 --- include/linux/usb/storage.h | 48 +++++++++++++++++++++++++++++++++++++ include/linux/usb_usual.h | 38 +---------------------------- 2 files changed, 49 insertions(+), 37 deletions(-) create mode 100644 include/linux/usb/storage.h diff --git a/include/linux/usb/storage.h b/include/linux/usb/storage.h new file mode 100644 index 000000000000..d7fc910f1dc4 --- /dev/null +++ b/include/linux/usb/storage.h @@ -0,0 +1,48 @@ +#ifndef __LINUX_USB_STORAGE_H +#define __LINUX_USB_STORAGE_H + +/* + * linux/usb/storage.h + * + * Copyright Matthew Wilcox for Intel Corp, 2010 + * + * This file contains definitions taken from the + * USB Mass Storage Class Specification Overview + * + * Distributed under the terms of the GNU GPL, version two. + */ + +/* Storage subclass codes */ + +#define USB_SC_RBC 0x01 /* Typically, flash devices */ +#define USB_SC_8020 0x02 /* CD-ROM */ +#define USB_SC_QIC 0x03 /* QIC-157 Tapes */ +#define USB_SC_UFI 0x04 /* Floppy */ +#define USB_SC_8070 0x05 /* Removable media */ +#define USB_SC_SCSI 0x06 /* Transparent */ +#define USB_SC_LOCKABLE 0x07 /* Password-protected */ + +#define USB_SC_ISD200 0xf0 /* ISD200 ATA */ +#define USB_SC_CYP_ATACB 0xf1 /* Cypress ATACB */ +#define USB_SC_DEVICE 0xff /* Use device's value */ + +/* Storage protocol codes */ + +#define USB_PR_CBI 0x00 /* Control/Bulk/Interrupt */ +#define USB_PR_CB 0x01 /* Control/Bulk w/o interrupt */ +#define USB_PR_BULK 0x50 /* bulk only */ +#define USB_PR_UAS 0x62 /* USB Attached SCSI */ + +#define USB_PR_USBAT 0x80 /* SCM-ATAPI bridge */ +#define USB_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */ +#define USB_PR_SDDR55 0x82 /* SDDR-55 (made up) */ +#define USB_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */ +#define USB_PR_FREECOM 0xf1 /* Freecom */ +#define USB_PR_DATAFAB 0xf2 /* Datafab chipsets */ +#define USB_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */ +#define USB_PR_ALAUDA 0xf4 /* Alauda chipsets */ +#define USB_PR_KARMA 0xf5 /* Rio Karma */ + +#define USB_PR_DEVICE 0xff /* Use device's value */ + +#endif diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index f387c436042e..f091dc6e5a00 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -74,43 +74,7 @@ enum { US_DO_ALL_FLAGS }; #define USB_US_TYPE(flags) (((flags) >> 24) & 0xFF) #define USB_US_ORIG_FLAGS(flags) ((flags) & 0x00FFFFFF) -/* - * This is probably not the best place to keep these constants, conceptually. - * But it's the only header included into all places which need them. - */ - -/* Sub Classes */ - -#define USB_SC_RBC 0x01 /* Typically, flash devices */ -#define USB_SC_8020 0x02 /* CD-ROM */ -#define USB_SC_QIC 0x03 /* QIC-157 Tapes */ -#define USB_SC_UFI 0x04 /* Floppy */ -#define USB_SC_8070 0x05 /* Removable media */ -#define USB_SC_SCSI 0x06 /* Transparent */ -#define USB_SC_LOCKABLE 0x07 /* Password-protected */ - -#define USB_SC_ISD200 0xf0 /* ISD200 ATA */ -#define USB_SC_CYP_ATACB 0xf1 /* Cypress ATACB */ -#define USB_SC_DEVICE 0xff /* Use device's value */ - -/* Storage protocol codes */ - -#define USB_PR_CBI 0x00 /* Control/Bulk/Interrupt */ -#define USB_PR_CB 0x01 /* Control/Bulk w/o interrupt */ -#define USB_PR_BULK 0x50 /* bulk only */ -#define USB_PR_UAS 0x62 /* USB Attached SCSI */ - -#define USB_PR_USBAT 0x80 /* SCM-ATAPI bridge */ -#define USB_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */ -#define USB_PR_SDDR55 0x82 /* SDDR-55 (made up) */ -#define USB_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */ -#define USB_PR_FREECOM 0xf1 /* Freecom */ -#define USB_PR_DATAFAB 0xf2 /* Datafab chipsets */ -#define USB_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */ -#define USB_PR_ALAUDA 0xf4 /* Alauda chipsets */ -#define USB_PR_KARMA 0xf5 /* Rio Karma */ - -#define USB_PR_DEVICE 0xff /* Use device's value */ +#include /* */ From 115bb1ffa54c3934f3617bdd4e4dfc68b11e1e69 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 7 Oct 2010 13:05:23 +0200 Subject: [PATCH 059/141] USB: Add UAS driver USB Attached SCSI is a new protocol specified jointly by the SCSI T10 committee and the USB Implementors Forum. Signed-off-by: Matthew Wilcox Cc: Matthew Dharm [mina86@mina86.com: updated to use new USB_ prefix] Signed-off-by: Michal Nazarewicz Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 8 + drivers/usb/storage/Kconfig | 13 + drivers/usb/storage/Makefile | 1 + drivers/usb/storage/uas.c | 751 +++++++++++++++++++++++++++++++++++ 4 files changed, 773 insertions(+) create mode 100644 drivers/usb/storage/uas.c diff --git a/MAINTAINERS b/MAINTAINERS index f2a2b8e647c5..8dac57f53d87 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5934,6 +5934,14 @@ S: Maintained F: Documentation/usb/acm.txt F: drivers/usb/class/cdc-acm.* +USB ATTACHED SCSI +M: Matthew Wilcox +M: Sarah Sharp +L: linux-usb@vger.kernel.org +L: linux-scsi@vger.kernel.org +S: Supported +F: drivers/usb/storage/uas.c + USB BLOCK DRIVER (UB ub) M: Pete Zaitcev L: linux-usb@vger.kernel.org diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 8a372bac0e43..f2767cf2e229 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -172,6 +172,19 @@ config USB_STORAGE_CYPRESS_ATACB If this driver is compiled as a module, it will be named ums-cypress. +config USB_UAS + tristate "USB Attached SCSI" + depends on USB && SCSI + help + The USB Attached SCSI protocol is supported by some USB + storage devices. It permits higher performance by supporting + multiple outstanding commands. + + If you don't know whether you have a UAS device, it is safe to + say 'Y' or 'M' here and the kernel will use the right driver. + + If you compile this driver as a module, it will be named uas. + config USB_LIBUSUAL bool "The shared table of common (or usual) storage devices" depends on USB diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index ef7e5a8ceab5..0332aa5df24f 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -7,6 +7,7 @@ EXTRA_CFLAGS := -Idrivers/scsi +obj-$(CONFIG_USB_UAS) += uas.o obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c new file mode 100644 index 000000000000..2054b1e25a65 --- /dev/null +++ b/drivers/usb/storage/uas.c @@ -0,0 +1,751 @@ +/* + * USB Attached SCSI + * Note that this is not the same as the USB Mass Storage driver + * + * Copyright Matthew Wilcox for Intel Corp, 2010 + * Copyright Sarah Sharp for Intel Corp, 2010 + * + * Distributed under the terms of the GNU GPL, version two. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* Common header for all IUs */ +struct iu { + __u8 iu_id; + __u8 rsvd1; + __be16 tag; +}; + +enum { + IU_ID_COMMAND = 0x01, + IU_ID_STATUS = 0x03, + IU_ID_RESPONSE = 0x04, + IU_ID_TASK_MGMT = 0x05, + IU_ID_READ_READY = 0x06, + IU_ID_WRITE_READY = 0x07, +}; + +struct command_iu { + __u8 iu_id; + __u8 rsvd1; + __be16 tag; + __u8 prio_attr; + __u8 rsvd5; + __u8 len; + __u8 rsvd7; + struct scsi_lun lun; + __u8 cdb[16]; /* XXX: Overflow-checking tools may misunderstand */ +}; + +struct sense_iu { + __u8 iu_id; + __u8 rsvd1; + __be16 tag; + __be16 status_qual; + __u8 status; + __u8 service_response; + __u8 rsvd8[6]; + __be16 len; + __u8 sense[SCSI_SENSE_BUFFERSIZE]; +}; + +/* + * The r00-r01c specs define this version of the SENSE IU data structure. + * It's still in use by several different firmware releases. + */ +struct sense_iu_old { + __u8 iu_id; + __u8 rsvd1; + __be16 tag; + __be16 len; + __u8 status; + __u8 service_response; + __u8 sense[SCSI_SENSE_BUFFERSIZE]; +}; + +enum { + CMD_PIPE_ID = 1, + STATUS_PIPE_ID = 2, + DATA_IN_PIPE_ID = 3, + DATA_OUT_PIPE_ID = 4, + + UAS_SIMPLE_TAG = 0, + UAS_HEAD_TAG = 1, + UAS_ORDERED_TAG = 2, + UAS_ACA = 4, +}; + +struct uas_dev_info { + struct usb_interface *intf; + struct usb_device *udev; + int qdepth; + unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe; + unsigned use_streams:1; + unsigned uas_sense_old:1; +}; + +enum { + ALLOC_SENSE_URB = (1 << 0), + SUBMIT_SENSE_URB = (1 << 1), + ALLOC_DATA_IN_URB = (1 << 2), + SUBMIT_DATA_IN_URB = (1 << 3), + ALLOC_DATA_OUT_URB = (1 << 4), + SUBMIT_DATA_OUT_URB = (1 << 5), + ALLOC_CMD_URB = (1 << 6), + SUBMIT_CMD_URB = (1 << 7), +}; + +/* Overrides scsi_pointer */ +struct uas_cmd_info { + unsigned int state; + unsigned int stream; + struct urb *cmd_urb; + struct urb *sense_urb; + struct urb *data_in_urb; + struct urb *data_out_urb; + struct list_head list; +}; + +/* I hate forward declarations, but I actually have a loop */ +static int uas_submit_urbs(struct scsi_cmnd *cmnd, + struct uas_dev_info *devinfo, gfp_t gfp); + +static DEFINE_SPINLOCK(uas_work_lock); +static LIST_HEAD(uas_work_list); + +static void uas_do_work(struct work_struct *work) +{ + struct uas_cmd_info *cmdinfo; + struct list_head list; + + spin_lock_irq(&uas_work_lock); + list_replace_init(&uas_work_list, &list); + spin_unlock_irq(&uas_work_lock); + + list_for_each_entry(cmdinfo, &list, list) { + struct scsi_pointer *scp = (void *)cmdinfo; + struct scsi_cmnd *cmnd = container_of(scp, + struct scsi_cmnd, SCp); + uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_KERNEL); + } +} + +static DECLARE_WORK(uas_work, uas_do_work); + +static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) +{ + struct sense_iu *sense_iu = urb->transfer_buffer; + struct scsi_device *sdev = cmnd->device; + + if (urb->actual_length > 16) { + unsigned len = be16_to_cpup(&sense_iu->len); + if (len + 16 != urb->actual_length) { + int newlen = min(len + 16, urb->actual_length) - 16; + if (newlen < 0) + newlen = 0; + sdev_printk(KERN_INFO, sdev, "%s: urb length %d " + "disagrees with IU sense data length %d, " + "using %d bytes of sense data\n", __func__, + urb->actual_length, len, newlen); + len = newlen; + } + memcpy(cmnd->sense_buffer, sense_iu->sense, len); + } + + cmnd->result = sense_iu->status; + if (sdev->current_cmnd) + sdev->current_cmnd = NULL; + cmnd->scsi_done(cmnd); + usb_free_urb(urb); +} + +static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) +{ + struct sense_iu_old *sense_iu = urb->transfer_buffer; + struct scsi_device *sdev = cmnd->device; + + if (urb->actual_length > 8) { + unsigned len = be16_to_cpup(&sense_iu->len) - 2; + if (len + 8 != urb->actual_length) { + int newlen = min(len + 8, urb->actual_length) - 8; + if (newlen < 0) + newlen = 0; + sdev_printk(KERN_INFO, sdev, "%s: urb length %d " + "disagrees with IU sense data length %d, " + "using %d bytes of sense data\n", __func__, + urb->actual_length, len, newlen); + len = newlen; + } + memcpy(cmnd->sense_buffer, sense_iu->sense, len); + } + + cmnd->result = sense_iu->status; + if (sdev->current_cmnd) + sdev->current_cmnd = NULL; + cmnd->scsi_done(cmnd); + usb_free_urb(urb); +} + +static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, + unsigned direction) +{ + struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + int err; + + cmdinfo->state = direction | SUBMIT_SENSE_URB; + err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); + if (err) { + spin_lock(&uas_work_lock); + list_add_tail(&cmdinfo->list, &uas_work_list); + spin_unlock(&uas_work_lock); + schedule_work(&uas_work); + } +} + +static void uas_stat_cmplt(struct urb *urb) +{ + struct iu *iu = urb->transfer_buffer; + struct scsi_device *sdev = urb->context; + struct uas_dev_info *devinfo = sdev->hostdata; + struct scsi_cmnd *cmnd; + u16 tag; + + if (urb->status) { + dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status); + usb_free_urb(urb); + return; + } + + tag = be16_to_cpup(&iu->tag) - 1; + if (sdev->current_cmnd) + cmnd = sdev->current_cmnd; + else + cmnd = scsi_find_tag(sdev, tag); + if (!cmnd) + return; + + switch (iu->iu_id) { + case IU_ID_STATUS: + if (urb->actual_length < 16) + devinfo->uas_sense_old = 1; + if (devinfo->uas_sense_old) + uas_sense_old(urb, cmnd); + else + uas_sense(urb, cmnd); + break; + case IU_ID_READ_READY: + uas_xfer_data(urb, cmnd, SUBMIT_DATA_IN_URB); + break; + case IU_ID_WRITE_READY: + uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB); + break; + default: + scmd_printk(KERN_ERR, cmnd, + "Bogus IU (%d) received on status pipe\n", iu->iu_id); + } +} + +static void uas_data_cmplt(struct urb *urb) +{ + struct scsi_data_buffer *sdb = urb->context; + sdb->resid = sdb->length - urb->actual_length; + usb_free_urb(urb); +} + +static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp, + unsigned int pipe, u16 stream_id, + struct scsi_data_buffer *sdb, + enum dma_data_direction dir) +{ + struct usb_device *udev = devinfo->udev; + struct urb *urb = usb_alloc_urb(0, gfp); + + if (!urb) + goto out; + usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, uas_data_cmplt, + sdb); + if (devinfo->use_streams) + urb->stream_id = stream_id; + urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0; + urb->sg = sdb->table.sgl; + out: + return urb; +} + +static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, + struct scsi_cmnd *cmnd, u16 stream_id) +{ + struct usb_device *udev = devinfo->udev; + struct urb *urb = usb_alloc_urb(0, gfp); + struct sense_iu *iu; + + if (!urb) + goto out; + + iu = kmalloc(sizeof(*iu), gfp); + if (!iu) + goto free; + + usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu), + uas_stat_cmplt, cmnd->device); + urb->stream_id = stream_id; + urb->transfer_flags |= URB_FREE_BUFFER; + out: + return urb; + free: + usb_free_urb(urb); + return NULL; +} + +static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp, + struct scsi_cmnd *cmnd, u16 stream_id) +{ + struct usb_device *udev = devinfo->udev; + struct scsi_device *sdev = cmnd->device; + struct urb *urb = usb_alloc_urb(0, gfp); + struct command_iu *iu; + int len; + + if (!urb) + goto out; + + len = cmnd->cmd_len - 16; + if (len < 0) + len = 0; + len = ALIGN(len, 4); + iu = kmalloc(sizeof(*iu) + len, gfp); + if (!iu) + goto free; + + iu->iu_id = IU_ID_COMMAND; + iu->tag = cpu_to_be16(stream_id); + if (sdev->ordered_tags && (cmnd->request->cmd_flags & REQ_HARDBARRIER)) + iu->prio_attr = UAS_ORDERED_TAG; + else + iu->prio_attr = UAS_SIMPLE_TAG; + iu->len = len; + int_to_scsilun(sdev->lun, &iu->lun); + memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len); + + usb_fill_bulk_urb(urb, udev, devinfo->cmd_pipe, iu, sizeof(*iu) + len, + usb_free_urb, NULL); + urb->transfer_flags |= URB_FREE_BUFFER; + out: + return urb; + free: + usb_free_urb(urb); + return NULL; +} + +/* + * Why should I request the Status IU before sending the Command IU? Spec + * says to, but also says the device may receive them in any order. Seems + * daft to me. + */ + +static int uas_submit_urbs(struct scsi_cmnd *cmnd, + struct uas_dev_info *devinfo, gfp_t gfp) +{ + struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + + if (cmdinfo->state & ALLOC_SENSE_URB) { + cmdinfo->sense_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd, + cmdinfo->stream); + if (!cmdinfo->sense_urb) + return SCSI_MLQUEUE_DEVICE_BUSY; + cmdinfo->state &= ~ALLOC_SENSE_URB; + } + + if (cmdinfo->state & SUBMIT_SENSE_URB) { + if (usb_submit_urb(cmdinfo->sense_urb, gfp)) { + scmd_printk(KERN_INFO, cmnd, + "sense urb submission failure\n"); + return SCSI_MLQUEUE_DEVICE_BUSY; + } + cmdinfo->state &= ~SUBMIT_SENSE_URB; + } + + if (cmdinfo->state & ALLOC_DATA_IN_URB) { + cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp, + devinfo->data_in_pipe, cmdinfo->stream, + scsi_in(cmnd), DMA_FROM_DEVICE); + if (!cmdinfo->data_in_urb) + return SCSI_MLQUEUE_DEVICE_BUSY; + cmdinfo->state &= ~ALLOC_DATA_IN_URB; + } + + if (cmdinfo->state & SUBMIT_DATA_IN_URB) { + if (usb_submit_urb(cmdinfo->data_in_urb, gfp)) { + scmd_printk(KERN_INFO, cmnd, + "data in urb submission failure\n"); + return SCSI_MLQUEUE_DEVICE_BUSY; + } + cmdinfo->state &= ~SUBMIT_DATA_IN_URB; + } + + if (cmdinfo->state & ALLOC_DATA_OUT_URB) { + cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp, + devinfo->data_out_pipe, cmdinfo->stream, + scsi_out(cmnd), DMA_TO_DEVICE); + if (!cmdinfo->data_out_urb) + return SCSI_MLQUEUE_DEVICE_BUSY; + cmdinfo->state &= ~ALLOC_DATA_OUT_URB; + } + + if (cmdinfo->state & SUBMIT_DATA_OUT_URB) { + if (usb_submit_urb(cmdinfo->data_out_urb, gfp)) { + scmd_printk(KERN_INFO, cmnd, + "data out urb submission failure\n"); + return SCSI_MLQUEUE_DEVICE_BUSY; + } + cmdinfo->state &= ~SUBMIT_DATA_OUT_URB; + } + + if (cmdinfo->state & ALLOC_CMD_URB) { + cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, gfp, cmnd, + cmdinfo->stream); + if (!cmdinfo->cmd_urb) + return SCSI_MLQUEUE_DEVICE_BUSY; + cmdinfo->state &= ~ALLOC_CMD_URB; + } + + if (cmdinfo->state & SUBMIT_CMD_URB) { + if (usb_submit_urb(cmdinfo->cmd_urb, gfp)) { + scmd_printk(KERN_INFO, cmnd, + "cmd urb submission failure\n"); + return SCSI_MLQUEUE_DEVICE_BUSY; + } + cmdinfo->state &= ~SUBMIT_CMD_URB; + } + + return 0; +} + +static int uas_queuecommand(struct scsi_cmnd *cmnd, + void (*done)(struct scsi_cmnd *)) +{ + struct scsi_device *sdev = cmnd->device; + struct uas_dev_info *devinfo = sdev->hostdata; + struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + int err; + + BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer)); + + if (!cmdinfo->sense_urb && sdev->current_cmnd) + return SCSI_MLQUEUE_DEVICE_BUSY; + + if (blk_rq_tagged(cmnd->request)) { + cmdinfo->stream = cmnd->request->tag + 1; + } else { + sdev->current_cmnd = cmnd; + cmdinfo->stream = 1; + } + + cmnd->scsi_done = done; + + cmdinfo->state = ALLOC_SENSE_URB | SUBMIT_SENSE_URB | + ALLOC_CMD_URB | SUBMIT_CMD_URB; + + switch (cmnd->sc_data_direction) { + case DMA_FROM_DEVICE: + cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB; + break; + case DMA_BIDIRECTIONAL: + cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB; + case DMA_TO_DEVICE: + cmdinfo->state |= ALLOC_DATA_OUT_URB | SUBMIT_DATA_OUT_URB; + case DMA_NONE: + break; + } + + if (!devinfo->use_streams) { + cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB); + cmdinfo->stream = 0; + } + + err = uas_submit_urbs(cmnd, devinfo, GFP_ATOMIC); + if (err) { + /* If we did nothing, give up now */ + if (cmdinfo->state & SUBMIT_SENSE_URB) { + usb_free_urb(cmdinfo->sense_urb); + return SCSI_MLQUEUE_DEVICE_BUSY; + } + spin_lock(&uas_work_lock); + list_add_tail(&cmdinfo->list, &uas_work_list); + spin_unlock(&uas_work_lock); + schedule_work(&uas_work); + } + + return 0; +} + +static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) +{ + struct scsi_device *sdev = cmnd->device; + sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__, + cmnd->request->tag); + +/* XXX: Send ABORT TASK Task Management command */ + return FAILED; +} + +static int uas_eh_device_reset_handler(struct scsi_cmnd *cmnd) +{ + struct scsi_device *sdev = cmnd->device; + sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__, + cmnd->request->tag); + +/* XXX: Send LOGICAL UNIT RESET Task Management command */ + return FAILED; +} + +static int uas_eh_target_reset_handler(struct scsi_cmnd *cmnd) +{ + struct scsi_device *sdev = cmnd->device; + sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__, + cmnd->request->tag); + +/* XXX: Can we reset just the one USB interface? + * Would calling usb_set_interface() have the right effect? + */ + return FAILED; +} + +static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd) +{ + struct scsi_device *sdev = cmnd->device; + struct uas_dev_info *devinfo = sdev->hostdata; + struct usb_device *udev = devinfo->udev; + + sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__, + cmnd->request->tag); + + if (usb_reset_device(udev)) + return SUCCESS; + + return FAILED; +} + +static int uas_slave_alloc(struct scsi_device *sdev) +{ + sdev->hostdata = (void *)sdev->host->hostdata[0]; + return 0; +} + +static int uas_slave_configure(struct scsi_device *sdev) +{ + struct uas_dev_info *devinfo = sdev->hostdata; + scsi_set_tag_type(sdev, MSG_ORDERED_TAG); + scsi_activate_tcq(sdev, devinfo->qdepth - 1); + return 0; +} + +static struct scsi_host_template uas_host_template = { + .module = THIS_MODULE, + .name = "uas", + .queuecommand = uas_queuecommand, + .slave_alloc = uas_slave_alloc, + .slave_configure = uas_slave_configure, + .eh_abort_handler = uas_eh_abort_handler, + .eh_device_reset_handler = uas_eh_device_reset_handler, + .eh_target_reset_handler = uas_eh_target_reset_handler, + .eh_bus_reset_handler = uas_eh_bus_reset_handler, + .can_queue = 65536, /* Is there a limit on the _host_ ? */ + .this_id = -1, + .sg_tablesize = SG_NONE, + .cmd_per_lun = 1, /* until we override it */ + .skip_settle_delay = 1, + .ordered_tag = 1, +}; + +static struct usb_device_id uas_usb_ids[] = { + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) }, + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_UAS) }, + /* 0xaa is a prototype device I happen to have access to */ + { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, 0xaa) }, + { } +}; +MODULE_DEVICE_TABLE(usb, uas_usb_ids); + +static void uas_configure_endpoints(struct uas_dev_info *devinfo) +{ + struct usb_host_endpoint *eps[4] = { }; + struct usb_interface *intf = devinfo->intf; + struct usb_device *udev = devinfo->udev; + struct usb_host_endpoint *endpoint = intf->cur_altsetting->endpoint; + unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints; + + devinfo->uas_sense_old = 0; + + for (i = 0; i < n_endpoints; i++) { + unsigned char *extra = endpoint[i].extra; + int len = endpoint[i].extralen; + while (len > 1) { + if (extra[1] == USB_DT_PIPE_USAGE) { + unsigned pipe_id = extra[2]; + if (pipe_id > 0 && pipe_id < 5) + eps[pipe_id - 1] = &endpoint[i]; + break; + } + len -= extra[0]; + extra += extra[0]; + } + } + + /* + * Assume that if we didn't find a control pipe descriptor, we're + * using a device with old firmware that happens to be set up like + * this. + */ + if (!eps[0]) { + devinfo->cmd_pipe = usb_sndbulkpipe(udev, 1); + devinfo->status_pipe = usb_rcvbulkpipe(udev, 1); + devinfo->data_in_pipe = usb_rcvbulkpipe(udev, 2); + devinfo->data_out_pipe = usb_sndbulkpipe(udev, 2); + + eps[1] = usb_pipe_endpoint(udev, devinfo->status_pipe); + eps[2] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); + eps[3] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); + } else { + devinfo->cmd_pipe = usb_sndbulkpipe(udev, + eps[0]->desc.bEndpointAddress); + devinfo->status_pipe = usb_rcvbulkpipe(udev, + eps[1]->desc.bEndpointAddress); + devinfo->data_in_pipe = usb_rcvbulkpipe(udev, + eps[2]->desc.bEndpointAddress); + devinfo->data_out_pipe = usb_sndbulkpipe(udev, + eps[3]->desc.bEndpointAddress); + } + + devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1, 3, 256, + GFP_KERNEL); + if (devinfo->qdepth < 0) { + devinfo->qdepth = 256; + devinfo->use_streams = 0; + } else { + devinfo->use_streams = 1; + } +} + +/* + * XXX: What I'd like to do here is register a SCSI host for each USB host in + * the system. Follow usb-storage's design of registering a SCSI host for + * each USB device for the moment. Can implement this by walking up the + * USB hierarchy until we find a USB host. + */ +static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + int result; + struct Scsi_Host *shost; + struct uas_dev_info *devinfo; + struct usb_device *udev = interface_to_usbdev(intf); + + if (id->bInterfaceProtocol == 0x50) { + int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; +/* XXX: Shouldn't assume that 1 is the alternative we want */ + int ret = usb_set_interface(udev, ifnum, 1); + if (ret) + return -ENODEV; + } + + devinfo = kmalloc(sizeof(struct uas_dev_info), GFP_KERNEL); + if (!devinfo) + return -ENOMEM; + + result = -ENOMEM; + shost = scsi_host_alloc(&uas_host_template, sizeof(void *)); + if (!shost) + goto free; + + shost->max_cmd_len = 16 + 252; + shost->max_id = 1; + shost->sg_tablesize = udev->bus->sg_tablesize; + + result = scsi_add_host(shost, &intf->dev); + if (result) + goto free; + shost->hostdata[0] = (unsigned long)devinfo; + + devinfo->intf = intf; + devinfo->udev = udev; + uas_configure_endpoints(devinfo); + + scsi_scan_host(shost); + usb_set_intfdata(intf, shost); + return result; + free: + kfree(devinfo); + if (shost) + scsi_host_put(shost); + return result; +} + +static int uas_pre_reset(struct usb_interface *intf) +{ +/* XXX: Need to return 1 if it's not our device in error handling */ + return 0; +} + +static int uas_post_reset(struct usb_interface *intf) +{ +/* XXX: Need to return 1 if it's not our device in error handling */ + return 0; +} + +static void uas_disconnect(struct usb_interface *intf) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct usb_host_endpoint *eps[3]; + struct Scsi_Host *shost = usb_get_intfdata(intf); + struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; + + scsi_remove_host(shost); + + eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); + eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); + eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); + usb_free_streams(intf, eps, 3, GFP_KERNEL); + + kfree(devinfo); +} + +/* + * XXX: Should this plug into libusual so we can auto-upgrade devices from + * Bulk-Only to UAS? + */ +static struct usb_driver uas_driver = { + .name = "uas", + .probe = uas_probe, + .disconnect = uas_disconnect, + .pre_reset = uas_pre_reset, + .post_reset = uas_post_reset, + .id_table = uas_usb_ids, +}; + +static int uas_init(void) +{ + return usb_register(&uas_driver); +} + +static void uas_exit(void) +{ + usb_deregister(&uas_driver); +} + +module_init(uas_init); +module_exit(uas_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Matthew Wilcox and Sarah Sharp"); From 3323b7107ece794eb3e16111b583f5afb6749278 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 7 Oct 2010 13:05:24 +0200 Subject: [PATCH 060/141] USB: gadget: file_storage: reuse definitions from a header file This commit changes storage_common.c and file_storage.c to reuse definitions from linux/usb/storage.h header file. Signed-off-by: Michal Nazarewicz Cc: Alan Stern Cc: Matthew Wilcox Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/storage_common.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index d7856c599d5a..0a7df3db71f1 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -54,6 +54,7 @@ #include +#include /* @@ -156,19 +157,6 @@ #define TYPE_DISK 0x00 #define TYPE_CDROM 0x05 -/* USB protocol value = the transport method */ -#define USB_PR_CBI 0x00 /* Control/Bulk/Interrupt */ -#define USB_PR_CB 0x01 /* Control/Bulk w/o interrupt */ -#define USB_PR_BULK 0x50 /* Bulk-only */ - -/* USB subclass value = the protocol encapsulation */ -#define USB_SC_RBC 0x01 /* Reduced Block Commands (flash) */ -#define USB_SC_8020 0x02 /* SFF-8020i, MMC-2, ATAPI (CD-ROM) */ -#define USB_SC_QIC 0x03 /* QIC-157 (tape) */ -#define USB_SC_UFI 0x04 /* UFI (floppy) */ -#define USB_SC_8070 0x05 /* SFF-8070i (removable) */ -#define USB_SC_SCSI 0x06 /* Transparent SCSI */ - /* Bulk-only data structures */ /* Command Block Wrapper */ From 6bc235a2e24a5ef677daee3fd4f74f6cd643e23c Mon Sep 17 00:00:00 2001 From: Tomoki Sekiyama Date: Wed, 29 Sep 2010 12:16:50 +0900 Subject: [PATCH 061/141] USB: add driver for Meywa-Denki & Kayac YUREX Meywa-Denki/Kayac YUREX is a leg-shakes sensor device. See http://bbu.kayac.com/en/about/ for further information. This driver support read/write the leg-shakes counter in the device via a device file /dev/yurex[0-9]*. [minor coding style cleanups fixed by gregkh] Signed-off-by: Tomoki Sekiyama Cc: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 + drivers/usb/misc/Kconfig | 13 + drivers/usb/misc/Makefile | 1 + drivers/usb/misc/yurex.c | 552 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 570 insertions(+) create mode 100644 drivers/usb/misc/yurex.c diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index a0dea3d1296e..3cb6632d4518 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1662,6 +1662,7 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) }, { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, + { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_YUREX) }, { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index c5ae5f1545bd..855aa8e355f4 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -304,6 +304,9 @@ #define USB_VENDOR_ID_IMATION 0x0718 #define USB_DEVICE_ID_DISC_STAKKA 0xd000 +#define USB_VENDOR_ID_JESS 0x0c45 +#define USB_DEVICE_ID_JESS_YUREX 0x1010 + #define USB_VENDOR_ID_KBGEAR 0x084e #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 55660eaf947c..1bfcd02ebeb5 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -231,3 +231,16 @@ config USB_ISIGHTFW driver beforehand. Tools for doing so are available at http://bersace03.free.fr +config USB_YUREX + tristate "USB YUREX driver support" + depends on USB + help + Say Y here if you want to connect a YUREX to your computer's + USB port. The YUREX is a leg-shakes sensor. See + for further information. + This driver supports read/write of leg-shakes counter and + fasync for the counter update via a device file /dev/yurex*. + + To compile this driver as a module, choose M here: the + module will be called yurex. + diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 717703e81425..d203ff6870e4 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_USB_TEST) += usbtest.o obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o obj-$(CONFIG_USB_USS720) += uss720.o obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o +obj-$(CONFIG_USB_YUREX) += yurex.o obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c new file mode 100644 index 000000000000..76b8ab47fe04 --- /dev/null +++ b/drivers/usb/misc/yurex.c @@ -0,0 +1,552 @@ +/* + * Driver for Meywa-Denki & KAYAC YUREX + * + * Copyright (C) 2010 Tomoki Sekiyama (tomoki.sekiyama@gmail.com) + * + * 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, version 2. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_AUTHOR "Tomoki Sekiyama" +#define DRIVER_DESC "Driver for Meywa-Denki & KAYAC YUREX" + +#define YUREX_VENDOR_ID 0x0c45 +#define YUREX_PRODUCT_ID 0x1010 + +#define CMD_ACK '!' +#define CMD_ANIMATE 'A' +#define CMD_COUNT 'C' +#define CMD_LED 'L' +#define CMD_READ 'R' +#define CMD_SET 'S' +#define CMD_VERSION 'V' +#define CMD_EOF 0x0d +#define CMD_PADDING 0xff + +#define YUREX_BUF_SIZE 8 +#define YUREX_WRITE_TIMEOUT (HZ) + +/* table of devices that work with this driver */ +static struct usb_device_id yurex_table[] = { + { USB_DEVICE(YUREX_VENDOR_ID, YUREX_PRODUCT_ID) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, yurex_table); + +#ifdef CONFIG_USB_DYNAMIC_MINORS +#define YUREX_MINOR_BASE 0 +#else +#define YUREX_MINOR_BASE 224 /* not official yet */ +#endif + +/* Structure to hold all of our device specific stuff */ +struct usb_yurex { + struct usb_device *udev; + struct usb_interface *interface; + __u8 int_in_endpointAddr; + struct urb *urb; /* URB for interrupt in */ + unsigned char *int_buffer; /* buffer for intterupt in */ + struct urb *cntl_urb; /* URB for control msg */ + struct usb_ctrlrequest *cntl_req; /* req for control msg */ + unsigned char *cntl_buffer; /* buffer for control msg */ + + struct kref kref; + struct mutex io_mutex; + struct fasync_struct *async_queue; + wait_queue_head_t waitq; + + spinlock_t lock; + __s64 bbu; /* BBU from device */ +}; +#define to_yurex_dev(d) container_of(d, struct usb_yurex, kref) + +static struct usb_driver yurex_driver; +static const struct file_operations yurex_fops; + + +static void yurex_control_callback(struct urb *urb) +{ + struct usb_yurex *dev = urb->context; + int status = urb->status; + + if (status) { + err("%s - control failed: %d¥n", __func__, status); + wake_up_interruptible(&dev->waitq); + return; + } + /* on success, sender woken up by CMD_ACK int in, or timeout */ +} + +static void yurex_delete(struct kref *kref) +{ + struct usb_yurex *dev = to_yurex_dev(kref); + + dbg("yurex_delete"); + + usb_put_dev(dev->udev); + if (dev->urb) { + usb_kill_urb(dev->urb); + if (dev->int_buffer) + usb_free_coherent(dev->udev, YUREX_BUF_SIZE, + dev->int_buffer, dev->urb->transfer_dma); + usb_free_urb(dev->urb); + } + kfree(dev); +} + +/* + * usb class driver info in order to get a minor number from the usb core, + * and to have the device registered with the driver core + */ +static struct usb_class_driver yurex_class = { + .name = "yurex%d", + .fops = &yurex_fops, + .minor_base = YUREX_MINOR_BASE, +}; + +static void yurex_interrupt(struct urb *urb) +{ + struct usb_yurex *dev = urb->context; + unsigned char *buf = dev->int_buffer; + int status = urb->status; + unsigned long flags; + int retval, i; + + switch (status) { + case 0: /*success*/ + break; + case -EOVERFLOW: + err("%s - overflow with length %d, actual length is %d", + __func__, YUREX_BUF_SIZE, dev->urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + case -EILSEQ: + /* The device is terminated, clean up */ + return; + default: + err("%s - unknown status received: %d", __func__, status); + goto exit; + } + + /* handle received message */ + switch (buf[0]) { + case CMD_COUNT: + case CMD_READ: + if (buf[6] == CMD_EOF) { + spin_lock_irqsave(&dev->lock, flags); + dev->bbu = 0; + for (i = 1; i < 6; i++) { + dev->bbu += buf[i]; + if (i != 5) + dev->bbu <<= 8; + } + dbg("%s count: %lld", __func__, dev->bbu); + spin_unlock_irqrestore(&dev->lock, flags); + + kill_fasync(&dev->async_queue, SIGIO, POLL_IN); + } + else + dbg("data format error - no EOF"); + break; + case CMD_ACK: + dbg("%s ack: %c", __func__, buf[1]); + wake_up_interruptible(&dev->waitq); + break; + } + +exit: + retval = usb_submit_urb(dev->urb, GFP_ATOMIC); + if (retval) { + err("%s - usb_submit_urb failed: %d", + __func__, retval); + } +} + +static int yurex_probe(struct usb_interface *interface, const struct usb_device_id *id) +{ + struct usb_yurex *dev; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int retval = -ENOMEM; + int i; + DEFINE_WAIT(wait); + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + err("Out of memory"); + goto error; + } + kref_init(&dev->kref); + mutex_init(&dev->io_mutex); + spin_lock_init(&dev->lock); + init_waitqueue_head(&dev->waitq); + + dev->udev = usb_get_dev(interface_to_usbdev(interface)); + dev->interface = interface; + + /* set up the endpoint information */ + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { + endpoint = &iface_desc->endpoint[i].desc; + + if (usb_endpoint_is_int_in(endpoint)) { + dev->int_in_endpointAddr = endpoint->bEndpointAddress; + break; + } + } + if (!dev->int_in_endpointAddr) { + retval = -ENODEV; + err("Could not find endpoints"); + goto error; + } + + + /* allocate control URB */ + dev->cntl_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->cntl_urb) { + err("Could not allocate control URB"); + goto error; + } + + /* allocate buffer for control req */ + dev->cntl_req = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE, + GFP_KERNEL, + &dev->cntl_urb->setup_dma); + if (!dev->cntl_req) { + err("Could not allocate cntl_req"); + goto error; + } + + /* allocate buffer for control msg */ + dev->cntl_buffer = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE, + GFP_KERNEL, + &dev->cntl_urb->transfer_dma); + if (!dev->cntl_buffer) { + err("Could not allocate cntl_buffer"); + goto error; + } + + /* configure control URB */ + dev->cntl_req->bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | + USB_RECIP_INTERFACE; + dev->cntl_req->bRequest = HID_REQ_SET_REPORT; + dev->cntl_req->wValue = cpu_to_le16((HID_OUTPUT_REPORT + 1) << 8); + dev->cntl_req->wIndex = cpu_to_le16(iface_desc->desc.bInterfaceNumber); + dev->cntl_req->wLength = cpu_to_le16(YUREX_BUF_SIZE); + + usb_fill_control_urb(dev->cntl_urb, dev->udev, + usb_sndctrlpipe(dev->udev, 0), + (void *)dev->cntl_req, dev->cntl_buffer, + YUREX_BUF_SIZE, yurex_control_callback, dev); + dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + + /* allocate interrupt URB */ + dev->urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->urb) { + err("Could not allocate URB"); + goto error; + } + + /* allocate buffer for interrupt in */ + dev->int_buffer = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE, + GFP_KERNEL, &dev->urb->transfer_dma); + if (!dev->int_buffer) { + err("Could not allocate int_buffer"); + goto error; + } + + /* configure interrupt URB */ + usb_fill_int_urb(dev->urb, dev->udev, + usb_rcvintpipe(dev->udev, dev->int_in_endpointAddr), + dev->int_buffer, YUREX_BUF_SIZE, yurex_interrupt, + dev, 1); + if (usb_submit_urb(dev->urb, GFP_KERNEL)) { + retval = -EIO; + err("Could not submitting URB"); + goto error; + } + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + + /* we can register the device now, as it is ready */ + retval = usb_register_dev(interface, &yurex_class); + if (retval) { + err("Not able to get a minor for this device."); + usb_set_intfdata(interface, NULL); + goto error; + } + + dev->bbu = -1; + + dev_info(&interface->dev, + "USB Yurex device now attached to Yurex-%d¥n", + interface->minor); + + return 0; + +error: + if (dev) + /* this frees allocated memory */ + kref_put(&dev->kref, yurex_delete); + return retval; +} + +static void yurex_disconnect(struct usb_interface *interface) +{ + struct usb_yurex *dev; + int minor = interface->minor; + + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + /* give back our minor */ + usb_deregister_dev(interface, &yurex_class); + + /* prevent more I/O from starting */ + mutex_lock(&dev->io_mutex); + dev->interface = NULL; + mutex_unlock(&dev->io_mutex); + + /* wakeup waiters */ + kill_fasync(&dev->async_queue, SIGIO, POLL_IN); + wake_up_interruptible(&dev->waitq); + + /* decrement our usage count */ + kref_put(&dev->kref, yurex_delete); + + dev_info(&interface->dev, "USB Yurex #%d now disconnected", minor); +} + +static struct usb_driver yurex_driver = { + .name = "yurex", + .probe = yurex_probe, + .disconnect = yurex_disconnect, + .id_table = yurex_table, +}; + + +static int yurex_fasync(int fd, struct file *file, int on) +{ + struct usb_yurex *dev; + + dev = (struct usb_yurex *)file->private_data; + return fasync_helper(fd, file, on, &dev->async_queue); +} + +static int yurex_open(struct inode *inode, struct file *file) +{ + struct usb_yurex *dev; + struct usb_interface *interface; + int subminor; + int retval = 0; + + subminor = iminor(inode); + + interface = usb_find_interface(&yurex_driver, subminor); + if (!interface) { + err("%s - error, can't find device for minor %d", + __func__, subminor); + retval = -ENODEV; + goto exit; + } + + dev = usb_get_intfdata(interface); + if (!dev) { + retval = -ENODEV; + goto exit; + } + + /* increment our usage count for the device */ + kref_get(&dev->kref); + + /* save our object in the file's private structure */ + mutex_lock(&dev->io_mutex); + file->private_data = dev; + mutex_unlock(&dev->io_mutex); + +exit: + return retval; +} + +static int yurex_release(struct inode *inode, struct file *file) +{ + struct usb_yurex *dev; + + dev = (struct usb_yurex *)file->private_data; + if (dev == NULL) + return -ENODEV; + + yurex_fasync(-1, file, 0); + + /* decrement the count on our device */ + kref_put(&dev->kref, yurex_delete); + return 0; +} + +static ssize_t yurex_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + struct usb_yurex *dev; + int retval = 0; + int bytes_read = 0; + char in_buffer[20]; + unsigned long flags; + + dev = (struct usb_yurex *)file->private_data; + + mutex_lock(&dev->io_mutex); + if (!dev->interface) { /* already disconnected */ + retval = -ENODEV; + goto exit; + } + + spin_lock_irqsave(&dev->lock, flags); + bytes_read = snprintf(in_buffer, 20, "%lld¥n", dev->bbu); + spin_unlock_irqrestore(&dev->lock, flags); + + if (*ppos < bytes_read) { + if (copy_to_user(buffer, in_buffer + *ppos, bytes_read - *ppos)) + retval = -EFAULT; + else { + retval = bytes_read - *ppos; + *ppos += bytes_read; + } + } + +exit: + mutex_unlock(&dev->io_mutex); + return retval; +} + +static ssize_t yurex_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) +{ + struct usb_yurex *dev; + int i, set = 0, retval = 0; + char buffer[16]; + char *data = buffer; + unsigned long long c, c2 = 0; + signed long timeout = 0; + DEFINE_WAIT(wait); + + count = min(sizeof(buffer), count); + dev = (struct usb_yurex *)file->private_data; + + /* verify that we actually have some data to write */ + if (count == 0) + goto error; + + mutex_lock(&dev->io_mutex); + if (!dev->interface) { /* alreaday disconnected */ + mutex_unlock(&dev->io_mutex); + retval = -ENODEV; + goto error; + } + + if (copy_from_user(buffer, user_buffer, count)) { + mutex_unlock(&dev->io_mutex); + retval = -EFAULT; + goto error; + } + memset(dev->cntl_buffer, CMD_PADDING, YUREX_BUF_SIZE); + + switch (buffer[0]) { + case CMD_ANIMATE: + case CMD_LED: + dev->cntl_buffer[0] = buffer[0]; + dev->cntl_buffer[1] = buffer[1]; + dev->cntl_buffer[2] = CMD_EOF; + break; + case CMD_READ: + case CMD_VERSION: + dev->cntl_buffer[0] = buffer[0]; + dev->cntl_buffer[1] = 0x00; + dev->cntl_buffer[2] = CMD_EOF; + break; + case CMD_SET: + data++; + /* FALL THROUGH */ + case '0' ... '9': + set = 1; + c = c2 = simple_strtoull(data, NULL, 0); + dev->cntl_buffer[0] = CMD_SET; + for (i = 1; i < 6; i++) { + dev->cntl_buffer[i] = (c>>32) & 0xff; + c <<= 8; + } + buffer[6] = CMD_EOF; + break; + default: + mutex_unlock(&dev->io_mutex); + return -EINVAL; + } + + /* send the data as the control msg */ + prepare_to_wait(&dev->waitq, &wait, TASK_INTERRUPTIBLE); + dbg("%s - submit %c", __func__, dev->cntl_buffer[0]); + retval = usb_submit_urb(dev->cntl_urb, GFP_KERNEL); + if (retval >= 0) + timeout = schedule_timeout(YUREX_WRITE_TIMEOUT); + finish_wait(&dev->waitq, &wait); + + mutex_unlock(&dev->io_mutex); + + if (retval < 0) { + err("%s - failed to send bulk msg, error %d", __func__, retval); + goto error; + } + if (set && timeout) + dev->bbu = c2; + return timeout ? count : -EIO; + +error: + return retval; +} + +static const struct file_operations yurex_fops = { + .owner = THIS_MODULE, + .read = yurex_read, + .write = yurex_write, + .open = yurex_open, + .release = yurex_release, + .fasync = yurex_fasync, +}; + + +static int __init usb_yurex_init(void) +{ + int result; + + /* register this driver with the USB subsystem */ + result = usb_register(&yurex_driver); + if (result) + err("usb_register failed. Error number %d", result); + + return result; +} + +static void __exit usb_yurex_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&yurex_driver); +} + +module_init(usb_yurex_init); +module_exit(usb_yurex_exit); + +MODULE_LICENSE("GPL"); From 1b62d2583963d5974974aa923214bada7aa7b5d1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 30 Sep 2010 05:01:22 -0700 Subject: [PATCH 062/141] USB: yurex: assign a real minor number to the driver This assigns the minor number 192 to the yurex driver. We also fix up the previous usb minor number entry, it was wrong. Cc: Tomoki Sekiyama Signed-off-by: Greg Kroah-Hartman --- Documentation/devices.txt | 5 ++++- drivers/usb/misc/yurex.c | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Documentation/devices.txt b/Documentation/devices.txt index d0d1df6cb5de..3cab6b342017 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -2553,7 +2553,10 @@ Your cooperation is appreciated. 175 = /dev/usb/legousbtower15 16th USB Legotower device 176 = /dev/usb/usbtmc1 First USB TMC device ... - 192 = /dev/usb/usbtmc16 16th USB TMC device + 191 = /dev/usb/usbtmc16 16th USB TMC device + 192 = /dev/usb/yurex1 First USB Yurex device + ... + 209 = /dev/usb/yurex16 16th USB Yurex device 240 = /dev/usb/dabusb0 First daubusb device ... 243 = /dev/usb/dabusb3 Fourth dabusb device diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index 76b8ab47fe04..5f6443bc6142 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -47,9 +47,9 @@ static struct usb_device_id yurex_table[] = { MODULE_DEVICE_TABLE(usb, yurex_table); #ifdef CONFIG_USB_DYNAMIC_MINORS -#define YUREX_MINOR_BASE 0 +#define YUREX_MINOR_BASE 0 #else -#define YUREX_MINOR_BASE 224 /* not official yet */ +#define YUREX_MINOR_BASE 192 #endif /* Structure to hold all of our device specific stuff */ From e06ea97fa47611992a5a61058729cf8e83bf6fda Mon Sep 17 00:00:00 2001 From: Tomoki Sekiyama Date: Sun, 3 Oct 2010 06:59:06 +0900 Subject: [PATCH 063/141] USB: yurex: fix memory leak and corrupted messages This fixes the memory leak on disconnecting the device. In addition, it fixes some messages corrupted by incorrect encoding. Signed-off-by: Tomoki Sekiyama Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/yurex.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index 5f6443bc6142..719c6180b31f 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -37,7 +37,7 @@ #define CMD_PADDING 0xff #define YUREX_BUF_SIZE 8 -#define YUREX_WRITE_TIMEOUT (HZ) +#define YUREX_WRITE_TIMEOUT (HZ*2) /* table of devices that work with this driver */ static struct usb_device_id yurex_table[] = { @@ -83,7 +83,7 @@ static void yurex_control_callback(struct urb *urb) int status = urb->status; if (status) { - err("%s - control failed: %d¥n", __func__, status); + err("%s - control failed: %d\n", __func__, status); wake_up_interruptible(&dev->waitq); return; } @@ -97,6 +97,16 @@ static void yurex_delete(struct kref *kref) dbg("yurex_delete"); usb_put_dev(dev->udev); + if (dev->cntl_urb) { + usb_kill_urb(dev->cntl_urb); + if (dev->cntl_req) + usb_free_coherent(dev->udev, YUREX_BUF_SIZE, + dev->cntl_req, dev->cntl_urb->setup_dma); + if (dev->cntl_buffer) + usb_free_coherent(dev->udev, YUREX_BUF_SIZE, + dev->cntl_buffer, dev->cntl_urb->transfer_dma); + usb_free_urb(dev->cntl_urb); + } if (dev->urb) { usb_kill_urb(dev->urb); if (dev->int_buffer) @@ -253,7 +263,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ usb_sndctrlpipe(dev->udev, 0), (void *)dev->cntl_req, dev->cntl_buffer, YUREX_BUF_SIZE, yurex_control_callback, dev); - dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* allocate interrupt URB */ @@ -276,6 +286,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ usb_rcvintpipe(dev->udev, dev->int_in_endpointAddr), dev->int_buffer, YUREX_BUF_SIZE, yurex_interrupt, dev, 1); + dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; if (usb_submit_urb(dev->urb, GFP_KERNEL)) { retval = -EIO; err("Could not submitting URB"); @@ -296,7 +307,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ dev->bbu = -1; dev_info(&interface->dev, - "USB Yurex device now attached to Yurex-%d¥n", + "USB YUREX device now attached to Yurex #%d\n", interface->minor); return 0; @@ -331,7 +342,7 @@ static void yurex_disconnect(struct usb_interface *interface) /* decrement our usage count */ kref_put(&dev->kref, yurex_delete); - dev_info(&interface->dev, "USB Yurex #%d now disconnected", minor); + dev_info(&interface->dev, "USB YUREX #%d now disconnected\n", minor); } static struct usb_driver yurex_driver = { @@ -417,7 +428,7 @@ static ssize_t yurex_read(struct file *file, char *buffer, size_t count, loff_t } spin_lock_irqsave(&dev->lock, flags); - bytes_read = snprintf(in_buffer, 20, "%lld¥n", dev->bbu); + bytes_read = snprintf(in_buffer, 20, "%lld\n", dev->bbu); spin_unlock_irqrestore(&dev->lock, flags); if (*ppos < bytes_read) { From d613746d8bc3a2904d4585d7efd7f457d9db6fb9 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 24 Sep 2010 13:44:02 +0300 Subject: [PATCH 064/141] USB: musb: make DBG() calls actually depend on CONFIG_USB_MUSB_DEBUG Enabling CONFIG_USB_MUSB_DEBUG option causes -DDEBUG to be added to gcc's command line, however the DBG() macro doesn't depend on DEBUG, so that the debugging messages get printed regardless of the option, and I don't think that this was intended. Get rid of otherwise unused xprintk() macro and make DBG() macro directly call pr_debug() which only results in the actual code generated if DEBUG is defined. This change makes musb_hdrc.o ~30% less in size with CONFIG_USB_MUSB_DEBUG disabled (in host mode). Signed-off-by: Sergei Shtylyov Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_debug.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h index d73afdbde3ee..94f6973cf8f7 100644 --- a/drivers/usb/musb/musb_debug.h +++ b/drivers/usb/musb/musb_debug.h @@ -42,11 +42,10 @@ #define INFO(fmt, args...) yprintk(KERN_INFO, fmt, ## args) #define ERR(fmt, args...) yprintk(KERN_ERR, fmt, ## args) -#define xprintk(level, facility, format, args...) do { \ - if (_dbg_level(level)) { \ - printk(facility "%s %d: " format , \ - __func__, __LINE__ , ## args); \ - } } while (0) +#define DBG(level, format, args...) do { \ + if (_dbg_level(level)) \ + pr_debug("%s %d: " format, __func__, __LINE__, ## args); \ + } while (0) extern unsigned musb_debug; @@ -55,8 +54,6 @@ static inline int _dbg_level(unsigned l) return musb_debug >= l; } -#define DBG(level, fmt, args...) xprintk(level, KERN_DEBUG, fmt, ## args) - extern const char *otg_state_string(struct musb *); #ifdef CONFIG_DEBUG_FS From 3ee076dea68e11d4685972df7298b80b8e7673e4 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 24 Sep 2010 13:44:03 +0300 Subject: [PATCH 065/141] usb: musb: introduce DA8xx/OMAP-L1x glue layer Texas Instruments DA8xx/OMAP-L1x glue layer for the MUSBMHRDC driver. Signed-off-by: Sergei Shtylyov Signed-off-by: Yadviga Grigorieva Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/Kconfig | 5 +- drivers/usb/musb/Makefile | 4 + drivers/usb/musb/da8xx.c | 469 +++++++++++++++++++++++++++++++++++ drivers/usb/musb/musb_core.h | 1 + 4 files changed, 478 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/musb/da8xx.c diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index cfd38edfcf9e..1dd21c2315e4 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -45,6 +45,9 @@ config USB_MUSB_SOC comment "DaVinci 35x and 644x USB support" depends on USB_MUSB_HDRC && ARCH_DAVINCI_DMx +comment "DA8xx/OMAP-L1x USB support" + depends on USB_MUSB_HDRC && ARCH_DAVINCI_DA8XX + comment "OMAP 243x high speed USB support" depends on USB_MUSB_HDRC && ARCH_OMAP2430 @@ -144,7 +147,7 @@ config USB_MUSB_HDRC_HCD config MUSB_PIO_ONLY bool 'Disable DMA (always use PIO)' depends on USB_MUSB_HDRC - default y if USB_TUSB6010 + default USB_TUSB6010 || ARCH_DAVINCI_DA8XX help All data is copied between memory and FIFO by the CPU. DMA controllers are ignored. diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 9705f716386e..f664ecfa21c4 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -10,6 +10,10 @@ ifeq ($(CONFIG_ARCH_DAVINCI_DMx),y) musb_hdrc-objs += davinci.o endif +ifeq ($(CONFIG_ARCH_DAVINCI_DA8XX),y) + musb_hdrc-objs += da8xx.o +endif + ifeq ($(CONFIG_USB_TUSB6010),y) musb_hdrc-objs += tusb6010.o endif diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c new file mode 100644 index 000000000000..84427bebbf62 --- /dev/null +++ b/drivers/usb/musb/da8xx.c @@ -0,0 +1,469 @@ +/* + * Texas Instruments DA8xx/OMAP-L1x "glue layer" + * + * Copyright (c) 2008-2009 MontaVista Software, Inc. + * + * Based on the DaVinci "glue layer" code. + * Copyright (C) 2005-2006 by Texas Instruments + * + * This file is part of the Inventra Controller Driver for Linux. + * + * The Inventra Controller Driver for Linux 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. + * + * The Inventra Controller Driver for Linux 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. + * + * You should have received a copy of the GNU General Public License + * along with The Inventra Controller Driver for Linux ; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include + +#include +#include + +#include "musb_core.h" + +/* + * DA8XX specific definitions + */ + +/* USB 2.0 OTG module registers */ +#define DA8XX_USB_REVISION_REG 0x00 +#define DA8XX_USB_CTRL_REG 0x04 +#define DA8XX_USB_STAT_REG 0x08 +#define DA8XX_USB_EMULATION_REG 0x0c +#define DA8XX_USB_MODE_REG 0x10 /* Transparent, CDC, [Generic] RNDIS */ +#define DA8XX_USB_AUTOREQ_REG 0x14 +#define DA8XX_USB_SRP_FIX_TIME_REG 0x18 +#define DA8XX_USB_TEARDOWN_REG 0x1c +#define DA8XX_USB_INTR_SRC_REG 0x20 +#define DA8XX_USB_INTR_SRC_SET_REG 0x24 +#define DA8XX_USB_INTR_SRC_CLEAR_REG 0x28 +#define DA8XX_USB_INTR_MASK_REG 0x2c +#define DA8XX_USB_INTR_MASK_SET_REG 0x30 +#define DA8XX_USB_INTR_MASK_CLEAR_REG 0x34 +#define DA8XX_USB_INTR_SRC_MASKED_REG 0x38 +#define DA8XX_USB_END_OF_INTR_REG 0x3c +#define DA8XX_USB_GENERIC_RNDIS_EP_SIZE_REG(n) (0x50 + (((n) - 1) << 2)) + +/* Control register bits */ +#define DA8XX_SOFT_RESET_MASK 1 + +#define DA8XX_USB_TX_EP_MASK 0x1f /* EP0 + 4 Tx EPs */ +#define DA8XX_USB_RX_EP_MASK 0x1e /* 4 Rx EPs */ + +/* USB interrupt register bits */ +#define DA8XX_INTR_USB_SHIFT 16 +#define DA8XX_INTR_USB_MASK (0x1ff << DA8XX_INTR_USB_SHIFT) /* 8 Mentor */ + /* interrupts and DRVVBUS interrupt */ +#define DA8XX_INTR_DRVVBUS 0x100 +#define DA8XX_INTR_RX_SHIFT 8 +#define DA8XX_INTR_RX_MASK (DA8XX_USB_RX_EP_MASK << DA8XX_INTR_RX_SHIFT) +#define DA8XX_INTR_TX_SHIFT 0 +#define DA8XX_INTR_TX_MASK (DA8XX_USB_TX_EP_MASK << DA8XX_INTR_TX_SHIFT) + +#define DA8XX_MENTOR_CORE_OFFSET 0x400 + +#define CFGCHIP2 IO_ADDRESS(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG) + +/* + * REVISIT (PM): we should be able to keep the PHY in low power mode most + * of the time (24 MHz oscillator and PLL off, etc.) by setting POWER.D0 + * and, when in host mode, autosuspending idle root ports... PHY_PLLON + * (overriding SUSPENDM?) then likely needs to stay off. + */ + +static inline void phy_on(void) +{ + u32 cfgchip2 = __raw_readl(CFGCHIP2); + + /* + * Start the on-chip PHY and its PLL. + */ + cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN); + cfgchip2 |= CFGCHIP2_PHY_PLLON; + __raw_writel(cfgchip2, CFGCHIP2); + + pr_info("Waiting for USB PHY clock good...\n"); + while (!(__raw_readl(CFGCHIP2) & CFGCHIP2_PHYCLKGD)) + cpu_relax(); +} + +static inline void phy_off(void) +{ + u32 cfgchip2 = __raw_readl(CFGCHIP2); + + /* + * Ensure that USB 1.1 reference clock is not being sourced from + * USB 2.0 PHY. Otherwise do not power down the PHY. + */ + if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX) && + (cfgchip2 & CFGCHIP2_USB1SUSPENDM)) { + pr_warning("USB 1.1 clocked from USB 2.0 PHY -- " + "can't power it down\n"); + return; + } + + /* + * Power down the on-chip PHY. + */ + cfgchip2 |= CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN; + __raw_writel(cfgchip2, CFGCHIP2); +} + +/* + * Because we don't set CTRL.UINT, it's "important" to: + * - not read/write INTRUSB/INTRUSBE (except during + * initial setup, as a workaround); + * - use INTSET/INTCLR instead. + */ + +/** + * musb_platform_enable - enable interrupts + */ +void musb_platform_enable(struct musb *musb) +{ + void __iomem *reg_base = musb->ctrl_base; + u32 mask; + + /* Workaround: setup IRQs through both register sets. */ + mask = ((musb->epmask & DA8XX_USB_TX_EP_MASK) << DA8XX_INTR_TX_SHIFT) | + ((musb->epmask & DA8XX_USB_RX_EP_MASK) << DA8XX_INTR_RX_SHIFT) | + DA8XX_INTR_USB_MASK; + musb_writel(reg_base, DA8XX_USB_INTR_MASK_SET_REG, mask); + + /* Force the DRVVBUS IRQ so we can start polling for ID change. */ + if (is_otg_enabled(musb)) + musb_writel(reg_base, DA8XX_USB_INTR_SRC_SET_REG, + DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT); +} + +/** + * musb_platform_disable - disable HDRC and flush interrupts + */ +void musb_platform_disable(struct musb *musb) +{ + void __iomem *reg_base = musb->ctrl_base; + + musb_writel(reg_base, DA8XX_USB_INTR_MASK_CLEAR_REG, + DA8XX_INTR_USB_MASK | + DA8XX_INTR_TX_MASK | DA8XX_INTR_RX_MASK); + musb_writeb(musb->mregs, MUSB_DEVCTL, 0); + musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0); +} + +#ifdef CONFIG_USB_MUSB_HDRC_HCD +#define portstate(stmt) stmt +#else +#define portstate(stmt) +#endif + +static void da8xx_set_vbus(struct musb *musb, int is_on) +{ + WARN_ON(is_on && is_peripheral_active(musb)); +} + +#define POLL_SECONDS 2 + +static struct timer_list otg_workaround; + +static void otg_timer(unsigned long _musb) +{ + struct musb *musb = (void *)_musb; + void __iomem *mregs = musb->mregs; + u8 devctl; + unsigned long flags; + + /* + * We poll because DaVinci's won't expose several OTG-critical + * status change events (from the transceiver) otherwise. + */ + devctl = musb_readb(mregs, MUSB_DEVCTL); + DBG(7, "Poll devctl %02x (%s)\n", devctl, otg_state_string(musb)); + + spin_lock_irqsave(&musb->lock, flags); + switch (musb->xceiv->state) { + case OTG_STATE_A_WAIT_BCON: + devctl &= ~MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + + devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + if (devctl & MUSB_DEVCTL_BDEVICE) { + musb->xceiv->state = OTG_STATE_B_IDLE; + MUSB_DEV_MODE(musb); + } else { + musb->xceiv->state = OTG_STATE_A_IDLE; + MUSB_HST_MODE(musb); + } + break; + case OTG_STATE_A_WAIT_VFALL: + /* + * Wait till VBUS falls below SessionEnd (~0.2 V); the 1.3 + * RTL seems to mis-handle session "start" otherwise (or in + * our case "recover"), in routine "VBUS was valid by the time + * VBUSERR got reported during enumeration" cases. + */ + if (devctl & MUSB_DEVCTL_VBUS) { + mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); + break; + } + musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; + musb_writel(musb->ctrl_base, DA8XX_USB_INTR_SRC_SET_REG, + MUSB_INTR_VBUSERROR << DA8XX_INTR_USB_SHIFT); + break; + case OTG_STATE_B_IDLE: + if (!is_peripheral_enabled(musb)) + break; + + /* + * There's no ID-changed IRQ, so we have no good way to tell + * when to switch to the A-Default state machine (by setting + * the DEVCTL.Session bit). + * + * Workaround: whenever we're in B_IDLE, try setting the + * session flag every few seconds. If it works, ID was + * grounded and we're now in the A-Default state machine. + * + * NOTE: setting the session flag is _supposed_ to trigger + * SRP but clearly it doesn't. + */ + musb_writeb(mregs, MUSB_DEVCTL, devctl | MUSB_DEVCTL_SESSION); + devctl = musb_readb(mregs, MUSB_DEVCTL); + if (devctl & MUSB_DEVCTL_BDEVICE) + mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); + else + musb->xceiv->state = OTG_STATE_A_IDLE; + break; + default: + break; + } + spin_unlock_irqrestore(&musb->lock, flags); +} + +void musb_platform_try_idle(struct musb *musb, unsigned long timeout) +{ + static unsigned long last_timer; + + if (!is_otg_enabled(musb)) + return; + + if (timeout == 0) + timeout = jiffies + msecs_to_jiffies(3); + + /* Never idle if active, or when VBUS timeout is not set as host */ + if (musb->is_active || (musb->a_wait_bcon == 0 && + musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { + DBG(4, "%s active, deleting timer\n", otg_state_string(musb)); + del_timer(&otg_workaround); + last_timer = jiffies; + return; + } + + if (time_after(last_timer, timeout) && timer_pending(&otg_workaround)) { + DBG(4, "Longer idle timer already pending, ignoring...\n"); + return; + } + last_timer = timeout; + + DBG(4, "%s inactive, starting idle timer for %u ms\n", + otg_state_string(musb), jiffies_to_msecs(timeout - jiffies)); + mod_timer(&otg_workaround, timeout); +} + +static irqreturn_t da8xx_interrupt(int irq, void *hci) +{ + struct musb *musb = hci; + void __iomem *reg_base = musb->ctrl_base; + unsigned long flags; + irqreturn_t ret = IRQ_NONE; + u32 status; + + spin_lock_irqsave(&musb->lock, flags); + + /* + * NOTE: DA8XX shadows the Mentor IRQs. Don't manage them through + * the Mentor registers (except for setup), use the TI ones and EOI. + */ + + /* Acknowledge and handle non-CPPI interrupts */ + status = musb_readl(reg_base, DA8XX_USB_INTR_SRC_MASKED_REG); + if (!status) + goto eoi; + + musb_writel(reg_base, DA8XX_USB_INTR_SRC_CLEAR_REG, status); + DBG(4, "USB IRQ %08x\n", status); + + musb->int_rx = (status & DA8XX_INTR_RX_MASK) >> DA8XX_INTR_RX_SHIFT; + musb->int_tx = (status & DA8XX_INTR_TX_MASK) >> DA8XX_INTR_TX_SHIFT; + musb->int_usb = (status & DA8XX_INTR_USB_MASK) >> DA8XX_INTR_USB_SHIFT; + + /* + * DRVVBUS IRQs are the only proxy we have (a very poor one!) for + * DA8xx's missing ID change IRQ. We need an ID change IRQ to + * switch appropriately between halves of the OTG state machine. + * Managing DEVCTL.Session per Mentor docs requires that we know its + * value but DEVCTL.BDevice is invalid without DEVCTL.Session set. + * Also, DRVVBUS pulses for SRP (but not at 5 V)... + */ + if (status & (DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT)) { + int drvvbus = musb_readl(reg_base, DA8XX_USB_STAT_REG); + void __iomem *mregs = musb->mregs; + u8 devctl = musb_readb(mregs, MUSB_DEVCTL); + int err; + + err = is_host_enabled(musb) && (musb->int_usb & + MUSB_INTR_VBUSERROR); + if (err) { + /* + * The Mentor core doesn't debounce VBUS as needed + * to cope with device connect current spikes. This + * means it's not uncommon for bus-powered devices + * to get VBUS errors during enumeration. + * + * This is a workaround, but newer RTL from Mentor + * seems to allow a better one: "re"-starting sessions + * without waiting for VBUS to stop registering in + * devctl. + */ + musb->int_usb &= ~MUSB_INTR_VBUSERROR; + musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; + mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); + WARNING("VBUS error workaround (delay coming)\n"); + } else if (is_host_enabled(musb) && drvvbus) { + MUSB_HST_MODE(musb); + musb->xceiv->default_a = 1; + musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; + portstate(musb->port1_status |= USB_PORT_STAT_POWER); + del_timer(&otg_workaround); + } else { + musb->is_active = 0; + MUSB_DEV_MODE(musb); + musb->xceiv->default_a = 0; + musb->xceiv->state = OTG_STATE_B_IDLE; + portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); + } + + DBG(2, "VBUS %s (%s)%s, devctl %02x\n", + drvvbus ? "on" : "off", + otg_state_string(musb), + err ? " ERROR" : "", + devctl); + ret = IRQ_HANDLED; + } + + if (musb->int_tx || musb->int_rx || musb->int_usb) + ret |= musb_interrupt(musb); + + eoi: + /* EOI needs to be written for the IRQ to be re-asserted. */ + if (ret == IRQ_HANDLED || status) + musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0); + + /* Poll for ID change */ + if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE) + mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); + + spin_unlock_irqrestore(&musb->lock, flags); + + return ret; +} + +int musb_platform_set_mode(struct musb *musb, u8 musb_mode) +{ + u32 cfgchip2 = __raw_readl(CFGCHIP2); + + cfgchip2 &= ~CFGCHIP2_OTGMODE; + switch (musb_mode) { +#ifdef CONFIG_USB_MUSB_HDRC_HCD + case MUSB_HOST: /* Force VBUS valid, ID = 0 */ + cfgchip2 |= CFGCHIP2_FORCE_HOST; + break; +#endif +#ifdef CONFIG_USB_GADGET_MUSB_HDRC + case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */ + cfgchip2 |= CFGCHIP2_FORCE_DEVICE; + break; +#endif +#ifdef CONFIG_USB_MUSB_OTG + case MUSB_OTG: /* Don't override the VBUS/ID comparators */ + cfgchip2 |= CFGCHIP2_NO_OVERRIDE; + break; +#endif + default: + DBG(2, "Trying to set unsupported mode %u\n", musb_mode); + } + + __raw_writel(cfgchip2, CFGCHIP2); + return 0; +} + +int __init musb_platform_init(struct musb *musb, void *board_data) +{ + void __iomem *reg_base = musb->ctrl_base; + u32 rev; + + musb->mregs += DA8XX_MENTOR_CORE_OFFSET; + + clk_enable(musb->clock); + + /* Returns zero if e.g. not clocked */ + rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG); + if (!rev) + goto fail; + + usb_nop_xceiv_register(); + musb->xceiv = otg_get_transceiver(); + if (!musb->xceiv) + goto fail; + + if (is_host_enabled(musb)) + setup_timer(&otg_workaround, otg_timer, (unsigned long)musb); + + musb->board_set_vbus = da8xx_set_vbus; + + /* Reset the controller */ + musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK); + + /* Start the on-chip PHY and its PLL. */ + phy_on(); + + msleep(5); + + /* NOTE: IRQs are in mixed mode, not bypass to pure MUSB */ + pr_debug("DA8xx OTG revision %08x, PHY %03x, control %02x\n", + rev, __raw_readl(CFGCHIP2), + musb_readb(reg_base, DA8XX_USB_CTRL_REG)); + + musb->isr = da8xx_interrupt; + return 0; +fail: + clk_disable(musb->clock); + return -ENODEV; +} + +int musb_platform_exit(struct musb *musb) +{ + if (is_host_enabled(musb)) + del_timer_sync(&otg_workaround); + + phy_off(); + + otg_put_transceiver(musb->xceiv); + usb_nop_xceiv_unregister(); + + clk_disable(musb->clock); + + return 0; +} diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 91d67794e350..2a8236216dc7 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -599,6 +599,7 @@ extern void musb_hnp_stop(struct musb *musb); extern int musb_platform_set_mode(struct musb *musb, u8 musb_mode); #if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN) || \ + defined(CONFIG_ARCH_DAVINCI_DA8XX) || \ defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ defined(CONFIG_ARCH_OMAP4) extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout); From f11d893de444965dfd3e55f726533ae1df5c6471 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 24 Sep 2010 13:44:04 +0300 Subject: [PATCH 066/141] usb: musb: support ISO high bandwidth for gadget mode This patch has been tested OK on beagle B5 board and use usbtest #15 and #16 as testcase. Signed-off-by: Ming Lei Reviewed-by: Sergei Shtylyov Cc: David Brownell Cc: Anand Gadiyar Cc: Mike Frysinger Cc: Sergei Shtylyov Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget.c | 49 +++++++++++++++++++++++++--------- drivers/usb/musb/musb_gadget.h | 2 ++ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index ecd5f8cffcbf..f497586e36ec 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -337,13 +337,15 @@ static void txstate(struct musb *musb, struct musb_request *req) csr |= (MUSB_TXCSR_DMAENAB | MUSB_TXCSR_MODE); /* against programming guide */ - } else - csr |= (MUSB_TXCSR_AUTOSET - | MUSB_TXCSR_DMAENAB + } else { + csr |= (MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE); - + if (!musb_ep->hb_mult) + csr |= MUSB_TXCSR_AUTOSET; + } csr &= ~MUSB_TXCSR_P_UNDERRUN; + musb_writew(epio, MUSB_TXCSR, csr); } } @@ -643,7 +645,8 @@ static void rxstate(struct musb *musb, struct musb_request *req) */ csr |= MUSB_RXCSR_DMAENAB; - csr |= MUSB_RXCSR_AUTOCLEAR; + if (!musb_ep->hb_mult) + csr |= MUSB_RXCSR_AUTOCLEAR; #ifdef USE_MODE1 /* csr |= MUSB_RXCSR_DMAMODE; */ @@ -875,9 +878,25 @@ static int musb_gadget_enable(struct usb_ep *ep, /* REVISIT this rules out high bandwidth periodic transfers */ tmp = le16_to_cpu(desc->wMaxPacketSize); - if (tmp & ~0x07ff) - goto fail; - musb_ep->packet_sz = tmp; + if (tmp & ~0x07ff) { + int ok; + + if (usb_endpoint_dir_in(desc)) + ok = musb->hb_iso_tx; + else + ok = musb->hb_iso_rx; + + if (!ok) { + DBG(4, "%s: not support ISO high bandwidth\n", __func__); + goto fail; + } + musb_ep->hb_mult = (tmp >> 11) & 3; + } else { + musb_ep->hb_mult = 0; + } + + musb_ep->packet_sz = tmp & 0x7ff; + tmp = musb_ep->packet_sz * (musb_ep->hb_mult + 1); /* enable the interrupts for the endpoint, set the endpoint * packet size (or fail), set the mode, clear the fifo @@ -890,8 +909,11 @@ static int musb_gadget_enable(struct usb_ep *ep, musb_ep->is_in = 1; if (!musb_ep->is_in) goto fail; - if (tmp > hw_ep->max_packet_sz_tx) + + if (tmp > hw_ep->max_packet_sz_tx) { + DBG(4, "%s: packet size beyond hw fifo size\n", __func__); goto fail; + } int_txe |= (1 << epnum); musb_writew(mbase, MUSB_INTRTXE, int_txe); @@ -906,7 +928,7 @@ static int musb_gadget_enable(struct usb_ep *ep, if (musb->hwvers < MUSB_HWVERS_2000) musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx); else - musb_writew(regs, MUSB_TXMAXP, tmp); + musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11)); csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG; if (musb_readw(regs, MUSB_TXCSR) @@ -927,8 +949,11 @@ static int musb_gadget_enable(struct usb_ep *ep, musb_ep->is_in = 0; if (musb_ep->is_in) goto fail; - if (tmp > hw_ep->max_packet_sz_rx) + + if (tmp > hw_ep->max_packet_sz_rx) { + DBG(4, "%s: packet size beyond hw fifo size\n", __func__); goto fail; + } int_rxe |= (1 << epnum); musb_writew(mbase, MUSB_INTRRXE, int_rxe); @@ -942,7 +967,7 @@ static int musb_gadget_enable(struct usb_ep *ep, if (musb->hwvers < MUSB_HWVERS_2000) musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_rx); else - musb_writew(regs, MUSB_RXMAXP, tmp); + musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11)); /* force shared fifo to OUT-only mode */ if (hw_ep->is_shared_fifo) { diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h index 572b1da7f2dc..dec8dc008191 100644 --- a/drivers/usb/musb/musb_gadget.h +++ b/drivers/usb/musb/musb_gadget.h @@ -79,6 +79,8 @@ struct musb_ep { /* true if lock must be dropped but req_list may not be advanced */ u8 busy; + + u8 hb_mult; }; static inline struct musb_ep *to_musb_ep(struct usb_ep *ep) From 6587cc0f30cd2f27cf0677e470f18792925a23a4 Mon Sep 17 00:00:00 2001 From: Anil Shetty Date: Fri, 24 Sep 2010 13:44:05 +0300 Subject: [PATCH 067/141] usb: musb: musbhsdma: increase max_len to 1MB MUSB's DMA controller max channel length was set to 64k. Transfer length greater than this max value is being truncated. Signed-off-by: Anil Shetty Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musbhsdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 6dc107f25245..6f771af5cbdb 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -91,7 +91,7 @@ static struct dma_channel *dma_channel_allocate(struct dma_controller *c, channel = &(musb_channel->channel); channel->private_data = musb_channel; channel->status = MUSB_DMA_STATUS_FREE; - channel->max_len = 0x10000; + channel->max_len = 0x100000; /* Tx => mode 1; Rx => mode 0 */ channel->desired_mode = transmit; channel->actual_len = 0; From 496dda704bca1208e08773ba39b29a69536f5381 Mon Sep 17 00:00:00 2001 From: Maulik Mankad Date: Fri, 24 Sep 2010 13:44:06 +0300 Subject: [PATCH 068/141] usb: musb: host: unmap the buffer for PIO data transfers The USB stack maps the buffer for DMA if the controller supports DMA. MUSB controller can perform DMA as well as PIO transfers. The buffer needs to be unmapped before CPU can perform PIO data transfers. Export unmap_urb_for_dma() so that drivers can perform the DMA unmapping in a sane way. Signed-off-by: Maulik Mankad Acked-by: Alan Stern Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 3 ++- drivers/usb/musb/musb_host.c | 5 +++++ include/linux/usb/hcd.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 5cca00a6d09d..cb2d894321da 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1263,7 +1263,7 @@ static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle, *dma_handle = 0; } -static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) +void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) { enum dma_data_direction dir; @@ -1307,6 +1307,7 @@ static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) URB_DMA_MAP_SG | URB_DMA_MAP_PAGE | URB_DMA_MAP_SINGLE | URB_MAP_LOCAL); } +EXPORT_SYMBOL_GPL(unmap_urb_for_dma); static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 9e65c47cc98b..62e39fc57211 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "musb_core.h" #include "musb_host.h" @@ -1332,6 +1333,8 @@ void musb_host_tx(struct musb *musb, u8 epnum) */ if (length > qh->maxpacket) length = qh->maxpacket; + /* Unmap the buffer so that CPU can use it */ + unmap_urb_for_dma(musb_to_hcd(musb), urb); musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset); qh->segsize = length; @@ -1752,6 +1755,8 @@ void musb_host_rx(struct musb *musb, u8 epnum) #endif /* Mentor DMA */ if (!dma) { + /* Unmap the buffer so that CPU can use it */ + unmap_urb_for_dma(musb_to_hcd(musb), urb); done = musb_host_packet_rx(musb, urb, epnum, iso_err); DBG(6, "read %spacket\n", done ? "last " : ""); diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 3b571f1ffbb3..fe89f7c298aa 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -329,6 +329,7 @@ extern int usb_hcd_submit_urb(struct urb *urb, gfp_t mem_flags); extern int usb_hcd_unlink_urb(struct urb *urb, int status); extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status); +extern void unmap_urb_for_dma(struct usb_hcd *, struct urb *); extern void usb_hcd_flush_endpoint(struct usb_device *udev, struct usb_host_endpoint *ep); extern void usb_hcd_disable_endpoint(struct usb_device *udev, From ae9b2ad2eea729b907ef5dd5e25d1ff8443d03fc Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Fri, 24 Sep 2010 13:44:07 +0300 Subject: [PATCH 069/141] usb: musb: Change to direct addr in context save/restore Since not all platforms are using the same offset 0x10 in musb_save/restore_context() eg Blackfin the offset is 0x40, Change the indexed address to direct. Signed-off-by: Bob Liu Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 46 +++++++++++++++++------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 540c766c4f86..d4f18bbc8f8f 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2266,6 +2266,7 @@ void musb_save_context(struct musb *musb) { int i; void __iomem *musb_base = musb->mregs; + void __iomem *epio; if (is_host_enabled(musb)) { musb_context.frame = musb_readw(musb_base, MUSB_FRAME); @@ -2279,16 +2280,16 @@ void musb_save_context(struct musb *musb) musb_context.index = musb_readb(musb_base, MUSB_INDEX); musb_context.devctl = musb_readb(musb_base, MUSB_DEVCTL); - for (i = 0; i < MUSB_C_NUM_EPS; ++i) { - musb_writeb(musb_base, MUSB_INDEX, i); + for (i = 0; i < musb->config->num_eps; ++i) { + epio = musb->endpoints[i].regs; musb_context.index_regs[i].txmaxp = - musb_readw(musb_base, 0x10 + MUSB_TXMAXP); + musb_readw(epio, MUSB_TXMAXP); musb_context.index_regs[i].txcsr = - musb_readw(musb_base, 0x10 + MUSB_TXCSR); + musb_readw(epio, MUSB_TXCSR); musb_context.index_regs[i].rxmaxp = - musb_readw(musb_base, 0x10 + MUSB_RXMAXP); + musb_readw(epio, MUSB_RXMAXP); musb_context.index_regs[i].rxcsr = - musb_readw(musb_base, 0x10 + MUSB_RXCSR); + musb_readw(epio, MUSB_RXCSR); if (musb->dyn_fifo) { musb_context.index_regs[i].txfifoadd = @@ -2302,13 +2303,13 @@ void musb_save_context(struct musb *musb) } if (is_host_enabled(musb)) { musb_context.index_regs[i].txtype = - musb_readb(musb_base, 0x10 + MUSB_TXTYPE); + musb_readb(epio, MUSB_TXTYPE); musb_context.index_regs[i].txinterval = - musb_readb(musb_base, 0x10 + MUSB_TXINTERVAL); + musb_readb(epio, MUSB_TXINTERVAL); musb_context.index_regs[i].rxtype = - musb_readb(musb_base, 0x10 + MUSB_RXTYPE); + musb_readb(epio, MUSB_RXTYPE); musb_context.index_regs[i].rxinterval = - musb_readb(musb_base, 0x10 + MUSB_RXINTERVAL); + musb_readb(epio, MUSB_RXINTERVAL); musb_context.index_regs[i].txfunaddr = musb_read_txfunaddr(musb_base, i); @@ -2326,8 +2327,6 @@ void musb_save_context(struct musb *musb) } } - musb_writeb(musb_base, MUSB_INDEX, musb_context.index); - musb_platform_save_context(musb, &musb_context); } @@ -2336,6 +2335,7 @@ void musb_restore_context(struct musb *musb) int i; void __iomem *musb_base = musb->mregs; void __iomem *ep_target_regs; + void __iomem *epio; musb_platform_restore_context(musb, &musb_context); @@ -2350,15 +2350,15 @@ void musb_restore_context(struct musb *musb) musb_writeb(musb_base, MUSB_INTRUSBE, musb_context.intrusbe); musb_writeb(musb_base, MUSB_DEVCTL, musb_context.devctl); - for (i = 0; i < MUSB_C_NUM_EPS; ++i) { - musb_writeb(musb_base, MUSB_INDEX, i); - musb_writew(musb_base, 0x10 + MUSB_TXMAXP, + for (i = 0; i < musb->config->num_eps; ++i) { + epio = musb->endpoints[i].regs; + musb_writew(epio, MUSB_TXMAXP, musb_context.index_regs[i].txmaxp); - musb_writew(musb_base, 0x10 + MUSB_TXCSR, + musb_writew(epio, MUSB_TXCSR, musb_context.index_regs[i].txcsr); - musb_writew(musb_base, 0x10 + MUSB_RXMAXP, + musb_writew(epio, MUSB_RXMAXP, musb_context.index_regs[i].rxmaxp); - musb_writew(musb_base, 0x10 + MUSB_RXCSR, + musb_writew(epio, MUSB_RXCSR, musb_context.index_regs[i].rxcsr); if (musb->dyn_fifo) { @@ -2373,13 +2373,13 @@ void musb_restore_context(struct musb *musb) } if (is_host_enabled(musb)) { - musb_writeb(musb_base, 0x10 + MUSB_TXTYPE, + musb_writeb(epio, MUSB_TXTYPE, musb_context.index_regs[i].txtype); - musb_writeb(musb_base, 0x10 + MUSB_TXINTERVAL, + musb_writeb(epio, MUSB_TXINTERVAL, musb_context.index_regs[i].txinterval); - musb_writeb(musb_base, 0x10 + MUSB_RXTYPE, + musb_writeb(epio, MUSB_RXTYPE, musb_context.index_regs[i].rxtype); - musb_writeb(musb_base, 0x10 + MUSB_RXINTERVAL, + musb_writeb(epio, MUSB_RXINTERVAL, musb_context.index_regs[i].rxinterval); musb_write_txfunaddr(musb_base, i, @@ -2400,8 +2400,6 @@ void musb_restore_context(struct musb *musb) musb_context.index_regs[i].rxhubport); } } - - musb_writeb(musb_base, MUSB_INDEX, musb_context.index); } static int musb_suspend(struct device *dev) From f8afbf7f2bf3cee0f4fff7cb753ecc9f583972c3 Mon Sep 17 00:00:00 2001 From: "T. S., Anil Kumar" Date: Fri, 24 Sep 2010 13:44:09 +0300 Subject: [PATCH 070/141] usb: musb: host: support DMA transfers greater than max channel length Add support for MUSB Host DMA transfers greater than max channel length, so that such transfers won't be truncated. Signed-off-by: Anil Shetty Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_host.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 62e39fc57211..4d5bcb4e14d2 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1120,6 +1120,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) u32 status = 0; void __iomem *mbase = musb->mregs; struct dma_channel *dma; + bool transfer_pending = false; musb_ep_select(mbase, epnum); tx_csr = musb_readw(epio, MUSB_TXCSR); @@ -1280,7 +1281,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) offset = d->offset; length = d->length; } - } else if (dma) { + } else if (dma && urb->transfer_buffer_length == qh->offset) { done = true; } else { /* see if we need to send more data, or ZLP */ @@ -1293,6 +1294,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) if (!done) { offset = qh->offset; length = urb->transfer_buffer_length - offset; + transfer_pending = true; } } } @@ -1312,7 +1314,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) urb->actual_length = qh->offset; musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT); return; - } else if (usb_pipeisoc(pipe) && dma) { + } else if ((usb_pipeisoc(pipe) || transfer_pending) && dma) { if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb, offset, length)) { if (is_cppi_enabled() || tusb_dma_omap()) From 2f8d5cd6bcf814411ec356bcdbc666d07bbc6026 Mon Sep 17 00:00:00 2001 From: Jon Povey Date: Fri, 24 Sep 2010 13:44:10 +0300 Subject: [PATCH 071/141] USB: musb: suppress warning about unused flags Wrap flags with uninitialized_var() to suppress this: drivers/usb/musb/cppi_dma.c:1158: warning: 'flags' may be used uninitialized in this function Signed-off-by: Jon Povey Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/cppi_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 5ab5bb89bae3..f5a65ff0ac2b 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -1156,7 +1156,7 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id) struct musb_hw_ep *hw_ep = NULL; u32 rx, tx; int i, index; - unsigned long flags; + unsigned long uninitialized_var(flags); cppi = container_of(musb->dma_controller, struct cppi, controller); if (cppi->irq) From 434678685407e045ffb246df059c486fc0a16e75 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 24 Sep 2010 13:44:12 +0300 Subject: [PATCH 072/141] usb: musb: gadget: kill unreachable code in musb_g_rx() musb_g_rx() always returns if next_request() call yields NULL, so the DBG() near the function's end can never be invoked. Remove it along with unneeded 'return'; also remove the duplicate 'request' check... Signed-off-by: Sergei Shtylyov Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index f497586e36ec..6a8c061b66f1 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -775,7 +775,7 @@ void musb_g_rx(struct musb *musb, u8 epnum) musb_writew(epio, MUSB_RXCSR, csr); DBG(3, "%s iso overrun on %p\n", musb_ep->name, request); - if (request && request->status == -EINPROGRESS) + if (request->status == -EINPROGRESS) request->status = -EOVERFLOW; } if (csr & MUSB_RXCSR_INCOMPRX) { @@ -828,14 +828,8 @@ void musb_g_rx(struct musb *musb, u8 epnum) return; } - /* analyze request if the ep is hot */ - if (request) - rxstate(musb, to_musb_request(request)); - else - DBG(3, "packet waiting for %s%s request\n", - musb_ep->desc ? "" : "inactive ", - musb_ep->end_point.name); - return; + /* Analyze request */ + rxstate(musb, to_musb_request(request)); } /* ------------------------------------------------------------ */ From a6038ee76a29ea31f8aae4eb6c419794c739e077 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Fri, 24 Sep 2010 13:44:13 +0300 Subject: [PATCH 073/141] usb: musb: ignore spurious SESSREQ interrupts This will ignore any SESSREQ interrupt if musb is B state. Charger detection may cause spurious SESSREQ interrupts. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index d4f18bbc8f8f..472b2a7e7896 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -550,6 +550,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, if (int_usb & MUSB_INTR_SESSREQ) { void __iomem *mbase = musb->mregs; + if (devctl & MUSB_DEVCTL_BDEVICE) { + DBG(3, "SessReq while on B state\n"); + return IRQ_HANDLED; + } + DBG(1, "SESSION_REQUEST (%s)\n", otg_state_string(musb)); /* IRQ arrives from ID pin sense or (later, if VBUS power From e7379aaa5ca12f9e011eb5a6bcba88e9bbbfbf87 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 24 Sep 2010 13:44:14 +0300 Subject: [PATCH 074/141] usb: musb: gadget: fix ZLP sending in musb_g_tx(v1) This patch fixes the problem reported by Sergei: >how come? we need to send ZLP before giving back the request. >Well, look at the code ionce again. We need to send ZLP *after* >request->actual == request->length, but as the check is inserted >after the ZLP send, ZLP *may* be sent once the first DMA completes, >not the last. The patch also has been discussed on the link below: http://marc.info/?t=128454814900001&r=1&w=2 Signed-off-by: Ming Lei Reported-by: Sergei Shtylyov Cc: David Brownell Cc: Anand Gadiyar Cc: Mike Frysinger Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget.c | 59 +++++++++++++++++----------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 6a8c061b66f1..3f1cc5a8381f 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -477,40 +477,39 @@ void musb_g_tx(struct musb *musb, u8 epnum) epnum, csr, musb_ep->dma->actual_len, request); } - if (is_dma || request->actual == request->length) { - /* - * First, maybe a terminating short packet. Some DMA - * engines might handle this by themselves. - */ - if ((request->zero && request->length - && request->length % musb_ep->packet_sz == 0) + /* + * First, maybe a terminating short packet. Some DMA + * engines might handle this by themselves. + */ + if ((request->zero && request->length + && (request->length % musb_ep->packet_sz == 0) + && (request->actual == request->length)) #ifdef CONFIG_USB_INVENTRA_DMA - || (is_dma && (!dma->desired_mode || - (request->actual & - (musb_ep->packet_sz - 1)))) + || (is_dma && (!dma->desired_mode || + (request->actual & + (musb_ep->packet_sz - 1)))) #endif - ) { - /* - * On DMA completion, FIFO may not be - * available yet... - */ - if (csr & MUSB_TXCSR_TXPKTRDY) - return; + ) { + /* + * On DMA completion, FIFO may not be + * available yet... + */ + if (csr & MUSB_TXCSR_TXPKTRDY) + return; - DBG(4, "sending zero pkt\n"); - musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE - | MUSB_TXCSR_TXPKTRDY); - request->zero = 0; - } + DBG(4, "sending zero pkt\n"); + musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE + | MUSB_TXCSR_TXPKTRDY); + request->zero = 0; + } - if (request->actual == request->length) { - musb_g_giveback(musb_ep, request, 0); - request = musb_ep->desc ? next_request(musb_ep) : NULL; - if (!request) { - DBG(4, "%s idle now\n", - musb_ep->end_point.name); - return; - } + if (request->actual == request->length) { + musb_g_giveback(musb_ep, request, 0); + request = musb_ep->desc ? next_request(musb_ep) : NULL; + if (!request) { + DBG(4, "%s idle now\n", + musb_ep->end_point.name); + return; } } From e0c43476c12db99e20066151d0c49aa76b34e50d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 24 Sep 2010 13:44:15 +0300 Subject: [PATCH 075/141] usb: musb: gadget: only enable AUTOCLEAR in double buffered case commit 633ba7876b96ec339ef685357e2f7c60b5a8ce85 broke g_file_storage functionality by enabling AUTOCLEAR on all cases without caring for all gadget drivers. This patch will only enable AUTOCLEAR if our endpoint's FIFO was configured with double buffering support. Note this is not a complete fix, double buffered case still doesn't work always, but that hasn't been working for quite some time. Other than reverting the entire commit and breaking testusb with double buffered case again, I decided it was better to fix the single buffered case and spend more time fixing double buffered case properly. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 3f1cc5a8381f..5d815049cbaa 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -644,7 +644,8 @@ static void rxstate(struct musb *musb, struct musb_request *req) */ csr |= MUSB_RXCSR_DMAENAB; - if (!musb_ep->hb_mult) + if (!musb_ep->hb_mult && + musb_ep->hw_ep->rx_double_buffered) csr |= MUSB_RXCSR_AUTOCLEAR; #ifdef USE_MODE1 /* csr |= MUSB_RXCSR_DMAMODE; */ From 25013315678c78091a7826be7097fa2b60e30aac Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 24 Sep 2010 12:17:33 -0700 Subject: [PATCH 076/141] usb: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/Makefile | 4 +--- drivers/usb/core/Makefile | 4 +--- drivers/usb/gadget/Makefile | 4 +--- drivers/usb/host/Makefile | 4 +--- drivers/usb/misc/Makefile | 4 +--- drivers/usb/musb/Makefile | 4 +--- drivers/usb/storage/Makefile | 2 +- drivers/usb/wusbcore/Makefile | 4 +--- 8 files changed, 8 insertions(+), 22 deletions(-) diff --git a/drivers/usb/atm/Makefile b/drivers/usb/atm/Makefile index 4c4a776ab1cd..d40a126e47a3 100644 --- a/drivers/usb/atm/Makefile +++ b/drivers/usb/atm/Makefile @@ -8,6 +8,4 @@ obj-$(CONFIG_USB_UEAGLEATM) += ueagle-atm.o obj-$(CONFIG_USB_ATM) += usbatm.o obj-$(CONFIG_USB_XUSBATM) += xusbatm.o -ifeq ($(CONFIG_USB_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index ec16e6029905..17c8e2d2a07d 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile @@ -16,6 +16,4 @@ endif obj-$(CONFIG_USB) += usbcore.o -ifeq ($(CONFIG_USB_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 27283df37d09..c68200536500 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -1,9 +1,7 @@ # # USB peripheral controller drivers # -ifeq ($(CONFIG_USB_GADGET_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o obj-$(CONFIG_USB_NET2280) += net2280.o diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index b6315aa47f7a..f0414429502f 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -2,9 +2,7 @@ # Makefile for USB Host Controller Drivers # -ifeq ($(CONFIG_USB_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG isp1760-objs := isp1760-hcd.o isp1760-if.o fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \ diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index d203ff6870e4..d2633c035626 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -26,6 +26,4 @@ obj-$(CONFIG_USB_YUREX) += yurex.o obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ -ifeq ($(CONFIG_USB_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index f664ecfa21c4..16aaae28714d 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -78,6 +78,4 @@ endif # Debugging -ifeq ($(CONFIG_USB_MUSB_DEBUG),y) - EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_USB_MUSB_DEBUG) := -DDEBUG diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 0332aa5df24f..65dbf652487e 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -5,7 +5,7 @@ # Rewritten to use lists instead of if-statements. # -EXTRA_CFLAGS := -Idrivers/scsi +ccflags-y := -Idrivers/scsi obj-$(CONFIG_USB_UAS) += uas.o obj-$(CONFIG_USB_STORAGE) += usb-storage.o diff --git a/drivers/usb/wusbcore/Makefile b/drivers/usb/wusbcore/Makefile index 75f1ade66258..f0d8045c802e 100644 --- a/drivers/usb/wusbcore/Makefile +++ b/drivers/usb/wusbcore/Makefile @@ -21,6 +21,4 @@ wusb-wa-objs := wa-hc.o \ wa-rpipe.o \ wa-xfer.o -ifeq ($(CONFIG_USB_WUSB_CBAF_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_USB_WUSB_CBAF_DEBUG) := -DDEBUG From 7893afc035590383a14b176c1497cba984276ef4 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Sun, 26 Sep 2010 23:35:05 -0300 Subject: [PATCH 077/141] USB: cdc-acm: fix code indentation Signed-off-by: Otavio Salvador Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index bc62fae0680f..d6ede989ff22 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1614,7 +1614,7 @@ static const struct usb_device_id acm_ids[] = { /* Support Lego NXT using pbLua firmware */ { USB_DEVICE(0x0694, 0xff00), .driver_info = NOT_A_MODEM, - }, + }, /* control interfaces without any protocol set */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, From 748eee0986f0d51c7bc39f194d515a8d8248ebdd Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Mon, 27 Sep 2010 15:17:18 +0300 Subject: [PATCH 078/141] USB: Add more empty functions in otg.h Add empty functions for get/put transceiver functions too, so that drivers that optionally use them can call them without worrying that they might not exist, eliminating ifdefs. Signed-off-by: Grazvydas Ignotas Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/otg.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 545cba73ccaf..0a5b3711e502 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -164,8 +164,19 @@ otg_shutdown(struct otg_transceiver *otg) } /* for usb host and peripheral controller drivers */ +#ifdef CONFIG_USB_OTG_UTILS extern struct otg_transceiver *otg_get_transceiver(void); extern void otg_put_transceiver(struct otg_transceiver *); +#else +static inline struct otg_transceiver *otg_get_transceiver(void) +{ + return NULL; +} + +static inline void otg_put_transceiver(struct otg_transceiver *x) +{ +} +#endif /* Context: can sleep */ static inline int From 99c1e4f89d1033444ce4d0c064bd2826e81c3775 Mon Sep 17 00:00:00 2001 From: Rainer Keller Date: Tue, 28 Sep 2010 12:27:43 +0200 Subject: [PATCH 079/141] USB: add PID for FTDI based OpenDCC hardware The OpenDCC project is developing a new hardware. This patch adds its PID to the list of known FTDI devices. The PID can be found at http://www.opendcc.de/elektronik/usb/opendcc_usb.html Signed-off-by: Rainer Keller Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 42fea29637b3..e128f9125f71 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -177,6 +177,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_SNIFFER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) }, { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 02659f5c79e2..517d01435abb 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -61,6 +61,7 @@ #define FTDI_OPENDCC_SNIFFER_PID 0xBFD9 #define FTDI_OPENDCC_THROTTLE_PID 0xBFDA #define FTDI_OPENDCC_GATEWAY_PID 0xBFDB +#define FTDI_OPENDCC_GBM_PID 0xBFDC /* * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com) From 126512e3f274802ca65ebeca8660237f0361ad48 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Tue, 28 Sep 2010 20:55:20 +0200 Subject: [PATCH 080/141] USB: add platform glue driver for FSL USB DR controller Replace FSL USB platform code by simple platform driver for creation of FSL USB platform devices. The driver creates platform devices based on the information from USB nodes in the flat device tree. This is the replacement for old arch fsl_soc usb code removed by this patch. The driver uses usual of-style binding, available EHCI-HCD and UDC drivers can be bound to the created devices. The new of-style driver additionaly instantiates USB OTG platform device, as the appropriate USB OTG driver will be added soon. Signed-off-by: Anatolij Gustschin Cc: Kumar Gala Cc: Grant Likely Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/sysdev/fsl_soc.c | 163 ----------------------- drivers/usb/gadget/Kconfig | 1 + drivers/usb/host/Kconfig | 4 + drivers/usb/host/Makefile | 1 + drivers/usb/host/fsl-mph-dr-of.c | 219 +++++++++++++++++++++++++++++++ 5 files changed, 225 insertions(+), 163 deletions(-) create mode 100644 drivers/usb/host/fsl-mph-dr-of.c diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index b91f7acdda6f..49a51f134c51 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -209,169 +209,6 @@ static int __init of_add_fixed_phys(void) arch_initcall(of_add_fixed_phys); #endif /* CONFIG_FIXED_PHY */ -static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type) -{ - if (!phy_type) - return FSL_USB2_PHY_NONE; - if (!strcasecmp(phy_type, "ulpi")) - return FSL_USB2_PHY_ULPI; - if (!strcasecmp(phy_type, "utmi")) - return FSL_USB2_PHY_UTMI; - if (!strcasecmp(phy_type, "utmi_wide")) - return FSL_USB2_PHY_UTMI_WIDE; - if (!strcasecmp(phy_type, "serial")) - return FSL_USB2_PHY_SERIAL; - - return FSL_USB2_PHY_NONE; -} - -static int __init fsl_usb_of_init(void) -{ - struct device_node *np; - unsigned int i = 0; - struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL, - *usb_dev_dr_client = NULL; - int ret; - - for_each_compatible_node(np, NULL, "fsl-usb2-mph") { - struct resource r[2]; - struct fsl_usb2_platform_data usb_data; - const unsigned char *prop = NULL; - - memset(&r, 0, sizeof(r)); - memset(&usb_data, 0, sizeof(usb_data)); - - ret = of_address_to_resource(np, 0, &r[0]); - if (ret) - goto err; - - of_irq_to_resource(np, 0, &r[1]); - - usb_dev_mph = - platform_device_register_simple("fsl-ehci", i, r, 2); - if (IS_ERR(usb_dev_mph)) { - ret = PTR_ERR(usb_dev_mph); - goto err; - } - - usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL; - usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask; - - usb_data.operating_mode = FSL_USB2_MPH_HOST; - - prop = of_get_property(np, "port0", NULL); - if (prop) - usb_data.port_enables |= FSL_USB2_PORT0_ENABLED; - - prop = of_get_property(np, "port1", NULL); - if (prop) - usb_data.port_enables |= FSL_USB2_PORT1_ENABLED; - - prop = of_get_property(np, "phy_type", NULL); - usb_data.phy_mode = determine_usb_phy(prop); - - ret = - platform_device_add_data(usb_dev_mph, &usb_data, - sizeof(struct - fsl_usb2_platform_data)); - if (ret) - goto unreg_mph; - i++; - } - - for_each_compatible_node(np, NULL, "fsl-usb2-dr") { - struct resource r[2]; - struct fsl_usb2_platform_data usb_data; - const unsigned char *prop = NULL; - - if (!of_device_is_available(np)) - continue; - - memset(&r, 0, sizeof(r)); - memset(&usb_data, 0, sizeof(usb_data)); - - ret = of_address_to_resource(np, 0, &r[0]); - if (ret) - goto unreg_mph; - - of_irq_to_resource(np, 0, &r[1]); - - prop = of_get_property(np, "dr_mode", NULL); - - if (!prop || !strcmp(prop, "host")) { - usb_data.operating_mode = FSL_USB2_DR_HOST; - usb_dev_dr_host = platform_device_register_simple( - "fsl-ehci", i, r, 2); - if (IS_ERR(usb_dev_dr_host)) { - ret = PTR_ERR(usb_dev_dr_host); - goto err; - } - } else if (prop && !strcmp(prop, "peripheral")) { - usb_data.operating_mode = FSL_USB2_DR_DEVICE; - usb_dev_dr_client = platform_device_register_simple( - "fsl-usb2-udc", i, r, 2); - if (IS_ERR(usb_dev_dr_client)) { - ret = PTR_ERR(usb_dev_dr_client); - goto err; - } - } else if (prop && !strcmp(prop, "otg")) { - usb_data.operating_mode = FSL_USB2_DR_OTG; - usb_dev_dr_host = platform_device_register_simple( - "fsl-ehci", i, r, 2); - if (IS_ERR(usb_dev_dr_host)) { - ret = PTR_ERR(usb_dev_dr_host); - goto err; - } - usb_dev_dr_client = platform_device_register_simple( - "fsl-usb2-udc", i, r, 2); - if (IS_ERR(usb_dev_dr_client)) { - ret = PTR_ERR(usb_dev_dr_client); - goto err; - } - } else { - ret = -EINVAL; - goto err; - } - - prop = of_get_property(np, "phy_type", NULL); - usb_data.phy_mode = determine_usb_phy(prop); - - if (usb_dev_dr_host) { - usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL; - usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host-> - dev.coherent_dma_mask; - if ((ret = platform_device_add_data(usb_dev_dr_host, - &usb_data, sizeof(struct - fsl_usb2_platform_data)))) - goto unreg_dr; - } - if (usb_dev_dr_client) { - usb_dev_dr_client->dev.coherent_dma_mask = 0xffffffffUL; - usb_dev_dr_client->dev.dma_mask = &usb_dev_dr_client-> - dev.coherent_dma_mask; - if ((ret = platform_device_add_data(usb_dev_dr_client, - &usb_data, sizeof(struct - fsl_usb2_platform_data)))) - goto unreg_dr; - } - i++; - } - return 0; - -unreg_dr: - if (usb_dev_dr_host) - platform_device_unregister(usb_dev_dr_host); - if (usb_dev_dr_client) - platform_device_unregister(usb_dev_dr_client); -unreg_mph: - if (usb_dev_mph) - platform_device_unregister(usb_dev_mph); -err: - return ret; -} - -arch_initcall(fsl_usb_of_init); - #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) static __be32 __iomem *rstcr; diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index fab765d387b8..0fe5bc876fa5 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -158,6 +158,7 @@ config USB_GADGET_FSL_USB2 boolean "Freescale Highspeed USB DR Peripheral Controller" depends on FSL_SOC || ARCH_MXC select USB_GADGET_DUALSPEED + select USB_FSL_MPH_DR_OF help Some of Freescale PowerPC processors have a High Speed Dual-Role(DR) USB controller, which supports device mode. diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 2d926cec0725..f3a90b0fc422 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -112,10 +112,14 @@ config XPS_USB_HCD_XILINX support both high speed and full speed devices, or high speed devices only. +config USB_FSL_MPH_DR_OF + tristate + config USB_EHCI_FSL bool "Support for Freescale on-chip EHCI USB controller" depends on USB_EHCI_HCD && FSL_SOC select USB_EHCI_ROOT_HUB_TT + select USB_FSL_MPH_DR_OF ---help--- Variation of ARC USB block used in some Freescale chips. diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index f0414429502f..19b3a30b1cdb 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -31,4 +31,5 @@ obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o +obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c new file mode 100644 index 000000000000..12db5d5cb0bc --- /dev/null +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -0,0 +1,219 @@ +/* + * Setup platform devices needed by the Freescale multi-port host + * and/or dual-role USB controller modules based on the description + * in flat device tree. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +struct fsl_usb2_dev_data { + char *dr_mode; /* controller mode */ + char *drivers[3]; /* drivers to instantiate for this mode */ + enum fsl_usb2_operating_modes op_mode; /* operating mode */ +}; + +struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = { + { + .dr_mode = "host", + .drivers = { "fsl-ehci", NULL, NULL, }, + .op_mode = FSL_USB2_DR_HOST, + }, + { + .dr_mode = "otg", + .drivers = { "fsl-usb2-otg", "fsl-ehci", "fsl-usb2-udc", }, + .op_mode = FSL_USB2_DR_OTG, + }, + { + .dr_mode = "peripheral", + .drivers = { "fsl-usb2-udc", NULL, NULL, }, + .op_mode = FSL_USB2_DR_DEVICE, + }, +}; + +struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np) +{ + const unsigned char *prop; + int i; + + prop = of_get_property(np, "dr_mode", NULL); + if (prop) { + for (i = 0; i < ARRAY_SIZE(dr_mode_data); i++) { + if (!strcmp(prop, dr_mode_data[i].dr_mode)) + return &dr_mode_data[i]; + } + } + pr_warn("%s: Invalid 'dr_mode' property, fallback to host mode\n", + np->full_name); + return &dr_mode_data[0]; /* mode not specified, use host */ +} + +static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type) +{ + if (!phy_type) + return FSL_USB2_PHY_NONE; + if (!strcasecmp(phy_type, "ulpi")) + return FSL_USB2_PHY_ULPI; + if (!strcasecmp(phy_type, "utmi")) + return FSL_USB2_PHY_UTMI; + if (!strcasecmp(phy_type, "utmi_wide")) + return FSL_USB2_PHY_UTMI_WIDE; + if (!strcasecmp(phy_type, "serial")) + return FSL_USB2_PHY_SERIAL; + + return FSL_USB2_PHY_NONE; +} + +struct platform_device * __devinit fsl_usb2_device_register( + struct platform_device *ofdev, + struct fsl_usb2_platform_data *pdata, + const char *name, int id) +{ + struct platform_device *pdev; + const struct resource *res = ofdev->resource; + unsigned int num = ofdev->num_resources; + int retval; + + pdev = platform_device_alloc(name, id); + if (!pdev) { + retval = -ENOMEM; + goto error; + } + + pdev->dev.parent = &ofdev->dev; + + pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask; + pdev->dev.dma_mask = &pdev->archdata.dma_mask; + *pdev->dev.dma_mask = *ofdev->dev.dma_mask; + + retval = platform_device_add_data(pdev, pdata, sizeof(*pdata)); + if (retval) + goto error; + + if (num) { + retval = platform_device_add_resources(pdev, res, num); + if (retval) + goto error; + } + + retval = platform_device_add(pdev); + if (retval) + goto error; + + return pdev; + +error: + platform_device_put(pdev); + return ERR_PTR(retval); +} + +static const struct of_device_id fsl_usb2_mph_dr_of_match[]; + +static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev) +{ + struct device_node *np = ofdev->dev.of_node; + struct platform_device *usb_dev; + struct fsl_usb2_platform_data data, *pdata; + struct fsl_usb2_dev_data *dev_data; + const struct of_device_id *match; + const unsigned char *prop; + static unsigned int idx; + int i; + + if (!of_device_is_available(np)) + return -ENODEV; + + match = of_match_device(fsl_usb2_mph_dr_of_match, &ofdev->dev); + if (!match) + return -ENODEV; + + pdata = &data; + if (match->data) + memcpy(pdata, match->data, sizeof(data)); + else + memset(pdata, 0, sizeof(data)); + + dev_data = get_dr_mode_data(np); + + if (of_device_is_compatible(np, "fsl-usb2-mph")) { + if (of_get_property(np, "port0", NULL)) + pdata->port_enables |= FSL_USB2_PORT0_ENABLED; + + if (of_get_property(np, "port1", NULL)) + pdata->port_enables |= FSL_USB2_PORT1_ENABLED; + + pdata->operating_mode = FSL_USB2_MPH_HOST; + } else { + /* setup mode selected in the device tree */ + pdata->operating_mode = dev_data->op_mode; + } + + prop = of_get_property(np, "phy_type", NULL); + pdata->phy_mode = determine_usb_phy(prop); + + for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) { + if (!dev_data->drivers[i]) + continue; + usb_dev = fsl_usb2_device_register(ofdev, pdata, + dev_data->drivers[i], idx); + if (IS_ERR(usb_dev)) { + dev_err(&ofdev->dev, "Can't register usb device\n"); + return PTR_ERR(usb_dev); + } + } + idx++; + return 0; +} + +static int __devexit __unregister_subdev(struct device *dev, void *d) +{ + platform_device_unregister(to_platform_device(dev)); + return 0; +} + +static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev) +{ + device_for_each_child(&ofdev->dev, NULL, __unregister_subdev); + return 0; +} + +static const struct of_device_id fsl_usb2_mph_dr_of_match[] = { + { .compatible = "fsl-usb2-mph", }, + { .compatible = "fsl-usb2-dr", }, + {}, +}; + +static struct platform_driver fsl_usb2_mph_dr_driver = { + .driver = { + .name = "fsl-usb2-mph-dr", + .owner = THIS_MODULE, + .of_match_table = fsl_usb2_mph_dr_of_match, + }, + .probe = fsl_usb2_mph_dr_of_probe, + .remove = __devexit_p(fsl_usb2_mph_dr_of_remove), +}; + +static int __init fsl_usb2_mph_dr_init(void) +{ + return platform_driver_register(&fsl_usb2_mph_dr_driver); +} +module_init(fsl_usb2_mph_dr_init); + +static void __exit fsl_usb2_mph_dr_exit(void) +{ + platform_driver_unregister(&fsl_usb2_mph_dr_driver); +} +module_exit(fsl_usb2_mph_dr_exit); + +MODULE_DESCRIPTION("FSL MPH DR OF devices driver"); +MODULE_AUTHOR("Anatolij Gustschin "); +MODULE_LICENSE("GPL"); From 230f7ede6c2f0e403f29e03e0251a470aa9350dd Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Tue, 28 Sep 2010 20:55:21 +0200 Subject: [PATCH 081/141] USB: add USB EHCI support for MPC5121 SoC Extends FSL EHCI platform driver glue layer to support MPC5121 USB controllers. MPC5121 Rev 2.0 silicon EHCI registers are in big endian format. The appropriate flags are set using the information in the platform data structure. MPC83xx system interface registers are not available on MPC512x, so the access to these registers is isolated in MPC512x case. Furthermore the USB controller clocks must be enabled before 512x register accesses which is done by providing platform specific init callback. The MPC512x internal USB PHY doesn't provide supply voltage. For boards using different power switches allow specifying DRVVBUS and PWR_FAULT signal polarity of the MPC5121 internal PHY using "fsl,invert-drvvbus" and "fsl,invert-pwr-fault" properties in the device tree USB nodes. Adds documentation for this new device tree bindings. Signed-off-by: Anatolij Gustschin Cc: Grant Likely Signed-off-by: Greg Kroah-Hartman --- .../powerpc/dts-bindings/fsl/usb.txt | 22 +++++ drivers/usb/Kconfig | 1 + drivers/usb/host/Kconfig | 6 +- drivers/usb/host/ehci-fsl.c | 99 +++++++++++++------ drivers/usb/host/ehci-fsl.h | 13 ++- drivers/usb/host/ehci-mem.c | 2 +- drivers/usb/host/fsl-mph-dr-of.c | 89 +++++++++++++++++ include/linux/fsl_devices.h | 15 +++ 8 files changed, 215 insertions(+), 32 deletions(-) diff --git a/Documentation/powerpc/dts-bindings/fsl/usb.txt b/Documentation/powerpc/dts-bindings/fsl/usb.txt index b00152402694..bd5723f0b67e 100644 --- a/Documentation/powerpc/dts-bindings/fsl/usb.txt +++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt @@ -8,6 +8,7 @@ and additions : Required properties : - compatible : Should be "fsl-usb2-mph" for multi port host USB controllers, or "fsl-usb2-dr" for dual role USB controllers + or "fsl,mpc5121-usb2-dr" for dual role USB controllers of MPC5121 - phy_type : For multi port host USB controllers, should be one of "ulpi", or "serial". For dual role USB controllers, should be one of "ulpi", "utmi", "utmi_wide", or "serial". @@ -33,6 +34,12 @@ Recommended properties : - interrupt-parent : the phandle for the interrupt controller that services interrupts for this device. +Optional properties : + - fsl,invert-drvvbus : boolean; for MPC5121 USB0 only. Indicates the + port power polarity of internal PHY signal DRVVBUS is inverted. + - fsl,invert-pwr-fault : boolean; for MPC5121 USB0 only. Indicates + the PWR_FAULT signal polarity is inverted. + Example multi port host USB controller device node : usb@22000 { compatible = "fsl-usb2-mph"; @@ -57,3 +64,18 @@ Example dual role USB controller device node : dr_mode = "otg"; phy = "ulpi"; }; + +Example dual role USB controller device node for MPC5121ADS: + + usb@4000 { + compatible = "fsl,mpc5121-usb2-dr"; + reg = <0x4000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = < &ipic >; + interrupts = <44 0x8>; + dr_mode = "otg"; + phy_type = "utmi_wide"; + fsl,invert-drvvbus; + fsl,invert-pwr-fault; + }; diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 4aa00e6e57ad..67eb3770868f 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -59,6 +59,7 @@ config USB_ARCH_HAS_OHCI config USB_ARCH_HAS_EHCI boolean default y if PPC_83xx + default y if PPC_MPC512x default y if SOC_AU1200 default y if ARCH_IXP4XX default y if ARCH_W90X900 diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index f3a90b0fc422..bf2e7d234533 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -93,12 +93,14 @@ config USB_EHCI_TT_NEWSCHED config USB_EHCI_BIG_ENDIAN_MMIO bool - depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX) + depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || \ + XPS_USB_HCD_XILINX || PPC_MPC512x) default y config USB_EHCI_BIG_ENDIAN_DESC bool - depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX) + depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \ + PPC_MPC512x) default y config XPS_USB_HCD_XILINX diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 8600317bd60b..86e42892016d 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -116,13 +116,33 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, goto err3; } - /* Enable USB controller */ - temp = in_be32(hcd->regs + 0x500); - out_be32(hcd->regs + 0x500, temp | 0x4); + pdata->regs = hcd->regs; - /* Set to Host mode */ - temp = in_le32(hcd->regs + 0x1a8); - out_le32(hcd->regs + 0x1a8, temp | 0x3); + /* + * do platform specific init: check the clock, grab/config pins, etc. + */ + if (pdata->init && pdata->init(pdev)) { + retval = -ENODEV; + goto err3; + } + + /* + * Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs + * flag for 83xx or 8536 system interface registers. + */ + if (pdata->big_endian_mmio) + temp = in_be32(hcd->regs + FSL_SOC_USB_ID); + else + temp = in_le32(hcd->regs + FSL_SOC_USB_ID); + + if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK)) + pdata->have_sysif_regs = 1; + + /* Enable USB controller, 83xx or 8536 */ + if (pdata->have_sysif_regs) + setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4); + + /* Don't need to set host mode here. It will be done by tdi_reset() */ retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (retval != 0) @@ -137,6 +157,8 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, usb_put_hcd(hcd); err1: dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval); + if (pdata->exit) + pdata->exit(pdev); return retval; } @@ -154,17 +176,30 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, static void usb_hcd_fsl_remove(struct usb_hcd *hcd, struct platform_device *pdev) { + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; + usb_remove_hcd(hcd); + + /* + * do platform specific un-initialization: + * release iomux pins, disable clock, etc. + */ + if (pdata->exit) + pdata->exit(pdev); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); } -static void mpc83xx_setup_phy(struct ehci_hcd *ehci, - enum fsl_usb2_phy_modes phy_mode, - unsigned int port_offset) +static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, + enum fsl_usb2_phy_modes phy_mode, + unsigned int port_offset) { - u32 portsc = 0; + u32 portsc; + + portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]); + portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW); + switch (phy_mode) { case FSL_USB2_PHY_ULPI: portsc |= PORT_PTS_ULPI; @@ -184,20 +219,21 @@ static void mpc83xx_setup_phy(struct ehci_hcd *ehci, ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); } -static void mpc83xx_usb_setup(struct usb_hcd *hcd) +static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) { - struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct usb_hcd *hcd = ehci_to_hcd(ehci); struct fsl_usb2_platform_data *pdata; void __iomem *non_ehci = hcd->regs; u32 temp; - pdata = - (struct fsl_usb2_platform_data *)hcd->self.controller-> - platform_data; + pdata = hcd->self.controller->platform_data; + /* Enable PHY interface in the control reg. */ - temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); - out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004); - out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b); + if (pdata->have_sysif_regs) { + temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); + out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004); + out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b); + } #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) /* @@ -214,7 +250,7 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd) if ((pdata->operating_mode == FSL_USB2_DR_HOST) || (pdata->operating_mode == FSL_USB2_DR_OTG)) - mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); + ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); if (pdata->operating_mode == FSL_USB2_MPH_HOST) { unsigned int chip, rev, svr; @@ -228,25 +264,27 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd) ehci->has_fsl_port_bug = 1; if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) - mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); + ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) - mpc83xx_setup_phy(ehci, pdata->phy_mode, 1); + ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1); } + if (pdata->have_sysif_regs) { #ifdef CONFIG_PPC_85xx - out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008); - out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080); + out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008); + out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080); #else - out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); - out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); + out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); + out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); #endif - out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); + out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); + } } /* called after powerup, by probe or system-pm "wakeup" */ static int ehci_fsl_reinit(struct ehci_hcd *ehci) { - mpc83xx_usb_setup(ehci_to_hcd(ehci)); + ehci_fsl_usb_setup(ehci); ehci_port_power(ehci, 0); return 0; @@ -257,6 +295,11 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; + struct fsl_usb2_platform_data *pdata; + + pdata = hcd->self.controller->platform_data; + ehci->big_endian_desc = pdata->big_endian_desc; + ehci->big_endian_mmio = pdata->big_endian_mmio; /* EHCI registers start at offset 0x100 */ ehci->caps = hcd->regs + 0x100; @@ -370,7 +413,7 @@ static const struct hc_driver ehci_fsl_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_USB2, + .flags = HCD_USB2 | HCD_MEMORY, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index eb537aa54610..2c8353795226 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2005 freescale semiconductor +/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc. * Copyright (c) 2005 MontaVista Software * * This program is free software; you can redistribute it and/or modify it @@ -19,6 +19,9 @@ #define _EHCI_FSL_H /* offsets for the non-ehci registers in the FSL SOC USB controller */ +#define FSL_SOC_USB_ID 0x0 +#define ID_MSK 0x3f +#define NID_MSK 0x3f00 #define FSL_SOC_USB_ULPIVP 0x170 #define FSL_SOC_USB_PORTSC1 0x184 #define PORT_PTS_MSK (3<<30) @@ -27,6 +30,14 @@ #define PORT_PTS_SERIAL (3<<30) #define PORT_PTS_PTW (1<<28) #define FSL_SOC_USB_PORTSC2 0x188 + +#define FSL_SOC_USB_USBGENCTRL 0x200 +#define USBGENCTRL_PPP (1 << 3) +#define USBGENCTRL_PFP (1 << 2) +#define FSL_SOC_USB_ISIPHYCTRL 0x204 +#define ISIPHYCTRL_PXE (1) +#define ISIPHYCTRL_PHYE (1 << 4) + #define FSL_SOC_USB_SNOOP1 0x400 /* NOTE: big-endian */ #define FSL_SOC_USB_SNOOP2 0x404 /* NOTE: big-endian */ #define FSL_SOC_USB_AGECNTTHRSH 0x408 /* NOTE: big-endian */ diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index 1f3f01eacaf0..d36e4e75e08d 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c @@ -40,7 +40,7 @@ static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd, { memset (qtd, 0, sizeof *qtd); qtd->qtd_dma = dma; - qtd->hw_token = cpu_to_le32 (QTD_STS_HALT); + qtd->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); qtd->hw_next = EHCI_LIST_END(ehci); qtd->hw_alt_next = EHCI_LIST_END(ehci); INIT_LIST_HEAD (&qtd->qtd_list); diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 12db5d5cb0bc..574b99ea0700 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -15,6 +15,7 @@ #include #include #include +#include struct fsl_usb2_dev_data { char *dr_mode; /* controller mode */ @@ -153,6 +154,12 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev) pdata->operating_mode = FSL_USB2_MPH_HOST; } else { + if (of_get_property(np, "fsl,invert-drvvbus", NULL)) + pdata->invert_drvvbus = 1; + + if (of_get_property(np, "fsl,invert-pwr-fault", NULL)) + pdata->invert_pwr_fault = 1; + /* setup mode selected in the device tree */ pdata->operating_mode = dev_data->op_mode; } @@ -186,9 +193,91 @@ static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev) return 0; } +#ifdef CONFIG_PPC_MPC512x + +#define USBGENCTRL 0x200 /* NOTE: big endian */ +#define GC_WU_INT_CLR (1 << 5) /* Wakeup int clear */ +#define GC_ULPI_SEL (1 << 4) /* ULPI i/f select (usb0 only)*/ +#define GC_PPP (1 << 3) /* Inv. Port Power Polarity */ +#define GC_PFP (1 << 2) /* Inv. Power Fault Polarity */ +#define GC_WU_ULPI_EN (1 << 1) /* Wakeup on ULPI event */ +#define GC_WU_IE (1 << 1) /* Wakeup interrupt enable */ + +#define ISIPHYCTRL 0x204 /* NOTE: big endian */ +#define PHYCTRL_PHYE (1 << 4) /* On-chip UTMI PHY enable */ +#define PHYCTRL_BSENH (1 << 3) /* Bit Stuff Enable High */ +#define PHYCTRL_BSEN (1 << 2) /* Bit Stuff Enable */ +#define PHYCTRL_LSFE (1 << 1) /* Line State Filter Enable */ +#define PHYCTRL_PXE (1 << 0) /* PHY oscillator enable */ + +int fsl_usb2_mpc5121_init(struct platform_device *pdev) +{ + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; + struct clk *clk; + char clk_name[10]; + int base, clk_num; + + base = pdev->resource->start & 0xf000; + if (base == 0x3000) + clk_num = 1; + else if (base == 0x4000) + clk_num = 2; + else + return -ENODEV; + + snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num); + clk = clk_get(&pdev->dev, clk_name); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "failed to get clk\n"); + return PTR_ERR(clk); + } + + clk_enable(clk); + pdata->clk = clk; + + if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) { + u32 reg = 0; + + if (pdata->invert_drvvbus) + reg |= GC_PPP; + + if (pdata->invert_pwr_fault) + reg |= GC_PFP; + + out_be32(pdata->regs + ISIPHYCTRL, PHYCTRL_PHYE | PHYCTRL_PXE); + out_be32(pdata->regs + USBGENCTRL, reg); + } + return 0; +} + +static void fsl_usb2_mpc5121_exit(struct platform_device *pdev) +{ + struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; + + pdata->regs = NULL; + + if (pdata->clk) { + clk_disable(pdata->clk); + clk_put(pdata->clk); + } +} + +struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = { + .big_endian_desc = 1, + .big_endian_mmio = 1, + .es = 1, + .le_setup_buf = 1, + .init = fsl_usb2_mpc5121_init, + .exit = fsl_usb2_mpc5121_exit, +}; +#endif /* CONFIG_PPC_MPC512x */ + static const struct of_device_id fsl_usb2_mph_dr_of_match[] = { { .compatible = "fsl-usb2-mph", }, { .compatible = "fsl-usb2-dr", }, +#ifdef CONFIG_PPC_MPC512x + { .compatible = "fsl,mpc5121-usb2-dr", .data = &fsl_usb2_mpc5121_pd, }, +#endif {}, }; diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index 28e33fea5107..d5f9a7431bd0 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -58,11 +58,26 @@ enum fsl_usb2_phy_modes { FSL_USB2_PHY_SERIAL, }; +struct clk; +struct platform_device; + struct fsl_usb2_platform_data { /* board specific information */ enum fsl_usb2_operating_modes operating_mode; enum fsl_usb2_phy_modes phy_mode; unsigned int port_enables; + + int (*init)(struct platform_device *); + void (*exit)(struct platform_device *); + void __iomem *regs; /* ioremap'd register base */ + struct clk *clk; + unsigned big_endian_mmio:1; + unsigned big_endian_desc:1; + unsigned es:1; /* need USBMODE:ES */ + unsigned le_setup_buf:1; + unsigned have_sysif_regs:1; + unsigned invert_drvvbus:1; + unsigned invert_pwr_fault:1; }; /* Flags in fsl_usb2_mph_platform_data */ From f405387435a85a440d1ce16f3ca36e042281643a Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 29 Sep 2010 09:54:29 +0300 Subject: [PATCH 082/141] USB: MUSB: fix kernel WARNING/oops when unloading module in OTG mode Since commit 461972d8a4c94bc44f11a13046041c78a7cf18dd (musb_core: don't call musb_platform_exit() twice), unloading the driver module results in a WARNING "kobject: '(null)' (c73de788): is not initialized, yet kobject_put() is being called." (or even kernel oops) on e.g. DaVincis, though only in the OTG mode. There exists dubious and unbalanced put_device() call in musb_free() which takes place only in the OTG mode. As this commit caused musb_platform_exit() to be called (and so unregister the NOP transceiver) before this put_device() call, this function references already freed memory. On the other hand, all the glue layers miss the otg_put_transceiver() call, complementary to the otg_get_transceiver() call that they do. So, I think the solution is to get rid of the strange put_device() call, and instead call otg_put_transceiver() in the glue layers... Signed-off-by: Sergei Shtylyov Cc: stable Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/blackfin.c | 1 + drivers/usb/musb/davinci.c | 2 ++ drivers/usb/musb/musb_core.c | 4 ---- drivers/usb/musb/omap2430.c | 1 + drivers/usb/musb/tusb6010.c | 4 ++++ 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index b611420a8050..9733fe9b597a 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -397,5 +397,6 @@ int musb_platform_exit(struct musb *musb) gpio_free(musb->config->gpio_vrsel); + otg_put_transceiver(musb->xceiv); return 0; } diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 57624361c1de..6e67629f50cc 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -446,6 +446,7 @@ int __init musb_platform_init(struct musb *musb, void *board_data) fail: clk_disable(musb->clock); + otg_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return -ENODEV; } @@ -496,6 +497,7 @@ int musb_platform_exit(struct musb *musb) clk_disable(musb->clock); + otg_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 472b2a7e7896..7e2c353755d2 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1926,10 +1926,6 @@ static void musb_free(struct musb *musb) dma_controller_destroy(c); } -#ifdef CONFIG_USB_MUSB_OTG - put_device(musb->xceiv->dev); -#endif - #ifdef CONFIG_USB_MUSB_HDRC_HCD usb_put_hcd(musb_to_hcd(musb)); #else diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 2111a241dd03..ed618bde1eec 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -320,5 +320,6 @@ int musb_platform_exit(struct musb *musb) musb_platform_suspend(musb); + otg_put_transceiver(musb->xceiv); return 0; } diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 3c48e77a0aa2..bde40efc7046 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -1152,6 +1152,8 @@ done: if (ret < 0) { if (sync) iounmap(sync); + + otg_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); } return ret; @@ -1166,6 +1168,8 @@ int musb_platform_exit(struct musb *musb) musb->board_set_power(0); iounmap(musb->sync_va); + + otg_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; } From 3daad24d6c72affdd40e8b6a75c87d3c175880b6 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 29 Sep 2010 09:54:30 +0300 Subject: [PATCH 083/141] usb: musb: blackfin: call usb_nop_xceiv_unregister() in musb_platform_exit() Blackfin's musb_platform_exit() forgets to call usb_nop_xceiv_unregister(). While fixing this, also remove the unneeded blank line there. Signed-off-by: Sergei Shtylyov Acked-by: Mike Frysinger Cc: stable Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/blackfin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index 9733fe9b597a..4fa25553c450 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -394,9 +394,9 @@ int __init musb_platform_init(struct musb *musb, void *board_data) int musb_platform_exit(struct musb *musb) { - gpio_free(musb->config->gpio_vrsel); otg_put_transceiver(musb->xceiv); + usb_nop_xceiv_unregister(); return 0; } From 00be545e49d83485d49a598d3b7e090088934be8 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 29 Sep 2010 09:54:31 +0300 Subject: [PATCH 084/141] usb: musb: blackfin: call gpio_free() on error path in musb_platform_init() Blackfin's musb_platform_init() needs to call gpio_free() for error cleanup iff otg_get_transceiver() call returns NULL. Signed-off-by: Sergei Shtylyov Acked-by: Mike Frysinger Signed-off-by: Felipe Balbi Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/blackfin.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index 4fa25553c450..611a9d274363 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -342,8 +342,10 @@ int __init musb_platform_init(struct musb *musb, void *board_data) usb_nop_xceiv_register(); musb->xceiv = otg_get_transceiver(); - if (!musb->xceiv) + if (!musb->xceiv) { + gpio_free(musb->config->gpio_vrsel); return -ENODEV; + } if (ANOMALY_05000346) { bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); From 689d6eacd1b7c3677bfe6ee367766f21c3c80e26 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 30 Sep 2010 20:32:44 +0800 Subject: [PATCH 085/141] USB: UHCI: add native scatter-gather support(v1) This patch adds native scatter-gather support to uhci-hcd. Reviewed-by: Alan Stern Signed-off-by: Ming Lei Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-q.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index d3ade4018487..2090b45eb606 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -917,10 +917,13 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, unsigned long destination, status; int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize); int len = urb->transfer_buffer_length; - dma_addr_t data = urb->transfer_dma; + int this_sg_len; + dma_addr_t data; __le32 *plink; struct urb_priv *urbp = urb->hcpriv; unsigned int toggle; + struct scatterlist *sg; + int i; if (len < 0) return -EINVAL; @@ -937,12 +940,26 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, if (usb_pipein(urb->pipe)) status |= TD_CTRL_SPD; + i = urb->num_sgs; + if (len > 0 && i > 0) { + sg = urb->sg; + data = sg_dma_address(sg); + + /* urb->transfer_buffer_length may be smaller than the + * size of the scatterlist (or vice versa) + */ + this_sg_len = min_t(int, sg_dma_len(sg), len); + } else { + sg = NULL; + data = urb->transfer_dma; + this_sg_len = len; + } /* * Build the DATA TDs */ plink = NULL; td = qh->dummy_td; - do { /* Allow zero length packets */ + for (;;) { /* Allow zero length packets */ int pktsze = maxsze; if (len <= pktsze) { /* The last packet */ @@ -965,10 +982,18 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, plink = &td->link; status |= TD_CTRL_ACTIVE; - data += pktsze; - len -= maxsze; toggle ^= 1; - } while (len > 0); + data += pktsze; + this_sg_len -= pktsze; + len -= maxsze; + if (this_sg_len <= 0) { + if (--i <= 0 || len <= 0) + break; + sg = sg_next(sg); + data = sg_dma_address(sg); + this_sg_len = min_t(int, sg_dma_len(sg), len); + } + } /* * URB_ZERO_PACKET means adding a 0-length packet, if direction From c8458d59d424fcba2456d6cba5811ce01c3aedb9 Mon Sep 17 00:00:00 2001 From: Christophe Lebouc Date: Thu, 30 Sep 2010 15:34:36 +0100 Subject: [PATCH 086/141] usb: langwell_udc: fix big file transfer issue. This patch fixing the problem with large file transfers failing. Swap the read order to avoid unexpected RX status. Signed-off-by: Christophe Lebouc Signed-off-by: Hao Wu Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/langwell_udc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index d297f9eb92e4..064306046702 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -2440,12 +2440,14 @@ static int process_ep_req(struct langwell_udc *dev, int index, dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); for (i = 0; i < curr_req->dtd_count; i++) { - remaining_length = le16_to_cpu(curr_dtd->dtd_total); - actual -= remaining_length; /* command execution states by dTD */ dtd_status = curr_dtd->dtd_status; + barrier(); + remaining_length = le16_to_cpu(curr_dtd->dtd_total); + actual -= remaining_length; + if (!dtd_status) { /* transfers completed successfully */ if (!remaining_length) { From cf7d3c8e579a643ff81ff95d51babdaf4c55f5f4 Mon Sep 17 00:00:00 2001 From: Philippe Skowronski Date: Fri, 1 Oct 2010 14:59:16 +0100 Subject: [PATCH 087/141] usb: langwell_udc: cancel pending requests when controller is suspended. It is safer to cancel pending requests before free dTD and dQH when controller enters suspend state. Signed-off-by: Philippe Skowronski Signed-off-by: Hao Wu [Switch to spin_lock_irq as suggested by Alan Stern] Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/langwell_udc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index 064306046702..b8ec954c0692 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -3391,6 +3391,11 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) /* save PCI state */ pci_save_state(pdev); + spin_lock_irq(&dev->lock); + /* stop all usb activities */ + stop_activity(dev, dev->driver); + spin_unlock_irq(&dev->lock); + /* free dTD dma_pool and dQH */ if (dev->dtd_pool) dma_pool_destroy(dev->dtd_pool); From 80f0cf3947889014d3a3dc0ad60fb87cfda4b12a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 30 Sep 2010 15:16:23 -0400 Subject: [PATCH 088/141] USB: disable endpoints after unbinding interfaces, not before This patch (as1430) fixes a bug in usbcore. When a device configuration change occurs or a device is removed, the endpoints for the old config should be completely disabled. However it turns out they aren't; this is because usb_unbind_interface() calls usb_enable_interface() or usb_set_interface() to put interfaces back in altsetting 0, which re-enables the interfaces' endpoints. As a result, when a device goes through a config change or is unconfigured, the ep_in[] and ep_out[] arrays may be left holding old pointers to usb_host_endpoint structures. If the device is deauthorized these structures get freed, and the stale pointers cause errors when the the device is eventually unplugged. The solution is to disable the endpoints after unbinding the interfaces instead of before. This isn't as large a change as it sounds, since usb_unbind_interface() disables all the interface's endpoints anyway before calling the driver's disconnect routine, unless the driver claims to support "soft" unbind. This fixes Bugzilla #19192. Thanks to "Tom" Lei Ming for diagnosing the underlying cause of the problem. Signed-off-by: Alan Stern Tested-by: Carsten Sommer CC: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 9f0ce7de0e36..d6e3e410477e 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1140,13 +1140,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) { int i; - dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, - skip_ep0 ? "non-ep0" : "all"); - for (i = skip_ep0; i < 16; ++i) { - usb_disable_endpoint(dev, i, true); - usb_disable_endpoint(dev, i + USB_DIR_IN, true); - } - /* getting rid of interfaces will disconnect * any drivers bound to them (a key side effect) */ @@ -1176,6 +1169,13 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) if (dev->state == USB_STATE_CONFIGURED) usb_set_device_state(dev, USB_STATE_ADDRESS); } + + dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, + skip_ep0 ? "non-ep0" : "all"); + for (i = skip_ep0; i < 16; ++i) { + usb_disable_endpoint(dev, i, true); + usb_disable_endpoint(dev, i + USB_DIR_IN, true); + } } /** From fabbf2196d0db0b4d175456dcb373aa2440f5728 Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Fri, 1 Oct 2010 00:20:42 +0200 Subject: [PATCH 089/141] USB: usbtest fix coding style Signed-off-by: Martin Fuzzey Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbtest.c | 665 +++++++++++++++++++------------------ 1 file changed, 341 insertions(+), 324 deletions(-) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index eef370eb7a54..bb078ebb8e81 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -13,17 +13,16 @@ /*-------------------------------------------------------------------------*/ -// FIXME make these public somewhere; usbdevfs.h? -// +/* FIXME make these public somewhere; usbdevfs.h? */ struct usbtest_param { - // inputs + /* inputs */ unsigned test_num; /* 0..(TEST_CASES-1) */ unsigned iterations; unsigned length; unsigned vary; unsigned sglen; - // outputs + /* outputs */ struct timeval duration; }; #define USBTEST_REQUEST _IOWR('U', 100, struct usbtest_param) @@ -45,9 +44,9 @@ struct usbtest_info { const char *name; u8 ep_in; /* bulk/intr source */ u8 ep_out; /* bulk/intr sink */ - unsigned autoconf : 1; - unsigned ctrl_out : 1; - unsigned iso : 1; /* try iso in/out */ + unsigned autoconf:1; + unsigned ctrl_out:1; + unsigned iso:1; /* try iso in/out */ int alt; }; @@ -71,9 +70,9 @@ struct usbtest_dev { u8 *buf; }; -static struct usb_device *testdev_to_usbdev (struct usbtest_dev *test) +static struct usb_device *testdev_to_usbdev(struct usbtest_dev *test) { - return interface_to_usbdev (test->intf); + return interface_to_usbdev(test->intf); } /* set up all urbs so they can be used with either bulk or interrupt */ @@ -87,7 +86,7 @@ static struct usb_device *testdev_to_usbdev (struct usbtest_dev *test) /*-------------------------------------------------------------------------*/ static int -get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf) +get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf) { int tmp; struct usb_host_interface *alt; @@ -115,7 +114,7 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf) case USB_ENDPOINT_XFER_ISOC: if (dev->info->iso) goto try_iso; - // FALLTHROUGH + /* FALLTHROUGH */ default: continue; } @@ -142,9 +141,9 @@ try_iso: return -EINVAL; found: - udev = testdev_to_usbdev (dev); + udev = testdev_to_usbdev(dev); if (alt->desc.bAlternateSetting != 0) { - tmp = usb_set_interface (udev, + tmp = usb_set_interface(udev, alt->desc.bInterfaceNumber, alt->desc.bAlternateSetting); if (tmp < 0) @@ -152,21 +151,21 @@ found: } if (in) { - dev->in_pipe = usb_rcvbulkpipe (udev, + dev->in_pipe = usb_rcvbulkpipe(udev, in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); - dev->out_pipe = usb_sndbulkpipe (udev, + dev->out_pipe = usb_sndbulkpipe(udev, out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); } if (iso_in) { dev->iso_in = &iso_in->desc; - dev->in_iso_pipe = usb_rcvisocpipe (udev, + dev->in_iso_pipe = usb_rcvisocpipe(udev, iso_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); } if (iso_out) { dev->iso_out = &iso_out->desc; - dev->out_iso_pipe = usb_sndisocpipe (udev, + dev->out_iso_pipe = usb_sndisocpipe(udev, iso_out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); } @@ -182,12 +181,12 @@ found: * them with non-zero test data (or test for it) when appropriate. */ -static void simple_callback (struct urb *urb) +static void simple_callback(struct urb *urb) { complete(urb->context); } -static struct urb *simple_alloc_urb ( +static struct urb *simple_alloc_urb( struct usb_device *udev, int pipe, unsigned long bytes @@ -195,32 +194,32 @@ static struct urb *simple_alloc_urb ( { struct urb *urb; - urb = usb_alloc_urb (0, GFP_KERNEL); + urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return urb; - usb_fill_bulk_urb (urb, udev, pipe, NULL, bytes, simple_callback, NULL); + usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, simple_callback, NULL); urb->interval = (udev->speed == USB_SPEED_HIGH) ? (INTERRUPT_RATE << 3) : INTERRUPT_RATE; urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; - if (usb_pipein (pipe)) + if (usb_pipein(pipe)) urb->transfer_flags |= URB_SHORT_NOT_OK; - urb->transfer_buffer = usb_alloc_coherent (udev, bytes, GFP_KERNEL, + urb->transfer_buffer = usb_alloc_coherent(udev, bytes, GFP_KERNEL, &urb->transfer_dma); if (!urb->transfer_buffer) { - usb_free_urb (urb); + usb_free_urb(urb); urb = NULL; } else - memset (urb->transfer_buffer, 0, bytes); + memset(urb->transfer_buffer, 0, bytes); return urb; } -static unsigned pattern = 0; +static unsigned pattern; static unsigned mod_pattern; module_param_named(pattern, mod_pattern, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(mod_pattern, "i/o pattern (0 == zeroes)"); -static inline void simple_fill_buf (struct urb *urb) +static inline void simple_fill_buf(struct urb *urb) { unsigned i; u8 *buf = urb->transfer_buffer; @@ -228,9 +227,9 @@ static inline void simple_fill_buf (struct urb *urb) switch (pattern) { default: - // FALLTHROUGH + /* FALLTHROUGH */ case 0: - memset (buf, 0, len); + memset(buf, 0, len); break; case 1: /* mod63 */ for (i = 0; i < len; i++) @@ -273,14 +272,14 @@ static inline int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb) return 0; } -static void simple_free_urb (struct urb *urb) +static void simple_free_urb(struct urb *urb) { usb_free_coherent(urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); - usb_free_urb (urb); + usb_free_urb(urb); } -static int simple_io ( +static int simple_io( struct usbtest_dev *tdev, struct urb *urb, int iterations, @@ -296,17 +295,18 @@ static int simple_io ( urb->context = &completion; while (retval == 0 && iterations-- > 0) { - init_completion (&completion); - if (usb_pipeout (urb->pipe)) - simple_fill_buf (urb); - if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0) + init_completion(&completion); + if (usb_pipeout(urb->pipe)) + simple_fill_buf(urb); + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval != 0) break; /* NOTE: no timeouts; can't be broken out of by interrupt */ - wait_for_completion (&completion); + wait_for_completion(&completion); retval = urb->status; urb->dev = udev; - if (retval == 0 && usb_pipein (urb->pipe)) + if (retval == 0 && usb_pipein(urb->pipe)) retval = simple_check_buf(tdev, urb); if (vary) { @@ -337,7 +337,7 @@ static int simple_io ( * Yes, this also tests the scatterlist primitives. */ -static void free_sglist (struct scatterlist *sg, int nents) +static void free_sglist(struct scatterlist *sg, int nents) { unsigned i; @@ -346,19 +346,19 @@ static void free_sglist (struct scatterlist *sg, int nents) for (i = 0; i < nents; i++) { if (!sg_page(&sg[i])) continue; - kfree (sg_virt(&sg[i])); + kfree(sg_virt(&sg[i])); } - kfree (sg); + kfree(sg); } static struct scatterlist * -alloc_sglist (int nents, int max, int vary) +alloc_sglist(int nents, int max, int vary) { struct scatterlist *sg; unsigned i; unsigned size = max; - sg = kmalloc (nents * sizeof *sg, GFP_KERNEL); + sg = kmalloc(nents * sizeof *sg, GFP_KERNEL); if (!sg) return NULL; sg_init_table(sg, nents); @@ -367,9 +367,9 @@ alloc_sglist (int nents, int max, int vary) char *buf; unsigned j; - buf = kzalloc (size, GFP_KERNEL); + buf = kzalloc(size, GFP_KERNEL); if (!buf) { - free_sglist (sg, i); + free_sglist(sg, i); return NULL; } @@ -397,7 +397,7 @@ alloc_sglist (int nents, int max, int vary) return sg; } -static int perform_sglist ( +static int perform_sglist( struct usbtest_dev *tdev, unsigned iterations, int pipe, @@ -410,7 +410,7 @@ static int perform_sglist ( int retval = 0; while (retval == 0 && iterations-- > 0) { - retval = usb_sg_init (req, udev, pipe, + retval = usb_sg_init(req, udev, pipe, (udev->speed == USB_SPEED_HIGH) ? (INTERRUPT_RATE << 3) : INTERRUPT_RATE, @@ -418,7 +418,7 @@ static int perform_sglist ( if (retval) break; - usb_sg_wait (req); + usb_sg_wait(req); retval = req->status; /* FIXME check resulting data pattern */ @@ -426,9 +426,9 @@ static int perform_sglist ( /* FIXME if endpoint halted, clear halt (and log) */ } - // FIXME for unlink or fault handling tests, don't report - // failure if retval is as we expected ... - + /* FIXME for unlink or fault handling tests, don't report + * failure if retval is as we expected ... + */ if (retval) ERROR(tdev, "perform_sglist failed, " "iterations left %d, status %d\n", @@ -452,31 +452,31 @@ static int perform_sglist ( */ static unsigned realworld = 1; -module_param (realworld, uint, 0); -MODULE_PARM_DESC (realworld, "clear to demand stricter spec compliance"); +module_param(realworld, uint, 0); +MODULE_PARM_DESC(realworld, "clear to demand stricter spec compliance"); -static int get_altsetting (struct usbtest_dev *dev) +static int get_altsetting(struct usbtest_dev *dev) { struct usb_interface *iface = dev->intf; - struct usb_device *udev = interface_to_usbdev (iface); + struct usb_device *udev = interface_to_usbdev(iface); int retval; - retval = usb_control_msg (udev, usb_rcvctrlpipe (udev, 0), + retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), USB_REQ_GET_INTERFACE, USB_DIR_IN|USB_RECIP_INTERFACE, - 0, iface->altsetting [0].desc.bInterfaceNumber, + 0, iface->altsetting[0].desc.bInterfaceNumber, dev->buf, 1, USB_CTRL_GET_TIMEOUT); switch (retval) { case 1: - return dev->buf [0]; + return dev->buf[0]; case 0: retval = -ERANGE; - // FALLTHROUGH + /* FALLTHROUGH */ default: return retval; } } -static int set_altsetting (struct usbtest_dev *dev, int alternate) +static int set_altsetting(struct usbtest_dev *dev, int alternate) { struct usb_interface *iface = dev->intf; struct usb_device *udev; @@ -484,9 +484,9 @@ static int set_altsetting (struct usbtest_dev *dev, int alternate) if (alternate < 0 || alternate >= 256) return -EINVAL; - udev = interface_to_usbdev (iface); - return usb_set_interface (udev, - iface->altsetting [0].desc.bInterfaceNumber, + udev = interface_to_usbdev(iface); + return usb_set_interface(udev, + iface->altsetting[0].desc.bInterfaceNumber, alternate); } @@ -519,9 +519,9 @@ static int is_good_config(struct usbtest_dev *tdev, int len) return 0; } - if (le16_to_cpu(config->wTotalLength) == len) /* read it all */ + if (le16_to_cpu(config->wTotalLength) == len) /* read it all */ return 1; - if (le16_to_cpu(config->wTotalLength) >= TBUF_SIZE) /* max partial read */ + if (le16_to_cpu(config->wTotalLength) >= TBUF_SIZE) /* max partial read */ return 1; ERROR(tdev, "bogus config descriptor read size\n"); return 0; @@ -542,10 +542,10 @@ static int is_good_config(struct usbtest_dev *tdev, int len) * to see if usbcore, hcd, and device all behave right. such testing would * involve varied read sizes and other operation sequences. */ -static int ch9_postconfig (struct usbtest_dev *dev) +static int ch9_postconfig(struct usbtest_dev *dev) { struct usb_interface *iface = dev->intf; - struct usb_device *udev = interface_to_usbdev (iface); + struct usb_device *udev = interface_to_usbdev(iface); int i, alt, retval; /* [9.2.3] if there's more than one altsetting, we need to be able to @@ -554,7 +554,7 @@ static int ch9_postconfig (struct usbtest_dev *dev) for (i = 0; i < iface->num_altsetting; i++) { /* 9.2.3 constrains the range here */ - alt = iface->altsetting [i].desc.bAlternateSetting; + alt = iface->altsetting[i].desc.bAlternateSetting; if (alt < 0 || alt >= iface->num_altsetting) { dev_err(&iface->dev, "invalid alt [%d].bAltSetting = %d\n", @@ -566,7 +566,7 @@ static int ch9_postconfig (struct usbtest_dev *dev) continue; /* [9.4.10] set_interface */ - retval = set_altsetting (dev, alt); + retval = set_altsetting(dev, alt); if (retval) { dev_err(&iface->dev, "can't set_interface = %d, %d\n", alt, retval); @@ -574,7 +574,7 @@ static int ch9_postconfig (struct usbtest_dev *dev) } /* [9.4.4] get_interface always works */ - retval = get_altsetting (dev); + retval = get_altsetting(dev); if (retval != alt) { dev_err(&iface->dev, "get alt should be %d, was %d\n", alt, retval); @@ -591,11 +591,11 @@ static int ch9_postconfig (struct usbtest_dev *dev) * ... although some cheap devices (like one TI Hub I've got) * won't return config descriptors except before set_config. */ - retval = usb_control_msg (udev, usb_rcvctrlpipe (udev, 0), + retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), USB_REQ_GET_CONFIGURATION, USB_DIR_IN | USB_RECIP_DEVICE, 0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT); - if (retval != 1 || dev->buf [0] != expected) { + if (retval != 1 || dev->buf[0] != expected) { dev_err(&iface->dev, "get config --> %d %d (1 %d)\n", retval, dev->buf[0], expected); return (retval < 0) ? retval : -EDOM; @@ -603,7 +603,7 @@ static int ch9_postconfig (struct usbtest_dev *dev) } /* there's always [9.4.3] a device descriptor [9.6.1] */ - retval = usb_get_descriptor (udev, USB_DT_DEVICE, 0, + retval = usb_get_descriptor(udev, USB_DT_DEVICE, 0, dev->buf, sizeof udev->descriptor); if (retval != sizeof udev->descriptor) { dev_err(&iface->dev, "dev descriptor --> %d\n", retval); @@ -612,7 +612,7 @@ static int ch9_postconfig (struct usbtest_dev *dev) /* there's always [9.4.3] at least one config descriptor [9.6.3] */ for (i = 0; i < udev->descriptor.bNumConfigurations; i++) { - retval = usb_get_descriptor (udev, USB_DT_CONFIG, i, + retval = usb_get_descriptor(udev, USB_DT_CONFIG, i, dev->buf, TBUF_SIZE); if (!is_good_config(dev, retval)) { dev_err(&iface->dev, @@ -621,18 +621,19 @@ static int ch9_postconfig (struct usbtest_dev *dev) return (retval < 0) ? retval : -EDOM; } - // FIXME cross-checking udev->config[i] to make sure usbcore - // parsed it right (etc) would be good testing paranoia + /* FIXME cross-checking udev->config[i] to make sure usbcore + * parsed it right (etc) would be good testing paranoia + */ } /* and sometimes [9.2.6.6] speed dependent descriptors */ if (le16_to_cpu(udev->descriptor.bcdUSB) == 0x0200) { - struct usb_qualifier_descriptor *d = NULL; + struct usb_qualifier_descriptor *d = NULL; /* device qualifier [9.6.2] */ - retval = usb_get_descriptor (udev, + retval = usb_get_descriptor(udev, USB_DT_DEVICE_QUALIFIER, 0, dev->buf, - sizeof (struct usb_qualifier_descriptor)); + sizeof(struct usb_qualifier_descriptor)); if (retval == -EPIPE) { if (udev->speed == USB_SPEED_HIGH) { dev_err(&iface->dev, @@ -641,7 +642,7 @@ static int ch9_postconfig (struct usbtest_dev *dev) return (retval < 0) ? retval : -EDOM; } /* usb2.0 but not high-speed capable; fine */ - } else if (retval != sizeof (struct usb_qualifier_descriptor)) { + } else if (retval != sizeof(struct usb_qualifier_descriptor)) { dev_err(&iface->dev, "dev qualifier --> %d\n", retval); return (retval < 0) ? retval : -EDOM; } else @@ -651,7 +652,7 @@ static int ch9_postconfig (struct usbtest_dev *dev) if (d) { unsigned max = d->bNumConfigurations; for (i = 0; i < max; i++) { - retval = usb_get_descriptor (udev, + retval = usb_get_descriptor(udev, USB_DT_OTHER_SPEED_CONFIG, i, dev->buf, TBUF_SIZE); if (!is_good_config(dev, retval)) { @@ -663,25 +664,26 @@ static int ch9_postconfig (struct usbtest_dev *dev) } } } - // FIXME fetch strings from at least the device descriptor + /* FIXME fetch strings from at least the device descriptor */ /* [9.4.5] get_status always works */ - retval = usb_get_status (udev, USB_RECIP_DEVICE, 0, dev->buf); + retval = usb_get_status(udev, USB_RECIP_DEVICE, 0, dev->buf); if (retval != 2) { dev_err(&iface->dev, "get dev status --> %d\n", retval); return (retval < 0) ? retval : -EDOM; } - // FIXME configuration.bmAttributes says if we could try to set/clear - // the device's remote wakeup feature ... if we can, test that here + /* FIXME configuration.bmAttributes says if we could try to set/clear + * the device's remote wakeup feature ... if we can, test that here + */ - retval = usb_get_status (udev, USB_RECIP_INTERFACE, - iface->altsetting [0].desc.bInterfaceNumber, dev->buf); + retval = usb_get_status(udev, USB_RECIP_INTERFACE, + iface->altsetting[0].desc.bInterfaceNumber, dev->buf); if (retval != 2) { dev_err(&iface->dev, "get interface status --> %d\n", retval); return (retval < 0) ? retval : -EDOM; } - // FIXME get status for each endpoint in the interface + /* FIXME get status for each endpoint in the interface */ return 0; } @@ -717,7 +719,7 @@ struct subcase { int expected; }; -static void ctrl_complete (struct urb *urb) +static void ctrl_complete(struct urb *urb) { struct ctrl_ctx *ctx = urb->context; struct usb_ctrlrequest *reqp; @@ -725,9 +727,9 @@ static void ctrl_complete (struct urb *urb) int status = urb->status; reqp = (struct usb_ctrlrequest *)urb->setup_packet; - subcase = container_of (reqp, struct subcase, setup); + subcase = container_of(reqp, struct subcase, setup); - spin_lock (&ctx->lock); + spin_lock(&ctx->lock); ctx->count--; ctx->pending--; @@ -787,14 +789,14 @@ error: /* unlink whatever's still pending */ for (i = 1; i < ctx->param->sglen; i++) { - struct urb *u = ctx->urb [ - (i + subcase->number) - % ctx->param->sglen]; + struct urb *u = ctx->urb[ + (i + subcase->number) + % ctx->param->sglen]; if (u == urb || !u->dev) continue; spin_unlock(&ctx->lock); - status = usb_unlink_urb (u); + status = usb_unlink_urb(u); spin_lock(&ctx->lock); switch (status) { case -EINPROGRESS: @@ -812,7 +814,8 @@ error: /* resubmit if we need to, else mark this as done */ if ((status == 0) && (ctx->pending < ctx->count)) { - if ((status = usb_submit_urb (urb, GFP_ATOMIC)) != 0) { + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status != 0) { ERROR(ctx->dev, "can't resubmit ctrl %02x.%02x, err %d\n", reqp->bRequestType, reqp->bRequest, status); @@ -824,21 +827,21 @@ error: /* signal completion when nothing's queued */ if (ctx->pending == 0) - complete (&ctx->complete); - spin_unlock (&ctx->lock); + complete(&ctx->complete); + spin_unlock(&ctx->lock); } static int -test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) +test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param) { - struct usb_device *udev = testdev_to_usbdev (dev); + struct usb_device *udev = testdev_to_usbdev(dev); struct urb **urb; struct ctrl_ctx context; int i; - spin_lock_init (&context.lock); + spin_lock_init(&context.lock); context.dev = dev; - init_completion (&context.complete); + init_completion(&context.complete); context.count = param->sglen * param->iterations; context.pending = 0; context.status = -ENOMEM; @@ -853,7 +856,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) if (!urb) return -ENOMEM; for (i = 0; i < param->sglen; i++) { - int pipe = usb_rcvctrlpipe (udev, 0); + int pipe = usb_rcvctrlpipe(udev, 0); unsigned len; struct urb *u; struct usb_ctrlrequest req; @@ -869,104 +872,108 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) * device, but some are chosen to trigger protocol stalls * or short reads. */ - memset (&req, 0, sizeof req); + memset(&req, 0, sizeof req); req.bRequest = USB_REQ_GET_DESCRIPTOR; req.bRequestType = USB_DIR_IN|USB_RECIP_DEVICE; switch (i % NUM_SUBCASES) { - case 0: // get device descriptor - req.wValue = cpu_to_le16 (USB_DT_DEVICE << 8); - len = sizeof (struct usb_device_descriptor); + case 0: /* get device descriptor */ + req.wValue = cpu_to_le16(USB_DT_DEVICE << 8); + len = sizeof(struct usb_device_descriptor); break; - case 1: // get first config descriptor (only) - req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0); - len = sizeof (struct usb_config_descriptor); + case 1: /* get first config descriptor (only) */ + req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0); + len = sizeof(struct usb_config_descriptor); break; - case 2: // get altsetting (OFTEN STALLS) + case 2: /* get altsetting (OFTEN STALLS) */ req.bRequest = USB_REQ_GET_INTERFACE; req.bRequestType = USB_DIR_IN|USB_RECIP_INTERFACE; - // index = 0 means first interface + /* index = 0 means first interface */ len = 1; expected = EPIPE; break; - case 3: // get interface status + case 3: /* get interface status */ req.bRequest = USB_REQ_GET_STATUS; req.bRequestType = USB_DIR_IN|USB_RECIP_INTERFACE; - // interface 0 + /* interface 0 */ len = 2; break; - case 4: // get device status + case 4: /* get device status */ req.bRequest = USB_REQ_GET_STATUS; req.bRequestType = USB_DIR_IN|USB_RECIP_DEVICE; len = 2; break; - case 5: // get device qualifier (MAY STALL) + case 5: /* get device qualifier (MAY STALL) */ req.wValue = cpu_to_le16 (USB_DT_DEVICE_QUALIFIER << 8); - len = sizeof (struct usb_qualifier_descriptor); + len = sizeof(struct usb_qualifier_descriptor); if (udev->speed != USB_SPEED_HIGH) expected = EPIPE; break; - case 6: // get first config descriptor, plus interface - req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0); - len = sizeof (struct usb_config_descriptor); - len += sizeof (struct usb_interface_descriptor); + case 6: /* get first config descriptor, plus interface */ + req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0); + len = sizeof(struct usb_config_descriptor); + len += sizeof(struct usb_interface_descriptor); break; - case 7: // get interface descriptor (ALWAYS STALLS) + case 7: /* get interface descriptor (ALWAYS STALLS) */ req.wValue = cpu_to_le16 (USB_DT_INTERFACE << 8); - // interface == 0 - len = sizeof (struct usb_interface_descriptor); + /* interface == 0 */ + len = sizeof(struct usb_interface_descriptor); expected = -EPIPE; break; - // NOTE: two consecutive stalls in the queue here. - // that tests fault recovery a bit more aggressively. - case 8: // clear endpoint halt (MAY STALL) + /* NOTE: two consecutive stalls in the queue here. + * that tests fault recovery a bit more aggressively. */ + case 8: /* clear endpoint halt (MAY STALL) */ req.bRequest = USB_REQ_CLEAR_FEATURE; req.bRequestType = USB_RECIP_ENDPOINT; - // wValue 0 == ep halt - // wIndex 0 == ep0 (shouldn't halt!) + /* wValue 0 == ep halt */ + /* wIndex 0 == ep0 (shouldn't halt!) */ len = 0; - pipe = usb_sndctrlpipe (udev, 0); + pipe = usb_sndctrlpipe(udev, 0); expected = EPIPE; break; - case 9: // get endpoint status + case 9: /* get endpoint status */ req.bRequest = USB_REQ_GET_STATUS; req.bRequestType = USB_DIR_IN|USB_RECIP_ENDPOINT; - // endpoint 0 + /* endpoint 0 */ len = 2; break; - case 10: // trigger short read (EREMOTEIO) - req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0); + case 10: /* trigger short read (EREMOTEIO) */ + req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0); len = 1024; expected = -EREMOTEIO; break; - // NOTE: two consecutive _different_ faults in the queue. - case 11: // get endpoint descriptor (ALWAYS STALLS) - req.wValue = cpu_to_le16 (USB_DT_ENDPOINT << 8); - // endpoint == 0 - len = sizeof (struct usb_interface_descriptor); + /* NOTE: two consecutive _different_ faults in the queue. */ + case 11: /* get endpoint descriptor (ALWAYS STALLS) */ + req.wValue = cpu_to_le16(USB_DT_ENDPOINT << 8); + /* endpoint == 0 */ + len = sizeof(struct usb_interface_descriptor); expected = EPIPE; break; - // NOTE: sometimes even a third fault in the queue! - case 12: // get string 0 descriptor (MAY STALL) - req.wValue = cpu_to_le16 (USB_DT_STRING << 8); - // string == 0, for language IDs - len = sizeof (struct usb_interface_descriptor); - // may succeed when > 4 languages - expected = EREMOTEIO; // or EPIPE, if no strings + /* NOTE: sometimes even a third fault in the queue! */ + case 12: /* get string 0 descriptor (MAY STALL) */ + req.wValue = cpu_to_le16(USB_DT_STRING << 8); + /* string == 0, for language IDs */ + len = sizeof(struct usb_interface_descriptor); + /* may succeed when > 4 languages */ + expected = EREMOTEIO; /* or EPIPE, if no strings */ break; - case 13: // short read, resembling case 10 - req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0); - // last data packet "should" be DATA1, not DATA0 + case 13: /* short read, resembling case 10 */ + req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0); + /* last data packet "should" be DATA1, not DATA0 */ len = 1024 - udev->descriptor.bMaxPacketSize0; expected = -EREMOTEIO; break; - case 14: // short read; try to fill the last packet - req.wValue = cpu_to_le16 ((USB_DT_DEVICE << 8) | 0); + case 14: /* short read; try to fill the last packet */ + req.wValue = cpu_to_le16((USB_DT_DEVICE << 8) | 0); /* device descriptor size == 18 bytes */ len = udev->descriptor.bMaxPacketSize0; switch (len) { - case 8: len = 24; break; - case 16: len = 32; break; + case 8: + len = 24; + break; + case 16: + len = 32; + break; } expected = -EREMOTEIO; break; @@ -975,8 +982,8 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) context.status = -EINVAL; goto cleanup; } - req.wLength = cpu_to_le16 (len); - urb [i] = u = simple_alloc_urb (udev, pipe, len); + req.wLength = cpu_to_le16(len); + urb[i] = u = simple_alloc_urb(udev, pipe, len); if (!u) goto cleanup; @@ -994,9 +1001,9 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) /* queue the urbs */ context.urb = urb; - spin_lock_irq (&context.lock); + spin_lock_irq(&context.lock); for (i = 0; i < param->sglen; i++) { - context.status = usb_submit_urb (urb [i], GFP_ATOMIC); + context.status = usb_submit_urb(urb[i], GFP_ATOMIC); if (context.status != 0) { ERROR(dev, "can't submit urb[%d], status %d\n", i, context.status); @@ -1005,23 +1012,23 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) } context.pending++; } - spin_unlock_irq (&context.lock); + spin_unlock_irq(&context.lock); /* FIXME set timer and time out; provide a disconnect hook */ /* wait for the last one to complete */ if (context.pending > 0) - wait_for_completion (&context.complete); + wait_for_completion(&context.complete); cleanup: for (i = 0; i < param->sglen; i++) { - if (!urb [i]) + if (!urb[i]) continue; - urb [i]->dev = udev; + urb[i]->dev = udev; kfree(urb[i]->setup_packet); - simple_free_urb (urb [i]); + simple_free_urb(urb[i]); } - kfree (urb); + kfree(urb); return context.status; } #undef NUM_SUBCASES @@ -1029,27 +1036,27 @@ cleanup: /*-------------------------------------------------------------------------*/ -static void unlink1_callback (struct urb *urb) +static void unlink1_callback(struct urb *urb) { int status = urb->status; - // we "know" -EPIPE (stall) never happens + /* we "know" -EPIPE (stall) never happens */ if (!status) - status = usb_submit_urb (urb, GFP_ATOMIC); + status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { urb->status = status; complete(urb->context); } } -static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async) +static int unlink1(struct usbtest_dev *dev, int pipe, int size, int async) { struct urb *urb; struct completion completion; int retval = 0; - init_completion (&completion); - urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size); + init_completion(&completion); + urb = simple_alloc_urb(testdev_to_usbdev(dev), pipe, size); if (!urb) return -ENOMEM; urb->context = &completion; @@ -1061,7 +1068,8 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async) * FIXME want additional tests for when endpoint is STALLing * due to errors, or is just NAKing requests. */ - if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0) { + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval != 0) { dev_err(&dev->intf->dev, "submit fail %d\n", retval); return retval; } @@ -1069,7 +1077,7 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async) /* unlinking that should always work. variable delay tests more * hcd states and code paths, even with little other system load. */ - msleep (jiffies % (2 * INTERRUPT_RATE)); + msleep(jiffies % (2 * INTERRUPT_RATE)); if (async) { while (!completion_done(&completion)) { retval = usb_unlink_urb(urb); @@ -1098,11 +1106,11 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async) break; } } else - usb_kill_urb (urb); + usb_kill_urb(urb); - wait_for_completion (&completion); + wait_for_completion(&completion); retval = urb->status; - simple_free_urb (urb); + simple_free_urb(urb); if (async) return (retval == -ECONNRESET) ? 0 : retval - 1000; @@ -1111,14 +1119,14 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async) 0 : retval - 2000; } -static int unlink_simple (struct usbtest_dev *dev, int pipe, int len) +static int unlink_simple(struct usbtest_dev *dev, int pipe, int len) { int retval = 0; /* test sync and async paths */ - retval = unlink1 (dev, pipe, len, 1); + retval = unlink1(dev, pipe, len, 1); if (!retval) - retval = unlink1 (dev, pipe, len, 0); + retval = unlink1(dev, pipe, len, 0); return retval; } @@ -1130,7 +1138,7 @@ static int verify_not_halted(struct usbtest_dev *tdev, int ep, struct urb *urb) u16 status; /* shouldn't look or act halted */ - retval = usb_get_status (urb->dev, USB_RECIP_ENDPOINT, ep, &status); + retval = usb_get_status(urb->dev, USB_RECIP_ENDPOINT, ep, &status); if (retval < 0) { ERROR(tdev, "ep %02x couldn't get no-halt status, %d\n", ep, retval); @@ -1152,7 +1160,7 @@ static int verify_halted(struct usbtest_dev *tdev, int ep, struct urb *urb) u16 status; /* should look and act halted */ - retval = usb_get_status (urb->dev, USB_RECIP_ENDPOINT, ep, &status); + retval = usb_get_status(urb->dev, USB_RECIP_ENDPOINT, ep, &status); if (retval < 0) { ERROR(tdev, "ep %02x couldn't get halt status, %d\n", ep, retval); @@ -1182,7 +1190,7 @@ static int test_halt(struct usbtest_dev *tdev, int ep, struct urb *urb) return retval; /* set halt (protocol test only), verify it worked */ - retval = usb_control_msg (urb->dev, usb_sndctrlpipe (urb->dev, 0), + retval = usb_control_msg(urb->dev, usb_sndctrlpipe(urb->dev, 0), USB_REQ_SET_FEATURE, USB_RECIP_ENDPOINT, USB_ENDPOINT_HALT, ep, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -1195,7 +1203,7 @@ static int test_halt(struct usbtest_dev *tdev, int ep, struct urb *urb) return retval; /* clear halt (tests API + protocol), verify it worked */ - retval = usb_clear_halt (urb->dev, urb->pipe); + retval = usb_clear_halt(urb->dev, urb->pipe); if (retval < 0) { ERROR(tdev, "ep %02x couldn't clear halt, %d\n", ep, retval); return retval; @@ -1209,18 +1217,18 @@ static int test_halt(struct usbtest_dev *tdev, int ep, struct urb *urb) return 0; } -static int halt_simple (struct usbtest_dev *dev) +static int halt_simple(struct usbtest_dev *dev) { int ep; int retval = 0; struct urb *urb; - urb = simple_alloc_urb (testdev_to_usbdev (dev), 0, 512); + urb = simple_alloc_urb(testdev_to_usbdev(dev), 0, 512); if (urb == NULL) return -ENOMEM; if (dev->in_pipe) { - ep = usb_pipeendpoint (dev->in_pipe) | USB_DIR_IN; + ep = usb_pipeendpoint(dev->in_pipe) | USB_DIR_IN; urb->pipe = dev->in_pipe; retval = test_halt(dev, ep, urb); if (retval < 0) @@ -1228,12 +1236,12 @@ static int halt_simple (struct usbtest_dev *dev) } if (dev->out_pipe) { - ep = usb_pipeendpoint (dev->out_pipe); + ep = usb_pipeendpoint(dev->out_pipe); urb->pipe = dev->out_pipe; retval = test_halt(dev, ep, urb); } done: - simple_free_urb (urb); + simple_free_urb(urb); return retval; } @@ -1247,7 +1255,7 @@ done: * need to be able to handle more than one OUT data packet. We'll * try whatever we're told to try. */ -static int ctrl_out (struct usbtest_dev *dev, +static int ctrl_out(struct usbtest_dev *dev, unsigned count, unsigned length, unsigned vary) { unsigned i, j, len; @@ -1263,7 +1271,7 @@ static int ctrl_out (struct usbtest_dev *dev, if (!buf) return -ENOMEM; - udev = testdev_to_usbdev (dev); + udev = testdev_to_usbdev(dev); len = length; retval = 0; @@ -1273,8 +1281,8 @@ static int ctrl_out (struct usbtest_dev *dev, for (i = 0; i < count; i++) { /* write patterned data */ for (j = 0; j < len; j++) - buf [j] = i + j; - retval = usb_control_msg (udev, usb_sndctrlpipe (udev,0), + buf[j] = i + j; + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x5b, USB_DIR_OUT|USB_TYPE_VENDOR, 0, 0, buf, len, USB_CTRL_SET_TIMEOUT); if (retval != len) { @@ -1288,7 +1296,7 @@ static int ctrl_out (struct usbtest_dev *dev, } /* read it back -- assuming nothing intervened!! */ - retval = usb_control_msg (udev, usb_rcvctrlpipe (udev,0), + retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x5c, USB_DIR_IN|USB_TYPE_VENDOR, 0, 0, buf, len, USB_CTRL_GET_TIMEOUT); if (retval != len) { @@ -1303,9 +1311,9 @@ static int ctrl_out (struct usbtest_dev *dev, /* fail if we can't verify */ for (j = 0; j < len; j++) { - if (buf [j] != (u8) (i + j)) { + if (buf[j] != (u8) (i + j)) { ERROR(dev, "ctrl_out, byte %d is %d not %d\n", - j, buf [j], (u8) i + j); + j, buf[j], (u8) i + j); retval = -EBADMSG; break; } @@ -1326,10 +1334,10 @@ static int ctrl_out (struct usbtest_dev *dev, } if (retval < 0) - ERROR (dev, "ctrl_out %s failed, code %d, count %d\n", + ERROR(dev, "ctrl_out %s failed, code %d, count %d\n", what, retval, i); - kfree (buf); + kfree(buf); return retval; } @@ -1351,7 +1359,7 @@ struct iso_context { struct usbtest_dev *dev; }; -static void iso_callback (struct urb *urb) +static void iso_callback(struct urb *urb) { struct iso_context *ctx = urb->context; @@ -1366,7 +1374,7 @@ static void iso_callback (struct urb *urb) if (urb->status == 0 && ctx->count > (ctx->pending - 1) && !ctx->submit_error) { - int status = usb_submit_urb (urb, GFP_ATOMIC); + int status = usb_submit_urb(urb, GFP_ATOMIC); switch (status) { case 0: goto done; @@ -1388,13 +1396,13 @@ static void iso_callback (struct urb *urb) dev_err(&ctx->dev->intf->dev, "iso test, %lu errors out of %lu\n", ctx->errors, ctx->packet_count); - complete (&ctx->done); + complete(&ctx->done); } done: spin_unlock(&ctx->lock); } -static struct urb *iso_alloc_urb ( +static struct urb *iso_alloc_urb( struct usb_device *udev, int pipe, struct usb_endpoint_descriptor *desc, @@ -1410,7 +1418,7 @@ static struct urb *iso_alloc_urb ( maxp *= 1 + (0x3 & (le16_to_cpu(desc->wMaxPacketSize) >> 11)); packets = DIV_ROUND_UP(bytes, maxp); - urb = usb_alloc_urb (packets, GFP_KERNEL); + urb = usb_alloc_urb(packets, GFP_KERNEL); if (!urb) return urb; urb->dev = udev; @@ -1418,30 +1426,30 @@ static struct urb *iso_alloc_urb ( urb->number_of_packets = packets; urb->transfer_buffer_length = bytes; - urb->transfer_buffer = usb_alloc_coherent (udev, bytes, GFP_KERNEL, + urb->transfer_buffer = usb_alloc_coherent(udev, bytes, GFP_KERNEL, &urb->transfer_dma); if (!urb->transfer_buffer) { - usb_free_urb (urb); + usb_free_urb(urb); return NULL; } - memset (urb->transfer_buffer, 0, bytes); + memset(urb->transfer_buffer, 0, bytes); for (i = 0; i < packets; i++) { /* here, only the last packet will be short */ - urb->iso_frame_desc[i].length = min ((unsigned) bytes, maxp); + urb->iso_frame_desc[i].length = min((unsigned) bytes, maxp); bytes -= urb->iso_frame_desc[i].length; urb->iso_frame_desc[i].offset = maxp * i; } urb->complete = iso_callback; - // urb->context = SET BY CALLER + /* urb->context = SET BY CALLER */ urb->interval = 1 << (desc->bInterval - 1); urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; return urb; } static int -test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, +test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param, int pipe, struct usb_endpoint_descriptor *desc) { struct iso_context context; @@ -1457,11 +1465,11 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, memset(&context, 0, sizeof context); context.count = param->iterations * param->sglen; context.dev = dev; - init_completion (&context.done); - spin_lock_init (&context.lock); + init_completion(&context.done); + spin_lock_init(&context.lock); - memset (urbs, 0, sizeof urbs); - udev = testdev_to_usbdev (dev); + memset(urbs, 0, sizeof urbs); + udev = testdev_to_usbdev(dev); dev_info(&dev->intf->dev, "... iso period %d %sframes, wMaxPacket %04x\n", 1 << (desc->bInterval - 1), @@ -1469,14 +1477,14 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, le16_to_cpu(desc->wMaxPacketSize)); for (i = 0; i < param->sglen; i++) { - urbs [i] = iso_alloc_urb (udev, pipe, desc, + urbs[i] = iso_alloc_urb(udev, pipe, desc, param->length); - if (!urbs [i]) { + if (!urbs[i]) { status = -ENOMEM; goto fail; } packets += urbs[i]->number_of_packets; - urbs [i]->context = &context; + urbs[i]->context = &context; } packets *= param->iterations; dev_info(&dev->intf->dev, @@ -1485,27 +1493,27 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, / ((udev->speed == USB_SPEED_HIGH) ? 8 : 1), packets); - spin_lock_irq (&context.lock); + spin_lock_irq(&context.lock); for (i = 0; i < param->sglen; i++) { ++context.pending; - status = usb_submit_urb (urbs [i], GFP_ATOMIC); + status = usb_submit_urb(urbs[i], GFP_ATOMIC); if (status < 0) { - ERROR (dev, "submit iso[%d], error %d\n", i, status); + ERROR(dev, "submit iso[%d], error %d\n", i, status); if (i == 0) { - spin_unlock_irq (&context.lock); + spin_unlock_irq(&context.lock); goto fail; } - simple_free_urb (urbs [i]); + simple_free_urb(urbs[i]); urbs[i] = NULL; context.pending--; context.submit_error = 1; break; } } - spin_unlock_irq (&context.lock); + spin_unlock_irq(&context.lock); - wait_for_completion (&context.done); + wait_for_completion(&context.done); for (i = 0; i < param->sglen; i++) { if (urbs[i]) @@ -1526,8 +1534,8 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, fail: for (i = 0; i < param->sglen; i++) { - if (urbs [i]) - simple_free_urb (urbs [i]); + if (urbs[i]) + simple_free_urb(urbs[i]); } return status; } @@ -1557,10 +1565,10 @@ fail: /* No BKL needed */ static int -usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) +usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) { - struct usbtest_dev *dev = usb_get_intfdata (intf); - struct usb_device *udev = testdev_to_usbdev (dev); + struct usbtest_dev *dev = usb_get_intfdata(intf); + struct usb_device *udev = testdev_to_usbdev(dev); struct usbtest_param *param = buf; int retval = -EOPNOTSUPP; struct urb *urb; @@ -1569,7 +1577,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) struct timeval start; unsigned i; - // FIXME USBDEVFS_CONNECTINFO doesn't say how fast the device is. + /* FIXME USBDEVFS_CONNECTINFO doesn't say how fast the device is. */ pattern = mod_pattern; @@ -1595,9 +1603,9 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) mutex_unlock(&dev->lock); return -ENODEV; } - res = set_altsetting (dev, dev->info->alt); + res = set_altsetting(dev, dev->info->alt); if (res) { - dev_err (&intf->dev, + dev_err(&intf->dev, "set altsetting to %d failed, %d\n", dev->info->alt, res); mutex_unlock(&dev->lock); @@ -1614,7 +1622,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) * FIXME add more tests! cancel requests, verify the data, control * queueing, concurrent read+write threads, and so on. */ - do_gettimeofday (&start); + do_gettimeofday(&start); switch (param->test_num) { case 0: @@ -1629,14 +1637,14 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) dev_info(&intf->dev, "TEST 1: write %d bytes %u times\n", param->length, param->iterations); - urb = simple_alloc_urb (udev, dev->out_pipe, param->length); + urb = simple_alloc_urb(udev, dev->out_pipe, param->length); if (!urb) { retval = -ENOMEM; break; } - // FIRMWARE: bulk sink (maybe accepts short writes) + /* FIRMWARE: bulk sink (maybe accepts short writes) */ retval = simple_io(dev, urb, param->iterations, 0, 0, "test1"); - simple_free_urb (urb); + simple_free_urb(urb); break; case 2: if (dev->in_pipe == 0) @@ -1644,14 +1652,14 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) dev_info(&intf->dev, "TEST 2: read %d bytes %u times\n", param->length, param->iterations); - urb = simple_alloc_urb (udev, dev->in_pipe, param->length); + urb = simple_alloc_urb(udev, dev->in_pipe, param->length); if (!urb) { retval = -ENOMEM; break; } - // FIRMWARE: bulk source (maybe generates short writes) + /* FIRMWARE: bulk source (maybe generates short writes) */ retval = simple_io(dev, urb, param->iterations, 0, 0, "test2"); - simple_free_urb (urb); + simple_free_urb(urb); break; case 3: if (dev->out_pipe == 0 || param->vary == 0) @@ -1659,15 +1667,15 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) dev_info(&intf->dev, "TEST 3: write/%d 0..%d bytes %u times\n", param->vary, param->length, param->iterations); - urb = simple_alloc_urb (udev, dev->out_pipe, param->length); + urb = simple_alloc_urb(udev, dev->out_pipe, param->length); if (!urb) { retval = -ENOMEM; break; } - // FIRMWARE: bulk sink (maybe accepts short writes) + /* FIRMWARE: bulk sink (maybe accepts short writes) */ retval = simple_io(dev, urb, param->iterations, param->vary, 0, "test3"); - simple_free_urb (urb); + simple_free_urb(urb); break; case 4: if (dev->in_pipe == 0 || param->vary == 0) @@ -1675,15 +1683,15 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) dev_info(&intf->dev, "TEST 4: read/%d 0..%d bytes %u times\n", param->vary, param->length, param->iterations); - urb = simple_alloc_urb (udev, dev->in_pipe, param->length); + urb = simple_alloc_urb(udev, dev->in_pipe, param->length); if (!urb) { retval = -ENOMEM; break; } - // FIRMWARE: bulk source (maybe generates short writes) + /* FIRMWARE: bulk source (maybe generates short writes) */ retval = simple_io(dev, urb, param->iterations, param->vary, 0, "test4"); - simple_free_urb (urb); + simple_free_urb(urb); break; /* Queued bulk I/O tests */ @@ -1694,15 +1702,15 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 5: write %d sglists %d entries of %d bytes\n", param->iterations, param->sglen, param->length); - sg = alloc_sglist (param->sglen, param->length, 0); + sg = alloc_sglist(param->sglen, param->length, 0); if (!sg) { retval = -ENOMEM; break; } - // FIRMWARE: bulk sink (maybe accepts short writes) + /* FIRMWARE: bulk sink (maybe accepts short writes) */ retval = perform_sglist(dev, param->iterations, dev->out_pipe, &req, sg, param->sglen); - free_sglist (sg, param->sglen); + free_sglist(sg, param->sglen); break; case 6: @@ -1712,15 +1720,15 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 6: read %d sglists %d entries of %d bytes\n", param->iterations, param->sglen, param->length); - sg = alloc_sglist (param->sglen, param->length, 0); + sg = alloc_sglist(param->sglen, param->length, 0); if (!sg) { retval = -ENOMEM; break; } - // FIRMWARE: bulk source (maybe generates short writes) + /* FIRMWARE: bulk source (maybe generates short writes) */ retval = perform_sglist(dev, param->iterations, dev->in_pipe, &req, sg, param->sglen); - free_sglist (sg, param->sglen); + free_sglist(sg, param->sglen); break; case 7: if (dev->out_pipe == 0 || param->sglen == 0 || param->vary == 0) @@ -1729,15 +1737,15 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 7: write/%d %d sglists %d entries 0..%d bytes\n", param->vary, param->iterations, param->sglen, param->length); - sg = alloc_sglist (param->sglen, param->length, param->vary); + sg = alloc_sglist(param->sglen, param->length, param->vary); if (!sg) { retval = -ENOMEM; break; } - // FIRMWARE: bulk sink (maybe accepts short writes) + /* FIRMWARE: bulk sink (maybe accepts short writes) */ retval = perform_sglist(dev, param->iterations, dev->out_pipe, &req, sg, param->sglen); - free_sglist (sg, param->sglen); + free_sglist(sg, param->sglen); break; case 8: if (dev->in_pipe == 0 || param->sglen == 0 || param->vary == 0) @@ -1746,15 +1754,15 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 8: read/%d %d sglists %d entries 0..%d bytes\n", param->vary, param->iterations, param->sglen, param->length); - sg = alloc_sglist (param->sglen, param->length, param->vary); + sg = alloc_sglist(param->sglen, param->length, param->vary); if (!sg) { retval = -ENOMEM; break; } - // FIRMWARE: bulk source (maybe generates short writes) + /* FIRMWARE: bulk source (maybe generates short writes) */ retval = perform_sglist(dev, param->iterations, dev->in_pipe, &req, sg, param->sglen); - free_sglist (sg, param->sglen); + free_sglist(sg, param->sglen); break; /* non-queued sanity tests for control (chapter 9 subset) */ @@ -1764,7 +1772,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 9: ch9 (subset) control tests, %d times\n", param->iterations); for (i = param->iterations; retval == 0 && i--; /* NOP */) - retval = ch9_postconfig (dev); + retval = ch9_postconfig(dev); if (retval) dev_err(&intf->dev, "ch9 subset failed, " "iterations left %d\n", i); @@ -1779,7 +1787,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 10: queue %d control calls, %d times\n", param->sglen, param->iterations); - retval = test_ctrl_queue (dev, param); + retval = test_ctrl_queue(dev, param); break; /* simple non-queued unlinks (ring with one urb) */ @@ -1790,7 +1798,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) dev_info(&intf->dev, "TEST 11: unlink %d reads of %d\n", param->iterations, param->length); for (i = param->iterations; retval == 0 && i--; /* NOP */) - retval = unlink_simple (dev, dev->in_pipe, + retval = unlink_simple(dev, dev->in_pipe, param->length); if (retval) dev_err(&intf->dev, "unlink reads failed %d, " @@ -1803,7 +1811,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) dev_info(&intf->dev, "TEST 12: unlink %d writes of %d\n", param->iterations, param->length); for (i = param->iterations; retval == 0 && i--; /* NOP */) - retval = unlink_simple (dev, dev->out_pipe, + retval = unlink_simple(dev, dev->out_pipe, param->length); if (retval) dev_err(&intf->dev, "unlink writes failed %d, " @@ -1818,7 +1826,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) dev_info(&intf->dev, "TEST 13: set/clear %d halts\n", param->iterations); for (i = param->iterations; retval == 0 && i--; /* NOP */) - retval = halt_simple (dev); + retval = halt_simple(dev); if (retval) ERROR(dev, "halts failed, iterations left %d\n", i); @@ -1844,8 +1852,8 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 15: write %d iso, %d entries of %d bytes\n", param->iterations, param->sglen, param->length); - // FIRMWARE: iso sink - retval = test_iso_queue (dev, param, + /* FIRMWARE: iso sink */ + retval = test_iso_queue(dev, param, dev->out_iso_pipe, dev->iso_out); break; @@ -1857,17 +1865,17 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) "TEST 16: read %d iso, %d entries of %d bytes\n", param->iterations, param->sglen, param->length); - // FIRMWARE: iso source - retval = test_iso_queue (dev, param, + /* FIRMWARE: iso source */ + retval = test_iso_queue(dev, param, dev->in_iso_pipe, dev->iso_in); break; - // FIXME unlink from queue (ring with N urbs) + /* FIXME unlink from queue (ring with N urbs) */ - // FIXME scatterlist cancel (needs helper thread) + /* FIXME scatterlist cancel (needs helper thread) */ } - do_gettimeofday (¶m->duration); + do_gettimeofday(¶m->duration); param->duration.tv_sec -= start.tv_sec; param->duration.tv_usec -= start.tv_usec; if (param->duration.tv_usec < 0) { @@ -1880,22 +1888,22 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) /*-------------------------------------------------------------------------*/ -static unsigned force_interrupt = 0; -module_param (force_interrupt, uint, 0); -MODULE_PARM_DESC (force_interrupt, "0 = test default; else interrupt"); +static unsigned force_interrupt; +module_param(force_interrupt, uint, 0); +MODULE_PARM_DESC(force_interrupt, "0 = test default; else interrupt"); #ifdef GENERIC static unsigned short vendor; module_param(vendor, ushort, 0); -MODULE_PARM_DESC (vendor, "vendor code (from usb-if)"); +MODULE_PARM_DESC(vendor, "vendor code (from usb-if)"); static unsigned short product; module_param(product, ushort, 0); -MODULE_PARM_DESC (product, "product code (from vendor)"); +MODULE_PARM_DESC(product, "product code (from vendor)"); #endif static int -usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) +usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev; struct usbtest_dev *dev; @@ -1903,7 +1911,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) char *rtest, *wtest; char *irtest, *iwtest; - udev = interface_to_usbdev (intf); + udev = interface_to_usbdev(intf); #ifdef GENERIC /* specify devices by module parameters? */ @@ -1930,8 +1938,9 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) dev->intf = intf; /* cacheline-aligned scratch for i/o */ - if ((dev->buf = kmalloc (TBUF_SIZE, GFP_KERNEL)) == NULL) { - kfree (dev); + dev->buf = kmalloc(TBUF_SIZE, GFP_KERNEL); + if (dev->buf == NULL) { + kfree(dev); return -ENOMEM; } @@ -1943,18 +1952,18 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) irtest = iwtest = ""; if (force_interrupt || udev->speed == USB_SPEED_LOW) { if (info->ep_in) { - dev->in_pipe = usb_rcvintpipe (udev, info->ep_in); + dev->in_pipe = usb_rcvintpipe(udev, info->ep_in); rtest = " intr-in"; } if (info->ep_out) { - dev->out_pipe = usb_sndintpipe (udev, info->ep_out); + dev->out_pipe = usb_sndintpipe(udev, info->ep_out); wtest = " intr-out"; } } else { if (info->autoconf) { int status; - status = get_endpoints (dev, intf); + status = get_endpoints(dev, intf); if (status < 0) { WARNING(dev, "couldn't get endpoints, %d\n", status); @@ -1963,10 +1972,10 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) /* may find bulk or ISO pipes */ } else { if (info->ep_in) - dev->in_pipe = usb_rcvbulkpipe (udev, + dev->in_pipe = usb_rcvbulkpipe(udev, info->ep_in); if (info->ep_out) - dev->out_pipe = usb_sndbulkpipe (udev, + dev->out_pipe = usb_sndbulkpipe(udev, info->ep_out); } if (dev->in_pipe) @@ -1979,15 +1988,23 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) iwtest = " iso-out"; } - usb_set_intfdata (intf, dev); - dev_info (&intf->dev, "%s\n", info->name); - dev_info (&intf->dev, "%s speed {control%s%s%s%s%s} tests%s\n", + usb_set_intfdata(intf, dev); + dev_info(&intf->dev, "%s\n", info->name); + dev_info(&intf->dev, "%s speed {control%s%s%s%s%s} tests%s\n", ({ char *tmp; switch (udev->speed) { - case USB_SPEED_LOW: tmp = "low"; break; - case USB_SPEED_FULL: tmp = "full"; break; - case USB_SPEED_HIGH: tmp = "high"; break; - default: tmp = "unknown"; break; + case USB_SPEED_LOW: + tmp = "low"; + break; + case USB_SPEED_FULL: + tmp = "full"; + break; + case USB_SPEED_HIGH: + tmp = "high"; + break; + default: + tmp = "unknown"; + break; }; tmp; }), info->ctrl_out ? " in/out" : "", rtest, wtest, @@ -1996,24 +2013,24 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) return 0; } -static int usbtest_suspend (struct usb_interface *intf, pm_message_t message) +static int usbtest_suspend(struct usb_interface *intf, pm_message_t message) { return 0; } -static int usbtest_resume (struct usb_interface *intf) +static int usbtest_resume(struct usb_interface *intf) { return 0; } -static void usbtest_disconnect (struct usb_interface *intf) +static void usbtest_disconnect(struct usb_interface *intf) { - struct usbtest_dev *dev = usb_get_intfdata (intf); + struct usbtest_dev *dev = usb_get_intfdata(intf); - usb_set_intfdata (intf, NULL); - dev_dbg (&intf->dev, "disconnect\n"); - kfree (dev); + usb_set_intfdata(intf, NULL); + dev_dbg(&intf->dev, "disconnect\n"); + kfree(dev); } /* Basic testing only needs a device that can source or sink bulk traffic. @@ -2050,9 +2067,9 @@ static struct usbtest_info fw_info = { .ep_in = 2, .ep_out = 2, .alt = 1, - .autoconf = 1, // iso and ctrl_out need autoconf + .autoconf = 1, /* iso and ctrl_out need autoconf */ .ctrl_out = 1, - .iso = 1, // iso_ep's are #8 in/out + .iso = 1, /* iso_ep's are #8 in/out */ }; /* peripheral running Linux and 'zero.c' test firmware, or @@ -2109,56 +2126,56 @@ static const struct usb_device_id id_table[] = { */ /* generic EZ-USB FX controller */ - { USB_DEVICE (0x0547, 0x2235), + { USB_DEVICE(0x0547, 0x2235), .driver_info = (unsigned long) &ez1_info, - }, + }, /* CY3671 development board with EZ-USB FX */ - { USB_DEVICE (0x0547, 0x0080), + { USB_DEVICE(0x0547, 0x0080), .driver_info = (unsigned long) &ez1_info, - }, + }, /* generic EZ-USB FX2 controller (or development board) */ - { USB_DEVICE (0x04b4, 0x8613), + { USB_DEVICE(0x04b4, 0x8613), .driver_info = (unsigned long) &ez2_info, - }, + }, /* re-enumerated usb test device firmware */ - { USB_DEVICE (0xfff0, 0xfff0), + { USB_DEVICE(0xfff0, 0xfff0), .driver_info = (unsigned long) &fw_info, - }, + }, /* "Gadget Zero" firmware runs under Linux */ - { USB_DEVICE (0x0525, 0xa4a0), + { USB_DEVICE(0x0525, 0xa4a0), .driver_info = (unsigned long) &gz_info, - }, + }, /* so does a user-mode variant */ - { USB_DEVICE (0x0525, 0xa4a4), + { USB_DEVICE(0x0525, 0xa4a4), .driver_info = (unsigned long) &um_info, - }, + }, /* ... and a user-mode variant that talks iso */ - { USB_DEVICE (0x0525, 0xa4a3), + { USB_DEVICE(0x0525, 0xa4a3), .driver_info = (unsigned long) &um2_info, - }, + }, #ifdef KEYSPAN_19Qi /* Keyspan 19qi uses an21xx (original EZ-USB) */ - // this does not coexist with the real Keyspan 19qi driver! - { USB_DEVICE (0x06cd, 0x010b), + /* this does not coexist with the real Keyspan 19qi driver! */ + { USB_DEVICE(0x06cd, 0x010b), .driver_info = (unsigned long) &ez1_info, - }, + }, #endif /*-------------------------------------------------------------*/ #ifdef IBOT2 /* iBOT2 makes a nice source of high speed bulk-in data */ - // this does not coexist with a real iBOT2 driver! - { USB_DEVICE (0x0b62, 0x0059), + /* this does not coexist with a real iBOT2 driver! */ + { USB_DEVICE(0x0b62, 0x0059), .driver_info = (unsigned long) &ibot2_info, - }, + }, #endif /*-------------------------------------------------------------*/ @@ -2172,7 +2189,7 @@ static const struct usb_device_id id_table[] = { { } }; -MODULE_DEVICE_TABLE (usb, id_table); +MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver usbtest_driver = { .name = "usbtest", @@ -2186,22 +2203,22 @@ static struct usb_driver usbtest_driver = { /*-------------------------------------------------------------------------*/ -static int __init usbtest_init (void) +static int __init usbtest_init(void) { #ifdef GENERIC if (vendor) pr_debug("params: vend=0x%04x prod=0x%04x\n", vendor, product); #endif - return usb_register (&usbtest_driver); + return usb_register(&usbtest_driver); } -module_init (usbtest_init); +module_init(usbtest_init); -static void __exit usbtest_exit (void) +static void __exit usbtest_exit(void) { - usb_deregister (&usbtest_driver); + usb_deregister(&usbtest_driver); } -module_exit (usbtest_exit); +module_exit(usbtest_exit); -MODULE_DESCRIPTION ("USB Core/HCD Testing Driver"); -MODULE_LICENSE ("GPL"); +MODULE_DESCRIPTION("USB Core/HCD Testing Driver"); +MODULE_LICENSE("GPL"); From 40aed5241e4e5363c11acc841f6ef794b2c25668 Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Fri, 1 Oct 2010 00:20:48 +0200 Subject: [PATCH 090/141] USB: usbtest - ensure correct isoc data length Check the data length of isochronous transfers is as expected. With this test #16 will now fail if the device side sends no data. Signed-off-by: Martin Fuzzey Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbtest.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index bb078ebb8e81..a35b427c0bac 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -1371,6 +1371,8 @@ static void iso_callback(struct urb *urb) ctx->errors += urb->error_count; else if (urb->status != 0) ctx->errors += urb->number_of_packets; + else if (urb->actual_length != urb->transfer_buffer_length) + ctx->errors++; if (urb->status == 0 && ctx->count > (ctx->pending - 1) && !ctx->submit_error) { From e6da55cb0aa36f30168da8c20ceccdc538b054be Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Fri, 1 Oct 2010 00:21:38 +0200 Subject: [PATCH 091/141] USB: imx21-hcd: remove unused variable Remove a local variable left over from some debugging code. Signed-off-by: Martin Fuzzey Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/imx21-hcd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index 3e5630369c31..6c0848b66e25 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -1007,7 +1007,6 @@ static int imx21_hc_urb_enqueue(struct usb_hcd *hcd, struct etd_priv *etd; int ret; unsigned long flags; - int new_ep = 0; dev_vdbg(imx21->dev, "enqueue urb=%p ep=%p len=%d " @@ -1035,7 +1034,6 @@ static int imx21_hc_urb_enqueue(struct usb_hcd *hcd, } ep->hcpriv = ep_priv; ep_priv->ep = ep; - new_ep = 1; } ret = usb_hcd_link_urb_to_ep(hcd, urb); From b2a068d058e71519e14d2c03e92459c4c1d63c8b Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Fri, 1 Oct 2010 00:21:43 +0200 Subject: [PATCH 092/141] USB: imx21-hcd: refactor hardware data memory management We already have fields describing the hardware data memory (dmem_size and dmem_offset) in the HCD private data, use them rather than the rather obscure read from the hardware descriptor. Signed-off-by: Martin Fuzzey Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/imx21-hcd.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index 6c0848b66e25..1be144167da4 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -323,16 +323,23 @@ static void activate_queued_etd(struct imx21 *imx21, etd_writel(imx21, etd_num, 1, ((dmem_offset + maxpacket) << DW1_YBUFSRTAD) | dmem_offset); + etd->dmem_offset = dmem_offset; urb_priv->active = 1; activate_etd(imx21, etd_num, etd->dma_handle, dir); } -static void free_dmem(struct imx21 *imx21, int offset) +static void free_dmem(struct imx21 *imx21, struct etd_priv *etd) { struct imx21_dmem_area *area; - struct etd_priv *etd, *tmp; + struct etd_priv *tmp; int found = 0; + int offset; + if (!etd->dmem_size) + return; + etd->dmem_size = 0; + + offset = etd->dmem_offset; list_for_each_entry(area, &imx21->dmem_list, list) { if (area->offset == offset) { debug_dmem_freed(imx21, area->size); @@ -734,9 +741,7 @@ static void dequeue_isoc_urb(struct imx21 *imx21, struct etd_priv *etd = imx21->etd + etd_num; reset_etd(imx21, etd_num); - if (etd->dmem_size) - free_dmem(imx21, etd->dmem_offset); - etd->dmem_size = 0; + free_dmem(imx21, etd); } } } @@ -761,7 +766,6 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb) int state = urb_priv->state; int etd_num = ep_priv->etd[0]; struct etd_priv *etd; - int dmem_offset; u32 count; u16 etd_buf_size; u16 maxpacket; @@ -855,8 +859,8 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb) /* allocate x and y buffer space at once */ etd->dmem_size = (count > maxpacket) ? maxpacket * 2 : maxpacket; - dmem_offset = alloc_dmem(imx21, etd->dmem_size, urb_priv->ep); - if (dmem_offset < 0) { + etd->dmem_offset = alloc_dmem(imx21, etd->dmem_size, urb_priv->ep); + if (etd->dmem_offset < 0) { /* Setup everything we can in HW and update when we get DMEM */ etd_writel(imx21, etd_num, 1, (u32)maxpacket << 16); @@ -867,8 +871,8 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb) } etd_writel(imx21, etd_num, 1, - (((u32) dmem_offset + (u32) maxpacket) << DW1_YBUFSRTAD) | - (u32) dmem_offset); + (((u32) etd->dmem_offset + (u32) maxpacket) << DW1_YBUFSRTAD) | + (u32) etd->dmem_offset); urb_priv->active = 1; @@ -886,7 +890,6 @@ static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num) u32 etd_mask = 1 << etd_num; struct urb_priv *urb_priv = urb->hcpriv; int dir; - u16 xbufaddr; int cc; u32 bytes_xfrd; int etd_done; @@ -894,7 +897,6 @@ static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num) disactivate_etd(imx21, etd_num); dir = (etd_readl(imx21, etd_num, 0) >> DW0_DIRECT) & 0x3; - xbufaddr = etd_readl(imx21, etd_num, 1) & 0xffff; cc = (etd_readl(imx21, etd_num, 2) >> DW2_COMPCODE) & 0xf; bytes_xfrd = etd->len - (etd_readl(imx21, etd_num, 3) & 0x1fffff); @@ -907,7 +909,7 @@ static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num) clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask); clear_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask); } - free_dmem(imx21, xbufaddr); + free_dmem(imx21, etd); urb->error_count = 0; if (!(urb->transfer_flags & URB_SHORT_NOT_OK) @@ -1123,7 +1125,7 @@ static int imx21_hc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int etd_num = ep_priv->etd[0]; if (etd_num != -1) { disactivate_etd(imx21, etd_num); - free_dmem(imx21, etd_readl(imx21, etd_num, 1) & 0xffff); + free_dmem(imx21, &imx21->etd[etd_num]); imx21->etd[etd_num].urb = NULL; } } From 7a7e7896422baced4757070b813ba28ab24a214a Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Fri, 1 Oct 2010 00:21:48 +0200 Subject: [PATCH 093/141] USB: imx21-hcd: Fix isochronous endpoint idle Release the hardware resources and reset the internal HCD state associated with an isochronous endpoint when the last URB queued for it completes. Previously this was only done in then endpoint_disable() method causing usbtest 15 and 16 to hang when run twice in succession without a disconnect. Signed-off-by: Martin Fuzzey Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/imx21-hcd.c | 56 +++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index 1be144167da4..890a41ccc5cd 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -390,15 +390,19 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb); /* Endpoint now idle - release it's ETD(s) or asssign to queued request */ static void ep_idle(struct imx21 *imx21, struct ep_priv *ep_priv) { - int etd_num; int i; for (i = 0; i < NUM_ISO_ETDS; i++) { - etd_num = ep_priv->etd[i]; + int etd_num = ep_priv->etd[i]; + struct etd_priv *etd; if (etd_num < 0) continue; + etd = &imx21->etd[etd_num]; ep_priv->etd[i] = -1; + + free_dmem(imx21, etd); /* for isoc */ + if (list_empty(&imx21->queue_for_etd)) { free_etd(imx21, etd_num); continue; @@ -576,30 +580,43 @@ static struct ep_priv *alloc_isoc_ep( int i; ep_priv = kzalloc(sizeof(struct ep_priv), GFP_ATOMIC); - if (ep_priv == NULL) + if (!ep_priv) return NULL; - /* Allocate the ETDs */ - for (i = 0; i < NUM_ISO_ETDS; i++) { - ep_priv->etd[i] = alloc_etd(imx21); - if (ep_priv->etd[i] < 0) { - int j; - dev_err(imx21->dev, "isoc: Couldn't allocate etd\n"); - for (j = 0; j < i; j++) - free_etd(imx21, ep_priv->etd[j]); - goto alloc_etd_failed; - } - imx21->etd[ep_priv->etd[i]].ep = ep; - } + for (i = 0; i < NUM_ISO_ETDS; i++) + ep_priv->etd[i] = -1; INIT_LIST_HEAD(&ep_priv->td_list); ep_priv->ep = ep; ep->hcpriv = ep_priv; return ep_priv; +} + +static int alloc_isoc_etds(struct imx21 *imx21, struct ep_priv *ep_priv) +{ + int i, j; + int etd_num; + + /* Allocate the ETDs if required */ + for (i = 0; i < NUM_ISO_ETDS; i++) { + if (ep_priv->etd[i] < 0) { + etd_num = alloc_etd(imx21); + if (etd_num < 0) + goto alloc_etd_failed; + + ep_priv->etd[i] = etd_num; + imx21->etd[etd_num].ep = ep_priv->ep; + } + } + return 0; alloc_etd_failed: - kfree(ep_priv); - return NULL; + dev_err(imx21->dev, "isoc: Couldn't allocate etd\n"); + for (j = 0; j < i; j++) { + free_etd(imx21, ep_priv->etd[j]); + ep_priv->etd[j] = -1; + } + return -ENOMEM; } static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd, @@ -639,6 +656,10 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd, ep_priv = ep->hcpriv; } + ret = alloc_isoc_etds(imx21, ep_priv); + if (ret) + goto alloc_etd_failed; + ret = usb_hcd_link_urb_to_ep(hcd, urb); if (ret) goto link_failed; @@ -718,6 +739,7 @@ alloc_dmem_failed: usb_hcd_unlink_urb_from_ep(hcd, urb); link_failed: +alloc_etd_failed: alloc_ep_failed: spin_unlock_irqrestore(&imx21->lock, flags); kfree(urb_priv->isoc_td); From 1dae423dd9b247b048eda00cb598c755e5933213 Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Fri, 1 Oct 2010 00:21:55 +0200 Subject: [PATCH 094/141] USB: introduce unmap_urb_setup_for_dma() Split unmap_urb_for_dma() to allow just the setup buffer to be unmapped. This allows HCDs to use PIO for the setup buffer if it is not suitable for DMA. Signed-off-by: Martin Fuzzey Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 18 +++++++++++++----- include/linux/usb/hcd.h | 1 + 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index cb2d894321da..61800f77dac8 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1263,10 +1263,8 @@ static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle, *dma_handle = 0; } -void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) +void unmap_urb_setup_for_dma(struct usb_hcd *hcd, struct urb *urb) { - enum dma_data_direction dir; - if (urb->transfer_flags & URB_SETUP_MAP_SINGLE) dma_unmap_single(hcd->self.controller, urb->setup_dma, @@ -1279,6 +1277,17 @@ void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) sizeof(struct usb_ctrlrequest), DMA_TO_DEVICE); + /* Make it safe to call this routine more than once */ + urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL); +} +EXPORT_SYMBOL_GPL(unmap_urb_setup_for_dma); + +void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) +{ + enum dma_data_direction dir; + + unmap_urb_setup_for_dma(hcd, urb); + dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; if (urb->transfer_flags & URB_DMA_MAP_SG) dma_unmap_sg(hcd->self.controller, @@ -1303,8 +1312,7 @@ void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) dir); /* Make it safe to call this routine more than once */ - urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL | - URB_DMA_MAP_SG | URB_DMA_MAP_PAGE | + urb->transfer_flags &= ~(URB_DMA_MAP_SG | URB_DMA_MAP_PAGE | URB_DMA_MAP_SINGLE | URB_MAP_LOCAL); } EXPORT_SYMBOL_GPL(unmap_urb_for_dma); diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index fe89f7c298aa..0b6e751ea0b1 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -329,6 +329,7 @@ extern int usb_hcd_submit_urb(struct urb *urb, gfp_t mem_flags); extern int usb_hcd_unlink_urb(struct urb *urb, int status); extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status); +extern void unmap_urb_setup_for_dma(struct usb_hcd *, struct urb *); extern void unmap_urb_for_dma(struct usb_hcd *, struct urb *); extern void usb_hcd_flush_endpoint(struct usb_device *udev, struct usb_host_endpoint *ep); From d0cc3d4100e829d726d7c0fbf5b7b8d2146f60ba Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Fri, 1 Oct 2010 00:21:59 +0200 Subject: [PATCH 095/141] USB: imx21-hcd accept arbitary transfer buffer alignement. The hardware can only do DMA to 4 byte aligned addresses. When this requirement is not met use PIO or a bounce buffer. PIO is used when the buffer is small enough to directly use the hardware data memory (2*maxpacket). A bounce buffer is used for larger transfers. Signed-off-by: Martin Fuzzey Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/imx21-hcd.c | 196 +++++++++++++++++++++++++++++------ drivers/usb/host/imx21-hcd.h | 8 +- 2 files changed, 169 insertions(+), 35 deletions(-) diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index 890a41ccc5cd..dd132eb7fee7 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -57,6 +57,7 @@ #include #include #include +#include #include "imx21-hcd.h" @@ -136,9 +137,18 @@ static int imx21_hc_get_frame(struct usb_hcd *hcd) return wrap_frame(readl(imx21->regs + USBH_FRMNUB)); } +static inline bool unsuitable_for_dma(dma_addr_t addr) +{ + return (addr & 3) != 0; +} #include "imx21-dbg.c" +static void nonisoc_urb_completed_for_etd( + struct imx21 *imx21, struct etd_priv *etd, int status); +static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb); +static void free_dmem(struct imx21 *imx21, struct etd_priv *etd); + /* =========================================== */ /* ETD management */ /* =========================================== */ @@ -185,7 +195,8 @@ static void reset_etd(struct imx21 *imx21, int num) etd_writel(imx21, num, i, 0); etd->urb = NULL; etd->ep = NULL; - etd->td = NULL;; + etd->td = NULL; + etd->bounce_buffer = NULL; } static void free_etd(struct imx21 *imx21, int num) @@ -221,26 +232,94 @@ static void setup_etd_dword0(struct imx21 *imx21, ((u32) maxpacket << DW0_MAXPKTSIZ)); } -static void activate_etd(struct imx21 *imx21, - int etd_num, dma_addr_t dma, u8 dir) +/** + * Copy buffer to data controller data memory. + * We cannot use memcpy_toio() because the hardware requires 32bit writes + */ +static void copy_to_dmem( + struct imx21 *imx21, int dmem_offset, void *src, int count) +{ + void __iomem *dmem = imx21->regs + USBOTG_DMEM + dmem_offset; + u32 word = 0; + u8 *p = src; + int byte = 0; + int i; + + for (i = 0; i < count; i++) { + byte = i % 4; + word += (*p++ << (byte * 8)); + if (byte == 3) { + writel(word, dmem); + dmem += 4; + word = 0; + } + } + + if (count && byte != 3) + writel(word, dmem); +} + +static void activate_etd(struct imx21 *imx21, int etd_num, u8 dir) { u32 etd_mask = 1 << etd_num; struct etd_priv *etd = &imx21->etd[etd_num]; + if (etd->dma_handle && unsuitable_for_dma(etd->dma_handle)) { + /* For non aligned isoc the condition below is always true */ + if (etd->len <= etd->dmem_size) { + /* Fits into data memory, use PIO */ + if (dir != TD_DIR_IN) { + copy_to_dmem(imx21, + etd->dmem_offset, + etd->cpu_buffer, etd->len); + } + etd->dma_handle = 0; + + } else { + /* Too big for data memory, use bounce buffer */ + enum dma_data_direction dmadir; + + if (dir == TD_DIR_IN) { + dmadir = DMA_FROM_DEVICE; + etd->bounce_buffer = kmalloc(etd->len, + GFP_ATOMIC); + } else { + dmadir = DMA_TO_DEVICE; + etd->bounce_buffer = kmemdup(etd->cpu_buffer, + etd->len, + GFP_ATOMIC); + } + if (!etd->bounce_buffer) { + dev_err(imx21->dev, "failed bounce alloc\n"); + goto err_bounce_alloc; + } + + etd->dma_handle = + dma_map_single(imx21->dev, + etd->bounce_buffer, + etd->len, + dmadir); + if (dma_mapping_error(imx21->dev, etd->dma_handle)) { + dev_err(imx21->dev, "failed bounce map\n"); + goto err_bounce_map; + } + } + } + clear_toggle_bit(imx21, USBH_ETDDONESTAT, etd_mask); set_register_bits(imx21, USBH_ETDDONEEN, etd_mask); clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask); clear_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask); - if (dma) { + if (etd->dma_handle) { set_register_bits(imx21, USB_ETDDMACHANLCLR, etd_mask); clear_toggle_bit(imx21, USBH_XBUFSTAT, etd_mask); clear_toggle_bit(imx21, USBH_YBUFSTAT, etd_mask); - writel(dma, imx21->regs + USB_ETDSMSA(etd_num)); + writel(etd->dma_handle, imx21->regs + USB_ETDSMSA(etd_num)); set_register_bits(imx21, USB_ETDDMAEN, etd_mask); } else { if (dir != TD_DIR_IN) { - /* need to set for ZLP */ + /* need to set for ZLP and PIO */ set_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask); set_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask); } @@ -263,6 +342,14 @@ static void activate_etd(struct imx21 *imx21, etd->active_count = 1; writel(etd_mask, imx21->regs + USBH_ETDENSET); + return; + +err_bounce_map: + kfree(etd->bounce_buffer); + +err_bounce_alloc: + free_dmem(imx21, etd); + nonisoc_urb_completed_for_etd(imx21, etd, -ENOMEM); } /* =========================================== */ @@ -325,7 +412,7 @@ static void activate_queued_etd(struct imx21 *imx21, etd->dmem_offset = dmem_offset; urb_priv->active = 1; - activate_etd(imx21, etd_num, etd->dma_handle, dir); + activate_etd(imx21, etd_num, dir); } static void free_dmem(struct imx21 *imx21, struct etd_priv *etd) @@ -385,7 +472,6 @@ static void free_epdmem(struct imx21 *imx21, struct usb_host_endpoint *ep) /* =========================================== */ /* End handling */ /* =========================================== */ -static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb); /* Endpoint now idle - release it's ETD(s) or asssign to queued request */ static void ep_idle(struct imx21 *imx21, struct ep_priv *ep_priv) @@ -448,6 +534,24 @@ __acquires(imx21->lock) ep_idle(imx21, ep_priv); } +static void nonisoc_urb_completed_for_etd( + struct imx21 *imx21, struct etd_priv *etd, int status) +{ + struct usb_host_endpoint *ep = etd->ep; + + urb_done(imx21->hcd, etd->urb, status); + etd->urb = NULL; + + if (!list_empty(&ep->urb_list)) { + struct urb *urb = list_first_entry( + &ep->urb_list, struct urb, urb_list); + + dev_vdbg(imx21->dev, "next URB %p\n", urb); + schedule_nonisoc_etd(imx21, urb); + } +} + + /* =========================================== */ /* ISOC Handling ... */ /* =========================================== */ @@ -500,6 +604,8 @@ too_late: etd->ep = td->ep; etd->urb = td->urb; etd->len = td->len; + etd->dma_handle = td->dma_handle; + etd->cpu_buffer = td->cpu_buffer; debug_isoc_submitted(imx21, cur_frame, td); @@ -513,16 +619,17 @@ too_late: (TD_NOTACCESSED << DW3_COMPCODE0) | (td->len << DW3_PKTLEN0)); - activate_etd(imx21, etd_num, td->data, dir); + activate_etd(imx21, etd_num, dir); } } -static void isoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num) +static void isoc_etd_done(struct usb_hcd *hcd, int etd_num) { struct imx21 *imx21 = hcd_to_imx21(hcd); int etd_mask = 1 << etd_num; - struct urb_priv *urb_priv = urb->hcpriv; struct etd_priv *etd = imx21->etd + etd_num; + struct urb *urb = etd->urb; + struct urb_priv *urb_priv = urb->hcpriv; struct td *td = etd->td; struct usb_host_endpoint *ep = etd->ep; int isoc_index = td->isoc_index; @@ -556,8 +663,13 @@ static void isoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num) bytes_xfrd, td->len, urb, etd_num, isoc_index); } - if (dir_in) + if (dir_in) { clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask); + if (!etd->dma_handle) + memcpy_fromio(etd->cpu_buffer, + imx21->regs + USBOTG_DMEM + etd->dmem_offset, + bytes_xfrd); + } urb->actual_length += bytes_xfrd; urb->iso_frame_desc[isoc_index].actual_length = bytes_xfrd; @@ -716,12 +828,14 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd, /* set up transfers */ td = urb_priv->isoc_td; for (i = 0; i < urb->number_of_packets; i++, td++) { + unsigned int offset = urb->iso_frame_desc[i].offset; td->ep = ep; td->urb = urb; td->len = urb->iso_frame_desc[i].length; td->isoc_index = i; td->frame = wrap_frame(urb->start_frame + urb->interval * i); - td->data = urb->transfer_dma + urb->iso_frame_desc[i].offset; + td->dma_handle = urb->transfer_dma + offset; + td->cpu_buffer = urb->transfer_buffer + offset; list_add_tail(&td->list, &ep_priv->td_list); } @@ -812,13 +926,15 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb) if (usb_pipecontrol(pipe) && (state != US_CTRL_DATA)) { if (state == US_CTRL_SETUP) { dir = TD_DIR_SETUP; + if (unsuitable_for_dma(urb->setup_dma)) + unmap_urb_setup_for_dma(imx21->hcd, urb); etd->dma_handle = urb->setup_dma; + etd->cpu_buffer = urb->setup_packet; bufround = 0; count = 8; datatoggle = TD_TOGGLE_DATA0; } else { /* US_CTRL_ACK */ dir = usb_pipeout(pipe) ? TD_DIR_IN : TD_DIR_OUT; - etd->dma_handle = urb->transfer_dma; bufround = 0; count = 0; datatoggle = TD_TOGGLE_DATA1; @@ -826,7 +942,11 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb) } else { dir = usb_pipeout(pipe) ? TD_DIR_OUT : TD_DIR_IN; bufround = (dir == TD_DIR_IN) ? 1 : 0; + if (unsuitable_for_dma(urb->transfer_dma)) + unmap_urb_for_dma(imx21->hcd, urb); + etd->dma_handle = urb->transfer_dma; + etd->cpu_buffer = urb->transfer_buffer; if (usb_pipebulk(pipe) && (state == US_BULK0)) count = 0; else @@ -901,14 +1021,15 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb) /* enable the ETD to kick off transfer */ dev_vdbg(imx21->dev, "Activating etd %d for %d bytes %s\n", etd_num, count, dir != TD_DIR_IN ? "out" : "in"); - activate_etd(imx21, etd_num, etd->dma_handle, dir); + activate_etd(imx21, etd_num, dir); } -static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num) +static void nonisoc_etd_done(struct usb_hcd *hcd, int etd_num) { struct imx21 *imx21 = hcd_to_imx21(hcd); struct etd_priv *etd = &imx21->etd[etd_num]; + struct urb *urb = etd->urb; u32 etd_mask = 1 << etd_num; struct urb_priv *urb_priv = urb->hcpriv; int dir; @@ -930,7 +1051,20 @@ static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num) if (dir == TD_DIR_IN) { clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask); clear_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask); + + if (etd->bounce_buffer) { + memcpy(etd->cpu_buffer, etd->bounce_buffer, bytes_xfrd); + dma_unmap_single(imx21->dev, + etd->dma_handle, etd->len, DMA_FROM_DEVICE); + } else if (!etd->dma_handle && bytes_xfrd) {/* PIO */ + memcpy_fromio(etd->cpu_buffer, + imx21->regs + USBOTG_DMEM + etd->dmem_offset, + bytes_xfrd); + } } + + kfree(etd->bounce_buffer); + etd->bounce_buffer = NULL; free_dmem(imx21, etd); urb->error_count = 0; @@ -988,24 +1122,15 @@ static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num) break; } - if (!etd_done) { + if (etd_done) + nonisoc_urb_completed_for_etd(imx21, etd, cc_to_error[cc]); + else { dev_vdbg(imx21->dev, "next state=%d\n", urb_priv->state); schedule_nonisoc_etd(imx21, urb); - } else { - struct usb_host_endpoint *ep = urb->ep; - - urb_done(hcd, urb, cc_to_error[cc]); - etd->urb = NULL; - - if (!list_empty(&ep->urb_list)) { - urb = list_first_entry(&ep->urb_list, - struct urb, urb_list); - dev_vdbg(imx21->dev, "next URB %p\n", urb); - schedule_nonisoc_etd(imx21, urb); - } } } + static struct ep_priv *alloc_ep(void) { int i; @@ -1146,9 +1271,13 @@ static int imx21_hc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, } else if (urb_priv->active) { int etd_num = ep_priv->etd[0]; if (etd_num != -1) { + struct etd_priv *etd = &imx21->etd[etd_num]; + disactivate_etd(imx21, etd_num); - free_dmem(imx21, &imx21->etd[etd_num]); - imx21->etd[etd_num].urb = NULL; + free_dmem(imx21, etd); + etd->urb = NULL; + kfree(etd->bounce_buffer); + etd->bounce_buffer = NULL; } } @@ -1248,9 +1377,9 @@ static void process_etds(struct usb_hcd *hcd, struct imx21 *imx21, int sof) } if (usb_pipeisoc(etd->urb->pipe)) - isoc_etd_done(hcd, etd->urb, etd_num); + isoc_etd_done(hcd, etd_num); else - nonisoc_etd_done(hcd, etd->urb, etd_num); + nonisoc_etd_done(hcd, etd_num); } /* only enable SOF interrupt if it may be needed for the kludge */ @@ -1718,6 +1847,7 @@ static int imx21_probe(struct platform_device *pdev) } imx21 = hcd_to_imx21(hcd); + imx21->hcd = hcd; imx21->dev = &pdev->dev; imx21->pdata = pdev->dev.platform_data; if (!imx21->pdata) diff --git a/drivers/usb/host/imx21-hcd.h b/drivers/usb/host/imx21-hcd.h index 1b0d913780a5..87b29fd971b4 100644 --- a/drivers/usb/host/imx21-hcd.h +++ b/drivers/usb/host/imx21-hcd.h @@ -250,6 +250,7 @@ #define USBCTRL_USB_BYP (1 << 2) #define USBCTRL_HOST1_TXEN_OE (1 << 1) +#define USBOTG_DMEM 0x1000 /* Values in TD blocks */ #define TD_DIR_SETUP 0 @@ -346,8 +347,8 @@ struct td { struct list_head list; struct urb *urb; struct usb_host_endpoint *ep; - dma_addr_t data; - unsigned long buf_addr; + dma_addr_t dma_handle; + void *cpu_buffer; int len; int frame; int isoc_index; @@ -360,6 +361,8 @@ struct etd_priv { struct td *td; struct list_head queue; dma_addr_t dma_handle; + void *cpu_buffer; + void *bounce_buffer; int alloc; int len; int dmem_size; @@ -412,6 +415,7 @@ struct debug_isoc_trace { struct imx21 { spinlock_t lock; struct device *dev; + struct usb_hcd *hcd; struct mx21_usbh_platform_data *pdata; struct list_head dmem_list; struct list_head queue_for_etd; /* eps queued due to etd shortage */ From 319feaabb6c7ccd90da6e3207563c265da7d21ae Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 5 Oct 2010 18:55:34 +0200 Subject: [PATCH 096/141] usb: gadget: goku_udc: Fix error path This is based on an initial patch by Rahul Ruikar. The goku_remove() function can be called before device_register() so it can call device_unregister() improperly. Also if the call to device_register() fails we need to call put_device(). As I was changing the error handling in goku_probe(), I noticed that the label was "done" but actually if the function succeeds we return earlier. I renamed the error path to "err" instead of "done." Reported-by: Rahul Ruikar Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/goku_udc.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 49fbd4dbeb94..48a760220baf 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1745,7 +1745,8 @@ static void goku_remove(struct pci_dev *pdev) pci_resource_len (pdev, 0)); if (dev->enabled) pci_disable_device(pdev); - device_unregister(&dev->gadget.dev); + if (dev->registered) + device_unregister(&dev->gadget.dev); pci_set_drvdata(pdev, NULL); dev->regs = NULL; @@ -1775,7 +1776,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (!pdev->irq) { printk(KERN_ERR "Check PCI %s IRQ setup!\n", pci_name(pdev)); retval = -ENODEV; - goto done; + goto err; } /* alloc, and start init */ @@ -1783,7 +1784,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (dev == NULL){ pr_debug("enomem %s\n", pci_name(pdev)); retval = -ENOMEM; - goto done; + goto err; } spin_lock_init(&dev->lock); @@ -1801,7 +1802,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) retval = pci_enable_device(pdev); if (retval < 0) { DBG(dev, "can't enable, %d\n", retval); - goto done; + goto err; } dev->enabled = 1; @@ -1810,7 +1811,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (!request_mem_region(resource, len, driver_name)) { DBG(dev, "controller already in use\n"); retval = -EBUSY; - goto done; + goto err; } dev->got_region = 1; @@ -1818,7 +1819,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (base == NULL) { DBG(dev, "can't map memory\n"); retval = -EFAULT; - goto done; + goto err; } dev->regs = (struct goku_udc_regs __iomem *) base; @@ -1834,7 +1835,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) driver_name, dev) != 0) { DBG(dev, "request interrupt %d failed\n", pdev->irq); retval = -EBUSY; - goto done; + goto err; } dev->got_irq = 1; if (use_dma) @@ -1845,13 +1846,16 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev); #endif - /* done */ the_controller = dev; retval = device_register(&dev->gadget.dev); - if (retval == 0) - return 0; + if (retval) { + put_device(&dev->gadget.dev); + goto err; + } + dev->registered = 1; + return 0; -done: +err: if (dev) goku_remove (pdev); return retval; From 8e04d8056c1ea0e0aab730994b74756f0526cda8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 1 Oct 2010 14:20:08 -0700 Subject: [PATCH 097/141] scsi/sr: add no_read_disc_info scsi_device flag Some USB devices emulate a usb-mass-storage attached (scsi) cdrom device, usually this fake cdrom contains the windows software for the device. While working on supporting Appotech ax3003 based photoframes, which do this I discovered that they will go of into lala land when ever they see a READ_DISC_INFO scsi command. Thus this patch adds a scsi_device flag (which can then be set by the usb-storage driver through an unsual-devs entry), to indicate this, and makes the sr driver honor this flag. I know this sucks, but as discussed on linux-scsi list there is no other way to make this device work properly. Looking at usb traces made under windows, windows never sends a READ_DISC_INFO during normal interactions with a usb cdrom device. So as this cdrom emulation thingie becomes more common we might see more of this problem. Signed-off-by: Hans de Goede Cc: James Bottomley Cc: Alan Stern Cc: Matthew Dharm Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/sr.c | 8 +++++++- include/scsi/scsi_device.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index ba9c3e0387ce..b811dd0eb240 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -862,10 +862,16 @@ static void get_capabilities(struct scsi_cd *cd) static int sr_packet(struct cdrom_device_info *cdi, struct packet_command *cgc) { + struct scsi_cd *cd = cdi->handle; + struct scsi_device *sdev = cd->device; + + if (cgc->cmd[0] == GPCMD_READ_DISC_INFO && sdev->no_read_disc_info) + return -EDRIVE_CANT_DO_THIS; + if (cgc->timeout <= 0) cgc->timeout = IOCTL_TIMEOUT; - sr_do_ioctl(cdi->handle, cgc); + sr_do_ioctl(cd, cgc); return cgc->stat; } diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 50cb34ffef11..e8c2433ad8a8 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -148,6 +148,7 @@ struct scsi_device { unsigned retry_hwerror:1; /* Retry HARDWARE_ERROR */ unsigned last_sector_bug:1; /* do not use multisector accesses on SD_LAST_BUGGY_SECTORS */ + unsigned no_read_disc_info:1; /* Avoid READ_DISC_INFO cmds */ unsigned is_visible:1; /* is the device visible in sysfs */ DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ From ae38c78a03e1b77ad45248fcf097e4568e740209 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 1 Oct 2010 14:20:10 -0700 Subject: [PATCH 098/141] usb-storage: add new no_read_disc_info quirk Appotech ax3003 (the larger brother of the ax203) based devices are even more buggy then the ax203. They will go of into lala land when ever they see a READ_DISC_INFO scsi command. So add a new US_FL which tells the scsi sr driver to not issue any READ_DISC_INFO scsi commands. [akpm@linux-foundation.org: fix build] Signed-off-by: Hans de Goede Cc: James Bottomley Cc: Alan Stern Cc: Matthew Dharm Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/scsiglue.c | 4 ++++ drivers/usb/storage/unusual_devs.h | 5 +++++ include/linux/usb_usual.h | 4 +++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index e80362d148f3..a1128ff5cc2c 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -253,6 +253,10 @@ static int slave_configure(struct scsi_device *sdev) * or to force 192-byte transfer lengths for MODE SENSE. * But they do need to use MODE SENSE(10). */ sdev->use_10_for_ms = 1; + + /* Some (fake) usb cdrom devices don't like READ_DISC_INFO */ + if (us->fflags & US_FL_NO_READ_DISC_INFO) + sdev->no_read_disc_info = 1; } /* The CB and CBI transports have no way to pass LUN values diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index f43314a22ba4..c8264ff5457e 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1858,6 +1858,11 @@ UNUSUAL_DEV( 0x1908, 0x1320, 0x0000, 0x0000, "Photo Frame", USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BAD_SENSE ), +UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200, + "BUILDWIN", + "Photo Frame", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NO_READ_DISC_INFO ), UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001, "ST", diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index f091dc6e5a00..e62e9fe08883 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -58,7 +58,9 @@ US_FLAG(CAPACITY_OK, 0x00010000) \ /* READ CAPACITY response is correct */ \ US_FLAG(BAD_SENSE, 0x00020000) \ - /* Bad Sense (never more than 18 bytes) */ + /* Bad Sense (never more than 18 bytes) */ \ + US_FLAG(NO_READ_DISC_INFO, 0x00040000) \ + /* cannot handle READ_DISC_INFO */ #define US_FLAG(name, value) US_FL_##name = value , enum { US_DO_ALL_FLAGS }; From 5ce524bdff367b4abda20bcfd4dafd9d30c773df Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 1 Oct 2010 14:20:10 -0700 Subject: [PATCH 099/141] scsi/sd: add a no_read_capacity_16 scsi_device flag I seem to have a knack for digging up buggy usb devices which don't work with Linux, and I'm crazy enough to try to make them work. So this time a friend of mine asked me to get an mp4 player (an mp3 player which can play videos on a small screen) to work with Linux. It is based on the well known rockbox chipset for which we already have an unusual devs entries to work around some of its bugs. But this model comes with an additional twist. This model chokes on read_capacity_16 calls. Now normally we don't make those calls, but this model comes with an sdcard slot and when there is no card in there (and shipped from the factory there is none), it reports a size of 0. However this time the programmers actually got the read_capacity_10 response right! So they substract one from the size as stored internally in the mp3 player before reporting it back, resulting in an answer of ... 0xffffffff sectors, causing sd.c to try a read_capacity_16, on which the device crashes. This patch adds a flag to scsi_device to indicate that a a device cannot handle read_capacity_16, and when this flag is set if a device reports an lba of 0xffffffff as answer to a read_capacity_10, assumes it tries to report a size of 0. Signed-off-by: Hans de Goede Cc: James Bottomley Cc: Alan Stern Cc: Matthew Dharm Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/sd.c | 12 ++++++++++++ include/scsi/scsi_device.h | 1 + 2 files changed, 13 insertions(+) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index ffa0689ee840..ff4c9a3aa5b2 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1498,6 +1498,9 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, unsigned long long lba; unsigned sector_size; + if (sdp->no_read_capacity_16) + return -EINVAL; + do { memset(cmd, 0, 16); cmd[0] = SERVICE_ACTION_IN; @@ -1626,6 +1629,15 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, sector_size = get_unaligned_be32(&buffer[4]); lba = get_unaligned_be32(&buffer[0]); + if (sdp->no_read_capacity_16 && (lba == 0xffffffff)) { + /* Some buggy (usb cardreader) devices return an lba of + 0xffffffff when the want to report a size of 0 (with + which they really mean no media is present) */ + sdkp->capacity = 0; + sdkp->hw_sector_size = sector_size; + return sector_size; + } + if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) { sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a " "kernel compiled with support for large block " diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index e8c2433ad8a8..85867dcde335 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -149,6 +149,7 @@ struct scsi_device { unsigned last_sector_bug:1; /* do not use multisector accesses on SD_LAST_BUGGY_SECTORS */ unsigned no_read_disc_info:1; /* Avoid READ_DISC_INFO cmds */ + unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */ unsigned is_visible:1; /* is the device visible in sysfs */ DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ From 00914025cc4e783d4703b4db1d47b41f389e50c8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 1 Oct 2010 14:20:11 -0700 Subject: [PATCH 100/141] usb-storage: add new no_read_capacity_16 quirk Some Rockbox based mp4 players will crash when ever they see a read_capacity_16 scsi command. So add a new US_FL which tells the scsi sd driver to not issue any read_capacity_16 scsi commands. Signed-off-by: Hans de Goede Cc: James Bottomley Cc: Alan Stern Cc: Matthew Dharm Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/scsiglue.c | 4 ++++ drivers/usb/storage/unusual_devs.h | 3 ++- include/linux/usb_usual.h | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index a1128ff5cc2c..a688b1e686ea 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -209,6 +209,10 @@ static int slave_configure(struct scsi_device *sdev) if (us->fflags & US_FL_CAPACITY_HEURISTICS) sdev->guess_capacity = 1; + /* Some devices cannot handle READ_CAPACITY_16 */ + if (us->fflags & US_FL_NO_READ_CAPACITY_16) + sdev->no_read_capacity_16 = 1; + /* assume SPC3 or latter devices support sense size > 18 */ if (sdev->scsi_level > SCSI_SPC_2) us->fflags |= US_FL_SANE_SENSE; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index c8264ff5457e..6ccdd3dd5259 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -877,7 +877,8 @@ UNUSUAL_DEV( 0x071b, 0x3203, 0x0000, 0x0000, "RockChip", "MP3", USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64), + US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64 | + US_FL_NO_READ_CAPACITY_16), /* Reported by Jean-Baptiste Onofre * Support the following product : diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index e62e9fe08883..71693d4a4fe1 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -60,7 +60,9 @@ US_FLAG(BAD_SENSE, 0x00020000) \ /* Bad Sense (never more than 18 bytes) */ \ US_FLAG(NO_READ_DISC_INFO, 0x00040000) \ - /* cannot handle READ_DISC_INFO */ + /* cannot handle READ_DISC_INFO */ \ + US_FLAG(NO_READ_CAPACITY_16, 0x00080000) \ + /* cannot handle READ_CAPACITY_16 */ #define US_FLAG(name, value) US_FL_##name = value , enum { US_DO_ALL_FLAGS }; From 7491f13367919d97525b73b1fd38801ac83aac06 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Mon, 27 Sep 2010 16:43:25 +0800 Subject: [PATCH 101/141] USB: do not print -ESHUTDOWN message if usb at otg device mode At otg device mode, the otg host resume should do no-op during system resume, otherwise, the otg device will be treated as a host for enumeration. So, the otg host driver returns -ESHUTDOWN if it detects the current usb mode is device mode. The host driver has to return -ESHUTDOWN, otherwise, the usb_hc_died will be called. Signed-off-by: Peter Chen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index d7a4401ef019..c0e60fbcb048 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1337,7 +1337,7 @@ int usb_resume(struct device *dev, pm_message_t msg) /* Avoid PM error messages for devices disconnected while suspended * as we'll display regular disconnect messages just a bit later. */ - if (status == -ENODEV) + if (status == -ENODEV || status == -ESHUTDOWN) status = 0; return status; } From 93ad03d60b5b18897030038234aa2ebae8234748 Mon Sep 17 00:00:00 2001 From: Anders Larsen Date: Wed, 6 Oct 2010 23:46:25 +0200 Subject: [PATCH 102/141] USB: cp210x: Add WAGO 750-923 Service Cable device ID The WAGO 750-923 USB Service Cable is used for configuration and firmware updates of several industrial automation products from WAGO Kontakttechnik GmbH. Bus 004 Device 002: ID 1be3:07a6 Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x1be3 idProduct 0x07a6 bcdDevice 1.00 iManufacturer 1 Silicon Labs iProduct 2 WAGO USB Service Cable iSerial 3 1277796751 . . . Signed-off-by: Anders Larsen Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index f72afa970503..8d7731dbf478 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -133,6 +133,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ + { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ { } /* Terminating Entry */ }; From 7b3a766c7b9bce07875098cb68642df2b8f0b152 Mon Sep 17 00:00:00 2001 From: Rahul Ruikar Date: Thu, 7 Oct 2010 09:31:12 +0530 Subject: [PATCH 103/141] usb: core: endpoint: Fix error path In function usb_create_ep_devs() call put_device() when device_register() fails. Signed-off-by: Rahul Ruikar Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/endpoint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 3788e738e265..9da250563027 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -202,7 +202,7 @@ int usb_create_ep_devs(struct device *parent, return retval; error_register: - kfree(ep_dev); + put_device(&ep_dev->dev); exit: return retval; } From 75d87cdf3cefd2744fabd3f2a558c49cdf36238b Mon Sep 17 00:00:00 2001 From: Rahul Ruikar Date: Thu, 7 Oct 2010 09:40:45 +0530 Subject: [PATCH 104/141] usb: gadget: dummy_hcd: Fix error path In function dummy_udc_probe() call put_device() when device_register() fails. also usb_get_hcd() put before device_register() after review comment from Alan Stern. Signed-off-by: Rahul Ruikar Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/dummy_hcd.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 7bb9d78aac27..1d2a2abbfa80 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -874,6 +874,8 @@ static int dummy_udc_probe (struct platform_device *pdev) struct dummy *dum = the_controller; int rc; + usb_get_hcd(dummy_to_hcd(dum)); + dum->gadget.name = gadget_name; dum->gadget.ops = &dummy_ops; dum->gadget.is_dualspeed = 1; @@ -885,10 +887,10 @@ static int dummy_udc_probe (struct platform_device *pdev) dum->gadget.dev.parent = &pdev->dev; dum->gadget.dev.release = dummy_gadget_release; rc = device_register (&dum->gadget.dev); - if (rc < 0) + if (rc < 0) { + put_device(&dum->gadget.dev); return rc; - - usb_get_hcd (dummy_to_hcd (dum)); + } platform_set_drvdata (pdev, dum); rc = device_create_file (&dum->gadget.dev, &dev_attr_function); From 0a2b8a0d1101179fdebc974a7c72b514aede9d9d Mon Sep 17 00:00:00 2001 From: matt mooney Date: Wed, 6 Oct 2010 19:03:26 -0700 Subject: [PATCH 105/141] usb: makefile cleanup For all modules, change -objs to -y; remove if-statements and replace with lists using the kbuild idiom; move flags to the top of the file; and fix alignment while trying to maintain the original scheme in each file. None of the dependencies are modified. Signed-off-by: matt mooney Acked-by: Sam Ravnborg Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/Makefile | 4 +- drivers/usb/c67x00/Makefile | 6 +-- drivers/usb/core/Makefile | 23 ++++------ drivers/usb/early/Makefile | 2 +- drivers/usb/gadget/Makefile | 39 ++++++++-------- drivers/usb/host/Makefile | 19 ++++---- drivers/usb/host/whci/Kbuild | 2 +- drivers/usb/misc/Makefile | 44 +++++++++--------- drivers/usb/misc/sisusbvga/Makefile | 3 +- drivers/usb/mon/Makefile | 2 +- drivers/usb/musb/Makefile | 71 +++++++---------------------- drivers/usb/otg/Makefile | 7 ++- drivers/usb/serial/Makefile | 9 ++-- drivers/usb/storage/Makefile | 34 +++++++------- drivers/usb/wusbcore/Makefile | 17 +++---- 15 files changed, 118 insertions(+), 164 deletions(-) diff --git a/drivers/usb/atm/Makefile b/drivers/usb/atm/Makefile index d40a126e47a3..a5d792ec3ad5 100644 --- a/drivers/usb/atm/Makefile +++ b/drivers/usb/atm/Makefile @@ -2,10 +2,10 @@ # Makefile for USB ATM/xDSL drivers # +ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG + obj-$(CONFIG_USB_CXACRU) += cxacru.o obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o obj-$(CONFIG_USB_UEAGLEATM) += ueagle-atm.o obj-$(CONFIG_USB_ATM) += usbatm.o obj-$(CONFIG_USB_XUSBATM) += xusbatm.o - -ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG diff --git a/drivers/usb/c67x00/Makefile b/drivers/usb/c67x00/Makefile index 868bc41b5980..b1218683c8ec 100644 --- a/drivers/usb/c67x00/Makefile +++ b/drivers/usb/c67x00/Makefile @@ -2,8 +2,8 @@ # Makefile for Cypress C67X00 USB Controller # -ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG +ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG -obj-$(CONFIG_USB_C67X00_HCD) += c67x00.o +obj-$(CONFIG_USB_C67X00_HCD) += c67x00.o -c67x00-objs := c67x00-drv.o c67x00-ll-hpi.o c67x00-hcd.o c67x00-sched.o +c67x00-y := c67x00-drv.o c67x00-ll-hpi.o c67x00-hcd.o c67x00-sched.o diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index 17c8e2d2a07d..507a4e1b6360 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile @@ -2,18 +2,13 @@ # Makefile for USB Core files and filesystem # -usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ - config.o file.o buffer.o sysfs.o endpoint.o \ - devio.o notify.o generic.o quirks.o devices.o - -ifeq ($(CONFIG_PCI),y) - usbcore-objs += hcd-pci.o -endif - -ifeq ($(CONFIG_USB_DEVICEFS),y) - usbcore-objs += inode.o -endif - -obj-$(CONFIG_USB) += usbcore.o - ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG + +usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o +usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o +usbcore-y += devio.o notify.o generic.o quirks.o devices.o + +usbcore-$(CONFIG_PCI) += hcd-pci.o +usbcore-$(CONFIG_USB_DEVICEFS) += inode.o + +obj-$(CONFIG_USB) += usbcore.o diff --git a/drivers/usb/early/Makefile b/drivers/usb/early/Makefile index dfedee8c45b6..24bbe519c737 100644 --- a/drivers/usb/early/Makefile +++ b/drivers/usb/early/Makefile @@ -2,4 +2,4 @@ # Makefile for early USB devices # -obj-$(CONFIG_EARLY_PRINTK_DBGP) += ehci-dbgp.o +obj-$(CONFIG_EARLY_PRINTK_DBGP) += ehci-dbgp.o diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index c68200536500..5780db42417b 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -1,7 +1,7 @@ # # USB peripheral controller drivers # -ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG +ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o obj-$(CONFIG_USB_NET2280) += net2280.o @@ -16,10 +16,8 @@ obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o obj-$(CONFIG_USB_AT91) += at91_udc.o obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o -fsl_usb2_udc-objs := fsl_udc_core.o -ifeq ($(CONFIG_ARCH_MXC),y) -fsl_usb2_udc-objs += fsl_mxc_udc.o -endif +fsl_usb2_udc-y := fsl_udc_core.o +fsl_usb2_udc-$(CONFIG_ARCH_MXC) += fsl_mxc_udc.o obj-$(CONFIG_USB_M66592) += m66592-udc.o obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o @@ -30,21 +28,21 @@ obj-$(CONFIG_USB_LANGWELL) += langwell_udc.o # # USB gadget drivers # -g_zero-objs := zero.o -g_audio-objs := audio.o -g_ether-objs := ether.o -g_serial-objs := serial.o -g_midi-objs := gmidi.o -gadgetfs-objs := inode.o -g_file_storage-objs := file_storage.o -g_mass_storage-objs := mass_storage.o -g_printer-objs := printer.o -g_cdc-objs := cdc2.o -g_multi-objs := multi.o -g_hid-objs := hid.o -g_dbgp-objs := dbgp.o -g_nokia-objs := nokia.o -g_webcam-objs := webcam.o +g_zero-y := zero.o +g_audio-y := audio.o +g_ether-y := ether.o +g_serial-y := serial.o +g_midi-y := gmidi.o +gadgetfs-y := inode.o +g_file_storage-y := file_storage.o +g_mass_storage-y := mass_storage.o +g_printer-y := printer.o +g_cdc-y := cdc2.o +g_multi-y := multi.o +g_hid-y := hid.o +g_dbgp-y := dbgp.o +g_nokia-y := nokia.o +g_webcam-y := webcam.o obj-$(CONFIG_USB_ZERO) += g_zero.o obj-$(CONFIG_USB_AUDIO) += g_audio.o @@ -62,4 +60,3 @@ obj-$(CONFIG_USB_G_DBGP) += g_dbgp.o obj-$(CONFIG_USB_G_MULTI) += g_multi.o obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o - diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 19b3a30b1cdb..91c5a1bd1026 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -2,15 +2,17 @@ # Makefile for USB Host Controller Drivers # -ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG +ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG -isp1760-objs := isp1760-hcd.o isp1760-if.o -fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \ - fhci-tds.o fhci-sched.o -ifeq ($(CONFIG_FHCI_DEBUG),y) -fhci-objs += fhci-dbg.o -endif -xhci-hcd-objs := xhci.o xhci-mem.o xhci-pci.o xhci-ring.o xhci-hub.o xhci-dbg.o +isp1760-y := isp1760-hcd.o isp1760-if.o + +fhci-y := fhci-hcd.o fhci-hub.o fhci-q.o +fhci-y += fhci-mem.o fhci-tds.o fhci-sched.o + +fhci-$(CONFIG_FHCI_DEBUG) += fhci-dbg.o + +xhci-hcd-y := xhci.o xhci-mem.o xhci-pci.o +xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o obj-$(CONFIG_USB_WHCI_HCD) += whci/ @@ -32,4 +34,3 @@ obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o - diff --git a/drivers/usb/host/whci/Kbuild b/drivers/usb/host/whci/Kbuild index 11e5040b8337..26df0138079e 100644 --- a/drivers/usb/host/whci/Kbuild +++ b/drivers/usb/host/whci/Kbuild @@ -3,7 +3,7 @@ obj-$(CONFIG_USB_WHCI_HCD) += whci-hcd.o whci-hcd-y := \ asl.o \ debug.o \ - hcd.o \ + hcd.o \ hw.o \ init.o \ int.o \ diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index d2633c035626..796ce7ebccc8 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -3,27 +3,27 @@ # (the ones that don't fit into any other categories) # -obj-$(CONFIG_USB_ADUTUX) += adutux.o -obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o -obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o -obj-$(CONFIG_USB_CYTHERM) += cytherm.o -obj-$(CONFIG_USB_EMI26) += emi26.o -obj-$(CONFIG_USB_EMI62) += emi62.o -obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o -obj-$(CONFIG_USB_IDMOUSE) += idmouse.o -obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o -obj-$(CONFIG_USB_ISIGHTFW) += isight_firmware.o -obj-$(CONFIG_USB_LCD) += usblcd.o -obj-$(CONFIG_USB_LD) += ldusb.o -obj-$(CONFIG_USB_LED) += usbled.o -obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o -obj-$(CONFIG_USB_RIO500) += rio500.o -obj-$(CONFIG_USB_TEST) += usbtest.o +ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG + +obj-$(CONFIG_USB_ADUTUX) += adutux.o +obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o +obj-$(CONFIG_USB_CYPRESS_CY7C63) += cypress_cy7c63.o +obj-$(CONFIG_USB_CYTHERM) += cytherm.o +obj-$(CONFIG_USB_EMI26) += emi26.o +obj-$(CONFIG_USB_EMI62) += emi62.o +obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o +obj-$(CONFIG_USB_IDMOUSE) += idmouse.o +obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o +obj-$(CONFIG_USB_ISIGHTFW) += isight_firmware.o +obj-$(CONFIG_USB_LCD) += usblcd.o +obj-$(CONFIG_USB_LD) += ldusb.o +obj-$(CONFIG_USB_LED) += usbled.o +obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o +obj-$(CONFIG_USB_RIO500) += rio500.o +obj-$(CONFIG_USB_TEST) += usbtest.o obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o -obj-$(CONFIG_USB_USS720) += uss720.o -obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o -obj-$(CONFIG_USB_YUREX) += yurex.o +obj-$(CONFIG_USB_USS720) += uss720.o +obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o +obj-$(CONFIG_USB_YUREX) += yurex.o -obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ - -ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG +obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ diff --git a/drivers/usb/misc/sisusbvga/Makefile b/drivers/usb/misc/sisusbvga/Makefile index 7f934cfc906c..3142476ccc8e 100644 --- a/drivers/usb/misc/sisusbvga/Makefile +++ b/drivers/usb/misc/sisusbvga/Makefile @@ -4,5 +4,4 @@ obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o -sisusbvga-objs := sisusb.o sisusb_init.o sisusb_con.o - +sisusbvga-y := sisusb.o sisusb_init.o sisusb_con.o diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile index 384b198faa7c..8ed24ab08698 100644 --- a/drivers/usb/mon/Makefile +++ b/drivers/usb/mon/Makefile @@ -2,6 +2,6 @@ # Makefile for USB monitor # -usbmon-objs := mon_main.o mon_stat.o mon_text.o mon_bin.o +usbmon-y := mon_main.o mon_stat.o mon_text.o mon_bin.o obj-$(CONFIG_USB_MON) += usbmon.o diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 16aaae28714d..ffc0e0525823 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -2,53 +2,23 @@ # for USB OTG silicon based on Mentor Graphics INVENTRA designs # -musb_hdrc-objs := musb_core.o +ccflags-$(CONFIG_USB_MUSB_DEBUG) := -DDEBUG -obj-$(CONFIG_USB_MUSB_HDRC) += musb_hdrc.o +obj-$(CONFIG_USB_MUSB_HDRC) += musb_hdrc.o -ifeq ($(CONFIG_ARCH_DAVINCI_DMx),y) - musb_hdrc-objs += davinci.o -endif +musb_hdrc-y := musb_core.o -ifeq ($(CONFIG_ARCH_DAVINCI_DA8XX),y) - musb_hdrc-objs += da8xx.o -endif - -ifeq ($(CONFIG_USB_TUSB6010),y) - musb_hdrc-objs += tusb6010.o -endif - -ifeq ($(CONFIG_ARCH_OMAP2430),y) - musb_hdrc-objs += omap2430.o -endif - -ifeq ($(CONFIG_ARCH_OMAP3430),y) - musb_hdrc-objs += omap2430.o -endif - -ifeq ($(CONFIG_ARCH_OMAP4),y) - musb_hdrc-objs += omap2430.o -endif - -ifeq ($(CONFIG_BF54x),y) - musb_hdrc-objs += blackfin.o -endif - -ifeq ($(CONFIG_BF52x),y) - musb_hdrc-objs += blackfin.o -endif - -ifeq ($(CONFIG_USB_GADGET_MUSB_HDRC),y) - musb_hdrc-objs += musb_gadget_ep0.o musb_gadget.o -endif - -ifeq ($(CONFIG_USB_MUSB_HDRC_HCD),y) - musb_hdrc-objs += musb_virthub.o musb_host.o -endif - -ifeq ($(CONFIG_DEBUG_FS),y) - musb_hdrc-objs += musb_debugfs.o -endif +musb_hdrc-$(CONFIG_ARCH_DAVINCI_DMx) += davinci.o +musb_hdrc-$(CONFIG_ARCH_DAVINCI_DA8XX) += da8xx.o +musb_hdrc-$(CONFIG_USB_TUSB6010) += tusb6010.o +musb_hdrc-$(CONFIG_ARCH_OMAP2430) += omap2430.o +musb_hdrc-$(CONFIG_ARCH_OMAP3430) += omap2430.o +musb_hdrc-$(CONFIG_ARCH_OMAP4) += omap2430.o +musb_hdrc-$(CONFIG_BF54x) += blackfin.o +musb_hdrc-$(CONFIG_BF52x) += blackfin.o +musb_hdrc-$(CONFIG_USB_GADGET_MUSB_HDRC) += musb_gadget_ep0.o musb_gadget.o +musb_hdrc-$(CONFIG_USB_MUSB_HDRC_HCD) += musb_virthub.o musb_host.o +musb_hdrc-$(CONFIG_DEBUG_FS) += musb_debugfs.o # the kconfig must guarantee that only one of the # possible I/O schemes will be enabled at a time ... @@ -58,24 +28,17 @@ endif ifneq ($(CONFIG_MUSB_PIO_ONLY),y) ifeq ($(CONFIG_USB_INVENTRA_DMA),y) - musb_hdrc-objs += musbhsdma.o + musb_hdrc-y += musbhsdma.o else ifeq ($(CONFIG_USB_TI_CPPI_DMA),y) - musb_hdrc-objs += cppi_dma.o + musb_hdrc-y += cppi_dma.o else ifeq ($(CONFIG_USB_TUSB_OMAP_DMA),y) - musb_hdrc-objs += tusb6010_omap.o + musb_hdrc-y += tusb6010_omap.o endif endif endif endif - - -################################################################################ - -# Debugging - -ccflags-$(CONFIG_USB_MUSB_DEBUG) := -DDEBUG diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index b6609db3a849..66f1b83e4fa7 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -2,6 +2,9 @@ # OTG infrastructure and transceiver drivers # +ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG +ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG + # infrastructure obj-$(CONFIG_USB_OTG_UTILS) += otg.o @@ -12,7 +15,3 @@ obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o obj-$(CONFIG_USB_ULPI) += ulpi.o - -ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG -ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG - diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index cf41b6209c74..9a2117f2b06e 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -6,10 +6,10 @@ obj-$(CONFIG_USB_SERIAL) += usbserial.o -usbserial-obj-$(CONFIG_USB_SERIAL_CONSOLE) += console.o -usbserial-obj-$(CONFIG_USB_EZUSB) += ezusb.o +usbserial-y := usb-serial.o generic.o bus.o -usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y) +usbserial-$(CONFIG_USB_SERIAL_CONSOLE) += console.o +usbserial-$(CONFIG_USB_EZUSB) += ezusb.o obj-$(CONFIG_USB_SERIAL_AIRCABLE) += aircable.o obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o @@ -59,6 +59,5 @@ obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o obj-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda.o -obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL) += vivopay-serial.o +obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL) += vivopay-serial.o obj-$(CONFIG_USB_SERIAL_ZIO) += zio.o - diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 65dbf652487e..fcf14cdc4a04 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -5,21 +5,21 @@ # Rewritten to use lists instead of if-statements. # -ccflags-y := -Idrivers/scsi +ccflags-y := -Idrivers/scsi obj-$(CONFIG_USB_UAS) += uas.o obj-$(CONFIG_USB_STORAGE) += usb-storage.o -usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o +usb-storage-y := scsiglue.o protocol.o transport.o usb.o +usb-storage-y += initializers.o sierra_ms.o option_ms.o -usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ - initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) +usb-storage-$(CONFIG_USB_STORAGE_DEBUG) += debug.o ifeq ($(CONFIG_USB_LIBUSUAL),) - usb-storage-objs += usual-tables.o + usb-storage-y += usual-tables.o else obj-$(CONFIG_USB) += usb-libusual.o - usb-libusual-objs := libusual.o usual-tables.o + usb-libusual-y := libusual.o usual-tables.o endif obj-$(CONFIG_USB_STORAGE_ALAUDA) += ums-alauda.o @@ -34,14 +34,14 @@ obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o -ums-alauda-objs := alauda.o -ums-cypress-objs := cypress_atacb.o -ums-datafab-objs := datafab.o -ums-freecom-objs := freecom.o -ums-isd200-objs := isd200.o -ums-jumpshot-objs := jumpshot.o -ums-karma-objs := karma.o -ums-onetouch-objs := onetouch.o -ums-sddr09-objs := sddr09.o -ums-sddr55-objs := sddr55.o -ums-usbat-objs := shuttle_usbat.o +ums-alauda-y := alauda.o +ums-cypress-y := cypress_atacb.o +ums-datafab-y := datafab.o +ums-freecom-y := freecom.o +ums-isd200-y := isd200.o +ums-jumpshot-y := jumpshot.o +ums-karma-y := karma.o +ums-onetouch-y := onetouch.o +ums-sddr09-y := sddr09.o +ums-sddr55-y := sddr55.o +ums-usbat-y := shuttle_usbat.o diff --git a/drivers/usb/wusbcore/Makefile b/drivers/usb/wusbcore/Makefile index f0d8045c802e..b3bd313032b1 100644 --- a/drivers/usb/wusbcore/Makefile +++ b/drivers/usb/wusbcore/Makefile @@ -1,9 +1,11 @@ +ccflags-$(CONFIG_USB_WUSB_CBAF_DEBUG) := -DDEBUG + obj-$(CONFIG_USB_WUSB) += wusbcore.o obj-$(CONFIG_USB_HWA_HCD) += wusb-wa.o obj-$(CONFIG_USB_WUSB_CBAF) += wusb-cbaf.o -wusbcore-objs := \ +wusbcore-y := \ crypto.o \ devconnect.o \ dev-sysfs.o \ @@ -14,11 +16,10 @@ wusbcore-objs := \ security.o \ wusbhc.o -wusb-cbaf-objs := cbaf.o +wusb-cbaf-y := cbaf.o -wusb-wa-objs := wa-hc.o \ - wa-nep.o \ - wa-rpipe.o \ - wa-xfer.o - -ccflags-$(CONFIG_USB_WUSB_CBAF_DEBUG) := -DDEBUG +wusb-wa-y := \ + wa-hc.o \ + wa-nep.o \ + wa-rpipe.o \ + wa-xfer.o From 0a6a717ceff67f887b16783ce891f5dcf846f1fc Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 7 Oct 2010 14:46:15 +0200 Subject: [PATCH 106/141] USB: gadget: storage: reuse definitions from scsi.h header file This commit changes storage_common.h, file_storage.c and f_mass_storage.c to use definitions of SCSI commands from scsi/scsi.h file instead of redefining the commands in storage_common.c. scsi/scsi.h header file was missing READ_FORMAT_CAPACITIES and READ_HEADER so this commit also add those to the header. Signed-off-by: Michal Nazarewicz Cc: Alan Stern Cc: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_mass_storage.c | 72 ++++++++++++++-------------- drivers/usb/gadget/file_storage.c | 74 ++++++++++++++--------------- drivers/usb/gadget/storage_common.c | 34 +------------ include/scsi/scsi.h | 2 + 4 files changed, 77 insertions(+), 105 deletions(-) diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 44e5ffed5c08..838286b1cd14 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -741,7 +741,7 @@ static int do_read(struct fsg_common *common) /* Get the starting Logical Block Address and check that it's * not too big */ - if (common->cmnd[0] == SC_READ_6) + if (common->cmnd[0] == READ_6) lba = get_unaligned_be24(&common->cmnd[1]); else { lba = get_unaligned_be32(&common->cmnd[2]); @@ -879,7 +879,7 @@ static int do_write(struct fsg_common *common) /* Get the starting Logical Block Address and check that it's * not too big */ - if (common->cmnd[0] == SC_WRITE_6) + if (common->cmnd[0] == WRITE_6) lba = get_unaligned_be24(&common->cmnd[1]); else { lba = get_unaligned_be32(&common->cmnd[2]); @@ -1186,7 +1186,7 @@ static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh) return 36; } - buf[0] = curlun->cdrom ? TYPE_CDROM : TYPE_DISK; + buf[0] = curlun->cdrom ? TYPE_ROM : TYPE_DISK; buf[1] = curlun->removable ? 0x80 : 0; buf[2] = 2; /* ANSI SCSI level 2 */ buf[3] = 2; /* SCSI-2 INQUIRY data format */ @@ -1353,11 +1353,11 @@ static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh) * The only variable value is the WriteProtect bit. We will fill in * the mode data length later. */ memset(buf, 0, 8); - if (mscmnd == SC_MODE_SENSE_6) { + if (mscmnd == MODE_SENSE) { buf[2] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ buf += 4; limit = 255; - } else { /* SC_MODE_SENSE_10 */ + } else { /* MODE_SENSE_10 */ buf[3] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ buf += 8; limit = 65535; /* Should really be FSG_BUFLEN */ @@ -1397,7 +1397,7 @@ static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh) } /* Store the mode data length */ - if (mscmnd == SC_MODE_SENSE_6) + if (mscmnd == MODE_SENSE) buf0[0] = len - 1; else put_unaligned_be16(len - 2, buf0); @@ -1886,7 +1886,7 @@ static int check_command(struct fsg_common *common, int cmnd_size, if (common->lun >= 0 && common->lun < common->nluns) { curlun = &common->luns[common->lun]; common->curlun = curlun; - if (common->cmnd[0] != SC_REQUEST_SENSE) { + if (common->cmnd[0] != REQUEST_SENSE) { curlun->sense_data = SS_NO_SENSE; curlun->sense_data_info = 0; curlun->info_valid = 0; @@ -1898,8 +1898,8 @@ static int check_command(struct fsg_common *common, int cmnd_size, /* INQUIRY and REQUEST SENSE commands are explicitly allowed * to use unsupported LUNs; all others may not. */ - if (common->cmnd[0] != SC_INQUIRY && - common->cmnd[0] != SC_REQUEST_SENSE) { + if (common->cmnd[0] != INQUIRY && + common->cmnd[0] != REQUEST_SENSE) { DBG(common, "unsupported LUN %d\n", common->lun); return -EINVAL; } @@ -1908,8 +1908,8 @@ static int check_command(struct fsg_common *common, int cmnd_size, /* If a unit attention condition exists, only INQUIRY and * REQUEST SENSE commands are allowed; anything else must fail. */ if (curlun && curlun->unit_attention_data != SS_NO_SENSE && - common->cmnd[0] != SC_INQUIRY && - common->cmnd[0] != SC_REQUEST_SENSE) { + common->cmnd[0] != INQUIRY && + common->cmnd[0] != REQUEST_SENSE) { curlun->sense_data = curlun->unit_attention_data; curlun->unit_attention_data = SS_NO_SENSE; return -EINVAL; @@ -1960,7 +1960,7 @@ static int do_scsi_command(struct fsg_common *common) down_read(&common->filesem); /* We're using the backing file */ switch (common->cmnd[0]) { - case SC_INQUIRY: + case INQUIRY: common->data_size_from_cmnd = common->cmnd[4]; reply = check_command(common, 6, DATA_DIR_TO_HOST, (1<<4), 0, @@ -1969,7 +1969,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_inquiry(common, bh); break; - case SC_MODE_SELECT_6: + case MODE_SELECT: common->data_size_from_cmnd = common->cmnd[4]; reply = check_command(common, 6, DATA_DIR_FROM_HOST, (1<<1) | (1<<4), 0, @@ -1978,7 +1978,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_mode_select(common, bh); break; - case SC_MODE_SELECT_10: + case MODE_SELECT_10: common->data_size_from_cmnd = get_unaligned_be16(&common->cmnd[7]); reply = check_command(common, 10, DATA_DIR_FROM_HOST, @@ -1988,7 +1988,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_mode_select(common, bh); break; - case SC_MODE_SENSE_6: + case MODE_SENSE: common->data_size_from_cmnd = common->cmnd[4]; reply = check_command(common, 6, DATA_DIR_TO_HOST, (1<<1) | (1<<2) | (1<<4), 0, @@ -1997,7 +1997,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_mode_sense(common, bh); break; - case SC_MODE_SENSE_10: + case MODE_SENSE_10: common->data_size_from_cmnd = get_unaligned_be16(&common->cmnd[7]); reply = check_command(common, 10, DATA_DIR_TO_HOST, @@ -2007,7 +2007,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_mode_sense(common, bh); break; - case SC_PREVENT_ALLOW_MEDIUM_REMOVAL: + case ALLOW_MEDIUM_REMOVAL: common->data_size_from_cmnd = 0; reply = check_command(common, 6, DATA_DIR_NONE, (1<<4), 0, @@ -2016,7 +2016,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_prevent_allow(common); break; - case SC_READ_6: + case READ_6: i = common->cmnd[4]; common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; reply = check_command(common, 6, DATA_DIR_TO_HOST, @@ -2026,7 +2026,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_read(common); break; - case SC_READ_10: + case READ_10: common->data_size_from_cmnd = get_unaligned_be16(&common->cmnd[7]) << 9; reply = check_command(common, 10, DATA_DIR_TO_HOST, @@ -2036,7 +2036,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_read(common); break; - case SC_READ_12: + case READ_12: common->data_size_from_cmnd = get_unaligned_be32(&common->cmnd[6]) << 9; reply = check_command(common, 12, DATA_DIR_TO_HOST, @@ -2046,7 +2046,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_read(common); break; - case SC_READ_CAPACITY: + case READ_CAPACITY: common->data_size_from_cmnd = 8; reply = check_command(common, 10, DATA_DIR_TO_HOST, (0xf<<2) | (1<<8), 1, @@ -2055,7 +2055,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_read_capacity(common, bh); break; - case SC_READ_HEADER: + case READ_HEADER: if (!common->curlun || !common->curlun->cdrom) goto unknown_cmnd; common->data_size_from_cmnd = @@ -2067,7 +2067,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_read_header(common, bh); break; - case SC_READ_TOC: + case READ_TOC: if (!common->curlun || !common->curlun->cdrom) goto unknown_cmnd; common->data_size_from_cmnd = @@ -2079,7 +2079,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_read_toc(common, bh); break; - case SC_READ_FORMAT_CAPACITIES: + case READ_FORMAT_CAPACITIES: common->data_size_from_cmnd = get_unaligned_be16(&common->cmnd[7]); reply = check_command(common, 10, DATA_DIR_TO_HOST, @@ -2089,7 +2089,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_read_format_capacities(common, bh); break; - case SC_REQUEST_SENSE: + case REQUEST_SENSE: common->data_size_from_cmnd = common->cmnd[4]; reply = check_command(common, 6, DATA_DIR_TO_HOST, (1<<4), 0, @@ -2098,7 +2098,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_request_sense(common, bh); break; - case SC_START_STOP_UNIT: + case START_STOP: common->data_size_from_cmnd = 0; reply = check_command(common, 6, DATA_DIR_NONE, (1<<1) | (1<<4), 0, @@ -2107,7 +2107,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_start_stop(common); break; - case SC_SYNCHRONIZE_CACHE: + case SYNCHRONIZE_CACHE: common->data_size_from_cmnd = 0; reply = check_command(common, 10, DATA_DIR_NONE, (0xf<<2) | (3<<7), 1, @@ -2116,7 +2116,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_synchronize_cache(common); break; - case SC_TEST_UNIT_READY: + case TEST_UNIT_READY: common->data_size_from_cmnd = 0; reply = check_command(common, 6, DATA_DIR_NONE, 0, 1, @@ -2125,7 +2125,7 @@ static int do_scsi_command(struct fsg_common *common) /* Although optional, this command is used by MS-Windows. We * support a minimal version: BytChk must be 0. */ - case SC_VERIFY: + case VERIFY: common->data_size_from_cmnd = 0; reply = check_command(common, 10, DATA_DIR_NONE, (1<<1) | (0xf<<2) | (3<<7), 1, @@ -2134,7 +2134,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_verify(common); break; - case SC_WRITE_6: + case WRITE_6: i = common->cmnd[4]; common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; reply = check_command(common, 6, DATA_DIR_FROM_HOST, @@ -2144,7 +2144,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_write(common); break; - case SC_WRITE_10: + case WRITE_10: common->data_size_from_cmnd = get_unaligned_be16(&common->cmnd[7]) << 9; reply = check_command(common, 10, DATA_DIR_FROM_HOST, @@ -2154,7 +2154,7 @@ static int do_scsi_command(struct fsg_common *common) reply = do_write(common); break; - case SC_WRITE_12: + case WRITE_12: common->data_size_from_cmnd = get_unaligned_be32(&common->cmnd[6]) << 9; reply = check_command(common, 12, DATA_DIR_FROM_HOST, @@ -2168,10 +2168,10 @@ static int do_scsi_command(struct fsg_common *common) * They don't mean much in this setting. It's left as an exercise * for anyone interested to implement RESERVE and RELEASE in terms * of Posix locks. */ - case SC_FORMAT_UNIT: - case SC_RELEASE: - case SC_RESERVE: - case SC_SEND_DIAGNOSTIC: + case FORMAT_UNIT: + case RELEASE: + case RESERVE: + case SEND_DIAGNOSTIC: /* Fall through */ default: diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index ce437f5dd674..d4fdf65fb925 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -783,7 +783,7 @@ static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) { struct usb_request *req = fsg->ep0req; static u8 cbi_reset_cmnd[6] = { - SC_SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff}; + SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff}; /* Error in command transfer? */ if (req->status || req->length != req->actual || @@ -1135,7 +1135,7 @@ static int do_read(struct fsg_dev *fsg) /* Get the starting Logical Block Address and check that it's * not too big */ - if (fsg->cmnd[0] == SC_READ_6) + if (fsg->cmnd[0] == READ_6) lba = get_unaligned_be24(&fsg->cmnd[1]); else { lba = get_unaligned_be32(&fsg->cmnd[2]); @@ -1270,7 +1270,7 @@ static int do_write(struct fsg_dev *fsg) /* Get the starting Logical Block Address and check that it's * not too big */ - if (fsg->cmnd[0] == SC_WRITE_6) + if (fsg->cmnd[0] == WRITE_6) lba = get_unaligned_be24(&fsg->cmnd[1]); else { lba = get_unaligned_be32(&fsg->cmnd[2]); @@ -1578,7 +1578,7 @@ static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) } memset(buf, 0, 8); - buf[0] = (mod_data.cdrom ? TYPE_CDROM : TYPE_DISK); + buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK); if (mod_data.removable) buf[1] = 0x80; buf[2] = 2; // ANSI SCSI level 2 @@ -1747,11 +1747,11 @@ static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) * The only variable value is the WriteProtect bit. We will fill in * the mode data length later. */ memset(buf, 0, 8); - if (mscmnd == SC_MODE_SENSE_6) { + if (mscmnd == MODE_SENSE) { buf[2] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA buf += 4; limit = 255; - } else { // SC_MODE_SENSE_10 + } else { // MODE_SENSE_10 buf[3] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA buf += 8; limit = 65535; // Should really be mod_data.buflen @@ -1791,7 +1791,7 @@ static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) } /* Store the mode data length */ - if (mscmnd == SC_MODE_SENSE_6) + if (mscmnd == MODE_SENSE) buf0[0] = len - 1; else put_unaligned_be16(len - 2, buf0); @@ -2316,7 +2316,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, /* Check the LUN */ if (fsg->lun >= 0 && fsg->lun < fsg->nluns) { fsg->curlun = curlun = &fsg->luns[fsg->lun]; - if (fsg->cmnd[0] != SC_REQUEST_SENSE) { + if (fsg->cmnd[0] != REQUEST_SENSE) { curlun->sense_data = SS_NO_SENSE; curlun->sense_data_info = 0; curlun->info_valid = 0; @@ -2327,8 +2327,8 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, /* INQUIRY and REQUEST SENSE commands are explicitly allowed * to use unsupported LUNs; all others may not. */ - if (fsg->cmnd[0] != SC_INQUIRY && - fsg->cmnd[0] != SC_REQUEST_SENSE) { + if (fsg->cmnd[0] != INQUIRY && + fsg->cmnd[0] != REQUEST_SENSE) { DBG(fsg, "unsupported LUN %d\n", fsg->lun); return -EINVAL; } @@ -2337,8 +2337,8 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, /* If a unit attention condition exists, only INQUIRY and * REQUEST SENSE commands are allowed; anything else must fail. */ if (curlun && curlun->unit_attention_data != SS_NO_SENSE && - fsg->cmnd[0] != SC_INQUIRY && - fsg->cmnd[0] != SC_REQUEST_SENSE) { + fsg->cmnd[0] != INQUIRY && + fsg->cmnd[0] != REQUEST_SENSE) { curlun->sense_data = curlun->unit_attention_data; curlun->unit_attention_data = SS_NO_SENSE; return -EINVAL; @@ -2388,7 +2388,7 @@ static int do_scsi_command(struct fsg_dev *fsg) down_read(&fsg->filesem); // We're using the backing file switch (fsg->cmnd[0]) { - case SC_INQUIRY: + case INQUIRY: fsg->data_size_from_cmnd = fsg->cmnd[4]; if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, (1<<4), 0, @@ -2396,7 +2396,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_inquiry(fsg, bh); break; - case SC_MODE_SELECT_6: + case MODE_SELECT: fsg->data_size_from_cmnd = fsg->cmnd[4]; if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST, (1<<1) | (1<<4), 0, @@ -2404,7 +2404,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_mode_select(fsg, bh); break; - case SC_MODE_SELECT_10: + case MODE_SELECT_10: fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST, (1<<1) | (3<<7), 0, @@ -2412,7 +2412,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_mode_select(fsg, bh); break; - case SC_MODE_SENSE_6: + case MODE_SENSE: fsg->data_size_from_cmnd = fsg->cmnd[4]; if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, (1<<1) | (1<<2) | (1<<4), 0, @@ -2420,7 +2420,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_mode_sense(fsg, bh); break; - case SC_MODE_SENSE_10: + case MODE_SENSE_10: fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, (1<<1) | (1<<2) | (3<<7), 0, @@ -2428,7 +2428,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_mode_sense(fsg, bh); break; - case SC_PREVENT_ALLOW_MEDIUM_REMOVAL: + case ALLOW_MEDIUM_REMOVAL: fsg->data_size_from_cmnd = 0; if ((reply = check_command(fsg, 6, DATA_DIR_NONE, (1<<4), 0, @@ -2436,7 +2436,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_prevent_allow(fsg); break; - case SC_READ_6: + case READ_6: i = fsg->cmnd[4]; fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, @@ -2445,7 +2445,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_read(fsg); break; - case SC_READ_10: + case READ_10: fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]) << 9; if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, @@ -2454,7 +2454,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_read(fsg); break; - case SC_READ_12: + case READ_12: fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]) << 9; if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST, @@ -2463,7 +2463,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_read(fsg); break; - case SC_READ_CAPACITY: + case READ_CAPACITY: fsg->data_size_from_cmnd = 8; if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, (0xf<<2) | (1<<8), 1, @@ -2471,7 +2471,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_read_capacity(fsg, bh); break; - case SC_READ_HEADER: + case READ_HEADER: if (!mod_data.cdrom) goto unknown_cmnd; fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); @@ -2481,7 +2481,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_read_header(fsg, bh); break; - case SC_READ_TOC: + case READ_TOC: if (!mod_data.cdrom) goto unknown_cmnd; fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); @@ -2491,7 +2491,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_read_toc(fsg, bh); break; - case SC_READ_FORMAT_CAPACITIES: + case READ_FORMAT_CAPACITIES: fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, (3<<7), 1, @@ -2499,7 +2499,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_read_format_capacities(fsg, bh); break; - case SC_REQUEST_SENSE: + case REQUEST_SENSE: fsg->data_size_from_cmnd = fsg->cmnd[4]; if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, (1<<4), 0, @@ -2507,7 +2507,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_request_sense(fsg, bh); break; - case SC_START_STOP_UNIT: + case START_STOP: fsg->data_size_from_cmnd = 0; if ((reply = check_command(fsg, 6, DATA_DIR_NONE, (1<<1) | (1<<4), 0, @@ -2515,7 +2515,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_start_stop(fsg); break; - case SC_SYNCHRONIZE_CACHE: + case SYNCHRONIZE_CACHE: fsg->data_size_from_cmnd = 0; if ((reply = check_command(fsg, 10, DATA_DIR_NONE, (0xf<<2) | (3<<7), 1, @@ -2523,7 +2523,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_synchronize_cache(fsg); break; - case SC_TEST_UNIT_READY: + case TEST_UNIT_READY: fsg->data_size_from_cmnd = 0; reply = check_command(fsg, 6, DATA_DIR_NONE, 0, 1, @@ -2532,7 +2532,7 @@ static int do_scsi_command(struct fsg_dev *fsg) /* Although optional, this command is used by MS-Windows. We * support a minimal version: BytChk must be 0. */ - case SC_VERIFY: + case VERIFY: fsg->data_size_from_cmnd = 0; if ((reply = check_command(fsg, 10, DATA_DIR_NONE, (1<<1) | (0xf<<2) | (3<<7), 1, @@ -2540,7 +2540,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_verify(fsg); break; - case SC_WRITE_6: + case WRITE_6: i = fsg->cmnd[4]; fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST, @@ -2549,7 +2549,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_write(fsg); break; - case SC_WRITE_10: + case WRITE_10: fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]) << 9; if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST, @@ -2558,7 +2558,7 @@ static int do_scsi_command(struct fsg_dev *fsg) reply = do_write(fsg); break; - case SC_WRITE_12: + case WRITE_12: fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]) << 9; if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST, @@ -2571,10 +2571,10 @@ static int do_scsi_command(struct fsg_dev *fsg) * They don't mean much in this setting. It's left as an exercise * for anyone interested to implement RESERVE and RELEASE in terms * of Posix locks. */ - case SC_FORMAT_UNIT: - case SC_RELEASE: - case SC_RESERVE: - case SC_SEND_DIAGNOSTIC: + case FORMAT_UNIT: + case RELEASE: + case RESERVE: + case SEND_DIAGNOSTIC: // Fall through default: diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index 0a7df3db71f1..3b513bafaf2a 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -53,8 +53,9 @@ */ -#include #include +#include +#include /* @@ -153,10 +154,6 @@ /*-------------------------------------------------------------------------*/ -/* SCSI device types */ -#define TYPE_DISK 0x00 -#define TYPE_CDROM 0x05 - /* Bulk-only data structures */ /* Command Block Wrapper */ @@ -208,33 +205,6 @@ struct interrupt_data { /* Length of a SCSI Command Data Block */ #define MAX_COMMAND_SIZE 16 -/* SCSI commands that we recognize */ -#define SC_FORMAT_UNIT 0x04 -#define SC_INQUIRY 0x12 -#define SC_MODE_SELECT_6 0x15 -#define SC_MODE_SELECT_10 0x55 -#define SC_MODE_SENSE_6 0x1a -#define SC_MODE_SENSE_10 0x5a -#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e -#define SC_READ_6 0x08 -#define SC_READ_10 0x28 -#define SC_READ_12 0xa8 -#define SC_READ_CAPACITY 0x25 -#define SC_READ_FORMAT_CAPACITIES 0x23 -#define SC_READ_HEADER 0x44 -#define SC_READ_TOC 0x43 -#define SC_RELEASE 0x17 -#define SC_REQUEST_SENSE 0x03 -#define SC_RESERVE 0x16 -#define SC_SEND_DIAGNOSTIC 0x1d -#define SC_START_STOP_UNIT 0x1b -#define SC_SYNCHRONIZE_CACHE 0x35 -#define SC_TEST_UNIT_READY 0x00 -#define SC_VERIFY 0x2f -#define SC_WRITE_6 0x0a -#define SC_WRITE_10 0x2a -#define SC_WRITE_12 0xaa - /* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */ #define SS_NO_SENSE 0 #define SS_COMMUNICATION_FAILURE 0x040800 diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 8fcb6e0e9e72..1418e9010f3e 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -67,6 +67,7 @@ struct scsi_cmnd; #define SEND_DIAGNOSTIC 0x1d #define ALLOW_MEDIUM_REMOVAL 0x1e +#define READ_FORMAT_CAPACITIES 0x23 #define SET_WINDOW 0x24 #define READ_CAPACITY 0x25 #define READ_10 0x28 @@ -96,6 +97,7 @@ struct scsi_cmnd; #define WRITE_SAME 0x41 #define UNMAP 0x42 #define READ_TOC 0x43 +#define READ_HEADER 0x44 #define LOG_SELECT 0x4c #define LOG_SENSE 0x4d #define XDWRITEREAD_10 0x53 From 562e7c71c6708353bfe7b615576bcbcf7afd522e Mon Sep 17 00:00:00 2001 From: Tatyana Brokhman Date: Sat, 9 Oct 2010 16:46:12 +0200 Subject: [PATCH 107/141] usb: usb3.0 ch9 definitions Adding SuperSpeed usb definitions as defined by ch9 of the USB3.0 spec. This patch is a preparation for adding SuperSpeed support to the gadget framework. Signed-off-by: Tatyana Brokhman Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/ch9.h | 58 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index b0f7e9f57176..f917bbbc8901 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -123,8 +123,23 @@ #define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */ #define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ +/* + * New Feature Selectors as added by USB 3.0 + * See USB 3.0 spec Table 9-6 + */ +#define USB_DEVICE_U1_ENABLE 48 /* dev may initiate U1 transition */ +#define USB_DEVICE_U2_ENABLE 49 /* dev may initiate U2 transition */ +#define USB_DEVICE_LTM_ENABLE 50 /* dev may send LTM */ +#define USB_INTRF_FUNC_SUSPEND 0 /* function suspend */ + +#define USB_INTR_FUNC_SUSPEND_OPT_MASK 0xFF00 + #define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ +/* Bit array elements as returned by the USB_REQ_GET_STATUS request. */ +#define USB_DEV_STAT_U1_ENABLED 2 /* transition into U1 state */ +#define USB_DEV_STAT_U2_ENABLED 3 /* transition into U2 state */ +#define USB_DEV_STAT_LTM_ENABLED 4 /* Latency tolerance messages */ /** * struct usb_ctrlrequest - SETUP data for a USB device control request @@ -675,6 +690,7 @@ struct usb_bos_descriptor { __u8 bNumDeviceCaps; } __attribute__((packed)); +#define USB_DT_BOS_SIZE 5 /*-------------------------------------------------------------------------*/ /* USB_DT_DEVICE_CAPABILITY: grouped with BOS */ @@ -712,16 +728,56 @@ struct usb_wireless_cap_descriptor { /* Ultra Wide Band */ __u8 bReserved; } __attribute__((packed)); +/* USB 2.0 Extension descriptor */ #define USB_CAP_TYPE_EXT 2 struct usb_ext_cap_descriptor { /* Link Power Management */ __u8 bLength; __u8 bDescriptorType; __u8 bDevCapabilityType; - __u8 bmAttributes; + __le32 bmAttributes; #define USB_LPM_SUPPORT (1 << 1) /* supports LPM */ } __attribute__((packed)); +#define USB_DT_USB_EXT_CAP_SIZE 7 + +/* + * SuperSpeed USB Capability descriptor: Defines the set of SuperSpeed USB + * specific device level capabilities + */ +#define USB_SS_CAP_TYPE 3 +struct usb_ss_cap_descriptor { /* Link Power Management */ + __u8 bLength; + __u8 bDescriptorType; + __u8 bDevCapabilityType; + __u8 bmAttributes; +#define USB_LTM_SUPPORT (1 << 1) /* supports LTM */ + __le16 wSpeedSupported; +#define USB_LOW_SPEED_OPERATION (1) /* Low speed operation */ +#define USB_FULL_SPEED_OPERATION (1 << 1) /* Full speed operation */ +#define USB_HIGH_SPEED_OPERATION (1 << 2) /* High speed operation */ +#define USB_5GBPS_OPERATION (1 << 3) /* Operation at 5Gbps */ + __u8 bFunctionalitySupport; + __u8 bU1devExitLat; + __le16 bU2DevExitLat; +} __attribute__((packed)); + +#define USB_DT_USB_SS_CAP_SIZE 10 + +/* + * Container ID Capability descriptor: Defines the instance unique ID used to + * identify the instance across all operating modes + */ +#define CONTAINER_ID_TYPE 4 +struct usb_ss_container_id_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDevCapabilityType; + __u8 bReserved; + __u8 ContainerID[16]; /* 128-bit number */ +} __attribute__((packed)); + +#define USB_DT_USB_SS_CONTN_ID_SIZE 20 /*-------------------------------------------------------------------------*/ /* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with From 59c6ccd9f9aecfa59c99ceba6d4d34b180547a05 Mon Sep 17 00:00:00 2001 From: Daniel Suchy Date: Tue, 12 Oct 2010 15:44:24 +0200 Subject: [PATCH 108/141] USB: ftdi_sio: new VID/PIDs for various Papouch devices This patch for FTDI USB serial driver ads new VID/PIDs used on various devices manufactured by Papouch (http://www.papouch.com). These devices have their own VID/PID, although they're using standard FTDI chip. In ftdi_sio.c, I also made small cleanup to have declarations for all Papouch devices together. Signed-off-by: Daniel Suchy Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 30 +++++++++++++++++++++++++++++- drivers/usb/serial/ftdi_sio_ids.h | 27 ++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index e128f9125f71..89284df2f8d9 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -675,7 +675,6 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, - { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, @@ -716,8 +715,37 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, + + /* Papouch devices based on FTDI chip */ + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_2_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_2_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_2_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485S_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485C_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_LEC_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB232_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_IRAMP_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK5_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO8x8_PID) }, { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x2_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO10x1_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO30x3_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO60x3_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x16_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO3x32_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK6_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_UPSUSB_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_MU_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_SIMUKEY_PID) }, { USB_DEVICE(PAPOUCH_VID, PAPOUCH_AD4USB_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMUX_PID) }, + { USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMSR_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DGQG_PID) }, { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) }, { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 517d01435abb..fc44369ec1a6 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1023,9 +1023,34 @@ */ #define PAPOUCH_VID 0x5050 /* Vendor ID */ +#define PAPOUCH_SB485_PID 0x0100 /* Papouch SB485 USB-485/422 Converter */ +#define PAPOUCH_AP485_PID 0x0101 /* AP485 USB-RS485 Converter */ +#define PAPOUCH_SB422_PID 0x0102 /* Papouch SB422 USB-RS422 Converter */ +#define PAPOUCH_SB485_2_PID 0x0103 /* Papouch SB485 USB-485/422 Converter */ +#define PAPOUCH_AP485_2_PID 0x0104 /* AP485 USB-RS485 Converter */ +#define PAPOUCH_SB422_2_PID 0x0105 /* Papouch SB422 USB-RS422 Converter */ +#define PAPOUCH_SB485S_PID 0x0106 /* Papouch SB485S USB-485/422 Converter */ +#define PAPOUCH_SB485C_PID 0x0107 /* Papouch SB485C USB-485/422 Converter */ +#define PAPOUCH_LEC_PID 0x0300 /* LEC USB Converter */ +#define PAPOUCH_SB232_PID 0x0301 /* Papouch SB232 USB-RS232 Converter */ #define PAPOUCH_TMU_PID 0x0400 /* TMU USB Thermometer */ -#define PAPOUCH_QUIDO4x4_PID 0x0900 /* Quido 4/4 Module */ +#define PAPOUCH_IRAMP_PID 0x0500 /* Papouch IRAmp Duplex */ +#define PAPOUCH_DRAK5_PID 0x0700 /* Papouch DRAK5 */ +#define PAPOUCH_QUIDO8x8_PID 0x0800 /* Papouch Quido 8/8 Module */ +#define PAPOUCH_QUIDO4x4_PID 0x0900 /* Papouch Quido 4/4 Module */ +#define PAPOUCH_QUIDO2x2_PID 0x0a00 /* Papouch Quido 2/2 Module */ +#define PAPOUCH_QUIDO10x1_PID 0x0b00 /* Papouch Quido 10/1 Module */ +#define PAPOUCH_QUIDO30x3_PID 0x0c00 /* Papouch Quido 30/3 Module */ +#define PAPOUCH_QUIDO60x3_PID 0x0d00 /* Papouch Quido 60(100)/3 Module */ +#define PAPOUCH_QUIDO2x16_PID 0x0e00 /* Papouch Quido 2/16 Module */ +#define PAPOUCH_QUIDO3x32_PID 0x0f00 /* Papouch Quido 3/32 Module */ +#define PAPOUCH_DRAK6_PID 0x1000 /* Papouch DRAK6 */ +#define PAPOUCH_UPSUSB_PID 0x8000 /* Papouch UPS-USB adapter */ +#define PAPOUCH_MU_PID 0x8001 /* MU controller */ +#define PAPOUCH_SIMUKEY_PID 0x8002 /* Papouch SimuKey */ #define PAPOUCH_AD4USB_PID 0x8003 /* AD4USB Measurement Module */ +#define PAPOUCH_GMUX_PID 0x8004 /* Papouch GOLIATH MUX */ +#define PAPOUCH_GMSR_PID 0x8005 /* Papouch GOLIATH MSR */ /* * Marvell SheevaPlug From cfb8da8f69b81d367b766888e83ec0483a31bf01 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 12 Oct 2010 01:07:05 +0200 Subject: [PATCH 109/141] USB: visor: fix initialisation of UX50/TH55 devices Fix regression introduced by commit 214916f2ec6701e1c9972f26c60b3dc37d3153c6 (USB: visor: reimplement using generic framework) which broke initialisation of UX50/TH55 devices that used re-mapped bulk-out endpoint addresses. Reported-by: Robert Gadsdon Tested-by: Robert Gadsdon Cc: stable Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/visor.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index eb76aaef4268..15a5d89b7f39 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -606,6 +606,10 @@ static int treo_attach(struct usb_serial *serial) static int clie_5_attach(struct usb_serial *serial) { + struct usb_serial_port *port; + unsigned int pipe; + int j; + dbg("%s", __func__); /* TH55 registers 2 ports. @@ -621,9 +625,14 @@ static int clie_5_attach(struct usb_serial *serial) return -1; /* port 0 now uses the modified endpoint Address */ - serial->port[0]->bulk_out_endpointAddress = + port = serial->port[0]; + port->bulk_out_endpointAddress = serial->port[1]->bulk_out_endpointAddress; + pipe = usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress); + for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) + port->write_urbs[j]->pipe = pipe; + return 0; } From 3ed780117dbe5acb64280d218f0347f238dafed0 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 11 Oct 2010 11:28:16 -0700 Subject: [PATCH 110/141] usb: iowarrior: don't trust report_size for buffer size If the iowarrior devices in this case statement support more than 8 bytes per report, it is possible to write past the end of a kernel heap allocation. This will probably never be possible, but change the allocation to be more defensive anyway. Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/iowarrior.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index bc88c79875a1..8ed8d05750d4 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -374,7 +374,7 @@ static ssize_t iowarrior_write(struct file *file, case USB_DEVICE_ID_CODEMERCS_IOWPV2: case USB_DEVICE_ID_CODEMERCS_IOW40: /* IOW24 and IOW40 use a synchronous call */ - buf = kmalloc(8, GFP_KERNEL); /* 8 bytes are enough for both products */ + buf = kmalloc(count, GFP_KERNEL); if (!buf) { retval = -ENOMEM; goto exit; From c19db4c9e49a049054594272d408e101aaf41b27 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 11 Oct 2010 20:23:36 +0200 Subject: [PATCH 111/141] USB: ftdi_sio: set device latency timeout at port probe No need to set latency timeout at every open. This also fixes an issue with the read latency being as high as 250ms (instead of 1ms) for the first read after port probe. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 89284df2f8d9..d3e58b56f56d 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1589,6 +1589,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) ftdi_set_max_packet_size(port); if (read_latency_timer(port) < 0) priv->latency = 16; + write_latency_timer(port); create_sysfs_attrs(port); return 0; } @@ -1717,8 +1718,6 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) dbg("%s", __func__); - write_latency_timer(port); - /* No error checking for this (will get errors later anyway) */ /* See ftdi_sio.h for description of what is reset */ usb_control_msg(dev, usb_sndctrlpipe(dev, 0), From 97cd8dc4ca9a1a5efb2cc38758e01492e3b013e2 Mon Sep 17 00:00:00 2001 From: Alon Ziv Date: Sun, 10 Oct 2010 08:32:18 +0200 Subject: [PATCH 112/141] USB: opticon: Fix long-standing bugs in opticon driver The bulk-read callback had two bugs: a) The bulk-in packet's leading two zeros were returned (and the two last bytes truncated) b) The wrong URB was transmitted for the second (and later) read requests, causing further reads to return the entire packet (including leading zeros) Signed-off-by: Alon Ziv Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index ed01f3b2de8c..9ff19c8a122e 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -96,8 +96,8 @@ static void opticon_bulk_callback(struct urb *urb) /* real data, send it to the tty layer */ tty = tty_port_tty_get(&port->port); if (tty) { - tty_insert_flip_string(tty, data, - data_length); + tty_insert_flip_string(tty, data + 2, + data_length); tty_flip_buffer_push(tty); tty_kref_put(tty); } @@ -130,7 +130,7 @@ exit: priv->bulk_address), priv->bulk_in_buffer, priv->buffer_size, opticon_bulk_callback, priv); - result = usb_submit_urb(port->read_urb, GFP_ATOMIC); + result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC); if (result) dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", From 0d930e51cfe6f748339d7d13b3fad2b91a1d92c2 Mon Sep 17 00:00:00 2001 From: Alon Ziv Date: Sun, 10 Oct 2010 08:32:19 +0200 Subject: [PATCH 113/141] USB: opticon: Add Opticon OPN2001 write support OPN2001 expects write operations to arrive as a vendor-specific command through the control pipe (instead of using a separate bulk-out pipe). Signed-off-by: Alon Ziv Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 9ff19c8a122e..4fe7c3d9ef98 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -187,6 +187,9 @@ static void opticon_write_bulk_callback(struct urb *urb) /* free up the transfer buffer, as usb_free_urb() does not do this */ kfree(urb->transfer_buffer); + /* setup packet may be set if we're using it for writing */ + kfree(urb->setup_packet); + if (status) dbg("%s - nonzero write bulk status received: %d", __func__, status); @@ -237,10 +240,29 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); - usb_fill_bulk_urb(urb, serial->dev, - usb_sndbulkpipe(serial->dev, - port->bulk_out_endpointAddress), - buffer, count, opticon_write_bulk_callback, priv); + if (port->bulk_out_endpointAddress) { + usb_fill_bulk_urb(urb, serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), + buffer, count, opticon_write_bulk_callback, priv); + } else { + struct usb_ctrlrequest *dr; + + dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO); + if (!dr) + return -ENOMEM; + + dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT; + dr->bRequest = 0x01; + dr->wValue = 0; + dr->wIndex = 0; + dr->wLength = cpu_to_le16(count); + + usb_fill_control_urb(urb, serial->dev, + usb_sndctrlpipe(serial->dev, 0), + (unsigned char *)dr, buffer, count, + opticon_write_bulk_callback, priv); + } /* send it down the pipe */ status = usb_submit_urb(urb, GFP_ATOMIC); From c6f694af8318a526c639306d9d07ee33cb7c168a Mon Sep 17 00:00:00 2001 From: Alon Ziv Date: Sun, 10 Oct 2010 08:32:20 +0200 Subject: [PATCH 114/141] USB: opticon: Whitespace fixes in opticon driver Signed-off-by: Alon Ziv Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 4fe7c3d9ef98..eda1f9266c4e 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -108,10 +108,10 @@ static void opticon_bulk_callback(struct urb *urb) else priv->rts = true; } else { - dev_dbg(&priv->udev->dev, - "Unknown data packet received from the device:" - " %2x %2x\n", - data[0], data[1]); + dev_dbg(&priv->udev->dev, + "Unknown data packet received from the device:" + " %2x %2x\n", + data[0], data[1]); } } } else { From a9138192d0e716c3e9714b3fe03543d93ebbad9f Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Sun, 10 Oct 2010 17:59:18 +0200 Subject: [PATCH 115/141] USB: otg/ulpi: improve ulpi phy detection. Improve ulpi phy detection by utilizing the "scratch" register. Allow unknown ulpi phy work without the need to hard-code the id. Signed-off-by: Igor Grinberg Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/ulpi.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index ccc81950822b..e0d2a5c504cc 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/otg/ulpi.c @@ -137,6 +137,32 @@ static int ulpi_set_flags(struct otg_transceiver *otg) return ulpi_set_fc_flags(otg); } +static int ulpi_check_integrity(struct otg_transceiver *otg) +{ + int ret, i; + unsigned int val = 0x55; + + for (i = 0; i < 2; i++) { + ret = otg_io_write(otg, val, ULPI_SCRATCH); + if (ret < 0) + return ret; + + ret = otg_io_read(otg, ULPI_SCRATCH); + if (ret < 0) + return ret; + + if (ret != val) { + pr_err("ULPI integrity check: failed!"); + return -ENODEV; + } + val = val << 1; + } + + pr_info("ULPI integrity check: passed.\n"); + + return 0; +} + static int ulpi_init(struct otg_transceiver *otg) { int i, vid, pid, ret; @@ -155,10 +181,13 @@ static int ulpi_init(struct otg_transceiver *otg) for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) if (ulpi_ids[i] == ULPI_ID(vid, pid)) - return ulpi_set_flags(otg); + break; - pr_err("ULPI ID does not match any known transceiver.\n"); - return -ENODEV; + ret = ulpi_check_integrity(otg); + if (ret) + return ret; + + return ulpi_set_flags(otg); } static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host) From 96b9e83231f543391c29d12e1e65ddb2ed963154 Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Sun, 10 Oct 2010 17:59:19 +0200 Subject: [PATCH 116/141] USB: otg/ulpi: extend id's table. Extend id's table to have ulpi phy names in it. Report if the known phy is found. Signed-off-by: Igor Grinberg Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/ulpi.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index e0d2a5c504cc..059d9ac0ab5b 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/otg/ulpi.c @@ -29,12 +29,23 @@ #include #include + +struct ulpi_info { + unsigned int id; + char *name; +}; + #define ULPI_ID(vendor, product) (((vendor) << 16) | (product)) +#define ULPI_INFO(_id, _name) \ + { \ + .id = (_id), \ + .name = (_name), \ + } /* ULPI hardcoded IDs, used for probing */ -static unsigned int ulpi_ids[] = { - ULPI_ID(0x04cc, 0x1504), /* NXP ISP1504 */ - ULPI_ID(0x0424, 0x0006), /* SMSC USB3319 */ +static struct ulpi_info ulpi_ids[] = { + ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"), + ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB3319"), }; static int ulpi_set_otg_flags(struct otg_transceiver *otg) @@ -179,9 +190,13 @@ static int ulpi_init(struct otg_transceiver *otg) pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid); - for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) - if (ulpi_ids[i] == ULPI_ID(vid, pid)) + for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) { + if (ulpi_ids[i].id == ULPI_ID(vid, pid)) { + pr_info("Found %s ULPI transceiver.\n", + ulpi_ids[i].name); break; + } + } ret = ulpi_check_integrity(otg); if (ret) From ac9dfe9cdda4eb42ecaa9f13b0fee518e0b6518e Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 14 Oct 2010 14:52:54 +0900 Subject: [PATCH 117/141] usb: r8a66597-hcd: Change mistake of the outsw function Some functions changed by 1c98347e613bf17ea2f18c9766ce0ab77f65a96d. However, There was a change mistake of the function (outsw). Signed-off-by: Nobuhiro Iwamatsu CC: Paul Mundt Cc: stable [.35 & .36] Acked-by: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/r8a66597.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h index 95d0f5adfdcf..25563e9a90bc 100644 --- a/drivers/usb/host/r8a66597.h +++ b/drivers/usb/host/r8a66597.h @@ -227,7 +227,7 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, int odd = len & 0x0001; len = len / 2; - ioread16_rep(fifoaddr, buf, len); + iowrite16_rep(fifoaddr, buf, len); if (unlikely(odd)) { buf = &buf[len]; iowrite8((unsigned char)*buf, fifoaddr); From 64927730c66333c9d5987aa72a0e6d44ed91cec7 Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Thu, 14 Oct 2010 07:22:45 -0700 Subject: [PATCH 118/141] USB: xHCI: Add pointer to udev in struct xhci_virt_device Add a pointer to udev in struct xhci_virt_device. When allocate a new virt_device, make the pointer point to the corresponding udev. Modify xhci_check_args(), check if virt_dev->udev matches the target udev, to make sure command is issued to the right device. Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 1 + drivers/usb/host/xhci.c | 83 +++++++++++++++---------------------- drivers/usb/host/xhci.h | 1 + 3 files changed, 36 insertions(+), 49 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 4e51343ddffc..be901808e474 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -778,6 +778,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, init_completion(&dev->cmd_completion); INIT_LIST_HEAD(&dev->cmd_list); + dev->udev = udev; /* Point to output device context in dcbaa. */ xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d5c550ea3e68..0bec04070334 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -607,7 +607,11 @@ unsigned int xhci_last_valid_endpoint(u32 added_ctxs) * returns 0 this is a root hub; returns -EINVAL for NULL pointers. */ int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev, - struct usb_host_endpoint *ep, int check_ep, const char *func) { + struct usb_host_endpoint *ep, int check_ep, bool check_virt_dev, + const char *func) { + struct xhci_hcd *xhci; + struct xhci_virt_device *virt_dev; + if (!hcd || (check_ep && !ep) || !udev) { printk(KERN_DEBUG "xHCI %s called with invalid args\n", func); @@ -618,11 +622,24 @@ int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev, func); return 0; } - if (!udev->slot_id) { - printk(KERN_DEBUG "xHCI %s called with unaddressed device\n", - func); - return -EINVAL; + + if (check_virt_dev) { + xhci = hcd_to_xhci(hcd); + if (!udev->slot_id || !xhci->devs + || !xhci->devs[udev->slot_id]) { + printk(KERN_DEBUG "xHCI %s called with unaddressed " + "device\n", func); + return -EINVAL; + } + + virt_dev = xhci->devs[udev->slot_id]; + if (virt_dev->udev != udev) { + printk(KERN_DEBUG "xHCI %s called with udev and " + "virt_dev does not match\n", func); + return -EINVAL; + } } + return 1; } @@ -704,18 +721,13 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) struct urb_priv *urb_priv; int size, i; - if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0) + if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, + true, true, __func__) <= 0) return -EINVAL; slot_id = urb->dev->slot_id; ep_index = xhci_get_endpoint_index(&urb->ep->desc); - if (!xhci->devs || !xhci->devs[slot_id]) { - if (!in_interrupt()) - dev_warn(&urb->dev->dev, "WARN: urb submitted for dev with no Slot ID\n"); - ret = -EINVAL; - goto exit; - } if (!HCD_HW_ACCESSIBLE(hcd)) { if (!in_interrupt()) xhci_dbg(xhci, "urb submitted during PCI suspend\n"); @@ -991,7 +1003,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, u32 new_add_flags, new_drop_flags, new_slot_info; int ret; - ret = xhci_check_args(hcd, udev, ep, 1, __func__); + ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); if (ret <= 0) return ret; xhci = hcd_to_xhci(hcd); @@ -1004,12 +1016,6 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, return 0; } - if (!xhci->devs || !xhci->devs[udev->slot_id]) { - xhci_warn(xhci, "xHCI %s called with unaddressed device\n", - __func__); - return -EINVAL; - } - in_ctx = xhci->devs[udev->slot_id]->in_ctx; out_ctx = xhci->devs[udev->slot_id]->out_ctx; ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); @@ -1078,7 +1084,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, u32 new_add_flags, new_drop_flags, new_slot_info; int ret = 0; - ret = xhci_check_args(hcd, udev, ep, 1, __func__); + ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); if (ret <= 0) { /* So we won't queue a reset ep command for a root hub */ ep->hcpriv = NULL; @@ -1098,12 +1104,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, return 0; } - if (!xhci->devs || !xhci->devs[udev->slot_id]) { - xhci_warn(xhci, "xHCI %s called with unaddressed device\n", - __func__); - return -EINVAL; - } - in_ctx = xhci->devs[udev->slot_id]->in_ctx; out_ctx = xhci->devs[udev->slot_id]->out_ctx; ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); @@ -1346,16 +1346,11 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_input_control_ctx *ctrl_ctx; struct xhci_slot_ctx *slot_ctx; - ret = xhci_check_args(hcd, udev, NULL, 0, __func__); + ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); if (ret <= 0) return ret; xhci = hcd_to_xhci(hcd); - if (!udev->slot_id || !xhci->devs || !xhci->devs[udev->slot_id]) { - xhci_warn(xhci, "xHCI %s called with unaddressed device\n", - __func__); - return -EINVAL; - } xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev); virt_dev = xhci->devs[udev->slot_id]; @@ -1405,16 +1400,11 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_virt_device *virt_dev; int i, ret; - ret = xhci_check_args(hcd, udev, NULL, 0, __func__); + ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); if (ret <= 0) return; xhci = hcd_to_xhci(hcd); - if (!xhci->devs || !xhci->devs[udev->slot_id]) { - xhci_warn(xhci, "xHCI %s called with unaddressed device\n", - __func__); - return; - } xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev); virt_dev = xhci->devs[udev->slot_id]; /* Free any rings allocated for added endpoints */ @@ -1575,7 +1565,7 @@ static int xhci_check_streams_endpoint(struct xhci_hcd *xhci, if (!ep) return -EINVAL; - ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, __func__); + ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, true, __func__); if (ret <= 0) return -EINVAL; if (ep->ss_ep_comp.bmAttributes == 0) { @@ -1965,17 +1955,12 @@ int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev) int timeleft; int last_freed_endpoint; - ret = xhci_check_args(hcd, udev, NULL, 0, __func__); + ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); if (ret <= 0) return ret; xhci = hcd_to_xhci(hcd); slot_id = udev->slot_id; virt_dev = xhci->devs[slot_id]; - if (!virt_dev) { - xhci_dbg(xhci, "%s called with invalid slot ID %u\n", - __func__, slot_id); - return -EINVAL; - } xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id); /* Allocate the command structure that holds the struct completion. @@ -2077,13 +2062,13 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_virt_device *virt_dev; unsigned long flags; u32 state; - int i; + int i, ret; - if (udev->slot_id == 0) + ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); + if (ret <= 0) return; + virt_dev = xhci->devs[udev->slot_id]; - if (!virt_dev) - return; /* Stop any wayward timer functions (which may grab the lock) */ for (i = 0; i < 31; ++i) { diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 34a60d9f056a..f03f140a7d9a 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -731,6 +731,7 @@ struct xhci_virt_ep { }; struct xhci_virt_device { + struct usb_device *udev; /* * Commands to the hardware are passed an "input context" that * tells the hardware what to change in its data structures. From f0615c45ce5feb141c1172480c5198d4b8d25436 Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Thu, 14 Oct 2010 07:22:48 -0700 Subject: [PATCH 119/141] USB: xHCI: change xhci_reset_device() to allocate new device Rename xhci_reset_device() to xhci_discover_or_reset_device(). If xhci_discover_or_reset_device() is called to reset a device which does not exist or does not match the udev, it calls xhci_alloc_dev() to re-allocate the device. This would prevent the reset device failure, possibly due to the xHC restore error during S3/S4 resume. Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 2 +- drivers/usb/host/xhci.c | 44 ++++++++++++++++++++++++++++++++----- drivers/usb/host/xhci.h | 2 +- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index f7efe025beda..aefc3496376a 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -152,7 +152,7 @@ static const struct hc_driver xhci_pci_hc_driver = { .reset_bandwidth = xhci_reset_bandwidth, .address_device = xhci_address_device, .update_hub_device = xhci_update_hub_device, - .reset_device = xhci_reset_device, + .reset_device = xhci_discover_or_reset_device, /* * scheduling support diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 0bec04070334..7928af5c91cb 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1943,8 +1943,13 @@ int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev, * Wait for the Reset Device command to finish. Remove all structures * associated with the endpoints that were disabled. Clear the input device * structure? Cache the rings? Reset the control endpoint 0 max packet size? + * + * If the virt_dev to be reset does not exist or does not match the udev, + * it means the device is lost, possibly due to the xHC restore error and + * re-initialization during S3/S4. In this case, call xhci_alloc_dev() to + * re-allocate the device. */ -int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev) +int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) { int ret, i; unsigned long flags; @@ -1955,12 +1960,36 @@ int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev) int timeleft; int last_freed_endpoint; - ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); + ret = xhci_check_args(hcd, udev, NULL, 0, false, __func__); if (ret <= 0) return ret; xhci = hcd_to_xhci(hcd); slot_id = udev->slot_id; virt_dev = xhci->devs[slot_id]; + if (!virt_dev) { + xhci_dbg(xhci, "The device to be reset with slot ID %u does " + "not exist. Re-allocate the device\n", slot_id); + ret = xhci_alloc_dev(hcd, udev); + if (ret == 1) + return 0; + else + return -EINVAL; + } + + if (virt_dev->udev != udev) { + /* If the virt_dev and the udev does not match, this virt_dev + * may belong to another udev. + * Re-allocate the device. + */ + xhci_dbg(xhci, "The device to be reset with slot ID %u does " + "not match the udev. Re-allocate the device\n", + slot_id); + ret = xhci_alloc_dev(hcd, udev); + if (ret == 1) + return 0; + else + return -EINVAL; + } xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id); /* Allocate the command structure that holds the struct completion. @@ -2176,12 +2205,17 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) virt_dev = xhci->devs[udev->slot_id]; - /* If this is a Set Address to an unconfigured device, setup ep 0 */ - if (!udev->config) + slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); + /* + * If this is the first Set Address since device plug-in or + * virt_device realloaction after a resume with an xHCI power loss, + * then set up the slot context. + */ + if (!slot_ctx->dev_info) xhci_setup_addressable_virt_dev(xhci, udev); + /* Otherwise, update the control endpoint ring enqueue pointer. */ else xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev); - /* Otherwise, assume the core has the device configured how it wants */ xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index f03f140a7d9a..490409f918f2 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1389,7 +1389,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status); int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); void xhci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep); -int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev); +int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev); int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); From c8d4af8e2af12cd4835ba5c4b54bdafe9deda71a Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Thu, 14 Oct 2010 07:22:51 -0700 Subject: [PATCH 120/141] USB: core: use kernel assigned address for devices under xHCI xHCI driver uses hardware assigned device address. This may cause device address conflict in certain cases. Use kernel assigned address for devices under xHCI. Store the xHC assigned address locally in xHCI driver. Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp --- drivers/usb/core/hub.c | 27 +++++++++++++-------------- drivers/usb/host/xhci.c | 8 ++++---- drivers/usb/host/xhci.h | 2 ++ 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 5da546c4fd79..f07ab71859dd 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2594,16 +2594,14 @@ static int hub_set_address(struct usb_device *udev, int devnum) return 0; if (udev->state != USB_STATE_DEFAULT) return -EINVAL; - if (hcd->driver->address_device) { + if (hcd->driver->address_device) retval = hcd->driver->address_device(hcd, udev); - } else { + else retval = usb_control_msg(udev, usb_sndaddr0pipe(), USB_REQ_SET_ADDRESS, 0, devnum, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); - if (retval == 0) - update_address(udev, devnum); - } if (retval == 0) { + update_address(udev, devnum); /* Device now using proper address. */ usb_set_device_state(udev, USB_STATE_ADDRESS); usb_ep0_reinit(udev); @@ -3097,16 +3095,17 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, udev->speed = USB_SPEED_UNKNOWN; /* - * xHCI needs to issue an address device command later - * in the hub_port_init sequence for SS/HS/FS/LS devices. + * Set the address. + * Note xHCI needs to issue an address device command later + * in the hub_port_init sequence for SS/HS/FS/LS devices, + * and xHC will assign an address to the device. But use + * kernel assigned address here, to avoid any address conflict + * issue. */ - if (!(hcd->driver->flags & HCD_USB3)) { - /* set the address */ - choose_address(udev); - if (udev->devnum <= 0) { - status = -ENOTCONN; /* Don't retry */ - goto loop; - } + choose_address(udev); + if (udev->devnum <= 0) { + status = -ENOTCONN; /* Don't retry */ + goto loop; } /* reset (non-USB 3.0 devices) and get descriptor */ diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7928af5c91cb..caccecb7368e 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2287,15 +2287,15 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) * address given back to us by the HC. */ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); - udev->devnum = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1; + /* Use kernel assigned address for devices; store xHC assigned + * address locally. */ + virt_dev->address = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1; /* Zero the input context control for later use */ ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); ctrl_ctx->add_flags = 0; ctrl_ctx->drop_flags = 0; - xhci_dbg(xhci, "Device address = %d\n", udev->devnum); - /* XXX Meh, not sure if anyone else but choose_address uses this. */ - set_bit(udev->devnum, udev->bus->devmap.devicemap); + xhci_dbg(xhci, "Internal device address = %d\n", virt_dev->address); return 0; } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 490409f918f2..a7181b491e67 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -746,6 +746,8 @@ struct xhci_virt_device { /* Rings saved to ensure old alt settings can be re-instated */ struct xhci_ring **ring_cache; int num_rings_cached; + /* Store xHC assigned device address */ + int address; #define XHCI_MAX_RINGS_CACHED 31 struct xhci_virt_ep eps[31]; struct completion cmd_completion; From 85f0ff46960c2853fd1436a56798260eae91db86 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 14 Oct 2010 07:22:54 -0700 Subject: [PATCH 121/141] usb: Fix issue with USB 3.0 devices after system resume When the system suspends and a host controller's power is lost, the USB core attempts to revive any USB devices that had the persist_enabled flag set. For non-SuperSpeed devices, it will disable the port, and then set the udev->reset_resume flag. This will cause the USB core to reset the device, verify the device descriptors to make sure it's the same device, and re-install any non-default configurations or alternate interface settings. However, we can't disable SuperSpeed root hub ports because that turns off SuperSpeed terminations, which will inhibit any devices connecting at USB 3.0 speeds. (Plus external hubs don't allow SuperSpeed ports to be disabled.) Because of this logic in hub_activate(): /* We can forget about a "removed" device when there's a * physical disconnect or the connect status changes. */ if (!(portstatus & USB_PORT_STAT_CONNECTION) || (portchange & USB_PORT_STAT_C_CONNECTION)) clear_bit(port1, hub->removed_bits); if (!udev || udev->state == USB_STATE_NOTATTACHED) { /* Tell khubd to disconnect the device or * check for a new connection */ if (udev || (portstatus & USB_PORT_STAT_CONNECTION)) set_bit(port1, hub->change_bits); } else if (portstatus & USB_PORT_STAT_ENABLE) { /* The power session apparently survived the resume. * If there was an overcurrent or suspend change * (i.e., remote wakeup request), have khubd * take care of it. */ if (portchange) set_bit(port1, hub->change_bits); } else if (udev->persist_enabled) { udev->reset_resume = 1; set_bit(port1, hub->change_bits); } else { /* The power session is gone; tell khubd */ usb_set_device_state(udev, USB_STATE_NOTATTACHED); set_bit(port1, hub->change_bits); } a SuperSpeed device after a resume with a loss of power will never get the reset_resume flag set. Instead the core will assume the power session survived and that the device still has the same address, configuration, and alternate interface settings. The xHCI host controller will have no knowledge of the device (since all xhci_virt_devices were destroyed when power loss was discovered, and xhci_discover_or_reset_device() has not been called), and all URBs to the device will fail. If the device driver responds by resetting the device, everything will continue smoothly. However, if lsusb is used before the device driver resets the device (or there is no driver), then all lsusb descriptor fetches will fail. The quick fix is to pretend the port is disabled in hub_activate(), by clearing the local variable. But I'm not sure what other parts of the hub driver need to be changed because they have assumptions about when ports will be disabled. Signed-off-by: Sarah Sharp Signed-off-by: Andiry Xu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f07ab71859dd..7f82c48a0bae 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -758,6 +758,9 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); portstatus &= ~USB_PORT_STAT_ENABLE; + } else { + /* Pretend that power was lost for USB3 devs */ + portstatus &= ~USB_PORT_STAT_ENABLE; } } From be88fe4f4dda93e3264a887745123b1e6c4a6845 Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Thu, 14 Oct 2010 07:22:57 -0700 Subject: [PATCH 122/141] USB: xHCI: port power management implementation Add software trigger USB device suspend resume function hook. Do port suspend & resume in terms of xHCI spec. Port Suspend: Stop all endpoints via Stop Endpoint Command with Suspend (SP) flag set. Place individual ports into suspend mode by writing '3' for Port Link State (PLS) field into PORTSC register. This can only be done when the port is in Enabled state. When writing, the Port Link State Write Strobe (LWS) bit shall be set to '1'. Allocate an xhci_command and stash it in xhci_virt_device to wait completion for the last Stop Endpoint Command. Use the Suspend bit in TRB to indicate the Stop Endpoint Command is for port suspend. Based on Sarah's suggestion. Port Resume: Write '0' in PLS field, device will transition to running state. Ring an endpoints' doorbell to restart it. Ref: USB device remote wake need another patch to implement. For details of how USB subsystem do power management, please see: Documentation/usb/power-management.txt Signed-off-by: Crane Cai Signed-off-by: Libin Yang Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hub.c | 196 ++++++++++++++++++++++++++++++++++- drivers/usb/host/xhci-mem.c | 1 + drivers/usb/host/xhci-ring.c | 44 ++++++-- drivers/usb/host/xhci.c | 2 +- drivers/usb/host/xhci.h | 17 ++- 5 files changed, 248 insertions(+), 12 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index a1a7a9795536..14b48b261e06 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -129,6 +129,99 @@ static u32 xhci_port_state_to_neutral(u32 state) return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS); } +/* + * find slot id based on port number. + */ +static int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port) +{ + int slot_id; + int i; + + slot_id = 0; + for (i = 0; i < MAX_HC_SLOTS; i++) { + if (!xhci->devs[i]) + continue; + if (xhci->devs[i]->port == port) { + slot_id = i; + break; + } + } + + return slot_id; +} + +/* + * Stop device + * It issues stop endpoint command for EP 0 to 30. And wait the last command + * to complete. + * suspend will set to 1, if suspend bit need to set in command. + */ +static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) +{ + struct xhci_virt_device *virt_dev; + struct xhci_command *cmd; + unsigned long flags; + int timeleft; + int ret; + int i; + + ret = 0; + virt_dev = xhci->devs[slot_id]; + cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO); + if (!cmd) { + xhci_dbg(xhci, "Couldn't allocate command structure.\n"); + return -ENOMEM; + } + + spin_lock_irqsave(&xhci->lock, flags); + for (i = LAST_EP_INDEX; i > 0; i--) { + if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue) + xhci_queue_stop_endpoint(xhci, slot_id, i, suspend); + } + cmd->command_trb = xhci->cmd_ring->enqueue; + list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list); + xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend); + xhci_ring_cmd_db(xhci); + spin_unlock_irqrestore(&xhci->lock, flags); + + /* Wait for last stop endpoint command to finish */ + timeleft = wait_for_completion_interruptible_timeout( + cmd->completion, + USB_CTRL_SET_TIMEOUT); + if (timeleft <= 0) { + xhci_warn(xhci, "%s while waiting for stop endpoint command\n", + timeleft == 0 ? "Timeout" : "Signal"); + spin_lock_irqsave(&xhci->lock, flags); + /* The timeout might have raced with the event ring handler, so + * only delete from the list if the item isn't poisoned. + */ + if (cmd->cmd_list.next != LIST_POISON1) + list_del(&cmd->cmd_list); + spin_unlock_irqrestore(&xhci->lock, flags); + ret = -ETIME; + goto command_cleanup; + } + +command_cleanup: + xhci_free_command(xhci, cmd); + return ret; +} + +/* + * Ring device, it rings the all doorbells unconditionally. + */ +static void xhci_ring_device(struct xhci_hcd *xhci, int slot_id) +{ + int i; + + for (i = 0; i < LAST_EP_INDEX + 1; i++) + if (xhci->devs[slot_id]->eps[i].ring && + xhci->devs[slot_id]->eps[i].ring->dequeue) + xhci_ring_ep_doorbell(xhci, slot_id, i, 0); + + return; +} + static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex, u32 __iomem *addr, u32 port_status) { @@ -162,6 +255,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, status = PORT_PEC; port_change_bit = "enable/disable"; break; + case USB_PORT_FEAT_C_SUSPEND: + status = PORT_PLC; + port_change_bit = "suspend/resume"; + break; default: /* Should never happen */ return; @@ -182,6 +279,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u32 temp, status; int retval = 0; u32 __iomem *addr; + int slot_id; ports = HCS_MAX_PORTS(xhci->hcs_params1); @@ -211,9 +309,21 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, if ((temp & PORT_OCC)) status |= USB_PORT_STAT_C_OVERCURRENT << 16; /* - * FIXME ignoring suspend, reset, and USB 2.1/3.0 specific + * FIXME ignoring reset and USB 2.1/3.0 specific * changes */ + if ((temp & PORT_PLS_MASK) == XDEV_U3 + && (temp & PORT_POWER)) + status |= 1 << USB_PORT_FEAT_SUSPEND; + if ((temp & PORT_PLS_MASK) == XDEV_U0 + && (temp & PORT_POWER) + && (xhci->suspended_ports[wIndex >> 5] & + (1 << (wIndex & 31)))) { + xhci->suspended_ports[wIndex >> 5] &= + ~(1 << (wIndex & 31)); + xhci->port_c_suspend[wIndex >> 5] |= + 1 << (wIndex & 31); + } if (temp & PORT_CONNECT) { status |= USB_PORT_STAT_CONNECTION; status |= xhci_port_speed(temp); @@ -226,6 +336,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, status |= USB_PORT_STAT_RESET; if (temp & PORT_POWER) status |= USB_PORT_STAT_POWER; + if (xhci->port_c_suspend[wIndex >> 5] & (1 << (wIndex & 31))) + status |= 1 << USB_PORT_FEAT_C_SUSPEND; xhci_dbg(xhci, "Get port status returned 0x%x\n", status); put_unaligned(cpu_to_le32(status), (__le32 *) buf); break; @@ -238,6 +350,42 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = xhci_readl(xhci, addr); temp = xhci_port_state_to_neutral(temp); switch (wValue) { + case USB_PORT_FEAT_SUSPEND: + temp = xhci_readl(xhci, addr); + /* In spec software should not attempt to suspend + * a port unless the port reports that it is in the + * enabled (PED = ‘1’,PLS < ‘3’) state. + */ + if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) + || (temp & PORT_PLS_MASK) >= XDEV_U3) { + xhci_warn(xhci, "USB core suspending device " + "not in U0/U1/U2.\n"); + goto error; + } + + slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1); + if (!slot_id) { + xhci_warn(xhci, "slot_id is zero\n"); + goto error; + } + /* unlock to execute stop endpoint commands */ + spin_unlock_irqrestore(&xhci->lock, flags); + xhci_stop_device(xhci, slot_id, 1); + spin_lock_irqsave(&xhci->lock, flags); + + temp = xhci_port_state_to_neutral(temp); + temp &= ~PORT_PLS_MASK; + temp |= PORT_LINK_STROBE | XDEV_U3; + xhci_writel(xhci, temp, addr); + + spin_unlock_irqrestore(&xhci->lock, flags); + msleep(10); /* wait device to enter */ + spin_lock_irqsave(&xhci->lock, flags); + + temp = xhci_readl(xhci, addr); + xhci->suspended_ports[wIndex >> 5] |= + 1 << (wIndex & (31)); + break; case USB_PORT_FEAT_POWER: /* * Turn on ports, even if there isn't per-port switching. @@ -271,6 +419,52 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = xhci_readl(xhci, addr); temp = xhci_port_state_to_neutral(temp); switch (wValue) { + case USB_PORT_FEAT_SUSPEND: + temp = xhci_readl(xhci, addr); + xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n"); + xhci_dbg(xhci, "PORTSC %04x\n", temp); + if (temp & PORT_RESET) + goto error; + if (temp & XDEV_U3) { + if ((temp & PORT_PE) == 0) + goto error; + if (DEV_SUPERSPEED(temp)) { + temp = xhci_port_state_to_neutral(temp); + temp &= ~PORT_PLS_MASK; + temp |= PORT_LINK_STROBE | XDEV_U0; + xhci_writel(xhci, temp, addr); + xhci_readl(xhci, addr); + } else { + temp = xhci_port_state_to_neutral(temp); + temp &= ~PORT_PLS_MASK; + temp |= PORT_LINK_STROBE | XDEV_RESUME; + xhci_writel(xhci, temp, addr); + + spin_unlock_irqrestore(&xhci->lock, + flags); + msleep(20); + spin_lock_irqsave(&xhci->lock, flags); + + temp = xhci_readl(xhci, addr); + temp = xhci_port_state_to_neutral(temp); + temp &= ~PORT_PLS_MASK; + temp |= PORT_LINK_STROBE | XDEV_U0; + xhci_writel(xhci, temp, addr); + } + xhci->port_c_suspend[wIndex >> 5] |= + 1 << (wIndex & 31); + } + + slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1); + if (!slot_id) { + xhci_dbg(xhci, "slot_id is zero\n"); + goto error; + } + xhci_ring_device(xhci, slot_id); + break; + case USB_PORT_FEAT_C_SUSPEND: + xhci->port_c_suspend[wIndex >> 5] &= + ~(1 << (wIndex & 31)); case USB_PORT_FEAT_C_RESET: case USB_PORT_FEAT_C_CONNECTION: case USB_PORT_FEAT_C_OVER_CURRENT: diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index be901808e474..858a82867e1d 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -867,6 +867,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud top_dev = top_dev->parent) /* Found device below root hub */; slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum); + dev->port = top_dev->portnum; xhci_dbg(xhci, "Set root hub portnum to %d\n", top_dev->portnum); /* Is this a LS/FS device under a HS hub? */ diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 48e60d166ff0..b18e00ecb468 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -68,6 +68,10 @@ #include #include "xhci.h" +static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, + struct xhci_virt_device *virt_dev, + struct xhci_event_cmd *event); + /* * Returns zero if the TRB isn't in this segment, otherwise it returns the DMA * address of the TRB. @@ -313,7 +317,7 @@ void xhci_ring_cmd_db(struct xhci_hcd *xhci) xhci_readl(xhci, &xhci->dba->doorbell[0]); } -static void ring_ep_doorbell(struct xhci_hcd *xhci, +void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, unsigned int stream_id) @@ -353,7 +357,7 @@ static void ring_doorbell_for_active_rings(struct xhci_hcd *xhci, /* A ring has pending URBs if its TD list is not empty */ if (!(ep->ep_state & EP_HAS_STREAMS)) { if (!(list_empty(&ep->ring->td_list))) - ring_ep_doorbell(xhci, slot_id, ep_index, 0); + xhci_ring_ep_doorbell(xhci, slot_id, ep_index, 0); return; } @@ -361,7 +365,8 @@ static void ring_doorbell_for_active_rings(struct xhci_hcd *xhci, stream_id++) { struct xhci_stream_info *stream_info = ep->stream_info; if (!list_empty(&stream_info->stream_rings[stream_id]->td_list)) - ring_ep_doorbell(xhci, slot_id, ep_index, stream_id); + xhci_ring_ep_doorbell(xhci, slot_id, ep_index, + stream_id); } } @@ -626,10 +631,11 @@ static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci, * bit cleared) so that the HW will skip over them. */ static void handle_stopped_endpoint(struct xhci_hcd *xhci, - union xhci_trb *trb) + union xhci_trb *trb, struct xhci_event_cmd *event) { unsigned int slot_id; unsigned int ep_index; + struct xhci_virt_device *virt_dev; struct xhci_ring *ep_ring; struct xhci_virt_ep *ep; struct list_head *entry; @@ -638,6 +644,21 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, struct xhci_dequeue_state deq_state; + if (unlikely(TRB_TO_SUSPEND_PORT( + xhci->cmd_ring->dequeue->generic.field[3]))) { + slot_id = TRB_TO_SLOT_ID( + xhci->cmd_ring->dequeue->generic.field[3]); + virt_dev = xhci->devs[slot_id]; + if (virt_dev) + handle_cmd_in_cmd_wait_list(xhci, virt_dev, + event); + else + xhci_warn(xhci, "Stop endpoint command " + "completion for disabled slot %u\n", + slot_id); + return; + } + memset(&deq_state, 0, sizeof(deq_state)); slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]); ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]); @@ -1091,7 +1112,7 @@ bandwidth_change: complete(&xhci->addr_dev); break; case TRB_TYPE(TRB_STOP_RING): - handle_stopped_endpoint(xhci, xhci->cmd_ring->dequeue); + handle_stopped_endpoint(xhci, xhci->cmd_ring->dequeue, event); break; case TRB_TYPE(TRB_SET_DEQ): handle_set_deq_completion(xhci, event, xhci->cmd_ring->dequeue); @@ -2347,7 +2368,7 @@ static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id, */ wmb(); start_trb->field[3] |= start_cycle; - ring_ep_doorbell(xhci, slot_id, ep_index, stream_id); + xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id); } /* @@ -2931,7 +2952,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, wmb(); start_trb->field[3] |= start_cycle; - ring_ep_doorbell(xhci, slot_id, ep_index, urb->stream_id); + xhci_ring_ep_doorbell(xhci, slot_id, ep_index, urb->stream_id); return 0; } @@ -3108,15 +3129,20 @@ int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, false); } +/* + * Suspend is set to indicate "Stop Endpoint Command" is being issued to stop + * activity on an endpoint that is about to be suspended. + */ int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id, - unsigned int ep_index) + unsigned int ep_index, int suspend) { u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id); u32 trb_ep_index = EP_ID_FOR_TRB(ep_index); u32 type = TRB_TYPE(TRB_STOP_RING); + u32 trb_suspend = SUSPEND_PORT_FOR_TRB(suspend); return queue_command(xhci, 0, 0, 0, - trb_slot_id | trb_ep_index | type, false); + trb_slot_id | trb_ep_index | type | trb_suspend, false); } /* Set Transfer Ring Dequeue Pointer command. diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index caccecb7368e..3d2af688157a 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -968,7 +968,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ep->stop_cmd_timer.expires = jiffies + XHCI_STOP_EP_CMD_TIMEOUT * HZ; add_timer(&ep->stop_cmd_timer); - xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index); + xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index, 0); xhci_ring_cmd_db(xhci); } done: diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index a7181b491e67..73e5db3e89c9 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -269,6 +269,10 @@ struct xhci_op_regs { * A read gives the current link PM state of the port, * a write with Link State Write Strobe set sets the link state. */ +#define PORT_PLS_MASK (0xf << 5) +#define XDEV_U0 (0x0 << 5) +#define XDEV_U3 (0x3 << 5) +#define XDEV_RESUME (0xf << 5) /* true: port has power (see HCC_PPC) */ #define PORT_POWER (1 << 9) /* bits 10:13 indicate device speed: @@ -510,6 +514,7 @@ struct xhci_slot_ctx { #define MAX_EXIT (0xffff) /* Root hub port number that is needed to access the USB device */ #define ROOT_HUB_PORT(p) (((p) & 0xff) << 16) +#define DEVINFO_TO_ROOT_HUB_PORT(p) (((p) >> 16) & 0xff) /* Maximum number of ports under a hub device */ #define XHCI_MAX_PORTS(p) (((p) & 0xff) << 24) @@ -754,6 +759,7 @@ struct xhci_virt_device { /* Status of the last command issued for this device */ u32 cmd_status; struct list_head cmd_list; + u8 port; }; @@ -884,6 +890,10 @@ struct xhci_event_cmd { #define TRB_TO_EP_INDEX(p) ((((p) & (0x1f << 16)) >> 16) - 1) #define EP_ID_FOR_TRB(p) ((((p) + 1) & 0x1f) << 16) +#define SUSPEND_PORT_FOR_TRB(p) (((p) & 1) << 23) +#define TRB_TO_SUSPEND_PORT(p) (((p) & (1 << 23)) >> 23) +#define LAST_EP_INDEX 30 + /* Set TR Dequeue Pointer command TRB fields */ #define TRB_TO_STREAM_ID(p) ((((p) & (0xffff << 16)) >> 16)) #define STREAM_ID_FOR_TRB(p) ((((p)) & 0xffff) << 16) @@ -1202,6 +1212,9 @@ struct xhci_hcd { #define XHCI_LINK_TRB_QUIRK (1 << 0) #define XHCI_RESET_EP_QUIRK (1 << 1) #define XHCI_NEC_HOST (1 << 2) + u32 port_c_suspend[8]; /* port suspend change*/ + u32 suspended_ports[8]; /* which ports are + suspended */ }; /* For testing purposes */ @@ -1409,7 +1422,7 @@ int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, int xhci_queue_vendor_command(struct xhci_hcd *xhci, u32 field1, u32 field2, u32 field3, u32 field4); int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id, - unsigned int ep_index); + unsigned int ep_index, int suspend); int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index); int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, @@ -1439,6 +1452,8 @@ void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, struct xhci_dequeue_state *deq_state); void xhci_stop_endpoint_command_watchdog(unsigned long arg); +void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, + unsigned int ep_index, unsigned int stream_id); /* xHCI roothub code */ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, From 561925318725a41189a69f36ebe99199b3fb84c4 Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Thu, 14 Oct 2010 07:23:00 -0700 Subject: [PATCH 123/141] USB: xHCI: port remote wakeup implementation This commit implements port remote wakeup. When a port is in U3 state and resume signaling is detected from a device, the port transitions to the Resume state, and the xHC generates a Port Status Change Event. For USB3 port, software write a '0' to the PLS field to complete the resume signaling. For USB2 port, the resume should be signaling for at least 20ms, irq handler set a timer for port remote wakeup, and then finishes process in hub_control GetPortStatus. Some codes are borrowed from EHCI code. Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hub.c | 44 ++++++++++++++++++++++++---- drivers/usb/host/xhci-mem.c | 2 ++ drivers/usb/host/xhci-ring.c | 57 +++++++++++++++++++++++++++++++++++- drivers/usb/host/xhci.h | 4 +++ 4 files changed, 101 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 14b48b261e06..8163f17e7043 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -123,7 +123,7 @@ static unsigned int xhci_port_speed(unsigned int port_status) * writing a 0 clears the bit and writing a 1 sets the bit (RWS). * For all other types (RW1S, RW1CS, RW, and RZ), writing a '0' has no effect. */ -static u32 xhci_port_state_to_neutral(u32 state) +u32 xhci_port_state_to_neutral(u32 state) { /* Save read-only status and port state */ return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS); @@ -132,7 +132,7 @@ static u32 xhci_port_state_to_neutral(u32 state) /* * find slot id based on port number. */ -static int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port) +int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port) { int slot_id; int i; @@ -210,7 +210,7 @@ command_cleanup: /* * Ring device, it rings the all doorbells unconditionally. */ -static void xhci_ring_device(struct xhci_hcd *xhci, int slot_id) +void xhci_ring_device(struct xhci_hcd *xhci, int slot_id) { int i; @@ -276,7 +276,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, struct xhci_hcd *xhci = hcd_to_xhci(hcd); int ports; unsigned long flags; - u32 temp, status; + u32 temp, temp1, status; int retval = 0; u32 __iomem *addr; int slot_id; @@ -315,6 +315,34 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, if ((temp & PORT_PLS_MASK) == XDEV_U3 && (temp & PORT_POWER)) status |= 1 << USB_PORT_FEAT_SUSPEND; + if ((temp & PORT_PLS_MASK) == XDEV_RESUME) { + if ((temp & PORT_RESET) || !(temp & PORT_PE)) + goto error; + if (!DEV_SUPERSPEED(temp) && time_after_eq(jiffies, + xhci->resume_done[wIndex])) { + xhci_dbg(xhci, "Resume USB2 port %d\n", + wIndex + 1); + xhci->resume_done[wIndex] = 0; + temp1 = xhci_port_state_to_neutral(temp); + temp1 &= ~PORT_PLS_MASK; + temp1 |= PORT_LINK_STROBE | XDEV_U0; + xhci_writel(xhci, temp1, addr); + + xhci_dbg(xhci, "set port %d resume\n", + wIndex + 1); + slot_id = xhci_find_slot_id_by_port(xhci, + wIndex + 1); + if (!slot_id) { + xhci_dbg(xhci, "slot_id is zero\n"); + goto error; + } + xhci_ring_device(xhci, slot_id); + xhci->port_c_suspend[wIndex >> 5] |= + 1 << (wIndex & 31); + xhci->suspended_ports[wIndex >> 5] &= + ~(1 << (wIndex & 31)); + } + } if ((temp & PORT_PLS_MASK) == XDEV_U0 && (temp & PORT_POWER) && (xhci->suspended_ports[wIndex >> 5] & @@ -500,6 +528,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) { unsigned long flags; u32 temp, status; + u32 mask; int i, retval; struct xhci_hcd *xhci = hcd_to_xhci(hcd); int ports; @@ -512,13 +541,18 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) memset(buf, 0, retval); status = 0; + mask = PORT_CSC | PORT_PEC | PORT_OCC; + spin_lock_irqsave(&xhci->lock, flags); /* For each port, did anything change? If so, set that bit in buf. */ for (i = 0; i < ports; i++) { addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS*i; temp = xhci_readl(xhci, addr); - if (temp & (PORT_CSC | PORT_PEC | PORT_OCC)) { + if ((temp & mask) != 0 || + (xhci->port_c_suspend[i >> 5] & 1 << (i & 31)) || + (xhci->resume_done[i] && time_after_eq( + jiffies, xhci->resume_done[i]))) { buf[(i + 1) / 8] |= 1 << (i + 1) % 8; status = 1; } diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 858a82867e1d..fd888bc0422b 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1803,6 +1803,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) init_completion(&xhci->addr_dev); for (i = 0; i < MAX_HC_SLOTS; ++i) xhci->devs[i] = NULL; + for (i = 0; i < MAX_HC_PORTS; ++i) + xhci->resume_done[i] = 0; if (scratchpad_alloc(xhci, flags)) goto fail; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b18e00ecb468..9f3115e729b1 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1165,17 +1165,72 @@ static void handle_vendor_event(struct xhci_hcd *xhci, static void handle_port_status(struct xhci_hcd *xhci, union xhci_trb *event) { + struct usb_hcd *hcd = xhci_to_hcd(xhci); u32 port_id; + u32 temp, temp1; + u32 __iomem *addr; + int ports; + int slot_id; /* Port status change events always have a successful completion code */ if (GET_COMP_CODE(event->generic.field[2]) != COMP_SUCCESS) { xhci_warn(xhci, "WARN: xHC returned failed port status event\n"); xhci->error_bitmask |= 1 << 8; } - /* FIXME: core doesn't care about all port link state changes yet */ port_id = GET_PORT_ID(event->generic.field[0]); xhci_dbg(xhci, "Port Status Change Event for port %d\n", port_id); + ports = HCS_MAX_PORTS(xhci->hcs_params1); + if ((port_id <= 0) || (port_id > ports)) { + xhci_warn(xhci, "Invalid port id %d\n", port_id); + goto cleanup; + } + + addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS * (port_id - 1); + temp = xhci_readl(xhci, addr); + if ((temp & PORT_CONNECT) && (hcd->state == HC_STATE_SUSPENDED)) { + xhci_dbg(xhci, "resume root hub\n"); + usb_hcd_resume_root_hub(hcd); + } + + if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) { + xhci_dbg(xhci, "port resume event for port %d\n", port_id); + + temp1 = xhci_readl(xhci, &xhci->op_regs->command); + if (!(temp1 & CMD_RUN)) { + xhci_warn(xhci, "xHC is not running.\n"); + goto cleanup; + } + + if (DEV_SUPERSPEED(temp)) { + xhci_dbg(xhci, "resume SS port %d\n", port_id); + temp = xhci_port_state_to_neutral(temp); + temp &= ~PORT_PLS_MASK; + temp |= PORT_LINK_STROBE | XDEV_U0; + xhci_writel(xhci, temp, addr); + slot_id = xhci_find_slot_id_by_port(xhci, port_id); + if (!slot_id) { + xhci_dbg(xhci, "slot_id is zero\n"); + goto cleanup; + } + xhci_ring_device(xhci, slot_id); + xhci_dbg(xhci, "resume SS port %d finished\n", port_id); + /* Clear PORT_PLC */ + temp = xhci_readl(xhci, addr); + temp = xhci_port_state_to_neutral(temp); + temp |= PORT_PLC; + xhci_writel(xhci, temp, addr); + } else { + xhci_dbg(xhci, "resume HS port %d\n", port_id); + xhci->resume_done[port_id - 1] = jiffies + + msecs_to_jiffies(20); + mod_timer(&hcd->rh_timer, + xhci->resume_done[port_id - 1]); + /* Do the rest in GetPortStatus */ + } + } + +cleanup: /* Update event ring dequeue pointer before dropping the lock */ inc_deq(xhci, xhci->event_ring, true); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 73e5db3e89c9..ca4a923dc810 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1215,6 +1215,7 @@ struct xhci_hcd { u32 port_c_suspend[8]; /* port suspend change*/ u32 suspended_ports[8]; /* which ports are suspended */ + unsigned long resume_done[MAX_HC_PORTS]; }; /* For testing purposes */ @@ -1459,6 +1460,9 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength); int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); +u32 xhci_port_state_to_neutral(u32 state); +int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port); +void xhci_ring_device(struct xhci_hcd *xhci, int slot_id); /* xHCI contexts */ struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx); From 9777e3ce907d4cb5a513902a87ecd03b52499569 Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Thu, 14 Oct 2010 07:23:03 -0700 Subject: [PATCH 124/141] USB: xHCI: bus power management implementation This patch implements xHCI bus suspend/resume function hook. In the patch it goes through all the ports and suspend/resume the ports if needed. If any port is in remote wakeup, abort bus suspend as what ehci/ohci do. Signed-off-by: Libin Yang Signed-off-by: Crane Cai Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hub.c | 188 ++++++++++++++++++++++++++++++++++++ drivers/usb/host/xhci-mem.c | 1 + drivers/usb/host/xhci-pci.c | 2 + drivers/usb/host/xhci.h | 9 ++ 4 files changed, 200 insertions(+) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 8163f17e7043..7f2f63cb6c53 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -24,6 +24,10 @@ #include "xhci.h" +#define PORT_WAKE_BITS (PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E) +#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \ + PORT_RC | PORT_PLC | PORT_PE) + static void xhci_hub_descriptor(struct xhci_hcd *xhci, struct usb_hub_descriptor *desc) { @@ -560,3 +564,187 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) spin_unlock_irqrestore(&xhci->lock, flags); return status ? retval : 0; } + +#ifdef CONFIG_PM + +int xhci_bus_suspend(struct usb_hcd *hcd) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + int port; + unsigned long flags; + + xhci_dbg(xhci, "suspend root hub\n"); + + spin_lock_irqsave(&xhci->lock, flags); + + if (hcd->self.root_hub->do_remote_wakeup) { + port = HCS_MAX_PORTS(xhci->hcs_params1); + while (port--) { + if (xhci->resume_done[port] != 0) { + spin_unlock_irqrestore(&xhci->lock, flags); + xhci_dbg(xhci, "suspend failed because " + "port %d is resuming\n", + port + 1); + return -EBUSY; + } + } + } + + port = HCS_MAX_PORTS(xhci->hcs_params1); + xhci->bus_suspended = 0; + while (port--) { + /* suspend the port if the port is not suspended */ + u32 __iomem *addr; + u32 t1, t2; + int slot_id; + + addr = &xhci->op_regs->port_status_base + + NUM_PORT_REGS * (port & 0xff); + t1 = xhci_readl(xhci, addr); + t2 = xhci_port_state_to_neutral(t1); + + if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) { + xhci_dbg(xhci, "port %d not suspended\n", port); + slot_id = xhci_find_slot_id_by_port(xhci, port + 1); + if (slot_id) { + spin_unlock_irqrestore(&xhci->lock, flags); + xhci_stop_device(xhci, slot_id, 1); + spin_lock_irqsave(&xhci->lock, flags); + } + t2 &= ~PORT_PLS_MASK; + t2 |= PORT_LINK_STROBE | XDEV_U3; + set_bit(port, &xhci->bus_suspended); + } + if (hcd->self.root_hub->do_remote_wakeup) { + if (t1 & PORT_CONNECT) { + t2 |= PORT_WKOC_E | PORT_WKDISC_E; + t2 &= ~PORT_WKCONN_E; + } else { + t2 |= PORT_WKOC_E | PORT_WKCONN_E; + t2 &= ~PORT_WKDISC_E; + } + } else + t2 &= ~PORT_WAKE_BITS; + + t1 = xhci_port_state_to_neutral(t1); + if (t1 != t2) + xhci_writel(xhci, t2, addr); + + if (DEV_HIGHSPEED(t1)) { + /* enable remote wake up for USB 2.0 */ + u32 __iomem *addr; + u32 tmp; + + addr = &xhci->op_regs->port_power_base + + NUM_PORT_REGS * (port & 0xff); + tmp = xhci_readl(xhci, addr); + tmp |= PORT_RWE; + xhci_writel(xhci, tmp, addr); + } + } + hcd->state = HC_STATE_SUSPENDED; + xhci->next_statechange = jiffies + msecs_to_jiffies(10); + spin_unlock_irqrestore(&xhci->lock, flags); + return 0; +} + +int xhci_bus_resume(struct usb_hcd *hcd) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + int port; + u32 temp; + unsigned long flags; + + xhci_dbg(xhci, "resume root hub\n"); + + if (time_before(jiffies, xhci->next_statechange)) + msleep(5); + + spin_lock_irqsave(&xhci->lock, flags); + if (!HCD_HW_ACCESSIBLE(hcd)) { + spin_unlock_irqrestore(&xhci->lock, flags); + return -ESHUTDOWN; + } + + /* delay the irqs */ + temp = xhci_readl(xhci, &xhci->op_regs->command); + temp &= ~CMD_EIE; + xhci_writel(xhci, temp, &xhci->op_regs->command); + + port = HCS_MAX_PORTS(xhci->hcs_params1); + while (port--) { + /* Check whether need resume ports. If needed + resume port and disable remote wakeup */ + u32 __iomem *addr; + u32 temp; + int slot_id; + + addr = &xhci->op_regs->port_status_base + + NUM_PORT_REGS * (port & 0xff); + temp = xhci_readl(xhci, addr); + if (DEV_SUPERSPEED(temp)) + temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS); + else + temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); + if (test_bit(port, &xhci->bus_suspended) && + (temp & PORT_PLS_MASK)) { + if (DEV_SUPERSPEED(temp)) { + temp = xhci_port_state_to_neutral(temp); + temp &= ~PORT_PLS_MASK; + temp |= PORT_LINK_STROBE | XDEV_U0; + xhci_writel(xhci, temp, addr); + } else { + temp = xhci_port_state_to_neutral(temp); + temp &= ~PORT_PLS_MASK; + temp |= PORT_LINK_STROBE | XDEV_RESUME; + xhci_writel(xhci, temp, addr); + + spin_unlock_irqrestore(&xhci->lock, flags); + msleep(20); + spin_lock_irqsave(&xhci->lock, flags); + + temp = xhci_readl(xhci, addr); + temp = xhci_port_state_to_neutral(temp); + temp &= ~PORT_PLS_MASK; + temp |= PORT_LINK_STROBE | XDEV_U0; + xhci_writel(xhci, temp, addr); + } + slot_id = xhci_find_slot_id_by_port(xhci, port + 1); + if (slot_id) + xhci_ring_device(xhci, slot_id); + } else + xhci_writel(xhci, temp, addr); + + if (DEV_HIGHSPEED(temp)) { + /* disable remote wake up for USB 2.0 */ + u32 __iomem *addr; + u32 tmp; + + addr = &xhci->op_regs->port_power_base + + NUM_PORT_REGS * (port & 0xff); + tmp = xhci_readl(xhci, addr); + tmp &= ~PORT_RWE; + xhci_writel(xhci, tmp, addr); + } + } + + (void) xhci_readl(xhci, &xhci->op_regs->command); + + xhci->next_statechange = jiffies + msecs_to_jiffies(5); + hcd->state = HC_STATE_RUNNING; + /* re-enable irqs */ + temp = xhci_readl(xhci, &xhci->op_regs->command); + temp |= CMD_EIE; + xhci_writel(xhci, temp, &xhci->op_regs->command); + temp = xhci_readl(xhci, &xhci->op_regs->command); + + spin_unlock_irqrestore(&xhci->lock, flags); + return 0; +} + +#else + +#define xhci_bus_suspend NULL +#define xhci_bus_resume NULL + +#endif diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index fd888bc0422b..202770676da3 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1445,6 +1445,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) scratchpad_free(xhci); xhci->page_size = 0; xhci->page_shift = 0; + xhci->bus_suspended = 0; } static int xhci_test_trb_in_td(struct xhci_hcd *xhci, diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index aefc3496376a..3865f8c6f647 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -162,6 +162,8 @@ static const struct hc_driver xhci_pci_hc_driver = { /* Root hub support */ .hub_control = xhci_hub_control, .hub_status_data = xhci_hub_status_data, + .bus_suspend = xhci_bus_suspend, + .bus_resume = xhci_bus_resume, }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index ca4a923dc810..196e21fb36ff 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -357,6 +357,8 @@ struct xhci_op_regs { #define PORT_U2_TIMEOUT(p) (((p) & 0xff) << 8) /* Bits 24:31 for port testing */ +/* USB2 Protocol PORTSPMSC */ +#define PORT_RWE (1 << 0x3) /** * struct xhci_intr_reg - Interrupt Register Set @@ -1191,6 +1193,11 @@ struct xhci_hcd { #endif /* Host controller watchdog timer structures */ unsigned int xhc_state; + + unsigned long bus_suspended; + unsigned long next_statechange; + + u32 command; /* Host controller is dying - not responding to commands. "I'm not dead yet!" * * xHC interrupts have been disabled and a watchdog timer will (or has already) @@ -1460,6 +1467,8 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength); int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); +int xhci_bus_suspend(struct usb_hcd *hcd); +int xhci_bus_resume(struct usb_hcd *hcd); u32 xhci_port_state_to_neutral(u32 state); int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port); void xhci_ring_device(struct xhci_hcd *xhci, int slot_id); From 5535b1d5f8885695c6ded783c692e3c0d0eda8ca Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Thu, 14 Oct 2010 07:23:06 -0700 Subject: [PATCH 125/141] USB: xHCI: PCI power management implementation This patch implements the PCI suspend/resume. Please refer to xHCI spec for doing the suspend/resume operation. For S3, CSS/SRS in USBCMD is used to save/restore the internal state. However, an error maybe occurs while restoring the internal state. In this case, it means that HC internal state is wrong and HC will be re-initialized. Signed-off-by: Libin Yang Signed-off-by: Dong Nguyen Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-pci.c | 34 +++++- drivers/usb/host/xhci.c | 210 ++++++++++++++++++++++++++++++++++++ drivers/usb/host/xhci.h | 16 ++- 3 files changed, 258 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 3865f8c6f647..bb668a894ab9 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -116,6 +116,30 @@ static int xhci_pci_setup(struct usb_hcd *hcd) return xhci_pci_reinit(xhci, pdev); } +#ifdef CONFIG_PM +static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + int retval = 0; + + if (hcd->state != HC_STATE_SUSPENDED) + return -EINVAL; + + retval = xhci_suspend(xhci); + + return retval; +} + +static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + int retval = 0; + + retval = xhci_resume(xhci, hibernated); + return retval; +} +#endif /* CONFIG_PM */ + static const struct hc_driver xhci_pci_hc_driver = { .description = hcd_name, .product_desc = "xHCI Host Controller", @@ -132,7 +156,10 @@ static const struct hc_driver xhci_pci_hc_driver = { */ .reset = xhci_pci_setup, .start = xhci_run, - /* suspend and resume implemented later */ +#ifdef CONFIG_PM + .pci_suspend = xhci_pci_suspend, + .pci_resume = xhci_pci_resume, +#endif .stop = xhci_stop, .shutdown = xhci_shutdown, @@ -188,6 +215,11 @@ static struct pci_driver xhci_pci_driver = { /* suspend and resume implemented later */ .shutdown = usb_hcd_pci_shutdown, +#ifdef CONFIG_PM_SLEEP + .driver = { + .pm = &usb_hcd_pci_pm_ops + }, +#endif }; int xhci_register_pci(void) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 3d2af688157a..33d0034d8a6f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -551,6 +551,216 @@ void xhci_shutdown(struct usb_hcd *hcd) xhci_readl(xhci, &xhci->op_regs->status)); } +static void xhci_save_registers(struct xhci_hcd *xhci) +{ + xhci->s3.command = xhci_readl(xhci, &xhci->op_regs->command); + xhci->s3.dev_nt = xhci_readl(xhci, &xhci->op_regs->dev_notification); + xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); + xhci->s3.config_reg = xhci_readl(xhci, &xhci->op_regs->config_reg); + xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); + xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control); + xhci->s3.erst_size = xhci_readl(xhci, &xhci->ir_set->erst_size); + xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base); + xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); +} + +static void xhci_restore_registers(struct xhci_hcd *xhci) +{ + xhci_writel(xhci, xhci->s3.command, &xhci->op_regs->command); + xhci_writel(xhci, xhci->s3.dev_nt, &xhci->op_regs->dev_notification); + xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr); + xhci_writel(xhci, xhci->s3.config_reg, &xhci->op_regs->config_reg); + xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending); + xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control); + xhci_writel(xhci, xhci->s3.erst_size, &xhci->ir_set->erst_size); + xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base); +} + +/* + * Stop HC (not bus-specific) + * + * This is called when the machine transition into S3/S4 mode. + * + */ +int xhci_suspend(struct xhci_hcd *xhci) +{ + int rc = 0; + struct usb_hcd *hcd = xhci_to_hcd(xhci); + u32 command; + + spin_lock_irq(&xhci->lock); + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + /* step 1: stop endpoint */ + /* skipped assuming that port suspend has done */ + + /* step 2: clear Run/Stop bit */ + command = xhci_readl(xhci, &xhci->op_regs->command); + command &= ~CMD_RUN; + xhci_writel(xhci, command, &xhci->op_regs->command); + if (handshake(xhci, &xhci->op_regs->status, + STS_HALT, STS_HALT, 100*100)) { + xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n"); + spin_unlock_irq(&xhci->lock); + return -ETIMEDOUT; + } + + /* step 3: save registers */ + xhci_save_registers(xhci); + + /* step 4: set CSS flag */ + command = xhci_readl(xhci, &xhci->op_regs->command); + command |= CMD_CSS; + xhci_writel(xhci, command, &xhci->op_regs->command); + if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10*100)) { + xhci_warn(xhci, "WARN: xHC CMD_CSS timeout\n"); + spin_unlock_irq(&xhci->lock); + return -ETIMEDOUT; + } + /* step 5: remove core well power */ + xhci_cleanup_msix(xhci); + spin_unlock_irq(&xhci->lock); + + return rc; +} + +/* + * start xHC (not bus-specific) + * + * This is called when the machine transition from S3/S4 mode. + * + */ +int xhci_resume(struct xhci_hcd *xhci, bool hibernated) +{ + u32 command, temp = 0; + struct usb_hcd *hcd = xhci_to_hcd(xhci); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + u64 val_64; + int old_state, retval; + + old_state = hcd->state; + if (time_before(jiffies, xhci->next_statechange)) + msleep(100); + + spin_lock_irq(&xhci->lock); + + if (!hibernated) { + /* step 1: restore register */ + xhci_restore_registers(xhci); + /* step 2: initialize command ring buffer */ + val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); + val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | + (xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, + xhci->cmd_ring->dequeue) & + (u64) ~CMD_RING_RSVD_BITS) | + xhci->cmd_ring->cycle_state; + xhci_dbg(xhci, "// Setting command ring address to 0x%llx\n", + (long unsigned long) val_64); + xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring); + /* step 3: restore state and start state*/ + /* step 3: set CRS flag */ + command = xhci_readl(xhci, &xhci->op_regs->command); + command |= CMD_CRS; + xhci_writel(xhci, command, &xhci->op_regs->command); + if (handshake(xhci, &xhci->op_regs->status, + STS_RESTORE, 0, 10*100)) { + xhci_dbg(xhci, "WARN: xHC CMD_CSS timeout\n"); + spin_unlock_irq(&xhci->lock); + return -ETIMEDOUT; + } + temp = xhci_readl(xhci, &xhci->op_regs->status); + } + + /* If restore operation fails, re-initialize the HC during resume */ + if ((temp & STS_SRE) || hibernated) { + usb_root_hub_lost_power(hcd->self.root_hub); + + xhci_dbg(xhci, "Stop HCD\n"); + xhci_halt(xhci); + xhci_reset(xhci); + if (hibernated) + xhci_cleanup_msix(xhci); + spin_unlock_irq(&xhci->lock); + +#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING + /* Tell the event ring poll function not to reschedule */ + xhci->zombie = 1; + del_timer_sync(&xhci->event_ring_timer); +#endif + + xhci_dbg(xhci, "// Disabling event ring interrupts\n"); + temp = xhci_readl(xhci, &xhci->op_regs->status); + xhci_writel(xhci, temp & ~STS_EINT, &xhci->op_regs->status); + temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); + xhci_writel(xhci, ER_IRQ_DISABLE(temp), + &xhci->ir_set->irq_pending); + xhci_print_ir_set(xhci, xhci->ir_set, 0); + + xhci_dbg(xhci, "cleaning up memory\n"); + xhci_mem_cleanup(xhci); + xhci_dbg(xhci, "xhci_stop completed - status = %x\n", + xhci_readl(xhci, &xhci->op_regs->status)); + + xhci_dbg(xhci, "Initialize the HCD\n"); + retval = xhci_init(hcd); + if (retval) + return retval; + + xhci_dbg(xhci, "Start the HCD\n"); + retval = xhci_run(hcd); + if (!retval) + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + hcd->state = HC_STATE_SUSPENDED; + return retval; + } + + /* Re-setup MSI-X */ + if (hcd->irq) + free_irq(hcd->irq, hcd); + hcd->irq = -1; + + retval = xhci_setup_msix(xhci); + if (retval) + /* fall back to msi*/ + retval = xhci_setup_msi(xhci); + + if (retval) { + /* fall back to legacy interrupt*/ + retval = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, + hcd->irq_descr, hcd); + if (retval) { + xhci_err(xhci, "request interrupt %d failed\n", + pdev->irq); + return retval; + } + hcd->irq = pdev->irq; + } + + /* step 4: set Run/Stop bit */ + command = xhci_readl(xhci, &xhci->op_regs->command); + command |= CMD_RUN; + xhci_writel(xhci, command, &xhci->op_regs->command); + handshake(xhci, &xhci->op_regs->status, STS_HALT, + 0, 250 * 1000); + + /* step 5: walk topology and initialize portsc, + * portpmsc and portli + */ + /* this is done in bus_resume */ + + /* step 6: restart each of the previously + * Running endpoints by ringing their doorbells + */ + + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + if (!hibernated) + hcd->state = old_state; + else + hcd->state = HC_STATE_SUSPENDED; + + spin_unlock_irq(&xhci->lock); + return 0; +} + /*-------------------------------------------------------------------------*/ /** diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 196e21fb36ff..c08928adc524 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -191,7 +191,7 @@ struct xhci_op_regs { /* bits 4:6 are reserved (and should be preserved on writes). */ /* light reset (port status stays unchanged) - reset completed when this is 0 */ #define CMD_LRESET (1 << 7) -/* FIXME: ignoring host controller save/restore state for now. */ +/* host controller save/restore state. */ #define CMD_CSS (1 << 8) #define CMD_CRS (1 << 9) /* Enable Wrap Event - '1' means xHC generates an event when MFINDEX wraps. */ @@ -1130,6 +1130,17 @@ struct urb_priv { #define XHCI_STOP_EP_CMD_TIMEOUT 5 /* XXX: Make these module parameters */ +struct s3_save { + u32 command; + u32 dev_nt; + u64 dcbaa_ptr; + u32 config_reg; + u32 irq_pending; + u32 irq_control; + u32 erst_size; + u64 erst_base; + u64 erst_dequeue; +}; /* There is one ehci_hci structure per controller */ struct xhci_hcd { @@ -1198,6 +1209,7 @@ struct xhci_hcd { unsigned long next_statechange; u32 command; + struct s3_save s3; /* Host controller is dying - not responding to commands. "I'm not dead yet!" * * xHC interrupts have been disabled and a watchdog timer will (or has already) @@ -1393,6 +1405,8 @@ int xhci_init(struct usb_hcd *hcd); int xhci_run(struct usb_hcd *hcd); void xhci_stop(struct usb_hcd *hcd); void xhci_shutdown(struct usb_hcd *hcd); +int xhci_suspend(struct xhci_hcd *xhci); +int xhci_resume(struct xhci_hcd *xhci, bool hibernated); int xhci_get_frame(struct usb_hcd *hcd); irqreturn_t xhci_irq(struct usb_hcd *hcd); irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd); From 56626a72a47bf3e50875d960d6b5f17b9bee0ab2 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 14 Oct 2010 15:25:21 -0400 Subject: [PATCH 126/141] USB: accept some invalid ep0-maxpacket values A few devices (such as the RCA VR5220 voice recorder) are so non-compliant with the USB spec that they have invalid maxpacket sizes for endpoint 0. Nevertheless, as long as we can safely use them, we may as well do so. This patch (as1432) softens our acceptance criterion by allowing high-speed devices to have ep0-maxpacket sizes other than 64. A warning is printed in the system log when this happens, and the existing error message is clarified. Signed-off-by: Alan Stern Reported-by: James Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 7f82c48a0bae..27115b45edc5 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2861,13 +2861,16 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, else i = udev->descriptor.bMaxPacketSize0; if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) { - if (udev->speed != USB_SPEED_FULL || + if (udev->speed == USB_SPEED_LOW || !(i == 8 || i == 16 || i == 32 || i == 64)) { - dev_err(&udev->dev, "ep0 maxpacket = %d\n", i); + dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i); retval = -EMSGSIZE; goto fail; } - dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i); + if (udev->speed == USB_SPEED_FULL) + dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i); + else + dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i); udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i); usb_ep0_reinit(udev); } From b5b5c3ac5123dab047cfeff472053ab737052e9b Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 15 Oct 2010 11:24:14 -0700 Subject: [PATCH 127/141] USB: xhci: Fix compile error when CONFIG_PM=n Fix this error when CONFIG_PM is not enabled: drivers/usb/host/xhci.c:675: error: implicit declaration of function 'usb_root_hub_lost_power' Wrap xhci_suspend() and xhci_resume() into an ifdef CONFIG_PM, along with the functions that only they call -- xhci_save_registers() and xhci_restore_registers(). Reported-by: Randy Dunlap Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 33d0034d8a6f..9dc5be557d92 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -551,6 +551,7 @@ void xhci_shutdown(struct usb_hcd *hcd) xhci_readl(xhci, &xhci->op_regs->status)); } +#ifdef CONFIG_PM static void xhci_save_registers(struct xhci_hcd *xhci) { xhci->s3.command = xhci_readl(xhci, &xhci->op_regs->command); @@ -761,6 +762,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) return 0; } +#else + +#define xhci_suspend NULL +#define xhci_resume NULL + +#endif /* CONFIG_PM */ + /*-------------------------------------------------------------------------*/ /** From 7a9d93e58583efcca0f1ade889b05131ea0d1ed1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 15 Oct 2010 13:26:21 +0800 Subject: [PATCH 128/141] USB: isp116x-hcd - use resource_size instead of defining its own resource_len macro Signed-off-by: Axel Lin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp116x-hcd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index d9e82123de2a..0da7fc05f453 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1557,8 +1557,6 @@ static int isp116x_remove(struct platform_device *pdev) return 0; } -#define resource_len(r) (((r)->end - (r)->start) + 1) - static int __devinit isp116x_probe(struct platform_device *pdev) { struct usb_hcd *hcd; @@ -1597,7 +1595,7 @@ static int __devinit isp116x_probe(struct platform_device *pdev) ret = -EBUSY; goto err1; } - addr_reg = ioremap(addr->start, resource_len(addr)); + addr_reg = ioremap(addr->start, resource_size(addr)); if (addr_reg == NULL) { ret = -ENOMEM; goto err2; @@ -1606,7 +1604,7 @@ static int __devinit isp116x_probe(struct platform_device *pdev) ret = -EBUSY; goto err3; } - data_reg = ioremap(data->start, resource_len(data)); + data_reg = ioremap(data->start, resource_size(data)); if (data_reg == NULL) { ret = -ENOMEM; goto err4; From 4e5c353b3ccc4cc856d75ac751f4c09e0275c08b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 15 Oct 2010 13:27:57 +0800 Subject: [PATCH 129/141] USB: isp1362-hcd - use resource_size instead of defining its own resource_len macro Signed-off-by: Axel Lin Acked-by: Mike Frysinger Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1362-hcd.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index ae3044019382..8196fa11fec4 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2649,8 +2649,6 @@ static struct hc_driver isp1362_hc_driver = { /*-------------------------------------------------------------------------*/ -#define resource_len(r) (((r)->end - (r)->start) + 1) - static int __devexit isp1362_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); @@ -2672,12 +2670,12 @@ static int __devexit isp1362_remove(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 1); DBG(0, "%s: release mem_region: %08lx\n", __func__, (long unsigned int)res->start); if (res) - release_mem_region(res->start, resource_len(res)); + release_mem_region(res->start, resource_size(res)); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); DBG(0, "%s: release mem_region: %08lx\n", __func__, (long unsigned int)res->start); if (res) - release_mem_region(res->start, resource_len(res)); + release_mem_region(res->start, resource_size(res)); DBG(0, "%s: put_hcd\n", __func__); usb_put_hcd(hcd); @@ -2723,21 +2721,21 @@ static int __init isp1362_probe(struct platform_device *pdev) goto err1; } - if (!request_mem_region(addr->start, resource_len(addr), hcd_name)) { + if (!request_mem_region(addr->start, resource_size(addr), hcd_name)) { retval = -EBUSY; goto err1; } - addr_reg = ioremap(addr->start, resource_len(addr)); + addr_reg = ioremap(addr->start, resource_size(addr)); if (addr_reg == NULL) { retval = -ENOMEM; goto err2; } - if (!request_mem_region(data->start, resource_len(data), hcd_name)) { + if (!request_mem_region(data->start, resource_size(data), hcd_name)) { retval = -EBUSY; goto err3; } - data_reg = ioremap(data->start, resource_len(data)); + data_reg = ioremap(data->start, resource_size(data)); if (data_reg == NULL) { retval = -ENOMEM; goto err4; @@ -2795,13 +2793,13 @@ static int __init isp1362_probe(struct platform_device *pdev) iounmap(data_reg); err4: DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)data->start); - release_mem_region(data->start, resource_len(data)); + release_mem_region(data->start, resource_size(data)); err3: DBG(0, "%s: Unmapping addr_reg @ %p\n", __func__, addr_reg); iounmap(addr_reg); err2: DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)addr->start); - release_mem_region(addr->start, resource_len(addr)); + release_mem_region(addr->start, resource_size(addr)); err1: pr_err("%s: init error, %d\n", __func__, retval); From 39eb234874af4322f85e2a29e3aad33ce68cbed5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 15 Oct 2010 13:29:24 +0800 Subject: [PATCH 130/141] USB: ohci-sh - use resource_size instead of defining its own resource_len macro Signed-off-by: Axel Lin Acked-by: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-sh.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c index 60f03cc7ec4f..0b35d22cc70e 100644 --- a/drivers/usb/host/ohci-sh.c +++ b/drivers/usb/host/ohci-sh.c @@ -77,7 +77,6 @@ static const struct hc_driver ohci_sh_hc_driver = { /*-------------------------------------------------------------------------*/ -#define resource_len(r) (((r)->end - (r)->start) + 1) static int ohci_hcd_sh_probe(struct platform_device *pdev) { struct resource *res = NULL; @@ -109,7 +108,7 @@ static int ohci_hcd_sh_probe(struct platform_device *pdev) hcd->regs = (void __iomem *)res->start; hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_len(res); + hcd->rsrc_len = resource_size(res); ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); if (ret != 0) { err("Failed to add hcd"); From 436a389096e1feda2c382cad83b6a8d6de8615a0 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 15 Oct 2010 14:59:15 -0700 Subject: [PATCH 131/141] usb: Fix linker errors with CONFIG_PM=n Fix these linker errors when CONFIG_PM=n: ERROR: "xhci_bus_resume" [drivers/usb/host/xhci-hcd.ko] undefined! ERROR: "xhci_bus_suspend" [drivers/usb/host/xhci-hcd.ko] undefined! Reported-by: Randy Dunlap Signed-off-by: Sarah Sharp Acked-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hub.c | 7 +------ drivers/usb/host/xhci.c | 6 ------ drivers/usb/host/xhci.h | 14 ++++++++++++++ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 7f2f63cb6c53..fef5a1f9d483 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -742,9 +742,4 @@ int xhci_bus_resume(struct usb_hcd *hcd) return 0; } -#else - -#define xhci_bus_suspend NULL -#define xhci_bus_resume NULL - -#endif +#endif /* CONFIG_PM */ diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 9dc5be557d92..5d7d4e951ea4 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -761,12 +761,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) spin_unlock_irq(&xhci->lock); return 0; } - -#else - -#define xhci_suspend NULL -#define xhci_resume NULL - #endif /* CONFIG_PM */ /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index c08928adc524..93d3bf4d213c 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1405,8 +1405,15 @@ int xhci_init(struct usb_hcd *hcd); int xhci_run(struct usb_hcd *hcd); void xhci_stop(struct usb_hcd *hcd); void xhci_shutdown(struct usb_hcd *hcd); + +#ifdef CONFIG_PM int xhci_suspend(struct xhci_hcd *xhci); int xhci_resume(struct xhci_hcd *xhci, bool hibernated); +#else +#define xhci_suspend NULL +#define xhci_resume NULL +#endif + int xhci_get_frame(struct usb_hcd *hcd); irqreturn_t xhci_irq(struct usb_hcd *hcd); irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd); @@ -1481,8 +1488,15 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength); int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); + +#ifdef CONFIG_PM int xhci_bus_suspend(struct usb_hcd *hcd); int xhci_bus_resume(struct usb_hcd *hcd); +#else +#define xhci_bus_suspend NULL +#define xhci_bus_resume NULL +#endif /* CONFIG_PM */ + u32 xhci_port_state_to_neutral(u32 state); int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port); void xhci_ring_device(struct xhci_hcd *xhci, int slot_id); From 3a0d30bcdfa73bd865f29899eb4bf29b58c4f54a Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Tue, 19 Oct 2010 10:08:11 +0300 Subject: [PATCH 132/141] USB: AM35x: Add musb support AM35x has musb interface (version 1.8) and uses CPPI41 DMA engine. It has USB phy built inside the IP itself. Signed-off-by: Ajay Kumar Gupta Acked-by: Tony Lindgren Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Cc: linux-omap@vger.kernel.org Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-omap2/board-am3517evm.c | 30 +++++++++++++++++++++++++++ arch/arm/mach-omap2/usb-musb.c | 4 ++++ arch/arm/plat-omap/include/plat/usb.h | 21 +++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 4d0f58592864..9ac9de6bb970 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -375,6 +375,31 @@ static void __init am3517_evm_init_irq(void) omap_gpio_init(); } +static struct omap_musb_board_data musb_board_data = { + .interface_type = MUSB_INTERFACE_ULPI, + .mode = MUSB_OTG, + .power = 500, +}; + +static __init void am3517_evm_musb_init(void) +{ + u32 devconf2; + + /* + * Set up USB clock/mode in the DEVCONF2 register. + */ + devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); + + /* USB2.0 PHY reference clock is 13 MHz */ + devconf2 &= ~(CONF2_REFFREQ | CONF2_OTGMODE | CONF2_PHY_GPIOMODE); + devconf2 |= CONF2_REFFREQ_13MHZ | CONF2_SESENDEN | CONF2_VBDTCTEN + | CONF2_DATPOL; + + omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); + + usb_musb_init(&musb_board_data); +} + static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { .port_mode[0] = EHCI_HCD_OMAP_MODE_PHY, #if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \ @@ -393,6 +418,8 @@ static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { #ifdef CONFIG_OMAP_MUX static struct omap_board_mux board_mux[] __initdata = { + /* USB OTG DRVVBUS offset = 0x212 */ + OMAP3_MUX(SAD2D_MCAD23, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN), { .reg_offset = OMAP_MUX_TERMINATOR }, }; #else @@ -459,6 +486,9 @@ static void __init am3517_evm_init(void) ARRAY_SIZE(am3517evm_i2c1_boardinfo)); /*Ethernet*/ am3517_evm_ethernet_init(&am3517_evm_emac_pdata); + + /* MUSB */ + am3517_evm_musb_init(); } MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM") diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c index 33a5cde1c227..72605584bfff 100644 --- a/arch/arm/mach-omap2/usb-musb.c +++ b/arch/arm/mach-omap2/usb-musb.c @@ -28,6 +28,7 @@ #include #include +#include #include #ifdef CONFIG_USB_MUSB_SOC @@ -89,6 +90,9 @@ void __init usb_musb_init(struct omap_musb_board_data *board_data) { if (cpu_is_omap243x()) { musb_resources[0].start = OMAP243X_HS_BASE; + } else if (cpu_is_omap3517() || cpu_is_omap3505()) { + musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE; + musb_resources[1].start = INT_35XX_USBOTG_IRQ; } else if (cpu_is_omap34xx()) { musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE; } else if (cpu_is_omap44xx()) { diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h index 2a9427c8cc48..9feddacfe850 100644 --- a/arch/arm/plat-omap/include/plat/usb.h +++ b/arch/arm/plat-omap/include/plat/usb.h @@ -218,6 +218,27 @@ static inline omap2_usbfs_init(struct omap_usb_config *pdata) # define USBT2TLL5PI (1 << 17) # define USB0PUENACTLOI (1 << 16) # define USBSTANDBYCTRL (1 << 15) +/* AM35x */ +/* USB 2.0 PHY Control */ +#define CONF2_PHY_GPIOMODE (1 << 23) +#define CONF2_OTGMODE (3 << 14) +#define CONF2_NO_OVERRIDE (0 << 14) +#define CONF2_FORCE_HOST (1 << 14) +#define CONF2_FORCE_DEVICE (2 << 14) +#define CONF2_FORCE_HOST_VBUS_LOW (3 << 14) +#define CONF2_SESENDEN (1 << 13) +#define CONF2_VBDTCTEN (1 << 12) +#define CONF2_REFFREQ_24MHZ (2 << 8) +#define CONF2_REFFREQ_26MHZ (7 << 8) +#define CONF2_REFFREQ_13MHZ (6 << 8) +#define CONF2_REFFREQ (0xf << 8) +#define CONF2_PHYCLKGD (1 << 7) +#define CONF2_VBUSSENSE (1 << 6) +#define CONF2_PHY_PLLON (1 << 5) +#define CONF2_RESET (1 << 4) +#define CONF2_PHYPWRDN (1 << 3) +#define CONF2_OTGPWRDN (1 << 2) +#define CONF2_DATPOL (1 << 1) #if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_USB) u32 omap1_usb0_init(unsigned nwires, unsigned is_device); From eb83092c2b24587719c917a1d6a5b682eeaa03df Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Tue, 19 Oct 2010 10:08:12 +0300 Subject: [PATCH 133/141] USB: musb: add musb support for AM35x AM35x has musb interface and uses CPPI4.1 DMA engine. Current patch supports only PIO mode. DMA support can be added later once basic CPPI4.1 DMA patch is accepted. Also added USB_MUSB_AM35X which is required to differentiate musb ips between OMAP3x and AM35x. This config would be used to for below purposes, - Select am35x.c instead of omap2430.c for compilation at drivers/usb/musb directory. Please note there are significant differneces in these two files as musb ip in quite different on AM35x. Please note that in multi omap configuration only omap2430.c file will get compiled and we would require to select only AM35x based board config to compile am35x.c - Select workaround codes applicable for AM35x musb issues. one such workaround is for bytewise read issue on AM35x. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/Kconfig | 13 +- drivers/usb/musb/Makefile | 6 +- drivers/usb/musb/am35x.c | 494 +++++++++++++++++++++++++++++++++++ drivers/usb/musb/musb_core.h | 1 + 4 files changed, 512 insertions(+), 2 deletions(-) create mode 100644 drivers/usb/musb/am35x.c diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 1dd21c2315e4..341a37a469bd 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -60,6 +60,17 @@ comment "OMAP 44xx high speed USB support" comment "Blackfin high speed USB Support" depends on USB_MUSB_HDRC && ((BF54x && !BF544) || (BF52x && !BF522 && !BF523)) +config USB_MUSB_AM35X + bool + depends on USB_MUSB_HDRC && !ARCH_OMAP2430 && !ARCH_OMAP4 + select NOP_USB_XCEIV + default MACH_OMAP3517EVM + help + Select this option if your platform is based on AM35x. As + AM35x has an updated MUSB with CPPI4.1 DMA so this config + is introduced to differentiate musb ip between OMAP3x and + AM35x platforms. + config USB_TUSB6010 boolean "TUSB 6010 support" depends on USB_MUSB_HDRC && !USB_MUSB_SOC @@ -147,7 +158,7 @@ config USB_MUSB_HDRC_HCD config MUSB_PIO_ONLY bool 'Disable DMA (always use PIO)' depends on USB_MUSB_HDRC - default USB_TUSB6010 || ARCH_DAVINCI_DA8XX + default USB_TUSB6010 || ARCH_DAVINCI_DA8XX || USB_MUSB_AM35X help All data is copied between memory and FIFO by the CPU. DMA controllers are ignored. diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index ffc0e0525823..ce164e8998d8 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -12,7 +12,11 @@ musb_hdrc-$(CONFIG_ARCH_DAVINCI_DMx) += davinci.o musb_hdrc-$(CONFIG_ARCH_DAVINCI_DA8XX) += da8xx.o musb_hdrc-$(CONFIG_USB_TUSB6010) += tusb6010.o musb_hdrc-$(CONFIG_ARCH_OMAP2430) += omap2430.o -musb_hdrc-$(CONFIG_ARCH_OMAP3430) += omap2430.o +ifeq ($(CONFIG_USB_MUSB_AM35X),y) + musb_hdrc-$(CONFIG_ARCH_OMAP3430) += am35x.o +else + musb_hdrc-$(CONFIG_ARCH_OMAP3430) += omap2430.o +endif musb_hdrc-$(CONFIG_ARCH_OMAP4) += omap2430.o musb_hdrc-$(CONFIG_BF54x) += blackfin.o musb_hdrc-$(CONFIG_BF52x) += blackfin.o diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c new file mode 100644 index 000000000000..53962a0389eb --- /dev/null +++ b/drivers/usb/musb/am35x.c @@ -0,0 +1,494 @@ +/* + * Texas Instruments AM35x "glue layer" + * + * Copyright (c) 2010, by Texas Instruments + * + * Based on the DA8xx "glue layer" code. + * Copyright (c) 2008-2009, MontaVista Software, Inc. + * + * This file is part of the Inventra Controller Driver for Linux. + * + * The Inventra Controller Driver for Linux 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. + * + * The Inventra Controller Driver for Linux 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. + * + * You should have received a copy of the GNU General Public License + * along with The Inventra Controller Driver for Linux ; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include + +#include +#include + +#include "musb_core.h" + +/* + * AM35x specific definitions + */ +/* USB 2.0 OTG module registers */ +#define USB_REVISION_REG 0x00 +#define USB_CTRL_REG 0x04 +#define USB_STAT_REG 0x08 +#define USB_EMULATION_REG 0x0c +/* 0x10 Reserved */ +#define USB_AUTOREQ_REG 0x14 +#define USB_SRP_FIX_TIME_REG 0x18 +#define USB_TEARDOWN_REG 0x1c +#define EP_INTR_SRC_REG 0x20 +#define EP_INTR_SRC_SET_REG 0x24 +#define EP_INTR_SRC_CLEAR_REG 0x28 +#define EP_INTR_MASK_REG 0x2c +#define EP_INTR_MASK_SET_REG 0x30 +#define EP_INTR_MASK_CLEAR_REG 0x34 +#define EP_INTR_SRC_MASKED_REG 0x38 +#define CORE_INTR_SRC_REG 0x40 +#define CORE_INTR_SRC_SET_REG 0x44 +#define CORE_INTR_SRC_CLEAR_REG 0x48 +#define CORE_INTR_MASK_REG 0x4c +#define CORE_INTR_MASK_SET_REG 0x50 +#define CORE_INTR_MASK_CLEAR_REG 0x54 +#define CORE_INTR_SRC_MASKED_REG 0x58 +/* 0x5c Reserved */ +#define USB_END_OF_INTR_REG 0x60 + +/* Control register bits */ +#define AM35X_SOFT_RESET_MASK 1 + +/* USB interrupt register bits */ +#define AM35X_INTR_USB_SHIFT 16 +#define AM35X_INTR_USB_MASK (0x1ff << AM35X_INTR_USB_SHIFT) +#define AM35X_INTR_DRVVBUS 0x100 +#define AM35X_INTR_RX_SHIFT 16 +#define AM35X_INTR_TX_SHIFT 0 +#define AM35X_TX_EP_MASK 0xffff /* EP0 + 15 Tx EPs */ +#define AM35X_RX_EP_MASK 0xfffe /* 15 Rx EPs */ +#define AM35X_TX_INTR_MASK (AM35X_TX_EP_MASK << AM35X_INTR_TX_SHIFT) +#define AM35X_RX_INTR_MASK (AM35X_RX_EP_MASK << AM35X_INTR_RX_SHIFT) + +#define USB_MENTOR_CORE_OFFSET 0x400 + +static inline void phy_on(void) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(100); + u32 devconf2; + + /* + * Start the on-chip PHY and its PLL. + */ + devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); + + devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN); + devconf2 |= CONF2_PHY_PLLON; + + omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); + + DBG(1, "Waiting for PHY clock good...\n"); + while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2) + & CONF2_PHYCLKGD)) { + cpu_relax(); + + if (time_after(jiffies, timeout)) { + DBG(1, "musb PHY clock good timed out\n"); + break; + } + } +} + +static inline void phy_off(void) +{ + u32 devconf2; + + /* + * Power down the on-chip PHY. + */ + devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); + + devconf2 &= ~CONF2_PHY_PLLON; + devconf2 |= CONF2_PHYPWRDN | CONF2_OTGPWRDN; + omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); +} + +/* + * musb_platform_enable - enable interrupts + */ +void musb_platform_enable(struct musb *musb) +{ + void __iomem *reg_base = musb->ctrl_base; + u32 epmask; + + /* Workaround: setup IRQs through both register sets. */ + epmask = ((musb->epmask & AM35X_TX_EP_MASK) << AM35X_INTR_TX_SHIFT) | + ((musb->epmask & AM35X_RX_EP_MASK) << AM35X_INTR_RX_SHIFT); + + musb_writel(reg_base, EP_INTR_MASK_SET_REG, epmask); + musb_writel(reg_base, CORE_INTR_MASK_SET_REG, AM35X_INTR_USB_MASK); + + /* Force the DRVVBUS IRQ so we can start polling for ID change. */ + if (is_otg_enabled(musb)) + musb_writel(reg_base, CORE_INTR_SRC_SET_REG, + AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT); +} + +/* + * musb_platform_disable - disable HDRC and flush interrupts + */ +void musb_platform_disable(struct musb *musb) +{ + void __iomem *reg_base = musb->ctrl_base; + + musb_writel(reg_base, CORE_INTR_MASK_CLEAR_REG, AM35X_INTR_USB_MASK); + musb_writel(reg_base, EP_INTR_MASK_CLEAR_REG, + AM35X_TX_INTR_MASK | AM35X_RX_INTR_MASK); + musb_writeb(musb->mregs, MUSB_DEVCTL, 0); + musb_writel(reg_base, USB_END_OF_INTR_REG, 0); +} + +#ifdef CONFIG_USB_MUSB_HDRC_HCD +#define portstate(stmt) stmt +#else +#define portstate(stmt) +#endif + +static void am35x_set_vbus(struct musb *musb, int is_on) +{ + WARN_ON(is_on && is_peripheral_active(musb)); +} + +#define POLL_SECONDS 2 + +static struct timer_list otg_workaround; + +static void otg_timer(unsigned long _musb) +{ + struct musb *musb = (void *)_musb; + void __iomem *mregs = musb->mregs; + u8 devctl; + unsigned long flags; + + /* + * We poll because AM35x's won't expose several OTG-critical + * status change events (from the transceiver) otherwise. + */ + devctl = musb_readb(mregs, MUSB_DEVCTL); + DBG(7, "Poll devctl %02x (%s)\n", devctl, otg_state_string(musb)); + + spin_lock_irqsave(&musb->lock, flags); + switch (musb->xceiv->state) { + case OTG_STATE_A_WAIT_BCON: + devctl &= ~MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + + devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + if (devctl & MUSB_DEVCTL_BDEVICE) { + musb->xceiv->state = OTG_STATE_B_IDLE; + MUSB_DEV_MODE(musb); + } else { + musb->xceiv->state = OTG_STATE_A_IDLE; + MUSB_HST_MODE(musb); + } + break; + case OTG_STATE_A_WAIT_VFALL: + musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; + musb_writel(musb->ctrl_base, CORE_INTR_SRC_SET_REG, + MUSB_INTR_VBUSERROR << AM35X_INTR_USB_SHIFT); + break; + case OTG_STATE_B_IDLE: + if (!is_peripheral_enabled(musb)) + break; + + devctl = musb_readb(mregs, MUSB_DEVCTL); + if (devctl & MUSB_DEVCTL_BDEVICE) + mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); + else + musb->xceiv->state = OTG_STATE_A_IDLE; + break; + default: + break; + } + spin_unlock_irqrestore(&musb->lock, flags); +} + +void musb_platform_try_idle(struct musb *musb, unsigned long timeout) +{ + static unsigned long last_timer; + + if (!is_otg_enabled(musb)) + return; + + if (timeout == 0) + timeout = jiffies + msecs_to_jiffies(3); + + /* Never idle if active, or when VBUS timeout is not set as host */ + if (musb->is_active || (musb->a_wait_bcon == 0 && + musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { + DBG(4, "%s active, deleting timer\n", otg_state_string(musb)); + del_timer(&otg_workaround); + last_timer = jiffies; + return; + } + + if (time_after(last_timer, timeout) && timer_pending(&otg_workaround)) { + DBG(4, "Longer idle timer already pending, ignoring...\n"); + return; + } + last_timer = timeout; + + DBG(4, "%s inactive, starting idle timer for %u ms\n", + otg_state_string(musb), jiffies_to_msecs(timeout - jiffies)); + mod_timer(&otg_workaround, timeout); +} + +static irqreturn_t am35x_interrupt(int irq, void *hci) +{ + struct musb *musb = hci; + void __iomem *reg_base = musb->ctrl_base; + unsigned long flags; + irqreturn_t ret = IRQ_NONE; + u32 epintr, usbintr, lvl_intr; + + spin_lock_irqsave(&musb->lock, flags); + + /* Get endpoint interrupts */ + epintr = musb_readl(reg_base, EP_INTR_SRC_MASKED_REG); + + if (epintr) { + musb_writel(reg_base, EP_INTR_SRC_CLEAR_REG, epintr); + + musb->int_rx = + (epintr & AM35X_RX_INTR_MASK) >> AM35X_INTR_RX_SHIFT; + musb->int_tx = + (epintr & AM35X_TX_INTR_MASK) >> AM35X_INTR_TX_SHIFT; + } + + /* Get usb core interrupts */ + usbintr = musb_readl(reg_base, CORE_INTR_SRC_MASKED_REG); + if (!usbintr && !epintr) + goto eoi; + + if (usbintr) { + musb_writel(reg_base, CORE_INTR_SRC_CLEAR_REG, usbintr); + + musb->int_usb = + (usbintr & AM35X_INTR_USB_MASK) >> AM35X_INTR_USB_SHIFT; + } + /* + * DRVVBUS IRQs are the only proxy we have (a very poor one!) for + * AM35x's missing ID change IRQ. We need an ID change IRQ to + * switch appropriately between halves of the OTG state machine. + * Managing DEVCTL.SESSION per Mentor docs requires that we know its + * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set. + * Also, DRVVBUS pulses for SRP (but not at 5V) ... + */ + if (usbintr & (AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT)) { + int drvvbus = musb_readl(reg_base, USB_STAT_REG); + void __iomem *mregs = musb->mregs; + u8 devctl = musb_readb(mregs, MUSB_DEVCTL); + int err; + + err = is_host_enabled(musb) && (musb->int_usb & + MUSB_INTR_VBUSERROR); + if (err) { + /* + * The Mentor core doesn't debounce VBUS as needed + * to cope with device connect current spikes. This + * means it's not uncommon for bus-powered devices + * to get VBUS errors during enumeration. + * + * This is a workaround, but newer RTL from Mentor + * seems to allow a better one: "re"-starting sessions + * without waiting for VBUS to stop registering in + * devctl. + */ + musb->int_usb &= ~MUSB_INTR_VBUSERROR; + musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; + mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); + WARNING("VBUS error workaround (delay coming)\n"); + } else if (is_host_enabled(musb) && drvvbus) { + MUSB_HST_MODE(musb); + musb->xceiv->default_a = 1; + musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; + portstate(musb->port1_status |= USB_PORT_STAT_POWER); + del_timer(&otg_workaround); + } else { + musb->is_active = 0; + MUSB_DEV_MODE(musb); + musb->xceiv->default_a = 0; + musb->xceiv->state = OTG_STATE_B_IDLE; + portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); + } + + /* NOTE: this must complete power-on within 100 ms. */ + DBG(2, "VBUS %s (%s)%s, devctl %02x\n", + drvvbus ? "on" : "off", + otg_state_string(musb), + err ? " ERROR" : "", + devctl); + ret = IRQ_HANDLED; + } + + if (musb->int_tx || musb->int_rx || musb->int_usb) + ret |= musb_interrupt(musb); + +eoi: + /* EOI needs to be written for the IRQ to be re-asserted. */ + if (ret == IRQ_HANDLED || epintr || usbintr) { + /* clear level interrupt */ + lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); + lvl_intr |= AM35XX_USBOTGSS_INT_CLR; + omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR); + /* write EOI */ + musb_writel(reg_base, USB_END_OF_INTR_REG, 0); + } + + /* Poll for ID change */ + if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE) + mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); + + spin_unlock_irqrestore(&musb->lock, flags); + + return ret; +} + +int musb_platform_set_mode(struct musb *musb, u8 musb_mode) +{ + u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); + + devconf2 &= ~CONF2_OTGMODE; + switch (musb_mode) { +#ifdef CONFIG_USB_MUSB_HDRC_HCD + case MUSB_HOST: /* Force VBUS valid, ID = 0 */ + devconf2 |= CONF2_FORCE_HOST; + break; +#endif +#ifdef CONFIG_USB_GADGET_MUSB_HDRC + case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */ + devconf2 |= CONF2_FORCE_DEVICE; + break; +#endif +#ifdef CONFIG_USB_MUSB_OTG + case MUSB_OTG: /* Don't override the VBUS/ID comparators */ + devconf2 |= CONF2_NO_OVERRIDE; + break; +#endif + default: + DBG(2, "Trying to set unsupported mode %u\n", musb_mode); + } + + omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); + return 0; +} + +int __init musb_platform_init(struct musb *musb, void *board_data) +{ + void __iomem *reg_base = musb->ctrl_base; + u32 rev, lvl_intr, sw_reset; + int status; + + musb->mregs += USB_MENTOR_CORE_OFFSET; + + clk_enable(musb->clock); + DBG(2, "musb->clock=%lud\n", clk_get_rate(musb->clock)); + + musb->phy_clock = clk_get(musb->controller, "fck"); + if (IS_ERR(musb->phy_clock)) { + status = PTR_ERR(musb->phy_clock); + goto exit0; + } + clk_enable(musb->phy_clock); + DBG(2, "musb->phy_clock=%lud\n", clk_get_rate(musb->phy_clock)); + + /* Returns zero if e.g. not clocked */ + rev = musb_readl(reg_base, USB_REVISION_REG); + if (!rev) { + status = -ENODEV; + goto exit1; + } + + usb_nop_xceiv_register(); + musb->xceiv = otg_get_transceiver(); + if (!musb->xceiv) { + status = -ENODEV; + goto exit1; + } + + if (is_host_enabled(musb)) + setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); + + musb->board_set_vbus = am35x_set_vbus; + + /* Global reset */ + sw_reset = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); + + sw_reset |= AM35XX_USBOTGSS_SW_RST; + omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET); + + sw_reset &= ~AM35XX_USBOTGSS_SW_RST; + omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET); + + /* Reset the controller */ + musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK); + + /* Start the on-chip PHY and its PLL. */ + phy_on(); + + msleep(5); + + musb->isr = am35x_interrupt; + + /* clear level interrupt */ + lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); + lvl_intr |= AM35XX_USBOTGSS_INT_CLR; + omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR); + return 0; +exit1: + clk_disable(musb->phy_clock); + clk_put(musb->phy_clock); +exit0: + clk_disable(musb->clock); + return status; +} + +int musb_platform_exit(struct musb *musb) +{ + if (is_host_enabled(musb)) + del_timer_sync(&otg_workaround); + + phy_off(); + + otg_put_transceiver(musb->xceiv); + usb_nop_xceiv_unregister(); + + clk_disable(musb->clock); + + clk_disable(musb->phy_clock); + clk_put(musb->phy_clock); + + return 0; +} + +#ifdef CONFIG_PM +void musb_platform_save_context(struct musb *musb, + struct musb_context_registers *musb_context) +{ + phy_off(); +} + +void musb_platform_restore_context(struct musb *musb, + struct musb_context_registers *musb_context) +{ + phy_on(); +} +#endif diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 2a8236216dc7..69797e5b46a7 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -330,6 +330,7 @@ struct musb { /* device lock */ spinlock_t lock; struct clk *clock; + struct clk *phy_clock; irqreturn_t (*isr)(int, void *); struct work_struct irq_work; u16 hwvers; From 843bb1d0ff29b96eeb184988223ba55e3e8c2f57 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Tue, 19 Oct 2010 10:08:13 +0300 Subject: [PATCH 134/141] USB: musb: AM35x: Workaround for fifo read issue AM35x supports only 32bit read operations so we need to have workaround for 8bit and 16bit read operations. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/am35x.c | 30 ++++++++++++++++++++++++++++++ drivers/usb/musb/musb_core.c | 2 ++ 2 files changed, 32 insertions(+) diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 53962a0389eb..b0aabf3a606f 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -492,3 +492,33 @@ void musb_platform_restore_context(struct musb *musb, phy_on(); } #endif + +/* AM35x supports only 32bit read operation */ +void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) +{ + void __iomem *fifo = hw_ep->fifo; + u32 val; + int i; + + /* Read for 32bit-aligned destination address */ + if (likely((0x03 & (unsigned long) dst) == 0) && len >= 4) { + readsl(fifo, dst, len >> 2); + dst += len & ~0x03; + len &= 0x03; + } + /* + * Now read the remaining 1 to 3 byte or complete length if + * unaligned address. + */ + if (len > 4) { + for (i = 0; i < (len >> 2); i++) { + *(u32 *) dst = musb_readl(fifo, 0); + dst += 4; + } + len &= 0x03; + } + if (len > 0) { + val = musb_readl(fifo, 0); + memcpy(dst, &val, len); + } +} diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 7e2c353755d2..c9f9024c5515 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -272,6 +272,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) } } +#if !defined(CONFIG_USB_MUSB_AM35X) /* * Unload an endpoint's FIFO */ @@ -309,6 +310,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) readsb(fifo, dst, len); } } +#endif #endif /* normal PIO */ From 0f266abd70cd83571eca019f764b5f1992da7361 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 19 Oct 2010 09:05:43 -0700 Subject: [PATCH 135/141] USB: ftdi_sio: add device ids for ScienceScope This adds the requested device ids to the ftdi_sio driver. Reported-by: Ewan Bingham Cc: Kuba Ober Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 3 +++ drivers/usb/serial/ftdi_sio_ids.h | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d3e58b56f56d..160b3c60c0c4 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -791,6 +791,9 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MAXI_WING_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MEDIA_WING_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index fc44369ec1a6..cf1aea1b9ee7 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1095,3 +1095,8 @@ * Accesio USB Data Acquisition products (http://www.accesio.com/) */ #define ACCESIO_COM4SM_PID 0xD578 + +/* www.sciencescope.co.uk educational dataloggers */ +#define FTDI_SCIENCESCOPE_LOGBOOKML_PID 0xFF18 +#define FTDI_SCIENCESCOPE_LS_LOGBOOK_PID 0xFF1C +#define FTDI_SCIENCESCOPE_HS_LOGBOOK_PID 0xFF1D From 69cb1ec4ce4da4bc4c07bb09c4c98b3e25d99fb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20B=C3=A9nard?= Date: Fri, 15 Oct 2010 14:30:58 +0200 Subject: [PATCH 136/141] mxc_udc: add workaround for ENGcm09152 for i.MX35 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this patch gives the possibility to workaround bug ENGcm09152 on i.MX35 when the hardware workaround is also implemented on the board. It covers the workaround described on page 25 of the following Errata : http://cache.freescale.com/files/dsp/doc/errata/IMX35CE.pdf Signed-off-by: Eric Bénard Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-mx3/mach-cpuimx35.c | 1 + drivers/usb/gadget/fsl_mxc_udc.c | 15 +++++++++++++++ include/linux/fsl_devices.h | 3 +++ 3 files changed, 19 insertions(+) diff --git a/arch/arm/mach-mx3/mach-cpuimx35.c b/arch/arm/mach-mx3/mach-cpuimx35.c index 2a4f8b781ba4..4d161b3fca65 100644 --- a/arch/arm/mach-mx3/mach-cpuimx35.c +++ b/arch/arm/mach-mx3/mach-cpuimx35.c @@ -155,6 +155,7 @@ static struct mxc_usbh_platform_data usbh1_pdata = { static struct fsl_usb2_platform_data otg_device_pdata = { .operating_mode = FSL_USB2_DR_DEVICE, .phy_mode = FSL_USB2_PHY_UTMI, + .workaround = FLS_USB2_WORKAROUND_ENGCM09152, }; static int otg_mode_host; diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c index eafa6d2c5ed7..5bdbfe619853 100644 --- a/drivers/usb/gadget/fsl_mxc_udc.c +++ b/drivers/usb/gadget/fsl_mxc_udc.c @@ -22,6 +22,10 @@ static struct clk *mxc_ahb_clk; static struct clk *mxc_usb_clk; +/* workaround ENGcm09152 for i.MX35 */ +#define USBPHYCTRL_OTGBASE_OFFSET 0x608 +#define USBPHYCTRL_EVDO (1 << 23) + int fsl_udc_clk_init(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata; @@ -84,6 +88,17 @@ eenahb: void fsl_udc_clk_finalize(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; +#if defined(CONFIG_ARCH_MX35) + unsigned int v; + + /* workaround ENGcm09152 for i.MX35 */ + if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) { + v = readl(MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR + + USBPHYCTRL_OTGBASE_OFFSET)); + writel(v | USBPHYCTRL_EVDO, MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR + + USBPHYCTRL_OTGBASE_OFFSET)); + } +#endif /* ULPI transceivers don't need usbpll */ if (pdata->phy_mode == FSL_USB2_PHY_ULPI) { diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index d5f9a7431bd0..4eb56ed75fbc 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -66,6 +66,7 @@ struct fsl_usb2_platform_data { enum fsl_usb2_operating_modes operating_mode; enum fsl_usb2_phy_modes phy_mode; unsigned int port_enables; + unsigned int workaround; int (*init)(struct platform_device *); void (*exit)(struct platform_device *); @@ -84,6 +85,8 @@ struct fsl_usb2_platform_data { #define FSL_USB2_PORT0_ENABLED 0x00000001 #define FSL_USB2_PORT1_ENABLED 0x00000002 +#define FLS_USB2_WORKAROUND_ENGCM09152 (1 << 0) + struct spi_device; struct fsl_spi_platform_data { From e576a7a96aae99b74dd758fff54c345f8f4ff097 Mon Sep 17 00:00:00 2001 From: Yusuke Goda Date: Wed, 20 Oct 2010 09:28:08 +0900 Subject: [PATCH 137/141] usb: r8a66597-udc: Add processing when USB was removed. When USB was removed, this patch prepares for the next insertion. Signed-off-by: Yusuke Goda Acked-by: Yoshihiro Shimoda Cc: Paul Mundt Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/r8a66597-udc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index 157640f7d2a8..20d43da319ae 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -42,6 +42,7 @@ static const char *r8a66597_ep_name[] = { "ep8", "ep9", }; +static void init_controller(struct r8a66597 *r8a66597); static void disable_controller(struct r8a66597 *r8a66597); static void irq_ep0_write(struct r8a66597_ep *ep, struct r8a66597_request *req); static void irq_packet_write(struct r8a66597_ep *ep, @@ -104,6 +105,8 @@ __acquires(r8a66597->lock) spin_lock(&r8a66597->lock); disable_controller(r8a66597); + init_controller(r8a66597); + r8a66597_bset(r8a66597, VBSE, INTENB0); INIT_LIST_HEAD(&r8a66597->ep[0].queue); } From bd68826897d328f332d8f98979d9ee95b96fb6f8 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Tue, 19 Oct 2010 13:03:26 +0300 Subject: [PATCH 138/141] usb: gadget: fix Kconfig warning warning: (USB_MUSB_HDRC_HCD && USB_SUPPORT && USB_MUSB_HDRC && (USB_MUSB_HOST || USB_MUSB_OTG) && USB_GADGET_MUSB_HDRC || USB_MUSB_OTG && && USB && USB_GADGET && PM && EXPERIMENTAL) selects USB_OTG which has unmet direct dependencies (USB_GADGET_OMAP && ARCH_OMAP_OTG && USB_OHCI_HCD) This doesn't seem to happen on 2.6.36-rc8, but still doesn't make sense to keep this duplicated config that is already defined in usb/core. Signed-off-by: Felipe Contreras Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/Kconfig | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 0fe5bc876fa5..b739ca814651 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -210,17 +210,6 @@ config USB_OMAP default USB_GADGET select USB_GADGET_SELECTED -config USB_OTG - boolean "OTG Support" - depends on USB_GADGET_OMAP && ARCH_OMAP_OTG && USB_OHCI_HCD - help - The most notable feature of USB OTG is support for a - "Dual-Role" device, which can act as either a device - or a host. The initial role choice can be changed - later, when two dual-role devices talk to each other. - - Select this only if your OMAP board has a Mini-AB connector. - config USB_GADGET_PXA25X boolean "PXA 25x or IXP 4xx" depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX From e581c8c8a957776db452afe316706242abcc1cdc Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 16 Oct 2010 22:48:08 +0800 Subject: [PATCH 139/141] USB: imx21-hcd - fix off by one resource size calculation Signed-off-by: Axel Lin Tested-by: Jon Povey Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/imx21-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index dd132eb7fee7..1dfb2c8f7707 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -1906,7 +1906,7 @@ failed_clock_set: failed_clock_get: iounmap(imx21->regs); failed_ioremap: - release_mem_region(res->start, res->end - res->start); + release_mem_region(res->start, resource_size(res)); failed_request_mem: remove_debug_files(imx21); usb_put_hcd(hcd); From f34c25ed78df6d1297db2187bf5e58aaf6674183 Mon Sep 17 00:00:00 2001 From: Rahul Ruikar Date: Wed, 20 Oct 2010 16:01:51 -0700 Subject: [PATCH 140/141] USB: gadget: amd5536udc.c: fix error path In function udc_probe() call put_device() when device_register() fails. Signed-off-by: Rahul Ruikar Acked-by: Thomas Dahlmann Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/amd5536udc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 2b361500af1e..9034e0344723 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3383,8 +3383,10 @@ static int udc_probe(struct udc *dev) udc = dev; retval = device_register(&dev->gadget.dev); - if (retval) + if (retval) { + put_device(&dev->gadget.dev); goto finished; + } /* timer init */ init_timer(&udc_timer); From 92ca0dc5ee022e4c0e488177e1d8865a0778c6c2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Oct 2010 10:49:10 +0200 Subject: [PATCH 141/141] USB: mct_u232: fix broken close Fix regression introduced by commit f26788da3b342099d2b02d99ba1cb7f154d6ef7b (USB: serial: refactor generic close) which broke driver close(). This driver uses non-standard semantics for the read urb which makes the generic close function fail to kill it (the read urb is actually an interrupt urb and therefore bulk_in size is zero). Reported-by: Eric Shattow "Eprecocious" Tested-by: Eric Shattow "Eprecocious" Cc: stable Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mct_u232.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 7aa01b95b1d4..2849f8c32015 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -549,9 +549,12 @@ static void mct_u232_close(struct usb_serial_port *port) { dbg("%s port %d", __func__, port->number); - usb_serial_generic_close(port); - if (port->serial->dev) + if (port->serial->dev) { + /* shutdown our urbs */ + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); usb_kill_urb(port->interrupt_in_urb); + } } /* mct_u232_close */