diff options
Diffstat (limited to 'drivers/usb')
275 files changed, 10178 insertions, 9951 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 640ae6c6d2d..92e1dc94ecc 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -122,9 +122,9 @@ config USB  	  To compile this driver as a module, choose M here: the  	  module will be called usbcore. -source "drivers/usb/core/Kconfig" +if USB -source "drivers/usb/dwc3/Kconfig" +source "drivers/usb/core/Kconfig"  source "drivers/usb/mon/Kconfig" @@ -134,8 +134,6 @@ source "drivers/usb/host/Kconfig"  source "drivers/usb/musb/Kconfig" -source "drivers/usb/chipidea/Kconfig" -  source "drivers/usb/renesas_usbhs/Kconfig"  source "drivers/usb/class/Kconfig" @@ -144,12 +142,19 @@ source "drivers/usb/storage/Kconfig"  source "drivers/usb/image/Kconfig" +endif + +source "drivers/usb/dwc3/Kconfig" + +source "drivers/usb/chipidea/Kconfig" +  comment "USB port drivers" -	depends on USB + +if USB  config USB_USS720  	tristate "USS720 parport driver" -	depends on USB && PARPORT +	depends on PARPORT  	select PARPORT_NOT_PC  	---help---  	  This driver is for USB parallel port adapters that use the Lucent @@ -180,12 +185,12 @@ source "drivers/usb/serial/Kconfig"  source "drivers/usb/misc/Kconfig" -source "drivers/usb/phy/Kconfig" -  source "drivers/usb/atm/Kconfig" -source "drivers/usb/gadget/Kconfig" +endif # USB + +source "drivers/usb/phy/Kconfig" -source "drivers/usb/otg/Kconfig" +source "drivers/usb/gadget/Kconfig"  endif # USB_SUPPORT diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 8f5ebced5df..c41feba8d5c 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -6,8 +6,6 @@  obj-$(CONFIG_USB)		+= core/ -obj-$(CONFIG_USB_OTG_UTILS)	+= otg/ -  obj-$(CONFIG_USB_DWC3)		+= dwc3/  obj-$(CONFIG_USB_MON)		+= mon/ @@ -46,7 +44,7 @@ obj-$(CONFIG_USB_MICROTEK)	+= image/  obj-$(CONFIG_USB_SERIAL)	+= serial/  obj-$(CONFIG_USB)		+= misc/ -obj-$(CONFIG_USB_OTG_UTILS)	+= phy/ +obj-$(CONFIG_USB_PHY)		+= phy/  obj-$(CONFIG_EARLY_PRINTK_DBGP)	+= early/  obj-$(CONFIG_USB_ATM)		+= atm/ diff --git a/drivers/usb/atm/Kconfig b/drivers/usb/atm/Kconfig index be0b8daac9c..0f922942a07 100644 --- a/drivers/usb/atm/Kconfig +++ b/drivers/usb/atm/Kconfig @@ -4,7 +4,7 @@  menuconfig USB_ATM  	tristate "USB DSL modem support" -	depends on USB && ATM +	depends on ATM  	select CRC32  	default n  	help diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 35f10bfe15d..d3527dd8b90 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -672,9 +672,6 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)  	struct usbatm_control *ctrl = UDSL_SKB(skb);  	int err; -	vdbg(&instance->usb_intf->dev, "%s called (skb 0x%p, len %u)", __func__, -	     skb, skb->len); -  	/* racy disconnection check - fine */  	if (!instance || instance->disconnected) {  #ifdef DEBUG @@ -684,6 +681,9 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)  		goto fail;  	} +	vdbg(&instance->usb_intf->dev, "%s called (skb 0x%p, len %u)", __func__, +	     skb, skb->len); +  	if (vcc->qos.aal != ATM_AAL5) {  		atm_rldbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);  		err = -EINVAL; diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile index d92ca325b10..4ab83e98219 100644 --- a/drivers/usb/chipidea/Makefile +++ b/drivers/usb/chipidea/Makefile @@ -17,5 +17,5 @@ ifneq ($(CONFIG_PCI),)  endif  ifneq ($(CONFIG_OF_DEVICE),) -	obj-$(CONFIG_USB_CHIPIDEA)	+= ci13xxx_imx.o usbmisc_imx6q.o +	obj-$(CONFIG_USB_CHIPIDEA)	+= ci13xxx_imx.o usbmisc_imx.o  endif diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index e25d1263da1..b0a6bce064c 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -21,6 +21,7 @@  /******************************************************************************   * DEFINE   *****************************************************************************/ +#define TD_PAGE_COUNT      5  #define CI13XXX_PAGE_SIZE  4096ul /* page size for TD's */  #define ENDPT_MAX          32 @@ -129,6 +130,7 @@ struct hw_bank {   * @vbus_active: is VBUS active   * @transceiver: pointer to USB PHY, if any   * @hcd: pointer to usb_hcd for ehci host driver + * @debugfs: root dentry for this controller in debugfs   */  struct ci13xxx {  	struct device			*dev; @@ -139,7 +141,6 @@ struct ci13xxx {  	enum ci_role			role;  	bool				is_otg;  	struct work_struct		work; -	struct work_struct		vbus_work;  	struct workqueue_struct		*wq;  	struct dma_pool			*qh_pool; @@ -165,6 +166,7 @@ struct ci13xxx {  	bool				global_phy;  	struct usb_phy			*transceiver;  	struct usb_hcd			*hcd; +	struct dentry			*debugfs;  };  static inline struct ci_role_driver *ci_role(struct ci13xxx *ci) @@ -234,19 +236,6 @@ enum ci13xxx_regs {  };  /** - * ffs_nr: find first (least significant) bit set - * @x: the word to search - * - * This function returns bit number (instead of position) - */ -static inline int ffs_nr(u32 x) -{ -	int n = ffs(x); - -	return n ? n-1 : 32; -} - -/**   * hw_read: reads from a hw register   * @reg:  register index   * @mask: bitfield mask @@ -304,7 +293,7 @@ static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg,  	u32 val = hw_read(ci, reg, ~0);  	hw_write(ci, reg, mask, data); -	return (val & mask) >> ffs_nr(mask); +	return (val & mask) >> __ffs(mask);  }  int hw_device_reset(struct ci13xxx *ci, u32 mode); diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c index 8c291220be7..8faec9dbbb8 100644 --- a/drivers/usb/chipidea/ci13xxx_imx.c +++ b/drivers/usb/chipidea/ci13xxx_imx.c @@ -79,6 +79,9 @@ int usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev)  	if (of_find_property(np, "disable-over-current", NULL))  		usbdev->disable_oc = 1; +	if (of_find_property(np, "external-vbus-divider", NULL)) +		usbdev->evdo = 1; +  	return 0;  }  EXPORT_SYMBOL_GPL(usbmisc_get_init_data); @@ -202,6 +205,15 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)  		goto err;  	} +	if (usbmisc_ops && usbmisc_ops->post) { +		ret = usbmisc_ops->post(&pdev->dev); +		if (ret) { +			dev_err(&pdev->dev, +				"usbmisc post failed, ret=%d\n", ret); +			goto put_np; +		} +	} +  	data->ci_pdev = plat_ci;  	platform_set_drvdata(pdev, data); diff --git a/drivers/usb/chipidea/ci13xxx_imx.h b/drivers/usb/chipidea/ci13xxx_imx.h index 9cd2e910b1c..550bfa45762 100644 --- a/drivers/usb/chipidea/ci13xxx_imx.h +++ b/drivers/usb/chipidea/ci13xxx_imx.h @@ -13,6 +13,8 @@  struct usbmisc_ops {  	/* It's called once when probe a usb device */  	int (*init)(struct device *dev); +	/* It's called once after adding a usb device */ +	int (*post)(struct device *dev);  };  struct usbmisc_usb_device { @@ -20,6 +22,7 @@ struct usbmisc_usb_device {  	int index;  	unsigned int disable_oc:1; /* over current detect disabled */ +	unsigned int evdo:1; /* set external vbus divider option */  };  int usbmisc_set_ops(const struct usbmisc_ops *ops); diff --git a/drivers/usb/chipidea/ci13xxx_pci.c b/drivers/usb/chipidea/ci13xxx_pci.c index 9b227e39299..4e1fc61b9d9 100644 --- a/drivers/usb/chipidea/ci13xxx_pci.c +++ b/drivers/usb/chipidea/ci13xxx_pci.c @@ -23,17 +23,17 @@  /******************************************************************************   * PCI block   *****************************************************************************/ -struct ci13xxx_platform_data pci_platdata = { +static struct ci13xxx_platform_data pci_platdata = {  	.name		= UDC_DRIVER_NAME,  	.capoffset	= DEF_CAPOFFSET,  }; -struct ci13xxx_platform_data langwell_pci_platdata = { +static struct ci13xxx_platform_data langwell_pci_platdata = {  	.name		= UDC_DRIVER_NAME,  	.capoffset	= 0,  }; -struct ci13xxx_platform_data penwell_pci_platdata = { +static struct ci13xxx_platform_data penwell_pci_platdata = {  	.name		= UDC_DRIVER_NAME,  	.capoffset	= 0,  	.power_budget	= 200, diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 57cae1f897b..450107e5f65 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -51,15 +51,12 @@   */  #include <linux/delay.h>  #include <linux/device.h> -#include <linux/dmapool.h>  #include <linux/dma-mapping.h> -#include <linux/init.h>  #include <linux/platform_device.h>  #include <linux/module.h>  #include <linux/idr.h>  #include <linux/interrupt.h>  #include <linux/io.h> -#include <linux/irq.h>  #include <linux/kernel.h>  #include <linux/slab.h>  #include <linux/pm_runtime.h> @@ -158,7 +155,7 @@ int hw_port_test_set(struct ci13xxx *ci, u8 mode)  	if (mode > TEST_MODE_MAX)  		return -EINVAL; -	hw_write(ci, OP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC)); +	hw_write(ci, OP_PORTSC, PORTSC_PTC, mode << __ffs(PORTSC_PTC));  	return 0;  } @@ -169,7 +166,7 @@ int hw_port_test_set(struct ci13xxx *ci, u8 mode)   */  u8 hw_port_test_get(struct ci13xxx *ci)  { -	return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC); +	return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> __ffs(PORTSC_PTC);  }  static int hw_device_init(struct ci13xxx *ci, void __iomem *base) @@ -181,11 +178,11 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base)  	ci->hw_bank.cap = ci->hw_bank.abs;  	ci->hw_bank.cap += ci->platdata->capoffset; -	ci->hw_bank.op = ci->hw_bank.cap + ioread8(ci->hw_bank.cap); +	ci->hw_bank.op = ci->hw_bank.cap + (ioread32(ci->hw_bank.cap) & 0xff);  	hw_alloc_regmap(ci, false);  	reg = hw_read(ci, CAP_HCCPARAMS, HCCPARAMS_LEN) >> -		ffs_nr(HCCPARAMS_LEN); +		__ffs(HCCPARAMS_LEN);  	ci->hw_bank.lpm  = reg;  	hw_alloc_regmap(ci, !!reg);  	ci->hw_bank.size = ci->hw_bank.op - ci->hw_bank.abs; @@ -193,7 +190,7 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base)  	ci->hw_bank.size /= sizeof(u32);  	reg = hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DEN) >> -		ffs_nr(DCCPARAMS_DEN); +		__ffs(DCCPARAMS_DEN);  	ci->hw_ep_max = reg * 2;   /* cache hw ENDPT_MAX */  	if (ci->hw_ep_max > ENDPT_MAX) @@ -283,38 +280,6 @@ static void ci_role_work(struct work_struct *work)  	}  } -static ssize_t show_role(struct device *dev, struct device_attribute *attr, -			 char *buf) -{ -	struct ci13xxx *ci = dev_get_drvdata(dev); - -	return sprintf(buf, "%s\n", ci_role(ci)->name); -} - -static ssize_t store_role(struct device *dev, struct device_attribute *attr, -			  const char *buf, size_t count) -{ -	struct ci13xxx *ci = dev_get_drvdata(dev); -	enum ci_role role; -	int ret; - -	for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++) -		if (ci->roles[role] && !strcmp(buf, ci->roles[role]->name)) -			break; - -	if (role == CI_ROLE_END || role == ci->role) -		return -EINVAL; - -	ci_role_stop(ci); -	ret = ci_role_start(ci, role); -	if (ret) -		return ret; - -	return count; -} - -static DEVICE_ATTR(role, S_IRUSR | S_IWUSR, show_role, store_role); -  static irqreturn_t ci_irq(int irq, void *data)  {  	struct ci13xxx *ci = data; @@ -410,11 +375,9 @@ static int ci_hdrc_probe(struct platform_device *pdev)  		return -ENODEV;  	} -	base = devm_request_and_ioremap(dev, res); -	if (!base) { -		dev_err(dev, "can't request and ioremap resource\n"); -		return -ENOMEM; -	} +	base = devm_ioremap_resource(dev, res); +	if (IS_ERR(base)) +		return PTR_ERR(base);  	ci = devm_kzalloc(dev, sizeof(*ci), GFP_KERNEL);  	if (!ci) { @@ -489,17 +452,14 @@ static int ci_hdrc_probe(struct platform_device *pdev)  	if (ret)  		goto stop; -	ret = device_create_file(dev, &dev_attr_role); -	if (ret) -		goto rm_attr; -  	if (ci->is_otg)  		hw_write(ci, OP_OTGSC, OTGSC_IDIE, OTGSC_IDIE); -	return ret; +	ret = dbg_create_files(ci); +	if (!ret) +		return 0; -rm_attr: -	device_remove_file(dev, &dev_attr_role); +	free_irq(ci->irq, ci);  stop:  	ci_role_stop(ci);  rm_wq: @@ -513,9 +473,9 @@ static int ci_hdrc_remove(struct platform_device *pdev)  {  	struct ci13xxx *ci = platform_get_drvdata(pdev); +	dbg_remove_files(ci);  	flush_workqueue(ci->wq);  	destroy_workqueue(ci->wq); -	device_remove_file(ci->dev, &dev_attr_role);  	free_irq(ci->irq, ci);  	ci_role_stop(ci); diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index a62c4a47d52..36a7063a6cb 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -1,801 +1,301 @@ -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/dmapool.h> -#include <linux/dma-mapping.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/irq.h>  #include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/pm_runtime.h> +#include <linux/device.h> +#include <linux/types.h> +#include <linux/spinlock.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/uaccess.h>  #include <linux/usb/ch9.h>  #include <linux/usb/gadget.h> -#include <linux/usb/otg.h> -#include <linux/usb/chipidea.h>  #include "ci.h"  #include "udc.h"  #include "bits.h"  #include "debug.h" -/* Interrupt statistics */ -#define ISR_MASK   0x1F -static struct isr_statistics { -	u32 test; -	u32 ui; -	u32 uei; -	u32 pci; -	u32 uri; -	u32 sli; -	u32 none; -	struct { -		u32 cnt; -		u32 buf[ISR_MASK+1]; -		u32 idx; -	} hndl; -} isr_statistics; - -void dbg_interrupt(u32 intmask) -{ -	if (!intmask) { -		isr_statistics.none++; -		return; -	} - -	isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intmask; -	isr_statistics.hndl.idx &= ISR_MASK; -	isr_statistics.hndl.cnt++; - -	if (USBi_URI & intmask) -		isr_statistics.uri++; -	if (USBi_PCI & intmask) -		isr_statistics.pci++; -	if (USBi_UEI & intmask) -		isr_statistics.uei++; -	if (USBi_UI  & intmask) -		isr_statistics.ui++; -	if (USBi_SLI & intmask) -		isr_statistics.sli++; -} - -/** - * hw_register_read: reads all device registers (execute without interruption) - * @buf:  destination buffer - * @size: buffer size - * - * This function returns number of registers read - */ -static size_t hw_register_read(struct ci13xxx *ci, u32 *buf, size_t size) -{ -	unsigned i; - -	if (size > ci->hw_bank.size) -		size = ci->hw_bank.size; - -	for (i = 0; i < size; i++) -		buf[i] = hw_read(ci, i * sizeof(u32), ~0); - -	return size; -} - -/** - * hw_register_write: writes to register - * @addr: register address - * @data: register value - * - * This function returns an error code - */ -static int hw_register_write(struct ci13xxx *ci, u16 addr, u32 data) -{ -	/* align */ -	addr /= sizeof(u32); - -	if (addr >= ci->hw_bank.size) -		return -EINVAL; - -	/* align */ -	addr *= sizeof(u32); - -	hw_write(ci, addr, ~0, data); -	return 0; -} -  /** - * hw_intr_clear: disables interrupt & clears interrupt status (execute without - *                interruption) - * @n: interrupt bit - * - * This function returns an error code + * ci_device_show: prints information about device capabilities and status   */ -static int hw_intr_clear(struct ci13xxx *ci, int n) +static int ci_device_show(struct seq_file *s, void *data)  { -	if (n >= REG_BITS) -		return -EINVAL; - -	hw_write(ci, OP_USBINTR, BIT(n), 0); -	hw_write(ci, OP_USBSTS,  BIT(n), BIT(n)); -	return 0; -} - -/** - * hw_intr_force: enables interrupt & forces interrupt status (execute without - *                interruption) - * @n: interrupt bit - * - * This function returns an error code - */ -static int hw_intr_force(struct ci13xxx *ci, int n) -{ -	if (n >= REG_BITS) -		return -EINVAL; - -	hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE); -	hw_write(ci, OP_USBINTR,  BIT(n), BIT(n)); -	hw_write(ci, OP_USBSTS,   BIT(n), BIT(n)); -	hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, 0); -	return 0; -} - -/** - * show_device: prints information about device capabilities and status - * - * Check "device.h" for details - */ -static ssize_t show_device(struct device *dev, struct device_attribute *attr, -			   char *buf) -{ -	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); +	struct ci13xxx *ci = s->private;  	struct usb_gadget *gadget = &ci->gadget; -	int n = 0; - -	if (attr == NULL || buf == NULL) { -		dev_err(ci->dev, "[%s] EINVAL\n", __func__); -		return 0; -	} -	n += scnprintf(buf + n, PAGE_SIZE - n, "speed             = %d\n", -		       gadget->speed); -	n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed         = %d\n", -		       gadget->max_speed); -	n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg            = %d\n", -		       gadget->is_otg); -	n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral   = %d\n", -		       gadget->is_a_peripheral); -	n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable      = %d\n", -		       gadget->b_hnp_enable); -	n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support     = %d\n", -		       gadget->a_hnp_support); -	n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n", -		       gadget->a_alt_hnp_support); -	n += scnprintf(buf + n, PAGE_SIZE - n, "name              = %s\n", -		       (gadget->name ? gadget->name : "")); - -	return n; -} -static DEVICE_ATTR(device, S_IRUSR, show_device, NULL); +	seq_printf(s, "speed             = %d\n", gadget->speed); +	seq_printf(s, "max_speed         = %d\n", gadget->max_speed); +	seq_printf(s, "is_otg            = %d\n", gadget->is_otg); +	seq_printf(s, "is_a_peripheral   = %d\n", gadget->is_a_peripheral); +	seq_printf(s, "b_hnp_enable      = %d\n", gadget->b_hnp_enable); +	seq_printf(s, "a_hnp_support     = %d\n", gadget->a_hnp_support); +	seq_printf(s, "a_alt_hnp_support = %d\n", gadget->a_alt_hnp_support); +	seq_printf(s, "name              = %s\n", +		   (gadget->name ? gadget->name : "")); -/** - * show_driver: prints information about attached gadget (if any) - * - * Check "device.h" for details - */ -static ssize_t show_driver(struct device *dev, struct device_attribute *attr, -			   char *buf) -{ -	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); -	struct usb_gadget_driver *driver = ci->driver; -	int n = 0; - -	if (attr == NULL || buf == NULL) { -		dev_err(dev, "[%s] EINVAL\n", __func__); +	if (!ci->driver)  		return 0; -	} - -	if (driver == NULL) -		return scnprintf(buf, PAGE_SIZE, -				 "There is no gadget attached!\n"); -	n += scnprintf(buf + n, PAGE_SIZE - n, "function  = %s\n", -		       (driver->function ? driver->function : "")); -	n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n", -		       driver->max_speed); +	seq_printf(s, "gadget function   = %s\n", +		       (ci->driver->function ? ci->driver->function : "")); +	seq_printf(s, "gadget max speed  = %d\n", ci->driver->max_speed); -	return n; +	return 0;  } -static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL); - -/* Maximum event message length */ -#define DBG_DATA_MSG   64UL - -/* Maximum event messages */ -#define DBG_DATA_MAX   128UL - -/* Event buffer descriptor */ -static struct { -	char     (buf[DBG_DATA_MAX])[DBG_DATA_MSG];   /* buffer */ -	unsigned idx;   /* index */ -	unsigned tty;   /* print to console? */ -	rwlock_t lck;   /* lock */ -} dbg_data = { -	.idx = 0, -	.tty = 0, -	.lck = __RW_LOCK_UNLOCKED(dbg_data.lck) -}; -/** - * dbg_dec: decrements debug event index - * @idx: buffer index - */ -static void dbg_dec(unsigned *idx) +static int ci_device_open(struct inode *inode, struct file *file)  { -	*idx = (*idx - 1) & (DBG_DATA_MAX-1); +	return single_open(file, ci_device_show, inode->i_private);  } -/** - * dbg_inc: increments debug event index - * @idx: buffer index - */ -static void dbg_inc(unsigned *idx) -{ -	*idx = (*idx + 1) & (DBG_DATA_MAX-1); -} +static const struct file_operations ci_device_fops = { +	.open		= ci_device_open, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= single_release, +};  /** - * dbg_print:  prints the common part of the event - * @addr:   endpoint address - * @name:   event name - * @status: status - * @extra:  extra information + * ci_port_test_show: reads port test mode   */ -static void dbg_print(u8 addr, const char *name, int status, const char *extra) +static int ci_port_test_show(struct seq_file *s, void *data)  { -	struct timeval tval; -	unsigned int stamp; +	struct ci13xxx *ci = s->private;  	unsigned long flags; +	unsigned mode; -	write_lock_irqsave(&dbg_data.lck, flags); - -	do_gettimeofday(&tval); -	stamp = tval.tv_sec & 0xFFFF;	/* 2^32 = 4294967296. Limit to 4096s */ -	stamp = stamp * 1000000 + tval.tv_usec; - -	scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG, -		  "%04X\t? %02X %-7.7s %4i ?\t%s\n", -		  stamp, addr, name, status, extra); - -	dbg_inc(&dbg_data.idx); - -	write_unlock_irqrestore(&dbg_data.lck, flags); - -	if (dbg_data.tty != 0) -		pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n", -			  stamp, addr, name, status, extra); -} - -/** - * dbg_done: prints a DONE event - * @addr:   endpoint address - * @td:     transfer descriptor - * @status: status - */ -void dbg_done(u8 addr, const u32 token, int status) -{ -	char msg[DBG_DATA_MSG]; - -	scnprintf(msg, sizeof(msg), "%d %02X", -		  (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES), -		  (int)(token & TD_STATUS)      >> ffs_nr(TD_STATUS)); -	dbg_print(addr, "DONE", status, msg); -} - -/** - * dbg_event: prints a generic event - * @addr:   endpoint address - * @name:   event name - * @status: status - */ -void dbg_event(u8 addr, const char *name, int status) -{ -	if (name != NULL) -		dbg_print(addr, name, status, ""); -} - -/* - * dbg_queue: prints a QUEUE event - * @addr:   endpoint address - * @req:    USB request - * @status: status - */ -void dbg_queue(u8 addr, const struct usb_request *req, int status) -{ -	char msg[DBG_DATA_MSG]; - -	if (req != NULL) { -		scnprintf(msg, sizeof(msg), -			  "%d %d", !req->no_interrupt, req->length); -		dbg_print(addr, "QUEUE", status, msg); -	} -} +	spin_lock_irqsave(&ci->lock, flags); +	mode = hw_port_test_get(ci); +	spin_unlock_irqrestore(&ci->lock, flags); -/** - * dbg_setup: prints a SETUP event - * @addr: endpoint address - * @req:  setup request - */ -void dbg_setup(u8 addr, const struct usb_ctrlrequest *req) -{ -	char msg[DBG_DATA_MSG]; +	seq_printf(s, "mode = %u\n", mode); -	if (req != NULL) { -		scnprintf(msg, sizeof(msg), -			  "%02X %02X %04X %04X %d", req->bRequestType, -			  req->bRequest, le16_to_cpu(req->wValue), -			  le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength)); -		dbg_print(addr, "SETUP", 0, msg); -	} +	return 0;  }  /** - * show_events: displays the event buffer - * - * Check "device.h" for details + * ci_port_test_write: writes port test mode   */ -static ssize_t show_events(struct device *dev, struct device_attribute *attr, -			   char *buf) +static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf, +				  size_t count, loff_t *ppos)  { +	struct seq_file *s = file->private_data; +	struct ci13xxx *ci = s->private;  	unsigned long flags; -	unsigned i, j, n = 0; - -	if (attr == NULL || buf == NULL) { -		dev_err(dev->parent, "[%s] EINVAL\n", __func__); -		return 0; -	} +	unsigned mode; +	char buf[32]; +	int ret; -	read_lock_irqsave(&dbg_data.lck, flags); +	if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) +		return -EFAULT; -	i = dbg_data.idx; -	for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) { -		n += strlen(dbg_data.buf[i]); -		if (n >= PAGE_SIZE) { -			n -= strlen(dbg_data.buf[i]); -			break; -		} -	} -	for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i)) -		j += scnprintf(buf + j, PAGE_SIZE - j, -			       "%s", dbg_data.buf[i]); +	if (sscanf(buf, "%u", &mode) != 1) +		return -EINVAL; -	read_unlock_irqrestore(&dbg_data.lck, flags); +	spin_lock_irqsave(&ci->lock, flags); +	ret = hw_port_test_set(ci, mode); +	spin_unlock_irqrestore(&ci->lock, flags); -	return n; +	return ret ? ret : count;  } -/** - * store_events: configure if events are going to be also printed to console - * - * Check "device.h" for details - */ -static ssize_t store_events(struct device *dev, struct device_attribute *attr, -			    const char *buf, size_t count) +static int ci_port_test_open(struct inode *inode, struct file *file)  { -	unsigned tty; - -	if (attr == NULL || buf == NULL) { -		dev_err(dev, "[%s] EINVAL\n", __func__); -		goto done; -	} - -	if (sscanf(buf, "%u", &tty) != 1 || tty > 1) { -		dev_err(dev, "<1|0>: enable|disable console log\n"); -		goto done; -	} - -	dbg_data.tty = tty; -	dev_info(dev, "tty = %u", dbg_data.tty); - - done: -	return count; +	return single_open(file, ci_port_test_show, inode->i_private);  } -static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events); + +static const struct file_operations ci_port_test_fops = { +	.open		= ci_port_test_open, +	.write		= ci_port_test_write, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= single_release, +};  /** - * show_inters: interrupt status, enable status and historic - * - * Check "device.h" for details + * ci_qheads_show: DMA contents of all queue heads   */ -static ssize_t show_inters(struct device *dev, struct device_attribute *attr, -			   char *buf) +static int ci_qheads_show(struct seq_file *s, void *data)  { -	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); +	struct ci13xxx *ci = s->private;  	unsigned long flags; -	u32 intr; -	unsigned i, j, n = 0; +	unsigned i, j; -	if (attr == NULL || buf == NULL) { -		dev_err(ci->dev, "[%s] EINVAL\n", __func__); +	if (ci->role != CI_ROLE_GADGET) { +		seq_printf(s, "not in gadget mode\n");  		return 0;  	}  	spin_lock_irqsave(&ci->lock, flags); - -	/*n += scnprintf(buf + n, PAGE_SIZE - n, -		       "status = %08x\n", hw_read_intr_status(ci)); -	n += scnprintf(buf + n, PAGE_SIZE - n, -	"enable = %08x\n", hw_read_intr_enable(ci));*/ - -	n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n", -		       isr_statistics.test); -	n += scnprintf(buf + n, PAGE_SIZE - n, "? ui  = %d\n", -		       isr_statistics.ui); -	n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n", -		       isr_statistics.uei); -	n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n", -		       isr_statistics.pci); -	n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n", -		       isr_statistics.uri); -	n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n", -		       isr_statistics.sli); -	n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n", -		       isr_statistics.none); -	n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n", -		       isr_statistics.hndl.cnt); - -	for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) { -		i   &= ISR_MASK; -		intr = isr_statistics.hndl.buf[i]; - -		if (USBi_UI  & intr) -			n += scnprintf(buf + n, PAGE_SIZE - n, "ui  "); -		intr &= ~USBi_UI; -		if (USBi_UEI & intr) -			n += scnprintf(buf + n, PAGE_SIZE - n, "uei "); -		intr &= ~USBi_UEI; -		if (USBi_PCI & intr) -			n += scnprintf(buf + n, PAGE_SIZE - n, "pci "); -		intr &= ~USBi_PCI; -		if (USBi_URI & intr) -			n += scnprintf(buf + n, PAGE_SIZE - n, "uri "); -		intr &= ~USBi_URI; -		if (USBi_SLI & intr) -			n += scnprintf(buf + n, PAGE_SIZE - n, "sli "); -		intr &= ~USBi_SLI; -		if (intr) -			n += scnprintf(buf + n, PAGE_SIZE - n, "??? "); -		if (isr_statistics.hndl.buf[i]) -			n += scnprintf(buf + n, PAGE_SIZE - n, "\n"); +	for (i = 0; i < ci->hw_ep_max/2; i++) { +		struct ci13xxx_ep *mEpRx = &ci->ci13xxx_ep[i]; +		struct ci13xxx_ep *mEpTx = +			&ci->ci13xxx_ep[i + ci->hw_ep_max/2]; +		seq_printf(s, "EP=%02i: RX=%08X TX=%08X\n", +			   i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma); +		for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) +			seq_printf(s, " %04X:    %08X    %08X\n", j, +				   *((u32 *)mEpRx->qh.ptr + j), +				   *((u32 *)mEpTx->qh.ptr + j));  	} -  	spin_unlock_irqrestore(&ci->lock, flags); -	return n; +	return 0;  } -/** - * store_inters: enable & force or disable an individual interrutps - *                   (to be used for test purposes only) - * - * Check "device.h" for details - */ -static ssize_t store_inters(struct device *dev, struct device_attribute *attr, -			    const char *buf, size_t count) +static int ci_qheads_open(struct inode *inode, struct file *file)  { -	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); -	unsigned long flags; -	unsigned en, bit; - -	if (attr == NULL || buf == NULL) { -		dev_err(ci->dev, "EINVAL\n"); -		goto done; -	} - -	if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) { -		dev_err(ci->dev, "<1|0> <bit>: enable|disable interrupt\n"); -		goto done; -	} - -	spin_lock_irqsave(&ci->lock, flags); -	if (en) { -		if (hw_intr_force(ci, bit)) -			dev_err(dev, "invalid bit number\n"); -		else -			isr_statistics.test++; -	} else { -		if (hw_intr_clear(ci, bit)) -			dev_err(dev, "invalid bit number\n"); -	} -	spin_unlock_irqrestore(&ci->lock, flags); - - done: -	return count; +	return single_open(file, ci_qheads_show, inode->i_private);  } -static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters); + +static const struct file_operations ci_qheads_fops = { +	.open		= ci_qheads_open, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= single_release, +};  /** - * show_port_test: reads port test mode - * - * Check "device.h" for details + * ci_requests_show: DMA contents of all requests currently queued (all endpts)   */ -static ssize_t show_port_test(struct device *dev, -			      struct device_attribute *attr, char *buf) +static int ci_requests_show(struct seq_file *s, void *data)  { -	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); +	struct ci13xxx *ci = s->private;  	unsigned long flags; -	unsigned mode; +	struct list_head   *ptr = NULL; +	struct ci13xxx_req *req = NULL; +	unsigned i, j, qsize = sizeof(struct ci13xxx_td)/sizeof(u32); -	if (attr == NULL || buf == NULL) { -		dev_err(ci->dev, "EINVAL\n"); +	if (ci->role != CI_ROLE_GADGET) { +		seq_printf(s, "not in gadget mode\n");  		return 0;  	}  	spin_lock_irqsave(&ci->lock, flags); -	mode = hw_port_test_get(ci); -	spin_unlock_irqrestore(&ci->lock, flags); - -	return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode); -} - -/** - * store_port_test: writes port test mode - * - * Check "device.h" for details - */ -static ssize_t store_port_test(struct device *dev, -			       struct device_attribute *attr, -			       const char *buf, size_t count) -{ -	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); -	unsigned long flags; -	unsigned mode; +	for (i = 0; i < ci->hw_ep_max; i++) +		list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue) { +			req = list_entry(ptr, struct ci13xxx_req, queue); -	if (attr == NULL || buf == NULL) { -		dev_err(ci->dev, "[%s] EINVAL\n", __func__); -		goto done; -	} +			seq_printf(s, "EP=%02i: TD=%08X %s\n", +				   i % (ci->hw_ep_max / 2), (u32)req->dma, +				   ((i < ci->hw_ep_max/2) ? "RX" : "TX")); -	if (sscanf(buf, "%u", &mode) != 1) { -		dev_err(ci->dev, "<mode>: set port test mode"); -		goto done; -	} - -	spin_lock_irqsave(&ci->lock, flags); -	if (hw_port_test_set(ci, mode)) -		dev_err(ci->dev, "invalid mode\n"); +			for (j = 0; j < qsize; j++) +				seq_printf(s, " %04X:    %08X\n", j, +					   *((u32 *)req->ptr + j)); +		}  	spin_unlock_irqrestore(&ci->lock, flags); - done: -	return count; +	return 0;  } -static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR, -		   show_port_test, store_port_test); -/** - * show_qheads: DMA contents of all queue heads - * - * Check "device.h" for details - */ -static ssize_t show_qheads(struct device *dev, struct device_attribute *attr, -			   char *buf) +static int ci_requests_open(struct inode *inode, struct file *file)  { -	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); -	unsigned long flags; -	unsigned i, j, n = 0; +	return single_open(file, ci_requests_show, inode->i_private); +} -	if (attr == NULL || buf == NULL) { -		dev_err(ci->dev, "[%s] EINVAL\n", __func__); -		return 0; -	} +static const struct file_operations ci_requests_fops = { +	.open		= ci_requests_open, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= single_release, +}; -	spin_lock_irqsave(&ci->lock, flags); -	for (i = 0; i < ci->hw_ep_max/2; i++) { -		struct ci13xxx_ep *mEpRx = &ci->ci13xxx_ep[i]; -		struct ci13xxx_ep *mEpTx = -			&ci->ci13xxx_ep[i + ci->hw_ep_max/2]; -		n += scnprintf(buf + n, PAGE_SIZE - n, -			       "EP=%02i: RX=%08X TX=%08X\n", -			       i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma); -		for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) { -			n += scnprintf(buf + n, PAGE_SIZE - n, -				       " %04X:    %08X    %08X\n", j, -				       *((u32 *)mEpRx->qh.ptr + j), -				       *((u32 *)mEpTx->qh.ptr + j)); -		} -	} -	spin_unlock_irqrestore(&ci->lock, flags); +static int ci_role_show(struct seq_file *s, void *data) +{ +	struct ci13xxx *ci = s->private; -	return n; +	seq_printf(s, "%s\n", ci_role(ci)->name); + +	return 0;  } -static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL); -/** - * show_registers: dumps all registers - * - * Check "device.h" for details - */ -#define DUMP_ENTRIES	512 -static ssize_t show_registers(struct device *dev, -			      struct device_attribute *attr, char *buf) +static ssize_t ci_role_write(struct file *file, const char __user *ubuf, +			     size_t count, loff_t *ppos)  { -	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); -	unsigned long flags; -	u32 *dump; -	unsigned i, k, n = 0; +	struct seq_file *s = file->private_data; +	struct ci13xxx *ci = s->private; +	enum ci_role role; +	char buf[8]; +	int ret; -	if (attr == NULL || buf == NULL) { -		dev_err(ci->dev, "[%s] EINVAL\n", __func__); -		return 0; -	} +	if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) +		return -EFAULT; -	dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL); -	if (!dump) { -		dev_err(ci->dev, "%s: out of memory\n", __func__); -		return 0; -	} +	for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++) +		if (ci->roles[role] && +		    !strncmp(buf, ci->roles[role]->name, +			     strlen(ci->roles[role]->name))) +			break; -	spin_lock_irqsave(&ci->lock, flags); -	k = hw_register_read(ci, dump, DUMP_ENTRIES); -	spin_unlock_irqrestore(&ci->lock, flags); +	if (role == CI_ROLE_END || role == ci->role) +		return -EINVAL; -	for (i = 0; i < k; i++) { -		n += scnprintf(buf + n, PAGE_SIZE - n, -			       "reg[0x%04X] = 0x%08X\n", -			       i * (unsigned)sizeof(u32), dump[i]); -	} -	kfree(dump); +	ci_role_stop(ci); +	ret = ci_role_start(ci, role); -	return n; +	return ret ? ret : count;  } -/** - * store_registers: writes value to register address - * - * Check "device.h" for details - */ -static ssize_t store_registers(struct device *dev, -			       struct device_attribute *attr, -			       const char *buf, size_t count) +static int ci_role_open(struct inode *inode, struct file *file)  { -	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); -	unsigned long addr, data, flags; - -	if (attr == NULL || buf == NULL) { -		dev_err(ci->dev, "[%s] EINVAL\n", __func__); -		goto done; -	} - -	if (sscanf(buf, "%li %li", &addr, &data) != 2) { -		dev_err(ci->dev, -			"<addr> <data>: write data to register address\n"); -		goto done; -	} - -	spin_lock_irqsave(&ci->lock, flags); -	if (hw_register_write(ci, addr, data)) -		dev_err(ci->dev, "invalid address range\n"); -	spin_unlock_irqrestore(&ci->lock, flags); - - done: -	return count; +	return single_open(file, ci_role_show, inode->i_private);  } -static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR, -		   show_registers, store_registers); + +static const struct file_operations ci_role_fops = { +	.open		= ci_role_open, +	.write		= ci_role_write, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= single_release, +};  /** - * show_requests: DMA contents of all requests currently queued (all endpts) + * dbg_create_files: initializes the attribute interface + * @ci: device   * - * Check "device.h" for details + * This function returns an error code   */ -static ssize_t show_requests(struct device *dev, struct device_attribute *attr, -			     char *buf) +int dbg_create_files(struct ci13xxx *ci)  { -	struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev); -	unsigned long flags; -	struct list_head   *ptr = NULL; -	struct ci13xxx_req *req = NULL; -	unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32); +	struct dentry *dent; -	if (attr == NULL || buf == NULL) { -		dev_err(ci->dev, "[%s] EINVAL\n", __func__); -		return 0; -	} +	ci->debugfs = debugfs_create_dir(dev_name(ci->dev), NULL); +	if (!ci->debugfs) +		return -ENOMEM; -	spin_lock_irqsave(&ci->lock, flags); -	for (i = 0; i < ci->hw_ep_max; i++) -		list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue) -		{ -			req = list_entry(ptr, struct ci13xxx_req, queue); +	dent = debugfs_create_file("device", S_IRUGO, ci->debugfs, ci, +				   &ci_device_fops); +	if (!dent) +		goto err; -			n += scnprintf(buf + n, PAGE_SIZE - n, -					"EP=%02i: TD=%08X %s\n", -					i % ci->hw_ep_max/2, (u32)req->dma, -					((i < ci->hw_ep_max/2) ? "RX" : "TX")); +	dent = debugfs_create_file("port_test", S_IRUGO | S_IWUSR, ci->debugfs, +				   ci, &ci_port_test_fops); +	if (!dent) +		goto err; -			for (j = 0; j < qSize; j++) -				n += scnprintf(buf + n, PAGE_SIZE - n, -						" %04X:    %08X\n", j, -						*((u32 *)req->ptr + j)); -		} -	spin_unlock_irqrestore(&ci->lock, flags); +	dent = debugfs_create_file("qheads", S_IRUGO, ci->debugfs, ci, +				   &ci_qheads_fops); +	if (!dent) +		goto err; -	return n; -} -static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL); +	dent = debugfs_create_file("requests", S_IRUGO, ci->debugfs, ci, +				   &ci_requests_fops); +	if (!dent) +		goto err; -/** - * dbg_create_files: initializes the attribute interface - * @dev: device - * - * This function returns an error code - */ -int dbg_create_files(struct device *dev) -{ -	int retval = 0; - -	if (dev == NULL) -		return -EINVAL; -	retval = device_create_file(dev, &dev_attr_device); -	if (retval) -		goto done; -	retval = device_create_file(dev, &dev_attr_driver); -	if (retval) -		goto rm_device; -	retval = device_create_file(dev, &dev_attr_events); -	if (retval) -		goto rm_driver; -	retval = device_create_file(dev, &dev_attr_inters); -	if (retval) -		goto rm_events; -	retval = device_create_file(dev, &dev_attr_port_test); -	if (retval) -		goto rm_inters; -	retval = device_create_file(dev, &dev_attr_qheads); -	if (retval) -		goto rm_port_test; -	retval = device_create_file(dev, &dev_attr_registers); -	if (retval) -		goto rm_qheads; -	retval = device_create_file(dev, &dev_attr_requests); -	if (retval) -		goto rm_registers; -	return 0; - - rm_registers: -	device_remove_file(dev, &dev_attr_registers); - rm_qheads: -	device_remove_file(dev, &dev_attr_qheads); - rm_port_test: -	device_remove_file(dev, &dev_attr_port_test); - rm_inters: -	device_remove_file(dev, &dev_attr_inters); - rm_events: -	device_remove_file(dev, &dev_attr_events); - rm_driver: -	device_remove_file(dev, &dev_attr_driver); - rm_device: -	device_remove_file(dev, &dev_attr_device); - done: -	return retval; +	dent = debugfs_create_file("role", S_IRUGO | S_IWUSR, ci->debugfs, ci, +				   &ci_role_fops); +	if (dent) +		return 0; +err: +	debugfs_remove_recursive(ci->debugfs); +	return -ENOMEM;  }  /**   * dbg_remove_files: destroys the attribute interface - * @dev: device - * - * This function returns an error code + * @ci: device   */ -int dbg_remove_files(struct device *dev) +void dbg_remove_files(struct ci13xxx *ci)  { -	if (dev == NULL) -		return -EINVAL; -	device_remove_file(dev, &dev_attr_requests); -	device_remove_file(dev, &dev_attr_registers); -	device_remove_file(dev, &dev_attr_qheads); -	device_remove_file(dev, &dev_attr_port_test); -	device_remove_file(dev, &dev_attr_inters); -	device_remove_file(dev, &dev_attr_events); -	device_remove_file(dev, &dev_attr_driver); -	device_remove_file(dev, &dev_attr_device); -	return 0; +	debugfs_remove_recursive(ci->debugfs);  } diff --git a/drivers/usb/chipidea/debug.h b/drivers/usb/chipidea/debug.h index 80d96865775..7ca6ca0a24a 100644 --- a/drivers/usb/chipidea/debug.h +++ b/drivers/usb/chipidea/debug.h @@ -14,42 +14,16 @@  #define __DRIVERS_USB_CHIPIDEA_DEBUG_H  #ifdef CONFIG_USB_CHIPIDEA_DEBUG -void dbg_interrupt(u32 intmask); -void dbg_done(u8 addr, const u32 token, int status); -void dbg_event(u8 addr, const char *name, int status); -void dbg_queue(u8 addr, const struct usb_request *req, int status); -void dbg_setup(u8 addr, const struct usb_ctrlrequest *req); -int dbg_create_files(struct device *dev); -int dbg_remove_files(struct device *dev); +int dbg_create_files(struct ci13xxx *ci); +void dbg_remove_files(struct ci13xxx *ci);  #else -static inline void dbg_interrupt(u32 intmask) -{ -} - -static inline void dbg_done(u8 addr, const u32 token, int status) -{ -} - -static inline void dbg_event(u8 addr, const char *name, int status) -{ -} - -static inline void dbg_queue(u8 addr, const struct usb_request *req, int status) -{ -} - -static inline void dbg_setup(u8 addr, const struct usb_ctrlrequest *req) -{ -} - -static inline int dbg_create_files(struct device *dev) +static inline int dbg_create_files(struct ci13xxx *ci)  {  	return 0;  } -static inline int dbg_remove_files(struct device *dev) +static inline void dbg_remove_files(struct ci13xxx *ci)  { -	return 0;  }  #endif diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index f64fbea1cf2..519ead2443c 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -13,14 +13,8 @@  #include <linux/delay.h>  #include <linux/device.h>  #include <linux/dmapool.h> -#include <linux/dma-mapping.h>  #include <linux/err.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/irq.h> +#include <linux/irqreturn.h>  #include <linux/kernel.h>  #include <linux/slab.h>  #include <linux/pm_runtime.h> @@ -146,7 +140,7 @@ static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type)  	if (dir) {  		mask  = ENDPTCTRL_TXT;  /* type    */ -		data  = type << ffs_nr(mask); +		data  = type << __ffs(mask);  		mask |= ENDPTCTRL_TXS;  /* unstall */  		mask |= ENDPTCTRL_TXR;  /* reset data toggle */ @@ -155,7 +149,7 @@ static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type)  		data |= ENDPTCTRL_TXE;  	} else {  		mask  = ENDPTCTRL_RXT;  /* type    */ -		data  = type << ffs_nr(mask); +		data  = type << __ffs(mask);  		mask |= ENDPTCTRL_RXS;  /* unstall */  		mask |= ENDPTCTRL_RXR;  /* reset data toggle */ @@ -305,18 +299,6 @@ static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci)  	return reg;  } -static void hw_enable_vbus_intr(struct ci13xxx *ci) -{ -	hw_write(ci, OP_OTGSC, OTGSC_AVVIS, OTGSC_AVVIS); -	hw_write(ci, OP_OTGSC, OTGSC_AVVIE, OTGSC_AVVIE); -	queue_work(ci->wq, &ci->vbus_work); -} - -static void hw_disable_vbus_intr(struct ci13xxx *ci) -{ -	hw_write(ci, OP_OTGSC, OTGSC_AVVIE, 0); -} -  /**   * hw_test_and_clear_setup_guard: test & clear setup guard (execute without   *                                interruption) @@ -349,7 +331,7 @@ static int hw_test_and_set_setup_guard(struct ci13xxx *ci)  static void hw_usb_set_address(struct ci13xxx *ci, u8 value)  {  	hw_write(ci, OP_DEVICEADDR, DEVICEADDR_USBADR, -		 value << ffs_nr(DEVICEADDR_USBADR)); +		 value << __ffs(DEVICEADDR_USBADR));  }  /** @@ -383,16 +365,6 @@ static int hw_usb_reset(struct ci13xxx *ci)  	return 0;  } -static void vbus_work(struct work_struct *work) -{ -	struct ci13xxx *ci = container_of(work, struct ci13xxx, vbus_work); - -	if (hw_read(ci, OP_OTGSC, OTGSC_AVV)) -		usb_gadget_vbus_connect(&ci->gadget); -	else -		usb_gadget_vbus_disconnect(&ci->gadget); -} -  /******************************************************************************   * UTIL block   *****************************************************************************/ @@ -432,10 +404,10 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)  			return -ENOMEM;  		memset(mReq->zptr, 0, sizeof(*mReq->zptr)); -		mReq->zptr->next    = TD_TERMINATE; -		mReq->zptr->token   = TD_STATUS_ACTIVE; +		mReq->zptr->next    = cpu_to_le32(TD_TERMINATE); +		mReq->zptr->token   = cpu_to_le32(TD_STATUS_ACTIVE);  		if (!mReq->req.no_interrupt) -			mReq->zptr->token   |= TD_IOC; +			mReq->zptr->token   |= cpu_to_le32(TD_IOC);  	}  	ret = usb_gadget_map_request(&ci->gadget, &mReq->req, mEp->dir);  	if (ret) @@ -446,32 +418,37 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)  	 * TODO - handle requests which spawns into several TDs  	 */  	memset(mReq->ptr, 0, sizeof(*mReq->ptr)); -	mReq->ptr->token    = length << ffs_nr(TD_TOTAL_BYTES); -	mReq->ptr->token   &= TD_TOTAL_BYTES; -	mReq->ptr->token   |= TD_STATUS_ACTIVE; +	mReq->ptr->token    = cpu_to_le32(length << __ffs(TD_TOTAL_BYTES)); +	mReq->ptr->token   &= cpu_to_le32(TD_TOTAL_BYTES); +	mReq->ptr->token   |= cpu_to_le32(TD_STATUS_ACTIVE);  	if (mReq->zptr) { -		mReq->ptr->next    = mReq->zdma; +		mReq->ptr->next    = cpu_to_le32(mReq->zdma);  	} else { -		mReq->ptr->next    = TD_TERMINATE; +		mReq->ptr->next    = cpu_to_le32(TD_TERMINATE);  		if (!mReq->req.no_interrupt) -			mReq->ptr->token  |= TD_IOC; +			mReq->ptr->token  |= cpu_to_le32(TD_IOC); +	} +	mReq->ptr->page[0]  = cpu_to_le32(mReq->req.dma); +	for (i = 1; i < TD_PAGE_COUNT; i++) { +		u32 page = mReq->req.dma + i * CI13XXX_PAGE_SIZE; +		page &= ~TD_RESERVED_MASK; +		mReq->ptr->page[i] = cpu_to_le32(page);  	} -	mReq->ptr->page[0]  = mReq->req.dma; -	for (i = 1; i < 5; i++) -		mReq->ptr->page[i] = -			(mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK; + +	wmb();  	if (!list_empty(&mEp->qh.queue)) {  		struct ci13xxx_req *mReqPrev;  		int n = hw_ep_bit(mEp->num, mEp->dir);  		int tmp_stat; +		u32 next = mReq->dma & TD_ADDR_MASK;  		mReqPrev = list_entry(mEp->qh.queue.prev,  				struct ci13xxx_req, queue);  		if (mReqPrev->zptr) -			mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK; +			mReqPrev->zptr->next = cpu_to_le32(next);  		else -			mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK; +			mReqPrev->ptr->next = cpu_to_le32(next);  		wmb();  		if (hw_read(ci, OP_ENDPTPRIME, BIT(n)))  			goto done; @@ -485,9 +462,9 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)  	}  	/*  QH configuration */ -	mEp->qh.ptr->td.next   = mReq->dma;    /* TERMINATE = 0 */ -	mEp->qh.ptr->td.token &= ~TD_STATUS;   /* clear status */ -	mEp->qh.ptr->cap |=  QH_ZLT; +	mEp->qh.ptr->td.next   = cpu_to_le32(mReq->dma);    /* TERMINATE = 0 */ +	mEp->qh.ptr->td.token &= +		cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE));  	wmb();   /* synchronize before ep prime */ @@ -506,14 +483,16 @@ done:   */  static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)  { +	u32 tmptoken = le32_to_cpu(mReq->ptr->token); +  	if (mReq->req.status != -EALREADY)  		return -EINVAL; -	if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0) +	if ((TD_STATUS_ACTIVE & tmptoken) != 0)  		return -EBUSY;  	if (mReq->zptr) { -		if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0) +		if ((cpu_to_le32(TD_STATUS_ACTIVE) & mReq->zptr->token) != 0)  			return -EBUSY;  		dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);  		mReq->zptr = NULL; @@ -523,7 +502,7 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)  	usb_gadget_unmap_request(&mEp->ci->gadget, &mReq->req, mEp->dir); -	mReq->req.status = mReq->ptr->token & TD_STATUS; +	mReq->req.status = tmptoken & TD_STATUS;  	if ((TD_STATUS_HALTED & mReq->req.status) != 0)  		mReq->req.status = -1;  	else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0) @@ -531,8 +510,8 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)  	else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)  		mReq->req.status = -1; -	mReq->req.actual   = mReq->ptr->token & TD_TOTAL_BYTES; -	mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES); +	mReq->req.actual   = tmptoken & TD_TOTAL_BYTES; +	mReq->req.actual >>= __ffs(TD_TOTAL_BYTES);  	mReq->req.actual   = mReq->req.length - mReq->req.actual;  	mReq->req.actual   = mReq->req.status ? 0 : mReq->req.actual; @@ -561,6 +540,12 @@ __acquires(mEp->lock)  		struct ci13xxx_req *mReq = \  			list_entry(mEp->qh.queue.next,  				   struct ci13xxx_req, queue); + +		if (mReq->zptr) { +			dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma); +			mReq->zptr = NULL; +		} +  		list_del_init(&mReq->queue);  		mReq->req.status = -ESHUTDOWN; @@ -629,8 +614,6 @@ __acquires(ci->lock)  {  	int retval; -	dbg_event(0xFF, "BUS RST", 0); -  	spin_unlock(&ci->lock);  	retval = _gadget_stop_activity(&ci->gadget);  	if (retval) @@ -668,6 +651,59 @@ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)  }  /** + * _ep_queue: queues (submits) an I/O request to an endpoint + * + * Caller must hold lock + */ +static int _ep_queue(struct usb_ep *ep, struct usb_request *req, +		    gfp_t __maybe_unused gfp_flags) +{ +	struct ci13xxx_ep  *mEp  = container_of(ep,  struct ci13xxx_ep, ep); +	struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); +	struct ci13xxx *ci = mEp->ci; +	int retval = 0; + +	if (ep == NULL || req == NULL || mEp->ep.desc == NULL) +		return -EINVAL; + +	if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { +		if (req->length) +			mEp = (ci->ep0_dir == RX) ? +			       ci->ep0out : ci->ep0in; +		if (!list_empty(&mEp->qh.queue)) { +			_ep_nuke(mEp); +			retval = -EOVERFLOW; +			dev_warn(mEp->ci->dev, "endpoint ctrl %X nuked\n", +				 _usb_addr(mEp)); +		} +	} + +	/* first nuke then test link, e.g. previous status has not sent */ +	if (!list_empty(&mReq->queue)) { +		dev_err(mEp->ci->dev, "request already in queue\n"); +		return -EBUSY; +	} + +	if (req->length > (TD_PAGE_COUNT - 1) * CI13XXX_PAGE_SIZE) { +		dev_err(mEp->ci->dev, "request bigger than one td\n"); +		return -EMSGSIZE; +	} + +	/* push request */ +	mReq->req.status = -EINPROGRESS; +	mReq->req.actual = 0; + +	retval = _hardware_enqueue(mEp, mReq); + +	if (retval == -EALREADY) +		retval = 0; +	if (!retval) +		list_add_tail(&mReq->queue, &mEp->qh.queue); + +	return retval; +} + +/**   * isr_get_status_response: get_status request response   * @ci: ci struct   * @setup: setup request packet @@ -714,9 +750,7 @@ __acquires(mEp->lock)  	}  	/* else do nothing; reserved for future use */ -	spin_unlock(mEp->lock); -	retval = usb_ep_queue(&mEp->ep, req, gfp_flags); -	spin_lock(mEp->lock); +	retval = _ep_queue(&mEp->ep, req, gfp_flags);  	if (retval)  		goto err_free_buf; @@ -763,8 +797,6 @@ isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)   * This function returns an error code   */  static int isr_setup_status_phase(struct ci13xxx *ci) -__releases(mEp->lock) -__acquires(mEp->lock)  {  	int retval;  	struct ci13xxx_ep *mEp; @@ -773,9 +805,7 @@ __acquires(mEp->lock)  	ci->status->context = ci;  	ci->status->complete = isr_setup_status_complete; -	spin_unlock(mEp->lock); -	retval = usb_ep_queue(&mEp->ep, ci->status, GFP_ATOMIC); -	spin_lock(mEp->lock); +	retval = _ep_queue(&mEp->ep, ci->status, GFP_ATOMIC);  	return retval;  } @@ -801,7 +831,6 @@ __acquires(mEp->lock)  		if (retval < 0)  			break;  		list_del_init(&mReq->queue); -		dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);  		if (mReq->req.complete != NULL) {  			spin_unlock(mEp->lock);  			if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) && @@ -814,8 +843,6 @@ __acquires(mEp->lock)  	if (retval == -EBUSY)  		retval = 0; -	if (retval < 0) -		dbg_event(_usb_addr(mEp), "DONE", retval);  	return retval;  } @@ -847,8 +874,6 @@ __acquires(ci->lock)  				if (err > 0)   /* needs status phase */  					err = isr_setup_status_phase(ci);  				if (err < 0) { -					dbg_event(_usb_addr(mEp), -						  "ERROR", err);  					spin_unlock(&ci->lock);  					if (usb_ep_set_halt(&mEp->ep))  						dev_err(ci->dev, @@ -884,8 +909,6 @@ __acquires(ci->lock)  		ci->ep0_dir = (type & USB_DIR_IN) ? TX : RX; -		dbg_setup(_usb_addr(mEp), &req); -  		switch (req.bRequest) {  		case USB_REQ_CLEAR_FEATURE:  			if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) && @@ -997,8 +1020,6 @@ delegate:  		}  		if (err < 0) { -			dbg_event(_usb_addr(mEp), "ERROR", err); -  			spin_unlock(&ci->lock);  			if (usb_ep_set_halt(&mEp->ep))  				dev_err(ci->dev, "error: ep_set_halt\n"); @@ -1021,6 +1042,7 @@ static int ep_enable(struct usb_ep *ep,  	struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);  	int retval = 0;  	unsigned long flags; +	u32 cap = 0;  	if (ep == NULL || desc == NULL)  		return -EINVAL; @@ -1040,20 +1062,15 @@ static int ep_enable(struct usb_ep *ep,  	mEp->ep.maxpacket = usb_endpoint_maxp(desc); -	dbg_event(_usb_addr(mEp), "ENABLE", 0); - -	mEp->qh.ptr->cap = 0; -  	if (mEp->type == USB_ENDPOINT_XFER_CONTROL) -		mEp->qh.ptr->cap |=  QH_IOS; -	else if (mEp->type == USB_ENDPOINT_XFER_ISOC) -		mEp->qh.ptr->cap &= ~QH_MULT; -	else -		mEp->qh.ptr->cap &= ~QH_ZLT; +		cap |= QH_IOS; +	if (mEp->num) +		cap |= QH_ZLT; +	cap |= (mEp->ep.maxpacket << __ffs(QH_MAX_PKT)) & QH_MAX_PKT; + +	mEp->qh.ptr->cap = cpu_to_le32(cap); -	mEp->qh.ptr->cap |= -		(mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT; -	mEp->qh.ptr->td.next |= TD_TERMINATE;   /* needed? */ +	mEp->qh.ptr->td.next |= cpu_to_le32(TD_TERMINATE);   /* needed? */  	/*  	 * Enable endpoints in the HW other than ep0 as ep0 @@ -1088,8 +1105,6 @@ static int ep_disable(struct usb_ep *ep)  	direction = mEp->dir;  	do { -		dbg_event(_usb_addr(mEp), "DISABLE", 0); -  		retval |= _ep_nuke(mEp);  		retval |= hw_ep_disable(mEp->ci, mEp->num, mEp->dir); @@ -1129,8 +1144,6 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)  		}  	} -	dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL); -  	return (mReq == NULL) ? NULL : &mReq->req;  } @@ -1158,8 +1171,6 @@ static void ep_free_request(struct usb_ep *ep, struct usb_request *req)  		dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);  	kfree(mReq); -	dbg_event(_usb_addr(mEp), "FREE", 0); -  	spin_unlock_irqrestore(mEp->lock, flags);  } @@ -1172,8 +1183,6 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,  		    gfp_t __maybe_unused gfp_flags)  {  	struct ci13xxx_ep  *mEp  = container_of(ep,  struct ci13xxx_ep, ep); -	struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); -	struct ci13xxx *ci = mEp->ci;  	int retval = 0;  	unsigned long flags; @@ -1181,48 +1190,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,  		return -EINVAL;  	spin_lock_irqsave(mEp->lock, flags); - -	if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { -		if (req->length) -			mEp = (ci->ep0_dir == RX) ? -			       ci->ep0out : ci->ep0in; -		if (!list_empty(&mEp->qh.queue)) { -			_ep_nuke(mEp); -			retval = -EOVERFLOW; -			dev_warn(mEp->ci->dev, "endpoint ctrl %X nuked\n", -				 _usb_addr(mEp)); -		} -	} - -	/* first nuke then test link, e.g. previous status has not sent */ -	if (!list_empty(&mReq->queue)) { -		retval = -EBUSY; -		dev_err(mEp->ci->dev, "request already in queue\n"); -		goto done; -	} - -	if (req->length > 4 * CI13XXX_PAGE_SIZE) { -		req->length = 4 * CI13XXX_PAGE_SIZE; -		retval = -EMSGSIZE; -		dev_warn(mEp->ci->dev, "request length truncated\n"); -	} - -	dbg_queue(_usb_addr(mEp), req, retval); - -	/* push request */ -	mReq->req.status = -EINPROGRESS; -	mReq->req.actual = 0; - -	retval = _hardware_enqueue(mEp, mReq); - -	if (retval == -EALREADY) { -		dbg_event(_usb_addr(mEp), "QUEUE", retval); -		retval = 0; -	} -	if (!retval) -		list_add_tail(&mReq->queue, &mEp->qh.queue); - - done: +	retval = _ep_queue(ep, req, gfp_flags);  	spin_unlock_irqrestore(mEp->lock, flags);  	return retval;  } @@ -1245,8 +1213,6 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)  	spin_lock_irqsave(mEp->lock, flags); -	dbg_event(_usb_addr(mEp), "DEQUEUE", 0); -  	hw_ep_flush(mEp->ci, mEp->num, mEp->dir);  	/* pop request */ @@ -1293,7 +1259,6 @@ static int ep_set_halt(struct usb_ep *ep, int value)  	direction = mEp->dir;  	do { -		dbg_event(_usb_addr(mEp), "HALT", value);  		retval |= hw_ep_set_halt(mEp->ci, mEp->num, mEp->dir, value);  		if (!value) @@ -1322,10 +1287,7 @@ static int ep_set_wedge(struct usb_ep *ep)  		return -EINVAL;  	spin_lock_irqsave(mEp->lock, flags); - -	dbg_event(_usb_addr(mEp), "WEDGE", 0);  	mEp->wedge = 1; -  	spin_unlock_irqrestore(mEp->lock, flags);  	return usb_ep_set_halt(ep); @@ -1348,7 +1310,6 @@ static void ep_fifo_flush(struct usb_ep *ep)  	spin_lock_irqsave(mEp->lock, flags); -	dbg_event(_usb_addr(mEp), "FFLUSH", 0);  	hw_ep_flush(mEp->ci, mEp->num, mEp->dir);  	spin_unlock_irqrestore(mEp->lock, flags); @@ -1392,7 +1353,6 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)  		if (is_active) {  			pm_runtime_get_sync(&_gadget->dev);  			hw_device_reset(ci, USBMODE_CM_DC); -			hw_enable_vbus_intr(ci);  			hw_device_state(ci, ci->ep0out->qh.dma);  		} else {  			hw_device_state(ci, 0); @@ -1567,10 +1527,8 @@ static int ci13xxx_start(struct usb_gadget *gadget,  	pm_runtime_get_sync(&ci->gadget.dev);  	if (ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) {  		if (ci->vbus_active) { -			if (ci->platdata->flags & CI13XXX_REGS_SHARED) { +			if (ci->platdata->flags & CI13XXX_REGS_SHARED)  				hw_device_reset(ci, USBMODE_CM_DC); -				hw_enable_vbus_intr(ci); -			}  		} else {  			pm_runtime_put_sync(&ci->gadget.dev);  			goto done; @@ -1642,7 +1600,6 @@ static irqreturn_t udc_irq(struct ci13xxx *ci)  		}  	}  	intr = hw_test_and_clear_intr_active(ci); -	dbg_interrupt(intr);  	if (intr) {  		/* order defines priority - do NOT change it */ @@ -1676,29 +1633,12 @@ static irqreturn_t udc_irq(struct ci13xxx *ci)  	} else {  		retval = IRQ_NONE;  	} - -	intr = hw_read(ci, OP_OTGSC, ~0); -	hw_write(ci, OP_OTGSC, ~0, intr); - -	if (intr & (OTGSC_AVVIE & OTGSC_AVVIS)) -		queue_work(ci->wq, &ci->vbus_work); -  	spin_unlock(&ci->lock);  	return retval;  }  /** - * udc_release: driver release function - * @dev: device - * - * Currently does nothing - */ -static void udc_release(struct device *dev) -{ -} - -/**   * udc_start: initialize gadget role   * @ci: chipidea controller   */ @@ -1717,12 +1657,6 @@ static int udc_start(struct ci13xxx *ci)  	INIT_LIST_HEAD(&ci->gadget.ep_list); -	dev_set_name(&ci->gadget.dev, "gadget"); -	ci->gadget.dev.dma_mask = dev->dma_mask; -	ci->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask; -	ci->gadget.dev.parent   = dev; -	ci->gadget.dev.release  = udc_release; -  	/* alloc resources */  	ci->qh_pool = dma_pool_create("ci13xxx_qh", dev,  				       sizeof(struct ci13xxx_qh), @@ -1758,24 +1692,13 @@ static int udc_start(struct ci13xxx *ci)  		retval = hw_device_reset(ci, USBMODE_CM_DC);  		if (retval)  			goto put_transceiver; -		hw_enable_vbus_intr(ci); -	} - -	retval = device_register(&ci->gadget.dev); -	if (retval) { -		put_device(&ci->gadget.dev); -		goto put_transceiver;  	} -	retval = dbg_create_files(ci->dev); -	if (retval) -		goto unreg_device; -  	if (!IS_ERR_OR_NULL(ci->transceiver)) {  		retval = otg_set_peripheral(ci->transceiver->otg,  						&ci->gadget);  		if (retval) -			goto remove_dbg; +			goto put_transceiver;  	}  	retval = usb_add_gadget_udc(dev, &ci->gadget); @@ -1795,10 +1718,6 @@ remove_trans:  	}  	dev_err(dev, "error = %i\n", retval); -remove_dbg: -	dbg_remove_files(ci->dev); -unreg_device: -	device_unregister(&ci->gadget.dev);  put_transceiver:  	if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)  		usb_put_phy(ci->transceiver); @@ -1821,9 +1740,6 @@ static void udc_stop(struct ci13xxx *ci)  	if (ci == NULL)  		return; -	hw_disable_vbus_intr(ci); -	cancel_work_sync(&ci->vbus_work); -  	usb_del_gadget_udc(&ci->gadget);  	destroy_eps(ci); @@ -1836,8 +1752,6 @@ static void udc_stop(struct ci13xxx *ci)  		if (ci->global_phy)  			usb_put_phy(ci->transceiver);  	} -	dbg_remove_files(ci->dev); -	device_unregister(&ci->gadget.dev);  	/* my kobject is dynamic, I swear! */  	memset(&ci->gadget, 0, sizeof(ci->gadget));  } @@ -1864,7 +1778,6 @@ int ci_hdrc_gadget_init(struct ci13xxx *ci)  	rdrv->irq	= udc_irq;  	rdrv->name	= "gadget";  	ci->roles[CI_ROLE_GADGET] = rdrv; -	INIT_WORK(&ci->vbus_work, vbus_work);  	return 0;  } diff --git a/drivers/usb/chipidea/udc.h b/drivers/usb/chipidea/udc.h index 4ff2384d7ca..d12e8b59b11 100644 --- a/drivers/usb/chipidea/udc.h +++ b/drivers/usb/chipidea/udc.h @@ -40,7 +40,7 @@ struct ci13xxx_td {  #define TD_CURR_OFFSET        (0x0FFFUL <<  0)  #define TD_FRAME_NUM          (0x07FFUL <<  0)  #define TD_RESERVED_MASK      (0x0FFFUL <<  0) -} __attribute__ ((packed)); +} __attribute__ ((packed, aligned(4)));  /* DMA layout of queue heads */  struct ci13xxx_qh { @@ -57,7 +57,7 @@ struct ci13xxx_qh {  	/* 9 */  	u32 RESERVED;  	struct usb_ctrlrequest   setup; -} __attribute__ ((packed)); +} __attribute__ ((packed, aligned(4)));  /**   * struct ci13xxx_req - usb request representation diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c new file mode 100644 index 00000000000..714a6bd810e --- /dev/null +++ b/drivers/usb/chipidea/usbmisc_imx.c @@ -0,0 +1,261 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <linux/module.h> +#include <linux/of_platform.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/delay.h> + +#include "ci13xxx_imx.h" + +#define USB_DEV_MAX 4 + +#define MX25_USB_PHY_CTRL_OFFSET	0x08 +#define MX25_BM_EXTERNAL_VBUS_DIVIDER	BIT(23) + +#define MX53_USB_OTG_PHY_CTRL_0_OFFSET	0x08 +#define MX53_USB_UH2_CTRL_OFFSET	0x14 +#define MX53_USB_UH3_CTRL_OFFSET	0x18 +#define MX53_BM_OVER_CUR_DIS_H1		BIT(5) +#define MX53_BM_OVER_CUR_DIS_OTG	BIT(8) +#define MX53_BM_OVER_CUR_DIS_UHx	BIT(30) + +#define MX6_BM_OVER_CUR_DIS		BIT(7) + +struct imx_usbmisc { +	void __iomem *base; +	spinlock_t lock; +	struct clk *clk; +	struct usbmisc_usb_device usbdev[USB_DEV_MAX]; +	const struct usbmisc_ops *ops; +}; + +static struct imx_usbmisc *usbmisc; + +static struct usbmisc_usb_device *get_usbdev(struct device *dev) +{ +	int i, ret; + +	for (i = 0; i < USB_DEV_MAX; i++) { +		if (usbmisc->usbdev[i].dev == dev) +			return &usbmisc->usbdev[i]; +		else if (!usbmisc->usbdev[i].dev) +			break; +	} + +	if (i >= USB_DEV_MAX) +		return ERR_PTR(-EBUSY); + +	ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]); +	if (ret) +		return ERR_PTR(ret); + +	return &usbmisc->usbdev[i]; +} + +static int usbmisc_imx25_post(struct device *dev) +{ +	struct usbmisc_usb_device *usbdev; +	void __iomem *reg; +	unsigned long flags; +	u32 val; + +	usbdev = get_usbdev(dev); +	if (IS_ERR(usbdev)) +		return PTR_ERR(usbdev); + +	reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET; + +	if (usbdev->evdo) { +		spin_lock_irqsave(&usbmisc->lock, flags); +		val = readl(reg); +		writel(val | MX25_BM_EXTERNAL_VBUS_DIVIDER, reg); +		spin_unlock_irqrestore(&usbmisc->lock, flags); +		usleep_range(5000, 10000); /* needed to stabilize voltage */ +	} + +	return 0; +} + +static int usbmisc_imx53_init(struct device *dev) +{ +	struct usbmisc_usb_device *usbdev; +	void __iomem *reg = NULL; +	unsigned long flags; +	u32 val = 0; + +	usbdev = get_usbdev(dev); +	if (IS_ERR(usbdev)) +		return PTR_ERR(usbdev); + +	if (usbdev->disable_oc) { +		spin_lock_irqsave(&usbmisc->lock, flags); +		switch (usbdev->index) { +		case 0: +			reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET; +			val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG; +			break; +		case 1: +			reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET; +			val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1; +			break; +		case 2: +			reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET; +			val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx; +			break; +		case 3: +			reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET; +			val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx; +			break; +		} +		if (reg && val) +			writel(val, reg); +		spin_unlock_irqrestore(&usbmisc->lock, flags); +	} + +	return 0; +} + +static int usbmisc_imx6q_init(struct device *dev) +{ + +	struct usbmisc_usb_device *usbdev; +	unsigned long flags; +	u32 reg; + +	usbdev = get_usbdev(dev); +	if (IS_ERR(usbdev)) +		return PTR_ERR(usbdev); + +	if (usbdev->disable_oc) { +		spin_lock_irqsave(&usbmisc->lock, flags); +		reg = readl(usbmisc->base + usbdev->index * 4); +		writel(reg | MX6_BM_OVER_CUR_DIS, +			usbmisc->base + usbdev->index * 4); +		spin_unlock_irqrestore(&usbmisc->lock, flags); +	} + +	return 0; +} + +static const struct usbmisc_ops imx25_usbmisc_ops = { +	.post = usbmisc_imx25_post, +}; + +static const struct usbmisc_ops imx53_usbmisc_ops = { +	.init = usbmisc_imx53_init, +}; + +static const struct usbmisc_ops imx6q_usbmisc_ops = { +	.init = usbmisc_imx6q_init, +}; + +static const struct of_device_id usbmisc_imx_dt_ids[] = { +	{ +		.compatible = "fsl,imx25-usbmisc", +		.data = &imx25_usbmisc_ops, +	}, +	{ +		.compatible = "fsl,imx53-usbmisc", +		.data = &imx53_usbmisc_ops, +	}, +	{ +		.compatible = "fsl,imx6q-usbmisc", +		.data = &imx6q_usbmisc_ops, +	}, +	{ /* sentinel */ } +}; + +static int usbmisc_imx_probe(struct platform_device *pdev) +{ +	struct resource	*res; +	struct imx_usbmisc *data; +	int ret; +	struct of_device_id *tmp_dev; + +	if (usbmisc) +		return -EBUSY; + +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); +	if (!data) +		return -ENOMEM; + +	spin_lock_init(&data->lock); + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	data->base = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(data->base)) +		return PTR_ERR(data->base); + +	data->clk = devm_clk_get(&pdev->dev, NULL); +	if (IS_ERR(data->clk)) { +		dev_err(&pdev->dev, +			"failed to get clock, err=%ld\n", PTR_ERR(data->clk)); +		return PTR_ERR(data->clk); +	} + +	ret = clk_prepare_enable(data->clk); +	if (ret) { +		dev_err(&pdev->dev, +			"clk_prepare_enable failed, err=%d\n", ret); +		return ret; +	} + +	tmp_dev = (struct of_device_id *) +		of_match_device(usbmisc_imx_dt_ids, &pdev->dev); +	data->ops = (const struct usbmisc_ops *)tmp_dev->data; +	usbmisc = data; +	ret = usbmisc_set_ops(data->ops); +	if (ret) { +		usbmisc = NULL; +		clk_disable_unprepare(data->clk); +		return ret; +	} + +	return 0; +} + +static int usbmisc_imx_remove(struct platform_device *pdev) +{ +	usbmisc_unset_ops(usbmisc->ops); +	clk_disable_unprepare(usbmisc->clk); +	usbmisc = NULL; +	return 0; +} + +static struct platform_driver usbmisc_imx_driver = { +	.probe = usbmisc_imx_probe, +	.remove = usbmisc_imx_remove, +	.driver = { +		.name = "usbmisc_imx", +		.owner = THIS_MODULE, +		.of_match_table = usbmisc_imx_dt_ids, +	 }, +}; + +int usbmisc_imx_drv_init(void) +{ +	return platform_driver_register(&usbmisc_imx_driver); +} +subsys_initcall(usbmisc_imx_drv_init); + +void usbmisc_imx_drv_exit(void) +{ +	platform_driver_unregister(&usbmisc_imx_driver); +} +module_exit(usbmisc_imx_drv_exit); + +MODULE_ALIAS("platform:usbmisc-imx"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("driver for imx usb non-core registers"); +MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); diff --git a/drivers/usb/chipidea/usbmisc_imx6q.c b/drivers/usb/chipidea/usbmisc_imx6q.c deleted file mode 100644 index a1bce391e82..00000000000 --- a/drivers/usb/chipidea/usbmisc_imx6q.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2012 Freescale Semiconductor, Inc. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include <linux/module.h> -#include <linux/of_platform.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/io.h> - -#include "ci13xxx_imx.h" - -#define USB_DEV_MAX 4 - -#define BM_OVER_CUR_DIS		BIT(7) - -struct imx6q_usbmisc { -	void __iomem *base; -	spinlock_t lock; -	struct clk *clk; -	struct usbmisc_usb_device usbdev[USB_DEV_MAX]; -}; - -static struct imx6q_usbmisc *usbmisc; - -static struct usbmisc_usb_device *get_usbdev(struct device *dev) -{ -	int i, ret; - -	for (i = 0; i < USB_DEV_MAX; i++) { -		if (usbmisc->usbdev[i].dev == dev) -			return &usbmisc->usbdev[i]; -		else if (!usbmisc->usbdev[i].dev) -			break; -	} - -	if (i >= USB_DEV_MAX) -		return ERR_PTR(-EBUSY); - -	ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]); -	if (ret) -		return ERR_PTR(ret); - -	return &usbmisc->usbdev[i]; -} - -static int usbmisc_imx6q_init(struct device *dev) -{ - -	struct usbmisc_usb_device *usbdev; -	unsigned long flags; -	u32 reg; - -	usbdev = get_usbdev(dev); -	if (IS_ERR(usbdev)) -		return PTR_ERR(usbdev); - -	if (usbdev->disable_oc) { -		spin_lock_irqsave(&usbmisc->lock, flags); -		reg = readl(usbmisc->base + usbdev->index * 4); -		writel(reg | BM_OVER_CUR_DIS, -			usbmisc->base + usbdev->index * 4); -		spin_unlock_irqrestore(&usbmisc->lock, flags); -	} - -	return 0; -} - -static const struct usbmisc_ops imx6q_usbmisc_ops = { -	.init = usbmisc_imx6q_init, -}; - -static const struct of_device_id usbmisc_imx6q_dt_ids[] = { -	{ .compatible = "fsl,imx6q-usbmisc"}, -	{ /* sentinel */ } -}; - -static int usbmisc_imx6q_probe(struct platform_device *pdev) -{ -	struct resource	*res; -	struct imx6q_usbmisc *data; -	int ret; - -	if (usbmisc) -		return -EBUSY; - -	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); -	if (!data) -		return -ENOMEM; - -	spin_lock_init(&data->lock); - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	data->base = devm_ioremap_resource(&pdev->dev, res); -	if (IS_ERR(data->base)) -		return PTR_ERR(data->base); - -	data->clk = devm_clk_get(&pdev->dev, NULL); -	if (IS_ERR(data->clk)) { -		dev_err(&pdev->dev, -			"failed to get clock, err=%ld\n", PTR_ERR(data->clk)); -		return PTR_ERR(data->clk); -	} - -	ret = clk_prepare_enable(data->clk); -	if (ret) { -		dev_err(&pdev->dev, -			"clk_prepare_enable failed, err=%d\n", ret); -		return ret; -	} - -	ret = usbmisc_set_ops(&imx6q_usbmisc_ops); -	if (ret) { -		clk_disable_unprepare(data->clk); -		return ret; -	} - -	usbmisc = data; - -	return 0; -} - -static int usbmisc_imx6q_remove(struct platform_device *pdev) -{ -	usbmisc_unset_ops(&imx6q_usbmisc_ops); -	clk_disable_unprepare(usbmisc->clk); -	return 0; -} - -static struct platform_driver usbmisc_imx6q_driver = { -	.probe = usbmisc_imx6q_probe, -	.remove = usbmisc_imx6q_remove, -	.driver = { -		.name = "usbmisc_imx6q", -		.owner = THIS_MODULE, -		.of_match_table = usbmisc_imx6q_dt_ids, -	 }, -}; - -int __init usbmisc_imx6q_drv_init(void) -{ -	return platform_driver_register(&usbmisc_imx6q_driver); -} -subsys_initcall(usbmisc_imx6q_drv_init); - -void __exit usbmisc_imx6q_drv_exit(void) -{ -	platform_driver_unregister(&usbmisc_imx6q_driver); -} -module_exit(usbmisc_imx6q_drv_exit); - -MODULE_ALIAS("platform:usbmisc-imx6q"); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("driver for imx6q usb non-core registers"); -MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig index 316aac8e4ca..bb8b73682a7 100644 --- a/drivers/usb/class/Kconfig +++ b/drivers/usb/class/Kconfig @@ -2,11 +2,10 @@  # USB Class driver configuration  #  comment "USB Device Class drivers" -	depends on USB  config USB_ACM  	tristate "USB Modem (CDC ACM) support" -	depends on USB && TTY +	depends on TTY  	---help---  	  This driver supports USB modems and ISDN adapters which support the  	  Communication Device Class Abstract Control Model interface. @@ -21,7 +20,6 @@ config USB_ACM  config USB_PRINTER  	tristate "USB Printer support" -	depends on USB  	help  	  Say Y here if you want to connect a USB printer to your computer's  	  USB port. @@ -31,7 +29,6 @@ config USB_PRINTER  config USB_WDM  	tristate "USB Wireless Device Management support" -	depends on USB  	---help---  	  This driver supports the WMC Device Management functionality  	  of cell phones compliant to the CDC WMC specification. You can use @@ -42,7 +39,6 @@ config USB_WDM  config USB_TMC  	tristate "USB Test and Measurement Class support" -	depends on USB  	help  	  Say Y here if you want to connect a USB device that follows  	  the USB.org specification for USB Test and Measurement devices diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index cb8ef3ef5c9..9b1cbcf8fb7 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -292,7 +292,6 @@ static void acm_ctrl_irq(struct urb *urb)  {  	struct acm *acm = urb->context;  	struct usb_cdc_notification *dr = urb->transfer_buffer; -	struct tty_struct *tty;  	unsigned char *data;  	int newctrl;  	int retval; @@ -327,17 +326,12 @@ static void acm_ctrl_irq(struct urb *urb)  		break;  	case USB_CDC_NOTIFY_SERIAL_STATE: -		tty = tty_port_tty_get(&acm->port);  		newctrl = get_unaligned_le16(data); -		if (tty) { -			if (!acm->clocal && -				(acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { -				dev_dbg(&acm->control->dev, -					"%s - calling hangup\n", __func__); -				tty_hangup(tty); -			} -			tty_kref_put(tty); +		if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { +			dev_dbg(&acm->control->dev, "%s - calling hangup\n", +					__func__); +			tty_port_tty_hangup(&acm->port, false);  		}  		acm->ctrlin = newctrl; @@ -475,15 +469,10 @@ static void acm_write_bulk(struct urb *urb)  static void acm_softint(struct work_struct *work)  {  	struct acm *acm = container_of(work, struct acm, work); -	struct tty_struct *tty;  	dev_vdbg(&acm->data->dev, "%s\n", __func__); -	tty = tty_port_tty_get(&acm->port); -	if (!tty) -		return; -	tty_wakeup(tty); -	tty_kref_put(tty); +	tty_port_tty_wakeup(&acm->port);  }  /* @@ -593,7 +582,6 @@ static void acm_port_destruct(struct tty_port *port)  	dev_dbg(&acm->control->dev, "%s\n", __func__); -	tty_unregister_device(acm_tty_driver, acm->minor);  	acm_release_minor(acm);  	usb_put_intf(acm->control);  	kfree(acm->country_codes); @@ -840,14 +828,6 @@ static int acm_tty_ioctl(struct tty_struct *tty,  	return rv;  } -static const __u32 acm_tty_speed[] = { -	0, 50, 75, 110, 134, 150, 200, 300, 600, -	1200, 1800, 2400, 4800, 9600, 19200, 38400, -	57600, 115200, 230400, 460800, 500000, 576000, -	921600, 1000000, 1152000, 1500000, 2000000, -	2500000, 3000000, 3500000, 4000000 -}; -  static void acm_tty_set_termios(struct tty_struct *tty,  						struct ktermios *termios_old)  { @@ -977,6 +957,8 @@ static int acm_probe(struct usb_interface *intf,  	int num_rx_buf;  	int i;  	int combined_interfaces = 0; +	struct device *tty_dev; +	int rv = -ENOMEM;  	/* normal quirks */  	quirks = (unsigned long)id->driver_info; @@ -1343,11 +1325,24 @@ skip_countries:  	usb_set_intfdata(data_interface, acm);  	usb_get_intf(control_interface); -	tty_port_register_device(&acm->port, acm_tty_driver, minor, +	tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor,  			&control_interface->dev); +	if (IS_ERR(tty_dev)) { +		rv = PTR_ERR(tty_dev); +		goto alloc_fail8; +	}  	return 0; +alloc_fail8: +	if (acm->country_codes) { +		device_remove_file(&acm->control->dev, +				&dev_attr_wCountryCodes); +		device_remove_file(&acm->control->dev, +				&dev_attr_iCountryCodeRelDate); +	} +	device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities);  alloc_fail7: +	usb_set_intfdata(intf, NULL);  	for (i = 0; i < ACM_NW; i++)  		usb_free_urb(acm->wb[i].urb);  alloc_fail6: @@ -1363,7 +1358,7 @@ alloc_fail2:  	acm_release_minor(acm);  	kfree(acm);  alloc_fail: -	return -ENOMEM; +	return rv;  }  static void stop_data_traffic(struct acm *acm) @@ -1415,6 +1410,8 @@ static void acm_disconnect(struct usb_interface *intf)  	stop_data_traffic(acm); +	tty_unregister_device(acm_tty_driver, acm->minor); +  	usb_free_urb(acm->ctrlurb);  	for (i = 0; i < ACM_NW; i++)  		usb_free_urb(acm->wb[i].urb); @@ -1507,15 +1504,9 @@ err_out:  static int acm_reset_resume(struct usb_interface *intf)  {  	struct acm *acm = usb_get_intfdata(intf); -	struct tty_struct *tty; -	if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) { -		tty = tty_port_tty_get(&acm->port); -		if (tty) { -			tty_hangup(tty); -			tty_kref_put(tty); -		} -	} +	if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) +		tty_port_tty_hangup(&acm->port, false);  	return acm_resume(intf);  } diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 122d056d96d..8a230f0ef77 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -13,6 +13,7 @@   */  #include <linux/kernel.h>  #include <linux/errno.h> +#include <linux/ioctl.h>  #include <linux/slab.h>  #include <linux/module.h>  #include <linux/mutex.h> @@ -644,6 +645,22 @@ static int wdm_release(struct inode *inode, struct file *file)  	return 0;  } +static long wdm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ +	struct wdm_device *desc = file->private_data; +	int rv = 0; + +	switch (cmd) { +	case IOCTL_WDM_MAX_COMMAND: +		if (copy_to_user((void __user *)arg, &desc->wMaxCommand, sizeof(desc->wMaxCommand))) +			rv = -EFAULT; +		break; +	default: +		rv = -ENOTTY; +	} +	return rv; +} +  static const struct file_operations wdm_fops = {  	.owner =	THIS_MODULE,  	.read =		wdm_read, @@ -652,6 +669,8 @@ static const struct file_operations wdm_fops = {  	.flush =	wdm_flush,  	.release =	wdm_release,  	.poll =		wdm_poll, +	.unlocked_ioctl = wdm_ioctl, +	.compat_ioctl = wdm_ioctl,  	.llseek =	noop_llseek,  }; diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 70d69d06054..4c5506ae5e4 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -718,50 +718,32 @@ exit:  static int usbtmc_ioctl_clear_out_halt(struct usbtmc_device_data *data)  { -	u8 *buffer;  	int rv; -	buffer = kmalloc(2, GFP_KERNEL); -	if (!buffer) -		return -ENOMEM; -  	rv = usb_clear_halt(data->usb_dev,  			    usb_sndbulkpipe(data->usb_dev, data->bulk_out));  	if (rv < 0) {  		dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n",  			rv); -		goto exit; +		return rv;  	} -	rv = 0; - -exit: -	kfree(buffer); -	return rv; +	return 0;  }  static int usbtmc_ioctl_clear_in_halt(struct usbtmc_device_data *data)  { -	u8 *buffer;  	int rv; -	buffer = kmalloc(2, GFP_KERNEL); -	if (!buffer) -		return -ENOMEM; -  	rv = usb_clear_halt(data->usb_dev,  			    usb_rcvbulkpipe(data->usb_dev, data->bulk_in));  	if (rv < 0) {  		dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n",  			rv); -		goto exit; +		return rv;  	} -	rv = 0; - -exit: -	kfree(buffer); -	return rv; +	return 0;  }  static int get_capabilities(struct usbtmc_device_data *data) diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index f70c1a1694a..8772b365929 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -3,7 +3,6 @@  #  config USB_DEBUG  	bool "USB verbose debug messages" -	depends on USB  	help  	  Say Y here if you want the USB core & hub drivers to produce a bunch  	  of debug messages to the system log. Select this if you are having a @@ -11,7 +10,6 @@ config USB_DEBUG  config USB_ANNOUNCE_NEW_DEVICES  	bool "USB announce new devices" -	depends on USB  	default N  	help  	  Say Y here if you want the USB core to always announce the @@ -25,11 +23,24 @@ config USB_ANNOUNCE_NEW_DEVICES  	  log, or have any doubts about this, say N here.  comment "Miscellaneous USB options" -	depends on USB + +config USB_DEFAULT_PERSIST +	bool "Enable USB persist by default" +	default y +	help +	  Say N here if you don't want USB power session persistance +	  enabled by default.  If you say N it will make suspended USB +	  devices that lose power get reenumerated as if they had been +	  unplugged, causing any mounted filesystems to be lost.  The +	  persist feature can still be enabled for individual devices +	  through the power/persist sysfs node. See +	  Documentation/usb/persist.txt for more info. + +	  If you have any questions about this, say Y here, only say N +	  if you know exactly what you are doing.  config USB_DYNAMIC_MINORS  	bool "Dynamic USB minor allocation" -	depends on USB  	help  	  If you say Y here, the USB subsystem will use dynamic minor  	  allocation for any device that uses the USB major number. @@ -38,25 +49,8 @@ config USB_DYNAMIC_MINORS  	  If you are unsure about this, say N here. -config USB_SUSPEND -	bool "USB runtime power management (autosuspend) and wakeup" -	depends on USB && PM_RUNTIME -	help -	  If you say Y here, you can use driver calls or the sysfs -	  "power/control" file to enable or disable autosuspend for -	  individual USB peripherals (see -	  Documentation/usb/power-management.txt for more details). - -	  Also, USB "remote wakeup" signaling is supported, whereby some -	  USB devices (like keyboards and network adapters) can wake up -	  their parent hub.  That wakeup cascades up the USB tree, and -	  could wake the system from states like suspend-to-RAM. - -	  If you are unsure about this, say N here. -  config USB_OTG  	bool "OTG support" -	depends on USB  	depends on USB_SUSPEND  	default n  	help diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 8823e98989f..caefc800f29 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -739,6 +739,8 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,  	index &= 0xff;  	switch (requesttype & USB_RECIP_MASK) {  	case USB_RECIP_ENDPOINT: +		if ((index & ~USB_DIR_IN) == 0) +			return 0;  		ret = findintfep(ps->dev, index);  		if (ret >= 0)  			ret = checkintf(ps, ret); diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index d938b2b99e3..6eab440e154 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1196,9 +1196,14 @@ done:   *   * This is the central routine for suspending USB devices.  It calls the   * suspend methods for all the interface drivers in @udev and then calls - * the suspend method for @udev itself.  If an error occurs at any stage, - * all the interfaces which were suspended are resumed so that they remain - * in the same state as the device. + * the suspend method for @udev itself.  When the routine is called in + * autosuspend, if an error occurs at any stage, all the interfaces + * which were suspended are resumed so that they remain in the same + * state as the device, but when called from system sleep, all error + * from suspend methods of interfaces and the non-root-hub device itself + * are simply ignored, so all suspended interfaces are only resumed + * to the device's state when @udev is root-hub and its suspend method + * returns failure.   *   * Autosuspend requests originating from a child device or an interface   * driver may be made without the protection of @udev's device lock, but @@ -1248,10 +1253,12 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)  	/* If the suspend failed, resume interfaces that did get suspended */  	if (status != 0) { -		msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME); -		while (++i < n) { -			intf = udev->actconfig->interface[i]; -			usb_resume_interface(udev, intf, msg, 0); +		if (udev->actconfig) { +			msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME); +			while (++i < n) { +				intf = udev->actconfig->interface[i]; +				usb_resume_interface(udev, intf, msg, 0); +			}  		}  	/* If the suspend succeeded then prevent any more URB submissions @@ -1407,7 +1414,7 @@ int usb_resume(struct device *dev, pm_message_t msg)  #endif /* CONFIG_PM */ -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM_RUNTIME  /**   * usb_enable_autosuspend - allow a USB device to be autosuspended @@ -1775,7 +1782,7 @@ int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)  	return ret;  } -#endif /* CONFIG_USB_SUSPEND */ +#endif /* CONFIG_PM_RUNTIME */  struct bus_type usb_bus_type = {  	.name =		"usb", diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 271e761f563..acbfeb0a011 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -169,7 +169,7 @@ static int generic_probe(struct usb_device *udev)  		c = usb_choose_configuration(udev);  		if (c >= 0) {  			err = usb_set_configuration(udev, c); -			if (err) { +			if (err && err != -ENODEV) {  				dev_err(&udev->dev, "can't set config #%d, error %d\n",  					c, err);  				/* This need not be fatal.  The user can try to diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 622b4a48e73..caeb8d6d39f 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -37,119 +37,123 @@  /* PCI-based HCs are common, but plenty of non-PCI HCs are used too */ -#ifdef CONFIG_PM_SLEEP - -/* Coordinate handoffs between EHCI and companion controllers - * during system resume +/* + * Coordinate handoffs between EHCI and companion controllers + * during EHCI probing and system resume.   */ -static DEFINE_MUTEX(companions_mutex); +static DECLARE_RWSEM(companions_rwsem);  #define CL_UHCI		PCI_CLASS_SERIAL_USB_UHCI  #define CL_OHCI		PCI_CLASS_SERIAL_USB_OHCI  #define CL_EHCI		PCI_CLASS_SERIAL_USB_EHCI -enum companion_action { -	SET_HS_COMPANION, CLEAR_HS_COMPANION, WAIT_FOR_COMPANIONS -}; +static inline int is_ohci_or_uhci(struct pci_dev *pdev) +{ +	return pdev->class == CL_OHCI || pdev->class == CL_UHCI; +} + +typedef void (*companion_fn)(struct pci_dev *pdev, struct usb_hcd *hcd, +		struct pci_dev *companion, struct usb_hcd *companion_hcd); -static void companion_common(struct pci_dev *pdev, struct usb_hcd *hcd, -		enum companion_action action) +/* Iterate over PCI devices in the same slot as pdev and call fn for each */ +static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd, +		companion_fn fn)  {  	struct pci_dev		*companion;  	struct usb_hcd		*companion_hcd;  	unsigned int		slot = PCI_SLOT(pdev->devfn); -	/* Iterate through other PCI functions in the same slot. -	 * If pdev is OHCI or UHCI then we are looking for EHCI, and -	 * vice versa. +	/* +	 * Iterate through other PCI functions in the same slot. +	 * If the function's drvdata isn't set then it isn't bound to +	 * a USB host controller driver, so skip it.  	 */  	companion = NULL;  	for_each_pci_dev(companion) {  		if (companion->bus != pdev->bus ||  				PCI_SLOT(companion->devfn) != slot)  			continue; -  		companion_hcd = pci_get_drvdata(companion);  		if (!companion_hcd)  			continue; - -		/* For SET_HS_COMPANION, store a pointer to the EHCI bus in -		 * the OHCI/UHCI companion bus structure. -		 * For CLEAR_HS_COMPANION, clear the pointer to the EHCI bus -		 * in the OHCI/UHCI companion bus structure. -		 * For WAIT_FOR_COMPANIONS, wait until the OHCI/UHCI -		 * companion controllers have fully resumed. -		 */ - -		if ((pdev->class == CL_OHCI || pdev->class == CL_UHCI) && -				companion->class == CL_EHCI) { -			/* action must be SET_HS_COMPANION */ -			dev_dbg(&companion->dev, "HS companion for %s\n", -					dev_name(&pdev->dev)); -			hcd->self.hs_companion = &companion_hcd->self; - -		} else if (pdev->class == CL_EHCI && -				(companion->class == CL_OHCI || -				companion->class == CL_UHCI)) { -			switch (action) { -			case SET_HS_COMPANION: -				dev_dbg(&pdev->dev, "HS companion for %s\n", -						dev_name(&companion->dev)); -				companion_hcd->self.hs_companion = &hcd->self; -				break; -			case CLEAR_HS_COMPANION: -				companion_hcd->self.hs_companion = NULL; -				break; -			case WAIT_FOR_COMPANIONS: -				device_pm_wait_for_dev(&pdev->dev, -						&companion->dev); -				break; -			} -		} +		fn(pdev, hcd, companion, companion_hcd);  	}  } -static void set_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd) +/* + * We're about to add an EHCI controller, which will unceremoniously grab + * all the port connections away from its companions.  To prevent annoying + * error messages, lock the companion's root hub and gracefully unconfigure + * it beforehand.  Leave it locked until the EHCI controller is all set. + */ +static void ehci_pre_add(struct pci_dev *pdev, struct usb_hcd *hcd, +		struct pci_dev *companion, struct usb_hcd *companion_hcd)  { -	mutex_lock(&companions_mutex); -	dev_set_drvdata(&pdev->dev, hcd); -	companion_common(pdev, hcd, SET_HS_COMPANION); -	mutex_unlock(&companions_mutex); +	struct usb_device *udev; + +	if (is_ohci_or_uhci(companion)) { +		udev = companion_hcd->self.root_hub; +		usb_lock_device(udev); +		usb_set_configuration(udev, 0); +	}  } -static void clear_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd) +/* + * Adding the EHCI controller has either succeeded or failed.  Set the + * companion pointer accordingly, and in either case, reconfigure and + * unlock the root hub. + */ +static void ehci_post_add(struct pci_dev *pdev, struct usb_hcd *hcd, +		struct pci_dev *companion, struct usb_hcd *companion_hcd)  { -	mutex_lock(&companions_mutex); -	dev_set_drvdata(&pdev->dev, NULL); +	struct usb_device *udev; -	/* If pdev is OHCI or UHCI, just clear its hs_companion pointer */ -	if (pdev->class == CL_OHCI || pdev->class == CL_UHCI) -		hcd->self.hs_companion = NULL; +	if (is_ohci_or_uhci(companion)) { +		if (dev_get_drvdata(&pdev->dev)) {	/* Succeeded */ +			dev_dbg(&pdev->dev, "HS companion for %s\n", +					dev_name(&companion->dev)); +			companion_hcd->self.hs_companion = &hcd->self; +		} +		udev = companion_hcd->self.root_hub; +		usb_set_configuration(udev, 1); +		usb_unlock_device(udev); +	} +} -	/* Otherwise search for companion buses and clear their pointers */ -	else -		companion_common(pdev, hcd, CLEAR_HS_COMPANION); -	mutex_unlock(&companions_mutex); +/* + * We just added a non-EHCI controller.  Find the EHCI controller to + * which it is a companion, and store a pointer to the bus structure. + */ +static void non_ehci_add(struct pci_dev *pdev, struct usb_hcd *hcd, +		struct pci_dev *companion, struct usb_hcd *companion_hcd) +{ +	if (is_ohci_or_uhci(pdev) && companion->class == CL_EHCI) { +		dev_dbg(&pdev->dev, "FS/LS companion for %s\n", +				dev_name(&companion->dev)); +		hcd->self.hs_companion = &companion_hcd->self; +	}  } -static void wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd) +/* We are removing an EHCI controller.  Clear the companions' pointers. */ +static void ehci_remove(struct pci_dev *pdev, struct usb_hcd *hcd, +		struct pci_dev *companion, struct usb_hcd *companion_hcd)  { -	/* Only EHCI controllers need to wait. -	 * No locking is needed because a controller cannot be resumed -	 * while one of its companions is getting unbound. -	 */ -	if (pdev->class == CL_EHCI) -		companion_common(pdev, hcd, WAIT_FOR_COMPANIONS); +	if (is_ohci_or_uhci(companion)) +		companion_hcd->self.hs_companion = NULL;  } -#else /* !CONFIG_PM_SLEEP */ +#ifdef	CONFIG_PM -static inline void set_hs_companion(struct pci_dev *d, struct usb_hcd *h) {} -static inline void clear_hs_companion(struct pci_dev *d, struct usb_hcd *h) {} -static inline void wait_for_companions(struct pci_dev *d, struct usb_hcd *h) {} +/* An EHCI controller must wait for its companions before resuming. */ +static void ehci_wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd, +		struct pci_dev *companion, struct usb_hcd *companion_hcd) +{ +	if (is_ohci_or_uhci(companion)) +		device_pm_wait_for_dev(&pdev->dev, &companion->dev); +} -#endif /* !CONFIG_PM_SLEEP */ +#endif	/* CONFIG_PM */  /*-------------------------------------------------------------------------*/ @@ -173,6 +177,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)  	struct hc_driver	*driver;  	struct usb_hcd		*hcd;  	int			retval; +	int			hcd_irq = 0;  	if (usb_disabled())  		return -ENODEV; @@ -187,15 +192,19 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)  		return -ENODEV;  	dev->current_state = PCI_D0; -	/* The xHCI driver supports MSI and MSI-X, -	 * so don't fail if the BIOS doesn't provide a legacy IRQ. +	/* +	 * The xHCI driver has its own irq management +	 * make sure irq setup is not touched for xhci in generic hcd code  	 */ -	if (!dev->irq && (driver->flags & HCD_MASK) != HCD_USB3) { -		dev_err(&dev->dev, -			"Found HC with no IRQ.  Check BIOS/PCI %s setup!\n", -			pci_name(dev)); -		retval = -ENODEV; -		goto disable_pci; +	if ((driver->flags & HCD_MASK) != HCD_USB3) { +		if (!dev->irq) { +			dev_err(&dev->dev, +			"Found HC with no IRQ. Check BIOS/PCI %s setup!\n", +				pci_name(dev)); +			retval = -ENODEV; +			goto disable_pci; +		} +		hcd_irq = dev->irq;  	}  	hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev)); @@ -212,7 +221,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)  				driver->description)) {  			dev_dbg(&dev->dev, "controller already in use\n");  			retval = -EBUSY; -			goto clear_companion; +			goto put_hcd;  		}  		hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);  		if (hcd->regs == NULL) { @@ -239,16 +248,35 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)  		if (region == PCI_ROM_RESOURCE) {  			dev_dbg(&dev->dev, "no i/o regions available\n");  			retval = -EBUSY; -			goto clear_companion; +			goto put_hcd;  		}  	}  	pci_set_master(dev); -	retval = usb_add_hcd(hcd, dev->irq, IRQF_SHARED); +	/* Note: dev_set_drvdata must be called while holding the rwsem */ +	if (dev->class == CL_EHCI) { +		down_write(&companions_rwsem); +		dev_set_drvdata(&dev->dev, hcd); +		for_each_companion(dev, hcd, ehci_pre_add); +		retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED); +		if (retval != 0) +			dev_set_drvdata(&dev->dev, NULL); +		for_each_companion(dev, hcd, ehci_post_add); +		up_write(&companions_rwsem); +	} else { +		down_read(&companions_rwsem); +		dev_set_drvdata(&dev->dev, hcd); +		retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED); +		if (retval != 0) +			dev_set_drvdata(&dev->dev, NULL); +		else +			for_each_companion(dev, hcd, non_ehci_add); +		up_read(&companions_rwsem); +	} +  	if (retval != 0)  		goto unmap_registers; -	set_hs_companion(dev, hcd);  	if (pci_dev_run_wake(dev))  		pm_runtime_put_noidle(&dev->dev); @@ -261,8 +289,7 @@ release_mem_region:  		release_mem_region(hcd->rsrc_start, hcd->rsrc_len);  	} else  		release_region(hcd->rsrc_start, hcd->rsrc_len); -clear_companion: -	clear_hs_companion(dev, hcd); +put_hcd:  	usb_put_hcd(hcd);  disable_pci:  	pci_disable_device(dev); @@ -305,14 +332,29 @@ void usb_hcd_pci_remove(struct pci_dev *dev)  	usb_hcd_irq(0, hcd);  	local_irq_enable(); -	usb_remove_hcd(hcd); +	/* Note: dev_set_drvdata must be called while holding the rwsem */ +	if (dev->class == CL_EHCI) { +		down_write(&companions_rwsem); +		for_each_companion(dev, hcd, ehci_remove); +		usb_remove_hcd(hcd); +		dev_set_drvdata(&dev->dev, NULL); +		up_write(&companions_rwsem); +	} else { +		/* Not EHCI; just clear the companion pointer */ +		down_read(&companions_rwsem); +		hcd->self.hs_companion = NULL; +		usb_remove_hcd(hcd); +		dev_set_drvdata(&dev->dev, NULL); +		up_read(&companions_rwsem); +	} +  	if (hcd->driver->flags & HCD_MEMORY) {  		iounmap(hcd->regs);  		release_mem_region(hcd->rsrc_start, hcd->rsrc_len);  	} else {  		release_region(hcd->rsrc_start, hcd->rsrc_len);  	} -	clear_hs_companion(dev, hcd); +  	usb_put_hcd(hcd);  	pci_disable_device(dev);  } @@ -458,8 +500,15 @@ static int resume_common(struct device *dev, int event)  	pci_set_master(pci_dev);  	if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) { -		if (event != PM_EVENT_AUTO_RESUME) -			wait_for_companions(pci_dev, hcd); + +		/* +		 * Only EHCI controllers have to wait for their companions. +		 * No locking is needed because PCI controller drivers do not +		 * get unbound during system resume. +		 */ +		if (pci_dev->class == CL_EHCI && event != PM_EVENT_AUTO_RESUME) +			for_each_companion(pci_dev, hcd, +					ehci_wait_for_companions);  		retval = hcd->driver->pci_resume(hcd,  				event == PM_EVENT_RESTORE); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 99b34a30354..d53547d2e4c 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2125,7 +2125,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)  #endif	/* CONFIG_PM */ -#ifdef	CONFIG_USB_SUSPEND +#ifdef	CONFIG_PM_RUNTIME  /* Workqueue routine for root-hub remote wakeup */  static void hcd_resume_work(struct work_struct *work) @@ -2160,7 +2160,7 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)  }  EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub); -#endif	/* CONFIG_USB_SUSPEND */ +#endif	/* CONFIG_PM_RUNTIME */  /*-------------------------------------------------------------------------*/ @@ -2336,7 +2336,7 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,  	init_timer(&hcd->rh_timer);  	hcd->rh_timer.function = rh_timer_func;  	hcd->rh_timer.data = (unsigned long) hcd; -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM_RUNTIME  	INIT_WORK(&hcd->wakeup_work, hcd_resume_work);  #endif @@ -2412,6 +2412,14 @@ int usb_hcd_is_primary_hcd(struct usb_hcd *hcd)  }  EXPORT_SYMBOL_GPL(usb_hcd_is_primary_hcd); +int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1) +{ +	if (!hcd->driver->find_raw_port_number) +		return port1; + +	return hcd->driver->find_raw_port_number(hcd, port1); +} +  static int usb_hcd_request_irqs(struct usb_hcd *hcd,  		unsigned int irqnum, unsigned long irqflags)  { @@ -2582,7 +2590,7 @@ error_create_attr_group:  	hcd->rh_registered = 0;  	spin_unlock_irq(&hcd_root_hub_lock); -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM_RUNTIME  	cancel_work_sync(&hcd->wakeup_work);  #endif  	mutex_lock(&usb_bus_list_lock); @@ -2637,7 +2645,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)  	hcd->rh_registered = 0;  	spin_unlock_irq (&hcd_root_hub_lock); -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM_RUNTIME  	cancel_work_sync(&hcd->wakeup_work);  #endif diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 5480352f984..feef9351463 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -555,8 +555,9 @@ static int hub_port_status(struct usb_hub *hub, int port1,  	mutex_lock(&hub->status_mutex);  	ret = get_port_status(hub->hdev, port1, &hub->status->port);  	if (ret < 4) { -		dev_err(hub->intfdev, -			"%s failed (err = %d)\n", __func__, ret); +		if (ret != -ENODEV) +			dev_err(hub->intfdev, +				"%s failed (err = %d)\n", __func__, ret);  		if (ret >= 0)  			ret = -EIO;  	} else { @@ -699,7 +700,7 @@ static void hub_tt_work(struct work_struct *work)  		/* drop lock so HCD can concurrently report other TT errors */  		spin_unlock_irqrestore (&hub->tt.lock, flags);  		status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt); -		if (status) +		if (status && status != -ENODEV)  			dev_err (&hdev->dev,  				"clear tt %d (%04x) error %d\n",  				clear->tt, clear->devinfo, status); @@ -837,10 +838,11 @@ static int hub_hub_status(struct usb_hub *hub,  	mutex_lock(&hub->status_mutex);  	ret = get_hub_status(hub->hdev, &hub->status->hub); -	if (ret < 0) -		dev_err (hub->intfdev, -			"%s failed (err = %d)\n", __func__, ret); -	else { +	if (ret < 0) { +		if (ret != -ENODEV) +			dev_err(hub->intfdev, +				"%s failed (err = %d)\n", __func__, ret); +	} else {  		*status = le16_to_cpu(hub->status->hub.wHubStatus);  		*change = le16_to_cpu(hub->status->hub.wHubChange);   		ret = 0; @@ -877,11 +879,8 @@ static int hub_usb3_port_disable(struct usb_hub *hub, int port1)  		return -EINVAL;  	ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED); -	if (ret) { -		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", -				port1, ret); +	if (ret)  		return ret; -	}  	/* Wait for the link to enter the disabled state. */  	for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) { @@ -918,7 +917,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)  			ret = usb_clear_port_feature(hdev, port1,  					USB_PORT_FEAT_ENABLE);  	} -	if (ret) +	if (ret && ret != -ENODEV)  		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",  				port1, ret);  	return ret; @@ -1317,6 +1316,10 @@ static int hub_configure(struct usb_hub *hub,  		message = "hub has too many ports!";  		ret = -ENODEV;  		goto fail; +	} else if (hub->descriptor->bNbrPorts == 0) { +		message = "hub doesn't have any ports!"; +		ret = -ENODEV; +		goto fail;  	}  	hdev->maxchild = hub->descriptor->bNbrPorts; @@ -2192,8 +2195,9 @@ static int usb_enumerate_device(struct usb_device *udev)  	if (udev->config == NULL) {  		err = usb_get_configuration(udev);  		if (err < 0) { -			dev_err(&udev->dev, "can't read configurations, error %d\n", -				err); +			if (err != -ENODEV) +				dev_err(&udev->dev, "can't read configurations, error %d\n", +						err);  			return err;  		}  	} @@ -2640,14 +2644,16 @@ static int hub_port_reset(struct usb_hub *hub, int port1,  		status = set_port_feature(hub->hdev, port1, (warm ?  					USB_PORT_FEAT_BH_PORT_RESET :  					USB_PORT_FEAT_RESET)); -		if (status) { +		if (status == -ENODEV) { +			;	/* The hub is gone */ +		} else if (status) {  			dev_err(hub->intfdev,  					"cannot %sreset port %d (err = %d)\n",  					warm ? "warm " : "", port1, status);  		} else {  			status = hub_port_wait_reset(hub, port1, udev, delay,  								warm); -			if (status && status != -ENOTCONN) +			if (status && status != -ENOTCONN && status != -ENODEV)  				dev_dbg(hub->intfdev,  						"port_wait_reset: err = %d\n",  						status); @@ -2821,7 +2827,7 @@ void usb_enable_ltm(struct usb_device *udev)  }  EXPORT_SYMBOL_GPL(usb_enable_ltm); -#ifdef	CONFIG_USB_SUSPEND +#ifdef	CONFIG_PM  /*   * usb_disable_function_remotewakeup - disable usb3.0   * device's function remote wakeup @@ -2880,9 +2886,11 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev)   * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd   * timer, no SRP, no requests through sysfs.   * - * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when - * the root hub for their bus goes into global suspend ... so we don't - * (falsely) update the device power state to say it suspended. + * If Runtime PM isn't enabled or used, non-SuperSpeed devices really get + * suspended only when their bus goes into global suspend (i.e., the root + * hub is suspended).  Nevertheless, we change @udev->state to + * USB_STATE_SUSPENDED as this is the device's "logical" state.  The actual + * upstream port setting is stored in @udev->port_is_suspended.   *   * Returns 0 on success, else negative errno.   */ @@ -2893,6 +2901,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)  	enum pm_qos_flags_status pm_qos_stat;  	int		port1 = udev->portnum;  	int		status; +	bool		really_suspend = true;  	/* enable remote wakeup when appropriate; this lets the device  	 * wake up the upstream hub (including maybe the root hub). @@ -2949,9 +2958,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)  	/* see 7.1.7.6 */  	if (hub_is_superspeed(hub->hdev))  		status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3); -	else +	else if (PMSG_IS_AUTO(msg))  		status = set_port_feature(hub->hdev, port1,  						USB_PORT_FEAT_SUSPEND); +	/* +	 * For system suspend, we do not need to enable the suspend feature +	 * on individual USB-2 ports.  The devices will automatically go +	 * into suspend a few ms after the root hub stops sending packets. +	 * The USB 2.0 spec calls this "global suspend". +	 */ +	else { +		really_suspend = false; +		status = 0; +	}  	if (status) {  		dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",  				port1, status); @@ -2987,8 +3006,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)  				(PMSG_IS_AUTO(msg) ? "auto-" : ""),  				udev->do_remote_wakeup);  		usb_set_device_state(udev, USB_STATE_SUSPENDED); -		udev->port_is_suspended = 1; -		msleep(10); +		if (really_suspend) { +			udev->port_is_suspended = 1; +			msleep(10); +		}  	}  	/* @@ -3226,6 +3247,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)  	return status;  } +#endif	/* CONFIG_PM */ + +#ifdef	CONFIG_PM_RUNTIME +  /* caller has locked udev */  int usb_remote_wakeup(struct usb_device *udev)  { @@ -3242,38 +3267,6 @@ int usb_remote_wakeup(struct usb_device *udev)  	return status;  } -#else	/* CONFIG_USB_SUSPEND */ - -/* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */ - -int usb_port_suspend(struct usb_device *udev, pm_message_t msg) -{ -	return 0; -} - -/* However we may need to do a reset-resume */ - -int usb_port_resume(struct usb_device *udev, pm_message_t msg) -{ -	struct usb_hub	*hub = usb_hub_to_struct_hub(udev->parent); -	int		port1 = udev->portnum; -	int		status; -	u16		portchange, portstatus; - -	status = hub_port_status(hub, port1, &portstatus, &portchange); -	status = check_port_resume_type(udev, -			hub, port1, status, portchange, portstatus); - -	if (status) { -		dev_dbg(&udev->dev, "can't resume, status %d\n", status); -		hub_port_logical_disconnect(hub, port1); -	} else if (udev->reset_resume) { -		dev_dbg(&udev->dev, "reset-resume\n"); -		status = usb_reset_and_verify_device(udev); -	} -	return status; -} -  #endif  static int check_ports_changed(struct usb_hub *hub) @@ -4090,9 +4083,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  				goto fail;  			}  			if (r) { -				dev_err(&udev->dev, -					"device descriptor read/64, error %d\n", -					r); +				if (r != -ENODEV) +					dev_err(&udev->dev, "device descriptor read/64, error %d\n", +							r);  				retval = -EMSGSIZE;  				continue;  			} @@ -4112,9 +4105,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  				msleep(200);  			}  			if (retval < 0) { -				dev_err(&udev->dev, -					"device not accepting address %d, error %d\n", -					devnum, retval); +				if (retval != -ENODEV) +					dev_err(&udev->dev, "device not accepting address %d, error %d\n", +							devnum, retval);  				goto fail;  			}  			if (udev->speed == USB_SPEED_SUPER) { @@ -4136,7 +4129,8 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  		retval = usb_get_device_descriptor(udev, 8);  		if (retval < 8) { -			dev_err(&udev->dev, +			if (retval != -ENODEV) +				dev_err(&udev->dev,  					"device descriptor read/8, error %d\n",  					retval);  			if (retval >= 0) @@ -4190,8 +4184,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  	retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);  	if (retval < (signed)sizeof(udev->descriptor)) { -		dev_err(&udev->dev, "device descriptor read/all, error %d\n", -			retval); +		if (retval != -ENODEV) +			dev_err(&udev->dev, "device descriptor read/all, error %d\n", +					retval);  		if (retval >= 0)  			retval = -ENOMSG;  		goto fail; @@ -4333,7 +4328,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  		if (portstatus & USB_PORT_STAT_ENABLE) {  			status = 0;		/* Nothing to do */ -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM_RUNTIME  		} else if (udev->state == USB_STATE_SUSPENDED &&  				udev->persist_enabled) {  			/* For a suspended device, treat this as a @@ -4373,7 +4368,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  				USB_PORT_STAT_C_ENABLE)) {  		status = hub_port_debounce_be_stable(hub, port1);  		if (status < 0) { -			if (printk_ratelimit()) +			if (status != -ENODEV && printk_ratelimit())  				dev_err(hub_dev, "connect-debounce failed, "  						"port %d disabled\n", port1);  			portstatus &= ~USB_PORT_STAT_CONNECTION; @@ -4402,6 +4397,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  	else  		unit_load = 100; +	status = 0;  	for (i = 0; i < SET_CONFIG_TRIES; i++) {  		/* reallocate for each attempt, since references @@ -4526,9 +4522,11 @@ loop:  	}  	if (hub->hdev->parent ||  			!hcd->driver->port_handed_over || -			!(hcd->driver->port_handed_over)(hcd, port1)) -		dev_err(hub_dev, "unable to enumerate USB device on port %d\n", -				port1); +			!(hcd->driver->port_handed_over)(hcd, port1)) { +		if (status != -ENOTCONN && status != -ENODEV) +			dev_err(hub_dev, "unable to enumerate USB device on port %d\n", +					port1); +	}  done:  	hub_port_disable(hub, port1, 1); diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 797f9d51473..b8bad294eeb 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -67,11 +67,10 @@ static void usb_port_device_release(struct device *dev)  {  	struct usb_port *port_dev = to_usb_port(dev); -	dev_pm_qos_hide_flags(dev);  	kfree(port_dev);  } -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM_RUNTIME  static int usb_port_runtime_resume(struct device *dev)  {  	struct usb_port *port_dev = to_usb_port(dev); @@ -139,7 +138,7 @@ static int usb_port_runtime_suspend(struct device *dev)  #endif  static const struct dev_pm_ops usb_port_pm_ops = { -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM_RUNTIME  	.runtime_suspend =	usb_port_runtime_suspend,  	.runtime_resume =	usb_port_runtime_resume,  	.runtime_idle =		pm_generic_runtime_idle, diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 3113c1d7144..ab5638d9c70 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -201,20 +201,14 @@ void usb_detect_quirks(struct usb_device *udev)  		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",  			udev->quirks); -	/* For the present, all devices default to USB-PERSIST enabled */ -#if 0		/* was: #ifdef CONFIG_PM */ -	/* Hubs are automatically enabled for USB-PERSIST */ -	if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) +#ifdef CONFIG_USB_DEFAULT_PERSIST +	if (!(udev->quirks & USB_QUIRK_RESET))  		udev->persist_enabled = 1; -  #else -	/* In the absence of PM, we can safely enable USB-PERSIST -	 * for all devices.  It will affect things like hub resets -	 * and EMF-related port disables. -	 */ -	if (!(udev->quirks & USB_QUIRK_RESET)) +	/* Hubs are automatically enabled for USB-PERSIST */ +	if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)  		udev->persist_enabled = 1; -#endif	/* CONFIG_PM */ +#endif	/* CONFIG_USB_DEFAULT_PERSIST */  }  void usb_detect_interface_quirks(struct usb_device *udev) diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 3f81a3dc686..aa38db44818 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -338,7 +338,7 @@ static void remove_persist_attributes(struct device *dev)  #endif	/* CONFIG_PM */ -#ifdef	CONFIG_USB_SUSPEND +#ifdef	CONFIG_PM_RUNTIME  static ssize_t  show_connected_duration(struct device *dev, struct device_attribute *attr, @@ -544,7 +544,7 @@ static void remove_power_attributes(struct device *dev)  #define add_power_attributes(dev)	0  #define remove_power_attributes(dev)	do {} while (0) -#endif	/* CONFIG_USB_SUSPEND */ +#endif	/* CONFIG_PM_RUNTIME */  /* Descriptor fields */ diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index e0d9d948218..16927fa88fb 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -683,10 +683,13 @@ EXPORT_SYMBOL_GPL(usb_kill_urb);  void usb_poison_urb(struct urb *urb)  {  	might_sleep(); -	if (!(urb && urb->dev && urb->ep)) +	if (!urb)  		return;  	atomic_inc(&urb->reject); +	if (!urb->dev || !urb->ep) +		return; +  	usb_hcd_unlink_urb(urb, -ENOENT);  	wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);  } diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index b6f4bad3f75..255c14464bf 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -15,6 +15,7 @@  #include <linux/kernel.h>  #include <linux/acpi.h>  #include <linux/pci.h> +#include <linux/usb/hcd.h>  #include <acpi/acpi_bus.h>  #include "usb.h" @@ -188,8 +189,13 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)  		 * connected to.  		 */  		if (!udev->parent) { -			*handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev), +			struct usb_hcd *hcd = bus_to_hcd(udev->bus); +			int raw_port_num; + +			raw_port_num = usb_hcd_find_raw_port_number(hcd,  				port_num); +			*handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev), +				raw_port_num);  			if (!*handle)  				return -ENODEV;  		} else { diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index f81b9257273..b10da720f2b 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -49,7 +49,7 @@ const char *usbcore_name = "usbcore";  static bool nousb;	/* Disable USB when built into kernel image */ -#ifdef	CONFIG_USB_SUSPEND +#ifdef	CONFIG_PM_RUNTIME  static int usb_autosuspend_delay = 2;		/* Default delay value,  						 * in seconds */  module_param_named(autosuspend, usb_autosuspend_delay, int, 0644); @@ -307,7 +307,7 @@ static const struct dev_pm_ops usb_device_pm_ops = {  	.thaw =		usb_dev_thaw,  	.poweroff =	usb_dev_poweroff,  	.restore =	usb_dev_restore, -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM_RUNTIME  	.runtime_suspend =	usb_runtime_suspend,  	.runtime_resume =	usb_runtime_resume,  	.runtime_idle =		usb_runtime_idle, @@ -317,7 +317,8 @@ static const struct dev_pm_ops usb_device_pm_ops = {  #endif	/* CONFIG_PM */ -static char *usb_devnode(struct device *dev, umode_t *mode) +static char *usb_devnode(struct device *dev, +			 umode_t *mode, kuid_t *uid, kgid_t *gid)  {  	struct usb_device *usb_dev; diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index a7f20bde0e5..823857767a1 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -93,7 +93,7 @@ static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg)  #endif -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM_RUNTIME  extern void usb_autosuspend_device(struct usb_device *udev);  extern int usb_autoresume_device(struct usb_device *udev); diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 68e9a2c5a01..ea5ee9c21c3 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -1,7 +1,6 @@  config USB_DWC3  	tristate "DesignWare USB3 DRD Core Support"  	depends on (USB || USB_GADGET) && GENERIC_HARDIRQS -	select USB_OTG_UTILS  	select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD  	help  	  Say Y or M here if your system has a Dual Role SuperSpeed diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index ffa6b004a84..c35d49d39b7 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -140,7 +140,8 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,   * Returns a pointer to the allocated event buffer structure on success   * otherwise ERR_PTR(errno).   */ -static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length) +static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, +		unsigned length)  {  	struct dwc3_event_buffer	*evt; @@ -259,6 +260,17 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)  	}  } +static void dwc3_core_num_eps(struct dwc3 *dwc) +{ +	struct dwc3_hwparams	*parms = &dwc->hwparams; + +	dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); +	dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; + +	dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n", +			dwc->num_in_eps, dwc->num_out_eps); +} +  static void dwc3_cache_hwparams(struct dwc3 *dwc)  {  	struct dwc3_hwparams	*parms = &dwc->hwparams; @@ -335,13 +347,9 @@ static int dwc3_core_init(struct dwc3 *dwc)  	if (dwc->revision < DWC3_REVISION_190A)  		reg |= DWC3_GCTL_U2RSTECN; -	dwc3_writel(dwc->regs, DWC3_GCTL, reg); +	dwc3_core_num_eps(dwc); -	ret = dwc3_event_buffers_setup(dwc); -	if (ret) { -		dev_err(dwc->dev, "failed to setup event buffers\n"); -		goto err0; -	} +	dwc3_writel(dwc->regs, DWC3_GCTL, reg);  	return 0; @@ -351,8 +359,6 @@ err0:  static void dwc3_core_exit(struct dwc3 *dwc)  { -	dwc3_event_buffers_cleanup(dwc); -  	usb_phy_shutdown(dwc->usb2_phy);  	usb_phy_shutdown(dwc->usb3_phy);  } @@ -428,12 +434,32 @@ static int dwc3_probe(struct platform_device *pdev)  		dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);  	} -	if (IS_ERR_OR_NULL(dwc->usb2_phy)) { +	if (IS_ERR(dwc->usb2_phy)) { +		ret = PTR_ERR(dwc->usb2_phy); + +		/* +		 * if -ENXIO is returned, it means PHY layer wasn't +		 * enabled, so it makes no sense to return -EPROBE_DEFER +		 * in that case, since no PHY driver will ever probe. +		 */ +		if (ret == -ENXIO) +			return ret; +  		dev_err(dev, "no usb2 phy configured\n");  		return -EPROBE_DEFER;  	} -	if (IS_ERR_OR_NULL(dwc->usb3_phy)) { +	if (IS_ERR(dwc->usb3_phy)) { +		ret = PTR_ERR(dwc->usb2_phy); + +		/* +		 * if -ENXIO is returned, it means PHY layer wasn't +		 * enabled, so it makes no sense to return -EPROBE_DEFER +		 * in that case, since no PHY driver will ever probe. +		 */ +		if (ret == -ENXIO) +			return ret; +  		dev_err(dev, "no usb3 phy configured\n");  		return -EPROBE_DEFER;  	} @@ -448,6 +474,10 @@ static int dwc3_probe(struct platform_device *pdev)  	dwc->regs_size	= resource_size(res);  	dwc->dev	= dev; +	dev->dma_mask	= dev->parent->dma_mask; +	dev->dma_parms	= dev->parent->dma_parms; +	dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); +  	if (!strncmp("super", maximum_speed, 5))  		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;  	else if (!strncmp("high", maximum_speed, 4)) @@ -480,7 +510,18 @@ static int dwc3_probe(struct platform_device *pdev)  		goto err0;  	} -	mode = DWC3_MODE(dwc->hwparams.hwparams0); +	ret = dwc3_event_buffers_setup(dwc); +	if (ret) { +		dev_err(dwc->dev, "failed to setup event buffers\n"); +		goto err1; +	} + +	if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) +		mode = DWC3_MODE_HOST; +	else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) +		mode = DWC3_MODE_DEVICE; +	else +		mode = DWC3_MODE_DRD;  	switch (mode) {  	case DWC3_MODE_DEVICE: @@ -488,7 +529,7 @@ static int dwc3_probe(struct platform_device *pdev)  		ret = dwc3_gadget_init(dwc);  		if (ret) {  			dev_err(dev, "failed to initialize gadget\n"); -			goto err1; +			goto err2;  		}  		break;  	case DWC3_MODE_HOST: @@ -496,7 +537,7 @@ static int dwc3_probe(struct platform_device *pdev)  		ret = dwc3_host_init(dwc);  		if (ret) {  			dev_err(dev, "failed to initialize host\n"); -			goto err1; +			goto err2;  		}  		break;  	case DWC3_MODE_DRD: @@ -504,32 +545,32 @@ static int dwc3_probe(struct platform_device *pdev)  		ret = dwc3_host_init(dwc);  		if (ret) {  			dev_err(dev, "failed to initialize host\n"); -			goto err1; +			goto err2;  		}  		ret = dwc3_gadget_init(dwc);  		if (ret) {  			dev_err(dev, "failed to initialize gadget\n"); -			goto err1; +			goto err2;  		}  		break;  	default:  		dev_err(dev, "Unsupported mode of operation %d\n", mode); -		goto err1; +		goto err2;  	}  	dwc->mode = mode;  	ret = dwc3_debugfs_init(dwc);  	if (ret) {  		dev_err(dev, "failed to initialize debugfs\n"); -		goto err2; +		goto err3;  	}  	pm_runtime_allow(dev);  	return 0; -err2: +err3:  	switch (mode) {  	case DWC3_MODE_DEVICE:  		dwc3_gadget_exit(dwc); @@ -546,6 +587,9 @@ err2:  		break;  	} +err2: +	dwc3_event_buffers_cleanup(dwc); +  err1:  	dwc3_core_exit(dwc); @@ -583,12 +627,130 @@ static int dwc3_remove(struct platform_device *pdev)  		break;  	} +	dwc3_event_buffers_cleanup(dwc);  	dwc3_free_event_buffers(dwc);  	dwc3_core_exit(dwc);  	return 0;  } +#ifdef CONFIG_PM_SLEEP +static int dwc3_prepare(struct device *dev) +{ +	struct dwc3	*dwc = dev_get_drvdata(dev); +	unsigned long	flags; + +	spin_lock_irqsave(&dwc->lock, flags); + +	switch (dwc->mode) { +	case DWC3_MODE_DEVICE: +	case DWC3_MODE_DRD: +		dwc3_gadget_prepare(dwc); +		/* FALLTHROUGH */ +	case DWC3_MODE_HOST: +	default: +		dwc3_event_buffers_cleanup(dwc); +		break; +	} + +	spin_unlock_irqrestore(&dwc->lock, flags); + +	return 0; +} + +static void dwc3_complete(struct device *dev) +{ +	struct dwc3	*dwc = dev_get_drvdata(dev); +	unsigned long	flags; + +	spin_lock_irqsave(&dwc->lock, flags); + +	switch (dwc->mode) { +	case DWC3_MODE_DEVICE: +	case DWC3_MODE_DRD: +		dwc3_gadget_complete(dwc); +		/* FALLTHROUGH */ +	case DWC3_MODE_HOST: +	default: +		dwc3_event_buffers_setup(dwc); +		break; +	} + +	spin_unlock_irqrestore(&dwc->lock, flags); +} + +static int dwc3_suspend(struct device *dev) +{ +	struct dwc3	*dwc = dev_get_drvdata(dev); +	unsigned long	flags; + +	spin_lock_irqsave(&dwc->lock, flags); + +	switch (dwc->mode) { +	case DWC3_MODE_DEVICE: +	case DWC3_MODE_DRD: +		dwc3_gadget_suspend(dwc); +		/* FALLTHROUGH */ +	case DWC3_MODE_HOST: +	default: +		/* do nothing */ +		break; +	} + +	dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL); +	spin_unlock_irqrestore(&dwc->lock, flags); + +	usb_phy_shutdown(dwc->usb3_phy); +	usb_phy_shutdown(dwc->usb2_phy); + +	return 0; +} + +static int dwc3_resume(struct device *dev) +{ +	struct dwc3	*dwc = dev_get_drvdata(dev); +	unsigned long	flags; + +	usb_phy_init(dwc->usb3_phy); +	usb_phy_init(dwc->usb2_phy); +	msleep(100); + +	spin_lock_irqsave(&dwc->lock, flags); + +	dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); + +	switch (dwc->mode) { +	case DWC3_MODE_DEVICE: +	case DWC3_MODE_DRD: +		dwc3_gadget_resume(dwc); +		/* FALLTHROUGH */ +	case DWC3_MODE_HOST: +	default: +		/* do nothing */ +		break; +	} + +	spin_unlock_irqrestore(&dwc->lock, flags); + +	pm_runtime_disable(dev); +	pm_runtime_set_active(dev); +	pm_runtime_enable(dev); + +	return 0; +} + +static const struct dev_pm_ops dwc3_dev_pm_ops = { +	.prepare	= dwc3_prepare, +	.complete	= dwc3_complete, + +	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) +}; + +#define DWC3_PM_OPS	&(dwc3_dev_pm_ops) +#else +#define DWC3_PM_OPS	NULL +#endif +  #ifdef CONFIG_OF  static const struct of_device_id of_dwc3_match[] = {  	{ @@ -605,6 +767,7 @@ static struct platform_driver dwc3_driver = {  	.driver		= {  		.name	= "dwc3",  		.of_match_table	= of_match_ptr(of_dwc3_match), +		.pm	= DWC3_PM_OPS,  	},  }; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index b4175066023..b69d322e3ca 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -154,8 +154,9 @@  /* OTG Registers */  #define DWC3_OCFG		0xcc00  #define DWC3_OCTL		0xcc04 -#define DWC3_OEVTEN		0xcc08 -#define DWC3_OSTS		0xcc0C +#define DWC3_OEVT		0xcc08 +#define DWC3_OEVTEN		0xcc0C +#define DWC3_OSTS		0xcc10  /* Bit fields */ @@ -369,6 +370,9 @@ struct dwc3_trb;   * @list: a list of event buffers   * @buf: _THE_ buffer   * @length: size of this buffer + * @lpos: event offset + * @count: cache of last read event count register + * @flags: flags related to this event buffer   * @dma: dma_addr_t   * @dwc: pointer to DWC controller   */ @@ -376,6 +380,10 @@ struct dwc3_event_buffer {  	void			*buf;  	unsigned		length;  	unsigned int		lpos; +	unsigned int		count; +	unsigned int		flags; + +#define DWC3_EVENT_PENDING	BIT(0)  	dma_addr_t		dma; @@ -487,12 +495,6 @@ enum dwc3_link_state {  	DWC3_LINK_STATE_MASK		= 0x0f,  }; -enum dwc3_device_state { -	DWC3_DEFAULT_STATE, -	DWC3_ADDRESS_STATE, -	DWC3_CONFIGURED_STATE, -}; -  /* TRB Length, PCM and Status */  #define DWC3_TRB_SIZE_MASK	(0x00ffffff)  #define DWC3_TRB_SIZE_LENGTH(n)	((n) & DWC3_TRB_SIZE_MASK) @@ -574,6 +576,14 @@ struct dwc3_hwparams {  /* HWPARAMS1 */  #define DWC3_NUM_INT(n)		(((n) & (0x3f << 15)) >> 15) +/* HWPARAMS3 */ +#define DWC3_NUM_IN_EPS_MASK	(0x1f << 18) +#define DWC3_NUM_EPS_MASK	(0x3f << 12) +#define DWC3_NUM_EPS(p)		(((p)->hwparams3 &		\ +			(DWC3_NUM_EPS_MASK)) >> 12) +#define DWC3_NUM_IN_EPS(p)	(((p)->hwparams3 &		\ +			(DWC3_NUM_IN_EPS_MASK)) >> 18) +  /* HWPARAMS7 */  #define DWC3_RAM1_DEPTH(n)	((n) & 0xffff) @@ -618,7 +628,6 @@ struct dwc3_scratchpad_array {   * @gadget_driver: pointer to the gadget driver   * @regs: base address for our registers   * @regs_size: address space size - * @irq: IRQ number   * @num_event_buffers: calculated number of event buffers   * @u1u2: only used on revisions <1.83a for workaround   * @maximum_speed: maximum speed requested (mainly for testing purposes) @@ -626,6 +635,8 @@ struct dwc3_scratchpad_array {   * @mode: mode of operation   * @usb2_phy: pointer to USB2 PHY   * @usb3_phy: pointer to USB3 PHY + * @dcfg: saved contents of DCFG register + * @gctl: saved contents of GCTL register   * @is_selfpowered: true when we are selfpowered   * @three_stage_setup: set if we perform a three phase setup   * @ep0_bounced: true when we used bounce buffer @@ -639,6 +650,8 @@ struct dwc3_scratchpad_array {   * @u2pel: parameter from Set SEL request.   * @u1sel: parameter from Set SEL request.   * @u1pel: parameter from Set SEL request. + * @num_out_eps: number of out endpoints + * @num_in_eps: number of in endpoints   * @ep0_next_event: hold the next expected event   * @ep0state: state of endpoint zero   * @link_state: link state @@ -656,8 +669,10 @@ struct dwc3 {  	dma_addr_t		ep0_trb_addr;  	dma_addr_t		ep0_bounce_addr;  	struct dwc3_request	ep0_usb_req; +  	/* device lock */  	spinlock_t		lock; +  	struct device		*dev;  	struct platform_device	*xhci; @@ -675,6 +690,10 @@ struct dwc3 {  	void __iomem		*regs;  	size_t			regs_size; +	/* used for suspend/resume */ +	u32			dcfg; +	u32			gctl; +  	u32			num_event_buffers;  	u32			u1u2;  	u32			maximum_speed; @@ -694,6 +713,9 @@ struct dwc3 {  #define DWC3_REVISION_202A	0x5533202a  #define DWC3_REVISION_210A	0x5533210a  #define DWC3_REVISION_220A	0x5533220a +#define DWC3_REVISION_230A	0x5533230a +#define DWC3_REVISION_240A	0x5533240a +#define DWC3_REVISION_250A	0x5533250a  	unsigned		is_selfpowered:1;  	unsigned		three_stage_setup:1; @@ -704,11 +726,11 @@ struct dwc3 {  	unsigned		delayed_status:1;  	unsigned		needs_fifo_resize:1;  	unsigned		resize_fifos:1; +	unsigned		pullups_connected:1;  	enum dwc3_ep0_next	ep0_next_event;  	enum dwc3_ep0_state	ep0state;  	enum dwc3_link_state	link_state; -	enum dwc3_device_state	dev_state;  	u16			isoch_delay;  	u16			u2sel; @@ -718,6 +740,9 @@ struct dwc3 {  	u8			speed; +	u8			num_out_eps; +	u8			num_in_eps; +  	void			*mem;  	struct dwc3_hwparams	hwparams; @@ -884,4 +909,31 @@ static inline void dwc3_gadget_exit(struct dwc3 *dwc)  { }  #endif +/* power management interface */ +#if !IS_ENABLED(CONFIG_USB_DWC3_HOST) +int dwc3_gadget_prepare(struct dwc3 *dwc); +void dwc3_gadget_complete(struct dwc3 *dwc); +int dwc3_gadget_suspend(struct dwc3 *dwc); +int dwc3_gadget_resume(struct dwc3 *dwc); +#else +static inline int dwc3_gadget_prepare(struct dwc3 *dwc) +{ +	return 0; +} + +static inline void dwc3_gadget_complete(struct dwc3 *dwc) +{ +} + +static inline int dwc3_gadget_suspend(struct dwc3 *dwc) +{ +	return 0; +} + +static inline int dwc3_gadget_resume(struct dwc3 *dwc) +{ +	return 0; +} +#endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */ +  #endif /* __DRIVERS_USB_DWC3_CORE_H */ diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 4a752e730c5..9e9f122162f 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -59,7 +59,7 @@  	.offset	= DWC3_ ##nm - DWC3_GLOBALS_REGS_START,	\  } -static struct debugfs_reg32 dwc3_regs[] = { +static const struct debugfs_reg32 dwc3_regs[] = {  	dump_register(GSBUSCFG0),  	dump_register(GSBUSCFG1),  	dump_register(GTXTHRCFG), @@ -372,6 +372,7 @@ static struct debugfs_reg32 dwc3_regs[] = {  	dump_register(OCFG),  	dump_register(OCTL), +	dump_register(OEVT),  	dump_register(OEVTEN),  	dump_register(OSTS),  }; @@ -577,8 +578,14 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused)  	case DWC3_LINK_STATE_LPBK:  		seq_printf(s, "Loopback\n");  		break; +	case DWC3_LINK_STATE_RESET: +		seq_printf(s, "Reset\n"); +		break; +	case DWC3_LINK_STATE_RESUME: +		seq_printf(s, "Resume\n"); +		break;  	default: -		seq_printf(s, "UNKNOWN %d\n", reg); +		seq_printf(s, "UNKNOWN %d\n", state);  	}  	return 0; @@ -661,28 +668,31 @@ int dwc3_debugfs_init(struct dwc3 *dwc)  		goto err1;  	} -#if IS_ENABLED(CONFIG_USB_DWC3_GADGET) -	file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, -			dwc, &dwc3_mode_fops); -	if (!file) { -		ret = -ENOMEM; -		goto err1; +	if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) { +		file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, +				dwc, &dwc3_mode_fops); +		if (!file) { +			ret = -ENOMEM; +			goto err1; +		}  	} -	file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, -			dwc, &dwc3_testmode_fops); -	if (!file) { -		ret = -ENOMEM; -		goto err1; -	} +	if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) || +			IS_ENABLED(CONFIG_USB_DWC3_GADGET)) { +		file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, +				dwc, &dwc3_testmode_fops); +		if (!file) { +			ret = -ENOMEM; +			goto err1; +		} -	file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root, -			dwc, &dwc3_link_state_fops); -	if (!file) { -		ret = -ENOMEM; -		goto err1; +		file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root, +				dwc, &dwc3_link_state_fops); +		if (!file) { +			ret = -ENOMEM; +			goto err1; +		}  	} -#endif  	return 0; diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index b082bec7343..a8afe6e2662 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -22,9 +22,9 @@  #include <linux/usb/otg.h>  #include <linux/usb/nop-usb-xceiv.h>  #include <linux/of.h> +#include <linux/of_platform.h>  struct dwc3_exynos { -	struct platform_device	*dwc3;  	struct platform_device	*usb2_phy;  	struct platform_device	*usb3_phy;  	struct device		*dev; @@ -86,21 +86,30 @@ err1:  	return ret;  } +static int dwc3_exynos_remove_child(struct device *dev, void *unused) +{ +	struct platform_device *pdev = to_platform_device(dev); + +	platform_device_unregister(pdev); + +	return 0; +} +  static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);  static int dwc3_exynos_probe(struct platform_device *pdev)  { -	struct platform_device	*dwc3;  	struct dwc3_exynos	*exynos;  	struct clk		*clk;  	struct device		*dev = &pdev->dev; +	struct device_node	*node = dev->of_node;  	int			ret = -ENOMEM;  	exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);  	if (!exynos) {  		dev_err(dev, "not enough memory\n"); -		return -ENOMEM; +		goto err1;  	}  	/* @@ -108,21 +117,15 @@ static int dwc3_exynos_probe(struct platform_device *pdev)  	 * Since shared usb code relies on it, set it here for now.  	 * Once we move to full device tree support this will vanish off.  	 */ -	if (!pdev->dev.dma_mask) -		pdev->dev.dma_mask = &dwc3_exynos_dma_mask; +	if (!dev->dma_mask) +		dev->dma_mask = &dwc3_exynos_dma_mask;  	platform_set_drvdata(pdev, exynos);  	ret = dwc3_exynos_register_phys(exynos);  	if (ret) {  		dev_err(dev, "couldn't register PHYs\n"); -		return ret; -	} - -	dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); -	if (!dwc3) { -		dev_err(dev, "couldn't allocate dwc3 device\n"); -		return -ENOMEM; +		goto err1;  	}  	clk = devm_clk_get(dev, "usbdrd30"); @@ -132,37 +135,28 @@ static int dwc3_exynos_probe(struct platform_device *pdev)  		goto err1;  	} -	dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask); - -	dwc3->dev.parent = dev; -	dwc3->dev.dma_mask = dev->dma_mask; -	dwc3->dev.dma_parms = dev->dma_parms; -	exynos->dwc3	= dwc3;  	exynos->dev	= dev;  	exynos->clk	= clk; -	clk_enable(exynos->clk); - -	ret = platform_device_add_resources(dwc3, pdev->resource, -			pdev->num_resources); -	if (ret) { -		dev_err(dev, "couldn't add resources to dwc3 device\n"); -		goto err2; -	} +	clk_prepare_enable(exynos->clk); -	ret = platform_device_add(dwc3); -	if (ret) { -		dev_err(dev, "failed to register dwc3 device\n"); +	if (node) { +		ret = of_platform_populate(node, NULL, NULL, dev); +		if (ret) { +			dev_err(dev, "failed to add dwc3 core\n"); +			goto err2; +		} +	} else { +		dev_err(dev, "no device node, failed to add dwc3 core\n"); +		ret = -ENODEV;  		goto err2;  	}  	return 0;  err2: -	clk_disable(clk); +	clk_disable_unprepare(clk);  err1: -	platform_device_put(dwc3); -  	return ret;  } @@ -170,11 +164,11 @@ static int dwc3_exynos_remove(struct platform_device *pdev)  {  	struct dwc3_exynos	*exynos = platform_get_drvdata(pdev); -	platform_device_unregister(exynos->dwc3);  	platform_device_unregister(exynos->usb2_phy);  	platform_device_unregister(exynos->usb3_phy); +	device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child); -	clk_disable(exynos->clk); +	clk_disable_unprepare(exynos->clk);  	return 0;  } @@ -187,12 +181,46 @@ static const struct of_device_id exynos_dwc3_match[] = {  MODULE_DEVICE_TABLE(of, exynos_dwc3_match);  #endif +#ifdef CONFIG_PM_SLEEP +static int dwc3_exynos_suspend(struct device *dev) +{ +	struct dwc3_exynos *exynos = dev_get_drvdata(dev); + +	clk_disable(exynos->clk); + +	return 0; +} + +static int dwc3_exynos_resume(struct device *dev) +{ +	struct dwc3_exynos *exynos = dev_get_drvdata(dev); + +	clk_enable(exynos->clk); + +	/* runtime set active to reflect active state. */ +	pm_runtime_disable(dev); +	pm_runtime_set_active(dev); +	pm_runtime_enable(dev); + +	return 0; +} + +static const struct dev_pm_ops dwc3_exynos_dev_pm_ops = { +	SET_SYSTEM_SLEEP_PM_OPS(dwc3_exynos_suspend, dwc3_exynos_resume) +}; + +#define DEV_PM_OPS	(&dwc3_exynos_dev_pm_ops) +#else +#define DEV_PM_OPS	NULL +#endif /* CONFIG_PM_SLEEP */ +  static struct platform_driver dwc3_exynos_driver = {  	.probe		= dwc3_exynos_probe,  	.remove		= dwc3_exynos_remove,  	.driver		= {  		.name	= "exynos-dwc3",  		.of_match_table = of_match_ptr(exynos_dwc3_match), +		.pm	= DEV_PM_OPS,  	},  }; diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index afa05e3c9cf..34638b92500 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -52,7 +52,6 @@  #include <linux/of_platform.h>  #include <linux/usb/otg.h> -#include <linux/usb/nop-usb-xceiv.h>  /*   * All these registers belong to OMAP's Wrapper around the @@ -117,20 +116,17 @@ struct dwc3_omap {  	/* device lock */  	spinlock_t		lock; -	struct platform_device	*usb2_phy; -	struct platform_device	*usb3_phy;  	struct device		*dev;  	int			irq;  	void __iomem		*base; -	void			*context; -	u32			resource_size; +	u32			utmi_otg_status;  	u32			dma_status:1;  }; -struct dwc3_omap		*_omap; +static struct dwc3_omap		*_omap;  static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)  { @@ -142,11 +138,14 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)  	writel(value, base + offset);  } -void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) +int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)  {  	u32			val;  	struct dwc3_omap	*omap = _omap; +	if (!omap) +		return -EPROBE_DEFER; +  	switch (status) {  	case OMAP_DWC3_ID_GROUND:  		dev_dbg(omap->dev, "ID GND\n"); @@ -189,63 +188,9 @@ void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)  		dev_dbg(omap->dev, "ID float\n");  	} -	return; -} -EXPORT_SYMBOL_GPL(dwc3_omap_mailbox); - -static int dwc3_omap_register_phys(struct dwc3_omap *omap) -{ -	struct nop_usb_xceiv_platform_data pdata; -	struct platform_device	*pdev; -	int			ret; - -	memset(&pdata, 0x00, sizeof(pdata)); - -	pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO); -	if (!pdev) -		return -ENOMEM; - -	omap->usb2_phy = pdev; -	pdata.type = USB_PHY_TYPE_USB2; - -	ret = platform_device_add_data(omap->usb2_phy, &pdata, sizeof(pdata)); -	if (ret) -		goto err1; - -	pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO); -	if (!pdev) { -		ret = -ENOMEM; -		goto err1; -	} - -	omap->usb3_phy = pdev; -	pdata.type = USB_PHY_TYPE_USB3; - -	ret = platform_device_add_data(omap->usb3_phy, &pdata, sizeof(pdata)); -	if (ret) -		goto err2; - -	ret = platform_device_add(omap->usb2_phy); -	if (ret) -		goto err2; - -	ret = platform_device_add(omap->usb3_phy); -	if (ret) -		goto err3; -  	return 0; - -err3: -	platform_device_del(omap->usb2_phy); - -err2: -	platform_device_put(omap->usb3_phy); - -err1: -	platform_device_put(omap->usb2_phy); - -	return ret;  } +EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);  static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)  { @@ -307,24 +252,57 @@ static int dwc3_omap_remove_core(struct device *dev, void *c)  	return 0;  } +static void dwc3_omap_enable_irqs(struct dwc3_omap *omap) +{ +	u32			reg; + +	/* enable all IRQs */ +	reg = USBOTGSS_IRQO_COREIRQ_ST; +	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg); + +	reg = (USBOTGSS_IRQ1_OEVT | +			USBOTGSS_IRQ1_DRVVBUS_RISE | +			USBOTGSS_IRQ1_CHRGVBUS_RISE | +			USBOTGSS_IRQ1_DISCHRGVBUS_RISE | +			USBOTGSS_IRQ1_IDPULLUP_RISE | +			USBOTGSS_IRQ1_DRVVBUS_FALL | +			USBOTGSS_IRQ1_CHRGVBUS_FALL | +			USBOTGSS_IRQ1_DISCHRGVBUS_FALL | +			USBOTGSS_IRQ1_IDPULLUP_FALL); + +	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg); +} + +static void dwc3_omap_disable_irqs(struct dwc3_omap *omap) +{ +	/* disable all IRQs */ +	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, 0x00); +	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, 0x00); +} + +static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32); +  static int dwc3_omap_probe(struct platform_device *pdev)  { -	struct dwc3_omap_data	*pdata = pdev->dev.platform_data;  	struct device_node	*node = pdev->dev.of_node;  	struct dwc3_omap	*omap;  	struct resource		*res;  	struct device		*dev = &pdev->dev; -	int			size;  	int			ret = -ENOMEM;  	int			irq; -	const u32		*utmi_mode; +	int			utmi_mode = 0; +  	u32			reg;  	void __iomem		*base; -	void			*context; + +	if (!node) { +		dev_err(dev, "device node not found\n"); +		return -EINVAL; +	}  	omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);  	if (!omap) { @@ -334,13 +312,13 @@ static int dwc3_omap_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, omap); -	irq = platform_get_irq(pdev, 1); +	irq = platform_get_irq(pdev, 0);  	if (irq < 0) {  		dev_err(dev, "missing IRQ resource\n");  		return -EINVAL;  	} -	res = platform_get_resource(pdev, IORESOURCE_MEM, 1); +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) {  		dev_err(dev, "missing memory base resource\n");  		return -EINVAL; @@ -352,25 +330,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)  		return -ENOMEM;  	} -	ret = dwc3_omap_register_phys(omap); -	if (ret) { -		dev_err(dev, "couldn't register PHYs\n"); -		return ret; -	} - -	context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL); -	if (!context) { -		dev_err(dev, "couldn't allocate dwc3 context memory\n"); -		return -ENOMEM; -	} -  	spin_lock_init(&omap->lock); -	omap->resource_size = resource_size(res); -	omap->context	= context;  	omap->dev	= dev;  	omap->irq	= irq;  	omap->base	= base; +	dev->dma_mask	= &dwc3_omap_dma_mask;  	/*  	 * REVISIT if we ever have two instances of the wrapper, we will be @@ -387,25 +352,17 @@ static int dwc3_omap_probe(struct platform_device *pdev)  	reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS); -	utmi_mode = of_get_property(node, "utmi-mode", &size); -	if (utmi_mode && size == sizeof(*utmi_mode)) { -		reg |= *utmi_mode; -	} else { -		if (!pdata) { -			dev_dbg(dev, "missing platform data\n"); -		} else { -			switch (pdata->utmi_mode) { -			case DWC3_OMAP_UTMI_MODE_SW: -				reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; -				break; -			case DWC3_OMAP_UTMI_MODE_HW: -				reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; -				break; -			default: -				dev_dbg(dev, "UNKNOWN utmi mode %d\n", -						pdata->utmi_mode); -			} -		} +	of_property_read_u32(node, "utmi-mode", &utmi_mode); + +	switch (utmi_mode) { +	case DWC3_OMAP_UTMI_MODE_SW: +		reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; +		break; +	case DWC3_OMAP_UTMI_MODE_HW: +		reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; +		break; +	default: +		dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode);  	}  	dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg); @@ -422,29 +379,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)  		return ret;  	} -	/* enable all IRQs */ -	reg = USBOTGSS_IRQO_COREIRQ_ST; -	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg); +	dwc3_omap_enable_irqs(omap); -	reg = (USBOTGSS_IRQ1_OEVT | -			USBOTGSS_IRQ1_DRVVBUS_RISE | -			USBOTGSS_IRQ1_CHRGVBUS_RISE | -			USBOTGSS_IRQ1_DISCHRGVBUS_RISE | -			USBOTGSS_IRQ1_IDPULLUP_RISE | -			USBOTGSS_IRQ1_DRVVBUS_FALL | -			USBOTGSS_IRQ1_CHRGVBUS_FALL | -			USBOTGSS_IRQ1_DISCHRGVBUS_FALL | -			USBOTGSS_IRQ1_IDPULLUP_FALL); - -	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg); - -	if (node) { -		ret = of_platform_populate(node, NULL, NULL, dev); -		if (ret) { -			dev_err(&pdev->dev, -				"failed to add create dwc3 core\n"); -			return ret; -		} +	ret = of_platform_populate(node, NULL, NULL, dev); +	if (ret) { +		dev_err(&pdev->dev, "failed to create dwc3 core\n"); +		return ret;  	}  	return 0; @@ -454,8 +394,7 @@ static int dwc3_omap_remove(struct platform_device *pdev)  {  	struct dwc3_omap	*omap = platform_get_drvdata(pdev); -	platform_device_unregister(omap->usb2_phy); -	platform_device_unregister(omap->usb3_phy); +	dwc3_omap_disable_irqs(omap);  	pm_runtime_put_sync(&pdev->dev);  	pm_runtime_disable(&pdev->dev);  	device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core); @@ -465,18 +404,72 @@ static int dwc3_omap_remove(struct platform_device *pdev)  static const struct of_device_id of_dwc3_match[] = {  	{ -		"ti,dwc3", +		.compatible =	"ti,dwc3"  	},  	{ },  };  MODULE_DEVICE_TABLE(of, of_dwc3_match); +#ifdef CONFIG_PM_SLEEP +static int dwc3_omap_prepare(struct device *dev) +{ +	struct dwc3_omap	*omap = dev_get_drvdata(dev); + +	dwc3_omap_disable_irqs(omap); + +	return 0; +} + +static void dwc3_omap_complete(struct device *dev) +{ +	struct dwc3_omap	*omap = dev_get_drvdata(dev); + +	dwc3_omap_enable_irqs(omap); +} + +static int dwc3_omap_suspend(struct device *dev) +{ +	struct dwc3_omap	*omap = dev_get_drvdata(dev); + +	omap->utmi_otg_status = dwc3_omap_readl(omap->base, +			USBOTGSS_UTMI_OTG_STATUS); + +	return 0; +} + +static int dwc3_omap_resume(struct device *dev) +{ +	struct dwc3_omap	*omap = dev_get_drvdata(dev); + +	dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, +			omap->utmi_otg_status); + +	pm_runtime_disable(dev); +	pm_runtime_set_active(dev); +	pm_runtime_enable(dev); + +	return 0; +} + +static const struct dev_pm_ops dwc3_omap_dev_pm_ops = { +	.prepare	= dwc3_omap_prepare, +	.complete	= dwc3_omap_complete, + +	SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume) +}; + +#define DEV_PM_OPS	(&dwc3_omap_dev_pm_ops) +#else +#define DEV_PM_OPS	NULL +#endif /* CONFIG_PM_SLEEP */ +  static struct platform_driver dwc3_omap_driver = {  	.probe		= dwc3_omap_probe,  	.remove		= dwc3_omap_remove,  	.driver		= {  		.name	= "omap-dwc3",  		.of_match_table	= of_dwc3_match, +		.pm	= DEV_PM_OPS,  	},  }; diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index e8d77689a32..227d4a7acad 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -212,11 +212,49 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {  };  MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table); +#ifdef CONFIG_PM +static int dwc3_pci_suspend(struct device *dev) +{ +	struct pci_dev	*pci = to_pci_dev(dev); + +	pci_disable_device(pci); + +	return 0; +} + +static int dwc3_pci_resume(struct device *dev) +{ +	struct pci_dev	*pci = to_pci_dev(dev); +	int		ret; + +	ret = pci_enable_device(pci); +	if (ret) { +		dev_err(dev, "can't re-enable device --> %d\n", ret); +		return ret; +	} + +	pci_set_master(pci); + +	return 0; +} + +static const struct dev_pm_ops dwc3_pci_dev_pm_ops = { +	SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume) +}; + +#define DEV_PM_OPS	(&dwc3_pci_dev_pm_ops) +#else +#define DEV_PM_OPS	NULL +#endif /* CONFIG_PM */ +  static struct pci_driver dwc3_pci_driver = {  	.name		= "dwc3-pci",  	.id_table	= dwc3_pci_id_table,  	.probe		= dwc3_pci_probe,  	.remove		= dwc3_pci_remove, +	.driver		= { +		.pm	= DEV_PM_OPS, +	},  };  MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 1d139ca05ef..5acbb948b70 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -394,10 +394,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,  	u32			wIndex;  	u32			reg;  	int			ret; +	enum usb_device_state	state;  	wValue = le16_to_cpu(ctrl->wValue);  	wIndex = le16_to_cpu(ctrl->wIndex);  	recip = ctrl->bRequestType & USB_RECIP_MASK; +	state = dwc->gadget.state; +  	switch (recip) {  	case USB_RECIP_DEVICE: @@ -409,7 +412,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,  		 * default control pipe  		 */  		case USB_DEVICE_U1_ENABLE: -			if (dwc->dev_state != DWC3_CONFIGURED_STATE) +			if (state != USB_STATE_CONFIGURED)  				return -EINVAL;  			if (dwc->speed != DWC3_DSTS_SUPERSPEED)  				return -EINVAL; @@ -423,7 +426,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,  			break;  		case USB_DEVICE_U2_ENABLE: -			if (dwc->dev_state != DWC3_CONFIGURED_STATE) +			if (state != USB_STATE_CONFIGURED)  				return -EINVAL;  			if (dwc->speed != DWC3_DSTS_SUPERSPEED)  				return -EINVAL; @@ -493,6 +496,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,  static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)  { +	enum usb_device_state state = dwc->gadget.state;  	u32 addr;  	u32 reg; @@ -502,7 +506,7 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)  		return -EINVAL;  	} -	if (dwc->dev_state == DWC3_CONFIGURED_STATE) { +	if (state == USB_STATE_CONFIGURED) {  		dev_dbg(dwc->dev, "trying to set address when configured\n");  		return -EINVAL;  	} @@ -513,9 +517,9 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)  	dwc3_writel(dwc->regs, DWC3_DCFG, reg);  	if (addr) -		dwc->dev_state = DWC3_ADDRESS_STATE; +		usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS);  	else -		dwc->dev_state = DWC3_DEFAULT_STATE; +		usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);  	return 0;  } @@ -532,6 +536,7 @@ static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)  static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)  { +	enum usb_device_state state = dwc->gadget.state;  	u32 cfg;  	int ret;  	u32 reg; @@ -539,16 +544,18 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)  	dwc->start_config_issued = false;  	cfg = le16_to_cpu(ctrl->wValue); -	switch (dwc->dev_state) { -	case DWC3_DEFAULT_STATE: +	switch (state) { +	case USB_STATE_DEFAULT:  		return -EINVAL;  		break; -	case DWC3_ADDRESS_STATE: +	case USB_STATE_ADDRESS:  		ret = dwc3_ep0_delegate_req(dwc, ctrl);  		/* if the cfg matches and the cfg is non zero */  		if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { -			dwc->dev_state = DWC3_CONFIGURED_STATE; +			usb_gadget_set_state(&dwc->gadget, +					USB_STATE_CONFIGURED); +  			/*  			 * Enable transition to U1/U2 state when  			 * nothing is pending from application. @@ -562,10 +569,11 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)  		}  		break; -	case DWC3_CONFIGURED_STATE: +	case USB_STATE_CONFIGURED:  		ret = dwc3_ep0_delegate_req(dwc, ctrl);  		if (!cfg) -			dwc->dev_state = DWC3_ADDRESS_STATE; +			usb_gadget_set_state(&dwc->gadget, +					USB_STATE_ADDRESS);  		break;  	default:  		ret = -EINVAL; @@ -620,10 +628,11 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req)  static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)  {  	struct dwc3_ep	*dep; +	enum usb_device_state state = dwc->gadget.state;  	u16		wLength;  	u16		wValue; -	if (dwc->dev_state == DWC3_DEFAULT_STATE) +	if (state == USB_STATE_DEFAULT)  		return -EINVAL;  	wValue = le16_to_cpu(ctrl->wValue); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 82e160e96fc..2b6e7e00120 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1425,8 +1425,10 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)  		if (dwc->revision >= DWC3_REVISION_194A)  			reg &= ~DWC3_DCTL_KEEP_CONNECT;  		reg |= DWC3_DCTL_RUN_STOP; +		dwc->pullups_connected = true;  	} else {  		reg &= ~DWC3_DCTL_RUN_STOP; +		dwc->pullups_connected = false;  	}  	dwc3_writel(dwc->regs, DWC3_DCTL, reg); @@ -1469,6 +1471,33 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)  	return ret;  } +static void dwc3_gadget_enable_irq(struct dwc3 *dwc) +{ +	u32			reg; + +	/* Enable all but Start and End of Frame IRQs */ +	reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN | +			DWC3_DEVTEN_EVNTOVERFLOWEN | +			DWC3_DEVTEN_CMDCMPLTEN | +			DWC3_DEVTEN_ERRTICERREN | +			DWC3_DEVTEN_WKUPEVTEN | +			DWC3_DEVTEN_ULSTCNGEN | +			DWC3_DEVTEN_CONNECTDONEEN | +			DWC3_DEVTEN_USBRSTEN | +			DWC3_DEVTEN_DISCONNEVTEN); + +	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); +} + +static void dwc3_gadget_disable_irq(struct dwc3 *dwc) +{ +	/* mask all interrupts */ +	dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); +} + +static irqreturn_t dwc3_interrupt(int irq, void *_dwc); +static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc); +  static int dwc3_gadget_start(struct usb_gadget *g,  		struct usb_gadget_driver *driver)  { @@ -1476,6 +1505,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,  	struct dwc3_ep		*dep;  	unsigned long		flags;  	int			ret = 0; +	int			irq;  	u32			reg;  	spin_lock_irqsave(&dwc->lock, flags); @@ -1489,7 +1519,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,  	}  	dwc->gadget_driver	= driver; -	dwc->gadget.dev.driver	= &driver->driver;  	reg = dwc3_readl(dwc->regs, DWC3_DCFG);  	reg &= ~(DWC3_DCFG_SPEED_MASK); @@ -1536,6 +1565,17 @@ static int dwc3_gadget_start(struct usb_gadget *g,  	dwc->ep0state = EP0_SETUP_PHASE;  	dwc3_ep0_out_start(dwc); +	irq = platform_get_irq(to_platform_device(dwc->dev), 0); +	ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt, +			IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc); +	if (ret) { +		dev_err(dwc->dev, "failed to request irq #%d --> %d\n", +				irq, ret); +		goto err1; +	} + +	dwc3_gadget_enable_irq(dwc); +  	spin_unlock_irqrestore(&dwc->lock, flags);  	return 0; @@ -1554,14 +1594,18 @@ static int dwc3_gadget_stop(struct usb_gadget *g,  {  	struct dwc3		*dwc = gadget_to_dwc(g);  	unsigned long		flags; +	int			irq;  	spin_lock_irqsave(&dwc->lock, flags); +	dwc3_gadget_disable_irq(dwc); +	irq = platform_get_irq(to_platform_device(dwc->dev), 0); +	free_irq(irq, dwc); +  	__dwc3_gadget_ep_disable(dwc->eps[0]);  	__dwc3_gadget_ep_disable(dwc->eps[1]);  	dwc->gadget_driver	= NULL; -	dwc->gadget.dev.driver	= NULL;  	spin_unlock_irqrestore(&dwc->lock, flags); @@ -1579,14 +1623,15 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {  /* -------------------------------------------------------------------------- */ -static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) +static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, +		u8 num, u32 direction)  {  	struct dwc3_ep			*dep; -	u8				epnum; +	u8				i; -	INIT_LIST_HEAD(&dwc->gadget.ep_list); +	for (i = 0; i < num; i++) { +		u8 epnum = (i << 1) | (!!direction); -	for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {  		dep = kzalloc(sizeof(*dep), GFP_KERNEL);  		if (!dep) {  			dev_err(dwc->dev, "can't allocate endpoint %d\n", @@ -1600,6 +1645,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)  		snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,  				(epnum & 1) ? "in" : "out"); +  		dep->endpoint.name = dep->name;  		dep->direction = (epnum & 1); @@ -1630,6 +1676,27 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)  	return 0;  } +static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) +{ +	int				ret; + +	INIT_LIST_HEAD(&dwc->gadget.ep_list); + +	ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_out_eps, 0); +	if (ret < 0) { +		dev_vdbg(dwc->dev, "failed to allocate OUT endpoints\n"); +		return ret; +	} + +	ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_in_eps, 1); +	if (ret < 0) { +		dev_vdbg(dwc->dev, "failed to allocate IN endpoints\n"); +		return ret; +	} + +	return 0; +} +  static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)  {  	struct dwc3_ep			*dep; @@ -1637,6 +1704,9 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)  	for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {  		dep = dwc->eps[epnum]; +		if (!dep) +			continue; +  		dwc3_free_trb_pool(dep);  		if (epnum != 0 && epnum != 1) @@ -1646,12 +1716,8 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)  	}  } -static void dwc3_gadget_release(struct device *dev) -{ -	dev_dbg(dev, "%s\n", __func__); -} -  /* -------------------------------------------------------------------------- */ +  static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,  		struct dwc3_request *req, struct dwc3_trb *trb,  		const struct dwc3_event_depevt *event, int status) @@ -1975,6 +2041,9 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)  		struct dwc3_ep *dep;  		dep = dwc->eps[epnum]; +		if (!dep) +			continue; +  		if (!(dep->flags & DWC3_EP_ENABLED))  			continue; @@ -1992,6 +2061,8 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)  		int ret;  		dep = dwc->eps[epnum]; +		if (!dep) +			continue;  		if (!(dep->flags & DWC3_EP_STALL))  			continue; @@ -2091,7 +2162,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)  	}  	/* after reset -> Default State */ -	dwc->dev_state = DWC3_DEFAULT_STATE; +	usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);  	/* Recent versions support automatic phy suspend and don't need this */  	if (dwc->revision < DWC3_REVISION_194A) { @@ -2277,6 +2348,34 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,  		unsigned int evtinfo)  {  	enum dwc3_link_state	next = evtinfo & DWC3_LINK_STATE_MASK; +	unsigned int		pwropt; + +	/* +	 * WORKAROUND: DWC3 < 2.50a have an issue when configured without +	 * Hibernation mode enabled which would show up when device detects +	 * host-initiated U3 exit. +	 * +	 * In that case, device will generate a Link State Change Interrupt +	 * from U3 to RESUME which is only necessary if Hibernation is +	 * configured in. +	 * +	 * There are no functional changes due to such spurious event and we +	 * just need to ignore it. +	 * +	 * Refers to: +	 * +	 * STAR#9000570034 RTL: SS Resume event generated in non-Hibernation +	 * operational mode +	 */ +	pwropt = DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1); +	if ((dwc->revision < DWC3_REVISION_250A) && +			(pwropt != DWC3_GHWPARAMS1_EN_PWROPT_HIB)) { +		if ((dwc->link_state == DWC3_LINK_STATE_U3) && +				(next == DWC3_LINK_STATE_RESUME)) { +			dev_vdbg(dwc->dev, "ignoring transition U3 -> Resume\n"); +			return; +		} +	}  	/*  	 * WORKAROUND: DWC3 Revisions <1.83a have an issue which, depending @@ -2387,40 +2486,73 @@ static void dwc3_process_event_entry(struct dwc3 *dwc,  	}  } +static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc) +{ +	struct dwc3 *dwc = _dwc; +	unsigned long flags; +	irqreturn_t ret = IRQ_NONE; +	int i; + +	spin_lock_irqsave(&dwc->lock, flags); + +	for (i = 0; i < dwc->num_event_buffers; i++) { +		struct dwc3_event_buffer *evt; +		int			left; + +		evt = dwc->ev_buffs[i]; +		left = evt->count; + +		if (!(evt->flags & DWC3_EVENT_PENDING)) +			continue; + +		while (left > 0) { +			union dwc3_event event; + +			event.raw = *(u32 *) (evt->buf + evt->lpos); + +			dwc3_process_event_entry(dwc, &event); + +			/* +			 * FIXME we wrap around correctly to the next entry as +			 * almost all entries are 4 bytes in size. There is one +			 * entry which has 12 bytes which is a regular entry +			 * followed by 8 bytes data. ATM I don't know how +			 * things are organized if we get next to the a +			 * boundary so I worry about that once we try to handle +			 * that. +			 */ +			evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE; +			left -= 4; + +			dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(i), 4); +		} + +		evt->count = 0; +		evt->flags &= ~DWC3_EVENT_PENDING; +		ret = IRQ_HANDLED; +	} + +	spin_unlock_irqrestore(&dwc->lock, flags); + +	return ret; +} +  static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)  {  	struct dwc3_event_buffer *evt; -	int left;  	u32 count; +	evt = dwc->ev_buffs[buf]; +  	count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf));  	count &= DWC3_GEVNTCOUNT_MASK;  	if (!count)  		return IRQ_NONE; -	evt = dwc->ev_buffs[buf]; -	left = count; - -	while (left > 0) { -		union dwc3_event event; - -		event.raw = *(u32 *) (evt->buf + evt->lpos); +	evt->count = count; +	evt->flags |= DWC3_EVENT_PENDING; -		dwc3_process_event_entry(dwc, &event); -		/* -		 * XXX we wrap around correctly to the next entry as almost all -		 * entries are 4 bytes in size. There is one entry which has 12 -		 * bytes which is a regular entry followed by 8 bytes data. ATM -		 * I don't know how things are organized if were get next to the -		 * a boundary so I worry about that once we try to handle that. -		 */ -		evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE; -		left -= 4; - -		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4); -	} - -	return IRQ_HANDLED; +	return IRQ_WAKE_THREAD;  }  static irqreturn_t dwc3_interrupt(int irq, void *_dwc) @@ -2435,7 +2567,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)  		irqreturn_t status;  		status = dwc3_process_event_buf(dwc, i); -		if (status == IRQ_HANDLED) +		if (status == IRQ_WAKE_THREAD)  			ret = status;  	} @@ -2454,7 +2586,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)  {  	u32					reg;  	int					ret; -	int					irq;  	dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),  			&dwc->ctrl_req_addr, GFP_KERNEL); @@ -2488,19 +2619,10 @@ int dwc3_gadget_init(struct dwc3 *dwc)  		goto err3;  	} -	dev_set_name(&dwc->gadget.dev, "gadget"); -  	dwc->gadget.ops			= &dwc3_gadget_ops;  	dwc->gadget.max_speed		= USB_SPEED_SUPER;  	dwc->gadget.speed		= USB_SPEED_UNKNOWN; -	dwc->gadget.dev.parent		= dwc->dev;  	dwc->gadget.sg_supported	= true; - -	dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask); - -	dwc->gadget.dev.dma_parms	= dwc->dev->dma_parms; -	dwc->gadget.dev.dma_mask	= dwc->dev->dma_mask; -	dwc->gadget.dev.release		= dwc3_gadget_release;  	dwc->gadget.name		= "dwc3-gadget";  	/* @@ -2512,60 +2634,24 @@ int dwc3_gadget_init(struct dwc3 *dwc)  	if (ret)  		goto err4; -	irq = platform_get_irq(to_platform_device(dwc->dev), 0); - -	ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED, -			"dwc3", dwc); -	if (ret) { -		dev_err(dwc->dev, "failed to request irq #%d --> %d\n", -				irq, ret); -		goto err5; -	} -  	reg = dwc3_readl(dwc->regs, DWC3_DCFG);  	reg |= DWC3_DCFG_LPM_CAP;  	dwc3_writel(dwc->regs, DWC3_DCFG, reg); -	/* Enable all but Start and End of Frame IRQs */ -	reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN | -			DWC3_DEVTEN_EVNTOVERFLOWEN | -			DWC3_DEVTEN_CMDCMPLTEN | -			DWC3_DEVTEN_ERRTICERREN | -			DWC3_DEVTEN_WKUPEVTEN | -			DWC3_DEVTEN_ULSTCNGEN | -			DWC3_DEVTEN_CONNECTDONEEN | -			DWC3_DEVTEN_USBRSTEN | -			DWC3_DEVTEN_DISCONNEVTEN); -	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); - -	/* automatic phy suspend only on recent versions */ +	/* Enable USB2 LPM and automatic phy suspend only on recent versions */  	if (dwc->revision >= DWC3_REVISION_194A) {  		dwc3_gadget_usb2_phy_suspend(dwc, false);  		dwc3_gadget_usb3_phy_suspend(dwc, false);  	} -	ret = device_register(&dwc->gadget.dev); -	if (ret) { -		dev_err(dwc->dev, "failed to register gadget device\n"); -		put_device(&dwc->gadget.dev); -		goto err6; -	} -  	ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);  	if (ret) {  		dev_err(dwc->dev, "failed to register udc\n"); -		goto err7; +		goto err5;  	}  	return 0; -err7: -	device_unregister(&dwc->gadget.dev); - -err6: -	dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); -	free_irq(irq, dwc); -  err5:  	dwc3_gadget_free_endpoints(dwc); @@ -2588,15 +2674,11 @@ err0:  	return ret;  } +/* -------------------------------------------------------------------------- */ +  void dwc3_gadget_exit(struct dwc3 *dwc)  { -	int			irq; -  	usb_del_gadget_udc(&dwc->gadget); -	irq = platform_get_irq(to_platform_device(dwc->dev), 0); - -	dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); -	free_irq(irq, dwc);  	dwc3_gadget_free_endpoints(dwc); @@ -2610,6 +2692,63 @@ void dwc3_gadget_exit(struct dwc3 *dwc)  	dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),  			dwc->ctrl_req, dwc->ctrl_req_addr); +} -	device_unregister(&dwc->gadget.dev); +int dwc3_gadget_prepare(struct dwc3 *dwc) +{ +	if (dwc->pullups_connected) +		dwc3_gadget_disable_irq(dwc); + +	return 0; +} + +void dwc3_gadget_complete(struct dwc3 *dwc) +{ +	if (dwc->pullups_connected) { +		dwc3_gadget_enable_irq(dwc); +		dwc3_gadget_run_stop(dwc, true); +	} +} + +int dwc3_gadget_suspend(struct dwc3 *dwc) +{ +	__dwc3_gadget_ep_disable(dwc->eps[0]); +	__dwc3_gadget_ep_disable(dwc->eps[1]); + +	dwc->dcfg = dwc3_readl(dwc->regs, DWC3_DCFG); + +	return 0; +} + +int dwc3_gadget_resume(struct dwc3 *dwc) +{ +	struct dwc3_ep		*dep; +	int			ret; + +	/* Start with SuperSpeed Default */ +	dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); + +	dep = dwc->eps[0]; +	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false); +	if (ret) +		goto err0; + +	dep = dwc->eps[1]; +	ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false); +	if (ret) +		goto err1; + +	/* begin to receive SETUP packets */ +	dwc->ep0state = EP0_SETUP_PHASE; +	dwc3_ep0_out_start(dwc); + +	dwc3_writel(dwc->regs, DWC3_DCFG, dwc->dcfg); + +	return 0; + +err1: +	__dwc3_gadget_ep_disable(dwc->eps[0]); + +err0: +	return ret;  } diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 5a0c541daf8..83300d94a89 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -144,7 +144,9 @@ config USB_AT91  config USB_LPC32XX  	tristate "LPC32XX USB Peripheral Controller"  	depends on ARCH_LPC32XX +	depends on USB_PHY  	select USB_ISP1301 +	select USB_OTG_UTILS  	help  	   This option selects the USB device controller in the LPC32xx SoC. @@ -194,8 +196,8 @@ config USB_FUSB300  config USB_OMAP  	tristate "OMAP USB Device Controller"  	depends on ARCH_OMAP1 +	depends on USB_PHY  	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG -	select USB_OTG_UTILS if ARCH_OMAP  	help  	   Many Texas Instruments OMAP processors have flexible full  	   speed USB device controllers, with support for up to 30 @@ -210,7 +212,6 @@ config USB_OMAP  config USB_PXA25X  	tristate "PXA 25x or IXP 4xx"  	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX -	select USB_OTG_UTILS  	help  	   Intel's PXA 25x series XScale ARM-5TE processors include  	   an integrated full speed USB 1.1 device controller.  The @@ -258,8 +259,6 @@ config USB_RENESAS_USBHS_UDC  config USB_PXA27X  	tristate "PXA 27x" -	depends on ARCH_PXA && (PXA27x || PXA3xx) -	select USB_OTG_UTILS  	help  	   Intel's PXA 27x series XScale ARM v5TE processors include  	   an integrated full speed USB 1.1 device controller. @@ -328,9 +327,6 @@ config USB_MV_UDC  config USB_MV_U3D  	tristate "MARVELL PXA2128 USB 3.0 controller" -	depends on CPU_MMP3 -	select USB_GADGET_DUALSPEED -	select USB_GADGET_SUPERSPEED  	help  	  MARVELL PXA2128 Processor series include a super speed USB3.0 device  	  controller, which support super speed USB peripheral. @@ -500,6 +496,7 @@ endmenu  # composite based drivers  config USB_LIBCOMPOSITE  	tristate +	select CONFIGFS_FS  	depends on USB_GADGET  config USB_F_ACM @@ -511,6 +508,12 @@ config USB_F_SS_LB  config USB_U_SERIAL  	tristate +config USB_F_SERIAL +	tristate + +config USB_F_OBEX +	tristate +  choice  	tristate "USB Gadget Drivers"  	default USB_ETH @@ -765,6 +768,8 @@ config USB_G_SERIAL  	depends on TTY  	select USB_U_SERIAL  	select USB_F_ACM +	select USB_F_SERIAL +	select USB_F_OBEX  	select USB_LIBCOMPOSITE  	help  	  The Serial Gadget talks to the Linux-USB generic serial driver. @@ -838,6 +843,7 @@ config USB_G_NOKIA  	depends on PHONET  	select USB_LIBCOMPOSITE  	select USB_U_SERIAL +	select USB_F_ACM  	help  	  The Nokia composite gadget provides support for acm, obex  	  and phonet in only one composite gadget driver. @@ -956,6 +962,7 @@ config USB_G_WEBCAM  	tristate "USB Webcam Gadget"  	depends on VIDEO_DEV  	select USB_LIBCOMPOSITE +	select VIDEOBUF2_VMALLOC  	help  	  The Webcam Gadget acts as a composite USB Audio and Video Class  	  device. It provides a userspace API to process UVC control requests diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 82fb2251135..6afd16659e7 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -6,7 +6,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG  obj-$(CONFIG_USB_GADGET)	+= udc-core.o  obj-$(CONFIG_USB_LIBCOMPOSITE)	+= libcomposite.o  libcomposite-y			:= usbstring.o config.o epautoconf.o -libcomposite-y			+= composite.o functions.o +libcomposite-y			+= composite.o functions.o configfs.o  obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o  obj-$(CONFIG_USB_NET2272)	+= net2272.o  obj-$(CONFIG_USB_NET2280)	+= net2280.o @@ -36,10 +36,15 @@ obj-$(CONFIG_USB_FUSB300)	+= fusb300_udc.o  obj-$(CONFIG_USB_MV_U3D)	+= mv_u3d_core.o  # USB Functions -obj-$(CONFIG_USB_F_ACM)		+= f_acm.o -f_ss_lb-y			:= f_loopback.o f_sourcesink.o -obj-$(CONFIG_USB_F_SS_LB)	+= f_ss_lb.o +usb_f_acm-y			:= f_acm.o +obj-$(CONFIG_USB_F_ACM)		+= usb_f_acm.o +usb_f_ss_lb-y			:= f_loopback.o f_sourcesink.o +obj-$(CONFIG_USB_F_SS_LB)	+= usb_f_ss_lb.o  obj-$(CONFIG_USB_U_SERIAL)	+= u_serial.o +usb_f_serial-y			:= f_serial.o +obj-$(CONFIG_USB_F_SERIAL)	+= usb_f_serial.o +usb_f_obex-y			:= f_obex.o +obj-$(CONFIG_USB_F_OBEX)	+= usb_f_obex.o  #  # USB gadget drivers diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c index 8f2b0e39153..4b947bb50f6 100644 --- a/drivers/usb/gadget/acm_ms.c +++ b/drivers/usb/gadget/acm_ms.c @@ -109,7 +109,6 @@ FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);  static struct fsg_common fsg_common;  /*-------------------------------------------------------------------------*/ -static unsigned char tty_line;  static struct usb_function *f_acm;  static struct usb_function_instance *f_acm_inst;  /* @@ -117,7 +116,6 @@ static struct usb_function_instance *f_acm_inst;   */  static int __init acm_ms_do_config(struct usb_configuration *c)  { -	struct f_serial_opts *opts;  	int	status;  	if (gadget_is_otg(c->cdev->gadget)) { @@ -129,9 +127,6 @@ static int __init acm_ms_do_config(struct usb_configuration *c)  	if (IS_ERR(f_acm_inst))  		return PTR_ERR(f_acm_inst); -	opts = container_of(f_acm_inst, struct f_serial_opts, func_inst); -	opts->port_num = tty_line; -  	f_acm = usb_get_function(f_acm_inst);  	if (IS_ERR(f_acm)) {  		status = PTR_ERR(f_acm); @@ -171,16 +166,11 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)  	int			status;  	void			*retp; -	/* set up serial link layer */ -	status = gserial_alloc_line(&tty_line); -	if (status < 0) -		return status; -  	/* set up mass storage function */  	retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);  	if (IS_ERR(retp)) {  		status = PTR_ERR(retp); -		goto fail0; +		return PTR_ERR(retp);  	}  	/* @@ -207,8 +197,6 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)  	/* error recovery */  fail1:  	fsg_common_put(&fsg_common); -fail0: -	gserial_free_line(tty_line);  	return status;  } @@ -216,7 +204,6 @@ static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)  {  	usb_put_function(f_acm);  	usb_put_function_instance(f_acm_inst); -	gserial_free_line(tty_line);  	return 0;  } diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 75973f33a4c..f52dcfe8f54 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -1922,7 +1922,6 @@ static int amd5536_udc_start(struct usb_gadget *g,  	driver->driver.bus = NULL;  	dev->driver = driver; -	dev->gadget.dev.driver = &driver->driver;  	/* Some gadget drivers use both ep0 directions.  	 * NOTE: to gadget driver, ep0 is just one endpoint... @@ -1973,7 +1972,6 @@ static int amd5536_udc_stop(struct usb_gadget *g,  	shutdown(dev, driver);  	spin_unlock_irqrestore(&dev->lock, flags); -	dev->gadget.dev.driver = NULL;  	dev->driver = NULL;  	/* set SD */ @@ -3080,7 +3078,6 @@ static void udc_pci_remove(struct pci_dev *pdev)  	if (dev->active)  		pci_disable_device(pdev); -	device_unregister(&dev->gadget.dev);  	pci_set_drvdata(pdev, NULL);  	udc_remove(dev); @@ -3245,8 +3242,6 @@ static int udc_pci_probe(  	dev->phys_addr = resource;  	dev->irq = pdev->irq;  	dev->pdev = pdev; -	dev->gadget.dev.parent = &pdev->dev; -	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;  	/* general probing */  	if (udc_probe(dev) == 0) @@ -3273,7 +3268,6 @@ static int udc_probe(struct udc *dev)  	dev->gadget.ops = &udc_ops;  	dev_set_name(&dev->gadget.dev, "gadget"); -	dev->gadget.dev.release = gadget_release;  	dev->gadget.name = name;  	dev->gadget.max_speed = USB_SPEED_HIGH; @@ -3297,17 +3291,11 @@ static int udc_probe(struct udc *dev)  		"driver version: %s(for Geode5536 B1)\n", tmp);  	udc = dev; -	retval = usb_add_gadget_udc(&udc->pdev->dev, &dev->gadget); +	retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget, +			gadget_release);  	if (retval)  		goto finished; -	retval = device_register(&dev->gadget.dev); -	if (retval) { -		usb_del_gadget_udc(&dev->gadget); -		put_device(&dev->gadget.dev); -		goto finished; -	} -  	/* timer init */  	init_timer(&udc_timer);  	udc_timer.function = udc_timer_function; diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/amd5536udc.h index f1bf32e6b8d..6744d3b8310 100644 --- a/drivers/usb/gadget/amd5536udc.h +++ b/drivers/usb/gadget/amd5536udc.h @@ -472,7 +472,6 @@ struct udc_request {  	/* flags */  	unsigned			dma_going : 1, -					dma_mapping : 1,  					dma_done : 1;  	/* phys. address */  	dma_addr_t			td_phys; diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 45dd2929a67..a690d64217f 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1631,7 +1631,6 @@ static int at91_start(struct usb_gadget *gadget,  	udc = container_of(gadget, struct at91_udc, gadget);  	udc->driver = driver; -	udc->gadget.dev.driver = &driver->driver;  	udc->gadget.dev.of_node = udc->pdev->dev.of_node;  	udc->enabled = 1;  	udc->selfpowered = 1; @@ -1652,7 +1651,6 @@ static int at91_stop(struct usb_gadget *gadget,  	at91_udp_write(udc, AT91_UDP_IDR, ~0);  	spin_unlock_irqrestore(&udc->lock, flags); -	udc->gadget.dev.driver = NULL;  	udc->driver = NULL;  	DBG("unbound from %s\n", driver->driver.name); @@ -1780,13 +1778,7 @@ static int at91udc_probe(struct platform_device *pdev)  		DBG("clocks missing\n");  		retval = -ENODEV;  		/* NOTE: we "know" here that refcounts on these are NOPs */ -		goto fail0b; -	} - -	retval = device_register(&udc->gadget.dev); -	if (retval < 0) { -		put_device(&udc->gadget.dev); -		goto fail0b; +		goto fail1;  	}  	/* don't do anything until we have both gadget driver and VBUS */ @@ -1857,8 +1849,6 @@ fail3:  fail2:  	free_irq(udc->udp_irq, udc);  fail1: -	device_unregister(&udc->gadget.dev); -fail0b:  	iounmap(udc->udp_baseaddr);  fail0a:  	if (cpu_is_at91rm9200()) @@ -1892,8 +1882,6 @@ static int __exit at91udc_remove(struct platform_device *pdev)  		gpio_free(udc->board.vbus_pin);  	}  	free_irq(udc->udp_irq, udc); -	device_unregister(&udc->gadget.dev); -  	iounmap(udc->udp_baseaddr);  	if (cpu_is_at91rm9200()) diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index b66130c9726..f2a970f75bf 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -489,13 +489,8 @@ request_complete(struct usba_ep *ep, struct usba_request *req, int status)  	if (req->req.status == -EINPROGRESS)  		req->req.status = status; -	if (req->mapped) { -		dma_unmap_single( -			&udc->pdev->dev, req->req.dma, req->req.length, -			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); -		req->req.dma = DMA_ADDR_INVALID; -		req->mapped = 0; -	} +	if (req->using_dma) +		usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);  	DBG(DBG_GADGET | DBG_REQ,  		"%s: req %p complete: status %d, actual %u\n", @@ -684,7 +679,6 @@ usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)  		return NULL;  	INIT_LIST_HEAD(&req->queue); -	req->req.dma = DMA_ADDR_INVALID;  	return &req->req;  } @@ -717,20 +711,11 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,  		return -EINVAL;  	} -	req->using_dma = 1; - -	if (req->req.dma == DMA_ADDR_INVALID) { -		req->req.dma = dma_map_single( -			&udc->pdev->dev, req->req.buf, req->req.length, -			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); -		req->mapped = 1; -	} else { -		dma_sync_single_for_device( -			&udc->pdev->dev, req->req.dma, req->req.length, -			ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); -		req->mapped = 0; -	} +	ret = usb_gadget_map_request(&udc->gadget, &req->req, ep->is_in); +	if (ret) +		return ret; +	req->using_dma = 1;  	req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length)  			| USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE  			| USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE; @@ -1799,7 +1784,6 @@ static int atmel_usba_start(struct usb_gadget *gadget,  	udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;  	udc->driver = driver; -	udc->gadget.dev.driver = &driver->driver;  	spin_unlock_irqrestore(&udc->lock, flags);  	clk_enable(udc->pclk); @@ -1841,7 +1825,6 @@ static int atmel_usba_stop(struct usb_gadget *gadget,  	toggle_bias(0);  	usba_writel(udc, CTRL, USBA_DISABLE_MASK); -	udc->gadget.dev.driver = NULL;  	udc->driver = NULL;  	clk_disable(udc->hclk); @@ -1900,10 +1883,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)  	dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",  		 (unsigned long)fifo->start, udc->fifo); -	device_initialize(&udc->gadget.dev); -	udc->gadget.dev.parent = &pdev->dev; -	udc->gadget.dev.dma_mask = pdev->dev.dma_mask; -  	platform_set_drvdata(pdev, udc);  	/* Make sure we start from a clean slate */ @@ -1962,12 +1941,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)  	}  	udc->irq = irq; -	ret = device_add(&udc->gadget.dev); -	if (ret) { -		dev_dbg(&pdev->dev, "Could not add gadget: %d\n", ret); -		goto err_device_add; -	} -  	if (gpio_is_valid(pdata->vbus_pin)) {  		if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {  			udc->vbus_pin = pdata->vbus_pin; @@ -2007,9 +1980,6 @@ err_add_udc:  		gpio_free(udc->vbus_pin);  	} -	device_unregister(&udc->gadget.dev); - -err_device_add:  	free_irq(irq, udc);  err_request_irq:  	kfree(usba_ep); @@ -2053,8 +2023,6 @@ static int __exit usba_udc_remove(struct platform_device *pdev)  	clk_put(udc->hclk);  	clk_put(udc->pclk); -	device_unregister(&udc->gadget.dev); -  	return 0;  } diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h index 9791259cbda..d65a61851d3 100644 --- a/drivers/usb/gadget/atmel_usba_udc.h +++ b/drivers/usb/gadget/atmel_usba_udc.h @@ -216,12 +216,6 @@  #define EP0_EPT_SIZE		USBA_EPT_SIZE_64  #define EP0_NR_BANKS		1 -/* - * REVISIT: Try to eliminate this value. Can we rely on req->mapped to - * provide this information? - */ -#define DMA_ADDR_INVALID (~(dma_addr_t)0) -  #define FIFO_IOMEM_ID	0  #define CTRL_IOMEM_ID	1 diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c index 8cc8253f110..6e6518264c4 100644 --- a/drivers/usb/gadget/bcm63xx_udc.c +++ b/drivers/usb/gadget/bcm63xx_udc.c @@ -1819,7 +1819,6 @@ static int bcm63xx_udc_start(struct usb_gadget *gadget,  	udc->driver = driver;  	driver->driver.bus = NULL; -	udc->gadget.dev.driver = &driver->driver;  	udc->gadget.dev.of_node = udc->dev->of_node;  	spin_unlock_irqrestore(&udc->lock, flags); @@ -1841,7 +1840,6 @@ static int bcm63xx_udc_stop(struct usb_gadget *gadget,  	spin_lock_irqsave(&udc->lock, flags);  	udc->driver = NULL; -	udc->gadget.dev.driver = NULL;  	/*  	 * If we switch the PHY too abruptly after dropping D+, the host @@ -2306,17 +2304,6 @@ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc)   ***********************************************************************/  /** - * bcm63xx_udc_gadget_release - Called from device_release(). - * @dev: Unused. - * - * We get a warning if this function doesn't exist, but it's empty because - * we don't have to free any of the memory allocated with the devm_* APIs. - */ -static void bcm63xx_udc_gadget_release(struct device *dev) -{ -} - -/**   * bcm63xx_udc_probe - Initialize a new instance of the UDC.   * @pdev: Platform device struct from the bcm63xx BSP code.   * @@ -2368,13 +2355,9 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)  	spin_lock_init(&udc->lock);  	INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process); -	dev_set_name(&udc->gadget.dev, "gadget");  	udc->gadget.ops = &bcm63xx_udc_ops;  	udc->gadget.name = dev_name(dev); -	udc->gadget.dev.parent = dev; -	udc->gadget.dev.release = bcm63xx_udc_gadget_release; -	udc->gadget.dev.dma_mask = dev->dma_mask;  	if (!pd->use_fullspeed && !use_fullspeed)  		udc->gadget.max_speed = USB_SPEED_HIGH; @@ -2414,17 +2397,12 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)  		}  	} -	rc = device_register(&udc->gadget.dev); -	if (rc) -		goto out_uninit; -  	bcm63xx_udc_init_debugfs(udc);  	rc = usb_add_gadget_udc(dev, &udc->gadget);  	if (!rc)  		return 0;  	bcm63xx_udc_cleanup_debugfs(udc); -	device_unregister(&udc->gadget.dev);  out_uninit:  	bcm63xx_uninit_udc_hw(udc);  	return rc; @@ -2440,7 +2418,6 @@ static int bcm63xx_udc_remove(struct platform_device *pdev)  	bcm63xx_udc_cleanup_debugfs(udc);  	usb_del_gadget_udc(&udc->gadget); -	device_unregister(&udc->gadget.dev);  	BUG_ON(udc->driver);  	platform_set_drvdata(pdev, NULL); diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index a7d6f702675..2c525518276 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -103,18 +103,16 @@ static struct usb_gadget_strings *dev_strings[] = {  };  static u8 hostaddr[ETH_ALEN]; - +static struct eth_dev *the_dev;  /*-------------------------------------------------------------------------*/  static struct usb_function *f_acm;  static struct usb_function_instance *fi_serial; -static unsigned char tty_line;  /*   * We _always_ have both CDC ECM and CDC ACM functions.   */  static int __init cdc_do_config(struct usb_configuration *c)  { -	struct f_serial_opts *opts;  	int	status;  	if (gadget_is_otg(c->cdev->gadget)) { @@ -122,7 +120,7 @@ static int __init cdc_do_config(struct usb_configuration *c)  		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;  	} -	status = ecm_bind_config(c, hostaddr); +	status = ecm_bind_config(c, hostaddr, the_dev);  	if (status < 0)  		return status; @@ -130,12 +128,11 @@ static int __init cdc_do_config(struct usb_configuration *c)  	if (IS_ERR(fi_serial))  		return PTR_ERR(fi_serial); -	opts = container_of(fi_serial, struct f_serial_opts, func_inst); -	opts->port_num = tty_line; -  	f_acm = usb_get_function(fi_serial); -	if (IS_ERR(f_acm)) +	if (IS_ERR(f_acm)) { +		status = PTR_ERR(f_acm);  		goto err_func_acm; +	}  	status = usb_add_function(c, f_acm);  	if (status) @@ -169,14 +166,9 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)  	}  	/* set up network link layer */ -	status = gether_setup(cdev->gadget, hostaddr); -	if (status < 0) -		return status; - -	/* set up serial link layer */ -	status = gserial_alloc_line(&tty_line); -	if (status < 0) -		goto fail0; +	the_dev = gether_setup(cdev->gadget, hostaddr); +	if (IS_ERR(the_dev)) +		return PTR_ERR(the_dev);  	/* Allocate string descriptor numbers ... note that string  	 * contents can be overridden by the composite_dev glue. @@ -200,9 +192,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)  	return 0;  fail1: -	gserial_free_line(tty_line); -fail0: -	gether_cleanup(); +	gether_cleanup(the_dev);  	return status;  } @@ -210,8 +200,7 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev)  {  	usb_put_function(f_acm);  	usb_put_function_instance(fi_serial); -	gserial_free_line(tty_line); -	gether_cleanup(); +	gether_cleanup(the_dev);  	return 0;  } diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index c0d62b27861..55f4df60f32 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1637,6 +1637,7 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)  		kfree(cdev->req->buf);  		usb_ep_free_request(cdev->gadget->ep0, cdev->req);  	} +	cdev->next_string_id = 0;  	device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);  } diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c new file mode 100644 index 00000000000..3d5cfc9c2c7 --- /dev/null +++ b/drivers/usb/gadget/configfs.c @@ -0,0 +1,1003 @@ +#include <linux/configfs.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/device.h> +#include <linux/usb/composite.h> +#include <linux/usb/gadget_configfs.h> + +int check_user_usb_string(const char *name, +		struct usb_gadget_strings *stringtab_dev) +{ +	unsigned primary_lang; +	unsigned sub_lang; +	u16 num; +	int ret; + +	ret = kstrtou16(name, 0, &num); +	if (ret) +		return ret; + +	primary_lang = num & 0x3ff; +	sub_lang = num >> 10; + +	/* simple sanity check for valid langid */ +	switch (primary_lang) { +	case 0: +	case 0x62 ... 0xfe: +	case 0x100 ... 0x3ff: +		return -EINVAL; +	} +	if (!sub_lang) +		return -EINVAL; + +	stringtab_dev->language = num; +	return 0; +} + +#define MAX_NAME_LEN	40 +#define MAX_USB_STRING_LANGS 2 + +struct gadget_info { +	struct config_group group; +	struct config_group functions_group; +	struct config_group configs_group; +	struct config_group strings_group; +	struct config_group *default_groups[4]; + +	struct mutex lock; +	struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1]; +	struct list_head string_list; +	struct list_head available_func; + +	const char *udc_name; +#ifdef CONFIG_USB_OTG +	struct usb_otg_descriptor otg; +#endif +	struct usb_composite_driver composite; +	struct usb_composite_dev cdev; +}; + +struct config_usb_cfg { +	struct config_group group; +	struct config_group strings_group; +	struct config_group *default_groups[2]; +	struct list_head string_list; +	struct usb_configuration c; +	struct list_head func_list; +	struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1]; +}; + +struct gadget_strings { +	struct usb_gadget_strings stringtab_dev; +	struct usb_string strings[USB_GADGET_FIRST_AVAIL_IDX]; +	char *manufacturer; +	char *product; +	char *serialnumber; + +	struct config_group group; +	struct list_head list; +}; + +struct gadget_config_name { +	struct usb_gadget_strings stringtab_dev; +	struct usb_string strings; +	char *configuration; + +	struct config_group group; +	struct list_head list; +}; + +static int usb_string_copy(const char *s, char **s_copy) +{ +	int ret; +	char *str; +	char *copy = *s_copy; +	ret = strlen(s); +	if (ret > 126) +		return -EOVERFLOW; + +	str = kstrdup(s, GFP_KERNEL); +	if (!str) +		return -ENOMEM; +	if (str[ret - 1] == '\n') +		str[ret - 1] = '\0'; +	kfree(copy); +	*s_copy = str; +	return 0; +} + +CONFIGFS_ATTR_STRUCT(gadget_info); +CONFIGFS_ATTR_STRUCT(config_usb_cfg); + +#define GI_DEVICE_DESC_ITEM_ATTR(name)	\ +	static struct gadget_info_attribute gadget_cdev_desc_##name = \ +		__CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,		\ +				gadget_dev_desc_##name##_show,		\ +				gadget_dev_desc_##name##_store) + +#define GI_DEVICE_DESC_SIMPLE_R_u8(__name)	\ +	static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \ +			char *page)	\ +{	\ +	return sprintf(page, "0x%02x\n", gi->cdev.desc.__name);	\ +} + +#define GI_DEVICE_DESC_SIMPLE_R_u16(__name)	\ +	static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \ +			char *page)	\ +{	\ +	return sprintf(page, "0x%04x\n", le16_to_cpup(&gi->cdev.desc.__name)); \ +} + + +#define GI_DEVICE_DESC_SIMPLE_W_u8(_name)		\ +	static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \ +		const char *page, size_t len)		\ +{							\ +	u8 val;						\ +	int ret;					\ +	ret = kstrtou8(page, 0, &val);			\ +	if (ret)					\ +		return ret;				\ +	gi->cdev.desc._name = val;			\ +	return len;					\ +} + +#define GI_DEVICE_DESC_SIMPLE_W_u16(_name)	\ +	static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \ +		const char *page, size_t len)		\ +{							\ +	u16 val;					\ +	int ret;					\ +	ret = kstrtou16(page, 0, &val);			\ +	if (ret)					\ +		return ret;				\ +	gi->cdev.desc._name = cpu_to_le16p(&val);	\ +	return len;					\ +} + +#define GI_DEVICE_DESC_SIMPLE_RW(_name, _type)	\ +	GI_DEVICE_DESC_SIMPLE_R_##_type(_name)	\ +	GI_DEVICE_DESC_SIMPLE_W_##_type(_name) + +GI_DEVICE_DESC_SIMPLE_R_u16(bcdUSB); +GI_DEVICE_DESC_SIMPLE_RW(bDeviceClass, u8); +GI_DEVICE_DESC_SIMPLE_RW(bDeviceSubClass, u8); +GI_DEVICE_DESC_SIMPLE_RW(bDeviceProtocol, u8); +GI_DEVICE_DESC_SIMPLE_RW(bMaxPacketSize0, u8); +GI_DEVICE_DESC_SIMPLE_RW(idVendor, u16); +GI_DEVICE_DESC_SIMPLE_RW(idProduct, u16); +GI_DEVICE_DESC_SIMPLE_R_u16(bcdDevice); + +static ssize_t is_valid_bcd(u16 bcd_val) +{ +	if ((bcd_val & 0xf) > 9) +		return -EINVAL; +	if (((bcd_val >> 4) & 0xf) > 9) +		return -EINVAL; +	if (((bcd_val >> 8) & 0xf) > 9) +		return -EINVAL; +	if (((bcd_val >> 12) & 0xf) > 9) +		return -EINVAL; +	return 0; +} + +static ssize_t gadget_dev_desc_bcdDevice_store(struct gadget_info *gi, +		const char *page, size_t len) +{ +	u16 bcdDevice; +	int ret; + +	ret = kstrtou16(page, 0, &bcdDevice); +	if (ret) +		return ret; +	ret = is_valid_bcd(bcdDevice); +	if (ret) +		return ret; + +	gi->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice); +	return len; +} + +static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi, +		const char *page, size_t len) +{ +	u16 bcdUSB; +	int ret; + +	ret = kstrtou16(page, 0, &bcdUSB); +	if (ret) +		return ret; +	ret = is_valid_bcd(bcdUSB); +	if (ret) +		return ret; + +	gi->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB); +	return len; +} + +static ssize_t gadget_dev_desc_UDC_show(struct gadget_info *gi, char *page) +{ +	return sprintf(page, "%s\n", gi->udc_name ?: ""); +} + +static int unregister_gadget(struct gadget_info *gi) +{ +	int ret; + +	if (!gi->udc_name) +		return -ENODEV; + +	ret = usb_gadget_unregister_driver(&gi->composite.gadget_driver); +	if (ret) +		return ret; +	kfree(gi->udc_name); +	gi->udc_name = NULL; +	return 0; +} + +static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi, +		const char *page, size_t len) +{ +	char *name; +	int ret; + +	name = kstrdup(page, GFP_KERNEL); +	if (!name) +		return -ENOMEM; +	if (name[len - 1] == '\n') +		name[len - 1] = '\0'; + +	mutex_lock(&gi->lock); + +	if (!strlen(name)) { +		ret = unregister_gadget(gi); +		if (ret) +			goto err; +	} else { +		if (gi->udc_name) { +			ret = -EBUSY; +			goto err; +		} +		ret = udc_attach_driver(name, &gi->composite.gadget_driver); +		if (ret) +			goto err; +		gi->udc_name = name; +	} +	mutex_unlock(&gi->lock); +	return len; +err: +	kfree(name); +	mutex_unlock(&gi->lock); +	return ret; +} + +GI_DEVICE_DESC_ITEM_ATTR(bDeviceClass); +GI_DEVICE_DESC_ITEM_ATTR(bDeviceSubClass); +GI_DEVICE_DESC_ITEM_ATTR(bDeviceProtocol); +GI_DEVICE_DESC_ITEM_ATTR(bMaxPacketSize0); +GI_DEVICE_DESC_ITEM_ATTR(idVendor); +GI_DEVICE_DESC_ITEM_ATTR(idProduct); +GI_DEVICE_DESC_ITEM_ATTR(bcdDevice); +GI_DEVICE_DESC_ITEM_ATTR(bcdUSB); +GI_DEVICE_DESC_ITEM_ATTR(UDC); + +static struct configfs_attribute *gadget_root_attrs[] = { +	&gadget_cdev_desc_bDeviceClass.attr, +	&gadget_cdev_desc_bDeviceSubClass.attr, +	&gadget_cdev_desc_bDeviceProtocol.attr, +	&gadget_cdev_desc_bMaxPacketSize0.attr, +	&gadget_cdev_desc_idVendor.attr, +	&gadget_cdev_desc_idProduct.attr, +	&gadget_cdev_desc_bcdDevice.attr, +	&gadget_cdev_desc_bcdUSB.attr, +	&gadget_cdev_desc_UDC.attr, +	NULL, +}; + +static inline struct gadget_info *to_gadget_info(struct config_item *item) +{ +	 return container_of(to_config_group(item), struct gadget_info, group); +} + +static inline struct gadget_strings *to_gadget_strings(struct config_item *item) +{ +	 return container_of(to_config_group(item), struct gadget_strings, +			 group); +} + +static inline struct gadget_config_name *to_gadget_config_name( +		struct config_item *item) +{ +	 return container_of(to_config_group(item), struct gadget_config_name, +			 group); +} + +static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item) +{ +	return container_of(to_config_group(item), struct config_usb_cfg, +			group); +} + +static inline struct usb_function_instance *to_usb_function_instance( +		struct config_item *item) +{ +	 return container_of(to_config_group(item), +			 struct usb_function_instance, group); +} + +static void gadget_info_attr_release(struct config_item *item) +{ +	struct gadget_info *gi = to_gadget_info(item); + +	WARN_ON(!list_empty(&gi->cdev.configs)); +	WARN_ON(!list_empty(&gi->string_list)); +	WARN_ON(!list_empty(&gi->available_func)); +	kfree(gi->composite.gadget_driver.function); +	kfree(gi); +} + +CONFIGFS_ATTR_OPS(gadget_info); + +static struct configfs_item_operations gadget_root_item_ops = { +	.release                = gadget_info_attr_release, +	.show_attribute         = gadget_info_attr_show, +	.store_attribute        = gadget_info_attr_store, +}; + +static void gadget_config_attr_release(struct config_item *item) +{ +	struct config_usb_cfg *cfg = to_config_usb_cfg(item); + +	WARN_ON(!list_empty(&cfg->c.functions)); +	list_del(&cfg->c.list); +	kfree(cfg->c.label); +	kfree(cfg); +} + +static int config_usb_cfg_link( +	struct config_item *usb_cfg_ci, +	struct config_item *usb_func_ci) +{ +	struct config_usb_cfg *cfg = to_config_usb_cfg(usb_cfg_ci); +	struct usb_composite_dev *cdev = cfg->c.cdev; +	struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev); + +	struct config_group *group = to_config_group(usb_func_ci); +	struct usb_function_instance *fi = container_of(group, +			struct usb_function_instance, group); +	struct usb_function_instance *a_fi; +	struct usb_function *f; +	int ret; + +	mutex_lock(&gi->lock); +	/* +	 * Make sure this function is from within our _this_ gadget and not +	 * from another gadget or a random directory. +	 * Also a function instance can only be linked once. +	 */ +	list_for_each_entry(a_fi, &gi->available_func, cfs_list) { +		if (a_fi == fi) +			break; +	} +	if (a_fi != fi) { +		ret = -EINVAL; +		goto out; +	} + +	list_for_each_entry(f, &cfg->func_list, list) { +		if (f->fi == fi) { +			ret = -EEXIST; +			goto out; +		} +	} + +	f = usb_get_function(fi); +	if (IS_ERR(f)) { +		ret = PTR_ERR(f); +		goto out; +	} + +	/* stash the function until we bind it to the gadget */ +	list_add_tail(&f->list, &cfg->func_list); +	ret = 0; +out: +	mutex_unlock(&gi->lock); +	return ret; +} + +static int config_usb_cfg_unlink( +	struct config_item *usb_cfg_ci, +	struct config_item *usb_func_ci) +{ +	struct config_usb_cfg *cfg = to_config_usb_cfg(usb_cfg_ci); +	struct usb_composite_dev *cdev = cfg->c.cdev; +	struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev); + +	struct config_group *group = to_config_group(usb_func_ci); +	struct usb_function_instance *fi = container_of(group, +			struct usb_function_instance, group); +	struct usb_function *f; + +	/* +	 * ideally I would like to forbid to unlink functions while a gadget is +	 * bound to an UDC. Since this isn't possible at the moment, we simply +	 * force an unbind, the function is available here and then we can +	 * remove the function. +	 */ +	mutex_lock(&gi->lock); +	if (gi->udc_name) +		unregister_gadget(gi); +	WARN_ON(gi->udc_name); + +	list_for_each_entry(f, &cfg->func_list, list) { +		if (f->fi == fi) { +			list_del(&f->list); +			usb_put_function(f); +			mutex_unlock(&gi->lock); +			return 0; +		} +	} +	mutex_unlock(&gi->lock); +	WARN(1, "Unable to locate function to unbind\n"); +	return 0; +} + +CONFIGFS_ATTR_OPS(config_usb_cfg); + +static struct configfs_item_operations gadget_config_item_ops = { +	.release                = gadget_config_attr_release, +	.show_attribute         = config_usb_cfg_attr_show, +	.store_attribute        = config_usb_cfg_attr_store, +	.allow_link             = config_usb_cfg_link, +	.drop_link              = config_usb_cfg_unlink, +}; + + +static ssize_t gadget_config_desc_MaxPower_show(struct config_usb_cfg *cfg, +		char *page) +{ +	return sprintf(page, "%u\n", cfg->c.MaxPower); +} + +static ssize_t gadget_config_desc_MaxPower_store(struct config_usb_cfg *cfg, +		const char *page, size_t len) +{ +	u16 val; +	int ret; +	ret = kstrtou16(page, 0, &val); +	if (ret) +		return ret; +	if (DIV_ROUND_UP(val, 8) > 0xff) +		return -ERANGE; +	cfg->c.MaxPower = val; +	return len; +} + +static ssize_t gadget_config_desc_bmAttributes_show(struct config_usb_cfg *cfg, +		char *page) +{ +	return sprintf(page, "0x%02x\n", cfg->c.bmAttributes); +} + +static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg, +		const char *page, size_t len) +{ +	u8 val; +	int ret; +	ret = kstrtou8(page, 0, &val); +	if (ret) +		return ret; +	if (!(val & USB_CONFIG_ATT_ONE)) +		return -EINVAL; +	if (val & ~(USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER | +				USB_CONFIG_ATT_WAKEUP)) +		return -EINVAL; +	cfg->c.bmAttributes = val; +	return len; +} + +#define CFG_CONFIG_DESC_ITEM_ATTR(name)	\ +	static struct config_usb_cfg_attribute gadget_usb_cfg_##name = \ +		__CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,		\ +				gadget_config_desc_##name##_show,	\ +				gadget_config_desc_##name##_store) + +CFG_CONFIG_DESC_ITEM_ATTR(MaxPower); +CFG_CONFIG_DESC_ITEM_ATTR(bmAttributes); + +static struct configfs_attribute *gadget_config_attrs[] = { +	&gadget_usb_cfg_MaxPower.attr, +	&gadget_usb_cfg_bmAttributes.attr, +	NULL, +}; + +static struct config_item_type gadget_config_type = { +	.ct_item_ops	= &gadget_config_item_ops, +	.ct_attrs	= gadget_config_attrs, +	.ct_owner	= THIS_MODULE, +}; + +static struct config_item_type gadget_root_type = { +	.ct_item_ops	= &gadget_root_item_ops, +	.ct_attrs	= gadget_root_attrs, +	.ct_owner	= THIS_MODULE, +}; + +static void composite_init_dev(struct usb_composite_dev *cdev) +{ +	spin_lock_init(&cdev->lock); +	INIT_LIST_HEAD(&cdev->configs); +	INIT_LIST_HEAD(&cdev->gstrings); +} + +static struct config_group *function_make( +		struct config_group *group, +		const char *name) +{ +	struct gadget_info *gi; +	struct usb_function_instance *fi; +	char buf[MAX_NAME_LEN]; +	char *func_name; +	char *instance_name; +	int ret; + +	ret = snprintf(buf, MAX_NAME_LEN, "%s", name); +	if (ret >= MAX_NAME_LEN) +		return ERR_PTR(-ENAMETOOLONG); + +	func_name = buf; +	instance_name = strchr(func_name, '.'); +	if (!instance_name) { +		pr_err("Unable to locate . in FUNC.INSTANCE\n"); +		return ERR_PTR(-EINVAL); +	} +	*instance_name = '\0'; +	instance_name++; + +	fi = usb_get_function_instance(func_name); +	if (IS_ERR(fi)) +		return ERR_PTR(PTR_ERR(fi)); + +	ret = config_item_set_name(&fi->group.cg_item, name); +	if (ret) { +		usb_put_function_instance(fi); +		return ERR_PTR(ret); +	} + +	gi = container_of(group, struct gadget_info, functions_group); + +	mutex_lock(&gi->lock); +	list_add_tail(&fi->cfs_list, &gi->available_func); +	mutex_unlock(&gi->lock); +	return &fi->group; +} + +static void function_drop( +		struct config_group *group, +		struct config_item *item) +{ +	struct usb_function_instance *fi = to_usb_function_instance(item); +	struct gadget_info *gi; + +	gi = container_of(group, struct gadget_info, functions_group); + +	mutex_lock(&gi->lock); +	list_del(&fi->cfs_list); +	mutex_unlock(&gi->lock); +	config_item_put(item); +} + +static struct configfs_group_operations functions_ops = { +	.make_group     = &function_make, +	.drop_item      = &function_drop, +}; + +static struct config_item_type functions_type = { +	.ct_group_ops   = &functions_ops, +	.ct_owner       = THIS_MODULE, +}; + +CONFIGFS_ATTR_STRUCT(gadget_config_name); +GS_STRINGS_RW(gadget_config_name, configuration); + +static struct configfs_attribute *gadget_config_name_langid_attrs[] = { +	&gadget_config_name_configuration.attr, +	NULL, +}; + +static void gadget_config_name_attr_release(struct config_item *item) +{ +	struct gadget_config_name *cn = to_gadget_config_name(item); + +	kfree(cn->configuration); + +	list_del(&cn->list); +	kfree(cn); +} + +USB_CONFIG_STRING_RW_OPS(gadget_config_name); +USB_CONFIG_STRINGS_LANG(gadget_config_name, config_usb_cfg); + +static struct config_group *config_desc_make( +		struct config_group *group, +		const char *name) +{ +	struct gadget_info *gi; +	struct config_usb_cfg *cfg; +	char buf[MAX_NAME_LEN]; +	char *num_str; +	u8 num; +	int ret; + +	gi = container_of(group, struct gadget_info, configs_group); +	ret = snprintf(buf, MAX_NAME_LEN, "%s", name); +	if (ret >= MAX_NAME_LEN) +		return ERR_PTR(-ENAMETOOLONG); + +	num_str = strchr(buf, '.'); +	if (!num_str) { +		pr_err("Unable to locate . in name.bConfigurationValue\n"); +		return ERR_PTR(-EINVAL); +	} + +	*num_str = '\0'; +	num_str++; + +	if (!strlen(buf)) +		return ERR_PTR(-EINVAL); + +	ret = kstrtou8(num_str, 0, &num); +	if (ret) +		return ERR_PTR(ret); + +	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); +	if (!cfg) +		return ERR_PTR(-ENOMEM); +	cfg->c.label = kstrdup(buf, GFP_KERNEL); +	if (!cfg->c.label) { +		ret = -ENOMEM; +		goto err; +	} +	cfg->c.bConfigurationValue = num; +	cfg->c.MaxPower = CONFIG_USB_GADGET_VBUS_DRAW; +	cfg->c.bmAttributes = USB_CONFIG_ATT_ONE; +	INIT_LIST_HEAD(&cfg->string_list); +	INIT_LIST_HEAD(&cfg->func_list); + +	cfg->group.default_groups = cfg->default_groups; +	cfg->default_groups[0] = &cfg->strings_group; + +	config_group_init_type_name(&cfg->group, name, +				&gadget_config_type); +	config_group_init_type_name(&cfg->strings_group, "strings", +			&gadget_config_name_strings_type); + +	ret = usb_add_config_only(&gi->cdev, &cfg->c); +	if (ret) +		goto err; + +	return &cfg->group; +err: +	kfree(cfg->c.label); +	kfree(cfg); +	return ERR_PTR(ret); +} + +static void config_desc_drop( +		struct config_group *group, +		struct config_item *item) +{ +	config_item_put(item); +} + +static struct configfs_group_operations config_desc_ops = { +	.make_group     = &config_desc_make, +	.drop_item      = &config_desc_drop, +}; + +static struct config_item_type config_desc_type = { +	.ct_group_ops   = &config_desc_ops, +	.ct_owner       = THIS_MODULE, +}; + +CONFIGFS_ATTR_STRUCT(gadget_strings); +GS_STRINGS_RW(gadget_strings, manufacturer); +GS_STRINGS_RW(gadget_strings, product); +GS_STRINGS_RW(gadget_strings, serialnumber); + +static struct configfs_attribute *gadget_strings_langid_attrs[] = { +	&gadget_strings_manufacturer.attr, +	&gadget_strings_product.attr, +	&gadget_strings_serialnumber.attr, +	NULL, +}; + +static void gadget_strings_attr_release(struct config_item *item) +{ +	struct gadget_strings *gs = to_gadget_strings(item); + +	kfree(gs->manufacturer); +	kfree(gs->product); +	kfree(gs->serialnumber); + +	list_del(&gs->list); +	kfree(gs); +} + +USB_CONFIG_STRING_RW_OPS(gadget_strings); +USB_CONFIG_STRINGS_LANG(gadget_strings, gadget_info); + +static int configfs_do_nothing(struct usb_composite_dev *cdev) +{ +	WARN_ON(1); +	return -EINVAL; +} + +int composite_dev_prepare(struct usb_composite_driver *composite, +		struct usb_composite_dev *dev); + +static void purge_configs_funcs(struct gadget_info *gi) +{ +	struct usb_configuration	*c; + +	list_for_each_entry(c, &gi->cdev.configs, list) { +		struct usb_function *f, *tmp; +		struct config_usb_cfg *cfg; + +		cfg = container_of(c, struct config_usb_cfg, c); + +		list_for_each_entry_safe(f, tmp, &c->functions, list) { + +			list_move_tail(&f->list, &cfg->func_list); +			if (f->unbind) { +				dev_err(&gi->cdev.gadget->dev, "unbind function" +						" '%s'/%p\n", f->name, f); +				f->unbind(c, f); +			} +		} +		c->next_interface_id = 0; +		c->superspeed = 0; +		c->highspeed = 0; +		c->fullspeed = 0; +	} +} + +static int configfs_composite_bind(struct usb_gadget *gadget, +		struct usb_gadget_driver *gdriver) +{ +	struct usb_composite_driver     *composite = to_cdriver(gdriver); +	struct gadget_info		*gi = container_of(composite, +						struct gadget_info, composite); +	struct usb_composite_dev	*cdev = &gi->cdev; +	struct usb_configuration	*c; +	struct usb_string		*s; +	unsigned			i; +	int				ret; + +	/* the gi->lock is hold by the caller */ +	cdev->gadget = gadget; +	set_gadget_data(gadget, cdev); +	ret = composite_dev_prepare(composite, cdev); +	if (ret) +		return ret; +	/* and now the gadget bind */ +	ret = -EINVAL; + +	if (list_empty(&gi->cdev.configs)) { +		pr_err("Need atleast one configuration in %s.\n", +				gi->composite.name); +		goto err_comp_cleanup; +	} + + +	list_for_each_entry(c, &gi->cdev.configs, list) { +		struct config_usb_cfg *cfg; + +		cfg = container_of(c, struct config_usb_cfg, c); +		if (list_empty(&cfg->func_list)) { +			pr_err("Config %s/%d of %s needs atleast one function.\n", +			      c->label, c->bConfigurationValue, +			      gi->composite.name); +			goto err_comp_cleanup; +		} +	} + +	/* init all strings */ +	if (!list_empty(&gi->string_list)) { +		struct gadget_strings *gs; + +		i = 0; +		list_for_each_entry(gs, &gi->string_list, list) { + +			gi->gstrings[i] = &gs->stringtab_dev; +			gs->stringtab_dev.strings = gs->strings; +			gs->strings[USB_GADGET_MANUFACTURER_IDX].s = +				gs->manufacturer; +			gs->strings[USB_GADGET_PRODUCT_IDX].s = gs->product; +			gs->strings[USB_GADGET_SERIAL_IDX].s = gs->serialnumber; +			i++; +		} +		gi->gstrings[i] = NULL; +		s = usb_gstrings_attach(&gi->cdev, gi->gstrings, +				USB_GADGET_FIRST_AVAIL_IDX); +		if (IS_ERR(s)) +			goto err_comp_cleanup; + +		gi->cdev.desc.iManufacturer = s[USB_GADGET_MANUFACTURER_IDX].id; +		gi->cdev.desc.iProduct = s[USB_GADGET_PRODUCT_IDX].id; +		gi->cdev.desc.iSerialNumber = s[USB_GADGET_SERIAL_IDX].id; +	} + +	/* Go through all configs, attach all functions */ +	list_for_each_entry(c, &gi->cdev.configs, list) { +		struct config_usb_cfg *cfg; +		struct usb_function *f; +		struct usb_function *tmp; +		struct gadget_config_name *cn; + +		cfg = container_of(c, struct config_usb_cfg, c); +		if (!list_empty(&cfg->string_list)) { +			i = 0; +			list_for_each_entry(cn, &cfg->string_list, list) { +				cfg->gstrings[i] = &cn->stringtab_dev; +				cn->stringtab_dev.strings = &cn->strings; +				cn->strings.s = cn->configuration; +				i++; +			} +			cfg->gstrings[i] = NULL; +			s = usb_gstrings_attach(&gi->cdev, cfg->gstrings, 1); +			if (IS_ERR(s)) +				goto err_comp_cleanup; +			c->iConfiguration = s[0].id; +		} + +		list_for_each_entry_safe(f, tmp, &cfg->func_list, list) { +			list_del(&f->list); +			ret = usb_add_function(c, f); +			if (ret) +				goto err_purge_funcs; +		} +		usb_ep_autoconfig_reset(cdev->gadget); +	} +	usb_ep_autoconfig_reset(cdev->gadget); +	return 0; + +err_purge_funcs: +	purge_configs_funcs(gi); +err_comp_cleanup: +	composite_dev_cleanup(cdev); +	return ret; +} + +static void configfs_composite_unbind(struct usb_gadget *gadget) +{ +	struct usb_composite_dev	*cdev; +	struct gadget_info		*gi; + +	/* the gi->lock is hold by the caller */ + +	cdev = get_gadget_data(gadget); +	gi = container_of(cdev, struct gadget_info, cdev); + +	purge_configs_funcs(gi); +	composite_dev_cleanup(cdev); +	usb_ep_autoconfig_reset(cdev->gadget); +	cdev->gadget = NULL; +	set_gadget_data(gadget, NULL); +} + +static const struct usb_gadget_driver configfs_driver_template = { +	.bind           = configfs_composite_bind, +	.unbind         = configfs_composite_unbind, + +	.setup          = composite_setup, +	.disconnect     = composite_disconnect, + +	.max_speed	= USB_SPEED_SUPER, +	.driver = { +		.owner          = THIS_MODULE, +		.name		= "configfs-gadget", +	}, +}; + +static struct config_group *gadgets_make( +		struct config_group *group, +		const char *name) +{ +	struct gadget_info *gi; + +	gi = kzalloc(sizeof(*gi), GFP_KERNEL); +	if (!gi) +		return ERR_PTR(-ENOMEM); + +	gi->group.default_groups = gi->default_groups; +	gi->group.default_groups[0] = &gi->functions_group; +	gi->group.default_groups[1] = &gi->configs_group; +	gi->group.default_groups[2] = &gi->strings_group; + +	config_group_init_type_name(&gi->functions_group, "functions", +			&functions_type); +	config_group_init_type_name(&gi->configs_group, "configs", +			&config_desc_type); +	config_group_init_type_name(&gi->strings_group, "strings", +			&gadget_strings_strings_type); + +	gi->composite.bind = configfs_do_nothing; +	gi->composite.unbind = configfs_do_nothing; +	gi->composite.suspend = NULL; +	gi->composite.resume = NULL; +	gi->composite.max_speed = USB_SPEED_SUPER; + +	mutex_init(&gi->lock); +	INIT_LIST_HEAD(&gi->string_list); +	INIT_LIST_HEAD(&gi->available_func); + +	composite_init_dev(&gi->cdev); +	gi->cdev.desc.bLength = USB_DT_DEVICE_SIZE; +	gi->cdev.desc.bDescriptorType = USB_DT_DEVICE; +	gi->cdev.desc.bcdDevice = cpu_to_le16(get_default_bcdDevice()); + +	gi->composite.gadget_driver = configfs_driver_template; + +	gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL); +	gi->composite.name = gi->composite.gadget_driver.function; + +	if (!gi->composite.gadget_driver.function) +		goto err; + +#ifdef CONFIG_USB_OTG +	gi->otg.bLength = sizeof(struct usb_otg_descriptor); +	gi->otg.bDescriptorType = USB_DT_OTG; +	gi->otg.bmAttributes = USB_OTG_SRP | USB_OTG_HNP; +#endif + +	config_group_init_type_name(&gi->group, name, +				&gadget_root_type); +	return &gi->group; +err: +	kfree(gi); +	return ERR_PTR(-ENOMEM); +} + +static void gadgets_drop(struct config_group *group, struct config_item *item) +{ +	config_item_put(item); +} + +static struct configfs_group_operations gadgets_ops = { +	.make_group     = &gadgets_make, +	.drop_item      = &gadgets_drop, +}; + +static struct config_item_type gadgets_type = { +	.ct_group_ops   = &gadgets_ops, +	.ct_owner       = THIS_MODULE, +}; + +static struct configfs_subsystem gadget_subsys = { +	.su_group = { +		.cg_item = { +			.ci_namebuf = "usb_gadget", +			.ci_type = &gadgets_type, +		}, +	}, +	.su_mutex = __MUTEX_INITIALIZER(gadget_subsys.su_mutex), +}; + +static int __init gadget_cfs_init(void) +{ +	int ret; + +	config_group_init(&gadget_subsys.su_group); + +	ret = configfs_register_subsystem(&gadget_subsys); +	return ret; +} +module_init(gadget_cfs_init); + +static void __exit gadget_cfs_exit(void) +{ +	configfs_unregister_subsystem(&gadget_subsys); +} +module_exit(gadget_cfs_exit); diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 8cf0c0f6fa1..a792e322f4f 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -912,7 +912,6 @@ static int dummy_udc_start(struct usb_gadget *g,  	dum->devstatus = 0;  	dum->driver = driver; -	dum->gadget.dev.driver = &driver->driver;  	dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",  			driver->driver.name);  	return 0; @@ -927,7 +926,6 @@ static int dummy_udc_stop(struct usb_gadget *g,  	dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",  			driver->driver.name); -	dum->gadget.dev.driver = NULL;  	dum->driver = NULL;  	return 0; @@ -937,11 +935,6 @@ static int dummy_udc_stop(struct usb_gadget *g,  /* The gadget structure is stored inside the hcd structure and will be   * released along with it. */ -static void dummy_gadget_release(struct device *dev) -{ -	return; -} -  static void init_dummy_udc_hw(struct dummy *dum)  {  	int i; @@ -984,15 +977,7 @@ static int dummy_udc_probe(struct platform_device *pdev)  	dum->gadget.ops = &dummy_ops;  	dum->gadget.max_speed = USB_SPEED_SUPER; -	dev_set_name(&dum->gadget.dev, "gadget");  	dum->gadget.dev.parent = &pdev->dev; -	dum->gadget.dev.release = dummy_gadget_release; -	rc = device_register(&dum->gadget.dev); -	if (rc < 0) { -		put_device(&dum->gadget.dev); -		return rc; -	} -  	init_dummy_udc_hw(dum);  	rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget); @@ -1008,7 +993,6 @@ static int dummy_udc_probe(struct platform_device *pdev)  err_dev:  	usb_del_gadget_udc(&dum->gadget);  err_udc: -	device_unregister(&dum->gadget.dev);  	return rc;  } @@ -1019,7 +1003,6 @@ static int dummy_udc_remove(struct platform_device *pdev)  	usb_del_gadget_udc(&dum->gadget);  	platform_set_drvdata(pdev, NULL);  	device_remove_file(&dum->gadget.dev, &dev_attr_function); -	device_unregister(&dum->gadget.dev);  	return 0;  } @@ -1923,7 +1906,7 @@ done:  }  /* usb 3.0 root hub device descriptor */ -struct { +static struct {  	struct usb_bos_descriptor bos;  	struct usb_ss_cap_descriptor ss_cap;  } __packed usb3_bos_desc = { diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 18c3f423706..56c8ecae9bc 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -207,7 +207,7 @@ static struct usb_gadget_strings *dev_strings[] = {  };  static u8 hostaddr[ETH_ALEN]; - +static struct eth_dev *the_dev;  /*-------------------------------------------------------------------------*/  /* @@ -224,7 +224,7 @@ static int __init rndis_do_config(struct usb_configuration *c)  		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;  	} -	return rndis_bind_config(c, hostaddr); +	return rndis_bind_config(c, hostaddr, the_dev);  }  static struct usb_configuration rndis_config_driver = { @@ -257,11 +257,11 @@ static int __init eth_do_config(struct usb_configuration *c)  	}  	if (use_eem) -		return eem_bind_config(c); +		return eem_bind_config(c, the_dev);  	else if (can_support_ecm(c->cdev->gadget)) -		return ecm_bind_config(c, hostaddr); +		return ecm_bind_config(c, hostaddr, the_dev);  	else -		return geth_bind_config(c, hostaddr); +		return geth_bind_config(c, hostaddr, the_dev);  }  static struct usb_configuration eth_config_driver = { @@ -279,9 +279,9 @@ static int __init eth_bind(struct usb_composite_dev *cdev)  	int			status;  	/* set up network link layer */ -	status = gether_setup(cdev->gadget, hostaddr); -	if (status < 0) -		return status; +	the_dev = gether_setup(cdev->gadget, hostaddr); +	if (IS_ERR(the_dev)) +		return PTR_ERR(the_dev);  	/* set up main config label and device descriptor */  	if (use_eem) { @@ -338,13 +338,13 @@ static int __init eth_bind(struct usb_composite_dev *cdev)  	return 0;  fail: -	gether_cleanup(); +	gether_cleanup(the_dev);  	return status;  }  static int __exit eth_unbind(struct usb_composite_dev *cdev)  { -	gether_cleanup(); +	gether_cleanup(the_dev);  	return 0;  } diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index 1ae180baa59..4b7e33e5d9c 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -715,13 +715,31 @@ fail:  	return status;  } -static struct f_acm *acm_alloc_basic_func(void) +static void acm_unbind(struct usb_configuration *c, struct usb_function *f) +{ +	struct f_acm		*acm = func_to_acm(f); + +	acm_string_defs[0].id = 0; +	usb_free_all_descriptors(f); +	if (acm->notify_req) +		gs_free_req(acm->notify, acm->notify_req); +} + +static void acm_free_func(struct usb_function *f) +{ +	struct f_acm		*acm = func_to_acm(f); + +	kfree(acm); +} + +static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)  { -	struct f_acm	*acm; +	struct f_serial_opts *opts; +	struct f_acm *acm;  	acm = kzalloc(sizeof(*acm), GFP_KERNEL);  	if (!acm) -		return NULL; +		return ERR_PTR(-ENOMEM);  	spin_lock_init(&acm->lock); @@ -730,109 +748,100 @@ static struct f_acm *acm_alloc_basic_func(void)  	acm->port.send_break = acm_send_break;  	acm->port.func.name = "acm"; +	acm->port.func.strings = acm_strings;  	/* descriptors are per-instance copies */  	acm->port.func.bind = acm_bind;  	acm->port.func.set_alt = acm_set_alt;  	acm->port.func.setup = acm_setup;  	acm->port.func.disable = acm_disable; -	return acm; +	opts = container_of(fi, struct f_serial_opts, func_inst); +	acm->port_num = opts->port_num; +	acm->port.func.unbind = acm_unbind; +	acm->port.func.free_func = acm_free_func; + +	return &acm->port.func;  } -#ifdef USB_FACM_INCLUDED -static void -acm_old_unbind(struct usb_configuration *c, struct usb_function *f) +static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)  { -	struct f_acm		*acm = func_to_acm(f); - -	usb_free_all_descriptors(f); -	if (acm->notify_req) -		gs_free_req(acm->notify, acm->notify_req); -	kfree(acm); +	return container_of(to_config_group(item), struct f_serial_opts, +			func_inst.group);  } -/** - * acm_bind_config - add a CDC ACM function to a configuration - * @c: the configuration to support the CDC ACM instance - * @port_num: /dev/ttyGS* port this interface will use - * Context: single threaded during gadget setup - * - * Returns zero on success, else negative errno. - * - */ -int acm_bind_config(struct usb_configuration *c, u8 port_num) +CONFIGFS_ATTR_STRUCT(f_serial_opts); +static ssize_t f_acm_attr_show(struct config_item *item, +				 struct configfs_attribute *attr, +				 char *page)  { -	struct f_acm	*acm; -	int		status; - -	/* allocate and initialize one new instance */ -	acm = acm_alloc_basic_func(); -	if (!acm) -		return -ENOMEM; +	struct f_serial_opts *opts = to_f_serial_opts(item); +	struct f_serial_opts_attribute *f_serial_opts_attr = +		container_of(attr, struct f_serial_opts_attribute, attr); +	ssize_t ret = 0; -	acm->port_num = port_num; -	acm->port.func.unbind = acm_old_unbind; - -	status = usb_add_function(c, &acm->port.func); -	if (status) -		kfree(acm); -	return status; +	if (f_serial_opts_attr->show) +		ret = f_serial_opts_attr->show(opts, page); +	return ret;  } -#else - -static void acm_unbind(struct usb_configuration *c, struct usb_function *f) +static void acm_attr_release(struct config_item *item)  { -	struct f_acm		*acm = func_to_acm(f); +	struct f_serial_opts *opts = to_f_serial_opts(item); -	acm_string_defs[0].id = 0; -	usb_free_all_descriptors(f); -	if (acm->notify_req) -		gs_free_req(acm->notify, acm->notify_req); +	usb_put_function_instance(&opts->func_inst);  } -static void acm_free_func(struct usb_function *f) -{ -	struct f_acm		*acm = func_to_acm(f); +static struct configfs_item_operations acm_item_ops = { +	.release                = acm_attr_release, +	.show_attribute		= f_acm_attr_show, +}; -	kfree(acm); +static ssize_t f_acm_port_num_show(struct f_serial_opts *opts, char *page) +{ +	return sprintf(page, "%u\n", opts->port_num);  } -static struct usb_function *acm_alloc_func(struct usb_function_instance *fi) -{ -	struct f_serial_opts *opts; -	struct f_acm *acm; +static struct f_serial_opts_attribute f_acm_port_num = +	__CONFIGFS_ATTR_RO(port_num, f_acm_port_num_show); -	acm = acm_alloc_basic_func(); -	if (!acm) -		return ERR_PTR(-ENOMEM); -	opts = container_of(fi, struct f_serial_opts, func_inst); -	acm->port_num = opts->port_num; -	acm->port.func.unbind = acm_unbind; -	acm->port.func.free_func = acm_free_func; +static struct configfs_attribute *acm_attrs[] = { +	&f_acm_port_num.attr, +	NULL, +}; -	return &acm->port.func; -} +static struct config_item_type acm_func_type = { +	.ct_item_ops    = &acm_item_ops, +	.ct_attrs	= acm_attrs, +	.ct_owner       = THIS_MODULE, +};  static void acm_free_instance(struct usb_function_instance *fi)  {  	struct f_serial_opts *opts;  	opts = container_of(fi, struct f_serial_opts, func_inst); +	gserial_free_line(opts->port_num);  	kfree(opts);  }  static struct usb_function_instance *acm_alloc_instance(void)  {  	struct f_serial_opts *opts; +	int ret;  	opts = kzalloc(sizeof(*opts), GFP_KERNEL);  	if (!opts)  		return ERR_PTR(-ENOMEM);  	opts->func_inst.free_func_inst = acm_free_instance; +	ret = gserial_alloc_line(&opts->port_num); +	if (ret) { +		kfree(opts); +		return ERR_PTR(ret); +	} +	config_group_init_type_name(&opts->func_inst.group, "", +			&acm_func_type);  	return &opts->func_inst;  }  DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);  MODULE_LICENSE("GPL"); -#endif diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index 83420a310fb..d893d692907 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -824,7 +824,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)   * for calling @gether_cleanup() before module unload.   */  int -ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) +ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], +		struct eth_dev *dev)  {  	struct f_ecm	*ecm;  	int		status; @@ -852,6 +853,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])  	snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr);  	ecm_string_defs[1].s = ecm->ethaddr; +	ecm->port.ioport = dev;  	ecm->port.cdc_filter = DEFAULT_FILTER;  	ecm->port.func.name = "cdc_ethernet"; diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c index cf0ebee8556..f4e0bbef602 100644 --- a/drivers/usb/gadget/f_eem.c +++ b/drivers/usb/gadget/f_eem.c @@ -528,7 +528,7 @@ error:   * Caller must have called @gether_setup().  Caller is also responsible   * for calling @gether_cleanup() before module unload.   */ -int __init eem_bind_config(struct usb_configuration *c) +int __init eem_bind_config(struct usb_configuration *c, struct eth_dev *dev)  {  	struct f_eem	*eem;  	int		status; @@ -549,6 +549,7 @@ int __init eem_bind_config(struct usb_configuration *c)  	if (!eem)  		return -ENOMEM; +	eem->port.ioport = dev;  	eem->port.cdc_filter = DEFAULT_FILTER;  	eem->port.func.name = "cdc_eem"; diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c index 5e7557e23ec..ee19bc8d004 100644 --- a/drivers/usb/gadget/f_ncm.c +++ b/drivers/usb/gadget/f_ncm.c @@ -1287,7 +1287,8 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f)   * Caller must have called @gether_setup().  Caller is also responsible   * for calling @gether_cleanup() before module unload.   */ -int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) +int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], +		struct eth_dev *dev)  {  	struct f_ncm	*ncm;  	int		status; @@ -1321,6 +1322,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])  	spin_lock_init(&ncm->lock);  	ncm_reset_values(ncm); +	ncm->port.ioport = dev;  	ncm->port.is_fixed = true;  	ncm->port.func.name = "cdc_network"; diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c index 36a004563b8..8aa2be5329b 100644 --- a/drivers/usb/gadget/f_obex.c +++ b/drivers/usb/gadget/f_obex.c @@ -72,7 +72,7 @@ static struct usb_gadget_strings *obex_strings[] = {  /*-------------------------------------------------------------------------*/ -static struct usb_interface_descriptor obex_control_intf __initdata = { +static struct usb_interface_descriptor obex_control_intf = {  	.bLength		= sizeof(obex_control_intf),  	.bDescriptorType	= USB_DT_INTERFACE,  	.bInterfaceNumber	= 0, @@ -83,7 +83,7 @@ static struct usb_interface_descriptor obex_control_intf __initdata = {  	.bInterfaceSubClass	= USB_CDC_SUBCLASS_OBEX,  }; -static struct usb_interface_descriptor obex_data_nop_intf __initdata = { +static struct usb_interface_descriptor obex_data_nop_intf = {  	.bLength		= sizeof(obex_data_nop_intf),  	.bDescriptorType	= USB_DT_INTERFACE,  	.bInterfaceNumber	= 1, @@ -93,7 +93,7 @@ static struct usb_interface_descriptor obex_data_nop_intf __initdata = {  	.bInterfaceClass	= USB_CLASS_CDC_DATA,  }; -static struct usb_interface_descriptor obex_data_intf __initdata = { +static struct usb_interface_descriptor obex_data_intf = {  	.bLength		= sizeof(obex_data_intf),  	.bDescriptorType	= USB_DT_INTERFACE,  	.bInterfaceNumber	= 2, @@ -103,14 +103,14 @@ static struct usb_interface_descriptor obex_data_intf __initdata = {  	.bInterfaceClass	= USB_CLASS_CDC_DATA,  }; -static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = { +static struct usb_cdc_header_desc obex_cdc_header_desc = {  	.bLength		= sizeof(obex_cdc_header_desc),  	.bDescriptorType	= USB_DT_CS_INTERFACE,  	.bDescriptorSubType	= USB_CDC_HEADER_TYPE,  	.bcdCDC			= cpu_to_le16(0x0120),  }; -static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = { +static struct usb_cdc_union_desc obex_cdc_union_desc = {  	.bLength		= sizeof(obex_cdc_union_desc),  	.bDescriptorType	= USB_DT_CS_INTERFACE,  	.bDescriptorSubType	= USB_CDC_UNION_TYPE, @@ -118,7 +118,7 @@ static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {  	.bSlaveInterface0	= 2,  }; -static struct usb_cdc_obex_desc obex_desc __initdata = { +static struct usb_cdc_obex_desc obex_desc = {  	.bLength		= sizeof(obex_desc),  	.bDescriptorType	= USB_DT_CS_INTERFACE,  	.bDescriptorSubType	= USB_CDC_OBEX_TYPE, @@ -127,7 +127,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = {  /* High-Speed Support */ -static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = { +static struct usb_endpoint_descriptor obex_hs_ep_out_desc = {  	.bLength		= USB_DT_ENDPOINT_SIZE,  	.bDescriptorType	= USB_DT_ENDPOINT, @@ -136,7 +136,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {  	.wMaxPacketSize		= cpu_to_le16(512),  }; -static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = { +static struct usb_endpoint_descriptor obex_hs_ep_in_desc = {  	.bLength		= USB_DT_ENDPOINT_SIZE,  	.bDescriptorType	= USB_DT_ENDPOINT, @@ -145,7 +145,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {  	.wMaxPacketSize		= cpu_to_le16(512),  }; -static struct usb_descriptor_header *hs_function[] __initdata = { +static struct usb_descriptor_header *hs_function[] = {  	(struct usb_descriptor_header *) &obex_control_intf,  	(struct usb_descriptor_header *) &obex_cdc_header_desc,  	(struct usb_descriptor_header *) &obex_desc, @@ -160,7 +160,7 @@ static struct usb_descriptor_header *hs_function[] __initdata = {  /* Full-Speed Support */ -static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = { +static struct usb_endpoint_descriptor obex_fs_ep_in_desc = {  	.bLength		= USB_DT_ENDPOINT_SIZE,  	.bDescriptorType	= USB_DT_ENDPOINT, @@ -168,7 +168,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {  	.bmAttributes		= USB_ENDPOINT_XFER_BULK,  }; -static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = { +static struct usb_endpoint_descriptor obex_fs_ep_out_desc = {  	.bLength		= USB_DT_ENDPOINT_SIZE,  	.bDescriptorType	= USB_DT_ENDPOINT, @@ -176,7 +176,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {  	.bmAttributes		= USB_ENDPOINT_XFER_BULK,  }; -static struct usb_descriptor_header *fs_function[] __initdata = { +static struct usb_descriptor_header *fs_function[] = {  	(struct usb_descriptor_header *) &obex_control_intf,  	(struct usb_descriptor_header *) &obex_cdc_header_desc,  	(struct usb_descriptor_header *) &obex_desc, @@ -290,14 +290,43 @@ static void obex_disconnect(struct gserial *g)  /*-------------------------------------------------------------------------*/ -static int __init -obex_bind(struct usb_configuration *c, struct usb_function *f) +/* Some controllers can't support CDC OBEX ... */ +static inline bool can_support_obex(struct usb_configuration *c) +{ +	/* Since the first interface is a NOP, we can ignore the +	 * issue of multi-interface support on most controllers. +	 * +	 * Altsettings are mandatory, however... +	 */ +	if (!gadget_supports_altsettings(c->cdev->gadget)) +		return false; + +	/* everything else is *probably* fine ... */ +	return true; +} + +static int obex_bind(struct usb_configuration *c, struct usb_function *f)  {  	struct usb_composite_dev *cdev = c->cdev;  	struct f_obex		*obex = func_to_obex(f);  	int			status;  	struct usb_ep		*ep; +	if (!can_support_obex(c)) +		return -EINVAL; + +	if (obex_string_defs[OBEX_CTRL_IDX].id == 0) { +		status = usb_string_ids_tab(c->cdev, obex_string_defs); +		if (status < 0) +			return status; +		obex_control_intf.iInterface = +			obex_string_defs[OBEX_CTRL_IDX].id; + +		status = obex_string_defs[OBEX_DATA_IDX].id; +		obex_data_nop_intf.iInterface = status; +		obex_data_intf.iInterface = status; +	} +  	/* allocate instance-specific interface IDs, and patch descriptors */  	status = usb_interface_id(c, f); @@ -319,6 +348,7 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)  	/* allocate instance-specific endpoints */ +	status = -ENODEV;  	ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_in_desc);  	if (!ep)  		goto fail; @@ -376,29 +406,16 @@ fail:  	return status;  } +#ifdef USBF_OBEX_INCLUDED +  static void -obex_unbind(struct usb_configuration *c, struct usb_function *f) +obex_old_unbind(struct usb_configuration *c, struct usb_function *f)  {  	obex_string_defs[OBEX_CTRL_IDX].id = 0;  	usb_free_all_descriptors(f);  	kfree(func_to_obex(f));  } -/* Some controllers can't support CDC OBEX ... */ -static inline bool can_support_obex(struct usb_configuration *c) -{ -	/* Since the first interface is a NOP, we can ignore the -	 * issue of multi-interface support on most controllers. -	 * -	 * Altsettings are mandatory, however... -	 */ -	if (!gadget_supports_altsettings(c->cdev->gadget)) -		return false; - -	/* everything else is *probably* fine ... */ -	return true; -} -  /**   * obex_bind_config - add a CDC OBEX function to a configuration   * @c: the configuration to support the CDC OBEX instance @@ -412,21 +429,6 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)  	struct f_obex	*obex;  	int		status; -	if (!can_support_obex(c)) -		return -EINVAL; - -	if (obex_string_defs[OBEX_CTRL_IDX].id == 0) { -		status = usb_string_ids_tab(c->cdev, obex_string_defs); -		if (status < 0) -			return status; -		obex_control_intf.iInterface = -			obex_string_defs[OBEX_CTRL_IDX].id; - -		status = obex_string_defs[OBEX_DATA_IDX].id; -		obex_data_nop_intf.iInterface = status; -		obex_data_intf.iInterface = status; -	} -  	/* allocate and initialize one new instance */  	obex = kzalloc(sizeof *obex, GFP_KERNEL);  	if (!obex) @@ -441,7 +443,7 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)  	obex->port.func.strings = obex_strings;  	/* descriptors are per-instance copies */  	obex->port.func.bind = obex_bind; -	obex->port.func.unbind = obex_unbind; +	obex->port.func.unbind = obex_old_unbind;  	obex->port.func.set_alt = obex_set_alt;  	obex->port.func.get_alt = obex_get_alt;  	obex->port.func.disable = obex_disable; @@ -453,5 +455,138 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)  	return status;  } +#else + +static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item) +{ +	return container_of(to_config_group(item), struct f_serial_opts, +			    func_inst.group); +} + +CONFIGFS_ATTR_STRUCT(f_serial_opts); +static ssize_t f_obex_attr_show(struct config_item *item, +				struct configfs_attribute *attr, +				char *page) +{ +	struct f_serial_opts *opts = to_f_serial_opts(item); +	struct f_serial_opts_attribute *f_serial_opts_attr = +		container_of(attr, struct f_serial_opts_attribute, attr); +	ssize_t ret = 0; + +	if (f_serial_opts_attr->show) +		ret = f_serial_opts_attr->show(opts, page); + +	return ret; +} + +static void obex_attr_release(struct config_item *item) +{ +	struct f_serial_opts *opts = to_f_serial_opts(item); + +	usb_put_function_instance(&opts->func_inst); +} + +static struct configfs_item_operations obex_item_ops = { +	.release	= obex_attr_release, +	.show_attribute = f_obex_attr_show, +}; + +static ssize_t f_obex_port_num_show(struct f_serial_opts *opts, char *page) +{ +	return sprintf(page, "%u\n", opts->port_num); +} + +static struct f_serial_opts_attribute f_obex_port_num = +	__CONFIGFS_ATTR_RO(port_num, f_obex_port_num_show); + +static struct configfs_attribute *acm_attrs[] = { +	&f_obex_port_num.attr, +	NULL, +}; + +static struct config_item_type obex_func_type = { +	.ct_item_ops	= &obex_item_ops, +	.ct_attrs	= acm_attrs, +	.ct_owner	= THIS_MODULE, +}; + +static void obex_free_inst(struct usb_function_instance *f) +{ +	struct f_serial_opts *opts; + +	opts = container_of(f, struct f_serial_opts, func_inst); +	gserial_free_line(opts->port_num); +	kfree(opts); +} + +static struct usb_function_instance *obex_alloc_inst(void) +{ +	struct f_serial_opts *opts; +	int ret; + +	opts = kzalloc(sizeof(*opts), GFP_KERNEL); +	if (!opts) +		return ERR_PTR(-ENOMEM); + +	opts->func_inst.free_func_inst = obex_free_inst; +	ret = gserial_alloc_line(&opts->port_num); +	if (ret) { +		kfree(opts); +		return ERR_PTR(ret); +	} +	config_group_init_type_name(&opts->func_inst.group, "", +				    &obex_func_type); + +	return &opts->func_inst; +} + +static void obex_free(struct usb_function *f) +{ +	struct f_obex *obex; + +	obex = func_to_obex(f); +	kfree(obex); +} + +static void obex_unbind(struct usb_configuration *c, struct usb_function *f) +{ +	obex_string_defs[OBEX_CTRL_IDX].id = 0; +	usb_free_all_descriptors(f); +} + +struct usb_function *obex_alloc(struct usb_function_instance *fi) +{ +	struct f_obex	*obex; +	struct f_serial_opts *opts; + +	/* allocate and initialize one new instance */ +	obex = kzalloc(sizeof(*obex), GFP_KERNEL); +	if (!obex) +		return ERR_PTR(-ENOMEM); + +	opts = container_of(fi, struct f_serial_opts, func_inst); + +	obex->port_num = opts->port_num; + +	obex->port.connect = obex_connect; +	obex->port.disconnect = obex_disconnect; + +	obex->port.func.name = "obex"; +	obex->port.func.strings = obex_strings; +	/* descriptors are per-instance copies */ +	obex->port.func.bind = obex_bind; +	obex->port.func.unbind = obex_unbind; +	obex->port.func.set_alt = obex_set_alt; +	obex->port.func.get_alt = obex_get_alt; +	obex->port.func.disable = obex_disable; +	obex->port.func.free_func = obex_free; + +	return &obex->port.func; +} + +DECLARE_USB_FUNCTION_INIT(obex, obex_alloc_inst, obex_alloc); + +#endif +  MODULE_AUTHOR("Felipe Balbi");  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 71beeb83355..36e8c44d8e5 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -447,14 +447,13 @@ static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req)  static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req)  {  	struct f_rndis			*rndis = req->context; -	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;  	int				status;  	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */  //	spin_lock(&dev->lock);  	status = rndis_msg_parser(rndis->config, (u8 *) req->buf);  	if (status < 0) -		ERROR(cdev, "RNDIS command error %d, %d/%d\n", +		pr_err("RNDIS command error %d, %d/%d\n",  			status, req->actual, req->length);  //	spin_unlock(&dev->lock);  } @@ -814,7 +813,7 @@ static inline bool can_support_rndis(struct usb_configuration *c)  int  rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], -				u32 vendorID, const char *manufacturer) +		u32 vendorID, const char *manufacturer, struct eth_dev *dev)  {  	struct f_rndis	*rndis;  	int		status; @@ -847,6 +846,7 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],  	rndis->vendorID = vendorID;  	rndis->manufacturer = manufacturer; +	rndis->port.ioport = dev;  	/* RNDIS activates when the host changes this filter */  	rndis->port.cdc_filter = 0; diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index da33cfb3031..981113c9924 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -12,6 +12,7 @@  #include <linux/slab.h>  #include <linux/kernel.h> +#include <linux/module.h>  #include <linux/device.h>  #include "u_serial.h" @@ -42,7 +43,7 @@ static inline struct f_gser *func_to_gser(struct usb_function *f)  /* interface descriptor: */ -static struct usb_interface_descriptor gser_interface_desc __initdata = { +static struct usb_interface_descriptor gser_interface_desc = {  	.bLength =		USB_DT_INTERFACE_SIZE,  	.bDescriptorType =	USB_DT_INTERFACE,  	/* .bInterfaceNumber = DYNAMIC */ @@ -55,21 +56,21 @@ static struct usb_interface_descriptor gser_interface_desc __initdata = {  /* full speed support: */ -static struct usb_endpoint_descriptor gser_fs_in_desc __initdata = { +static struct usb_endpoint_descriptor gser_fs_in_desc = {  	.bLength =		USB_DT_ENDPOINT_SIZE,  	.bDescriptorType =	USB_DT_ENDPOINT,  	.bEndpointAddress =	USB_DIR_IN,  	.bmAttributes =		USB_ENDPOINT_XFER_BULK,  }; -static struct usb_endpoint_descriptor gser_fs_out_desc __initdata = { +static struct usb_endpoint_descriptor gser_fs_out_desc = {  	.bLength =		USB_DT_ENDPOINT_SIZE,  	.bDescriptorType =	USB_DT_ENDPOINT,  	.bEndpointAddress =	USB_DIR_OUT,  	.bmAttributes =		USB_ENDPOINT_XFER_BULK,  }; -static struct usb_descriptor_header *gser_fs_function[] __initdata = { +static struct usb_descriptor_header *gser_fs_function[] = {  	(struct usb_descriptor_header *) &gser_interface_desc,  	(struct usb_descriptor_header *) &gser_fs_in_desc,  	(struct usb_descriptor_header *) &gser_fs_out_desc, @@ -78,47 +79,47 @@ static struct usb_descriptor_header *gser_fs_function[] __initdata = {  /* high speed support: */ -static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = { +static struct usb_endpoint_descriptor gser_hs_in_desc = {  	.bLength =		USB_DT_ENDPOINT_SIZE,  	.bDescriptorType =	USB_DT_ENDPOINT,  	.bmAttributes =		USB_ENDPOINT_XFER_BULK,  	.wMaxPacketSize =	cpu_to_le16(512),  }; -static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = { +static struct usb_endpoint_descriptor gser_hs_out_desc = {  	.bLength =		USB_DT_ENDPOINT_SIZE,  	.bDescriptorType =	USB_DT_ENDPOINT,  	.bmAttributes =		USB_ENDPOINT_XFER_BULK,  	.wMaxPacketSize =	cpu_to_le16(512),  }; -static struct usb_descriptor_header *gser_hs_function[] __initdata = { +static struct usb_descriptor_header *gser_hs_function[] = {  	(struct usb_descriptor_header *) &gser_interface_desc,  	(struct usb_descriptor_header *) &gser_hs_in_desc,  	(struct usb_descriptor_header *) &gser_hs_out_desc,  	NULL,  }; -static struct usb_endpoint_descriptor gser_ss_in_desc __initdata = { +static struct usb_endpoint_descriptor gser_ss_in_desc = {  	.bLength =		USB_DT_ENDPOINT_SIZE,  	.bDescriptorType =	USB_DT_ENDPOINT,  	.bmAttributes =		USB_ENDPOINT_XFER_BULK,  	.wMaxPacketSize =	cpu_to_le16(1024),  }; -static struct usb_endpoint_descriptor gser_ss_out_desc __initdata = { +static struct usb_endpoint_descriptor gser_ss_out_desc = {  	.bLength =		USB_DT_ENDPOINT_SIZE,  	.bDescriptorType =	USB_DT_ENDPOINT,  	.bmAttributes =		USB_ENDPOINT_XFER_BULK,  	.wMaxPacketSize =	cpu_to_le16(1024),  }; -static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc __initdata = { +static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc = {  	.bLength =              sizeof gser_ss_bulk_comp_desc,  	.bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,  }; -static struct usb_descriptor_header *gser_ss_function[] __initdata = { +static struct usb_descriptor_header *gser_ss_function[] = {  	(struct usb_descriptor_header *) &gser_interface_desc,  	(struct usb_descriptor_header *) &gser_ss_in_desc,  	(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc, @@ -183,14 +184,25 @@ static void gser_disable(struct usb_function *f)  /* serial function driver setup/binding */ -static int __init -gser_bind(struct usb_configuration *c, struct usb_function *f) +static int gser_bind(struct usb_configuration *c, struct usb_function *f)  {  	struct usb_composite_dev *cdev = c->cdev;  	struct f_gser		*gser = func_to_gser(f);  	int			status;  	struct usb_ep		*ep; +	/* REVISIT might want instance-specific strings to help +	 * distinguish instances ... +	 */ + +	/* maybe allocate device-global string ID */ +	if (gser_string_defs[0].id == 0) { +		status = usb_string_id(c->cdev); +		if (status < 0) +			return status; +		gser_string_defs[0].id = status; +	} +  	/* allocate instance-specific interface IDs */  	status = usb_interface_id(c, f);  	if (status < 0) @@ -246,44 +258,115 @@ fail:  	return status;  } -static void -gser_unbind(struct usb_configuration *c, struct usb_function *f) +static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)  { -	usb_free_all_descriptors(f); -	kfree(func_to_gser(f)); +	return container_of(to_config_group(item), struct f_serial_opts, +			    func_inst.group);  } -/** - * gser_bind_config - add a generic serial function to a configuration - * @c: the configuration to support the serial instance - * @port_num: /dev/ttyGS* port this interface will use - * Context: single threaded during gadget setup - * - * Returns zero on success, else negative errno. - */ -int __init gser_bind_config(struct usb_configuration *c, u8 port_num) +CONFIGFS_ATTR_STRUCT(f_serial_opts); +static ssize_t f_serial_attr_show(struct config_item *item, +				  struct configfs_attribute *attr, +				  char *page)  { -	struct f_gser	*gser; -	int		status; +	struct f_serial_opts *opts = to_f_serial_opts(item); +	struct f_serial_opts_attribute *f_serial_opts_attr = +		container_of(attr, struct f_serial_opts_attribute, attr); +	ssize_t ret = 0; -	/* REVISIT might want instance-specific strings to help -	 * distinguish instances ... -	 */ +	if (f_serial_opts_attr->show) +		ret = f_serial_opts_attr->show(opts, page); -	/* maybe allocate device-global string ID */ -	if (gser_string_defs[0].id == 0) { -		status = usb_string_id(c->cdev); -		if (status < 0) -			return status; -		gser_string_defs[0].id = status; +	return ret; +} + +static void serial_attr_release(struct config_item *item) +{ +	struct f_serial_opts *opts = to_f_serial_opts(item); + +	usb_put_function_instance(&opts->func_inst); +} + +static struct configfs_item_operations serial_item_ops = { +	.release	= serial_attr_release, +	.show_attribute = f_serial_attr_show, +}; + +static ssize_t f_serial_port_num_show(struct f_serial_opts *opts, char *page) +{ +	return sprintf(page, "%u\n", opts->port_num); +} + +static struct f_serial_opts_attribute f_serial_port_num = +	__CONFIGFS_ATTR_RO(port_num, f_serial_port_num_show); + +static struct configfs_attribute *acm_attrs[] = { +	&f_serial_port_num.attr, +	NULL, +}; + +static struct config_item_type serial_func_type = { +	.ct_item_ops	= &serial_item_ops, +	.ct_attrs	= acm_attrs, +	.ct_owner	= THIS_MODULE, +}; + +static void gser_free_inst(struct usb_function_instance *f) +{ +	struct f_serial_opts *opts; + +	opts = container_of(f, struct f_serial_opts, func_inst); +	gserial_free_line(opts->port_num); +	kfree(opts); +} + +static struct usb_function_instance *gser_alloc_inst(void) +{ +	struct f_serial_opts *opts; +	int ret; + +	opts = kzalloc(sizeof(*opts), GFP_KERNEL); +	if (!opts) +		return ERR_PTR(-ENOMEM); + +	opts->func_inst.free_func_inst = gser_free_inst; +	ret = gserial_alloc_line(&opts->port_num); +	if (ret) { +		kfree(opts); +		return ERR_PTR(ret);  	} +	config_group_init_type_name(&opts->func_inst.group, "", +				    &serial_func_type); + +	return &opts->func_inst; +} + +static void gser_free(struct usb_function *f) +{ +	struct f_gser *serial; + +	serial = func_to_gser(f); +	kfree(serial); +} + +static void gser_unbind(struct usb_configuration *c, struct usb_function *f) +{ +	usb_free_all_descriptors(f); +} + +struct usb_function *gser_alloc(struct usb_function_instance *fi) +{ +	struct f_gser	*gser; +	struct f_serial_opts *opts;  	/* allocate and initialize one new instance */ -	gser = kzalloc(sizeof *gser, GFP_KERNEL); +	gser = kzalloc(sizeof(*gser), GFP_KERNEL);  	if (!gser) -		return -ENOMEM; +		return ERR_PTR(-ENOMEM); -	gser->port_num = port_num; +	opts = container_of(fi, struct f_serial_opts, func_inst); + +	gser->port_num = opts->port_num;  	gser->port.func.name = "gser";  	gser->port.func.strings = gser_strings; @@ -291,9 +374,12 @@ int __init gser_bind_config(struct usb_configuration *c, u8 port_num)  	gser->port.func.unbind = gser_unbind;  	gser->port.func.set_alt = gser_set_alt;  	gser->port.func.disable = gser_disable; +	gser->port.func.free_func = gser_free; -	status = usb_add_function(c, &gser->port.func); -	if (status) -		kfree(gser); -	return status; +	return &gser->port.func;  } + +DECLARE_USB_FUNCTION_INIT(gser, gser_alloc_inst, gser_alloc); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Al Borchers"); +MODULE_AUTHOR("David Brownell"); diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index 41adf3ef96c..a8895859a22 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -898,7 +898,7 @@ static struct usb_function *source_sink_alloc_func(  	return &ss->function;  } -static void acm_free_instance(struct usb_function_instance *fi) +static void source_sink_free_instance(struct usb_function_instance *fi)  {  	struct f_ss_opts *ss_opts; @@ -913,7 +913,7 @@ static struct usb_function_instance *source_sink_alloc_inst(void)  	ss_opts = kzalloc(sizeof(*ss_opts), GFP_KERNEL);  	if (!ss_opts)  		return ERR_PTR(-ENOMEM); -	ss_opts->func_inst.free_func_inst = acm_free_instance; +	ss_opts->func_inst.free_func_inst = source_sink_free_instance;  	return &ss_opts->func_inst;  }  DECLARE_USB_FUNCTION(SourceSink, source_sink_alloc_inst, diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index f172bd152fb..185d6f5e4e4 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c @@ -380,7 +380,8 @@ geth_unbind(struct usb_configuration *c, struct usb_function *f)   * Caller must have called @gether_setup().  Caller is also responsible   * for calling @gether_cleanup() before module unload.   */ -int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) +int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], +		struct eth_dev *dev)  {  	struct f_gether	*geth;  	int		status; @@ -406,6 +407,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])  	snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr);  	geth_string_defs[1].s = geth->ethaddr; +	geth->port.ioport = dev;  	geth->port.cdc_filter = DEFAULT_FILTER;  	geth->port.func.name = "cdc_subset"; diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 92efd6ec48a..38dcedddc52 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -33,19 +33,15 @@ unsigned int uvc_gadget_trace_param;  /*-------------------------------------------------------------------------*/  /* module parameters specific to the Video streaming endpoint */ -static unsigned streaming_interval = 1; +static unsigned int streaming_interval = 1;  module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);  MODULE_PARM_DESC(streaming_interval, "1 - 16"); -static unsigned streaming_maxpacket = 1024; +static unsigned int streaming_maxpacket = 1024;  module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(streaming_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)"); +MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)"); -static unsigned streaming_mult; -module_param(streaming_mult, uint, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(streaming_mult, "0 - 2 (hs/ss only)"); - -static unsigned streaming_maxburst; +static unsigned int streaming_maxburst;  module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);  MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)"); @@ -55,13 +51,11 @@ MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");  /* string IDs are assigned dynamically */ -#define UVC_STRING_ASSOCIATION_IDX		0 -#define UVC_STRING_CONTROL_IDX			1 -#define UVC_STRING_STREAMING_IDX		2 +#define UVC_STRING_CONTROL_IDX			0 +#define UVC_STRING_STREAMING_IDX		1  static struct usb_string uvc_en_us_strings[] = { -	[UVC_STRING_ASSOCIATION_IDX].s = "UVC Camera", -	[UVC_STRING_CONTROL_IDX].s = "Video Control", +	[UVC_STRING_CONTROL_IDX].s = "UVC Camera",  	[UVC_STRING_STREAMING_IDX].s = "Video Streaming",  	{  }  }; @@ -79,7 +73,7 @@ static struct usb_gadget_strings *uvc_function_strings[] = {  #define UVC_INTF_VIDEO_CONTROL			0  #define UVC_INTF_VIDEO_STREAMING		1 -#define STATUS_BYTECOUNT			16	/* 16 bytes status */ +#define UVC_STATUS_MAX_PACKET_SIZE		16	/* 16 bytes status */  static struct usb_interface_assoc_descriptor uvc_iad __initdata = {  	.bLength		= sizeof(uvc_iad), @@ -104,20 +98,29 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = {  	.iInterface		= 0,  }; -static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = { +static struct usb_endpoint_descriptor uvc_control_ep __initdata = {  	.bLength		= USB_DT_ENDPOINT_SIZE,  	.bDescriptorType	= USB_DT_ENDPOINT,  	.bEndpointAddress	= USB_DIR_IN,  	.bmAttributes		= USB_ENDPOINT_XFER_INT, -	.wMaxPacketSize		= cpu_to_le16(STATUS_BYTECOUNT), +	.wMaxPacketSize		= cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),  	.bInterval		= 8,  }; +static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = { +	.bLength		= sizeof(uvc_ss_control_comp), +	.bDescriptorType	= USB_DT_SS_ENDPOINT_COMP, +	/* The following 3 values can be tweaked if necessary. */ +	.bMaxBurst		= 0, +	.bmAttributes		= 0, +	.wBytesPerInterval	= cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), +}; +  static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = {  	.bLength		= UVC_DT_CONTROL_ENDPOINT_SIZE,  	.bDescriptorType	= USB_DT_CS_ENDPOINT,  	.bDescriptorSubType	= UVC_EP_INTERRUPT, -	.wMaxTransferSize	= cpu_to_le16(STATUS_BYTECOUNT), +	.wMaxTransferSize	= cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),  };  static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = { @@ -144,63 +147,53 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = {  	.iInterface		= 0,  }; -static struct usb_endpoint_descriptor uvc_fs_streaming_ep = { +static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = {  	.bLength		= USB_DT_ENDPOINT_SIZE,  	.bDescriptorType	= USB_DT_ENDPOINT,  	.bEndpointAddress	= USB_DIR_IN, -	.bmAttributes		= USB_ENDPOINT_XFER_ISOC, -	.wMaxPacketSize		= cpu_to_le16(512), -	.bInterval		= 1, +	.bmAttributes		= USB_ENDPOINT_SYNC_ASYNC +				| USB_ENDPOINT_XFER_ISOC, +	/* The wMaxPacketSize and bInterval values will be initialized from +	 * module parameters. +	 */ +	.wMaxPacketSize		= 0, +	.bInterval		= 0,  }; -static struct usb_endpoint_descriptor uvc_hs_streaming_ep = { +static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = {  	.bLength		= USB_DT_ENDPOINT_SIZE,  	.bDescriptorType	= USB_DT_ENDPOINT,  	.bEndpointAddress	= USB_DIR_IN, -	.bmAttributes		= USB_ENDPOINT_XFER_ISOC, -	.wMaxPacketSize		= cpu_to_le16(1024), -	.bInterval		= 1, -}; - -/* super speed support */ -static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = { -	.bLength =		USB_DT_ENDPOINT_SIZE, -	.bDescriptorType =	USB_DT_ENDPOINT, - -	.bEndpointAddress =	USB_DIR_IN, -	.bmAttributes =		USB_ENDPOINT_XFER_INT, -	.wMaxPacketSize =	cpu_to_le16(STATUS_BYTECOUNT), -	.bInterval =		8, -}; - -static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = { -	.bLength =		sizeof uvc_ss_control_comp, -	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP, - -	/* the following 3 values can be tweaked if necessary */ -	/* .bMaxBurst =		0, */ -	/* .bmAttributes =	0, */ -	.wBytesPerInterval =	cpu_to_le16(STATUS_BYTECOUNT), +	.bmAttributes		= USB_ENDPOINT_SYNC_ASYNC +				| USB_ENDPOINT_XFER_ISOC, +	/* The wMaxPacketSize and bInterval values will be initialized from +	 * module parameters. +	 */ +	.wMaxPacketSize		= 0, +	.bInterval		= 0,  };  static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { -	.bLength =		USB_DT_ENDPOINT_SIZE, -	.bDescriptorType =	USB_DT_ENDPOINT, +	.bLength		= USB_DT_ENDPOINT_SIZE, +	.bDescriptorType	= USB_DT_ENDPOINT, -	.bEndpointAddress =	USB_DIR_IN, -	.bmAttributes =		USB_ENDPOINT_XFER_ISOC, -	.wMaxPacketSize =	cpu_to_le16(1024), -	.bInterval =		4, +	.bEndpointAddress	= USB_DIR_IN, +	.bmAttributes		= USB_ENDPOINT_SYNC_ASYNC +				| USB_ENDPOINT_XFER_ISOC, +	/* The wMaxPacketSize and bInterval values will be initialized from +	 * module parameters. +	 */ +	.wMaxPacketSize		= 0, +	.bInterval		= 0,  }; -static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = { -	.bLength =		sizeof uvc_ss_streaming_comp, -	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP, - -	/* the following 3 values can be tweaked if necessary */ -	.bMaxBurst =		0, -	.bmAttributes =	0, -	.wBytesPerInterval =	cpu_to_le16(1024), +static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp __initdata = { +	.bLength		= sizeof(uvc_ss_streaming_comp), +	.bDescriptorType	= USB_DT_SS_ENDPOINT_COMP, +	/* The following 3 values can be tweaked if necessary. */ +	.bMaxBurst		= 0, +	.bmAttributes		= 0, +	.wBytesPerInterval	= cpu_to_le16(1024),  };  static const struct usb_descriptor_header * const uvc_fs_streaming[] = { @@ -273,6 +266,13 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)  	return 0;  } +void uvc_function_setup_continue(struct uvc_device *uvc) +{ +	struct usb_composite_dev *cdev = uvc->func.config->cdev; + +	usb_composite_setup_continue(cdev); +} +  static int  uvc_function_get_alt(struct usb_function *f, unsigned interface)  { @@ -335,7 +335,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)  		v4l2_event_queue(uvc->vdev, &v4l2_event);  		uvc->state = UVC_STATE_CONNECTED; -		break; +		return 0;  	case 1:  		if (uvc->state != UVC_STATE_CONNECTED) @@ -352,15 +352,11 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)  		memset(&v4l2_event, 0, sizeof(v4l2_event));  		v4l2_event.type = UVC_EVENT_STREAMON;  		v4l2_event_queue(uvc->vdev, &v4l2_event); - -		uvc->state = UVC_STATE_STREAMING; -		break; +		return USB_GADGET_DELAYED_STATUS;  	default:  		return -EINVAL;  	} - -	return 0;  }  static void @@ -454,7 +450,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)  	const struct uvc_descriptor_header * const *uvc_streaming_cls;  	const struct usb_descriptor_header * const *uvc_streaming_std;  	const struct usb_descriptor_header * const *src; -	static struct usb_endpoint_descriptor *uvc_control_ep;  	struct usb_descriptor_header **dst;  	struct usb_descriptor_header **hdr;  	unsigned int control_size; @@ -468,14 +463,12 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)  		uvc_control_desc = uvc->desc.ss_control;  		uvc_streaming_cls = uvc->desc.ss_streaming;  		uvc_streaming_std = uvc_ss_streaming; -		uvc_control_ep = &uvc_ss_control_ep;  		break;  	case USB_SPEED_HIGH:  		uvc_control_desc = uvc->desc.fs_control;  		uvc_streaming_cls = uvc->desc.hs_streaming;  		uvc_streaming_std = uvc_hs_streaming; -		uvc_control_ep = &uvc_fs_control_ep;  		break;  	case USB_SPEED_FULL: @@ -483,7 +476,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)  		uvc_control_desc = uvc->desc.fs_control;  		uvc_streaming_cls = uvc->desc.fs_streaming;  		uvc_streaming_std = uvc_fs_streaming; -		uvc_control_ep = &uvc_fs_control_ep;  		break;  	} @@ -494,6 +486,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)  	 * Class-specific UVC control descriptors  	 * uvc_control_ep  	 * uvc_control_cs_ep +	 * uvc_ss_control_comp (for SS only)  	 * uvc_streaming_intf_alt0  	 * Class-specific UVC streaming descriptors  	 * uvc_{fs|hs}_streaming @@ -503,7 +496,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)  	control_size = 0;  	streaming_size = 0;  	bytes = uvc_iad.bLength + uvc_control_intf.bLength -	      + uvc_control_ep->bLength + uvc_control_cs_ep.bLength +	      + uvc_control_ep.bLength + uvc_control_cs_ep.bLength  	      + uvc_streaming_intf_alt0.bLength;  	if (speed == USB_SPEED_SUPER) { @@ -514,13 +507,13 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)  	}  	for (src = (const struct usb_descriptor_header **)uvc_control_desc; -			*src; ++src) { +	     *src; ++src) {  		control_size += (*src)->bLength;  		bytes += (*src)->bLength;  		n_desc++;  	}  	for (src = (const struct usb_descriptor_header **)uvc_streaming_cls; -			*src; ++src) { +	     *src; ++src) {  		streaming_size += (*src)->bLength;  		bytes += (*src)->bLength;  		n_desc++; @@ -549,7 +542,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)  	uvc_control_header->bInCollection = 1;  	uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf; -	UVC_COPY_DESCRIPTOR(mem, dst, uvc_control_ep); +	UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep);  	if (speed == USB_SPEED_SUPER)  		UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp); @@ -560,8 +553,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)  	UVC_COPY_DESCRIPTORS(mem, dst,  		(const struct usb_descriptor_header**)uvc_streaming_cls);  	uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size); -	uvc_streaming_header->bEndpointAddress = -		uvc_fs_streaming_ep.bEndpointAddress; +	uvc_streaming_header->bEndpointAddress = uvc->video.ep->address;  	UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std); @@ -581,7 +573,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)  	uvc->control_ep->driver_data = NULL;  	uvc->video.ep->driver_data = NULL; -	uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0; +	uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = 0;  	usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);  	kfree(uvc->control_buf); @@ -595,31 +587,52 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)  {  	struct usb_composite_dev *cdev = c->cdev;  	struct uvc_device *uvc = to_uvc(f); +	unsigned int max_packet_mult; +	unsigned int max_packet_size;  	struct usb_ep *ep;  	int ret = -EINVAL;  	INFO(cdev, "uvc_function_bind\n"); -	/* sanity check the streaming endpoint module parameters */ -	if (streaming_interval < 1) -		streaming_interval = 1; -	if (streaming_interval > 16) -		streaming_interval = 16; -	if (streaming_mult > 2) -		streaming_mult = 2; -	if (streaming_maxburst > 15) -		streaming_maxburst = 15; +	/* Sanity check the streaming endpoint module parameters. +	 */ +	streaming_interval = clamp(streaming_interval, 1U, 16U); +	streaming_maxpacket = clamp(streaming_maxpacket, 1U, 3072U); +	streaming_maxburst = min(streaming_maxburst, 15U); -	/* -	 * fill in the FS video streaming specific descriptors from the -	 * module parameters +	/* Fill in the FS/HS/SS Video Streaming specific descriptors from the +	 * module parameters. +	 * +	 * NOTE: We assume that the user knows what they are doing and won't +	 * give parameters that their UDC doesn't support.  	 */ -	uvc_fs_streaming_ep.wMaxPacketSize = streaming_maxpacket > 1023 ? -						1023 : streaming_maxpacket; +	if (streaming_maxpacket <= 1024) { +		max_packet_mult = 1; +		max_packet_size = streaming_maxpacket; +	} else if (streaming_maxpacket <= 2048) { +		max_packet_mult = 2; +		max_packet_size = streaming_maxpacket / 2; +	} else { +		max_packet_mult = 3; +		max_packet_size = streaming_maxpacket / 3; +	} + +	uvc_fs_streaming_ep.wMaxPacketSize = min(streaming_maxpacket, 1023U);  	uvc_fs_streaming_ep.bInterval = streaming_interval; +	uvc_hs_streaming_ep.wMaxPacketSize = max_packet_size; +	uvc_hs_streaming_ep.wMaxPacketSize |= ((max_packet_mult - 1) << 11); +	uvc_hs_streaming_ep.bInterval = streaming_interval; + +	uvc_ss_streaming_ep.wMaxPacketSize = max_packet_size; +	uvc_ss_streaming_ep.bInterval = streaming_interval; +	uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1; +	uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst; +	uvc_ss_streaming_comp.wBytesPerInterval = +		max_packet_size * max_packet_mult * streaming_maxburst; +  	/* Allocate endpoints. */ -	ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_control_ep); +	ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);  	if (!ep) {  		INFO(cdev, "Unable to allocate control EP\n");  		goto error; @@ -627,7 +640,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)  	uvc->control_ep = ep;  	ep->driver_data = uvc; -	ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); +	if (gadget_is_superspeed(c->cdev->gadget)) +		ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep, +					  &uvc_ss_streaming_comp); +	else if (gadget_is_dualspeed(cdev->gadget)) +		ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep); +	else +		ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); +  	if (!ep) {  		INFO(cdev, "Unable to allocate streaming EP\n");  		goto error; @@ -635,6 +655,10 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)  	uvc->video.ep = ep;  	ep->driver_data = uvc; +	uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address; +	uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address; +	uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address; +  	/* Allocate interface IDs. */  	if ((ret = usb_interface_id(c, f)) < 0)  		goto error; @@ -648,37 +672,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)  	uvc_streaming_intf_alt1.bInterfaceNumber = ret;  	uvc->streaming_intf = ret; -	/* sanity check the streaming endpoint module parameters */ -	if (streaming_maxpacket > 1024) -		streaming_maxpacket = 1024; -	/* -	 * Fill in the HS descriptors from the module parameters for the Video -	 * Streaming endpoint. -	 * NOTE: We assume that the user knows what they are doing and won't -	 * give parameters that their UDC doesn't support. -	 */ -	uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket; -	uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11; -	uvc_hs_streaming_ep.bInterval = streaming_interval; -	uvc_hs_streaming_ep.bEndpointAddress = -		uvc_fs_streaming_ep.bEndpointAddress; - -	/* -	 * Fill in the SS descriptors from the module parameters for the Video -	 * Streaming endpoint. -	 * NOTE: We assume that the user knows what they are doing and won't -	 * give parameters that their UDC doesn't support. -	 */ -	uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket; -	uvc_ss_streaming_ep.bInterval = streaming_interval; -	uvc_ss_streaming_comp.bmAttributes = streaming_mult; -	uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst; -	uvc_ss_streaming_comp.wBytesPerInterval = -		streaming_maxpacket * (streaming_mult + 1) * -		(streaming_maxburst + 1); -	uvc_ss_streaming_ep.bEndpointAddress = -		uvc_fs_streaming_ep.bEndpointAddress; -  	/* Copy descriptors */  	f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);  	if (gadget_is_dualspeed(cdev->gadget)) @@ -775,23 +768,23 @@ uvc_bind_config(struct usb_configuration *c,  	/* Validate the descriptors. */  	if (fs_control == NULL || fs_control[0] == NULL || -		fs_control[0]->bDescriptorSubType != UVC_VC_HEADER) +	    fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)  		goto error;  	if (ss_control == NULL || ss_control[0] == NULL || -		ss_control[0]->bDescriptorSubType != UVC_VC_HEADER) +	    ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)  		goto error;  	if (fs_streaming == NULL || fs_streaming[0] == NULL || -		fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) +	    fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)  		goto error;  	if (hs_streaming == NULL || hs_streaming[0] == NULL || -		hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) +	    hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)  		goto error;  	if (ss_streaming == NULL || ss_streaming[0] == NULL || -		ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) +	    ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)  		goto error;  	uvc->desc.fs_control = fs_control; @@ -800,13 +793,16 @@ uvc_bind_config(struct usb_configuration *c,  	uvc->desc.hs_streaming = hs_streaming;  	uvc->desc.ss_streaming = ss_streaming; -	/* Allocate string descriptor numbers. */ -	if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) { +	/* String descriptors are global, we only need to allocate string IDs +	 * for the first UVC function. UVC functions beyond the first (if any) +	 * will reuse the same IDs. +	 */ +	if (uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id == 0) {  		ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);  		if (ret)  			goto error;  		uvc_iad.iFunction = -			uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id; +			uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;  		uvc_control_intf.iInterface =  			uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;  		ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id; diff --git a/drivers/usb/gadget/f_uvc.h b/drivers/usb/gadget/f_uvc.h index c3d258d3018..ec52752f732 100644 --- a/drivers/usb/gadget/f_uvc.h +++ b/drivers/usb/gadget/f_uvc.h @@ -16,12 +16,12 @@  #include <linux/usb/composite.h>  #include <linux/usb/video.h> -extern int uvc_bind_config(struct usb_configuration *c, -		   const struct uvc_descriptor_header * const *fs_control, -		   const struct uvc_descriptor_header * const *hs_control, -		   const struct uvc_descriptor_header * const *fs_streaming, -		   const struct uvc_descriptor_header * const *hs_streaming, -		   const struct uvc_descriptor_header * const *ss_streaming); +int uvc_bind_config(struct usb_configuration *c, +		    const struct uvc_descriptor_header * const *fs_control, +		    const struct uvc_descriptor_header * const *hs_control, +		    const struct uvc_descriptor_header * const *fs_streaming, +		    const struct uvc_descriptor_header * const *hs_streaming, +		    const struct uvc_descriptor_header * const *ss_streaming);  #endif /* _F_UVC_H_ */ diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 034477ce77c..9a7ee3347e4 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -2296,7 +2296,6 @@ static int fsl_qe_start(struct usb_gadget *gadget,  	driver->driver.bus = NULL;  	/* hook up the driver */  	udc->driver = driver; -	udc->gadget.dev.driver = &driver->driver;  	udc->gadget.speed = driver->max_speed;  	/* Enable IRQ reg and Set usbcmd reg EN bit */ @@ -2338,7 +2337,6 @@ static int fsl_qe_stop(struct usb_gadget *gadget,  		nuke(loop_ep, -ESHUTDOWN);  	spin_unlock_irqrestore(&udc->lock, flags); -	udc->gadget.dev.driver = NULL;  	udc->driver = NULL;  	dev_info(udc->dev, "unregistered gadget driver '%s'\r\n", @@ -2523,12 +2521,6 @@ static int qe_udc_probe(struct platform_device *ofdev)  	/* name: Identifies the controller hardware type. */  	udc->gadget.name = driver_name; - -	device_initialize(&udc->gadget.dev); - -	dev_set_name(&udc->gadget.dev, "gadget"); - -	udc->gadget.dev.release = qe_udc_release;  	udc->gadget.dev.parent = &ofdev->dev;  	/* initialize qe_ep struct */ @@ -2592,22 +2584,17 @@ static int qe_udc_probe(struct platform_device *ofdev)  		goto err5;  	} -	ret = device_add(&udc->gadget.dev); +	ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget, +			qe_udc_release);  	if (ret)  		goto err6; -	ret = usb_add_gadget_udc(&ofdev->dev, &udc->gadget); -	if (ret) -		goto err7; -  	dev_set_drvdata(&ofdev->dev, udc);  	dev_info(udc->dev,  			"%s USB controller initialized as device\n",  			(udc->soc_type == PORT_QE) ? "QE" : "CPM");  	return 0; -err7: -	device_unregister(&udc->gadget.dev);  err6:  	free_irq(udc->usb_irq, udc);  err5: @@ -2702,7 +2689,6 @@ static int qe_udc_remove(struct platform_device *ofdev)  	iounmap(udc->usb_regs); -	device_unregister(&udc->gadget.dev);  	/* wait for release() of gadget.dev to free udc */  	wait_for_completion(&done); diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 04d5fef1440..7c2a101d19a 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -185,20 +185,7 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status)  		dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);  	} -	if (req->mapped) { -		dma_unmap_single(ep->udc->gadget.dev.parent, -			req->req.dma, req->req.length, -			ep_is_in(ep) -				? DMA_TO_DEVICE -				: DMA_FROM_DEVICE); -		req->req.dma = DMA_ADDR_INVALID; -		req->mapped = 0; -	} else -		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent, -			req->req.dma, req->req.length, -			ep_is_in(ep) -				? DMA_TO_DEVICE -				: DMA_FROM_DEVICE); +	usb_gadget_unmap_request(&ep->udc->gadget, &req->req, ep_is_in(ep));  	if (status && (status != -ESHUTDOWN))  		VDBG("complete %s req %p stat %d len %u/%u", @@ -888,6 +875,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)  	struct fsl_req *req = container_of(_req, struct fsl_req, req);  	struct fsl_udc *udc;  	unsigned long flags; +	int ret;  	/* catch various bogus parameters */  	if (!_req || !req->req.complete || !req->req.buf @@ -910,22 +898,9 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)  	req->ep = ep; -	/* map virtual address to hardware */ -	if (req->req.dma == DMA_ADDR_INVALID) { -		req->req.dma = dma_map_single(ep->udc->gadget.dev.parent, -					req->req.buf, -					req->req.length, ep_is_in(ep) -						? DMA_TO_DEVICE -						: DMA_FROM_DEVICE); -		req->mapped = 1; -	} else { -		dma_sync_single_for_device(ep->udc->gadget.dev.parent, -					req->req.dma, req->req.length, -					ep_is_in(ep) -						? DMA_TO_DEVICE -						: DMA_FROM_DEVICE); -		req->mapped = 0; -	} +	ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep)); +	if (ret) +		return ret;  	req->req.status = -EINPROGRESS;  	req->req.actual = 0; @@ -1290,6 +1265,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)  {  	struct fsl_req *req = udc->status_req;  	struct fsl_ep *ep; +	int ret;  	if (direction == EP_DIR_IN)  		udc->ep0_dir = USB_DIR_IN; @@ -1307,10 +1283,9 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)  	req->req.complete = NULL;  	req->dtd_count = 0; -	req->req.dma = dma_map_single(ep->udc->gadget.dev.parent, -			req->req.buf, req->req.length, -			ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); -	req->mapped = 1; +	ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep)); +	if (ret) +		return ret;  	if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)  		fsl_queue_td(ep, req); @@ -1353,6 +1328,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,  	u16 tmp = 0;		/* Status, cpu endian */  	struct fsl_req *req;  	struct fsl_ep *ep; +	int ret;  	ep = &udc->eps[0]; @@ -1390,10 +1366,9 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,  	req->req.complete = NULL;  	req->dtd_count = 0; -	req->req.dma = dma_map_single(ep->udc->gadget.dev.parent, -				req->req.buf, req->req.length, -				ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); -	req->mapped = 1; +	ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep)); +	if (ret) +		goto stall;  	/* prime the data phase */  	if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0)) @@ -1964,7 +1939,6 @@ static int fsl_udc_start(struct usb_gadget *g,  	driver->driver.bus = NULL;  	/* hook up the driver */  	udc_controller->driver = driver; -	udc_controller->gadget.dev.driver = &driver->driver;  	spin_unlock_irqrestore(&udc_controller->lock, flags);  	if (!IS_ERR_OR_NULL(udc_controller->transceiver)) { @@ -1980,7 +1954,6 @@ static int fsl_udc_start(struct usb_gadget *g,  			if (retval < 0) {  				ERR("can't bind to transceiver\n");  				driver->unbind(&udc_controller->gadget); -				udc_controller->gadget.dev.driver = 0;  				udc_controller->driver = 0;  				return retval;  			} @@ -2023,7 +1996,6 @@ static int fsl_udc_stop(struct usb_gadget *g,  		nuke(loop_ep, -ESHUTDOWN);  	spin_unlock_irqrestore(&udc_controller->lock, flags); -	udc_controller->gadget.dev.driver = NULL;  	udc_controller->driver = NULL;  	return 0; @@ -2521,12 +2493,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)  	/* Setup gadget.dev and register with kernel */  	dev_set_name(&udc_controller->gadget.dev, "gadget"); -	udc_controller->gadget.dev.release = fsl_udc_release; -	udc_controller->gadget.dev.parent = &pdev->dev;  	udc_controller->gadget.dev.of_node = pdev->dev.of_node; -	ret = device_register(&udc_controller->gadget.dev); -	if (ret < 0) -		goto err_free_irq;  	if (!IS_ERR_OR_NULL(udc_controller->transceiver))  		udc_controller->gadget.is_otg = 1; @@ -2559,10 +2526,11 @@ static int __init fsl_udc_probe(struct platform_device *pdev)  			DTD_ALIGNMENT, UDC_DMA_BOUNDARY);  	if (udc_controller->td_pool == NULL) {  		ret = -ENOMEM; -		goto err_unregister; +		goto err_free_irq;  	} -	ret = usb_add_gadget_udc(&pdev->dev, &udc_controller->gadget); +	ret = usb_add_gadget_udc_release(&pdev->dev, &udc_controller->gadget, +			fsl_udc_release);  	if (ret)  		goto err_del_udc; @@ -2571,8 +2539,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev)  err_del_udc:  	dma_pool_destroy(udc_controller->td_pool); -err_unregister: -	device_unregister(&udc_controller->gadget.dev);  err_free_irq:  	free_irq(udc_controller->irq, udc_controller);  err_iounmap: @@ -2622,7 +2588,6 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)  	if (pdata->operating_mode == FSL_USB2_DR_DEVICE)  		release_mem_region(res->start, resource_size(res)); -	device_unregister(&udc_controller->gadget.dev);  	/* free udc --wait for the release() finished */  	wait_for_completion(&done); @@ -2747,21 +2712,7 @@ static struct platform_driver udc_driver = {  	},  }; -static int __init udc_init(void) -{ -	printk(KERN_INFO "%s (%s)\n", driver_desc, DRIVER_VERSION); -	return platform_driver_probe(&udc_driver, fsl_udc_probe); -} - -module_init(udc_init); - -static void __exit udc_exit(void) -{ -	platform_driver_unregister(&udc_driver); -	printk(KERN_WARNING "%s unregistered\n", driver_desc); -} - -module_exit(udc_exit); +module_platform_driver_probe(udc_driver, fsl_udc_probe);  MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index 066cb89376d..cec8871b77f 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -394,7 +394,7 @@ static void fusb300_clear_epnstall(struct fusb300 *fusb300, u8 ep)  	if (reg & FUSB300_EPSET0_STL) {  		printk(KERN_DEBUG "EP%d stall... Clear!!\n", ep); -		reg &= ~FUSB300_EPSET0_STL; +		reg |= FUSB300_EPSET0_STL_CLR;  		iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET0(ep));  	}  } @@ -930,33 +930,33 @@ static void fusb300_wait_idma_finished(struct fusb300_ep *ep)  	fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0,  		FUSB300_IGR0_EPn_PRD_INT(ep->epnum)); +	return; +  IDMA_RESET: -	fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGER0, -		FUSB300_IGER0_EEPn_PRD_INT(ep->epnum)); +	reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGER0); +	reg &= ~FUSB300_IGER0_EEPn_PRD_INT(ep->epnum); +	iowrite32(reg, ep->fusb300->reg + FUSB300_OFFSET_IGER0);  } -static void  fusb300_set_idma(struct fusb300_ep *ep, +static void fusb300_set_idma(struct fusb300_ep *ep,  			struct fusb300_request *req)  { -	dma_addr_t d; - -	d = dma_map_single(NULL, req->req.buf, req->req.length, DMA_TO_DEVICE); +	int ret; -	if (dma_mapping_error(NULL, d)) { -		printk(KERN_DEBUG "dma_mapping_error\n"); +	ret = usb_gadget_map_request(&ep->fusb300->gadget, +			&req->req, DMA_TO_DEVICE); +	if (ret)  		return; -	} - -	dma_sync_single_for_device(NULL, d, req->req.length, DMA_TO_DEVICE);  	fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,  		FUSB300_IGER0_EEPn_PRD_INT(ep->epnum)); -	fusb300_fill_idma_prdtbl(ep, d, req->req.length); +	fusb300_fill_idma_prdtbl(ep, req->req.dma, req->req.length);  	/* check idma is done */  	fusb300_wait_idma_finished(ep); -	dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE); +	usb_gadget_unmap_request(&ep->fusb300->gadget, +			&req->req, DMA_TO_DEVICE);  }  static void in_ep_fifo_handler(struct fusb300_ep *ep) @@ -1316,7 +1316,6 @@ static int fusb300_udc_start(struct usb_gadget *g,  	/* hook up the driver */  	driver->driver.bus = NULL;  	fusb300->driver = driver; -	fusb300->gadget.dev.driver = &driver->driver;  	return 0;  } @@ -1327,7 +1326,6 @@ static int fusb300_udc_stop(struct usb_gadget *g,  	struct fusb300 *fusb300 = to_fusb300(g);  	driver->unbind(&fusb300->gadget); -	fusb300->gadget.dev.driver = NULL;  	init_controller(fusb300);  	fusb300->driver = NULL; @@ -1422,14 +1420,7 @@ static int __init fusb300_probe(struct platform_device *pdev)  	fusb300->gadget.ops = &fusb300_gadget_ops; -	device_initialize(&fusb300->gadget.dev); - -	dev_set_name(&fusb300->gadget.dev, "gadget"); -  	fusb300->gadget.max_speed = USB_SPEED_HIGH; -	fusb300->gadget.dev.parent = &pdev->dev; -	fusb300->gadget.dev.dma_mask = pdev->dev.dma_mask; -	fusb300->gadget.dev.release = pdev->dev.release;  	fusb300->gadget.name = udc_name;  	fusb300->reg = reg; @@ -1478,19 +1469,10 @@ static int __init fusb300_probe(struct platform_device *pdev)  	if (ret)  		goto err_add_udc; -	ret = device_add(&fusb300->gadget.dev); -	if (ret) { -		pr_err("device_add error (%d)\n", ret); -		goto err_add_device; -	} -  	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);  	return 0; -err_add_device: -	usb_del_gadget_udc(&fusb300->gadget); -  err_add_udc:  	fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req); diff --git a/drivers/usb/gadget/fusb300_udc.h b/drivers/usb/gadget/fusb300_udc.h index 6ba444ae8dd..ae811d8d38b 100644 --- a/drivers/usb/gadget/fusb300_udc.h +++ b/drivers/usb/gadget/fusb300_udc.h @@ -111,8 +111,8 @@  /*   * * EPn Setting 0 (EPn_SET0, offset = 020H+(n-1)*30H, n=1~15 )   * */ +#define FUSB300_EPSET0_STL_CLR		(1 << 3)  #define FUSB300_EPSET0_CLRSEQNUM	(1 << 2) -#define FUSB300_EPSET0_EPn_TX0BYTE	(1 << 1)  #define FUSB300_EPSET0_STL		(1 << 0)  /* diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 3953dd4d718..787a78e92aa 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -13,7 +13,6 @@  #define pr_fmt(fmt) "g_ffs: " fmt  #include <linux/module.h> -  /*   * kbuild is not very cooperative with respect to linking separately   * compiled library objects into one module.  So for now we won't use @@ -38,13 +37,16 @@  #  include "u_ether.c"  static u8 gfs_hostaddr[ETH_ALEN]; +static struct eth_dev *the_dev;  #  ifdef CONFIG_USB_FUNCTIONFS_ETH -static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); +static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], +		struct eth_dev *dev);  #  endif  #else -#  define gether_cleanup() do { } while (0) -#  define gether_setup(gadget, hostaddr)   ((int)0) +#  define the_dev	NULL +#  define gether_cleanup(dev) do { } while (0)  #  define gfs_hostaddr NULL +struct eth_dev;  #endif  #include "f_fs.c" @@ -137,7 +139,8 @@ static struct usb_gadget_strings *gfs_dev_strings[] = {  struct gfs_configuration {  	struct usb_configuration c; -	int (*eth)(struct usb_configuration *c, u8 *ethaddr); +	int (*eth)(struct usb_configuration *c, u8 *ethaddr, +			struct eth_dev *dev);  } gfs_configurations[] = {  #ifdef CONFIG_USB_FUNCTIONFS_RNDIS  	{ @@ -346,10 +349,13 @@ static int gfs_bind(struct usb_composite_dev *cdev)  	if (missing_funcs)  		return -ENODEV; - -	ret = gether_setup(cdev->gadget, gfs_hostaddr); -	if (unlikely(ret < 0)) +#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS +	the_dev = gether_setup(cdev->gadget, gfs_hostaddr); +#endif +	if (IS_ERR(the_dev)) { +		ret = PTR_ERR(the_dev);  		goto error_quick; +	}  	gfs_ether_setup = true;  	ret = usb_string_ids_tab(cdev, gfs_strings); @@ -357,7 +363,7 @@ static int gfs_bind(struct usb_composite_dev *cdev)  		goto error;  	gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id; -	for (i = func_num; --i; ) { +	for (i = func_num; i--; ) {  		ret = functionfs_bind(ffs_tab[i].ffs_data, cdev);  		if (unlikely(ret < 0)) {  			while (++i < func_num) @@ -386,7 +392,7 @@ error_unbind:  	for (i = 0; i < func_num; i++)  		functionfs_unbind(ffs_tab[i].ffs_data);  error: -	gether_cleanup(); +	gether_cleanup(the_dev);  error_quick:  	gfs_ether_setup = false;  	return ret; @@ -410,10 +416,10 @@ static int gfs_unbind(struct usb_composite_dev *cdev)  	 * do...?  	 */  	if (gfs_ether_setup) -		gether_cleanup(); +		gether_cleanup(the_dev);  	gfs_ether_setup = false; -	for (i = func_num; --i; ) +	for (i = func_num; i--; )  		if (ffs_tab[i].ffs_data)  			functionfs_unbind(ffs_tab[i].ffs_data); @@ -440,7 +446,7 @@ static int gfs_do_config(struct usb_configuration *c)  	}  	if (gc->eth) { -		ret = gc->eth(c, gfs_hostaddr); +		ret = gc->eth(c, gfs_hostaddr, the_dev);  		if (unlikely(ret < 0))  			return ret;  	} @@ -469,11 +475,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]) +static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], +		struct eth_dev *dev)  {  	return can_support_ecm(c->cdev->gadget) -		? ecm_bind_config(c, ethaddr) -		: geth_bind_config(c, ethaddr); +		? ecm_bind_config(c, ethaddr, dev) +		: geth_bind_config(c, ethaddr, dev);  }  #endif diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 85742d4c67d..991aba390d9 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -51,8 +51,6 @@  #define	DRIVER_DESC		"TC86C001 USB Device Controller"  #define	DRIVER_VERSION		"30-Oct 2003" -#define	DMA_ADDR_INVALID	(~(dma_addr_t)0) -  static const char driver_name [] = "goku_udc";  static const char driver_desc [] = DRIVER_DESC; @@ -275,7 +273,6 @@ goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)  	if (!req)  		return NULL; -	req->req.dma = DMA_ADDR_INVALID;  	INIT_LIST_HEAD(&req->queue);  	return &req->req;  } @@ -1354,7 +1351,6 @@ static int goku_udc_start(struct usb_gadget *g,  	/* hook up the driver */  	driver->driver.bus = NULL;  	dev->driver = driver; -	dev->gadget.dev.driver = &driver->driver;  	/*  	 * then enable host detection and ep0; and we're ready @@ -1394,7 +1390,6 @@ static int goku_udc_stop(struct usb_gadget *g,  	dev->driver = NULL;  	stop_activity(dev, driver);  	spin_unlock_irqrestore(&dev->lock, flags); -	dev->gadget.dev.driver = NULL;  	return 0;  } @@ -1716,8 +1711,6 @@ static void goku_remove(struct pci_dev *pdev)  				pci_resource_len (pdev, 0));  	if (dev->enabled)  		pci_disable_device(pdev); -	if (dev->registered) -		device_unregister(&dev->gadget.dev);  	pci_set_drvdata(pdev, NULL);  	dev->regs = NULL; @@ -1756,10 +1749,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)  	dev->gadget.max_speed = USB_SPEED_FULL;  	/* the "gadget" abstracts/virtualizes the controller */ -	dev_set_name(&dev->gadget.dev, "gadget"); -	dev->gadget.dev.parent = &pdev->dev; -	dev->gadget.dev.dma_mask = pdev->dev.dma_mask; -	dev->gadget.dev.release = gadget_release;  	dev->gadget.name = driver_name;  	/* now all the pci goodies ... */ @@ -1810,13 +1799,8 @@ 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 -	retval = device_register(&dev->gadget.dev); -	if (retval) { -		put_device(&dev->gadget.dev); -		goto err; -	} -	dev->registered = 1; -	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget); +	retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget, +			gadget_release);  	if (retval)  		goto err; diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h index b4470d2b1d8..86d2adafe14 100644 --- a/drivers/usb/gadget/goku_udc.h +++ b/drivers/usb/gadget/goku_udc.h @@ -250,8 +250,7 @@ struct goku_udc {  					got_region:1,  					req_config:1,  					configured:1, -					enabled:1, -					registered:1; +					enabled:1;  	/* pci state used to access those endpoints */  	struct pci_dev			*pdev; diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 5bd930d779b..b5cebd6b0d7 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1338,7 +1338,6 @@ static int imx_udc_start(struct usb_gadget *gadget,  	imx_usb = container_of(gadget, struct imx_udc_struct, gadget);  	/* first hook up the driver ... */  	imx_usb->driver = driver; -	imx_usb->gadget.dev.driver = &driver->driver;  	D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",  		__func__, driver->driver.name); @@ -1358,7 +1357,6 @@ static int imx_udc_stop(struct usb_gadget *gadget,  	imx_udc_disable(imx_usb);  	del_timer(&imx_usb->timer); -	imx_usb->gadget.dev.driver = NULL;  	imx_usb->driver = NULL;  	D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n", @@ -1461,15 +1459,6 @@ static int __init imx_udc_probe(struct platform_device *pdev)  	imx_usb->clk = clk;  	imx_usb->dev = &pdev->dev; -	device_initialize(&imx_usb->gadget.dev); - -	imx_usb->gadget.dev.parent = &pdev->dev; -	imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask; - -	ret = device_add(&imx_usb->gadget.dev); -	if (retval) -		goto fail4; -  	platform_set_drvdata(pdev, imx_usb);  	usb_init_data(imx_usb); @@ -1481,11 +1470,9 @@ static int __init imx_udc_probe(struct platform_device *pdev)  	ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);  	if (ret) -		goto fail5; +		goto fail4;  	return 0; -fail5: -	device_unregister(&imx_usb->gadget.dev);  fail4:  	for (i = 0; i < IMX_USB_NB_EP + 1; i++)  		free_irq(imx_usb->usbd_int[i], imx_usb); @@ -1509,7 +1496,6 @@ static int __exit imx_udc_remove(struct platform_device *pdev)  	int i;  	usb_del_gadget_udc(&imx_usb->gadget); -	device_unregister(&imx_usb->gadget.dev);  	imx_udc_disable(imx_usb);  	del_timer(&imx_usb->timer); diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index aa04089d689..b943d8cdfbf 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -1469,23 +1469,7 @@ static void done(struct lpc32xx_ep *ep, struct lpc32xx_request *req, int status)  		status = req->req.status;  	if (ep->lep) { -		enum dma_data_direction direction; - -		if (ep->is_in) -			direction = DMA_TO_DEVICE; -		else -			direction = DMA_FROM_DEVICE; - -		if (req->mapped) { -			dma_unmap_single(ep->udc->gadget.dev.parent, -					req->req.dma, req->req.length, -					direction); -			req->req.dma = 0; -			req->mapped = 0; -		} else -			dma_sync_single_for_cpu(ep->udc->gadget.dev.parent, -						req->req.dma, req->req.length, -						direction); +		usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);  		/* Free DDs */  		udc_dd_free(udc, req->dd_desc_ptr); @@ -1841,26 +1825,11 @@ static int lpc32xx_ep_queue(struct usb_ep *_ep,  	}  	if (ep->lep) { -		enum dma_data_direction direction;  		struct lpc32xx_usbd_dd_gad *dd; -		/* Map DMA pointer */ -		if (ep->is_in) -			direction = DMA_TO_DEVICE; -		else -			direction = DMA_FROM_DEVICE; - -		if (req->req.dma == 0) { -			req->req.dma = dma_map_single( -				ep->udc->gadget.dev.parent, -				req->req.buf, req->req.length, direction); -			req->mapped = 1; -		} else { -			dma_sync_single_for_device( -				ep->udc->gadget.dev.parent, req->req.dma, -				req->req.length, direction); -			req->mapped = 0; -		} +		status = usb_gadget_map_request(&udc->gadget, _req, ep->is_in); +		if (status) +			return status;  		/* For the request, build a list of DDs */  		dd = udc_dd_alloc(udc); @@ -2977,7 +2946,6 @@ static int lpc32xx_start(struct usb_gadget *gadget,  	}  	udc->driver = driver; -	udc->gadget.dev.driver = &driver->driver;  	udc->gadget.dev.of_node = udc->dev->of_node;  	udc->enabled = 1;  	udc->selfpowered = 1; @@ -3026,7 +2994,6 @@ static int lpc32xx_stop(struct usb_gadget *gadget,  	}  	udc->enabled = 0; -	udc->gadget.dev.driver = NULL;  	udc->driver = NULL;  	return 0; @@ -3248,12 +3215,6 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)  	udc_disable(udc);  	udc_reinit(udc); -	retval = device_register(&udc->gadget.dev); -	if (retval < 0) { -		dev_err(udc->dev, "Device registration failure\n"); -		goto dev_register_fail; -	} -  	/* Request IRQs - low and high priority USB device IRQs are routed to  	 * the same handler, while the DMA interrupt is routed elsewhere */  	retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq, @@ -3320,8 +3281,6 @@ irq_dev_fail:  irq_hp_fail:  	free_irq(udc->udp_irq[IRQ_USB_LP], udc);  irq_lp_fail: -	device_unregister(&udc->gadget.dev); -dev_register_fail:  	dma_pool_destroy(udc->dd_cache);  dma_alloc_fail:  	dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE, @@ -3376,8 +3335,6 @@ static int lpc32xx_udc_remove(struct platform_device *pdev)  	free_irq(udc->udp_irq[IRQ_USB_HP], udc);  	free_irq(udc->udp_irq[IRQ_USB_LP], udc); -	device_unregister(&udc->gadget.dev); -  	clk_disable(udc->usb_otg_clk);  	clk_put(udc->usb_otg_clk);  	clk_disable(udc->usb_slv_clk); diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index c1b8c2dd808..866ef099924 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1471,7 +1471,6 @@ static int m66592_udc_start(struct usb_gadget *g,  	/* hook up the driver */  	driver->driver.bus = NULL;  	m66592->driver = driver; -	m66592->gadget.dev.driver = &driver->driver;  	m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);  	if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) { @@ -1494,7 +1493,6 @@ static int m66592_udc_stop(struct usb_gadget *g,  	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);  	driver->unbind(&m66592->gadget); -	m66592->gadget.dev.driver = NULL;  	init_controller(m66592);  	disable_controller(m66592); @@ -1538,7 +1536,6 @@ static int __exit m66592_remove(struct platform_device *pdev)  	struct m66592		*m66592 = dev_get_drvdata(&pdev->dev);  	usb_del_gadget_udc(&m66592->gadget); -	device_del(&m66592->gadget.dev);  	del_timer_sync(&m66592->timer);  	iounmap(m66592->reg); @@ -1608,12 +1605,7 @@ static int __init m66592_probe(struct platform_device *pdev)  	dev_set_drvdata(&pdev->dev, m66592);  	m66592->gadget.ops = &m66592_gadget_ops; -	device_initialize(&m66592->gadget.dev); -	dev_set_name(&m66592->gadget.dev, "gadget");  	m66592->gadget.max_speed = USB_SPEED_HIGH; -	m66592->gadget.dev.parent = &pdev->dev; -	m66592->gadget.dev.dma_mask = pdev->dev.dma_mask; -	m66592->gadget.dev.release = pdev->dev.release;  	m66592->gadget.name = udc_name;  	init_timer(&m66592->timer); @@ -1674,12 +1666,6 @@ static int __init m66592_probe(struct platform_device *pdev)  	init_controller(m66592); -	ret = device_add(&m66592->gadget.dev); -	if (ret) { -		pr_err("device_add error (%d)\n", ret); -		goto err_device_add; -	} -  	ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);  	if (ret)  		goto err_add_udc; @@ -1688,9 +1674,6 @@ static int __init m66592_probe(struct platform_device *pdev)  	return 0;  err_add_udc: -	device_del(&m66592->gadget.dev); - -err_device_add:  	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);  clean_up3: diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 20bbbf917fc..4a45e80c6e3 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -135,8 +135,8 @@ static struct fsg_common fsg_common;  static u8 hostaddr[ETH_ALEN]; -static unsigned char tty_line;  static struct usb_function_instance *fi_acm; +static struct eth_dev *the_dev;  /********** RNDIS **********/ @@ -152,13 +152,15 @@ static __init int rndis_do_config(struct usb_configuration *c)  		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;  	} -	ret = rndis_bind_config(c, hostaddr); +	ret = rndis_bind_config(c, hostaddr, the_dev);  	if (ret < 0)  		return ret;  	f_acm_rndis = usb_get_function(fi_acm); -	if (IS_ERR(f_acm_rndis)) +	if (IS_ERR(f_acm_rndis)) { +		ret = PTR_ERR(f_acm_rndis);  		goto err_func_acm; +	}  	ret = usb_add_function(c, f_acm_rndis);  	if (ret) @@ -214,7 +216,7 @@ static __init int cdc_do_config(struct usb_configuration *c)  		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;  	} -	ret = ecm_bind_config(c, hostaddr); +	ret = ecm_bind_config(c, hostaddr, the_dev);  	if (ret < 0)  		return ret; @@ -269,7 +271,6 @@ static int cdc_config_register(struct usb_composite_dev *cdev)  static int __ref multi_bind(struct usb_composite_dev *cdev)  {  	struct usb_gadget *gadget = cdev->gadget; -	struct f_serial_opts *opts;  	int status;  	if (!can_support_ecm(cdev->gadget)) { @@ -279,24 +280,17 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)  	}  	/* set up network link layer */ -	status = gether_setup(cdev->gadget, hostaddr); -	if (status < 0) -		return status; +	the_dev = gether_setup(cdev->gadget, hostaddr); +	if (IS_ERR(the_dev)) +		return PTR_ERR(the_dev);  	/* set up serial link layer */ -	status = gserial_alloc_line(&tty_line); -	if (status < 0) -		goto fail0; -  	fi_acm = usb_get_function_instance("acm");  	if (IS_ERR(fi_acm)) {  		status = PTR_ERR(fi_acm); -		goto fail0dot5; +		goto fail0;  	} -	opts = container_of(fi_acm, struct f_serial_opts, func_inst); -	opts->port_num = tty_line; -  	/* set up mass storage function */  	{  		void *retp; @@ -334,10 +328,8 @@ fail2:  	fsg_common_put(&fsg_common);  fail1:  	usb_put_function_instance(fi_acm); -fail0dot5: -	gserial_free_line(tty_line);  fail0: -	gether_cleanup(); +	gether_cleanup(the_dev);  	return status;  } @@ -350,8 +342,7 @@ static int __exit multi_unbind(struct usb_composite_dev *cdev)  	usb_put_function(f_acm_rndis);  #endif  	usb_put_function_instance(fi_acm); -	gserial_free_line(tty_line); -	gether_cleanup(); +	gether_cleanup(the_dev);  	return 0;  } diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index b5cea273c95..58288e9cf72 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -30,9 +30,6 @@  #include <linux/platform_device.h>  #include <linux/platform_data/mv_usb.h>  #include <linux/clk.h> -#include <asm/system.h> -#include <asm/unaligned.h> -#include <asm/byteorder.h>  #include "mv_u3d.h" @@ -125,7 +122,7 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,  	struct mv_u3d_trb	*curr_trb;  	dma_addr_t cur_deq_lo;  	struct mv_u3d_ep_context	*curr_ep_context; -	int trb_complete, actual, remaining_length; +	int trb_complete, actual, remaining_length = 0;  	int direction, ep_num;  	int retval = 0;  	u32 tmp, status, length; @@ -189,6 +186,8 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,   */  static  void mv_u3d_done(struct mv_u3d_ep *ep, struct mv_u3d_req *req, int status) +	__releases(&ep->udc->lock) +	__acquires(&ep->udc->lock)  {  	struct mv_u3d *u3d = (struct mv_u3d *)ep->u3d; @@ -812,19 +811,19 @@ mv_u3d_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)  		return 0;  	} -	dev_dbg(u3d->dev, "%s: %s, req: 0x%x\n", -			__func__, _ep->name, (u32)req); +	dev_dbg(u3d->dev, "%s: %s, req: 0x%p\n", +			__func__, _ep->name, req);  	/* catch various bogus parameters */  	if (!req->req.complete || !req->req.buf  			|| !list_empty(&req->queue)) {  		dev_err(u3d->dev, -			"%s, bad params, _req: 0x%x," -			"req->req.complete: 0x%x, req->req.buf: 0x%x," +			"%s, bad params, _req: 0x%p," +			"req->req.complete: 0x%p, req->req.buf: 0x%p,"  			"list_empty: 0x%x\n", -			__func__, (u32)_req, -			(u32)req->req.complete, (u32)req->req.buf, -			(u32)list_empty(&req->queue)); +			__func__, _req, +			req->req.complete, req->req.buf, +			list_empty(&req->queue));  		return -EINVAL;  	}  	if (unlikely(!ep->ep.desc)) { @@ -905,7 +904,7 @@ static int mv_u3d_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)  					struct mv_u3d_req, queue);  			/* Point first TRB of next request to the EP context. */ -			iowrite32((u32) next_req->trb_head, +			iowrite32((unsigned long) next_req->trb_head,  					&ep_context->trb_addr_lo);  		} else {  			struct mv_u3d_ep_context *ep_context; @@ -1264,7 +1263,6 @@ static int mv_u3d_start(struct usb_gadget *g,  	/* hook up the driver ... */  	driver->driver.bus = NULL;  	u3d->driver = driver; -	u3d->gadget.dev.driver = &driver->driver;  	u3d->ep0_dir = USB_DIR_OUT; @@ -1302,7 +1300,6 @@ static int mv_u3d_stop(struct usb_gadget *g,  	spin_unlock_irqrestore(&u3d->lock, flags); -	u3d->gadget.dev.driver = NULL;  	u3d->driver = NULL;  	return 0; @@ -1525,6 +1522,8 @@ static int mv_u3d_is_set_configuration(struct usb_ctrlrequest *setup)  static void mv_u3d_handle_setup_packet(struct mv_u3d *u3d, u8 ep_num,  	struct usb_ctrlrequest *setup) +	__releases(&u3c->lock) +	__acquires(&u3c->lock)  {  	bool delegate = false; @@ -1758,11 +1757,6 @@ static irqreturn_t mv_u3d_irq(int irq, void *dev)  	return IRQ_HANDLED;  } -static void mv_u3d_gadget_release(struct device *dev) -{ -	dev_dbg(dev, "%s\n", __func__); -} -  static int mv_u3d_remove(struct platform_device *dev)  {  	struct mv_u3d *u3d = platform_get_drvdata(dev); @@ -1792,8 +1786,6 @@ static int mv_u3d_remove(struct platform_device *dev)  	clk_put(u3d->clk); -	device_unregister(&u3d->gadget.dev); -  	platform_set_drvdata(dev, NULL);  	kfree(u3d); @@ -1829,7 +1821,7 @@ static int mv_u3d_probe(struct platform_device *dev)  	u3d->dev = &dev->dev;  	u3d->vbus = pdata->vbus; -	u3d->clk = clk_get(&dev->dev, pdata->clkname[0]); +	u3d->clk = clk_get(&dev->dev, NULL);  	if (IS_ERR(u3d->clk)) {  		retval = PTR_ERR(u3d->clk);  		goto err_get_clk; @@ -1849,8 +1841,9 @@ static int mv_u3d_probe(struct platform_device *dev)  		retval = -EBUSY;  		goto err_map_cap_regs;  	} else { -		dev_dbg(&dev->dev, "cap_regs address: 0x%x/0x%x\n", -			(unsigned int)r->start, (unsigned int)u3d->cap_regs); +		dev_dbg(&dev->dev, "cap_regs address: 0x%lx/0x%lx\n", +			(unsigned long) r->start, +			(unsigned long) u3d->cap_regs);  	}  	/* we will access controller register, so enable the u3d controller */ @@ -1864,10 +1857,10 @@ static int mv_u3d_probe(struct platform_device *dev)  		}  	} -	u3d->op_regs = (struct mv_u3d_op_regs __iomem *)((u32)u3d->cap_regs +	u3d->op_regs = (struct mv_u3d_op_regs __iomem *)(u3d->cap_regs  		+ MV_U3D_USB3_OP_REGS_OFFSET); -	u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)((u32)u3d->cap_regs +	u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)(u3d->cap_regs  		+ ioread32(&u3d->cap_regs->vuoff));  	u3d->max_eps = 16; @@ -1957,16 +1950,8 @@ static int mv_u3d_probe(struct platform_device *dev)  	u3d->gadget.speed = USB_SPEED_UNKNOWN;	/* speed */  	/* the "gadget" abstracts/virtualizes the controller */ -	dev_set_name(&u3d->gadget.dev, "gadget"); -	u3d->gadget.dev.parent = &dev->dev; -	u3d->gadget.dev.dma_mask = dev->dev.dma_mask; -	u3d->gadget.dev.release = mv_u3d_gadget_release;  	u3d->gadget.name = driver_name;		/* gadget name */ -	retval = device_register(&u3d->gadget.dev); -	if (retval) -		goto err_register_gadget_device; -  	mv_u3d_eps_init(u3d);  	/* external vbus detection */ @@ -1991,8 +1976,6 @@ static int mv_u3d_probe(struct platform_device *dev)  	return 0;  err_unregister: -	device_unregister(&u3d->gadget.dev); -err_register_gadget_device:  	free_irq(u3d->irq, &dev->dev);  err_request_irq:  err_get_irq: @@ -2021,7 +2004,7 @@ err_pdata:  	return retval;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int mv_u3d_suspend(struct device *dev)  {  	struct mv_u3d *u3d = dev_get_drvdata(dev); @@ -2064,10 +2047,10 @@ static int mv_u3d_resume(struct device *dev)  	return 0;  } - -SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);  #endif +static SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume); +  static void mv_u3d_shutdown(struct platform_device *dev)  {  	struct mv_u3d *u3d = dev_get_drvdata(&dev->dev); @@ -2080,14 +2063,12 @@ static void mv_u3d_shutdown(struct platform_device *dev)  static struct platform_driver mv_u3d_driver = {  	.probe		= mv_u3d_probe, -	.remove		= __exit_p(mv_u3d_remove), +	.remove		= mv_u3d_remove,  	.shutdown	= mv_u3d_shutdown,  	.driver		= {  		.owner	= THIS_MODULE,  		.name	= "mv-u3d", -#ifdef CONFIG_PM  		.pm	= &mv_u3d_pm_ops, -#endif  	},  }; diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h index 9073436d8b2..be77f207dba 100644 --- a/drivers/usb/gadget/mv_udc.h +++ b/drivers/usb/gadget/mv_udc.h @@ -222,8 +222,7 @@ struct mv_udc {  	struct mv_usb_platform_data     *pdata;  	/* some SOC has mutiple clock sources for USB*/ -	unsigned int    clknum; -	struct clk      *clk[0]; +	struct clk      *clk;  };  /* endpoint data structure */ diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index c8cf959057f..c2a57023e46 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -212,6 +212,8 @@ static int process_ep_req(struct mv_udc *udc, int index,   * request is still in progress.   */  static void done(struct mv_ep *ep, struct mv_req *req, int status) +	__releases(&ep->udc->lock) +	__acquires(&ep->udc->lock)  {  	struct mv_udc *udc = NULL;  	unsigned char stopped = ep->stopped; @@ -237,18 +239,7 @@ static void done(struct mv_ep *ep, struct mv_req *req, int status)  		dma_pool_free(udc->dtd_pool, curr_td, curr_td->td_dma);  	} -	if (req->mapped) { -		dma_unmap_single(ep->udc->gadget.dev.parent, -			req->req.dma, req->req.length, -			((ep_dir(ep) == EP_DIR_IN) ? -				DMA_TO_DEVICE : DMA_FROM_DEVICE)); -		req->req.dma = DMA_ADDR_INVALID; -		req->mapped = 0; -	} else -		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent, -			req->req.dma, req->req.length, -			((ep_dir(ep) == EP_DIR_IN) ? -				DMA_TO_DEVICE : DMA_FROM_DEVICE)); +	usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));  	if (status && (status != -ESHUTDOWN))  		dev_info(&udc->dev->dev, "complete %s req %p stat %d len %u/%u", @@ -732,21 +723,9 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)  	req->ep = ep;  	/* map virtual address to hardware */ -	if (req->req.dma == DMA_ADDR_INVALID) { -		req->req.dma = dma_map_single(ep->udc->gadget.dev.parent, -					req->req.buf, -					req->req.length, ep_dir(ep) -						? DMA_TO_DEVICE -						: DMA_FROM_DEVICE); -		req->mapped = 1; -	} else { -		dma_sync_single_for_device(ep->udc->gadget.dev.parent, -					req->req.dma, req->req.length, -					ep_dir(ep) -						? DMA_TO_DEVICE -						: DMA_FROM_DEVICE); -		req->mapped = 0; -	} +	retval = usb_gadget_map_request(&udc->gadget, _req, ep_dir(ep)); +	if (retval) +		return retval;  	req->req.status = -EINPROGRESS;  	req->req.actual = 0; @@ -780,18 +759,7 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)  	return 0;  err_unmap_dma: -	if (req->mapped) { -		dma_unmap_single(ep->udc->gadget.dev.parent, -				req->req.dma, req->req.length, -				((ep_dir(ep) == EP_DIR_IN) ? -				DMA_TO_DEVICE : DMA_FROM_DEVICE)); -		req->req.dma = DMA_ADDR_INVALID; -		req->mapped = 0; -	} else -		dma_sync_single_for_cpu(ep->udc->gadget.dev.parent, -				req->req.dma, req->req.length, -				((ep_dir(ep) == EP_DIR_IN) ? -				DMA_TO_DEVICE : DMA_FROM_DEVICE)); +	usb_gadget_unmap_request(&udc->gadget, _req, ep_dir(ep));  	return retval;  } @@ -1006,18 +974,12 @@ static struct usb_ep_ops mv_ep_ops = {  static void udc_clock_enable(struct mv_udc *udc)  { -	unsigned int i; - -	for (i = 0; i < udc->clknum; i++) -		clk_prepare_enable(udc->clk[i]); +	clk_prepare_enable(udc->clk);  }  static void udc_clock_disable(struct mv_udc *udc)  { -	unsigned int i; - -	for (i = 0; i < udc->clknum; i++) -		clk_disable_unprepare(udc->clk[i]); +	clk_disable_unprepare(udc->clk);  }  static void udc_stop(struct mv_udc *udc) @@ -1386,7 +1348,6 @@ static int mv_udc_start(struct usb_gadget *gadget,  	/* hook up the driver ... */  	driver->driver.bus = NULL;  	udc->driver = driver; -	udc->gadget.dev.driver = &driver->driver;  	udc->usb_state = USB_STATE_ATTACHED;  	udc->ep0_state = WAIT_FOR_SETUP; @@ -1401,7 +1362,6 @@ static int mv_udc_start(struct usb_gadget *gadget,  			dev_err(&udc->dev->dev,  				"unable to register peripheral to otg\n");  			udc->driver = NULL; -			udc->gadget.dev.driver = NULL;  			return retval;  		}  	} @@ -1437,7 +1397,6 @@ static int mv_udc_stop(struct usb_gadget *gadget,  	spin_unlock_irqrestore(&udc->lock, flags);  	/* unbind gadget driver */ -	udc->gadget.dev.driver = NULL;  	udc->driver = NULL;  	return 0; @@ -1528,14 +1487,7 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)  	return 0;  out: -	if (req->mapped) { -		dma_unmap_single(ep->udc->gadget.dev.parent, -				req->req.dma, req->req.length, -				((ep_dir(ep) == EP_DIR_IN) ? -				DMA_TO_DEVICE : DMA_FROM_DEVICE)); -		req->req.dma = DMA_ADDR_INVALID; -		req->mapped = 0; -	} +	usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));  	return retval;  } @@ -1695,6 +1647,8 @@ out:  static void handle_setup_packet(struct mv_udc *udc, u8 ep_num,  	struct usb_ctrlrequest *setup) +	__releases(&ep->udc->lock) +	__acquires(&ep->udc->lock)  {  	bool delegate = false; @@ -1891,7 +1845,7 @@ static void irq_process_tr_complete(struct mv_udc *udc)  	}  } -void irq_process_reset(struct mv_udc *udc) +static void irq_process_reset(struct mv_udc *udc)  {  	u32 tmp;  	unsigned int loops; @@ -2138,8 +2092,6 @@ static int mv_udc_remove(struct platform_device *pdev)  	mv_udc_disable(udc); -	device_unregister(&udc->gadget.dev); -  	/* free dev, wait for the release() finished */  	wait_for_completion(udc->done); @@ -2151,7 +2103,6 @@ static int mv_udc_probe(struct platform_device *pdev)  	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;  	struct mv_udc *udc;  	int retval = 0; -	int clk_i = 0;  	struct resource *r;  	size_t size; @@ -2160,8 +2111,7 @@ static int mv_udc_probe(struct platform_device *pdev)  		return -ENODEV;  	} -	size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum; -	udc = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); +	udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL);  	if (udc == NULL) {  		dev_err(&pdev->dev, "failed to allocate memory for udc\n");  		return -ENOMEM; @@ -2173,26 +2123,24 @@ static int mv_udc_probe(struct platform_device *pdev)  	udc->dev = pdev; -#ifdef CONFIG_USB_OTG_UTILS  	if (pdata->mode == MV_USB_MODE_OTG) {  		udc->transceiver = devm_usb_get_phy(&pdev->dev,  					USB_PHY_TYPE_USB2); -		if (IS_ERR_OR_NULL(udc->transceiver)) { +		if (IS_ERR(udc->transceiver)) { +			retval = PTR_ERR(udc->transceiver); + +			if (retval == -ENXIO) +				return retval; +  			udc->transceiver = NULL; -			return -ENODEV; +			return -EPROBE_DEFER;  		}  	} -#endif -	udc->clknum = pdata->clknum; -	for (clk_i = 0; clk_i < udc->clknum; clk_i++) { -		udc->clk[clk_i] = devm_clk_get(&pdev->dev, -					pdata->clkname[clk_i]); -		if (IS_ERR(udc->clk[clk_i])) { -			retval = PTR_ERR(udc->clk[clk_i]); -			return retval; -		} -	} +	/* udc only have one sysclk. */ +	udc->clk = devm_clk_get(&pdev->dev, NULL); +	if (IS_ERR(udc->clk)) +		return PTR_ERR(udc->clk);  	r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");  	if (r == NULL) { @@ -2311,16 +2259,8 @@ static int mv_udc_probe(struct platform_device *pdev)  	udc->gadget.max_speed = USB_SPEED_HIGH;	/* support dual speed */  	/* the "gadget" abstracts/virtualizes the controller */ -	dev_set_name(&udc->gadget.dev, "gadget"); -	udc->gadget.dev.parent = &pdev->dev; -	udc->gadget.dev.dma_mask = pdev->dev.dma_mask; -	udc->gadget.dev.release = gadget_release;  	udc->gadget.name = driver_name;		/* gadget name */ -	retval = device_register(&udc->gadget.dev); -	if (retval) -		goto err_destroy_dma; -  	eps_init(udc);  	/* VBUS detect: we can disable/enable clock on demand.*/ @@ -2342,7 +2282,7 @@ static int mv_udc_probe(struct platform_device *pdev)  		if (!udc->qwork) {  			dev_err(&pdev->dev, "cannot create workqueue\n");  			retval = -ENOMEM; -			goto err_unregister; +			goto err_destroy_dma;  		}  		INIT_WORK(&udc->vbus_work, mv_udc_vbus_work); @@ -2358,7 +2298,8 @@ static int mv_udc_probe(struct platform_device *pdev)  	else  		udc->vbus_active = 1; -	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget); +	retval = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget, +			gadget_release);  	if (retval)  		goto err_create_workqueue; @@ -2370,8 +2311,6 @@ static int mv_udc_probe(struct platform_device *pdev)  err_create_workqueue:  	destroy_workqueue(udc->qwork); -err_unregister: -	device_unregister(&udc->gadget.dev);  err_destroy_dma:  	dma_pool_destroy(udc->dtd_pool);  err_free_dma: diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index a22ad9af056..3b02fd4649c 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c @@ -111,6 +111,7 @@ static struct usb_gadget_strings *dev_strings[] = {  	NULL,  }; +struct eth_dev *the_dev;  static u8 hostaddr[ETH_ALEN];  /*-------------------------------------------------------------------------*/ @@ -124,7 +125,7 @@ static int __init ncm_do_config(struct usb_configuration *c)  		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;  	} -	return ncm_bind_config(c, hostaddr); +	return ncm_bind_config(c, hostaddr, the_dev);  }  static struct usb_configuration ncm_config_driver = { @@ -143,9 +144,9 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)  	int			status;  	/* set up network link layer */ -	status = gether_setup(cdev->gadget, hostaddr); -	if (status < 0) -		return status; +	the_dev = gether_setup(cdev->gadget, hostaddr); +	if (IS_ERR(the_dev)) +		return PTR_ERR(the_dev);  	/* Allocate string descriptor numbers ... note that string  	 * contents can be overridden by the composite_dev glue. @@ -168,13 +169,13 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)  	return 0;  fail: -	gether_cleanup(); +	gether_cleanup(the_dev);  	return status;  }  static int __exit gncm_unbind(struct usb_composite_dev *cdev)  { -	gether_cleanup(); +	gether_cleanup(the_dev);  	return 0;  } diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index d226058e3b8..f1e50a3e322 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -58,8 +58,7 @@ static const char * const ep_name[] = {  	"ep-a", "ep-b", "ep-c",  }; -#define DMA_ADDR_INVALID	(~(dma_addr_t)0) -#ifdef CONFIG_USB_GADGET_NET2272_DMA +#ifdef CONFIG_USB_NET2272_DMA  /*   * use_dma: the NET2272 can use an external DMA controller.   * Note that since there is no generic DMA api, some functions, @@ -341,7 +340,6 @@ net2272_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)  	if (!req)  		return NULL; -	req->req.dma = DMA_ADDR_INVALID;  	INIT_LIST_HEAD(&req->queue);  	return &req->req; @@ -913,7 +911,7 @@ net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)  			}  		}  	} -	if (likely(req != 0)) +	if (likely(req))  		list_add_tail(&req->queue, &ep->queue);  	if (likely(!list_empty(&ep->queue))) @@ -1467,7 +1465,6 @@ static int net2272_start(struct usb_gadget *_gadget,  	dev->softconnect = 1;  	driver->driver.bus = NULL;  	dev->driver = driver; -	dev->gadget.dev.driver = &driver->driver;  	/* ... then enable host detection and ep0; and we're ready  	 * for set_configuration as well as eventual disconnect. @@ -1495,6 +1492,13 @@ stop_activity(struct net2272 *dev, struct usb_gadget_driver *driver)  	for (i = 0; i < 4; ++i)  		net2272_dequeue_all(&dev->ep[i]); +	/* report disconnect; the driver is already quiesced */ +	if (driver) { +		spin_unlock(&dev->lock); +		driver->disconnect(&dev->gadget); +		spin_lock(&dev->lock); +	} +  	net2272_usb_reinit(dev);  } @@ -1510,7 +1514,6 @@ static int net2272_stop(struct usb_gadget *_gadget,  	stop_activity(dev, driver);  	spin_unlock_irqrestore(&dev->lock, flags); -	dev->gadget.dev.driver = NULL;  	dev->driver = NULL;  	dev_dbg(dev->dev, "unregistered driver '%s'\n", driver->driver.name); @@ -1542,7 +1545,7 @@ net2272_handle_dma(struct net2272_ep *ep)  	      | (ep->dev->dma_eot_polarity << EOT_POLARITY)  	      | (ep->dev->dma_dack_polarity << DACK_POLARITY)  	      | (ep->dev->dma_dreq_polarity << DREQ_POLARITY) -	      | ((ep->dma >> 1) << DMA_ENDPOINT_SELECT)); +	      | (ep->dma << DMA_ENDPOINT_SELECT));  	ep->dev->dma_busy = 0; @@ -1615,7 +1618,7 @@ net2272_handle_ep(struct net2272_ep *ep)  	ep->irqs++;  	dev_vdbg(ep->dev->dev, "%s ack ep_stat0 %02x, ep_stat1 %02x, req %p\n", -		ep->ep.name, stat0, stat1, req ? &req->req : 0); +		ep->ep.name, stat0, stat1, req ? &req->req : NULL);  	net2272_ep_write(ep, EP_STAT0, stat0 &  		~((1 << NAK_OUT_PACKETS) @@ -2209,7 +2212,6 @@ net2272_remove(struct net2272 *dev)  	free_irq(dev->irq, dev);  	iounmap(dev->base_addr); -	device_unregister(&dev->gadget.dev);  	device_remove_file(dev->dev, &dev_attr_registers);  	dev_info(dev->dev, "unbind\n"); @@ -2236,10 +2238,6 @@ static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq)  	ret->gadget.max_speed = USB_SPEED_HIGH;  	/* the "gadget" abstracts/virtualizes the controller */ -	dev_set_name(&ret->gadget.dev, "gadget"); -	ret->gadget.dev.parent = dev; -	ret->gadget.dev.dma_mask = dev->dma_mask; -	ret->gadget.dev.release = net2272_gadget_release;  	ret->gadget.name = driver_name;  	return ret; @@ -2275,14 +2273,12 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)  		dma_mode_string());  	dev_info(dev->dev, "version: %s\n", driver_vers); -	ret = device_register(&dev->gadget.dev); -	if (ret) -		goto err_irq;  	ret = device_create_file(dev->dev, &dev_attr_registers);  	if (ret) -		goto err_dev_reg; +		goto err_irq; -	ret = usb_add_gadget_udc(dev->dev, &dev->gadget); +	ret = usb_add_gadget_udc_release(dev->dev, &dev->gadget, +			net2272_gadget_release);  	if (ret)  		goto err_add_udc; @@ -2290,8 +2286,6 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)  err_add_udc:  	device_remove_file(dev->dev, &dev_attr_registers); - err_dev_reg: -	device_unregister(&dev->gadget.dev);   err_irq:  	free_irq(dev->irq, dev);   err: diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index a1b650e1133..fbd006ab31d 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -65,7 +65,6 @@  #define	DRIVER_DESC		"PLX NET228x USB Peripheral Controller"  #define	DRIVER_VERSION		"2005 Sept 27" -#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)  #define	EP_DONTUSE		13	/* nonzero */  #define USE_RDK_LEDS		/* GPIO pins control three LEDs */ @@ -406,7 +405,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)  	if (!req)  		return NULL; -	req->req.dma = DMA_ADDR_INVALID;  	INIT_LIST_HEAD (&req->queue);  	/* this dma descriptor may be swapped with the previous dummy */ @@ -420,7 +418,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)  			return NULL;  		}  		td->dmacount = 0;	/* not VALID */ -		td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);  		td->dmadesc = td->dmaaddr;  		req->td = td;  	} @@ -1896,7 +1893,6 @@ static int net2280_start(struct usb_gadget *_gadget,  	dev->softconnect = 1;  	driver->driver.bus = NULL;  	dev->driver = driver; -	dev->gadget.dev.driver = &driver->driver;  	retval = device_create_file (&dev->pdev->dev, &dev_attr_function);  	if (retval) goto err_unbind; @@ -1924,8 +1920,6 @@ static int net2280_start(struct usb_gadget *_gadget,  err_func:  	device_remove_file (&dev->pdev->dev, &dev_attr_function);  err_unbind: -	driver->unbind (&dev->gadget); -	dev->gadget.dev.driver = NULL;  	dev->driver = NULL;  	return retval;  } @@ -1946,6 +1940,13 @@ stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)  	for (i = 0; i < 7; i++)  		nuke (&dev->ep [i]); +	/* report disconnect; the driver is already quiesced */ +	if (driver) { +		spin_unlock(&dev->lock); +		driver->disconnect(&dev->gadget); +		spin_lock(&dev->lock); +	} +  	usb_reinit (dev);  } @@ -1961,7 +1962,6 @@ static int net2280_stop(struct usb_gadget *_gadget,  	stop_activity (dev, driver);  	spin_unlock_irqrestore (&dev->lock, flags); -	dev->gadget.dev.driver = NULL;  	dev->driver = NULL;  	net2280_led_active (dev, 0); @@ -2066,7 +2066,7 @@ static void handle_ep_small (struct net2280_ep *ep)  		return;  	/* manual DMA queue advance after short OUT */ -	if (likely (ep->dma != 0)) { +	if (likely (ep->dma)) {  		if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {  			u32	count;  			int	stopped = ep->stopped; @@ -2324,7 +2324,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)  			/* hw handles device and interface status */  			if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))  				goto delegate; -			if ((e = get_ep_by_addr (dev, w_index)) == 0 +			if ((e = get_ep_by_addr (dev, w_index)) == NULL  					|| w_length > 2)  				goto do_stall; @@ -2352,7 +2352,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)  			if (w_value != USB_ENDPOINT_HALT  					|| w_length != 0)  				goto do_stall; -			if ((e = get_ep_by_addr (dev, w_index)) == 0) +			if ((e = get_ep_by_addr (dev, w_index)) == NULL)  				goto do_stall;  			if (e->wedged) {  				VDEBUG(dev, "%s wedged, halt not cleared\n", @@ -2374,7 +2374,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)  			if (w_value != USB_ENDPOINT_HALT  					|| w_length != 0)  				goto do_stall; -			if ((e = get_ep_by_addr (dev, w_index)) == 0) +			if ((e = get_ep_by_addr (dev, w_index)) == NULL)  				goto do_stall;  			if (e->ep.name == ep0name)  				goto do_stall; @@ -2679,7 +2679,6 @@ static void net2280_remove (struct pci_dev *pdev)  				pci_resource_len (pdev, 0));  	if (dev->enabled)  		pci_disable_device (pdev); -	device_unregister (&dev->gadget.dev);  	device_remove_file (&pdev->dev, &dev_attr_registers);  	pci_set_drvdata (pdev, NULL); @@ -2711,10 +2710,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)  	dev->gadget.max_speed = USB_SPEED_HIGH;  	/* the "gadget" abstracts/virtualizes the controller */ -	dev_set_name(&dev->gadget.dev, "gadget"); -	dev->gadget.dev.parent = &pdev->dev; -	dev->gadget.dev.dma_mask = pdev->dev.dma_mask; -	dev->gadget.dev.release = gadget_release;  	dev->gadget.name = driver_name;  	/* now all the pci goodies ... */ @@ -2796,7 +2791,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)  			goto done;  		}  		td->dmacount = 0;	/* not VALID */ -		td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);  		td->dmadesc = td->dmaaddr;  		dev->ep [i].dummy = td;  	} @@ -2823,12 +2817,11 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)  			use_dma  				? (use_dma_chaining ? "chaining" : "enabled")  				: "disabled"); -	retval = device_register (&dev->gadget.dev); -	if (retval) goto done;  	retval = device_create_file (&pdev->dev, &dev_attr_registers);  	if (retval) goto done; -	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget); +	retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget, +			gadget_release);  	if (retval)  		goto done;  	return 0; diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index def37403989..3b344b41a16 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -37,11 +37,9 @@   * the runtime footprint, and giving us at least some parts of what   * a "gcc --combine ... part1.c part2.c part3.c ... " build would.   */ -#define USB_FACM_INCLUDED -#include "f_acm.c" +#define USBF_OBEX_INCLUDED  #include "f_ecm.c"  #include "f_obex.c" -#include "f_serial.c"  #include "f_phonet.c"  #include "u_ether.c" @@ -98,20 +96,40 @@ MODULE_AUTHOR("Felipe Balbi");  MODULE_LICENSE("GPL");  /*-------------------------------------------------------------------------*/ - +static struct usb_function *f_acm_cfg1; +static struct usb_function *f_acm_cfg2;  static u8 hostaddr[ETH_ALEN]; +static struct eth_dev *the_dev;  enum {  	TTY_PORT_OBEX0,  	TTY_PORT_OBEX1, -	TTY_PORT_ACM,  	TTY_PORTS_MAX,  };  static unsigned char tty_lines[TTY_PORTS_MAX]; +static struct usb_configuration nokia_config_500ma_driver = { +	.label		= "Bus Powered", +	.bConfigurationValue = 1, +	/* .iConfiguration = DYNAMIC */ +	.bmAttributes	= USB_CONFIG_ATT_ONE, +	.MaxPower	= 500, +}; + +static struct usb_configuration nokia_config_100ma_driver = { +	.label		= "Self Powered", +	.bConfigurationValue = 2, +	/* .iConfiguration = DYNAMIC */ +	.bmAttributes	= USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, +	.MaxPower	= 100, +}; + +static struct usb_function_instance *fi_acm; +  static int __init nokia_bind_config(struct usb_configuration *c)  { +	struct usb_function *f_acm;  	int status = 0;  	status = phonet_bind_config(c); @@ -126,33 +144,32 @@ static int __init nokia_bind_config(struct usb_configuration *c)  	if (status)  		printk(KERN_DEBUG "could not bind obex config %d\n", 0); -	status = acm_bind_config(c, tty_lines[TTY_PORT_ACM]); -	if (status) -		printk(KERN_DEBUG "could not bind acm config\n"); +	f_acm = usb_get_function(fi_acm); +	if (IS_ERR(f_acm)) +		return PTR_ERR(f_acm); -	status = ecm_bind_config(c, hostaddr); +	status = usb_add_function(c, f_acm);  	if (status) -		printk(KERN_DEBUG "could not bind ecm config\n"); +		goto err_conf; + +	status = ecm_bind_config(c, hostaddr, the_dev); +	if (status) { +		pr_debug("could not bind ecm config %d\n", status); +		goto err_ecm; +	} +	if (c == &nokia_config_500ma_driver) +		f_acm_cfg1 = f_acm; +	else +		f_acm_cfg2 = f_acm;  	return status; +err_ecm: +	usb_remove_function(c, f_acm); +err_conf: +	usb_put_function(f_acm); +	return status;  } -static struct usb_configuration nokia_config_500ma_driver = { -	.label		= "Bus Powered", -	.bConfigurationValue = 1, -	/* .iConfiguration = DYNAMIC */ -	.bmAttributes	= USB_CONFIG_ATT_ONE, -	.MaxPower	= 500, -}; - -static struct usb_configuration nokia_config_100ma_driver = { -	.label		= "Self Powered", -	.bConfigurationValue = 2, -	/* .iConfiguration = DYNAMIC */ -	.bmAttributes	= USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, -	.MaxPower	= 100, -}; -  static int __init nokia_bind(struct usb_composite_dev *cdev)  {  	struct usb_gadget	*gadget = cdev->gadget; @@ -169,9 +186,11 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)  			goto err_ether;  	} -	status = gether_setup(cdev->gadget, hostaddr); -	if (status < 0) +	the_dev = gether_setup(cdev->gadget, hostaddr); +	if (IS_ERR(the_dev)) { +		status = PTR_ERR(the_dev);  		goto err_ether; +	}  	status = usb_string_ids_tab(cdev, strings_dev);  	if (status < 0) @@ -185,24 +204,32 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)  	if (!gadget_supports_altsettings(gadget))  		goto err_usb; +	fi_acm = usb_get_function_instance("acm"); +	if (IS_ERR(fi_acm)) +		goto err_usb; +  	/* finally register the configuration */  	status = usb_add_config(cdev, &nokia_config_500ma_driver,  			nokia_bind_config);  	if (status < 0) -		goto err_usb; +		goto err_acm_inst;  	status = usb_add_config(cdev, &nokia_config_100ma_driver,  			nokia_bind_config);  	if (status < 0) -		goto err_usb; +		goto err_put_cfg1;  	usb_composite_overwrite_options(cdev, &coverwrite);  	dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME);  	return 0; +err_put_cfg1: +	usb_put_function(f_acm_cfg1); +err_acm_inst: +	usb_put_function_instance(fi_acm);  err_usb: -	gether_cleanup(); +	gether_cleanup(the_dev);  err_ether:  	cur_line--;  	while (cur_line >= 0) @@ -217,12 +244,15 @@ static int __exit nokia_unbind(struct usb_composite_dev *cdev)  {  	int i; +	usb_put_function(f_acm_cfg1); +	usb_put_function(f_acm_cfg2); +	usb_put_function_instance(fi_acm);  	gphonet_cleanup();  	for (i = 0; i < TTY_PORTS_MAX; i++)  		gserial_free_line(tty_lines[i]); -	gether_cleanup(); +	gether_cleanup(the_dev);  	return 0;  } @@ -247,4 +277,3 @@ static void __exit nokia_cleanup(void)  	usb_composite_unregister(&nokia_driver);  }  module_exit(nokia_cleanup); - diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index f8445653577..b8ed74a823c 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2067,7 +2067,6 @@ static int omap_udc_start(struct usb_gadget *g,  	/* hook up the driver */  	driver->driver.bus = NULL;  	udc->driver = driver; -	udc->gadget.dev.driver = &driver->driver;  	spin_unlock_irqrestore(&udc->lock, flags);  	if (udc->dc_clk != NULL) @@ -2083,7 +2082,6 @@ static int omap_udc_start(struct usb_gadget *g,  			ERR("can't bind to transceiver\n");  			if (driver->unbind) {  				driver->unbind(&udc->gadget); -				udc->gadget.dev.driver = NULL;  				udc->driver = NULL;  			}  			goto done; @@ -2129,7 +2127,6 @@ static int omap_udc_stop(struct usb_gadget *g,  	udc_quiesce(udc);  	spin_unlock_irqrestore(&udc->lock, flags); -	udc->gadget.dev.driver = NULL;  	udc->driver = NULL;  	if (udc->dc_clk != NULL) @@ -2631,14 +2628,6 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)  	udc->gadget.speed = USB_SPEED_UNKNOWN;  	udc->gadget.max_speed = USB_SPEED_FULL;  	udc->gadget.name = driver_name; - -	device_initialize(&udc->gadget.dev); -	dev_set_name(&udc->gadget.dev, "gadget"); -	udc->gadget.dev.release = omap_udc_release; -	udc->gadget.dev.parent = &odev->dev; -	if (use_dma) -		udc->gadget.dev.dma_mask = odev->dev.dma_mask; -  	udc->transceiver = xceiv;  	/* ep0 is special; put it right after the SETUP buffer */ @@ -2912,14 +2901,13 @@ bad_on_1710:  	}  	create_proc_file(); -	status = device_add(&udc->gadget.dev); +	status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget, +			omap_udc_release);  	if (status)  		goto cleanup4; -	status = usb_add_gadget_udc(&pdev->dev, &udc->gadget); -	if (!status) -		return status; -	/* If fail, fall through */ +	return 0; +  cleanup4:  	remove_proc_file(); @@ -2990,7 +2978,6 @@ static int omap_udc_remove(struct platform_device *pdev)  	release_mem_region(pdev->resource[0].start,  			pdev->resource[0].end - pdev->resource[0].start + 1); -	device_unregister(&udc->gadget.dev);  	wait_for_completion(&done);  	return 0; diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index a787a8ef672..24174e1d156 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -358,7 +358,6 @@ struct pch_udc_dev {  			prot_stall:1,  			irq_registered:1,  			mem_region:1, -			registered:1,  			suspended:1,  			connected:1,  			vbus_session:1, @@ -1441,6 +1440,8 @@ static void pch_vbus_gpio_free(struct pch_udc_dev *dev)   */  static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,  								 int status) +	__releases(&dev->lock) +	__acquires(&dev->lock)  {  	struct pch_udc_dev	*dev;  	unsigned halted = ep->halted; @@ -2382,6 +2383,8 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev)   * @dev:	Reference to the device structure   */  static void pch_udc_svc_control_out(struct pch_udc_dev *dev) +	__releases(&dev->lock) +	__acquires(&dev->lock)  {  	u32	stat;  	int setup_supported; @@ -2989,7 +2992,6 @@ static int pch_udc_start(struct usb_gadget *g,  	driver->driver.bus = NULL;  	dev->driver = driver; -	dev->gadget.dev.driver = &driver->driver;  	/* get ready for ep0 traffic */  	pch_udc_setup_ep0(dev); @@ -3010,7 +3012,6 @@ static int pch_udc_stop(struct usb_gadget *g,  	pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);  	/* Assures that there are no pending requests with this driver */ -	dev->gadget.dev.driver = NULL;  	dev->driver = NULL;  	dev->connected = 0; @@ -3078,8 +3079,6 @@ static void pch_udc_remove(struct pci_dev *pdev)  				   pci_resource_len(pdev, PCH_UDC_PCI_BAR));  	if (dev->active)  		pci_disable_device(pdev); -	if (dev->registered) -		device_unregister(&dev->gadget.dev);  	kfree(dev);  	pci_set_drvdata(pdev, NULL);  } @@ -3196,21 +3195,13 @@ static int pch_udc_probe(struct pci_dev *pdev,  	if (retval)  		goto finished; -	dev_set_name(&dev->gadget.dev, "gadget"); -	dev->gadget.dev.parent = &pdev->dev; -	dev->gadget.dev.dma_mask = pdev->dev.dma_mask; -	dev->gadget.dev.release = gadget_release;  	dev->gadget.name = KBUILD_MODNAME;  	dev->gadget.max_speed = USB_SPEED_HIGH; -	retval = device_register(&dev->gadget.dev); -	if (retval) -		goto finished; -	dev->registered = 1; -  	/* Put the device in disconnected state till a driver is bound */  	pch_udc_set_disconnect(dev); -	retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget); +	retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget, +			gadget_release);  	if (retval)  		goto finished;  	return 0; diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index d0f37484b6b..ef47495dec8 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -1263,7 +1263,6 @@ static int pxa25x_udc_start(struct usb_gadget *g,  	/* first hook up the driver ... */  	dev->driver = driver; -	dev->gadget.dev.driver = &driver->driver;  	dev->pullup = 1;  	/* ... then enable host detection and ep0; and we're ready @@ -1325,7 +1324,6 @@ static int pxa25x_udc_stop(struct usb_gadget*g,  	if (!IS_ERR_OR_NULL(dev->transceiver))  		(void) otg_set_peripheral(dev->transceiver->otg, NULL); -	dev->gadget.dev.driver = NULL;  	dev->driver = NULL;  	dump_state(dev); @@ -2138,17 +2136,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)  	dev->timer.function = udc_watchdog;  	dev->timer.data = (unsigned long) dev; -	device_initialize(&dev->gadget.dev); -	dev->gadget.dev.parent = &pdev->dev; -	dev->gadget.dev.dma_mask = pdev->dev.dma_mask; - -	retval = device_add(&dev->gadget.dev); -	if (retval) { -		dev->driver = NULL; -		dev->gadget.dev.driver = NULL; -		goto err_device_add; -	} -  	the_controller = dev;  	platform_set_drvdata(pdev, dev); @@ -2199,8 +2186,6 @@ lubbock_fail0:  	free_irq(irq, dev);  #endif   err_irq1: -	device_unregister(&dev->gadget.dev); - err_device_add:  	if (gpio_is_valid(dev->mach->gpio_pullup))  		gpio_free(dev->mach->gpio_pullup);   err_gpio_pullup: @@ -2226,7 +2211,6 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)  		return -EBUSY;  	usb_del_gadget_udc(&dev->gadget); -	device_unregister(&dev->gadget.dev);  	dev->pullup = 0;  	pullup(dev); diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 2fc867652ef..6b4c7d95853 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -24,14 +24,12 @@  #include <linux/gpio.h>  #include <linux/slab.h>  #include <linux/prefetch.h> - -#include <asm/byteorder.h> -#include <mach/hardware.h> +#include <linux/byteorder/generic.h> +#include <linux/platform_data/pxa2xx_udc.h>  #include <linux/usb.h>  #include <linux/usb/ch9.h>  #include <linux/usb/gadget.h> -#include <mach/udc.h>  #include "pxa27x_udc.h" @@ -611,7 +609,7 @@ static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in)   *   * Find the physical pxa27x ep, and setup its UDCCR   */ -static __init void pxa_ep_setup(struct pxa_ep *ep) +static void pxa_ep_setup(struct pxa_ep *ep)  {  	u32 new_udccr; @@ -633,7 +631,7 @@ static __init void pxa_ep_setup(struct pxa_ep *ep)   *   * Setup all pxa physical endpoints, except ep0   */ -static __init void pxa_eps_setup(struct pxa_udc *dev) +static void pxa_eps_setup(struct pxa_udc *dev)  {  	unsigned int i; @@ -1718,7 +1716,7 @@ static void udc_disable(struct pxa_udc *udc)   * Initializes gadget endpoint list, endpoints locks. No action is taken   * on the hardware.   */ -static __init void udc_init_data(struct pxa_udc *dev) +static void udc_init_data(struct pxa_udc *dev)  {  	int i;  	struct pxa_ep *ep; @@ -1811,7 +1809,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,  	/* first hook up the driver ... */  	udc->driver = driver; -	udc->gadget.dev.driver = &driver->driver;  	dplus_pullup(udc, 1);  	if (!IS_ERR_OR_NULL(udc->transceiver)) { @@ -1829,7 +1826,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,  fail:  	udc->driver = NULL; -	udc->gadget.dev.driver = NULL;  	return retval;  } @@ -1871,7 +1867,6 @@ static int pxa27x_udc_stop(struct usb_gadget *g,  	udc->driver = NULL; -  	if (!IS_ERR_OR_NULL(udc->transceiver))  		return otg_set_peripheral(udc->transceiver->otg, NULL);  	return 0; @@ -2413,7 +2408,7 @@ static struct pxa_udc memory = {   * Perform basic init : allocates udc clock, creates sysfs files, requests   * irq.   */ -static int __init pxa_udc_probe(struct platform_device *pdev) +static int pxa_udc_probe(struct platform_device *pdev)  {  	struct resource *regs;  	struct pxa_udc *udc = &memory; @@ -2456,9 +2451,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)  		goto err_map;  	} -	device_initialize(&udc->gadget.dev); -	udc->gadget.dev.parent = &pdev->dev; -	udc->gadget.dev.dma_mask = NULL;  	udc->vbus_sensed = 0;  	the_controller = udc; @@ -2475,12 +2467,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)  		goto err_irq;  	} -	retval = device_add(&udc->gadget.dev); -	if (retval) { -		dev_err(udc->dev, "device_add error %d\n", retval); -		goto err_dev_add; -	} -  	retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);  	if (retval)  		goto err_add_udc; @@ -2490,8 +2476,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)  	return 0;  err_add_udc: -	device_unregister(&udc->gadget.dev); -err_dev_add:  	free_irq(udc->irq, udc);  err_irq:  	iounmap(udc->regs); @@ -2506,13 +2490,12 @@ err_clk:   * pxa_udc_remove - removes the udc device driver   * @_dev: platform device   */ -static int __exit pxa_udc_remove(struct platform_device *_dev) +static int pxa_udc_remove(struct platform_device *_dev)  {  	struct pxa_udc *udc = platform_get_drvdata(_dev);  	int gpio = udc->mach->gpio_pullup;  	usb_del_gadget_udc(&udc->gadget); -	device_del(&udc->gadget.dev);  	usb_gadget_unregister_driver(udc->driver);  	free_irq(udc->irq, udc);  	pxa_cleanup_debugfs(udc); @@ -2625,7 +2608,8 @@ static struct platform_driver udc_driver = {  		.name	= "pxa27x-udc",  		.owner	= THIS_MODULE,  	}, -	.remove		= __exit_p(pxa_udc_remove), +	.probe		= pxa_udc_probe, +	.remove		= pxa_udc_remove,  	.shutdown	= pxa_udc_shutdown,  #ifdef CONFIG_PM  	.suspend	= pxa_udc_suspend, @@ -2633,22 +2617,7 @@ static struct platform_driver udc_driver = {  #endif  }; -static int __init udc_init(void) -{ -	if (!cpu_is_pxa27x() && !cpu_is_pxa3xx()) -		return -ENODEV; - -	printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION); -	return platform_driver_probe(&udc_driver, pxa_udc_probe); -} -module_init(udc_init); - - -static void __exit udc_exit(void) -{ -	platform_driver_unregister(&udc_driver); -} -module_exit(udc_exit); +module_platform_driver(udc_driver);  MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_AUTHOR("Robert Jarzmik"); diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index f46a1b77ce3..0b742d17184 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -1837,7 +1837,6 @@ static int __exit r8a66597_remove(struct platform_device *pdev)  		clk_put(r8a66597->clk);  	} -	device_unregister(&r8a66597->gadget.dev);  	kfree(r8a66597);  	return 0;  } @@ -1915,17 +1914,8 @@ static int __init r8a66597_probe(struct platform_device *pdev)  	r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;  	r8a66597->gadget.ops = &r8a66597_gadget_ops; -	dev_set_name(&r8a66597->gadget.dev, "gadget");  	r8a66597->gadget.max_speed = USB_SPEED_HIGH; -	r8a66597->gadget.dev.parent = &pdev->dev; -	r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask; -	r8a66597->gadget.dev.release = pdev->dev.release;  	r8a66597->gadget.name = udc_name; -	ret = device_register(&r8a66597->gadget.dev); -	if (ret < 0) { -		dev_err(&pdev->dev, "device_register failed\n"); -		goto clean_up; -	}  	init_timer(&r8a66597->timer);  	r8a66597->timer.function = r8a66597_timer; @@ -1939,7 +1929,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)  			dev_err(&pdev->dev, "cannot get clock \"%s\"\n",  				clk_name);  			ret = PTR_ERR(r8a66597->clk); -			goto clean_up_dev; +			goto clean_up;  		}  		clk_enable(r8a66597->clk);  	} @@ -2007,8 +1997,6 @@ clean_up2:  		clk_disable(r8a66597->clk);  		clk_put(r8a66597->clk);  	} -clean_up_dev: -	device_unregister(&r8a66597->gadget.dev);  clean_up:  	if (r8a66597) {  		if (r8a66597->sudmac_reg) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index c26564f29a2..a3cdc32115d 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -39,8 +39,6 @@  #include "s3c-hsotg.h" -#define DMA_ADDR_INVALID (~((dma_addr_t)0)) -  static const char * const s3c_hsotg_supply_names[] = {  	"vusb_d",		/* digital USB supply, 1.2V */  	"vusb_a",		/* analog USB supply, 1.1V */ @@ -405,7 +403,6 @@ static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep,  	INIT_LIST_HEAD(&req->queue); -	req->req.dma = DMA_ADDR_INVALID;  	return &req->req;  } @@ -435,24 +432,12 @@ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg,  				struct s3c_hsotg_req *hs_req)  {  	struct usb_request *req = &hs_req->req; -	enum dma_data_direction dir; - -	dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;  	/* ignore this if we're not moving any data */  	if (hs_req->req.length == 0)  		return; -	if (hs_req->mapped) { -		/* we mapped this, so unmap and remove the dma */ - -		dma_unmap_single(hsotg->dev, req->dma, req->length, dir); - -		req->dma = DMA_ADDR_INVALID; -		hs_req->mapped = 0; -	} else { -		dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir); -	} +	usb_gadget_unmap_request(&hsotg->gadget, hs_req, hs_ep->dir_in);  }  /** @@ -852,37 +837,16 @@ static int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg,  			     struct s3c_hsotg_ep *hs_ep,  			     struct usb_request *req)  { -	enum dma_data_direction dir;  	struct s3c_hsotg_req *hs_req = our_req(req); - -	dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE; +	int ret;  	/* if the length is zero, ignore the DMA data */  	if (hs_req->req.length == 0)  		return 0; -	if (req->dma == DMA_ADDR_INVALID) { -		dma_addr_t dma; - -		dma = dma_map_single(hsotg->dev, req->buf, req->length, dir); - -		if (unlikely(dma_mapping_error(hsotg->dev, dma))) -			goto dma_error; - -		if (dma & 3) { -			dev_err(hsotg->dev, "%s: unaligned dma buffer\n", -				__func__); - -			dma_unmap_single(hsotg->dev, dma, req->length, dir); -			return -EINVAL; -		} - -		hs_req->mapped = 1; -		req->dma = dma; -	} else { -		dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir); -		hs_req->mapped = 0; -	} +	ret = usb_gadget_map_request(&hsotg->gadget, req, hs_ep->dir_in); +	if (ret) +		goto dma_error;  	return 0; @@ -2961,9 +2925,7 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,  	driver->driver.bus = NULL;  	hsotg->driver = driver; -	hsotg->gadget.dev.driver = &driver->driver;  	hsotg->gadget.dev.of_node = hsotg->dev->of_node; -	hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask;  	hsotg->gadget.speed = USB_SPEED_UNKNOWN;  	ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), @@ -2979,7 +2941,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,  err:  	hsotg->driver = NULL; -	hsotg->gadget.dev.driver = NULL;  	return ret;  } @@ -3014,7 +2975,6 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,  	hsotg->driver = NULL;  	hsotg->gadget.speed = USB_SPEED_UNKNOWN; -	hsotg->gadget.dev.driver = NULL;  	spin_unlock_irqrestore(&hsotg->lock, flags); @@ -3484,16 +3444,6 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)  }  /** - * s3c_hsotg_release - release callback for hsotg device - * @dev: Device to for which release is called - * - * Nothing to do as the resource is allocated using devm_ API. - */ -static void s3c_hsotg_release(struct device *dev) -{ -} - -/**   * s3c_hsotg_probe - probe function for hsotg driver   * @pdev: The platform information for the driver   */ @@ -3517,7 +3467,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)  	}  	phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); -	if (IS_ERR_OR_NULL(phy)) { +	if (IS_ERR(phy)) {  		/* Fallback for pdata */  		plat = pdev->dev.platform_data;  		if (!plat) { @@ -3567,18 +3517,10 @@ static int s3c_hsotg_probe(struct platform_device *pdev)  	dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq); -	device_initialize(&hsotg->gadget.dev); - -	dev_set_name(&hsotg->gadget.dev, "gadget"); -  	hsotg->gadget.max_speed = USB_SPEED_HIGH;  	hsotg->gadget.ops = &s3c_hsotg_gadget_ops;  	hsotg->gadget.name = dev_name(dev); -	hsotg->gadget.dev.parent = dev; -	hsotg->gadget.dev.dma_mask = dev->dma_mask; -	hsotg->gadget.dev.release = s3c_hsotg_release; -  	/* reset the system */  	clk_prepare_enable(hsotg->clk); @@ -3658,12 +3600,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)  	s3c_hsotg_phy_disable(hsotg); -	ret = device_add(&hsotg->gadget.dev); -	if (ret) { -		put_device(&hsotg->gadget.dev); -		goto err_ep_mem; -	} -  	ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);  	if (ret)  		goto err_ep_mem; @@ -3702,10 +3638,8 @@ static int s3c_hsotg_remove(struct platform_device *pdev)  	}  	s3c_hsotg_phy_disable(hsotg); -  	clk_disable_unprepare(hsotg->clk); -	device_unregister(&hsotg->gadget.dev);  	return 0;  } diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index 458965a1b13..b1f0771fbd3 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -283,7 +283,6 @@ static void s3c_hsudc_nuke_ep(struct s3c_hsudc_ep *hsep, int status)  /**   * s3c_hsudc_stop_activity - Stop activity on all endpoints.   * @hsudc: Device controller for which EP activity is to be stopped. - * @driver: Reference to the gadget driver which is currently active.   *   * All the endpoints are stopped and any pending transfer requests if any on   * the endpoint are terminated. @@ -1154,7 +1153,6 @@ static int s3c_hsudc_start(struct usb_gadget *gadget,  		return -EBUSY;  	hsudc->driver = driver; -	hsudc->gadget.dev.driver = &driver->driver;  	ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies),  				    hsudc->supplies); @@ -1190,7 +1188,6 @@ err_otg:  	regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);  err_supplies:  	hsudc->driver = NULL; -	hsudc->gadget.dev.driver = NULL;  	return ret;  } @@ -1208,7 +1205,6 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget,  	spin_lock_irqsave(&hsudc->lock, flags);  	hsudc->driver = NULL; -	hsudc->gadget.dev.driver = NULL;  	hsudc->gadget.speed = USB_SPEED_UNKNOWN;  	s3c_hsudc_uninit_phy(); @@ -1303,15 +1299,10 @@ static int s3c_hsudc_probe(struct platform_device *pdev)  	spin_lock_init(&hsudc->lock); -	dev_set_name(&hsudc->gadget.dev, "gadget"); -  	hsudc->gadget.max_speed = USB_SPEED_HIGH;  	hsudc->gadget.ops = &s3c_hsudc_gadget_ops;  	hsudc->gadget.name = dev_name(dev); -	hsudc->gadget.dev.parent = dev; -	hsudc->gadget.dev.dma_mask = dev->dma_mask;  	hsudc->gadget.ep0 = &hsudc->ep[0].ep; -  	hsudc->gadget.is_otg = 0;  	hsudc->gadget.is_a_peripheral = 0;  	hsudc->gadget.speed = USB_SPEED_UNKNOWN; @@ -1345,12 +1336,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)  	disable_irq(hsudc->irq);  	local_irq_enable(); -	ret = device_register(&hsudc->gadget.dev); -	if (ret) { -		put_device(&hsudc->gadget.dev); -		goto err_add_device; -	} -  	ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget);  	if (ret)  		goto err_add_udc; @@ -1359,7 +1344,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)  	return 0;  err_add_udc: -	device_unregister(&hsudc->gadget.dev);  err_add_device:  	clk_disable(hsudc->uclk);  err_res: diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 08f89652533..d0e75e1b3cc 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1674,7 +1674,6 @@ static int s3c2410_udc_start(struct usb_gadget *g,  	/* Hook the driver */  	udc->driver = driver; -	udc->gadget.dev.driver = &driver->driver;  	/* Enable udc */  	s3c2410_udc_enable(udc); @@ -1824,17 +1823,6 @@ static int s3c2410_udc_probe(struct platform_device *pdev)  		goto err_mem;  	} -	device_initialize(&udc->gadget.dev); -	udc->gadget.dev.parent = &pdev->dev; -	udc->gadget.dev.dma_mask = pdev->dev.dma_mask; - -	/* Bind the driver */ -	retval = device_add(&udc->gadget.dev); -	if (retval) { -		dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval); -		goto err_device_add; -	} -  	the_controller = udc;  	platform_set_drvdata(pdev, udc); @@ -1923,8 +1911,6 @@ err_gpio_claim:  err_int:  	free_irq(IRQ_USBD, udc);  err_map: -	device_unregister(&udc->gadget.dev); -err_device_add:  	iounmap(base_addr);  err_mem:  	release_mem_region(rsrc_start, rsrc_len); @@ -1946,7 +1932,6 @@ static int s3c2410_udc_remove(struct platform_device *pdev)  		return -EBUSY;  	usb_del_gadget_udc(&udc->gadget); -	device_unregister(&udc->gadget.dev);  	debugfs_remove(udc->regs_info);  	if (udc_info && !udc_info->udc_command && diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 68d7bb06ebc..1f5f978d35d 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -12,6 +12,7 @@  #include <linux/kernel.h>  #include <linux/device.h> +#include <linux/module.h>  #include <linux/tty.h>  #include <linux/tty_flip.h> @@ -28,18 +29,6 @@  #define GS_VERSION_NAME			GS_LONG_NAME " " GS_VERSION_STR  /*-------------------------------------------------------------------------*/ - -/* - * Kbuild is not very cooperative with respect to linking separately - * compiled library objects into one module.  So for now we won't use - * separate compilation ... ensuring init/exit sections work to shrink - * the runtime footprint, and giving us at least some parts of what - * a "gcc --combine ... part1.c part2.c part3.c ... " build would. - */ -#include "f_obex.c" -#include "f_serial.c" - -/*-------------------------------------------------------------------------*/  USB_GADGET_COMPOSITE_OPTIONS();  /* Thanks to NetChip Technologies for donating this product ID. @@ -126,27 +115,6 @@ module_param(n_ports, uint, 0);  MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");  /*-------------------------------------------------------------------------*/ -static unsigned char tty_lines[MAX_U_SERIAL_PORTS]; - -static int __init serial_bind_obex_config(struct usb_configuration *c) -{ -	unsigned i; -	int status = 0; - -	for (i = 0; i < n_ports && status == 0; i++) -		status = obex_bind_config(c, tty_lines[i]); -	return status; -} - -static int __init serial_bind_gser_config(struct usb_configuration *c) -{ -	unsigned i; -	int status = 0; - -	for (i = 0; i < n_ports && status == 0; i++) -		status = gser_bind_config(c, tty_lines[i]); -	return status; -}  static struct usb_configuration serial_config_driver = {  	/* .label = f(use_acm) */ @@ -169,15 +137,12 @@ static int serial_register_ports(struct usb_composite_dev *cdev,  		goto out;  	for (i = 0; i < n_ports; i++) { -		struct f_serial_opts *opts;  		fi_serial[i] = usb_get_function_instance(f_name);  		if (IS_ERR(fi_serial[i])) {  			ret = PTR_ERR(fi_serial[i]);  			goto fail;  		} -		opts = container_of(fi_serial[i], struct f_serial_opts, func_inst); -		opts->port_num = tty_lines[i];  		f_serial[i] = usb_get_function(fi_serial[i]);  		if (IS_ERR(f_serial[i])) { @@ -212,13 +177,6 @@ out:  static int __init gs_bind(struct usb_composite_dev *cdev)  {  	int			status; -	int			cur_line; - -	for (cur_line = 0; cur_line < n_ports; cur_line++) { -		status = gserial_alloc_line(&tty_lines[cur_line]); -		if (status) -			goto fail; -	}  	/* Allocate string descriptor numbers ... note that string  	 * contents can be overridden by the composite_dev glue. @@ -243,11 +201,12 @@ static int __init gs_bind(struct usb_composite_dev *cdev)  				"acm");  		usb_ep_autoconfig_reset(cdev->gadget);  	} else if (use_obex) -		status = usb_add_config(cdev, &serial_config_driver, -				serial_bind_obex_config); -	else -		status = usb_add_config(cdev, &serial_config_driver, -				serial_bind_gser_config); +		status = serial_register_ports(cdev, &serial_config_driver, +				"obex"); +	else { +		status = serial_register_ports(cdev, &serial_config_driver, +				"gser"); +	}  	if (status < 0)  		goto fail; @@ -257,9 +216,6 @@ static int __init gs_bind(struct usb_composite_dev *cdev)  	return 0;  fail: -	cur_line--; -	while (cur_line >= 0) -		gserial_free_line(tty_lines[cur_line--]);  	return status;  } @@ -270,7 +226,6 @@ static int gs_unbind(struct usb_composite_dev *cdev)  	for (i = 0; i < n_ports; i++) {  		usb_put_function(f_serial[i]);  		usb_put_function_instance(fi_serial[i]); -		gserial_free_line(tty_lines[i]);  	}  	return 0;  } diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index a0aa721d8b2..4b76124ce96 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -50,7 +50,6 @@  struct eth_dev {  	/* lock is held while accessing port_usb -	 * or updating its backlink port_usb->ioport  	 */  	spinlock_t		lock;  	struct gether		*port_usb; @@ -729,8 +728,6 @@ static int get_ether_addr(const char *str, u8 *dev_addr)  	return 1;  } -static struct eth_dev *the_dev; -  static const struct net_device_ops eth_netdev_ops = {  	.ndo_open		= eth_open,  	.ndo_stop		= eth_stop, @@ -758,19 +755,16 @@ static struct device_type gadget_type = {   *   * Returns negative errno, or zero on success   */ -int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], +struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],  		const char *netname)  {  	struct eth_dev		*dev;  	struct net_device	*net;  	int			status; -	if (the_dev) -		return -EBUSY; -  	net = alloc_etherdev(sizeof *dev);  	if (!net) -		return -ENOMEM; +		return ERR_PTR(-ENOMEM);  	dev = netdev_priv(net);  	spin_lock_init(&dev->lock); @@ -807,12 +801,11 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],  	if (status < 0) {  		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);  		free_netdev(net); +		dev = ERR_PTR(status);  	} else {  		INFO(dev, "MAC %pM\n", net->dev_addr);  		INFO(dev, "HOST MAC %pM\n", dev->host_mac); -		the_dev = dev; -  		/* two kinds of host-initiated state changes:  		 *  - iff DATA transfer is active, carrier is "on"  		 *  - tx queueing enabled if open *and* carrier is "on" @@ -820,7 +813,7 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],  		netif_carrier_off(net);  	} -	return status; +	return dev;  }  /** @@ -829,19 +822,16 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],   *   * This is called to free all resources allocated by @gether_setup().   */ -void gether_cleanup(void) +void gether_cleanup(struct eth_dev *dev)  { -	if (!the_dev) +	if (!dev)  		return; -	unregister_netdev(the_dev->net); -	flush_work(&the_dev->work); -	free_netdev(the_dev->net); - -	the_dev = NULL; +	unregister_netdev(dev->net); +	flush_work(&dev->work); +	free_netdev(dev->net);  } -  /**   * gether_connect - notify network layer that USB link is active   * @link: the USB link, set up with endpoints, descriptors matching @@ -860,7 +850,7 @@ void gether_cleanup(void)   */  struct net_device *gether_connect(struct gether *link)  { -	struct eth_dev		*dev = the_dev; +	struct eth_dev		*dev = link->ioport;  	int			result = 0;  	if (!dev) @@ -895,7 +885,6 @@ struct net_device *gether_connect(struct gether *link)  		spin_lock(&dev->lock);  		dev->port_usb = link; -		link->ioport = dev;  		if (netif_running(dev->net)) {  			if (link->open)  				link->open(link); @@ -989,6 +978,5 @@ void gether_disconnect(struct gether *link)  	spin_lock(&dev->lock);  	dev->port_usb = NULL; -	link->ioport = NULL;  	spin_unlock(&dev->lock);  } diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h index 6f4a1623d85..02522338a70 100644 --- a/drivers/usb/gadget/u_ether.h +++ b/drivers/usb/gadget/u_ether.h @@ -21,6 +21,7 @@  #include "gadget_chips.h" +struct eth_dev;  /*   * This represents the USB side of an "ethernet" link, managed by a USB @@ -70,7 +71,7 @@ struct gether {  			|USB_CDC_PACKET_TYPE_DIRECTED)  /* variant of gether_setup that allows customizing network device name */ -int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], +struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],  		const char *netname);  /* netdev setup/teardown as directed by the gadget driver */ @@ -86,12 +87,13 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],   *   * Returns negative errno, or zero on success   */ -static inline int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]) +static inline struct eth_dev *gether_setup(struct usb_gadget *g, +		u8 ethaddr[ETH_ALEN])  {  	return gether_setup_name(g, ethaddr, "usb");  } -void gether_cleanup(void); +void gether_cleanup(struct eth_dev *dev);  /* connect/disconnect is handled by individual functions */  struct net_device *gether_connect(struct gether *); @@ -111,21 +113,24 @@ static inline bool can_support_ecm(struct usb_gadget *gadget)  }  /* each configuration may bind one instance of an ethernet link */ -int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); -int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); -int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); -int eem_bind_config(struct usb_configuration *c); +int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], +		struct eth_dev *dev); +int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], +		struct eth_dev *dev); +int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], +		struct eth_dev *dev); +int eem_bind_config(struct usb_configuration *c, struct eth_dev *dev);  #ifdef USB_ETH_RNDIS  int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], -				u32 vendorID, const char *manufacturer); +		u32 vendorID, const char *manufacturer, struct eth_dev *dev);  #else  static inline int  rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], -				u32 vendorID, const char *manufacturer) +		u32 vendorID, const char *manufacturer, struct eth_dev *dev)  {  	return 0;  } @@ -145,9 +150,9 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],   * for calling @gether_cleanup() before module unload.   */  static inline int rndis_bind_config(struct usb_configuration *c, -				    u8 ethaddr[ETH_ALEN]) +		u8 ethaddr[ETH_ALEN], struct eth_dev *dev)  { -	return rndis_bind_config_vendor(c, ethaddr, 0, NULL); +	return rndis_bind_config_vendor(c, ethaddr, 0, NULL, dev);  } diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index c5034d9c946..b369292d4b9 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -136,7 +136,7 @@ static struct portmaster {  	pr_debug(fmt, ##arg)  #endif /* pr_vdebug */  #else -#ifndef pr_vdebig +#ifndef pr_vdebug  #define pr_vdebug(fmt, arg...) \  	({ if (0) pr_debug(fmt, ##arg); })  #endif /* pr_vdebug */ diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h index 66ce73a0050..c20210c0bab 100644 --- a/drivers/usb/gadget/u_serial.h +++ b/drivers/usb/gadget/u_serial.h @@ -65,7 +65,6 @@ int gserial_connect(struct gserial *, u8 port_num);  void gserial_disconnect(struct gserial *);  /* functions are bound to configurations by a config or gadget driver */ -int acm_bind_config(struct usb_configuration *c, u8 port_num);  int gser_bind_config(struct usb_configuration *c, u8 port_num);  int obex_bind_config(struct usb_configuration *c, u8 port_num); diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 2a9cd369f71..ffd8fa54110 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -101,6 +101,16 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);  /* ------------------------------------------------------------------------- */ +void usb_gadget_set_state(struct usb_gadget *gadget, +		enum usb_device_state state) +{ +	gadget->state = state; +	sysfs_notify(&gadget->dev.kobj, NULL, "status"); +} +EXPORT_SYMBOL_GPL(usb_gadget_set_state); + +/* ------------------------------------------------------------------------- */ +  /**   * usb_gadget_udc_start - tells usb device controller to start up   * @gadget: The gadget we want to get started @@ -156,15 +166,23 @@ static void usb_udc_release(struct device *dev)  }  static const struct attribute_group *usb_udc_attr_groups[]; + +static void usb_udc_nop_release(struct device *dev) +{ +	dev_vdbg(dev, "%s\n", __func__); +} +  /** - * usb_add_gadget_udc - adds a new gadget to the udc class driver list - * @parent: the parent device to this udc. Usually the controller - * driver's device. - * @gadget: the gadget to be added to the list + * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list + * @parent: the parent device to this udc. Usually the controller driver's + * device. + * @gadget: the gadget to be added to the list. + * @release: a gadget release function.   *   * Returns zero on success, negative errno otherwise.   */ -int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) +int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, +		void (*release)(struct device *dev))  {  	struct usb_udc		*udc;  	int			ret = -ENOMEM; @@ -173,6 +191,22 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)  	if (!udc)  		goto err1; +	dev_set_name(&gadget->dev, "gadget"); +	gadget->dev.parent = parent; + +	dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask); +	gadget->dev.dma_parms = parent->dma_parms; +	gadget->dev.dma_mask = parent->dma_mask; + +	if (release) +		gadget->dev.release = release; +	else +		gadget->dev.release = usb_udc_nop_release; + +	ret = device_register(&gadget->dev); +	if (ret) +		goto err2; +  	device_initialize(&udc->dev);  	udc->dev.release = usb_udc_release;  	udc->dev.class = udc_class; @@ -180,7 +214,7 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)  	udc->dev.parent = parent;  	ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));  	if (ret) -		goto err2; +		goto err3;  	udc->gadget = gadget; @@ -189,21 +223,42 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)  	ret = device_add(&udc->dev);  	if (ret) -		goto err3; +		goto err4; + +	usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);  	mutex_unlock(&udc_lock);  	return 0; -err3: + +err4:  	list_del(&udc->list);  	mutex_unlock(&udc_lock); -err2: +err3:  	put_device(&udc->dev); +err2: +	put_device(&gadget->dev); +	kfree(udc); +  err1:  	return ret;  } +EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release); + +/** + * usb_add_gadget_udc - adds a new gadget to the udc class driver list + * @parent: the parent device to this udc. Usually the controller + * driver's device. + * @gadget: the gadget to be added to the list + * + * Returns zero on success, negative errno otherwise. + */ +int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) +{ +	return usb_add_gadget_udc_release(parent, gadget, NULL); +}  EXPORT_SYMBOL_GPL(usb_add_gadget_udc);  static void usb_gadget_remove_driver(struct usb_udc *udc) @@ -216,10 +271,11 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)  	usb_gadget_disconnect(udc->gadget);  	udc->driver->disconnect(udc->gadget);  	udc->driver->unbind(udc->gadget); -	usb_gadget_udc_stop(udc->gadget, udc->driver); +	usb_gadget_udc_stop(udc->gadget, NULL);  	udc->driver = NULL;  	udc->dev.driver = NULL; +	udc->gadget->dev.driver = NULL;  }  /** @@ -254,6 +310,7 @@ found:  	kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);  	device_unregister(&udc->dev); +	device_unregister(&gadget->dev);  }  EXPORT_SYMBOL_GPL(usb_del_gadget_udc); @@ -268,6 +325,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri  	udc->driver = driver;  	udc->dev.driver = &driver->driver; +	udc->gadget->dev.driver = &driver->driver;  	ret = driver->bind(udc->gadget, driver);  	if (ret) @@ -286,6 +344,7 @@ err1:  			udc->driver->function, ret);  	udc->driver = NULL;  	udc->dev.driver = NULL; +	udc->gadget->dev.driver = NULL;  	return ret;  } @@ -395,6 +454,16 @@ static ssize_t usb_udc_softconn_store(struct device *dev,  }  static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store); +static ssize_t usb_gadget_state_show(struct device *dev, +		struct device_attribute *attr, char *buf) +{ +	struct usb_udc		*udc = container_of(dev, struct usb_udc, dev); +	struct usb_gadget	*gadget = udc->gadget; + +	return sprintf(buf, "%s\n", usb_state_string(gadget->state)); +} +static DEVICE_ATTR(state, S_IRUGO, usb_gadget_state_show, NULL); +  #define USB_UDC_SPEED_ATTR(name, param)					\  ssize_t usb_udc_##param##_show(struct device *dev,			\  		struct device_attribute *attr, char *buf)		\ @@ -403,7 +472,7 @@ ssize_t usb_udc_##param##_show(struct device *dev,			\  	return snprintf(buf, PAGE_SIZE, "%s\n",				\  			usb_speed_string(udc->gadget->param));		\  }									\ -static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL) +static DEVICE_ATTR(name, S_IRUGO, usb_udc_##param##_show, NULL)  static USB_UDC_SPEED_ATTR(current_speed, speed);  static USB_UDC_SPEED_ATTR(maximum_speed, max_speed); @@ -428,6 +497,7 @@ static USB_UDC_ATTR(a_alt_hnp_support);  static struct attribute *usb_udc_attrs[] = {  	&dev_attr_srp.attr,  	&dev_attr_soft_connect.attr, +	&dev_attr_state.attr,  	&dev_attr_current_speed.attr,  	&dev_attr_maximum_speed.attr, diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h index 93b0c119111..817e9e19cec 100644 --- a/drivers/usb/gadget/uvc.h +++ b/drivers/usb/gadget/uvc.h @@ -98,8 +98,6 @@ extern unsigned int uvc_gadget_trace_param;  #define DRIVER_VERSION				"0.1.0"  #define DRIVER_VERSION_NUMBER			KERNEL_VERSION(0, 1, 0) -#define DMA_ADDR_INVALID			(~(dma_addr_t)0) -  #define UVC_NUM_REQUESTS			4  #define UVC_MAX_REQUEST_SIZE			64  #define UVC_MAX_EVENTS				4 @@ -190,6 +188,7 @@ struct uvc_file_handle   * Functions   */ +extern void uvc_function_setup_continue(struct uvc_device *uvc);  extern void uvc_endpoint_stream(struct uvc_device *dev);  extern void uvc_function_connect(struct uvc_device *uvc); diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c index 104ae9c8125..7ce27e35550 100644 --- a/drivers/usb/gadget/uvc_queue.c +++ b/drivers/usb/gadget/uvc_queue.c @@ -10,6 +10,7 @@   *	(at your option) any later version.   */ +#include <linux/atomic.h>  #include <linux/kernel.h>  #include <linux/mm.h>  #include <linux/list.h> @@ -18,7 +19,8 @@  #include <linux/videodev2.h>  #include <linux/vmalloc.h>  #include <linux/wait.h> -#include <linux/atomic.h> + +#include <media/videobuf2-vmalloc.h>  #include "uvc.h" @@ -28,330 +30,175 @@   * Video queues is initialized by uvc_queue_init(). The function performs   * basic initialization of the uvc_video_queue struct and never fails.   * - * Video buffer allocation and freeing are performed by uvc_alloc_buffers and - * uvc_free_buffers respectively. The former acquires the video queue lock, - * while the later must be called with the lock held (so that allocation can - * free previously allocated buffers). Trying to free buffers that are mapped - * to user space will return -EBUSY. - * - * Video buffers are managed using two queues. However, unlike most USB video - * drivers that use an in queue and an out queue, we use a main queue to hold - * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to - * hold empty buffers. This design (copied from video-buf) minimizes locking - * in interrupt, as only one queue is shared between interrupt and user - * contexts. - * - * Use cases - * --------- - * - * Unless stated otherwise, all operations that modify the irq buffers queue - * are protected by the irq spinlock. - * - * 1. The user queues the buffers, starts streaming and dequeues a buffer. - * - *    The buffers are added to the main and irq queues. Both operations are - *    protected by the queue lock, and the later is protected by the irq - *    spinlock as well. - * - *    The completion handler fetches a buffer from the irq queue and fills it - *    with video data. If no buffer is available (irq queue empty), the handler - *    returns immediately. - * - *    When the buffer is full, the completion handler removes it from the irq - *    queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue. - *    At that point, any process waiting on the buffer will be woken up. If a - *    process tries to dequeue a buffer after it has been marked ready, the - *    dequeing will succeed immediately. - * - * 2. Buffers are queued, user is waiting on a buffer and the device gets - *    disconnected. - * - *    When the device is disconnected, the kernel calls the completion handler - *    with an appropriate status code. The handler marks all buffers in the - *    irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so - *    that any process waiting on a buffer gets woken up. - * - *    Waking up up the first buffer on the irq list is not enough, as the - *    process waiting on the buffer might restart the dequeue operation - *    immediately. - * + * Video buffers are managed by videobuf2. The driver uses a mutex to protect + * the videobuf2 queue operations by serializing calls to videobuf2 and a + * spinlock to protect the IRQ queue that holds the buffers to be processed by + * the driver.   */ -static void -uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) -{ -	mutex_init(&queue->mutex); -	spin_lock_init(&queue->irqlock); -	INIT_LIST_HEAD(&queue->mainqueue); -	INIT_LIST_HEAD(&queue->irqqueue); -	queue->type = type; -} - -/* - * Free the video buffers. - * - * This function must be called with the queue lock held. +/* ----------------------------------------------------------------------------- + * videobuf2 queue operations   */ -static int uvc_free_buffers(struct uvc_video_queue *queue) + +static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, +			   unsigned int *nbuffers, unsigned int *nplanes, +			   unsigned int sizes[], void *alloc_ctxs[])  { -	unsigned int i; +	struct uvc_video_queue *queue = vb2_get_drv_priv(vq); +	struct uvc_video *video = container_of(queue, struct uvc_video, queue); -	for (i = 0; i < queue->count; ++i) { -		if (queue->buffer[i].vma_use_count != 0) -			return -EBUSY; -	} +	if (*nbuffers > UVC_MAX_VIDEO_BUFFERS) +		*nbuffers = UVC_MAX_VIDEO_BUFFERS; -	if (queue->count) { -		vfree(queue->mem); -		queue->count = 0; -	} +	*nplanes = 1; + +	sizes[0] = video->imagesize;  	return 0;  } -/* - * Allocate the video buffers. - * - * Pages are reserved to make sure they will not be swapped, as they will be - * filled in the URB completion handler. - * - * Buffers will be individually mapped, so they must all be page aligned. - */ -static int -uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, -		  unsigned int buflength) +static int uvc_buffer_prepare(struct vb2_buffer *vb)  { -	unsigned int bufsize = PAGE_ALIGN(buflength); -	unsigned int i; -	void *mem = NULL; -	int ret; +	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); +	struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf); -	if (nbuffers > UVC_MAX_VIDEO_BUFFERS) -		nbuffers = UVC_MAX_VIDEO_BUFFERS; +	if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT && +	    vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { +		uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n"); +		return -EINVAL; +	} -	mutex_lock(&queue->mutex); +	if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED)) +		return -ENODEV; -	if ((ret = uvc_free_buffers(queue)) < 0) -		goto done; +	buf->state = UVC_BUF_STATE_QUEUED; +	buf->mem = vb2_plane_vaddr(vb, 0); +	buf->length = vb2_plane_size(vb, 0); +	if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) +		buf->bytesused = 0; +	else +		buf->bytesused = vb2_get_plane_payload(vb, 0); -	/* Bail out if no buffers should be allocated. */ -	if (nbuffers == 0) -		goto done; +	return 0; +} -	/* Decrement the number of buffers until allocation succeeds. */ -	for (; nbuffers > 0; --nbuffers) { -		mem = vmalloc_32(nbuffers * bufsize); -		if (mem != NULL) -			break; -	} +static void uvc_buffer_queue(struct vb2_buffer *vb) +{ +	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); +	struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf); +	unsigned long flags; -	if (mem == NULL) { -		ret = -ENOMEM; -		goto done; -	} +	spin_lock_irqsave(&queue->irqlock, flags); -	for (i = 0; i < nbuffers; ++i) { -		memset(&queue->buffer[i], 0, sizeof queue->buffer[i]); -		queue->buffer[i].buf.index = i; -		queue->buffer[i].buf.m.offset = i * bufsize; -		queue->buffer[i].buf.length = buflength; -		queue->buffer[i].buf.type = queue->type; -		queue->buffer[i].buf.sequence = 0; -		queue->buffer[i].buf.field = V4L2_FIELD_NONE; -		queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP; -		queue->buffer[i].buf.flags = 0; -		init_waitqueue_head(&queue->buffer[i].wait); +	if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) { +		list_add_tail(&buf->queue, &queue->irqqueue); +	} else { +		/* If the device is disconnected return the buffer to userspace +		 * directly. The next QBUF call will fail with -ENODEV. +		 */ +		buf->state = UVC_BUF_STATE_ERROR; +		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);  	} -	queue->mem = mem; -	queue->count = nbuffers; -	queue->buf_size = bufsize; -	ret = nbuffers; - -done: -	mutex_unlock(&queue->mutex); -	return ret; +	spin_unlock_irqrestore(&queue->irqlock, flags);  } -static void __uvc_query_buffer(struct uvc_buffer *buf, -		struct v4l2_buffer *v4l2_buf) +static struct vb2_ops uvc_queue_qops = { +	.queue_setup = uvc_queue_setup, +	.buf_prepare = uvc_buffer_prepare, +	.buf_queue = uvc_buffer_queue, +}; + +static int uvc_queue_init(struct uvc_video_queue *queue, +			  enum v4l2_buf_type type)  { -	memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf); +	int ret; -	if (buf->vma_use_count) -		v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED; +	queue->queue.type = type; +	queue->queue.io_modes = VB2_MMAP | VB2_USERPTR; +	queue->queue.drv_priv = queue; +	queue->queue.buf_struct_size = sizeof(struct uvc_buffer); +	queue->queue.ops = &uvc_queue_qops; +	queue->queue.mem_ops = &vb2_vmalloc_memops; +	ret = vb2_queue_init(&queue->queue); +	if (ret) +		return ret; -	switch (buf->state) { -	case UVC_BUF_STATE_ERROR: -	case UVC_BUF_STATE_DONE: -		v4l2_buf->flags |= V4L2_BUF_FLAG_DONE; -		break; -	case UVC_BUF_STATE_QUEUED: -	case UVC_BUF_STATE_ACTIVE: -		v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED; -		break; -	case UVC_BUF_STATE_IDLE: -	default: -		break; -	} +	mutex_init(&queue->mutex); +	spin_lock_init(&queue->irqlock); +	INIT_LIST_HEAD(&queue->irqqueue); +	queue->flags = 0; + +	return 0;  } -static int -uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf) +/* + * Free the video buffers. + */ +static void uvc_free_buffers(struct uvc_video_queue *queue)  { -	int ret = 0; -  	mutex_lock(&queue->mutex); -	if (v4l2_buf->index >= queue->count) { -		ret = -EINVAL; -		goto done; -	} - -	__uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf); - -done: +	vb2_queue_release(&queue->queue);  	mutex_unlock(&queue->mutex); -	return ret;  }  /* - * Queue a video buffer. Attempting to queue a buffer that has already been - * queued will return -EINVAL. + * Allocate the video buffers.   */ -static int -uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf) +static int uvc_alloc_buffers(struct uvc_video_queue *queue, +			     struct v4l2_requestbuffers *rb)  { -	struct uvc_buffer *buf; -	unsigned long flags; -	int ret = 0; +	int ret; -	uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index); +	mutex_lock(&queue->mutex); +	ret = vb2_reqbufs(&queue->queue, rb); +	mutex_unlock(&queue->mutex); -	if (v4l2_buf->type != queue->type || -	    v4l2_buf->memory != V4L2_MEMORY_MMAP) { -		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " -			"and/or memory (%u).\n", v4l2_buf->type, -			v4l2_buf->memory); -		return -EINVAL; -	} +	return ret ? ret : rb->count; +} -	mutex_lock(&queue->mutex); -	if (v4l2_buf->index >= queue->count) { -		uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n"); -		ret = -EINVAL; -		goto done; -	} +static int uvc_query_buffer(struct uvc_video_queue *queue, +			    struct v4l2_buffer *buf) +{ +	int ret; -	buf = &queue->buffer[v4l2_buf->index]; -	if (buf->state != UVC_BUF_STATE_IDLE) { -		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state " -			"(%u).\n", buf->state); -		ret = -EINVAL; -		goto done; -	} +	mutex_lock(&queue->mutex); +	ret = vb2_querybuf(&queue->queue, buf); +	mutex_unlock(&queue->mutex); -	if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && -	    v4l2_buf->bytesused > buf->buf.length) { -		uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n"); -		ret = -EINVAL; -		goto done; -	} +	return ret; +} -	if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) -		buf->buf.bytesused = 0; -	else -		buf->buf.bytesused = v4l2_buf->bytesused; +static int uvc_queue_buffer(struct uvc_video_queue *queue, +			    struct v4l2_buffer *buf) +{ +	unsigned long flags; +	int ret; +	mutex_lock(&queue->mutex); +	ret = vb2_qbuf(&queue->queue, buf);  	spin_lock_irqsave(&queue->irqlock, flags); -	if (queue->flags & UVC_QUEUE_DISCONNECTED) { -		spin_unlock_irqrestore(&queue->irqlock, flags); -		ret = -ENODEV; -		goto done; -	} -	buf->state = UVC_BUF_STATE_QUEUED; -  	ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;  	queue->flags &= ~UVC_QUEUE_PAUSED; - -	list_add_tail(&buf->stream, &queue->mainqueue); -	list_add_tail(&buf->queue, &queue->irqqueue);  	spin_unlock_irqrestore(&queue->irqlock, flags); - -done:  	mutex_unlock(&queue->mutex); -	return ret; -} - -static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking) -{ -	if (nonblocking) { -		return (buf->state != UVC_BUF_STATE_QUEUED && -			buf->state != UVC_BUF_STATE_ACTIVE) -			? 0 : -EAGAIN; -	} -	return wait_event_interruptible(buf->wait, -		buf->state != UVC_BUF_STATE_QUEUED && -		buf->state != UVC_BUF_STATE_ACTIVE); +	return ret;  }  /*   * Dequeue a video buffer. If nonblocking is false, block until a buffer is   * available.   */ -static int -uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf, -		   int nonblocking) +static int uvc_dequeue_buffer(struct uvc_video_queue *queue, +			      struct v4l2_buffer *buf, int nonblocking)  { -	struct uvc_buffer *buf; -	int ret = 0; - -	if (v4l2_buf->type != queue->type || -	    v4l2_buf->memory != V4L2_MEMORY_MMAP) { -		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " -			"and/or memory (%u).\n", v4l2_buf->type, -			v4l2_buf->memory); -		return -EINVAL; -	} +	int ret;  	mutex_lock(&queue->mutex); -	if (list_empty(&queue->mainqueue)) { -		uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n"); -		ret = -EINVAL; -		goto done; -	} - -	buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream); -	if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0) -		goto done; - -	uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n", -		buf->buf.index, buf->state, buf->buf.bytesused); - -	switch (buf->state) { -	case UVC_BUF_STATE_ERROR: -		uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data " -			"(transmission error).\n"); -		ret = -EIO; -	case UVC_BUF_STATE_DONE: -		buf->state = UVC_BUF_STATE_IDLE; -		break; - -	case UVC_BUF_STATE_IDLE: -	case UVC_BUF_STATE_QUEUED: -	case UVC_BUF_STATE_ACTIVE: -	default: -		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u " -			"(driver bug?).\n", buf->state); -		ret = -EINVAL; -		goto done; -	} - -	list_del(&buf->stream); -	__uvc_query_buffer(buf, v4l2_buf); - -done: +	ret = vb2_dqbuf(&queue->queue, buf, nonblocking);  	mutex_unlock(&queue->mutex); +  	return ret;  } @@ -361,105 +208,47 @@ done:   * This function implements video queue polling and is intended to be used by   * the device poll handler.   */ -static unsigned int -uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, -	       poll_table *wait) +static unsigned int uvc_queue_poll(struct uvc_video_queue *queue, +				   struct file *file, poll_table *wait)  { -	struct uvc_buffer *buf; -	unsigned int mask = 0; +	unsigned int ret;  	mutex_lock(&queue->mutex); -	if (list_empty(&queue->mainqueue)) -		goto done; - -	buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream); - -	poll_wait(file, &buf->wait, wait); -	if (buf->state == UVC_BUF_STATE_DONE || -	    buf->state == UVC_BUF_STATE_ERROR) -		mask |= POLLOUT | POLLWRNORM; - -done: +	ret = vb2_poll(&queue->queue, file, wait);  	mutex_unlock(&queue->mutex); -	return mask; -} -/* - * VMA operations. - */ -static void uvc_vm_open(struct vm_area_struct *vma) -{ -	struct uvc_buffer *buffer = vma->vm_private_data; -	buffer->vma_use_count++; +	return ret;  } -static void uvc_vm_close(struct vm_area_struct *vma) +static int uvc_queue_mmap(struct uvc_video_queue *queue, +			  struct vm_area_struct *vma)  { -	struct uvc_buffer *buffer = vma->vm_private_data; -	buffer->vma_use_count--; -} +	int ret; -static struct vm_operations_struct uvc_vm_ops = { -	.open		= uvc_vm_open, -	.close		= uvc_vm_close, -}; +	mutex_lock(&queue->mutex); +	ret = vb2_mmap(&queue->queue, vma); +	mutex_unlock(&queue->mutex); +	return ret; +} + +#ifndef CONFIG_MMU  /* - * Memory-map a buffer. + * Get unmapped area.   * - * This function implements video buffer memory mapping and is intended to be - * used by the device mmap handler. + * NO-MMU arch need this function to make mmap() work correctly.   */ -static int -uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) +static unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, +		unsigned long pgoff)  { -	struct uvc_buffer *uninitialized_var(buffer); -	struct page *page; -	unsigned long addr, start, size; -	unsigned int i; -	int ret = 0; - -	start = vma->vm_start; -	size = vma->vm_end - vma->vm_start; +	unsigned long ret;  	mutex_lock(&queue->mutex); - -	for (i = 0; i < queue->count; ++i) { -		buffer = &queue->buffer[i]; -		if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) -			break; -	} - -	if (i == queue->count || size != queue->buf_size) { -		ret = -EINVAL; -		goto done; -	} - -	/* -	 * VM_IO marks the area as being an mmaped region for I/O to a -	 * device. It also prevents the region from being core dumped. -	 */ -	vma->vm_flags |= VM_IO; - -	addr = (unsigned long)queue->mem + buffer->buf.m.offset; -	while (size > 0) { -		page = vmalloc_to_page((void *)addr); -		if ((ret = vm_insert_page(vma, start, page)) < 0) -			goto done; - -		start += PAGE_SIZE; -		addr += PAGE_SIZE; -		size -= PAGE_SIZE; -	} - -	vma->vm_ops = &uvc_vm_ops; -	vma->vm_private_data = buffer; -	uvc_vm_open(vma); - -done: +	ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0);  	mutex_unlock(&queue->mutex);  	return ret;  } +#endif  /*   * Cancel the video buffers queue. @@ -484,7 +273,7 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)  				       queue);  		list_del(&buf->queue);  		buf->state = UVC_BUF_STATE_ERROR; -		wake_up(&buf->wait); +		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);  	}  	/* This must be protected by the irqlock spinlock to avoid race  	 * conditions between uvc_queue_buffer and the disconnection event that @@ -516,26 +305,33 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)   */  static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)  { -	unsigned int i; +	unsigned long flags;  	int ret = 0;  	mutex_lock(&queue->mutex);  	if (enable) { -		if (uvc_queue_streaming(queue)) { -			ret = -EBUSY; +		ret = vb2_streamon(&queue->queue, queue->queue.type); +		if (ret < 0)  			goto done; -		} +  		queue->sequence = 0; -		queue->flags |= UVC_QUEUE_STREAMING;  		queue->buf_used = 0;  	} else { -		uvc_queue_cancel(queue, 0); -		INIT_LIST_HEAD(&queue->mainqueue); +		ret = vb2_streamoff(&queue->queue, queue->queue.type); +		if (ret < 0) +			goto done; -		for (i = 0; i < queue->count; ++i) -			queue->buffer[i].state = UVC_BUF_STATE_IDLE; +		spin_lock_irqsave(&queue->irqlock, flags); +		INIT_LIST_HEAD(&queue->irqqueue); -		queue->flags &= ~UVC_QUEUE_STREAMING; +		/* +		 * FIXME: We need to clear the DISCONNECTED flag to ensure that +		 * applications will be able to queue buffers for the next +		 * streaming run. However, clearing it here doesn't guarantee +		 * that the device will be reconnected in the meantime. +		 */ +		queue->flags &= ~UVC_QUEUE_DISCONNECTED; +		spin_unlock_irqrestore(&queue->irqlock, flags);  	}  done: @@ -544,15 +340,15 @@ done:  }  /* called with &queue_irqlock held.. */ -static struct uvc_buffer * -uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) +static struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, +						struct uvc_buffer *buf)  {  	struct uvc_buffer *nextbuf;  	if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && -	    buf->buf.length != buf->buf.bytesused) { +	     buf->length != buf->bytesused) {  		buf->state = UVC_BUF_STATE_QUEUED; -		buf->buf.bytesused = 0; +		vb2_set_plane_payload(&buf->buf, 0, 0);  		return buf;  	} @@ -563,10 +359,18 @@ uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)  	else  		nextbuf = NULL; -	buf->buf.sequence = queue->sequence++; -	do_gettimeofday(&buf->buf.timestamp); +	/* +	 * FIXME: with videobuf2, the sequence number or timestamp fields +	 * are valid only for video capture devices and the UVC gadget usually +	 * is a video output device. Keeping these until the specs are clear on +	 * this aspect. +	 */ +	buf->buf.v4l2_buf.sequence = queue->sequence++; +	do_gettimeofday(&buf->buf.v4l2_buf.timestamp); + +	vb2_set_plane_payload(&buf->buf, 0, buf->bytesused); +	vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE); -	wake_up(&buf->wait);  	return nextbuf;  } diff --git a/drivers/usb/gadget/uvc_queue.h b/drivers/usb/gadget/uvc_queue.h index 1812a8ecc5d..8e76ce982f1 100644 --- a/drivers/usb/gadget/uvc_queue.h +++ b/drivers/usb/gadget/uvc_queue.h @@ -6,6 +6,7 @@  #include <linux/kernel.h>  #include <linux/poll.h>  #include <linux/videodev2.h> +#include <media/videobuf2-core.h>  /* Maximum frame size in bytes, for sanity checking. */  #define UVC_MAX_FRAME_SIZE	(16*1024*1024) @@ -25,42 +26,35 @@ enum uvc_buffer_state {  };  struct uvc_buffer { -	unsigned long vma_use_count; -	struct list_head stream; - -	/* Touched by interrupt handler. */ -	struct v4l2_buffer buf; +	struct vb2_buffer buf;  	struct list_head queue; -	wait_queue_head_t wait; +  	enum uvc_buffer_state state; +	void *mem; +	unsigned int length; +	unsigned int bytesused;  }; -#define UVC_QUEUE_STREAMING		(1 << 0) -#define UVC_QUEUE_DISCONNECTED		(1 << 1) -#define UVC_QUEUE_DROP_INCOMPLETE	(1 << 2) -#define UVC_QUEUE_PAUSED		(1 << 3) +#define UVC_QUEUE_DISCONNECTED		(1 << 0) +#define UVC_QUEUE_DROP_INCOMPLETE	(1 << 1) +#define UVC_QUEUE_PAUSED		(1 << 2)  struct uvc_video_queue { -	enum v4l2_buf_type type; +	struct vb2_queue queue; +	struct mutex mutex;	/* Protects queue */ -	void *mem;  	unsigned int flags;  	__u32 sequence; -	unsigned int count; -	unsigned int buf_size;  	unsigned int buf_used; -	struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS]; -	struct mutex mutex;	/* protects buffers and mainqueue */ -	spinlock_t irqlock;	/* protects irqqueue */ -	struct list_head mainqueue; +	spinlock_t irqlock;	/* Protects flags and irqqueue */  	struct list_head irqqueue;  };  static inline int uvc_queue_streaming(struct uvc_video_queue *queue)  { -	return queue->flags & UVC_QUEUE_STREAMING; +	return vb2_is_streaming(&queue->queue);  }  #endif /* __KERNEL__ */ diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c index 2ca9386d655..ad48e81155e 100644 --- a/drivers/usb/gadget/uvc_v4l2.c +++ b/drivers/usb/gadget/uvc_v4l2.c @@ -41,9 +41,8 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)  	req->length = min_t(unsigned int, uvc->event_length, data->length);  	req->zero = data->length < uvc->event_length; -	req->dma = DMA_ADDR_INVALID; -	memcpy(req->buf, data->data, data->length); +	memcpy(req->buf, data->data, req->length);  	return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);  } @@ -148,16 +147,13 @@ uvc_v4l2_release(struct file *file)  	uvc_function_disconnect(uvc);  	uvc_video_enable(video, 0); -	mutex_lock(&video->queue.mutex); -	if (uvc_free_buffers(&video->queue) < 0) -		printk(KERN_ERR "uvc_v4l2_release: Unable to free " -				"buffers.\n"); -	mutex_unlock(&video->queue.mutex); +	uvc_free_buffers(&video->queue);  	file->private_data = NULL;  	v4l2_fh_del(&handle->vfh);  	v4l2_fh_exit(&handle->vfh);  	kfree(handle); +  	return 0;  } @@ -178,9 +174,9 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  		struct v4l2_capability *cap = arg;  		memset(cap, 0, sizeof *cap); -		strncpy(cap->driver, "g_uvc", sizeof(cap->driver)); -		strncpy(cap->card, cdev->gadget->name, sizeof(cap->card)); -		strncpy(cap->bus_info, dev_name(&cdev->gadget->dev), +		strlcpy(cap->driver, "g_uvc", sizeof(cap->driver)); +		strlcpy(cap->card, cdev->gadget->name, sizeof(cap->card)); +		strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev),  			sizeof cap->bus_info);  		cap->version = DRIVER_VERSION_NUMBER;  		cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; @@ -192,7 +188,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  	{  		struct v4l2_format *fmt = arg; -		if (fmt->type != video->queue.type) +		if (fmt->type != video->queue.queue.type)  			return -EINVAL;  		return uvc_v4l2_get_format(video, fmt); @@ -202,7 +198,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  	{  		struct v4l2_format *fmt = arg; -		if (fmt->type != video->queue.type) +		if (fmt->type != video->queue.queue.type)  			return -EINVAL;  		return uvc_v4l2_set_format(video, fmt); @@ -213,16 +209,13 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  	{  		struct v4l2_requestbuffers *rb = arg; -		if (rb->type != video->queue.type || -		    rb->memory != V4L2_MEMORY_MMAP) +		if (rb->type != video->queue.queue.type)  			return -EINVAL; -		ret = uvc_alloc_buffers(&video->queue, rb->count, -					video->imagesize); +		ret = uvc_alloc_buffers(&video->queue, rb);  		if (ret < 0)  			return ret; -		rb->count = ret;  		ret = 0;  		break;  	} @@ -231,9 +224,6 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  	{  		struct v4l2_buffer *buf = arg; -		if (buf->type != video->queue.type) -			return -EINVAL; -  		return uvc_query_buffer(&video->queue, buf);  	} @@ -251,24 +241,36 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  	{  		int *type = arg; -		if (*type != video->queue.type) +		if (*type != video->queue.queue.type)  			return -EINVAL; -		return uvc_video_enable(video, 1); +		/* Enable UVC video. */ +		ret = uvc_video_enable(video, 1); +		if (ret < 0) +			return ret; + +		/* +		 * Complete the alternate setting selection setup phase now that +		 * userspace is ready to provide video frames. +		 */ +		uvc_function_setup_continue(uvc); +		uvc->state = UVC_STATE_STREAMING; + +		return 0;  	}  	case VIDIOC_STREAMOFF:  	{  		int *type = arg; -		if (*type != video->queue.type) +		if (*type != video->queue.queue.type)  			return -EINVAL;  		return uvc_video_enable(video, 0);  	}  	/* Events */ -        case VIDIOC_DQEVENT: +	case VIDIOC_DQEVENT:  	{  		struct v4l2_event *event = arg; @@ -333,17 +335,21 @@ uvc_v4l2_poll(struct file *file, poll_table *wait)  {  	struct video_device *vdev = video_devdata(file);  	struct uvc_device *uvc = video_get_drvdata(vdev); -	struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data); -	unsigned int mask = 0; -	poll_wait(file, &handle->vfh.wait, wait); -	if (v4l2_event_pending(&handle->vfh)) -		mask |= POLLPRI; +	return uvc_queue_poll(&uvc->video.queue, file, wait); +} -	mask |= uvc_queue_poll(&uvc->video.queue, file, wait); +#ifndef CONFIG_MMU +static unsigned long uvc_v4l2_get_unmapped_area(struct file *file, +		unsigned long addr, unsigned long len, unsigned long pgoff, +		unsigned long flags) +{ +	struct video_device *vdev = video_devdata(file); +	struct uvc_device *uvc = video_get_drvdata(vdev); -	return mask; +	return uvc_queue_get_unmapped_area(&uvc->video.queue, pgoff);  } +#endif  static struct v4l2_file_operations uvc_v4l2_fops = {  	.owner		= THIS_MODULE, @@ -352,5 +358,8 @@ static struct v4l2_file_operations uvc_v4l2_fops = {  	.ioctl		= uvc_v4l2_ioctl,  	.mmap		= uvc_v4l2_mmap,  	.poll		= uvc_v4l2_poll, +#ifndef CONFIG_MMU +	.get_unmapped_area = uvc_v4l2_get_unmapped_area, +#endif  }; diff --git a/drivers/usb/gadget/uvc_video.c b/drivers/usb/gadget/uvc_video.c index b0e53a8ea4f..71e896d4c5a 100644 --- a/drivers/usb/gadget/uvc_video.c +++ b/drivers/usb/gadget/uvc_video.c @@ -32,7 +32,7 @@ uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf,  	data[0] = 2;  	data[1] = UVC_STREAM_EOH | video->fid; -	if (buf->buf.bytesused - video->queue.buf_used <= len - 2) +	if (buf->bytesused - video->queue.buf_used <= len - 2)  		data[1] |= UVC_STREAM_EOF;  	return 2; @@ -47,8 +47,8 @@ uvc_video_encode_data(struct uvc_video *video, struct uvc_buffer *buf,  	void *mem;  	/* Copy video data to the USB buffer. */ -	mem = queue->mem + buf->buf.m.offset + queue->buf_used; -	nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used); +	mem = buf->mem + queue->buf_used; +	nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);  	memcpy(data, mem, nbytes);  	queue->buf_used += nbytes; @@ -82,7 +82,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,  	req->length = video->req_size - len;  	req->zero = video->payload_size == video->max_payload_size; -	if (buf->buf.bytesused == video->queue.buf_used) { +	if (buf->bytesused == video->queue.buf_used) {  		video->queue.buf_used = 0;  		buf->state = UVC_BUF_STATE_DONE;  		uvc_queue_next_buffer(&video->queue, buf); @@ -92,7 +92,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,  	}  	if (video->payload_size == video->max_payload_size || -	    buf->buf.bytesused == video->queue.buf_used) +	    buf->bytesused == video->queue.buf_used)  		video->payload_size = 0;  } @@ -115,7 +115,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,  	req->length = video->req_size - len; -	if (buf->buf.bytesused == video->queue.buf_used) { +	if (buf->bytesused == video->queue.buf_used) {  		video->queue.buf_used = 0;  		buf->state = UVC_BUF_STATE_DONE;  		uvc_queue_next_buffer(&video->queue, buf); @@ -161,6 +161,7 @@ static void  uvc_video_complete(struct usb_ep *ep, struct usb_request *req)  {  	struct uvc_video *video = req->context; +	struct uvc_video_queue *queue = &video->queue;  	struct uvc_buffer *buf;  	unsigned long flags;  	int ret; @@ -169,13 +170,15 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)  	case 0:  		break; -	case -ESHUTDOWN: +	case -ESHUTDOWN:	/* disconnect from host. */  		printk(KERN_INFO "VS request cancelled.\n"); +		uvc_queue_cancel(queue, 1);  		goto requeue;  	default:  		printk(KERN_INFO "VS request completed with status %d.\n",  			req->status); +		uvc_queue_cancel(queue, 0);  		goto requeue;  	} @@ -229,13 +232,18 @@ uvc_video_free_requests(struct uvc_video *video)  static int  uvc_video_alloc_requests(struct uvc_video *video)  { +	unsigned int req_size;  	unsigned int i;  	int ret = -ENOMEM;  	BUG_ON(video->req_size); +	req_size = video->ep->maxpacket +		 * max_t(unsigned int, video->ep->maxburst, 1) +		 * (video->ep->mult + 1); +  	for (i = 0; i < UVC_NUM_REQUESTS; ++i) { -		video->req_buffer[i] = kmalloc(video->ep->maxpacket, GFP_KERNEL); +		video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);  		if (video->req_buffer[i] == NULL)  			goto error; @@ -245,14 +253,14 @@ uvc_video_alloc_requests(struct uvc_video *video)  		video->req[i]->buf = video->req_buffer[i];  		video->req[i]->length = 0; -		video->req[i]->dma = DMA_ADDR_INVALID;  		video->req[i]->complete = uvc_video_complete;  		video->req[i]->context = video;  		list_add_tail(&video->req[i]->list, &video->req_free);  	} -	video->req_size = video->ep->maxpacket; +	video->req_size = req_size; +  	return 0;  error: @@ -309,7 +317,8 @@ uvc_video_pump(struct uvc_video *video)  		video->encode(req, video, buf);  		/* Queue the USB request */ -		if ((ret = usb_ep_queue(video->ep, req, GFP_KERNEL)) < 0) { +		ret = usb_ep_queue(video->ep, req, GFP_ATOMIC); +		if (ret < 0) {  			printk(KERN_INFO "Failed to queue request (%d)\n", ret);  			usb_ep_set_halt(video->ep);  			spin_unlock_irqrestore(&video->queue.irqlock, flags); diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 685fa681cb6..2cd6262e8b7 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -368,8 +368,10 @@ static int zero_unbind(struct usb_composite_dev *cdev)  	del_timer_sync(&autoresume_timer);  	if (!IS_ERR_OR_NULL(func_ss))  		usb_put_function(func_ss); +	usb_put_function_instance(func_inst_ss);  	if (!IS_ERR_OR_NULL(func_lb))  		usb_put_function(func_lb); +	usb_put_function_instance(func_inst_lb);  	return 0;  } diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index c59a1126926..de94f269906 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -2,11 +2,9 @@  # USB Host Controller Drivers  #  comment "USB Host Controller Drivers" -	depends on USB  config USB_C67X00_HCD  	tristate "Cypress C67x00 HCD support" -	depends on USB  	help  	  The Cypress C67x00 (EZ-Host/EZ-OTG) chips are dual-role  	  host/peripheral/OTG USB controllers. @@ -19,7 +17,7 @@ config USB_C67X00_HCD  config USB_XHCI_HCD  	tristate "xHCI HCD (USB 3.0) support" -	depends on USB && USB_ARCH_HAS_XHCI +	depends on USB_ARCH_HAS_XHCI  	---help---  	  The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0  	  "SuperSpeed" host controller hardware. @@ -27,13 +25,13 @@ config USB_XHCI_HCD  	  To compile this driver as a module, choose M here: the  	  module will be called xhci-hcd. +if USB_XHCI_HCD +  config USB_XHCI_PLATFORM  	tristate -	depends on USB_XHCI_HCD  config USB_XHCI_HCD_DEBUGGING  	bool "Debugging for the xHCI host controller" -	depends on USB_XHCI_HCD  	---help---  	  Say 'Y' to turn on debugging for the xHCI host controller driver.  	  This will spew debugging output, even in interrupt context. @@ -41,9 +39,11 @@ config USB_XHCI_HCD_DEBUGGING  	  If unsure, say N. +endif # USB_XHCI_HCD +  config USB_EHCI_HCD  	tristate "EHCI HCD (USB 2.0) support" -	depends on USB && USB_ARCH_HAS_EHCI +	depends on USB_ARCH_HAS_EHCI  	---help---  	  The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0  	  "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. @@ -95,14 +95,19 @@ config USB_EHCI_TT_NEWSCHED  	  If unsure, say Y. +config USB_FSL_MPH_DR_OF +	tristate + +if USB_EHCI_HCD +  config USB_EHCI_PCI  	tristate -	depends on USB_EHCI_HCD && PCI +	depends on PCI  	default y  config USB_EHCI_HCD_PMC_MSP  	tristate "EHCI support for on-chip PMC MSP71xx USB controller" -	depends on USB_EHCI_HCD && MSP_HAS_USB +	depends on MSP_HAS_USB  	default n  	select USB_EHCI_BIG_ENDIAN_DESC  	select USB_EHCI_BIG_ENDIAN_MMIO @@ -112,22 +117,13 @@ config USB_EHCI_HCD_PMC_MSP  config USB_EHCI_BIG_ENDIAN_MMIO  	bool -	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || \ -				    ARCH_IXP4XX || XPS_USB_HCD_XILINX || \ -				    PPC_MPC512x || CPU_CAVIUM_OCTEON || \ -				    PMC_MSP || SPARC_LEON || MIPS_SEAD3) -	default y  config USB_EHCI_BIG_ENDIAN_DESC  	bool -	depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \ -				    PPC_MPC512x || PMC_MSP || SPARC_LEON || \ -				    MIPS_SEAD3) -	default y  config XPS_USB_HCD_XILINX  	bool "Use Xilinx usb host EHCI controller core" -	depends on USB_EHCI_HCD && (PPC32 || MICROBLAZE) +	depends on (PPC32 || MICROBLAZE)  	select USB_EHCI_BIG_ENDIAN_DESC  	select USB_EHCI_BIG_ENDIAN_MMIO  	---help--- @@ -136,12 +132,9 @@ 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 PPC on-chip EHCI USB controller" -	depends on USB_EHCI_HCD && FSL_SOC +	depends on FSL_SOC  	select USB_EHCI_ROOT_HUB_TT  	select USB_FSL_MPH_DR_OF if OF  	---help--- @@ -149,22 +142,53 @@ config USB_EHCI_FSL  config USB_EHCI_MXC  	tristate "Support for Freescale i.MX on-chip EHCI USB controller" -	depends on USB_EHCI_HCD && ARCH_MXC +	depends on ARCH_MXC  	select USB_EHCI_ROOT_HUB_TT  	---help---  	  Variation of ARC USB block used in some Freescale chips.  config USB_EHCI_HCD_OMAP -	bool "EHCI support for OMAP3 and later chips" -	depends on USB_EHCI_HCD && ARCH_OMAP +	tristate "EHCI support for OMAP3 and later chips" +	depends on ARCH_OMAP  	default y  	---help---  	  Enables support for the on-chip EHCI controller on  	  OMAP3 and later chips. +	  If your system uses a PHY on the USB port, you will need to +	  enable USB_PHY and the appropriate PHY driver as well. Most +	  boards need the NOP_USB_XCEIV PHY driver. + +config USB_EHCI_HCD_ORION +	tristate  "Support for Marvell EBU on-chip EHCI USB controller" +	depends on USB_EHCI_HCD && PLAT_ORION +	default y +	---help--- +	  Enables support for the on-chip EHCI controller on Marvell's +	  embedded ARM SoCs, including Orion, Kirkwood, Dove, Armada XP, +	  Armada 370.  This is different from the EHCI implementation +	  on Marvell's mobile PXA and MMP SoC, see "EHCI support for +	  Marvell PXA/MMP USB controller" for those. + +config USB_EHCI_HCD_SPEAR +        tristate "Support for ST SPEAr on-chip EHCI USB controller" +        depends on USB_EHCI_HCD && PLAT_SPEAR +        default y +        ---help--- +          Enables support for the on-chip EHCI controller on +          ST SPEAr chips. + +config USB_EHCI_HCD_AT91 +        tristate  "Support for Atmel on-chip EHCI USB controller" +        depends on USB_EHCI_HCD && ARCH_AT91 +        default y +        ---help--- +          Enables support for the on-chip EHCI controller on +          Atmel chips.  config USB_EHCI_MSM -	bool "Support for MSM on-chip EHCI USB controller" -	depends on USB_EHCI_HCD && ARCH_MSM +	tristate "Support for Qualcomm QSD/MSM on-chip EHCI USB controller" +	depends on ARCH_MSM +	depends on USB_PHY  	select USB_EHCI_ROOT_HUB_TT  	select USB_MSM_OTG  	---help--- @@ -177,15 +201,16 @@ config USB_EHCI_MSM  config USB_EHCI_TEGRA         boolean "NVIDIA Tegra HCD support" -       depends on USB_EHCI_HCD && ARCH_TEGRA +       depends on ARCH_TEGRA         select USB_EHCI_ROOT_HUB_TT +       select USB_PHY         help           This driver enables support for the internal USB Host Controllers           found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.  config USB_EHCI_HCD_PPC_OF  	bool "EHCI support for PPC USB controller on OF platform bus" -	depends on USB_EHCI_HCD && PPC_OF +	depends on PPC_OF  	default y  	---help---  	  Enables support for the USB controller present on the PowerPC @@ -193,35 +218,40 @@ config USB_EHCI_HCD_PPC_OF  config USB_EHCI_SH  	bool "EHCI support for SuperH USB controller" -	depends on USB_EHCI_HCD && SUPERH +	depends on SUPERH  	---help---  	  Enables support for the on-chip EHCI controller on the SuperH.  	  If you use the PCI EHCI controller, this option is not necessary.  config USB_EHCI_S5P -       boolean "S5P EHCI support" -       depends on USB_EHCI_HCD && PLAT_S5P +       tristate "EHCI support for Samsung S5P/EXYNOS SoC Series" +       depends on PLAT_S5P         help -	 Enable support for the S5P SOC's on-chip EHCI controller. +	Enable support for the Samsung S5Pxxxx and Exynos3/4/5 SOC's +	on-chip EHCI controller.  config USB_EHCI_MV -	bool "EHCI support for Marvell on-chip controller" -	depends on USB_EHCI_HCD && (ARCH_PXA || ARCH_MMP) +	bool "EHCI support for Marvell PXA/MMP USB controller" +	depends on (ARCH_PXA || ARCH_MMP)  	select USB_EHCI_ROOT_HUB_TT  	---help---  	  Enables support for Marvell (including PXA and MMP series) on-chip  	  USB SPH and OTG controller. SPH is a single port host, and it can  	  only be EHCI host. OTG is controller that can switch to host mode. +	  Note that this driver will not work on Marvell's other EHCI +	  controller used by the EBU-type SoCs including Orion, Kirkwood, +	  Dova, Armada 370 and Armada XP. See "Support for Marvell EBU +	  on-chip EHCI USB controller" for those.  config USB_W90X900_EHCI  	bool "W90X900(W90P910) EHCI support" -	depends on USB_EHCI_HCD && ARCH_W90X900 +	depends on ARCH_W90X900  	---help---  		Enables support for the W90X900 USB controller  config USB_CNS3XXX_EHCI  	bool "Cavium CNS3XXX EHCI Module (DEPRECATED)" -	depends on USB_EHCI_HCD && ARCH_CNS3XXX +	depends on ARCH_CNS3XXX  	select USB_EHCI_HCD_PLATFORM  	---help---  	  This option is deprecated now and the driver was removed, use @@ -233,7 +263,7 @@ config USB_CNS3XXX_EHCI  config USB_EHCI_ATH79  	bool "EHCI support for AR7XXX/AR9XXX SoCs (DEPRECATED)" -	depends on USB_EHCI_HCD && (SOC_AR71XX || SOC_AR724X || SOC_AR913X || SOC_AR933X) +	depends on (SOC_AR71XX || SOC_AR724X || SOC_AR913X || SOC_AR933X)  	select USB_EHCI_ROOT_HUB_TT  	select USB_EHCI_HCD_PLATFORM  	default y @@ -244,9 +274,31 @@ config USB_EHCI_ATH79  	  Enables support for the built-in EHCI controller present  	  on the Atheros AR7XXX/AR9XXX SoCs. +config USB_EHCI_HCD_PLATFORM +	tristate "Generic EHCI driver for a platform device" +	default n +	---help--- +	  Adds an EHCI host driver for a generic platform device, which +	  provides a memory space and an irq. + +	  If unsure, say N. + +config USB_OCTEON_EHCI +	bool "Octeon on-chip EHCI support" +	depends on CPU_CAVIUM_OCTEON +	default n +	select USB_EHCI_BIG_ENDIAN_MMIO +	help +	  Enable support for the Octeon II SOC's on-chip EHCI +	  controller.  It is needed for high-speed (480Mbit/sec) +	  USB 2.0 device support.  All CN6XXX based chips with USB are +	  supported. + +endif # USB_EHCI_HCD +  config USB_OXU210HP_HCD  	tristate "OXU210HP HCD support" -	depends on USB && GENERIC_HARDIRQS +	depends on GENERIC_HARDIRQS  	---help---  	  The OXU210HP is an USB host/OTG/device controller. Enable this  	  option if your board has this chip. If unsure, say N. @@ -259,7 +311,6 @@ config USB_OXU210HP_HCD  config USB_ISP116X_HCD  	tristate "ISP116X HCD support" -	depends on USB  	---help---  	  The ISP1160 and ISP1161 chips are USB host controllers. Enable this  	  option if your board has this chip. If unsure, say N. @@ -271,7 +322,6 @@ config USB_ISP116X_HCD  config USB_ISP1760_HCD  	tristate "ISP 1760 HCD support" -	depends on USB  	---help---  	  The ISP1760 chip is a USB 2.0 host controller. @@ -286,7 +336,6 @@ config USB_ISP1760_HCD  config USB_ISP1362_HCD  	tristate "ISP1362 HCD support" -	depends on USB  	default N  	---help---  	  Supports the Philips ISP1362 chip as a host controller @@ -298,9 +347,8 @@ config USB_ISP1362_HCD  config USB_OHCI_HCD  	tristate "OHCI HCD support" -	depends on USB && USB_ARCH_HAS_OHCI +	depends on USB_ARCH_HAS_OHCI  	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 -	select USB_OTG_UTILS if ARCH_OMAP  	depends on USB_ISP1301 || !ARCH_LPC32XX  	---help---  	  The Open Host Controller Interface (OHCI) is a standard for accessing @@ -315,16 +363,18 @@ config USB_OHCI_HCD  	  To compile this driver as a module, choose M here: the  	  module will be called ohci-hcd. +if USB_OHCI_HCD +  config USB_OHCI_HCD_OMAP1  	bool "OHCI support for OMAP1/2 chips" -	depends on USB_OHCI_HCD && ARCH_OMAP1 +	depends on ARCH_OMAP1  	default y  	---help---  	  Enables support for the OHCI controller on OMAP1/2 chips.  config USB_OHCI_HCD_OMAP3  	bool "OHCI support for OMAP3 and later chips" -	depends on USB_OHCI_HCD && (ARCH_OMAP3 || ARCH_OMAP4) +	depends on (ARCH_OMAP3 || ARCH_OMAP4)  	default y  	---help---  	  Enables support for the on-chip OHCI controller on @@ -332,7 +382,7 @@ config USB_OHCI_HCD_OMAP3  config USB_OHCI_ATH79  	bool "USB OHCI support for the Atheros AR71XX/AR7240 SoCs (DEPRECATED)" -	depends on USB_OHCI_HCD && (SOC_AR71XX || SOC_AR724X) +	depends on (SOC_AR71XX || SOC_AR724X)  	select USB_OHCI_HCD_PLATFORM  	default y  	help @@ -344,7 +394,7 @@ config USB_OHCI_ATH79  config USB_OHCI_HCD_PPC_OF_BE  	bool "OHCI support for OF platform bus (big endian)" -	depends on USB_OHCI_HCD && PPC_OF +	depends on PPC_OF  	select USB_OHCI_BIG_ENDIAN_DESC  	select USB_OHCI_BIG_ENDIAN_MMIO  	---help--- @@ -353,7 +403,7 @@ config USB_OHCI_HCD_PPC_OF_BE  config USB_OHCI_HCD_PPC_OF_LE  	bool "OHCI support for OF platform bus (little endian)" -	depends on USB_OHCI_HCD && PPC_OF +	depends on PPC_OF  	select USB_OHCI_LITTLE_ENDIAN  	---help---  	  Enables support for little-endian USB controllers present on the @@ -361,12 +411,12 @@ config USB_OHCI_HCD_PPC_OF_LE  config USB_OHCI_HCD_PPC_OF  	bool -	depends on USB_OHCI_HCD && PPC_OF +	depends on PPC_OF  	default USB_OHCI_HCD_PPC_OF_BE || USB_OHCI_HCD_PPC_OF_LE  config USB_OHCI_HCD_PCI  	bool "OHCI support for PCI-bus USB controllers" -	depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF) +	depends on PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF)  	default y  	select USB_OHCI_LITTLE_ENDIAN  	---help--- @@ -375,7 +425,7 @@ config USB_OHCI_HCD_PCI  config USB_OHCI_HCD_SSB  	bool "OHCI support for Broadcom SSB OHCI core (DEPRECATED)" -	depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) +	depends on (SSB = y || SSB = USB_OHCI_HCD)  	select USB_HCD_SSB  	select USB_OHCI_HCD_PLATFORM  	default n @@ -393,7 +443,7 @@ config USB_OHCI_HCD_SSB  config USB_OHCI_SH  	bool "OHCI support for SuperH USB controller (DEPRECATED)" -	depends on USB_OHCI_HCD && SUPERH +	depends on SUPERH  	select USB_OHCI_HCD_PLATFORM  	---help---  	  This option is deprecated now and the driver was removed, use @@ -404,13 +454,13 @@ config USB_OHCI_SH  config USB_OHCI_EXYNOS  	boolean "OHCI support for Samsung EXYNOS SoC Series" -	depends on USB_OHCI_HCD && ARCH_EXYNOS +	depends on ARCH_EXYNOS  	help  	 Enable support for the Samsung Exynos SOC's on-chip OHCI controller.  config USB_CNS3XXX_OHCI  	bool "Cavium CNS3XXX OHCI Module (DEPRECATED)" -	depends on USB_OHCI_HCD && ARCH_CNS3XXX +	depends on ARCH_CNS3XXX  	select USB_OHCI_HCD_PLATFORM  	---help---  	  This option is deprecated now and the driver was removed, use @@ -421,7 +471,6 @@ config USB_CNS3XXX_OHCI  config USB_OHCI_HCD_PLATFORM  	bool "Generic OHCI driver for a platform device" -	depends on USB_OHCI_HCD  	default n  	---help---  	  Adds an OHCI host driver for a generic platform device, which @@ -429,35 +478,36 @@ config USB_OHCI_HCD_PLATFORM  	  If unsure, say N. -config USB_EHCI_HCD_PLATFORM -	tristate "Generic EHCI driver for a platform device" -	depends on USB_EHCI_HCD -	default n -	---help--- -	  Adds an EHCI host driver for a generic platform device, which -	  provides a memory space and an irq. +config USB_OCTEON_OHCI +	bool "Octeon on-chip OHCI support" +	depends on CPU_CAVIUM_OCTEON +	default USB_OCTEON_EHCI +	select USB_OHCI_BIG_ENDIAN_MMIO +	select USB_OHCI_LITTLE_ENDIAN +	help +	  Enable support for the Octeon II SOC's on-chip OHCI +	  controller.  It is needed for low-speed USB 1.0 device +	  support.  All CN6XXX based chips with USB are supported. -	  If unsure, say N.  config USB_OHCI_BIG_ENDIAN_DESC  	bool -	depends on USB_OHCI_HCD  	default n  config USB_OHCI_BIG_ENDIAN_MMIO  	bool -	depends on USB_OHCI_HCD  	default n  config USB_OHCI_LITTLE_ENDIAN  	bool -	depends on USB_OHCI_HCD  	default n if STB03xxx || PPC_MPC52xx  	default y +endif # USB_OHCI_HCD +  config USB_UHCI_HCD  	tristate "UHCI HCD (most Intel and VIA) support" -	depends on USB && (PCI || SPARC_LEON || ARCH_VT8500) +	depends on PCI || SPARC_LEON || ARCH_VT8500  	---help---  	  The Universal Host Controller Interface is a standard by Intel for  	  accessing the USB hardware in the PC (which is also called the USB @@ -497,7 +547,7 @@ config USB_UHCI_BIG_ENDIAN_DESC  config USB_FHCI_HCD  	tristate "Freescale QE USB Host Controller support" -	depends on USB && OF_GPIO && QE_GPIO && QUICC_ENGINE +	depends on OF_GPIO && QE_GPIO && QUICC_ENGINE  	select FSL_GTM  	select QE_USB  	help @@ -514,7 +564,7 @@ config FHCI_DEBUG  config USB_U132_HCD  	tristate "Elan U132 Adapter Host Controller" -	depends on USB && USB_FTDI_ELAN +	depends on USB_FTDI_ELAN  	default M  	help  	  The U132 adapter is a USB to CardBus adapter specifically designed @@ -542,7 +592,6 @@ config USB_U132_HCD  config USB_SL811_HCD  	tristate "SL811HS HCD support" -	depends on USB  	help  	  The SL811HS is a single-port USB controller that supports either  	  host side or peripheral side roles.  Enable this option if your @@ -574,7 +623,6 @@ config USB_SL811_CS  config USB_R8A66597_HCD  	tristate "R8A66597 HCD support" -	depends on USB  	help  	  The R8A66597 is a USB 2.0 host and peripheral controller. @@ -586,7 +634,6 @@ config USB_R8A66597_HCD  config USB_RENESAS_USBHS_HCD  	tristate "Renesas USBHS HCD support" -	depends on USB  	depends on USB_RENESAS_USBHS  	help  	  The Renesas USBHS is a USB 2.0 host and peripheral controller. @@ -611,7 +658,7 @@ config USB_WHCI_HCD  config USB_HWA_HCD  	tristate "Host Wire Adapter (HWA) driver" -	depends on USB && UWB +	depends on UWB  	select USB_WUSB  	select UWB_HWA  	help @@ -625,7 +672,7 @@ config USB_HWA_HCD  config USB_IMX21_HCD         tristate "i.MX21 HCD support" -       depends on USB && ARM && ARCH_MXC +       depends on ARM && ARCH_MXC         help           This driver enables support for the on-chip USB host in the           i.MX21 processor. @@ -633,27 +680,7 @@ config USB_IMX21_HCD           To compile this driver as a module, choose M here: the           module will be called "imx21-hcd". -config USB_OCTEON_EHCI -	bool "Octeon on-chip EHCI support" -	depends on USB && USB_EHCI_HCD && CPU_CAVIUM_OCTEON -	default n -	select USB_EHCI_BIG_ENDIAN_MMIO -	help -	  Enable support for the Octeon II SOC's on-chip EHCI -	  controller.  It is needed for high-speed (480Mbit/sec) -	  USB 2.0 device support.  All CN6XXX based chips with USB are -	  supported. -config USB_OCTEON_OHCI -	bool "Octeon on-chip OHCI support" -	depends on USB && USB_OHCI_HCD && CPU_CAVIUM_OCTEON -	default USB_OCTEON_EHCI -	select USB_OHCI_BIG_ENDIAN_MMIO -	select USB_OHCI_LITTLE_ENDIAN -	help -	  Enable support for the Octeon II SOC's on-chip OHCI -	  controller.  It is needed for low-speed USB 1.0 device -	  support.  All CN6XXX based chips with USB are supported.  config USB_OCTEON2_COMMON  	bool diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 001fbff2fde..4fb73c156d7 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -27,6 +27,12 @@ obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o  obj-$(CONFIG_USB_EHCI_PCI)	+= ehci-pci.o  obj-$(CONFIG_USB_EHCI_HCD_PLATFORM)	+= ehci-platform.o  obj-$(CONFIG_USB_EHCI_MXC)	+= ehci-mxc.o +obj-$(CONFIG_USB_EHCI_HCD_OMAP)	+= ehci-omap.o +obj-$(CONFIG_USB_EHCI_HCD_ORION)	+= ehci-orion.o +obj-$(CONFIG_USB_EHCI_HCD_SPEAR)	+= ehci-spear.o +obj-$(CONFIG_USB_EHCI_S5P)	+= ehci-s5p.o +obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o +obj-$(CONFIG_USB_EHCI_MSM)	+= ehci-msm.o  obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o  obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index f3beac4d06b..66420097c24 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -12,9 +12,22 @@   */  #include <linux/clk.h> -#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h>  #include <linux/of.h>  #include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> + +#include "ehci.h" + +#define DRIVER_DESC "EHCI Atmel driver" + +static const char hcd_name[] = "ehci-atmel"; +static struct hc_driver __read_mostly ehci_atmel_hc_driver;  /* interface and function clocks */  static struct clk *iclk, *fclk; @@ -50,51 +63,6 @@ static void atmel_stop_ehci(struct platform_device *pdev)  /*-------------------------------------------------------------------------*/ -static int ehci_atmel_setup(struct usb_hcd *hcd) -{ -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); - -	/* registers start at offset 0x0 */ -	ehci->caps = hcd->regs; - -	return ehci_setup(hcd); -} - -static const struct hc_driver ehci_atmel_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "Atmel EHCI UHP HS", -	.hcd_priv_size		= sizeof(struct ehci_hcd), - -	/* generic hardware linkage */ -	.irq			= ehci_irq, -	.flags			= HCD_MEMORY | HCD_USB2, - -	/* basic lifecycle operations */ -	.reset			= ehci_atmel_setup, -	.start			= ehci_run, -	.stop			= ehci_stop, -	.shutdown		= ehci_shutdown, - -	/* managing i/o requests and associated device resources */ -	.urb_enqueue		= ehci_urb_enqueue, -	.urb_dequeue		= ehci_urb_dequeue, -	.endpoint_disable	= ehci_endpoint_disable, -	.endpoint_reset		= ehci_endpoint_reset, - -	/* scheduling support */ -	.get_frame_number	= ehci_get_frame, - -	/* root hub support */ -	.hub_status_data	= ehci_hub_status_data, -	.hub_control		= ehci_hub_control, -	.bus_suspend		= ehci_bus_suspend, -	.bus_resume		= ehci_bus_resume, -	.relinquish_port	= ehci_relinquish_port, -	.port_handed_over	= ehci_port_handed_over, - -	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete, -}; -  static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);  static int ehci_atmel_drv_probe(struct platform_device *pdev) @@ -102,6 +70,7 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev)  	struct usb_hcd *hcd;  	const struct hc_driver *driver = &ehci_atmel_hc_driver;  	struct resource *res; +	struct ehci_hcd *ehci;  	int irq;  	int retval; @@ -162,6 +131,10 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev)  		goto fail_request_resource;  	} +	ehci = hcd_to_ehci(hcd); +	/* registers start at offset 0x0 */ +	ehci->caps = hcd->regs; +  	atmel_start_ehci(pdev);  	retval = usb_add_hcd(hcd, irq, IRQF_SHARED); @@ -185,7 +158,6 @@ static int ehci_atmel_drv_remove(struct platform_device *pdev)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev); -	ehci_shutdown(hcd);  	usb_remove_hcd(hcd);  	usb_put_hcd(hcd); @@ -213,3 +185,25 @@ static struct platform_driver ehci_atmel_driver = {  		.of_match_table	= of_match_ptr(atmel_ehci_dt_ids),  	},  }; + +static int __init ehci_atmel_init(void) +{ +	if (usb_disabled()) +		return -ENODEV; + +	pr_info("%s: " DRIVER_DESC "\n", hcd_name); +	ehci_init_driver(&ehci_atmel_hc_driver, NULL); +	return platform_driver_register(&ehci_atmel_driver); +} +module_init(ehci_atmel_init); + +static void __exit ehci_atmel_cleanup(void) +{ +	platform_driver_unregister(&ehci_atmel_driver); +} +module_exit(ehci_atmel_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_ALIAS("platform:atmel-ehci"); +MODULE_AUTHOR("Nicolas Ferre"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 70b496dc18a..5429d2645bb 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -510,14 +510,16 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)  	spin_lock_irqsave (&ehci->lock, flags);  	for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh)  		qh_lines (ehci, qh, &next, &size); -	if (ehci->async_unlink && size > 0) { +	if (!list_empty(&ehci->async_unlink) && size > 0) {  		temp = scnprintf(next, size, "\nunlink =\n");  		size -= temp;  		next += temp; -		for (qh = ehci->async_unlink; size > 0 && qh; -				qh = qh->unlink_next) -			qh_lines (ehci, qh, &next, &size); +		list_for_each_entry(qh, &ehci->async_unlink, unlink_node) { +			if (size <= 0) +				break; +			qh_lines(ehci, qh, &next, &size); +		}  	}  	spin_unlock_irqrestore (&ehci->lock, flags); @@ -814,9 +816,10 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)  		}  	} -	if (ehci->async_unlink) { +	if (!list_empty(&ehci->async_unlink)) {  		temp = scnprintf(next, size, "async unlink qh %p\n", -				ehci->async_unlink); +				list_first_entry(&ehci->async_unlink, +						struct ehci_qh, unlink_node));  		size -= temp;  		next += temp;  	} diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index d81d2fcbff1..3be3df233a0 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -370,6 +370,15 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)  	/* EHCI registers start at offset 0x100 */  	ehci->caps = hcd->regs + 0x100; +#ifdef CONFIG_PPC_83xx +	/* +	 * Deal with MPC834X that need port power to be cycled after the power +	 * fault condition is removed. Otherwise the state machine does not +	 * reflect PORTSC[CSC] correctly. +	 */ +	ehci->need_oc_pp_cycle = 1; +#endif +  	hcd->has_tt = 1;  	retval = ehci_setup(hcd); diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 5726cb144ab..312fc10da3c 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -302,6 +302,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)  static void end_unlink_async(struct ehci_hcd *ehci);  static void unlink_empty_async(struct ehci_hcd *ehci); +static void unlink_empty_async_suspended(struct ehci_hcd *ehci);  static void ehci_work(struct ehci_hcd *ehci);  static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);  static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); @@ -481,6 +482,9 @@ static int ehci_init(struct usb_hcd *hcd)  	 * periodic_size can shrink by USBCMD update if hcc_params allows.  	 */  	ehci->periodic_size = DEFAULT_I_TDPS; +	INIT_LIST_HEAD(&ehci->async_unlink); +	INIT_LIST_HEAD(&ehci->async_idle); +	INIT_LIST_HEAD(&ehci->intr_unlink);  	INIT_LIST_HEAD(&ehci->intr_qh_list);  	INIT_LIST_HEAD(&ehci->cached_itd_list);  	INIT_LIST_HEAD(&ehci->cached_sitd_list); @@ -669,9 +673,6 @@ int ehci_setup(struct usb_hcd *hcd)  	if (retval)  		return retval; -	if (ehci_is_TDI(ehci)) -		tdi_reset(ehci); -  	ehci_reset(ehci);  	return 0; @@ -748,7 +749,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  		/* guard against (alleged) silicon errata */  		if (cmd & CMD_IAAD)  			ehci_dbg(ehci, "IAA with IAAD still set?\n"); -		if (ehci->async_iaa) +		if (ehci->iaa_in_progress)  			COUNT(ehci->stats.iaa);  		end_unlink_async(ehci);  	} @@ -756,7 +757,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  	/* remote wakeup [4.3.1] */  	if (status & STS_PCD) {  		unsigned	i = HCS_N_PORTS (ehci->hcs_params); -		u32		ppcd = 0; +		u32		ppcd = ~0;  		/* kick root hub later */  		pcd_status = status; @@ -773,7 +774,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  			int pstatus;  			/* leverage per-port change bits feature */ -			if (ehci->has_ppcd && !(ppcd & (1 << i))) +			if (!(ppcd & (1 << i)))  				continue;  			pstatus = ehci_readl(ehci,  					 &ehci->regs->port_status[i]); @@ -895,17 +896,24 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)  	if (rc)  		goto done; -	switch (usb_pipetype (urb->pipe)) { -	// case PIPE_CONTROL: -	// case PIPE_BULK: -	default: +	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { +		/* +		 * We don't expedite dequeue for isochronous URBs. +		 * Just wait until they complete normally or their +		 * time slot expires. +		 */ +	} else {  		qh = (struct ehci_qh *) urb->hcpriv; -		if (!qh) -			break; +		qh->exception = 1;  		switch (qh->qh_state) {  		case QH_STATE_LINKED: +			if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) +				start_unlink_intr(ehci, qh); +			else +				start_unlink_async(ehci, qh); +			break;  		case QH_STATE_COMPLETING: -			start_unlink_async(ehci, qh); +			qh->dequeue_during_giveback = 1;  			break;  		case QH_STATE_UNLINK:  		case QH_STATE_UNLINK_WAIT: @@ -916,33 +924,6 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)  			qh_completions(ehci, qh);  			break;  		} -		break; - -	case PIPE_INTERRUPT: -		qh = (struct ehci_qh *) urb->hcpriv; -		if (!qh) -			break; -		switch (qh->qh_state) { -		case QH_STATE_LINKED: -		case QH_STATE_COMPLETING: -			start_unlink_intr(ehci, qh); -			break; -		case QH_STATE_IDLE: -			qh_completions (ehci, qh); -			break; -		default: -			ehci_dbg (ehci, "bogus qh %p state %d\n", -					qh, qh->qh_state); -			goto done; -		} -		break; - -	case PIPE_ISOCHRONOUS: -		// itd or sitd ... - -		// wait till next completion, do it then. -		// completion irqs can wait up to 1024 msec, -		break;  	}  done:  	spin_unlock_irqrestore (&ehci->lock, flags); @@ -983,6 +964,7 @@ rescan:  		goto done;  	} +	qh->exception = 1;  	if (ehci->rh_state < EHCI_RH_RUNNING)  		qh->qh_state = QH_STATE_IDLE;  	switch (qh->qh_state) { @@ -1051,13 +1033,12 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)  		usb_settoggle(qh->dev, epnum, is_out, 0);  		if (!list_empty(&qh->qtd_list)) {  			WARN_ONCE(1, "clear_halt for a busy endpoint\n"); -		} else if (qh->qh_state == QH_STATE_LINKED || -				qh->qh_state == QH_STATE_COMPLETING) { - +		} else {  			/* The toggle value in the QH can't be updated  			 * while the QH is active.  Unlink it now;  			 * re-linking will call qh_refresh().  			 */ +			qh->exception = 1;  			if (eptype == USB_ENDPOINT_XFER_BULK)  				start_unlink_async(ehci, qh);  			else @@ -1250,11 +1231,6 @@ MODULE_LICENSE ("GPL");  #define PLATFORM_DRIVER		ehci_hcd_sh_driver  #endif -#ifdef CONFIG_USB_EHCI_HCD_OMAP -#include "ehci-omap.c" -#define        PLATFORM_DRIVER         ehci_hcd_omap_driver -#endif -  #ifdef CONFIG_PPC_PS3  #include "ehci-ps3.c"  #define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_driver @@ -1270,41 +1246,16 @@ MODULE_LICENSE ("GPL");  #define XILINX_OF_PLATFORM_DRIVER	ehci_hcd_xilinx_of_driver  #endif -#ifdef CONFIG_PLAT_ORION -#include "ehci-orion.c" -#define	PLATFORM_DRIVER		ehci_orion_driver -#endif -  #ifdef CONFIG_USB_W90X900_EHCI  #include "ehci-w90x900.c"  #define	PLATFORM_DRIVER		ehci_hcd_w90x900_driver  #endif -#ifdef CONFIG_ARCH_AT91 -#include "ehci-atmel.c" -#define	PLATFORM_DRIVER		ehci_atmel_driver -#endif -  #ifdef CONFIG_USB_OCTEON_EHCI  #include "ehci-octeon.c"  #define PLATFORM_DRIVER		ehci_octeon_driver  #endif -#ifdef CONFIG_ARCH_VT8500 -#include "ehci-vt8500.c" -#define	PLATFORM_DRIVER		vt8500_ehci_driver -#endif - -#ifdef CONFIG_PLAT_SPEAR -#include "ehci-spear.c" -#define PLATFORM_DRIVER		spear_ehci_hcd_driver -#endif - -#ifdef CONFIG_USB_EHCI_MSM -#include "ehci-msm.c" -#define PLATFORM_DRIVER		ehci_msm_driver -#endif -  #ifdef CONFIG_TILE_USB  #include "ehci-tilegx.c"  #define	PLATFORM_DRIVER		ehci_hcd_tilegx_driver @@ -1320,11 +1271,6 @@ MODULE_LICENSE ("GPL");  #define PLATFORM_DRIVER		tegra_ehci_driver  #endif -#ifdef CONFIG_USB_EHCI_S5P -#include "ehci-s5p.c" -#define PLATFORM_DRIVER		s5p_ehci_driver -#endif -  #ifdef CONFIG_SPARC_LEON  #include "ehci-grlib.c"  #define PLATFORM_DRIVER		ehci_grlib_driver @@ -1344,6 +1290,12 @@ MODULE_LICENSE ("GPL");  	!IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \  	!IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \  	!IS_ENABLED(CONFIG_USB_EHCI_MXC) && \ +	!IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \ +	!IS_ENABLED(CONFIG_USB_EHCI_HCD_ORION) && \ +	!IS_ENABLED(CONFIG_USB_EHCI_HCD_SPEAR) && \ +	!IS_ENABLED(CONFIG_USB_EHCI_S5P) && \ +	!IS_ENABLED(CONFIG_USB_EHCI_HCD_AT91) && \ +	!IS_ENABLED(CONFIG_USB_EHCI_MSM) && \  	!defined(PLATFORM_DRIVER) && \  	!defined(PS3_SYSTEM_BUS_DRIVER) && \  	!defined(OF_PLATFORM_DRIVER) && \ diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 4d3b294f203..9ab4a4d9768 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -328,7 +328,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)  	ehci->rh_state = EHCI_RH_SUSPENDED;  	end_unlink_async(ehci); -	unlink_empty_async(ehci); +	unlink_empty_async_suspended(ehci);  	ehci_handle_intr_unlinks(ehci);  	end_free_itds(ehci); @@ -464,7 +464,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)  	while (i--) {  		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);  		if (test_bit(i, &resume_needed)) { -			temp &= ~(PORT_RWC_BITS | PORT_RESUME); +			temp &= ~(PORT_RWC_BITS | PORT_SUSPEND | PORT_RESUME);  			ehci_writel(ehci, temp, &ehci->regs->port_status [i]);  			ehci_vdbg (ehci, "resumed port %d\n", i + 1);  		} @@ -590,7 +590,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)  	u32		mask;  	int		ports, i, retval = 1;  	unsigned long	flags; -	u32		ppcd = 0; +	u32		ppcd = ~0;  	/* init status to no-changes */  	buf [0] = 0; @@ -628,9 +628,10 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)  	for (i = 0; i < ports; i++) {  		/* leverage per-port change bits feature */ -		if (ehci->has_ppcd && !(ppcd & (1 << i))) -			continue; -		temp = ehci_readl(ehci, &ehci->regs->port_status [i]); +		if (ppcd & (1 << i)) +			temp = ehci_readl(ehci, &ehci->regs->port_status[i]); +		else +			temp = 0;  		/*  		 * Return status information even for ports with OWNER set. @@ -839,7 +840,8 @@ static int ehci_hub_control (  			 * power switching; they're allowed to just limit the  			 * current.  khubd will turn the power back on.  			 */ -			if ((temp & PORT_OC) && HCS_PPC(ehci->hcs_params)) { +			if (((temp & PORT_OC) || (ehci->need_oc_pp_cycle)) +					&& HCS_PPC(ehci->hcs_params)) {  				ehci_writel(ehci,  					temp & ~(PORT_RWC_BITS | PORT_POWER),  					status_reg); @@ -870,10 +872,9 @@ static int ehci_hub_control (  				usb_hcd_end_port_resume(&hcd->self, wIndex);  				/* stop resume signaling */ -				temp = ehci_readl(ehci, status_reg); -				ehci_writel(ehci, -					temp & ~(PORT_RWC_BITS | PORT_RESUME), -					status_reg); +				temp &= ~(PORT_RWC_BITS | +						PORT_SUSPEND | PORT_RESUME); +				ehci_writel(ehci, temp, status_reg);  				clear_bit(wIndex, &ehci->resuming_ports);  				retval = handshake(ehci, status_reg,  					   PORT_RESUME, 0, 2000 /* 2msec */); @@ -883,7 +884,7 @@ static int ehci_hub_control (  						wIndex + 1, retval);  					goto error;  				} -				temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); +				temp = ehci_readl(ehci, status_reg);  			}  		} diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 88a49c87e74..0f717dc688b 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -22,16 +22,26 @@   * along with this program; if not, you can find it at http://www.fsf.org   */ -#include <linux/platform_device.h>  #include <linux/clk.h>  #include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h>  #include <linux/pm_runtime.h> -  #include <linux/usb/otg.h>  #include <linux/usb/msm_hsusb_hw.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> + +#include "ehci.h"  #define MSM_USB_BASE (hcd->regs) +#define DRIVER_DESC "Qualcomm On-Chip EHCI Host Controller" + +static const char hcd_name[] = "ehci-msm"; +static struct hc_driver __read_mostly msm_hc_driver;  static struct usb_phy *phy;  static int ehci_msm_reset(struct usb_hcd *hcd) @@ -56,52 +66,6 @@ static int ehci_msm_reset(struct usb_hcd *hcd)  	return 0;  } -static struct hc_driver msm_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "Qualcomm On-Chip EHCI Host Controller", -	.hcd_priv_size		= sizeof(struct ehci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq			= ehci_irq, -	.flags			= HCD_USB2 | HCD_MEMORY, - -	.reset			= ehci_msm_reset, -	.start			= ehci_run, - -	.stop			= ehci_stop, -	.shutdown		= ehci_shutdown, - -	/* -	 * managing i/o requests and associated device resources -	 */ -	.urb_enqueue		= ehci_urb_enqueue, -	.urb_dequeue		= ehci_urb_dequeue, -	.endpoint_disable	= ehci_endpoint_disable, -	.endpoint_reset		= ehci_endpoint_reset, -	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, - -	/* -	 * scheduling support -	 */ -	.get_frame_number	= ehci_get_frame, - -	/* -	 * root hub support -	 */ -	.hub_status_data	= ehci_hub_status_data, -	.hub_control		= ehci_hub_control, -	.relinquish_port	= ehci_relinquish_port, -	.port_handed_over	= ehci_port_handed_over, - -	/* -	 * PM support -	 */ -	.bus_suspend		= ehci_bus_suspend, -	.bus_resume		= ehci_bus_resume, -}; -  static int ehci_msm_probe(struct platform_device *pdev)  {  	struct usb_hcd *hcd; @@ -145,7 +109,7 @@ static int ehci_msm_probe(struct platform_device *pdev)  	 * management.  	 */  	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); -	if (IS_ERR_OR_NULL(phy)) { +	if (IS_ERR(phy)) {  		dev_err(&pdev->dev, "unable to find transceiver\n");  		ret = -ENODEV;  		goto put_hcd; @@ -165,6 +129,8 @@ static int ehci_msm_probe(struct platform_device *pdev)  	pm_runtime_no_callbacks(&pdev->dev);  	pm_runtime_enable(&pdev->dev); +	/* FIXME: need to call usb_add_hcd() here? */ +  	return 0;  put_hcd: @@ -183,6 +149,8 @@ static int ehci_msm_remove(struct platform_device *pdev)  	otg_set_host(phy->otg, NULL); +	/* FIXME: need to call usb_remove_hcd() here? */ +  	usb_put_hcd(hcd);  	return 0; @@ -226,3 +194,28 @@ static struct platform_driver ehci_msm_driver = {  		   .pm = &ehci_msm_dev_pm_ops,  	},  }; + +static const struct ehci_driver_overrides msm_overrides __initdata = { +	.reset = ehci_msm_reset, +}; + +static int __init ehci_msm_init(void) +{ +	if (usb_disabled()) +		return -ENODEV; + +	pr_info("%s: " DRIVER_DESC "\n", hcd_name); +	ehci_init_driver(&msm_hc_driver, &msm_overrides); +	return platform_driver_register(&ehci_msm_driver); +} +module_init(ehci_msm_init); + +static void __exit ehci_msm_cleanup(void) +{ +	platform_driver_unregister(&ehci_msm_driver); +} +module_exit(ehci_msm_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_ALIAS("platform:msm-ehci"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 3065809546b..402062973f0 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -33,25 +33,17 @@ struct ehci_hcd_mv {  	struct mv_usb_platform_data *pdata; -	/* clock source and total clock number */ -	unsigned int clknum; -	struct clk *clk[0]; +	struct clk *clk;  };  static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)  { -	unsigned int i; - -	for (i = 0; i < ehci_mv->clknum; i++) -		clk_prepare_enable(ehci_mv->clk[i]); +	clk_prepare_enable(ehci_mv->clk);  }  static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)  { -	unsigned int i; - -	for (i = 0; i < ehci_mv->clknum; i++) -		clk_disable_unprepare(ehci_mv->clk[i]); +	clk_disable_unprepare(ehci_mv->clk);  }  static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv) @@ -144,9 +136,8 @@ static int mv_ehci_probe(struct platform_device *pdev)  	struct ehci_hcd *ehci;  	struct ehci_hcd_mv *ehci_mv;  	struct resource *r; -	int clk_i, retval = -ENODEV; +	int retval = -ENODEV;  	u32 offset; -	size_t size;  	if (!pdata) {  		dev_err(&pdev->dev, "missing platform_data\n"); @@ -160,8 +151,7 @@ static int mv_ehci_probe(struct platform_device *pdev)  	if (!hcd)  		return -ENOMEM; -	size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum; -	ehci_mv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); +	ehci_mv = devm_kzalloc(&pdev->dev, sizeof(*ehci_mv), GFP_KERNEL);  	if (ehci_mv == NULL) {  		dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n");  		retval = -ENOMEM; @@ -172,16 +162,11 @@ static int mv_ehci_probe(struct platform_device *pdev)  	ehci_mv->pdata = pdata;  	ehci_mv->hcd = hcd; -	ehci_mv->clknum = pdata->clknum; -	for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) { -		ehci_mv->clk[clk_i] = -		    devm_clk_get(&pdev->dev, pdata->clkname[clk_i]); -		if (IS_ERR(ehci_mv->clk[clk_i])) { -			dev_err(&pdev->dev, "error get clck \"%s\"\n", -				pdata->clkname[clk_i]); -			retval = PTR_ERR(ehci_mv->clk[clk_i]); -			goto err_clear_drvdata; -		} +	ehci_mv->clk = devm_clk_get(&pdev->dev, NULL); +	if (IS_ERR(ehci_mv->clk)) { +		dev_err(&pdev->dev, "error getting clock\n"); +		retval = PTR_ERR(ehci_mv->clk); +		goto err_clear_drvdata;  	}  	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs"); @@ -225,7 +210,7 @@ static int mv_ehci_probe(struct platform_device *pdev)  		(void __iomem *) ((unsigned long) ehci_mv->cap_regs + offset);  	hcd->rsrc_start = r->start; -	hcd->rsrc_len = r->end - r->start + 1; +	hcd->rsrc_len = resource_size(r);  	hcd->regs = ehci_mv->op_regs;  	hcd->irq = platform_get_irq(pdev, 0); @@ -240,12 +225,16 @@ static int mv_ehci_probe(struct platform_device *pdev)  	ehci_mv->mode = pdata->mode;  	if (ehci_mv->mode == MV_USB_MODE_OTG) { -#ifdef CONFIG_USB_OTG_UTILS  		ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); -		if (IS_ERR_OR_NULL(ehci_mv->otg)) { -			dev_err(&pdev->dev, -				"unable to find transceiver\n"); -			retval = -ENODEV; +		if (IS_ERR(ehci_mv->otg)) { +			retval = PTR_ERR(ehci_mv->otg); + +			if (retval == -ENXIO) +				dev_info(&pdev->dev, "MV_USB_MODE_OTG " +						"must have CONFIG_USB_PHY enabled\n"); +			else +				dev_err(&pdev->dev, +						"unable to find transceiver\n");  			goto err_disable_clk;  		} @@ -258,11 +247,6 @@ static int mv_ehci_probe(struct platform_device *pdev)  		}  		/* otg will enable clock before use as host */  		mv_ehci_disable(ehci_mv); -#else -		dev_info(&pdev->dev, "MV_USB_MODE_OTG " -			 "must have CONFIG_USB_OTG_UTILS enabled\n"); -		goto err_disable_clk; -#endif  	} else {  		if (pdata->set_vbus)  			pdata->set_vbus(1); diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index e9301fb97ea..c369767b00e 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -28,11 +28,7 @@  #include <linux/slab.h>  #include <linux/usb.h>  #include <linux/usb/hcd.h> -  #include <linux/platform_data/usb-ehci-mxc.h> - -#include <asm/mach-types.h> -  #include "ehci.h"  #define DRIVER_DESC "Freescale On-Chip EHCI Host driver" @@ -47,7 +43,7 @@ struct ehci_mxc_priv {  static struct hc_driver __read_mostly ehci_mxc_hc_driver; -static const struct ehci_driver_overrides ehci_mxc_overrides __initdata = { +static const struct ehci_driver_overrides ehci_mxc_overrides __initconst = {  	.extra_priv_size =	sizeof(struct ehci_mxc_priv),  }; @@ -61,8 +57,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)  	struct device *dev = &pdev->dev;  	struct ehci_hcd *ehci; -	dev_info(&pdev->dev, "initializing i.MX USB Controller\n"); -  	if (!pdata) {  		dev_err(dev, "No platform data given, bailing out.\n");  		return -EINVAL; @@ -178,7 +172,7 @@ err_alloc:  	return ret;  } -static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) +static int ehci_mxc_drv_remove(struct platform_device *pdev)  {  	struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;  	struct usb_hcd *hcd = platform_get_drvdata(pdev); diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 0555ee42d7c..3d1491b5f36 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -4,10 +4,11 @@   * Bus Glue for the EHCI controllers in OMAP3/4   * Tested on several OMAP3 boards, and OMAP4 Pandaboard   * - * Copyright (C) 2007-2011 Texas Instruments, Inc. + * Copyright (C) 2007-2013 Texas Instruments, Inc.   *	Author: Vikram Pandita <vikram.pandita@ti.com>   *	Author: Anand Gadiyar <gadiyar@ti.com>   *	Author: Keshava Munegowda <keshava_mgowda@ti.com> + *	Author: Roger Quadros <rogerq@ti.com>   *   * Copyright (C) 2009 Nokia Corporation   *	Contact: Felipe Balbi <felipe.balbi@nokia.com> @@ -28,21 +29,23 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA   * - * TODO (last updated Feb 27, 2010): - *	- add kernel-doc - *	- enable AUTOIDLE - *	- add suspend/resume - *	- add HSIC and TLL support - *	- convert to use hwmod and runtime PM   */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/io.h>  #include <linux/platform_device.h>  #include <linux/slab.h>  #include <linux/usb/ulpi.h> -#include <linux/regulator/consumer.h>  #include <linux/pm_runtime.h>  #include <linux/gpio.h>  #include <linux/clk.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> +#include <linux/of.h> +#include <linux/dma-mapping.h> + +#include "ehci.h"  #include <linux/platform_data/usb-omap.h> @@ -57,10 +60,16 @@  #define	EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT		8  #define	EHCI_INSNREG05_ULPI_WRDATA_SHIFT		0 -/*-------------------------------------------------------------------------*/ +#define DRIVER_DESC "OMAP-EHCI Host Controller driver" + +static const char hcd_name[] = "ehci-omap"; -static const struct hc_driver ehci_omap_hc_driver; +/*-------------------------------------------------------------------------*/ +struct omap_hcd { +	struct usb_phy *phy[OMAP3_HS_USB_PORTS]; /* one PHY for each port */ +	int nports; +};  static inline void ehci_write(void __iomem *base, u32 reg, u32 val)  { @@ -72,99 +81,16 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)  	return __raw_readl(base + reg);  } +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ -static void omap_ehci_soft_phy_reset(struct usb_hcd *hcd, u8 port) -{ -	unsigned long timeout = jiffies + msecs_to_jiffies(1000); -	unsigned reg = 0; - -	reg = ULPI_FUNC_CTRL_RESET -		/* FUNCTION_CTRL_SET register */ -		| (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT) -		/* Write */ -		| (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) -		/* PORTn */ -		| ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) -		/* start ULPI access*/ -		| (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT); - -	ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg); - -	/* Wait for ULPI access completion */ -	while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI) -			& (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) { -		cpu_relax(); - -		if (time_after(jiffies, timeout)) { -			dev_dbg(hcd->self.controller, -					"phy reset operation timed out\n"); -			break; -		} -	} -} - -static int omap_ehci_init(struct usb_hcd *hcd) -{ -	struct ehci_hcd		*ehci = hcd_to_ehci(hcd); -	int			rc; -	struct usbhs_omap_platform_data	*pdata; - -	pdata = hcd->self.controller->platform_data; - -	/* Hold PHYs in reset while initializing EHCI controller */ -	if (pdata->phy_reset) { -		if (gpio_is_valid(pdata->reset_gpio_port[0])) -			gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0); - -		if (gpio_is_valid(pdata->reset_gpio_port[1])) -			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0); - -		/* Hold the PHY in RESET for enough time till DIR is high */ -		udelay(10); -	} - -	/* Soft reset the PHY using PHY reset command over ULPI */ -	if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY) -		omap_ehci_soft_phy_reset(hcd, 0); -	if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY) -		omap_ehci_soft_phy_reset(hcd, 1); - -	/* we know this is the memory we want, no need to ioremap again */ -	ehci->caps = hcd->regs; - -	rc = ehci_setup(hcd); - -	if (pdata->phy_reset) { -		/* Hold the PHY in RESET for enough time till -		 * PHY is settled and ready -		 */ -		udelay(10); - -		if (gpio_is_valid(pdata->reset_gpio_port[0])) -			gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1); - -		if (gpio_is_valid(pdata->reset_gpio_port[1])) -			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); -	} - -	return rc; -} - -static void disable_put_regulator( -		struct usbhs_omap_platform_data *pdata) -{ -	int i; +static struct hc_driver __read_mostly ehci_omap_hc_driver; -	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { -		if (pdata->regulator[i]) { -			regulator_disable(pdata->regulator[i]); -			regulator_put(pdata->regulator[i]); -		} -	} -} +static const struct ehci_driver_overrides ehci_omap_overrides __initdata = { +	.extra_priv_size = sizeof(struct omap_hcd), +}; -/* configure so an HC device and id are always provided */ -/* always called with process context; sleeping is OK */ +static u64 omap_ehci_dma_mask = DMA_BIT_MASK(32);  /**   * ehci_hcd_omap_probe - initialize TI-based HCDs @@ -175,15 +101,15 @@ static void disable_put_regulator(   */  static int ehci_hcd_omap_probe(struct platform_device *pdev)  { -	struct device				*dev = &pdev->dev; -	struct usbhs_omap_platform_data		*pdata = dev->platform_data; -	struct resource				*res; -	struct usb_hcd				*hcd; -	void __iomem				*regs; -	int					ret = -ENODEV; -	int					irq; -	int					i; -	char					supply[7]; +	struct device *dev = &pdev->dev; +	struct usbhs_omap_platform_data *pdata = dev->platform_data; +	struct resource	*res; +	struct usb_hcd	*hcd; +	void __iomem *regs; +	int ret = -ENODEV; +	int irq; +	int i; +	struct omap_hcd	*omap;  	if (usb_disabled())  		return -ENODEV; @@ -193,52 +119,74 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)  		return -ENODEV;  	} -	irq = platform_get_irq_byname(pdev, "ehci-irq"); -	if (irq < 0) { -		dev_err(dev, "EHCI irq failed\n"); -		return -ENODEV; +	/* For DT boot, get platform data from parent. i.e. usbhshost */ +	if (dev->of_node) { +		pdata = dev->parent->platform_data; +		dev->platform_data = pdata;  	} -	res =  platform_get_resource_byname(pdev, -				IORESOURCE_MEM, "ehci"); -	if (!res) { -		dev_err(dev, "UHH EHCI get resource failed\n"); +	if (!pdata) { +		dev_err(dev, "Missing platform data\n");  		return -ENODEV;  	} -	regs = ioremap(res->start, resource_size(res)); -	if (!regs) { -		dev_err(dev, "UHH EHCI ioremap failed\n"); -		return -ENOMEM; +	irq = platform_get_irq(pdev, 0); +	if (irq < 0) { +		dev_err(dev, "EHCI irq failed\n"); +		return -ENODEV;  	} +	res =  platform_get_resource(pdev, IORESOURCE_MEM, 0); +	regs = devm_ioremap_resource(dev, res); +	if (IS_ERR(regs)) +		return PTR_ERR(regs); + +	/* +	 * Right now device-tree probed devices don't get dma_mask set. +	 * Since shared usb code relies on it, set it here for now. +	 * Once we have dma capability bindings this can go away. +	 */ +	if (!pdev->dev.dma_mask) +		pdev->dev.dma_mask = &omap_ehci_dma_mask; +  	hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,  			dev_name(dev));  	if (!hcd) { -		dev_err(dev, "failed to create hcd with err %d\n", ret); -		ret = -ENOMEM; -		goto err_io; +		dev_err(dev, "Failed to create HCD\n"); +		return -ENOMEM;  	}  	hcd->rsrc_start = res->start;  	hcd->rsrc_len = resource_size(res);  	hcd->regs = regs; +	hcd_to_ehci(hcd)->caps = regs; -	/* get ehci regulator and enable */ -	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { -		if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) { -			pdata->regulator[i] = NULL; -			continue; -		} -		snprintf(supply, sizeof(supply), "hsusb%d", i); -		pdata->regulator[i] = regulator_get(dev, supply); -		if (IS_ERR(pdata->regulator[i])) { -			pdata->regulator[i] = NULL; -			dev_dbg(dev, -			"failed to get ehci port%d regulator\n", i); -		} else { -			regulator_enable(pdata->regulator[i]); +	omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv; +	omap->nports = pdata->nports; + +	platform_set_drvdata(pdev, hcd); + +	/* get the PHY devices if needed */ +	for (i = 0 ; i < omap->nports ; i++) { +		struct usb_phy *phy; + +		/* get the PHY device */ +		if (dev->of_node) +			phy = devm_usb_get_phy_by_phandle(dev, "phys", i); +		else +			phy = devm_usb_get_phy_dev(dev, i); +		if (IS_ERR(phy)) { +			/* Don't bail out if PHY is not absolutely necessary */ +			if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) +				continue; + +			ret = PTR_ERR(phy); +			dev_err(dev, "Can't get PHY device for port %d: %d\n", +					i, ret); +			goto err_phy;  		} + +		omap->phy[i] = phy;  	}  	pm_runtime_enable(dev); @@ -262,16 +210,34 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)  		goto err_pm_runtime;  	} +	/* +	 * Bring PHYs out of reset. +	 * Even though HSIC mode is a PHY-less mode, the reset +	 * line exists between the chips and can be modelled +	 * as a PHY device for reset control. +	 */ +	for (i = 0; i < omap->nports; i++) { +		if (!omap->phy[i]) +			continue; + +		usb_phy_init(omap->phy[i]); +		/* bring PHY out of suspend */ +		usb_phy_set_suspend(omap->phy[i], 0); +	}  	return 0;  err_pm_runtime: -	disable_put_regulator(pdata);  	pm_runtime_put_sync(dev); + +err_phy: +	for (i = 0; i < omap->nports; i++) { +		if (omap->phy[i]) +			usb_phy_shutdown(omap->phy[i]); +	} +  	usb_put_hcd(hcd); -err_io: -	iounmap(regs);  	return ret;  } @@ -286,14 +252,19 @@ err_io:   */  static int ehci_hcd_omap_remove(struct platform_device *pdev)  { -	struct device *dev				= &pdev->dev; -	struct usb_hcd *hcd				= dev_get_drvdata(dev); +	struct device *dev = &pdev->dev; +	struct usb_hcd *hcd = dev_get_drvdata(dev); +	struct omap_hcd *omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv; +	int i;  	usb_remove_hcd(hcd); -	disable_put_regulator(dev->platform_data); -	iounmap(hcd->regs); -	usb_put_hcd(hcd); +	for (i = 0; i < omap->nports; i++) { +		if (omap->phy[i]) +			usb_phy_shutdown(omap->phy[i]); +	} + +	usb_put_hcd(hcd);  	pm_runtime_put_sync(dev);  	pm_runtime_disable(dev); @@ -308,6 +279,13 @@ static void ehci_hcd_omap_shutdown(struct platform_device *pdev)  		hcd->driver->shutdown(hcd);  } +static const struct of_device_id omap_ehci_dt_ids[] = { +	{ .compatible = "ti,ehci-omap" }, +	{ } +}; + +MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids); +  static struct platform_driver ehci_hcd_omap_driver = {  	.probe			= ehci_hcd_omap_probe,  	.remove			= ehci_hcd_omap_remove, @@ -315,56 +293,35 @@ static struct platform_driver ehci_hcd_omap_driver = {  	/*.suspend		= ehci_hcd_omap_suspend, */  	/*.resume		= ehci_hcd_omap_resume, */  	.driver = { -		.name		= "ehci-omap", +		.name		= hcd_name, +		.of_match_table = of_match_ptr(omap_ehci_dt_ids),  	}  };  /*-------------------------------------------------------------------------*/ -static const struct hc_driver ehci_omap_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "OMAP-EHCI Host Controller", -	.hcd_priv_size		= sizeof(struct ehci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq			= ehci_irq, -	.flags			= HCD_MEMORY | HCD_USB2, - -	/* -	 * basic lifecycle operations -	 */ -	.reset			= omap_ehci_init, -	.start			= ehci_run, -	.stop			= ehci_stop, -	.shutdown		= ehci_shutdown, - -	/* -	 * managing i/o requests and associated device resources -	 */ -	.urb_enqueue		= ehci_urb_enqueue, -	.urb_dequeue		= ehci_urb_dequeue, -	.endpoint_disable	= ehci_endpoint_disable, -	.endpoint_reset		= ehci_endpoint_reset, +static int __init ehci_omap_init(void) +{ +	if (usb_disabled()) +		return -ENODEV; -	/* -	 * scheduling support -	 */ -	.get_frame_number	= ehci_get_frame, +	pr_info("%s: " DRIVER_DESC "\n", hcd_name); -	/* -	 * root hub support -	 */ -	.hub_status_data	= ehci_hub_status_data, -	.hub_control		= ehci_hub_control, -	.bus_suspend		= ehci_bus_suspend, -	.bus_resume		= ehci_bus_resume, +	ehci_init_driver(&ehci_omap_hc_driver, &ehci_omap_overrides); +	return platform_driver_register(&ehci_hcd_omap_driver); +} +module_init(ehci_omap_init); -	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; +static void __exit ehci_omap_cleanup(void) +{ +	platform_driver_unregister(&ehci_hcd_omap_driver); +} +module_exit(ehci_omap_cleanup);  MODULE_ALIAS("platform:ehci-omap");  MODULE_AUTHOR("Texas Instruments, Inc.");  MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>"); +MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>"); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 914a3ecfb5d..54c57948515 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -17,6 +17,12 @@  #include <linux/of.h>  #include <linux/of_device.h>  #include <linux/of_irq.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> +#include <linux/io.h> +#include <linux/dma-mapping.h> + +#include "ehci.h"  #define rdl(off)	__raw_readl(hcd->regs + (off))  #define wrl(off, val)	__raw_writel((val), hcd->regs + (off)) @@ -34,6 +40,12 @@  #define USB_PHY_IVREF_CTRL	0x440  #define USB_PHY_TST_GRP_CTRL	0x450 +#define DRIVER_DESC "EHCI orion driver" + +static const char hcd_name[] = "ehci-orion"; + +static struct hc_driver __read_mostly ehci_orion_hc_driver; +  /*   * Implement Orion USB controller specification guidelines   */ @@ -104,51 +116,6 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd)  	wrl(USB_MODE, 0x13);  } -static const struct hc_driver ehci_orion_hc_driver = { -	.description = hcd_name, -	.product_desc = "Marvell Orion EHCI", -	.hcd_priv_size = sizeof(struct ehci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq = ehci_irq, -	.flags = HCD_MEMORY | HCD_USB2, - -	/* -	 * basic lifecycle operations -	 */ -	.reset = ehci_setup, -	.start = ehci_run, -	.stop = ehci_stop, -	.shutdown = ehci_shutdown, - -	/* -	 * managing i/o requests and associated device resources -	 */ -	.urb_enqueue = ehci_urb_enqueue, -	.urb_dequeue = ehci_urb_dequeue, -	.endpoint_disable = ehci_endpoint_disable, -	.endpoint_reset = ehci_endpoint_reset, - -	/* -	 * scheduling support -	 */ -	.get_frame_number = ehci_get_frame, - -	/* -	 * root hub support -	 */ -	.hub_status_data = ehci_hub_status_data, -	.hub_control = ehci_hub_control, -	.bus_suspend = ehci_bus_suspend, -	.bus_resume = ehci_bus_resume, -	.relinquish_port = ehci_relinquish_port, -	.port_handed_over = ehci_port_handed_over, - -	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; -  static void  ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,  			     const struct mbus_dram_target_info *dram) @@ -305,7 +272,7 @@ err1:  	return err;  } -static int __exit ehci_orion_drv_remove(struct platform_device *pdev) +static int ehci_orion_drv_remove(struct platform_device *pdev)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev);  	struct clk *clk; @@ -323,8 +290,6 @@ static int __exit ehci_orion_drv_remove(struct platform_device *pdev)  	return 0;  } -MODULE_ALIAS("platform:orion-ehci"); -  static const struct of_device_id ehci_orion_dt_ids[] = {  	{ .compatible = "marvell,orion-ehci", },  	{}, @@ -333,7 +298,7 @@ MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids);  static struct platform_driver ehci_orion_driver = {  	.probe		= ehci_orion_drv_probe, -	.remove		= __exit_p(ehci_orion_drv_remove), +	.remove		= ehci_orion_drv_remove,  	.shutdown	= usb_hcd_platform_shutdown,  	.driver = {  		.name	= "orion-ehci", @@ -341,3 +306,26 @@ static struct platform_driver ehci_orion_driver = {  		.of_match_table = of_match_ptr(ehci_orion_dt_ids),  	},  }; + +static int __init ehci_orion_init(void) +{ +	if (usb_disabled()) +		return -ENODEV; + +	pr_info("%s: " DRIVER_DESC "\n", hcd_name); + +	ehci_init_driver(&ehci_orion_hc_driver, NULL); +	return platform_driver_register(&ehci_orion_driver); +} +module_init(ehci_orion_init); + +static void __exit ehci_orion_cleanup(void) +{ +	platform_driver_unregister(&ehci_orion_driver); +} +module_exit(ehci_orion_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_ALIAS("platform:orion-ehci"); +MODULE_AUTHOR("Tzachi Perelstein"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 170b9399e09..595d210655b 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -292,17 +292,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)  		}  	} -#ifdef	CONFIG_USB_SUSPEND -	/* REVISIT: the controller works fine for wakeup iff the root hub -	 * itself is "globally" suspended, but usbcore currently doesn't -	 * understand such things. -	 * -	 * System suspend currently expects to be able to suspend the entire -	 * device tree, device-at-a-time.  If we failed selective suspend -	 * reports, system suspend would fail; so the root hub code must claim -	 * success.  That's lying to usbcore, and it matters for runtime -	 * PM scenarios with selective suspend and remote wakeup... -	 */ +#ifdef	CONFIG_PM_RUNTIME  	if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev))  		ehci_warn(ehci, "selective suspend/wakeup unavailable\n");  #endif @@ -385,7 +375,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)  static struct hc_driver __read_mostly ehci_pci_hc_driver; -static const struct ehci_driver_overrides pci_overrides __initdata = { +static const struct ehci_driver_overrides pci_overrides __initconst = {  	.reset =		ehci_pci_setup,  }; diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index ca750639054..f47f2594c9d 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -18,11 +18,13 @@   *   * Licensed under the GNU/GPL. See COPYING for details.   */ +#include <linux/dma-mapping.h>  #include <linux/err.h>  #include <linux/kernel.h>  #include <linux/hrtimer.h>  #include <linux/io.h>  #include <linux/module.h> +#include <linux/of.h>  #include <linux/platform_device.h>  #include <linux/usb.h>  #include <linux/usb/hcd.h> @@ -58,26 +60,36 @@ static int ehci_platform_reset(struct usb_hcd *hcd)  static struct hc_driver __read_mostly ehci_platform_hc_driver; -static const struct ehci_driver_overrides platform_overrides __initdata = { +static const struct ehci_driver_overrides platform_overrides __initconst = {  	.reset =	ehci_platform_reset,  }; +static struct usb_ehci_pdata ehci_platform_defaults; +  static int ehci_platform_probe(struct platform_device *dev)  {  	struct usb_hcd *hcd;  	struct resource *res_mem; -	struct usb_ehci_pdata *pdata = dev->dev.platform_data; +	struct usb_ehci_pdata *pdata;  	int irq;  	int err = -ENOMEM; -	if (!pdata) { -		WARN_ON(1); -		return -ENODEV; -	} -  	if (usb_disabled())  		return -ENODEV; +	/* +	 * use reasonable defaults so platforms don't have to provide these. +	 * with DT probing on ARM, none of these are set. +	 */ +	if (!dev->dev.platform_data) +		dev->dev.platform_data = &ehci_platform_defaults; +	if (!dev->dev.dma_mask) +		dev->dev.dma_mask = &dev->dev.coherent_dma_mask; +	if (!dev->dev.coherent_dma_mask) +		dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + +	pdata = dev->dev.platform_data; +  	irq = platform_get_irq(dev, 0);  	if (irq < 0) {  		dev_err(&dev->dev, "no irq provided"); @@ -139,6 +151,9 @@ static int ehci_platform_remove(struct platform_device *dev)  	if (pdata->power_off)  		pdata->power_off(dev); +	if (pdata == &ehci_platform_defaults) +		dev->dev.platform_data = NULL; +  	return 0;  } @@ -183,6 +198,12 @@ static int ehci_platform_resume(struct device *dev)  #define ehci_platform_resume	NULL  #endif /* CONFIG_PM */ +static const struct of_device_id vt8500_ehci_ids[] = { +	{ .compatible = "via,vt8500-ehci", }, +	{ .compatible = "wm,prizm-ehci", }, +	{} +}; +  static const struct platform_device_id ehci_platform_table[] = {  	{ "ehci-platform", 0 },  	{ } @@ -203,6 +224,7 @@ static struct platform_driver ehci_platform_driver = {  		.owner	= THIS_MODULE,  		.name	= "ehci-platform",  		.pm	= &ehci_platform_pm_ops, +		.of_match_table = of_match_ptr(vt8500_ehci_ids),  	}  }; diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index df5925a4f0d..fd983771b02 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c @@ -221,7 +221,6 @@ static int ps3_ehci_remove(struct ps3_system_bus_device *dev)  	tmp = hcd->irq; -	ehci_shutdown(hcd);  	usb_remove_hcd(hcd);  	ps3_system_bus_set_drvdata(dev, NULL); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 5464665f0b6..d34b399b78e 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -90,7 +90,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)  	struct ehci_qh_hw *hw = qh->hw;  	/* writes to an active overlay are unsafe */ -	BUG_ON(qh->qh_state != QH_STATE_IDLE); +	WARN_ON(qh->qh_state != QH_STATE_IDLE);  	hw->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);  	hw->hw_alt_next = EHCI_LIST_END(ehci); @@ -123,26 +123,19 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)  {  	struct ehci_qtd *qtd; -	if (list_empty (&qh->qtd_list)) -		qtd = qh->dummy; -	else { -		qtd = list_entry (qh->qtd_list.next, -				struct ehci_qtd, qtd_list); -		/* -		 * first qtd may already be partially processed. -		 * If we come here during unlink, the QH overlay region -		 * might have reference to the just unlinked qtd. The -		 * qtd is updated in qh_completions(). Update the QH -		 * overlay here. -		 */ -		if (qh->hw->hw_token & ACTIVE_BIT(ehci)) { -			qh->hw->hw_qtd_next = qtd->hw_next; -			qtd = NULL; -		} -	} +	qtd = list_entry(qh->qtd_list.next, struct ehci_qtd, qtd_list); -	if (qtd) -		qh_update (ehci, qh, qtd); +	/* +	 * first qtd may already be partially processed. +	 * If we come here during unlink, the QH overlay region +	 * might have reference to the just unlinked qtd. The +	 * qtd is updated in qh_completions(). Update the QH +	 * overlay here. +	 */ +	if (qh->hw->hw_token & ACTIVE_BIT(ehci)) +		qh->hw->hw_qtd_next = qtd->hw_next; +	else +		qh_update(ehci, qh, qtd);  }  /*-------------------------------------------------------------------------*/ @@ -299,8 +292,8 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);  /*   * Process and free completed qtds for a qh, returning URBs to drivers. - * Chases up to qh->hw_current.  Returns number of completions called, - * indicating how much "real" work we did. + * Chases up to qh->hw_current.  Returns nonzero if the caller should + * unlink qh.   */  static unsigned  qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) @@ -309,13 +302,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)  	struct list_head	*entry, *tmp;  	int			last_status;  	int			stopped; -	unsigned		count = 0;  	u8			state;  	struct ehci_qh_hw	*hw = qh->hw; -	if (unlikely (list_empty (&qh->qtd_list))) -		return count; -  	/* completions (or tasks on other cpus) must never clobber HALT  	 * till we've gone through and cleaned everything up, even when  	 * they add urbs to this qh's queue or mark them for unlinking. @@ -333,7 +322,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)   rescan:  	last = NULL;  	last_status = -EINPROGRESS; -	qh->needs_rescan = 0; +	qh->dequeue_during_giveback = 0;  	/* remove de-activated QTDs from front of queue.  	 * after faults (including short reads), cleanup this urb @@ -352,7 +341,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)  		if (last) {  			if (likely (last->urb != urb)) {  				ehci_urb_done(ehci, last->urb, last_status); -				count++;  				last_status = -EINPROGRESS;  			}  			ehci_qtd_free (ehci, last); @@ -526,23 +514,16 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)  	/* last urb's completion might still need calling */  	if (likely (last != NULL)) {  		ehci_urb_done(ehci, last->urb, last_status); -		count++;  		ehci_qtd_free (ehci, last);  	}  	/* Do we need to rescan for URBs dequeued during a giveback? */ -	if (unlikely(qh->needs_rescan)) { +	if (unlikely(qh->dequeue_during_giveback)) {  		/* If the QH is already unlinked, do the rescan now. */  		if (state == QH_STATE_IDLE)  			goto rescan; -		/* Otherwise we have to wait until the QH is fully unlinked. -		 * Our caller will start an unlink if qh->needs_rescan is -		 * set.  But if an unlink has already started, nothing needs -		 * to be done. -		 */ -		if (state != QH_STATE_LINKED) -			qh->needs_rescan = 0; +		/* Otherwise the caller must unlink the QH. */  	}  	/* restore original state; caller must unlink or relink */ @@ -551,33 +532,23 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)  	/* be sure the hardware's done with the qh before refreshing  	 * it after fault cleanup, or recovering from silicon wrongly  	 * overlaying the dummy qtd (which reduces DMA chatter). +	 * +	 * We won't refresh a QH that's linked (after the HC +	 * stopped the queue).  That avoids a race: +	 *  - HC reads first part of QH; +	 *  - CPU updates that first part and the token; +	 *  - HC reads rest of that QH, including token +	 * Result:  HC gets an inconsistent image, and then +	 * DMAs to/from the wrong memory (corrupting it). +	 * +	 * That should be rare for interrupt transfers, +	 * except maybe high bandwidth ...  	 */ -	if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) { -		switch (state) { -		case QH_STATE_IDLE: -			qh_refresh(ehci, qh); -			break; -		case QH_STATE_LINKED: -			/* We won't refresh a QH that's linked (after the HC -			 * stopped the queue).  That avoids a race: -			 *  - HC reads first part of QH; -			 *  - CPU updates that first part and the token; -			 *  - HC reads rest of that QH, including token -			 * Result:  HC gets an inconsistent image, and then -			 * DMAs to/from the wrong memory (corrupting it). -			 * -			 * That should be rare for interrupt transfers, -			 * except maybe high bandwidth ... -			 */ - -			/* Tell the caller to start an unlink */ -			qh->needs_rescan = 1; -			break; -		/* otherwise, unlink already started */ -		} -	} +	if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) +		qh->exception = 1; -	return count; +	/* Let the caller know if the QH needs to be unlinked. */ +	return qh->exception;  }  /*-------------------------------------------------------------------------*/ @@ -957,14 +928,13 @@ done:  	/* NOTE:  if (PIPE_INTERRUPT) { scheduler sets s-mask } */ -	/* init as live, toggle clear, advance to dummy */ +	/* init as live, toggle clear */  	qh->qh_state = QH_STATE_IDLE;  	hw = qh->hw;  	hw->hw_info1 = cpu_to_hc32(ehci, info1);  	hw->hw_info2 = cpu_to_hc32(ehci, info2);  	qh->is_out = !is_input;  	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); -	qh_refresh (ehci, qh);  	return qh;  } @@ -988,8 +958,9 @@ static void disable_async(struct ehci_hcd *ehci)  	if (--ehci->async_count)  		return; -	/* The async schedule and async_unlink list are supposed to be empty */ -	WARN_ON(ehci->async->qh_next.qh || ehci->async_unlink); +	/* The async schedule and unlink lists are supposed to be empty */ +	WARN_ON(ehci->async->qh_next.qh || !list_empty(&ehci->async_unlink) || +			!list_empty(&ehci->async_idle));  	/* Don't turn off the schedule until ASS is 1 */  	ehci_poll_ASS(ehci); @@ -1020,8 +991,9 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)  	head->qh_next.qh = qh;  	head->hw->hw_next = dma; -	qh->xacterrs = 0;  	qh->qh_state = QH_STATE_LINKED; +	qh->xacterrs = 0; +	qh->exception = 0;  	/* qtd completions reported later by interrupt */  	enable_async(ehci); @@ -1179,11 +1151,7 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)  	/* Add to the end of the list of QHs waiting for the next IAAD */  	qh->qh_state = QH_STATE_UNLINK_WAIT; -	if (ehci->async_unlink) -		ehci->async_unlink_last->unlink_next = qh; -	else -		ehci->async_unlink = qh; -	ehci->async_unlink_last = qh; +	list_add_tail(&qh->unlink_node, &ehci->async_unlink);  	/* Unlink it from the schedule */  	prev = ehci->async; @@ -1196,44 +1164,19 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)  		ehci->qh_scan_next = qh->qh_next.qh;  } -static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested) +static void start_iaa_cycle(struct ehci_hcd *ehci)  { -	/* -	 * Do nothing if an IAA cycle is already running or -	 * if one will be started shortly. -	 */ -	if (ehci->async_iaa || ehci->async_unlinking) +	/* Do nothing if an IAA cycle is already running */ +	if (ehci->iaa_in_progress)  		return; +	ehci->iaa_in_progress = true;  	/* If the controller isn't running, we don't have to wait for it */  	if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) { - -		/* Do all the waiting QHs */ -		ehci->async_iaa = ehci->async_unlink; -		ehci->async_unlink = NULL; - -		if (!nested)		/* Avoid recursion */ -			end_unlink_async(ehci); +		end_unlink_async(ehci);  	/* Otherwise start a new IAA cycle */  	} else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) { -		struct ehci_qh		*qh; - -		/* Do only the first waiting QH (nVidia bug?) */ -		qh = ehci->async_unlink; - -		/* -		 * Intel (?) bug: The HC can write back the overlay region -		 * even after the IAA interrupt occurs.  In self-defense, -		 * always go through two IAA cycles for each QH. -		 */ -		if (qh->qh_state == QH_STATE_UNLINK_WAIT) { -			qh->qh_state = QH_STATE_UNLINK; -		} else { -			ehci->async_iaa = qh; -			ehci->async_unlink = qh->unlink_next; -			qh->unlink_next = NULL; -		}  		/* Make sure the unlinks are all visible to the hardware */  		wmb(); @@ -1250,36 +1193,73 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)  static void end_unlink_async(struct ehci_hcd *ehci)  {  	struct ehci_qh		*qh; +	bool			early_exit;  	if (ehci->has_synopsys_hc_bug)  		ehci_writel(ehci, (u32) ehci->async->qh_dma,  			    &ehci->regs->async_next); +	/* The current IAA cycle has ended */ +	ehci->iaa_in_progress = false; + +	if (list_empty(&ehci->async_unlink)) +		return; +	qh = list_first_entry(&ehci->async_unlink, struct ehci_qh, +			unlink_node);	/* QH whose IAA cycle just ended */ + +	/* +	 * If async_unlinking is set then this routine is already running, +	 * either on the stack or on another CPU. +	 */ +	early_exit = ehci->async_unlinking; + +	/* If the controller isn't running, process all the waiting QHs */ +	if (ehci->rh_state < EHCI_RH_RUNNING) +		list_splice_tail_init(&ehci->async_unlink, &ehci->async_idle); + +	/* +	 * Intel (?) bug: The HC can write back the overlay region even +	 * after the IAA interrupt occurs.  In self-defense, always go +	 * through two IAA cycles for each QH. +	 */ +	else if (qh->qh_state == QH_STATE_UNLINK_WAIT) { +		qh->qh_state = QH_STATE_UNLINK; +		early_exit = true; +	} + +	/* Otherwise process only the first waiting QH (NVIDIA bug?) */ +	else +		list_move_tail(&qh->unlink_node, &ehci->async_idle); + +	/* Start a new IAA cycle if any QHs are waiting for it */ +	if (!list_empty(&ehci->async_unlink)) +		start_iaa_cycle(ehci); + +	/* +	 * Don't allow nesting or concurrent calls, +	 * or wait for the second IAA cycle for the next QH. +	 */ +	if (early_exit) +		return; +  	/* Process the idle QHs */ - restart:  	ehci->async_unlinking = true; -	while (ehci->async_iaa) { -		qh = ehci->async_iaa; -		ehci->async_iaa = qh->unlink_next; -		qh->unlink_next = NULL; +	while (!list_empty(&ehci->async_idle)) { +		qh = list_first_entry(&ehci->async_idle, struct ehci_qh, +				unlink_node); +		list_del(&qh->unlink_node);  		qh->qh_state = QH_STATE_IDLE;  		qh->qh_next.qh = NULL; -		qh_completions(ehci, qh); +		if (!list_empty(&qh->qtd_list)) +			qh_completions(ehci, qh);  		if (!list_empty(&qh->qtd_list) &&  				ehci->rh_state == EHCI_RH_RUNNING)  			qh_link_async(ehci, qh);  		disable_async(ehci);  	}  	ehci->async_unlinking = false; - -	/* Start a new IAA cycle if any QHs are waiting for it */ -	if (ehci->async_unlink) { -		start_iaa_cycle(ehci, true); -		if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) -			goto restart; -	}  }  static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh); @@ -1288,7 +1268,6 @@ static void unlink_empty_async(struct ehci_hcd *ehci)  {  	struct ehci_qh		*qh;  	struct ehci_qh		*qh_to_unlink = NULL; -	bool			check_unlinks_later = false;  	int			count = 0;  	/* Find the last async QH which has been empty for a timer cycle */ @@ -1296,15 +1275,13 @@ static void unlink_empty_async(struct ehci_hcd *ehci)  		if (list_empty(&qh->qtd_list) &&  				qh->qh_state == QH_STATE_LINKED) {  			++count; -			if (qh->unlink_cycle == ehci->async_unlink_cycle) -				check_unlinks_later = true; -			else +			if (qh->unlink_cycle != ehci->async_unlink_cycle)  				qh_to_unlink = qh;  		}  	}  	/* If nothing else is being unlinked, unlink the last empty QH */ -	if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) { +	if (list_empty(&ehci->async_unlink) && qh_to_unlink) {  		start_unlink_async(ehci, qh_to_unlink);  		--count;  	} @@ -1316,24 +1293,30 @@ static void unlink_empty_async(struct ehci_hcd *ehci)  	}  } +/* The root hub is suspended; unlink all the async QHs */ +static void __maybe_unused unlink_empty_async_suspended(struct ehci_hcd *ehci) +{ +	struct ehci_qh		*qh; + +	while (ehci->async->qh_next.qh) { +		qh = ehci->async->qh_next.qh; +		WARN_ON(!list_empty(&qh->qtd_list)); +		single_unlink_async(ehci, qh); +	} +	start_iaa_cycle(ehci); +} +  /* makes sure the async qh will become idle */  /* caller must own ehci->lock */  static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)  { -	/* -	 * If the QH isn't linked then there's nothing we can do -	 * unless we were called during a giveback, in which case -	 * qh_completions() has to deal with it. -	 */ -	if (qh->qh_state != QH_STATE_LINKED) { -		if (qh->qh_state == QH_STATE_COMPLETING) -			qh->needs_rescan = 1; +	/* If the QH isn't linked then there's nothing we can do. */ +	if (qh->qh_state != QH_STATE_LINKED)  		return; -	}  	single_unlink_async(ehci, qh); -	start_iaa_cycle(ehci, false); +	start_iaa_cycle(ehci);  }  /*-------------------------------------------------------------------------*/ @@ -1347,7 +1330,7 @@ static void scan_async (struct ehci_hcd *ehci)  	while (ehci->qh_scan_next) {  		qh = ehci->qh_scan_next;  		ehci->qh_scan_next = qh->qh_next.qh; - rescan: +  		/* clean any finished work for this qh */  		if (!list_empty(&qh->qtd_list)) {  			int temp; @@ -1360,14 +1343,13 @@ static void scan_async (struct ehci_hcd *ehci)  			 * in single_unlink_async().  			 */  			temp = qh_completions(ehci, qh); -			if (qh->needs_rescan) { +			if (unlikely(temp)) {  				start_unlink_async(ehci, qh);  			} else if (list_empty(&qh->qtd_list)  					&& qh->qh_state == QH_STATE_LINKED) {  				qh->unlink_cycle = ehci->async_unlink_cycle;  				check_unlinks_later = true; -			} else if (temp != 0) -				goto rescan; +			}  		}  	} diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index 20ebf6a8b7f..635775278c7 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -13,13 +13,23 @@   */  #include <linux/clk.h> +#include <linux/dma-mapping.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h>  #include <linux/of.h> -#include <linux/platform_device.h>  #include <linux/of_gpio.h> +#include <linux/platform_device.h>  #include <linux/platform_data/usb-ehci-s5p.h>  #include <linux/usb/phy.h>  #include <linux/usb/samsung_usb_phy.h> -#include <plat/usb-phy.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> +#include <linux/usb/otg.h> + +#include "ehci.h" + +#define DRIVER_DESC "EHCI s5p driver"  #define EHCI_INSNREG00(base)			(base + 0x90)  #define EHCI_INSNREG00_ENA_INCR16		(0x1 << 25) @@ -30,82 +40,35 @@  	(EHCI_INSNREG00_ENA_INCR16 | EHCI_INSNREG00_ENA_INCR8 |	\  	 EHCI_INSNREG00_ENA_INCR4 | EHCI_INSNREG00_ENA_INCRX_ALIGN) +static const char hcd_name[] = "ehci-s5p"; +static struct hc_driver __read_mostly s5p_ehci_hc_driver; +  struct s5p_ehci_hcd { -	struct device *dev; -	struct usb_hcd *hcd;  	struct clk *clk;  	struct usb_phy *phy;  	struct usb_otg *otg;  	struct s5p_ehci_platdata *pdata;  }; -static const struct hc_driver s5p_ehci_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "S5P EHCI Host Controller", -	.hcd_priv_size		= sizeof(struct ehci_hcd), - -	.irq			= ehci_irq, -	.flags			= HCD_MEMORY | HCD_USB2, - -	.reset			= ehci_setup, -	.start			= ehci_run, -	.stop			= ehci_stop, -	.shutdown		= ehci_shutdown, - -	.get_frame_number	= ehci_get_frame, - -	.urb_enqueue		= ehci_urb_enqueue, -	.urb_dequeue		= ehci_urb_dequeue, -	.endpoint_disable	= ehci_endpoint_disable, -	.endpoint_reset		= ehci_endpoint_reset, - -	.hub_status_data	= ehci_hub_status_data, -	.hub_control		= ehci_hub_control, -	.bus_suspend		= ehci_bus_suspend, -	.bus_resume		= ehci_bus_resume, - -	.relinquish_port	= ehci_relinquish_port, -	.port_handed_over	= ehci_port_handed_over, - -	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete, -}; - -static void s5p_ehci_phy_enable(struct s5p_ehci_hcd *s5p_ehci) -{ -	struct platform_device *pdev = to_platform_device(s5p_ehci->dev); - -	if (s5p_ehci->phy) -		usb_phy_init(s5p_ehci->phy); -	else if (s5p_ehci->pdata->phy_init) -		s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST); -} - -static void s5p_ehci_phy_disable(struct s5p_ehci_hcd *s5p_ehci) -{ -	struct platform_device *pdev = to_platform_device(s5p_ehci->dev); - -	if (s5p_ehci->phy) -		usb_phy_shutdown(s5p_ehci->phy); -	else if (s5p_ehci->pdata->phy_exit) -		s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST); -} +#define to_s5p_ehci(hcd)      (struct s5p_ehci_hcd *)(hcd_to_ehci(hcd)->priv)  static void s5p_setup_vbus_gpio(struct platform_device *pdev)  { +	struct device *dev = &pdev->dev;  	int err;  	int gpio; -	if (!pdev->dev.of_node) +	if (!dev->of_node)  		return; -	gpio = of_get_named_gpio(pdev->dev.of_node, -			"samsung,vbus-gpio", 0); +	gpio = of_get_named_gpio(dev->of_node, "samsung,vbus-gpio", 0);  	if (!gpio_is_valid(gpio))  		return; -	err = gpio_request_one(gpio, GPIOF_OUT_INIT_HIGH, "ehci_vbus_gpio"); +	err = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_HIGH, +				    "ehci_vbus_gpio");  	if (err) -		dev_err(&pdev->dev, "can't request ehci vbus gpio %d", gpio); +		dev_err(dev, "can't request ehci vbus gpio %d", gpio);  }  static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32); @@ -133,13 +96,15 @@ static int s5p_ehci_probe(struct platform_device *pdev)  	s5p_setup_vbus_gpio(pdev); -	s5p_ehci = devm_kzalloc(&pdev->dev, sizeof(struct s5p_ehci_hcd), -				GFP_KERNEL); -	if (!s5p_ehci) +	hcd = usb_create_hcd(&s5p_ehci_hc_driver, +			     &pdev->dev, dev_name(&pdev->dev)); +	if (!hcd) { +		dev_err(&pdev->dev, "Unable to create HCD\n");  		return -ENOMEM; - +	} +	s5p_ehci = to_s5p_ehci(hcd);  	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); -	if (IS_ERR_OR_NULL(phy)) { +	if (IS_ERR(phy)) {  		/* Fallback to pdata */  		if (!pdata) {  			dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); @@ -152,16 +117,6 @@ static int s5p_ehci_probe(struct platform_device *pdev)  		s5p_ehci->otg = phy->otg;  	} -	s5p_ehci->dev = &pdev->dev; - -	hcd = usb_create_hcd(&s5p_ehci_hc_driver, &pdev->dev, -					dev_name(&pdev->dev)); -	if (!hcd) { -		dev_err(&pdev->dev, "Unable to create HCD\n"); -		return -ENOMEM; -	} - -	s5p_ehci->hcd = hcd;  	s5p_ehci->clk = devm_clk_get(&pdev->dev, "usbhost");  	if (IS_ERR(s5p_ehci->clk)) { @@ -198,9 +153,12 @@ static int s5p_ehci_probe(struct platform_device *pdev)  	}  	if (s5p_ehci->otg) -		s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self); +		s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self); -	s5p_ehci_phy_enable(s5p_ehci); +	if (s5p_ehci->phy) +		usb_phy_init(s5p_ehci->phy); +	else if (s5p_ehci->pdata->phy_init) +		s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);  	ehci = hcd_to_ehci(hcd);  	ehci->caps = hcd->regs; @@ -214,12 +172,15 @@ static int s5p_ehci_probe(struct platform_device *pdev)  		goto fail_add_hcd;  	} -	platform_set_drvdata(pdev, s5p_ehci); +	platform_set_drvdata(pdev, hcd);  	return 0;  fail_add_hcd: -	s5p_ehci_phy_disable(s5p_ehci); +	if (s5p_ehci->phy) +		usb_phy_shutdown(s5p_ehci->phy); +	else if (s5p_ehci->pdata->phy_exit) +		s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);  fail_io:  	clk_disable_unprepare(s5p_ehci->clk);  fail_clk: @@ -229,15 +190,18 @@ fail_clk:  static int s5p_ehci_remove(struct platform_device *pdev)  { -	struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev); -	struct usb_hcd *hcd = s5p_ehci->hcd; +	struct usb_hcd *hcd = platform_get_drvdata(pdev); +	struct s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd);  	usb_remove_hcd(hcd);  	if (s5p_ehci->otg) -		s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self); +		s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self); -	s5p_ehci_phy_disable(s5p_ehci); +	if (s5p_ehci->phy) +		usb_phy_shutdown(s5p_ehci->phy); +	else if (s5p_ehci->pdata->phy_exit) +		s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);  	clk_disable_unprepare(s5p_ehci->clk); @@ -248,8 +212,7 @@ static int s5p_ehci_remove(struct platform_device *pdev)  static void s5p_ehci_shutdown(struct platform_device *pdev)  { -	struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev); -	struct usb_hcd *hcd = s5p_ehci->hcd; +	struct usb_hcd *hcd = platform_get_drvdata(pdev);  	if (hcd->driver->shutdown)  		hcd->driver->shutdown(hcd); @@ -258,17 +221,22 @@ static void s5p_ehci_shutdown(struct platform_device *pdev)  #ifdef CONFIG_PM  static int s5p_ehci_suspend(struct device *dev)  { -	struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); -	struct usb_hcd *hcd = s5p_ehci->hcd; +	struct usb_hcd *hcd = dev_get_drvdata(dev); +	struct s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd); +	struct platform_device *pdev = to_platform_device(dev); +  	bool do_wakeup = device_may_wakeup(dev);  	int rc;  	rc = ehci_suspend(hcd, do_wakeup);  	if (s5p_ehci->otg) -		s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self); +		s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self); -	s5p_ehci_phy_disable(s5p_ehci); +	if (s5p_ehci->phy) +		usb_phy_shutdown(s5p_ehci->phy); +	else if (s5p_ehci->pdata->phy_exit) +		s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);  	clk_disable_unprepare(s5p_ehci->clk); @@ -277,15 +245,19 @@ static int s5p_ehci_suspend(struct device *dev)  static int s5p_ehci_resume(struct device *dev)  { -	struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); -	struct usb_hcd *hcd = s5p_ehci->hcd; +	struct usb_hcd *hcd = dev_get_drvdata(dev); +	struct  s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd); +	struct platform_device *pdev = to_platform_device(dev);  	clk_prepare_enable(s5p_ehci->clk);  	if (s5p_ehci->otg) -		s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self); +		s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self); -	s5p_ehci_phy_enable(s5p_ehci); +	if (s5p_ehci->phy) +		usb_phy_init(s5p_ehci->phy); +	else if (s5p_ehci->pdata->phy_init) +		s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);  	/* DMA burst Enable */  	writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); @@ -322,5 +294,29 @@ static struct platform_driver s5p_ehci_driver = {  		.of_match_table = of_match_ptr(exynos_ehci_match),  	}  }; +static const struct ehci_driver_overrides s5p_overrides __initdata = { +	.extra_priv_size = sizeof(struct s5p_ehci_hcd), +}; + +static int __init ehci_s5p_init(void) +{ +	if (usb_disabled()) +		return -ENODEV; + +	pr_info("%s: " DRIVER_DESC "\n", hcd_name); +	ehci_init_driver(&s5p_ehci_hc_driver, &s5p_overrides); +	return platform_driver_register(&s5p_ehci_driver); +} +module_init(ehci_s5p_init); + +static void __exit ehci_s5p_cleanup(void) +{ +	platform_driver_unregister(&s5p_ehci_driver); +} +module_exit(ehci_s5p_cleanup); +MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_ALIAS("platform:s5p-ehci"); +MODULE_AUTHOR("Jingoo Han"); +MODULE_AUTHOR("Joonyoung Shim"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index b476daf49f6..acff5b8f6e8 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -539,6 +539,7 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)  	}  	qh->qh_state = QH_STATE_LINKED;  	qh->xacterrs = 0; +	qh->exception = 0;  	/* update per-qh bandwidth for usbfs */  	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period @@ -602,15 +603,9 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)  static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)  { -	/* If the QH isn't linked then there's nothing we can do -	 * unless we were called during a giveback, in which case -	 * qh_completions() has to deal with it. -	 */ -	if (qh->qh_state != QH_STATE_LINKED) { -		if (qh->qh_state == QH_STATE_COMPLETING) -			qh->needs_rescan = 1; +	/* If the QH isn't linked then there's nothing we can do. */ +	if (qh->qh_state != QH_STATE_LINKED)  		return; -	}  	qh_unlink_periodic (ehci, qh); @@ -625,17 +620,13 @@ static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)  	qh->unlink_cycle = ehci->intr_unlink_cycle;  	/* New entries go at the end of the intr_unlink list */ -	if (ehci->intr_unlink) -		ehci->intr_unlink_last->unlink_next = qh; -	else -		ehci->intr_unlink = qh; -	ehci->intr_unlink_last = qh; +	list_add_tail(&qh->unlink_node, &ehci->intr_unlink);  	if (ehci->intr_unlinking)  		;	/* Avoid recursive calls */  	else if (ehci->rh_state < EHCI_RH_RUNNING)  		ehci_handle_intr_unlinks(ehci); -	else if (ehci->intr_unlink == qh) { +	else if (ehci->intr_unlink.next == &qh->unlink_node) {  		ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true);  		++ehci->intr_unlink_cycle;  	} @@ -649,7 +640,8 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)  	qh->qh_state = QH_STATE_IDLE;  	hw->hw_next = EHCI_LIST_END(ehci); -	qh_completions(ehci, qh); +	if (!list_empty(&qh->qtd_list)) +		qh_completions(ehci, qh);  	/* reschedule QH iff another request is queued */  	if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) { @@ -792,7 +784,6 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)  	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */  	struct ehci_qh_hw	*hw = qh->hw; -	qh_refresh(ehci, qh);  	hw->hw_next = EHCI_LIST_END(ehci);  	frame = qh->start; @@ -844,8 +835,6 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)  	} else  		ehci_dbg (ehci, "reused qh %p schedule\n", qh); -	/* stuff into the periodic schedule */ -	qh_link_periodic(ehci, qh);  done:  	return status;  } @@ -891,6 +880,12 @@ static int intr_submit (  	qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv);  	BUG_ON (qh == NULL); +	/* stuff into the periodic schedule */ +	if (qh->qh_state == QH_STATE_IDLE) { +		qh_refresh(ehci, qh); +		qh_link_periodic(ehci, qh); +	} +  	/* ... update usbfs periodic stats */  	ehci_to_hcd(ehci)->self.bandwidth_int_reqs++; @@ -911,7 +906,7 @@ static void scan_intr(struct ehci_hcd *ehci)  	list_for_each_entry_safe(qh, ehci->qh_scan_next, &ehci->intr_qh_list,  			intr_node) { - rescan: +  		/* clean any finished work for this qh */  		if (!list_empty(&qh->qtd_list)) {  			int temp; @@ -924,12 +919,9 @@ static void scan_intr(struct ehci_hcd *ehci)  			 * in qh_unlink_periodic().  			 */  			temp = qh_completions(ehci, qh); -			if (unlikely(qh->needs_rescan || -					(list_empty(&qh->qtd_list) && -						qh->qh_state == QH_STATE_LINKED))) +			if (unlikely(temp || (list_empty(&qh->qtd_list) && +					qh->qh_state == QH_STATE_LINKED)))  				start_unlink_intr(ehci, qh); -			else if (temp != 0) -				goto rescan;  		}  	}  } @@ -1214,6 +1206,7 @@ itd_urb_transaction (  		memset (itd, 0, sizeof *itd);  		itd->itd_dma = itd_dma; +		itd->frame = 9999;		/* an invalid value */  		list_add (&itd->itd_list, &sched->td_list);  	}  	spin_unlock_irqrestore (&ehci->lock, flags); @@ -1915,6 +1908,7 @@ sitd_urb_transaction (  		memset (sitd, 0, sizeof *sitd);  		sitd->sitd_dma = sitd_dma; +		sitd->frame = 9999;		/* an invalid value */  		list_add (&sitd->sitd_list, &iso_sched->td_list);  	} diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index 3565a300f40..b44d716ddc8 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -77,7 +77,6 @@ static const struct hc_driver ehci_sh_hc_driver = {  static int ehci_hcd_sh_probe(struct platform_device *pdev)  { -	const struct hc_driver *driver = &ehci_sh_hc_driver;  	struct resource *res;  	struct ehci_sh_priv *priv;  	struct ehci_sh_platdata *pdata; @@ -170,7 +169,7 @@ fail_create_hcd:  	return ret;  } -static int __exit ehci_hcd_sh_remove(struct platform_device *pdev) +static int ehci_hcd_sh_remove(struct platform_device *pdev)  {  	struct ehci_sh_priv *priv = platform_get_drvdata(pdev);  	struct usb_hcd *hcd = priv->hcd; @@ -196,7 +195,7 @@ static void ehci_hcd_sh_shutdown(struct platform_device *pdev)  static struct platform_driver ehci_hcd_sh_driver = {  	.probe		= ehci_hcd_sh_probe, -	.remove		= __exit_p(ehci_hcd_sh_remove), +	.remove		= ehci_hcd_sh_remove,  	.shutdown	= ehci_hcd_sh_shutdown,  	.driver		= {  		.name	= "sh_ehci", diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c index 466c1bb5b96..61ecfb3d52f 100644 --- a/drivers/usb/host/ehci-spear.c +++ b/drivers/usb/host/ehci-spear.c @@ -1,5 +1,5 @@  /* -* Driver for EHCI HCD on SPEAR SOC +* Driver for EHCI HCD on SPEAr SOC  *  * Copyright (C) 2010 ST Micro Electronics,  * Deepak Sikri <deepak.sikri@st.com> @@ -12,73 +12,32 @@  */  #include <linux/clk.h> +#include <linux/dma-mapping.h> +#include <linux/io.h>  #include <linux/jiffies.h> +#include <linux/kernel.h> +#include <linux/module.h>  #include <linux/of.h>  #include <linux/platform_device.h>  #include <linux/pm.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> -struct spear_ehci { -	struct ehci_hcd ehci; -	struct clk *clk; -}; - -#define to_spear_ehci(hcd)	(struct spear_ehci *)hcd_to_ehci(hcd) - -static void spear_start_ehci(struct spear_ehci *ehci) -{ -	clk_prepare_enable(ehci->clk); -} - -static void spear_stop_ehci(struct spear_ehci *ehci) -{ -	clk_disable_unprepare(ehci->clk); -} +#include "ehci.h" -static int ehci_spear_setup(struct usb_hcd *hcd) -{ -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); +#define DRIVER_DESC "EHCI SPEAr driver" -	/* registers start at offset 0x0 */ -	ehci->caps = hcd->regs; - -	return ehci_setup(hcd); -} +static const char hcd_name[] = "SPEAr-ehci"; -static const struct hc_driver ehci_spear_hc_driver = { -	.description			= hcd_name, -	.product_desc			= "SPEAr EHCI", -	.hcd_priv_size			= sizeof(struct spear_ehci), - -	/* generic hardware linkage */ -	.irq				= ehci_irq, -	.flags				= HCD_MEMORY | HCD_USB2, - -	/* basic lifecycle operations */ -	.reset				= ehci_spear_setup, -	.start				= ehci_run, -	.stop				= ehci_stop, -	.shutdown			= ehci_shutdown, - -	/* managing i/o requests and associated device resources */ -	.urb_enqueue			= ehci_urb_enqueue, -	.urb_dequeue			= ehci_urb_dequeue, -	.endpoint_disable		= ehci_endpoint_disable, -	.endpoint_reset			= ehci_endpoint_reset, +struct spear_ehci { +	struct clk *clk; +}; -	/* scheduling support */ -	.get_frame_number		= ehci_get_frame, +#define to_spear_ehci(hcd)	(struct spear_ehci *)(hcd_to_ehci(hcd)->priv) -	/* root hub support */ -	.hub_status_data		= ehci_hub_status_data, -	.hub_control			= ehci_hub_control, -	.bus_suspend			= ehci_bus_suspend, -	.bus_resume			= ehci_bus_resume, -	.relinquish_port		= ehci_relinquish_port, -	.port_handed_over		= ehci_port_handed_over, -	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete, -}; +static struct hc_driver __read_mostly ehci_spear_hc_driver; -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int ehci_spear_drv_suspend(struct device *dev)  {  	struct usb_hcd *hcd = dev_get_drvdata(dev); @@ -94,7 +53,7 @@ static int ehci_spear_drv_resume(struct device *dev)  	ehci_resume(hcd, false);  	return 0;  } -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_SLEEP */  static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend,  		ehci_spear_drv_resume); @@ -104,7 +63,7 @@ static u64 spear_ehci_dma_mask = DMA_BIT_MASK(32);  static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)  {  	struct usb_hcd *hcd ; -	struct spear_ehci *ehci; +	struct spear_ehci *sehci;  	struct resource *res;  	struct clk *usbh_clk;  	const struct hc_driver *driver = &ehci_spear_hc_driver; @@ -161,10 +120,13 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)  		goto err_put_hcd;  	} -	ehci = (struct spear_ehci *)hcd_to_ehci(hcd); -	ehci->clk = usbh_clk; +	sehci = to_spear_ehci(hcd); +	sehci->clk = usbh_clk; + +	/* registers start at offset 0x0 */ +	hcd_to_ehci(hcd)->caps = hcd->regs; -	spear_start_ehci(ehci); +	clk_prepare_enable(sehci->clk);  	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);  	if (retval)  		goto err_stop_ehci; @@ -172,7 +134,7 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)  	return retval;  err_stop_ehci: -	spear_stop_ehci(ehci); +	clk_disable_unprepare(sehci->clk);  err_put_hcd:  	usb_put_hcd(hcd);  fail: @@ -184,7 +146,7 @@ fail:  static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev); -	struct spear_ehci *ehci_p = to_spear_ehci(hcd); +	struct spear_ehci *sehci = to_spear_ehci(hcd);  	if (!hcd)  		return 0; @@ -192,8 +154,8 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)  		BUG();  	usb_remove_hcd(hcd); -	if (ehci_p->clk) -		spear_stop_ehci(ehci_p); +	if (sehci->clk) +		clk_disable_unprepare(sehci->clk);  	usb_put_hcd(hcd);  	return 0; @@ -216,4 +178,29 @@ static struct platform_driver spear_ehci_hcd_driver = {  	}  }; +static const struct ehci_driver_overrides spear_overrides __initdata = { +	.extra_priv_size = sizeof(struct spear_ehci), +}; + +static int __init ehci_spear_init(void) +{ +	if (usb_disabled()) +		return -ENODEV; + +	pr_info("%s: " DRIVER_DESC "\n", hcd_name); + +	ehci_init_driver(&ehci_spear_hc_driver, &spear_overrides); +	return platform_driver_register(&spear_ehci_hcd_driver); +} +module_init(ehci_spear_init); + +static void __exit ehci_spear_cleanup(void) +{ +	platform_driver_unregister(&spear_ehci_hcd_driver); +} +module_exit(ehci_spear_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_ALIAS("platform:spear-ehci"); +MODULE_AUTHOR("Deepak Sikri"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 568aecc7075..e3eddc31ac8 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -28,6 +28,7 @@  #include <linux/pm_runtime.h>  #include <linux/usb/ehci_def.h>  #include <linux/usb/tegra_usb_phy.h> +#include <linux/clk/tegra.h>  #define TEGRA_USB_BASE			0xC5000000  #define TEGRA_USB2_BASE			0xC5004000 @@ -610,7 +611,7 @@ static const struct dev_pm_ops tegra_ehci_pm_ops = {  /* Bits of PORTSC1, which will get cleared by writing 1 into them */  #define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) -void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val) +static void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)  {  	unsigned long val;  	struct usb_hcd *hcd = bus_to_hcd(x->otg->host); @@ -621,9 +622,8 @@ void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)  	val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3);  	writel(val, base + TEGRA_USB_PORTSC1);  } -EXPORT_SYMBOL_GPL(tegra_ehci_set_pts); -void tegra_ehci_set_phcd(struct usb_phy *x, bool enable) +static void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)  {  	unsigned long val;  	struct usb_hcd *hcd = bus_to_hcd(x->otg->host); @@ -636,7 +636,6 @@ void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)  		val &= ~TEGRA_USB_PORTSC1_PHCD;  	writel(val, base + TEGRA_USB_PORTSC1);  } -EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd);  static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); @@ -691,6 +690,10 @@ static int tegra_ehci_probe(struct platform_device *pdev)  	if (err)  		goto fail_clk; +	tegra_periph_reset_assert(tegra->clk); +	udelay(1); +	tegra_periph_reset_deassert(tegra->clk); +  	tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node,  		"nvidia,needs-double-reset"); @@ -733,7 +736,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)  	tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs,  					pdata->phy_config, -					TEGRA_USB_PHY_MODE_HOST); +					TEGRA_USB_PHY_MODE_HOST, +					tegra_ehci_set_pts, +					tegra_ehci_set_phcd);  	if (IS_ERR(tegra->phy)) {  		dev_err(&pdev->dev, "Failed to open USB phy\n");  		err = -ENXIO; @@ -755,7 +760,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)  	err = usb_phy_set_suspend(hcd->phy, 0);  	if (err) {  		dev_err(&pdev->dev, "Failed to power on the phy\n"); -		goto fail; +		goto fail_phy;  	}  	tegra->host_resumed = 1; @@ -765,17 +770,17 @@ static int tegra_ehci_probe(struct platform_device *pdev)  	if (!irq) {  		dev_err(&pdev->dev, "Failed to get IRQ\n");  		err = -ENODEV; -		goto fail; +		goto fail_phy;  	} -#ifdef CONFIG_USB_OTG_UTILS  	if (pdata->operating_mode == TEGRA_USB_OTG) {  		tegra->transceiver =  			devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); -		if (!IS_ERR_OR_NULL(tegra->transceiver)) +		if (!IS_ERR(tegra->transceiver))  			otg_set_host(tegra->transceiver->otg, &hcd->self); +	} else { +		tegra->transceiver = ERR_PTR(-ENODEV);  	} -#endif  	err = usb_add_hcd(hcd, irq, IRQF_SHARED);  	if (err) { @@ -794,10 +799,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)  	return err;  fail: -#ifdef CONFIG_USB_OTG_UTILS -	if (!IS_ERR_OR_NULL(tegra->transceiver)) +	if (!IS_ERR(tegra->transceiver))  		otg_set_host(tegra->transceiver->otg, NULL); -#endif +fail_phy:  	usb_phy_shutdown(hcd->phy);  fail_io:  	clk_disable_unprepare(tegra->clk); @@ -815,10 +819,8 @@ static int tegra_ehci_remove(struct platform_device *pdev)  	pm_runtime_disable(&pdev->dev);  	pm_runtime_put_noidle(&pdev->dev); -#ifdef CONFIG_USB_OTG_UTILS -	if (!IS_ERR_OR_NULL(tegra->transceiver)) +	if (!IS_ERR(tegra->transceiver))  		otg_set_host(tegra->transceiver->otg, NULL); -#endif  	usb_phy_shutdown(hcd->phy);  	usb_remove_hcd(hcd); diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index 20dbdcbe9b0..11e5b32f73e 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -113,8 +113,8 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)  	if (want != actual) { -		/* Poll again later, but give up after about 20 ms */ -		if (ehci->ASS_poll_count++ < 20) { +		/* Poll again later, but give up after about 2-4 ms */ +		if (ehci->ASS_poll_count++ < 2) {  			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);  			return;  		} @@ -159,8 +159,8 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)  	if (want != actual) { -		/* Poll again later, but give up after about 20 ms */ -		if (ehci->PSS_poll_count++ < 20) { +		/* Poll again later, but give up after about 2-4 ms */ +		if (ehci->PSS_poll_count++ < 2) {  			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);  			return;  		} @@ -229,18 +229,19 @@ static void ehci_handle_intr_unlinks(struct ehci_hcd *ehci)  	 * process all the QHs on the list.  	 */  	ehci->intr_unlinking = true; -	while (ehci->intr_unlink) { -		struct ehci_qh	*qh = ehci->intr_unlink; +	while (!list_empty(&ehci->intr_unlink)) { +		struct ehci_qh	*qh; +		qh = list_first_entry(&ehci->intr_unlink, struct ehci_qh, +				unlink_node);  		if (!stopped && qh->unlink_cycle == ehci->intr_unlink_cycle)  			break; -		ehci->intr_unlink = qh->unlink_next; -		qh->unlink_next = NULL; +		list_del(&qh->unlink_node);  		end_unlink_intr(ehci, qh);  	}  	/* Handle remaining entries later */ -	if (ehci->intr_unlink) { +	if (!list_empty(&ehci->intr_unlink)) {  		ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true);  		++ehci->intr_unlink_cycle;  	} @@ -295,8 +296,7 @@ static void end_free_itds(struct ehci_hcd *ehci)  /* Handle lost (or very late) IAA interrupts */  static void ehci_iaa_watchdog(struct ehci_hcd *ehci)  { -	if (ehci->rh_state != EHCI_RH_RUNNING) -		return; +	u32 cmd, status;  	/*  	 * Lost IAA irqs wedge things badly; seen first with a vt8235. @@ -304,34 +304,32 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)  	 * (a) SMP races against real IAA firing and retriggering, and  	 * (b) clean HC shutdown, when IAA watchdog was pending.  	 */ -	if (ehci->async_iaa) { -		u32 cmd, status; - -		/* If we get here, IAA is *REALLY* late.  It's barely -		 * conceivable that the system is so busy that CMD_IAAD -		 * is still legitimately set, so let's be sure it's -		 * clear before we read STS_IAA.  (The HC should clear -		 * CMD_IAAD when it sets STS_IAA.) -		 */ -		cmd = ehci_readl(ehci, &ehci->regs->command); +	if (!ehci->iaa_in_progress || ehci->rh_state != EHCI_RH_RUNNING) +		return; -		/* -		 * If IAA is set here it either legitimately triggered -		 * after the watchdog timer expired (_way_ late, so we'll -		 * still count it as lost) ... or a silicon erratum: -		 * - VIA seems to set IAA without triggering the IRQ; -		 * - IAAD potentially cleared without setting IAA. -		 */ -		status = ehci_readl(ehci, &ehci->regs->status); -		if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { -			COUNT(ehci->stats.lost_iaa); -			ehci_writel(ehci, STS_IAA, &ehci->regs->status); -		} +	/* If we get here, IAA is *REALLY* late.  It's barely +	 * conceivable that the system is so busy that CMD_IAAD +	 * is still legitimately set, so let's be sure it's +	 * clear before we read STS_IAA.  (The HC should clear +	 * CMD_IAAD when it sets STS_IAA.) +	 */ +	cmd = ehci_readl(ehci, &ehci->regs->command); -		ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n", -				status, cmd); -		end_unlink_async(ehci); +	/* +	 * If IAA is set here it either legitimately triggered +	 * after the watchdog timer expired (_way_ late, so we'll +	 * still count it as lost) ... or a silicon erratum: +	 * - VIA seems to set IAA without triggering the IRQ; +	 * - IAAD potentially cleared without setting IAA. +	 */ +	status = ehci_readl(ehci, &ehci->regs->status); +	if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { +		COUNT(ehci->stats.lost_iaa); +		ehci_writel(ehci, STS_IAA, &ehci->regs->status);  	} + +	ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd); +	end_unlink_async(ehci);  } diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c deleted file mode 100644 index 7ecf709610b..00000000000 --- a/drivers/usb/host/ehci-vt8500.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * drivers/usb/host/ehci-vt8500.c - * - * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> - * - * Based on ehci-au1xxx.c - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - */ - -#include <linux/err.h> -#include <linux/of.h> -#include <linux/platform_device.h> - -static const struct hc_driver vt8500_ehci_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "VT8500 EHCI", -	.hcd_priv_size		= sizeof(struct ehci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq			= ehci_irq, -	.flags			= HCD_MEMORY | HCD_USB2, - -	/* -	 * basic lifecycle operations -	 */ -	.reset			= ehci_setup, -	.start			= ehci_run, -	.stop			= ehci_stop, -	.shutdown		= ehci_shutdown, - -	/* -	 * managing i/o requests and associated device resources -	 */ -	.urb_enqueue		= ehci_urb_enqueue, -	.urb_dequeue		= ehci_urb_dequeue, -	.endpoint_disable	= ehci_endpoint_disable, -	.endpoint_reset		= ehci_endpoint_reset, - -	/* -	 * scheduling support -	 */ -	.get_frame_number	= ehci_get_frame, - -	/* -	 * root hub support -	 */ -	.hub_status_data	= ehci_hub_status_data, -	.hub_control		= ehci_hub_control, -	.bus_suspend		= ehci_bus_suspend, -	.bus_resume		= ehci_bus_resume, -	.relinquish_port	= ehci_relinquish_port, -	.port_handed_over	= ehci_port_handed_over, - -	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete, -}; - -static u64 vt8500_ehci_dma_mask = DMA_BIT_MASK(32); - -static int vt8500_ehci_drv_probe(struct platform_device *pdev) -{ -	struct usb_hcd *hcd; -	struct ehci_hcd *ehci; -	struct resource *res; -	int ret; - -	if (usb_disabled()) -		return -ENODEV; - -	/* -	 * Right now device-tree probed devices don't get dma_mask set. -	 * Since shared usb code relies on it, set it here for now. -	 * Once we have dma capability bindings this can go away. -	 */ -	if (!pdev->dev.dma_mask) -		pdev->dev.dma_mask = &vt8500_ehci_dma_mask; - -	if (pdev->resource[1].flags != IORESOURCE_IRQ) { -		pr_debug("resource[1] is not IORESOURCE_IRQ"); -		return -ENOMEM; -	} -	hcd = usb_create_hcd(&vt8500_ehci_hc_driver, &pdev->dev, "VT8500"); -	if (!hcd) -		return -ENOMEM; - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	hcd->rsrc_start = res->start; -	hcd->rsrc_len = resource_size(res); - -	hcd->regs = devm_ioremap_resource(&pdev->dev, res); -	if (IS_ERR(hcd->regs)) { -		ret = PTR_ERR(hcd->regs); -		goto err1; -	} - -	ehci = hcd_to_ehci(hcd); -	ehci->caps = hcd->regs; - -	ret = usb_add_hcd(hcd, pdev->resource[1].start, -			  IRQF_SHARED); -	if (ret == 0) { -		platform_set_drvdata(pdev, hcd); -		return ret; -	} - -err1: -	usb_put_hcd(hcd); -	return ret; -} - -static int vt8500_ehci_drv_remove(struct platform_device *pdev) -{ -	struct usb_hcd *hcd = platform_get_drvdata(pdev); - -	usb_remove_hcd(hcd); -	usb_put_hcd(hcd); -	platform_set_drvdata(pdev, NULL); - -	return 0; -} - -static const struct of_device_id vt8500_ehci_ids[] = { -	{ .compatible = "via,vt8500-ehci", }, -	{ .compatible = "wm,prizm-ehci", }, -	{} -}; - -static struct platform_driver vt8500_ehci_driver = { -	.probe		= vt8500_ehci_drv_probe, -	.remove		= vt8500_ehci_drv_remove, -	.shutdown	= usb_hcd_platform_shutdown, -	.driver = { -		.name	= "vt8500-ehci", -		.owner	= THIS_MODULE, -		.of_match_table = of_match_ptr(vt8500_ehci_ids), -	} -}; - -MODULE_ALIAS("platform:vt8500-ehci"); -MODULE_DEVICE_TABLE(of, vt8500_ehci_ids); diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 36c3a821059..7c978b23520 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -121,6 +121,7 @@ struct ehci_hcd {			/* one per controller */  	bool			scanning:1;  	bool			need_rescan:1;  	bool			intr_unlinking:1; +	bool			iaa_in_progress:1;  	bool			async_unlinking:1;  	bool			shutdown:1;  	struct ehci_qh		*qh_scan_next; @@ -128,9 +129,8 @@ struct ehci_hcd {			/* one per controller */  	/* async schedule support */  	struct ehci_qh		*async;  	struct ehci_qh		*dummy;		/* For AMD quirk use */ -	struct ehci_qh		*async_unlink; -	struct ehci_qh		*async_unlink_last; -	struct ehci_qh		*async_iaa; +	struct list_head	async_unlink; +	struct list_head	async_idle;  	unsigned		async_unlink_cycle;  	unsigned		async_count;	/* async activity count */ @@ -143,8 +143,7 @@ struct ehci_hcd {			/* one per controller */  	unsigned		i_thresh;	/* uframes HC might cache */  	union ehci_shadow	*pshadow;	/* mirror hw periodic table */ -	struct ehci_qh		*intr_unlink; -	struct ehci_qh		*intr_unlink_last; +	struct list_head	intr_unlink;  	unsigned		intr_unlink_cycle;  	unsigned		now_frame;	/* frame from HC hardware */  	unsigned		last_iso_frame;	/* last frame scanned for iso */ @@ -200,6 +199,7 @@ struct ehci_hcd {			/* one per controller */  	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/  	unsigned		has_synopsys_hc_bug:1; /* Synopsys HC */  	unsigned		frame_index_bug:1; /* MosChip (AKA NetMos) */ +	unsigned		need_oc_pp_cycle:1; /* MPC834X port power */  	/* required for usb32 quirk */  	#define OHCI_CTRL_HCFS          (3 << 6) @@ -380,11 +380,10 @@ struct ehci_qh {  	struct list_head	qtd_list;	/* sw qtd list */  	struct list_head	intr_node;	/* list of intr QHs */  	struct ehci_qtd		*dummy; -	struct ehci_qh		*unlink_next;	/* next on unlink list */ +	struct list_head	unlink_node;  	unsigned		unlink_cycle; -	u8			needs_rescan;	/* Dequeue during giveback */  	u8			qh_state;  #define	QH_STATE_LINKED		1		/* HC sees this */  #define	QH_STATE_UNLINK		2		/* HC may still see this */ @@ -407,6 +406,9 @@ struct ehci_qh {  	struct usb_device	*dev;		/* access to TT */  	unsigned		is_out:1;	/* bulk or intr OUT */  	unsigned		clearing_tt:1;	/* Clear-TT-Buf in progress */ +	unsigned		dequeue_during_giveback:1; +	unsigned		exception:1;	/* got a fault, or an unlink +						   was requested */  };  /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index e3b7e85120e..114583a8e92 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -17,7 +17,6 @@  #include <linux/platform_data/usb-exynos.h>  #include <linux/usb/phy.h>  #include <linux/usb/samsung_usb_phy.h> -#include <plat/usb-phy.h>  struct exynos_ohci_hcd {  	struct device *dev; @@ -34,7 +33,7 @@ static void exynos_ohci_phy_enable(struct exynos_ohci_hcd *exynos_ohci)  	if (exynos_ohci->phy)  		usb_phy_init(exynos_ohci->phy); -	else if (exynos_ohci->pdata->phy_init) +	else if (exynos_ohci->pdata && exynos_ohci->pdata->phy_init)  		exynos_ohci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);  } @@ -44,7 +43,7 @@ static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci)  	if (exynos_ohci->phy)  		usb_phy_shutdown(exynos_ohci->phy); -	else if (exynos_ohci->pdata->phy_exit) +	else if (exynos_ohci->pdata && exynos_ohci->pdata->phy_exit)  		exynos_ohci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);  } @@ -127,8 +126,12 @@ static int exynos_ohci_probe(struct platform_device *pdev)  	if (!exynos_ohci)  		return -ENOMEM; +	if (of_device_is_compatible(pdev->dev.of_node, +					"samsung,exynos5440-ohci")) +		goto skip_phy; +  	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); -	if (IS_ERR_OR_NULL(phy)) { +	if (IS_ERR(phy)) {  		/* Fallback to pdata */  		if (!pdata) {  			dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); @@ -141,6 +144,8 @@ static int exynos_ohci_probe(struct platform_device *pdev)  		exynos_ohci->otg = phy->otg;  	} +skip_phy: +  	exynos_ohci->dev = &pdev->dev;  	hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev, @@ -311,6 +316,7 @@ static const struct dev_pm_ops exynos_ohci_pm_ops = {  #ifdef CONFIG_OF  static const struct of_device_id exynos_ohci_match[] = {  	{ .compatible = "samsung,exynos4210-ohci" }, +	{ .compatible = "samsung,exynos5440-ohci" },  	{},  };  MODULE_DEVICE_TABLE(of, exynos_ohci_match); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 180a2b01db5..9e6de9586ae 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1102,12 +1102,12 @@ MODULE_LICENSE ("GPL");  #if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX)  #include "ohci-s3c2410.c" -#define PLATFORM_DRIVER		ohci_hcd_s3c2410_driver +#define S3C2410_PLATFORM_DRIVER	ohci_hcd_s3c2410_driver  #endif  #ifdef CONFIG_USB_OHCI_EXYNOS  #include "ohci-exynos.c" -#define PLATFORM_DRIVER		exynos_ohci_driver +#define EXYNOS_PLATFORM_DRIVER	exynos_ohci_driver  #endif  #ifdef CONFIG_USB_OHCI_HCD_OMAP1 @@ -1127,25 +1127,24 @@ MODULE_LICENSE ("GPL");  #ifdef CONFIG_ARCH_EP93XX  #include "ohci-ep93xx.c" -#define PLATFORM_DRIVER		ohci_hcd_ep93xx_driver +#define EP93XX_PLATFORM_DRIVER	ohci_hcd_ep93xx_driver  #endif  #ifdef CONFIG_ARCH_AT91  #include "ohci-at91.c" -#define PLATFORM_DRIVER		ohci_hcd_at91_driver +#define AT91_PLATFORM_DRIVER	ohci_hcd_at91_driver  #endif  #ifdef CONFIG_ARCH_LPC32XX  #include "ohci-nxp.c" -#define PLATFORM_DRIVER		usb_hcd_nxp_driver +#define NXP_PLATFORM_DRIVER	usb_hcd_nxp_driver  #endif  #ifdef CONFIG_ARCH_DAVINCI_DA8XX  #include "ohci-da8xx.c" -#define PLATFORM_DRIVER		ohci_hcd_da8xx_driver +#define DAVINCI_PLATFORM_DRIVER	ohci_hcd_da8xx_driver  #endif -  #ifdef CONFIG_USB_OHCI_HCD_PPC_OF  #include "ohci-ppc-of.c"  #define OF_PLATFORM_DRIVER	ohci_hcd_ppc_of_driver @@ -1153,7 +1152,7 @@ MODULE_LICENSE ("GPL");  #ifdef CONFIG_PLAT_SPEAR  #include "ohci-spear.c" -#define PLATFORM_DRIVER		spear_ohci_hcd_driver +#define SPEAR_PLATFORM_DRIVER	spear_ohci_hcd_driver  #endif  #ifdef CONFIG_PPC_PS3 @@ -1199,7 +1198,14 @@ MODULE_LICENSE ("GPL");  	!defined(SA1111_DRIVER) &&	\  	!defined(PS3_SYSTEM_BUS_DRIVER) && \  	!defined(SM501_OHCI_DRIVER) && \ -	!defined(TMIO_OHCI_DRIVER) +	!defined(TMIO_OHCI_DRIVER) && \ +	!defined(S3C2410_PLATFORM_DRIVER) && \ +	!defined(EXYNOS_PLATFORM_DRIVER) && \ +	!defined(EP93XX_PLATFORM_DRIVER) && \ +	!defined(AT91_PLATFORM_DRIVER) && \ +	!defined(NXP_PLATFORM_DRIVER) && \ +	!defined(DAVINCI_PLATFORM_DRIVER) && \ +	!defined(SPEAR_PLATFORM_DRIVER)  #error "missing bus glue for ohci-hcd"  #endif @@ -1277,9 +1283,79 @@ static int __init ohci_hcd_mod_init(void)  		goto error_tmio;  #endif +#ifdef S3C2410_PLATFORM_DRIVER +	retval = platform_driver_register(&S3C2410_PLATFORM_DRIVER); +	if (retval < 0) +		goto error_s3c2410; +#endif + +#ifdef EXYNOS_PLATFORM_DRIVER +	retval = platform_driver_register(&EXYNOS_PLATFORM_DRIVER); +	if (retval < 0) +		goto error_exynos; +#endif + +#ifdef EP93XX_PLATFORM_DRIVER +	retval = platform_driver_register(&EP93XX_PLATFORM_DRIVER); +	if (retval < 0) +		goto error_ep93xx; +#endif + +#ifdef AT91_PLATFORM_DRIVER +	retval = platform_driver_register(&AT91_PLATFORM_DRIVER); +	if (retval < 0) +		goto error_at91; +#endif + +#ifdef NXP_PLATFORM_DRIVER +	retval = platform_driver_register(&NXP_PLATFORM_DRIVER); +	if (retval < 0) +		goto error_nxp; +#endif + +#ifdef DAVINCI_PLATFORM_DRIVER +	retval = platform_driver_register(&DAVINCI_PLATFORM_DRIVER); +	if (retval < 0) +		goto error_davinci; +#endif + +#ifdef SPEAR_PLATFORM_DRIVER +	retval = platform_driver_register(&SPEAR_PLATFORM_DRIVER); +	if (retval < 0) +		goto error_spear; +#endif +  	return retval;  	/* Error path */ +#ifdef SPEAR_PLATFORM_DRIVER +	platform_driver_unregister(&SPEAR_PLATFORM_DRIVER); + error_spear: +#endif +#ifdef DAVINCI_PLATFORM_DRIVER +	platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); + error_davinci: +#endif +#ifdef NXP_PLATFORM_DRIVER +	platform_driver_unregister(&NXP_PLATFORM_DRIVER); + error_nxp: +#endif +#ifdef AT91_PLATFORM_DRIVER +	platform_driver_unregister(&AT91_PLATFORM_DRIVER); + error_at91: +#endif +#ifdef EP93XX_PLATFORM_DRIVER +	platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); + error_ep93xx: +#endif +#ifdef EXYNOS_PLATFORM_DRIVER +	platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER); + error_exynos: +#endif +#ifdef S3C2410_PLATFORM_DRIVER +	platform_driver_unregister(&S3C2410_PLATFORM_DRIVER); + error_s3c2410: +#endif  #ifdef TMIO_OHCI_DRIVER  	platform_driver_unregister(&TMIO_OHCI_DRIVER);   error_tmio: @@ -1300,17 +1376,17 @@ static int __init ohci_hcd_mod_init(void)  	platform_driver_unregister(&OF_PLATFORM_DRIVER);   error_of_platform:  #endif -#ifdef PLATFORM_DRIVER -	platform_driver_unregister(&PLATFORM_DRIVER); - error_platform: +#ifdef OMAP3_PLATFORM_DRIVER +	platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); + error_omap3_platform:  #endif  #ifdef OMAP1_PLATFORM_DRIVER  	platform_driver_unregister(&OMAP1_PLATFORM_DRIVER);   error_omap1_platform:  #endif -#ifdef OMAP3_PLATFORM_DRIVER -	platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); - error_omap3_platform: +#ifdef PLATFORM_DRIVER +	platform_driver_unregister(&PLATFORM_DRIVER); + error_platform:  #endif  #ifdef PS3_SYSTEM_BUS_DRIVER  	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); @@ -1329,6 +1405,27 @@ module_init(ohci_hcd_mod_init);  static void __exit ohci_hcd_mod_exit(void)  { +#ifdef SPEAR_PLATFORM_DRIVER +	platform_driver_unregister(&SPEAR_PLATFORM_DRIVER); +#endif +#ifdef DAVINCI_PLATFORM_DRIVER +	platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); +#endif +#ifdef NXP_PLATFORM_DRIVER +	platform_driver_unregister(&NXP_PLATFORM_DRIVER); +#endif +#ifdef AT91_PLATFORM_DRIVER +	platform_driver_unregister(&AT91_PLATFORM_DRIVER); +#endif +#ifdef EP93XX_PLATFORM_DRIVER +	platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); +#endif +#ifdef EXYNOS_PLATFORM_DRIVER +	platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER); +#endif +#ifdef S3C2410_PLATFORM_DRIVER +	platform_driver_unregister(&S3C2410_PLATFORM_DRIVER); +#endif  #ifdef TMIO_OHCI_DRIVER  	platform_driver_unregister(&TMIO_OHCI_DRIVER);  #endif @@ -1344,12 +1441,15 @@ static void __exit ohci_hcd_mod_exit(void)  #ifdef OF_PLATFORM_DRIVER  	platform_driver_unregister(&OF_PLATFORM_DRIVER);  #endif -#ifdef PLATFORM_DRIVER -	platform_driver_unregister(&PLATFORM_DRIVER); -#endif  #ifdef OMAP3_PLATFORM_DRIVER  	platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);  #endif +#ifdef OMAP1_PLATFORM_DRIVER +	platform_driver_unregister(&OMAP1_PLATFORM_DRIVER); +#endif +#ifdef PLATFORM_DRIVER +	platform_driver_unregister(&PLATFORM_DRIVER); +#endif  #ifdef PS3_SYSTEM_BUS_DRIVER  	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);  #endif diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index db09dae7b55..60ff4220e8b 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -580,14 +580,8 @@ static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)  /* See usb 7.1.7.5:  root hubs must issue at least 50 msec reset signaling,   * not necessarily continuous ... to guard against resume signaling. - * The short timeout is safe for non-root hubs, and is backward-compatible - * with earlier Linux hosts.   */ -#ifdef	CONFIG_USB_SUSPEND  #define	PORT_RESET_MSEC		50 -#else -#define	PORT_RESET_MSEC		10 -#endif  /* this timer value might be vendor-specific ... */  #define	PORT_RESET_HW_MSEC	10 diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c index eb35d963023..ddfc31427bc 100644 --- a/drivers/usb/host/ohci-omap3.c +++ b/drivers/usb/host/ohci-omap3.c @@ -31,6 +31,8 @@  #include <linux/platform_device.h>  #include <linux/pm_runtime.h> +#include <linux/of.h> +#include <linux/dma-mapping.h>  /*-------------------------------------------------------------------------*/ @@ -112,6 +114,8 @@ static const struct hc_driver ohci_omap3_hc_driver = {  /*-------------------------------------------------------------------------*/ +static u64 omap_ohci_dma_mask = DMA_BIT_MASK(32); +  /*   * configure so an HC device and id are always provided   * always called with process context; sleeping is OK @@ -141,14 +145,13 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)  		return -ENODEV;  	} -	irq = platform_get_irq_byname(pdev, "ohci-irq"); +	irq = platform_get_irq(pdev, 0);  	if (irq < 0) {  		dev_err(dev, "OHCI irq failed\n");  		return -ENODEV;  	} -	res = platform_get_resource_byname(pdev, -				IORESOURCE_MEM, "ohci"); +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) {  		dev_err(dev, "UHH OHCI get resource failed\n");  		return -ENOMEM; @@ -160,6 +163,13 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)  		return -ENOMEM;  	} +	/* +	 * Right now device-tree probed devices don't get dma_mask set. +	 * Since shared usb code relies on it, set it here for now. +	 * Once we have dma capability bindings this can go away. +	 */ +	if (!pdev->dev.dma_mask) +		pdev->dev.dma_mask = &omap_ohci_dma_mask;  	hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev,  			dev_name(dev)); @@ -229,12 +239,20 @@ static void ohci_hcd_omap3_shutdown(struct platform_device *pdev)  		hcd->driver->shutdown(hcd);  } +static const struct of_device_id omap_ohci_dt_ids[] = { +	{ .compatible = "ti,ohci-omap3" }, +	{ } +}; + +MODULE_DEVICE_TABLE(of, omap_ohci_dt_ids); +  static struct platform_driver ohci_hcd_omap3_driver = {  	.probe		= ohci_hcd_omap3_probe,  	.remove		= ohci_hcd_omap3_remove,  	.shutdown	= ohci_hcd_omap3_shutdown,  	.driver		= {  		.name	= "ohci-omap3", +		.of_match_table = of_match_ptr(omap_ohci_dt_ids),  	},  }; diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index d62f0404baa..15ed7e8d887 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -1755,7 +1755,7 @@ sl811h_probe(struct platform_device *dev)  /* for this device there's no useful distinction between the controller   * and its root hub, except that the root hub only gets direct PM calls - * when CONFIG_USB_SUSPEND is enabled. + * when CONFIG_PM_RUNTIME is enabled.   */  static int diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 3b6f50eaec9..469564e57a5 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -200,17 +200,4 @@ static struct pcmcia_driver sl811_cs_driver = {  	.remove		= sl811_cs_detach,  	.id_table	= sl811_ids,  }; - -/*====================================================================*/ - -static int __init init_sl811_cs(void) -{ -	return pcmcia_register_driver(&sl811_cs_driver); -} -module_init(init_sl811_cs); - -static void __exit exit_sl811_cs(void) -{ -	pcmcia_unregister_driver(&sl811_cs_driver); -} -module_exit(exit_sl811_cs); +module_pcmcia_driver(sl811_cs_driver); diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 5efdffe3236..5c124bf5d01 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -3141,10 +3141,11 @@ static int u132_probe(struct platform_device *pdev)  #ifdef CONFIG_PM -/* for this device there's no useful distinction between the controller -* and its root hub, except that the root hub only gets direct PM calls -* when CONFIG_USB_SUSPEND is enabled. -*/ +/* + * for this device there's no useful distinction between the controller + * and its root hub, except that the root hub only gets direct PM calls + * when CONFIG_PM_RUNTIME is enabled. + */  static int u132_suspend(struct platform_device *pdev, pm_message_t state)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev); diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 68914429482..187a3ec1069 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1075,7 +1075,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)  			set_bit(port_index, &bus_state->bus_suspended);  		}  		/* USB core sets remote wake mask for USB 3.0 hubs, -		 * including the USB 3.0 roothub, but only if CONFIG_USB_SUSPEND +		 * including the USB 3.0 roothub, but only if CONFIG_PM_RUNTIME  		 * is enabled, so also enable remote wake here.  		 */  		if (hcd->self.root_hub->do_remote_wakeup) { diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 35616ffbe3a..965b539bc47 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -51,7 +51,7 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci,  		return NULL;  	} -	memset(seg->trbs, 0, SEGMENT_SIZE); +	memset(seg->trbs, 0, TRB_SEGMENT_SIZE);  	/* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */  	if (cycle_state == 0) {  		for (i = 0; i < TRBS_PER_SEGMENT; i++) @@ -467,7 +467,7 @@ struct xhci_ring *xhci_dma_to_transfer_ring(  {  	if (ep->ep_state & EP_HAS_STREAMS)  		return radix_tree_lookup(&ep->stream_info->trb_address_map, -				address >> SEGMENT_SHIFT); +				address >> TRB_SEGMENT_SHIFT);  	return ep->ring;  } @@ -478,7 +478,7 @@ static struct xhci_ring *dma_to_stream_ring(  		u64 address)  {  	return radix_tree_lookup(&stream_info->trb_address_map, -			address >> SEGMENT_SHIFT); +			address >> TRB_SEGMENT_SHIFT);  }  #endif	/* CONFIG_USB_XHCI_HCD_DEBUGGING */ @@ -514,7 +514,7 @@ static int xhci_test_radix_tree(struct xhci_hcd *xhci,  		cur_ring = stream_info->stream_rings[cur_stream];  		for (addr = cur_ring->first_seg->dma; -				addr < cur_ring->first_seg->dma + SEGMENT_SIZE; +				addr < cur_ring->first_seg->dma + TRB_SEGMENT_SIZE;  				addr += trb_size) {  			mapped_ring = dma_to_stream_ring(stream_info, addr);  			if (cur_ring != mapped_ring) { @@ -662,7 +662,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,  				cur_stream, (unsigned long long) addr);  		key = (unsigned long) -			(cur_ring->first_seg->dma >> SEGMENT_SHIFT); +			(cur_ring->first_seg->dma >> TRB_SEGMENT_SHIFT);  		ret = radix_tree_insert(&stream_info->trb_address_map,  				key, cur_ring);  		if (ret) { @@ -693,7 +693,7 @@ cleanup_rings:  		if (cur_ring) {  			addr = cur_ring->first_seg->dma;  			radix_tree_delete(&stream_info->trb_address_map, -					addr >> SEGMENT_SHIFT); +					addr >> TRB_SEGMENT_SHIFT);  			xhci_ring_free(xhci, cur_ring);  			stream_info->stream_rings[cur_stream] = NULL;  		} @@ -764,7 +764,7 @@ void xhci_free_stream_info(struct xhci_hcd *xhci,  		if (cur_ring) {  			addr = cur_ring->first_seg->dma;  			radix_tree_delete(&stream_info->trb_address_map, -					addr >> SEGMENT_SHIFT); +					addr >> TRB_SEGMENT_SHIFT);  			xhci_ring_free(xhci, cur_ring);  			stream_info->stream_rings[cur_stream] = NULL;  		} @@ -1022,44 +1022,24 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,   * is attached to (or the roothub port its ancestor hub is attached to).  All we   * know is the index of that port under either the USB 2.0 or the USB 3.0   * roothub, but that doesn't give us the real index into the HW port status - * registers.  Scan through the xHCI roothub port array, looking for the Nth - * entry of the correct port speed.  Return the port number of that entry. + * registers. Call xhci_find_raw_port_number() to get real index.   */  static u32 xhci_find_real_port_number(struct xhci_hcd *xhci,  		struct usb_device *udev)  {  	struct usb_device *top_dev; -	unsigned int num_similar_speed_ports; -	unsigned int faked_port_num; -	int i; +	struct usb_hcd *hcd; + +	if (udev->speed == USB_SPEED_SUPER) +		hcd = xhci->shared_hcd; +	else +		hcd = xhci->main_hcd;  	for (top_dev = udev; top_dev->parent && top_dev->parent->parent;  			top_dev = top_dev->parent)  		/* Found device below root hub */; -	faked_port_num = top_dev->portnum; -	for (i = 0, num_similar_speed_ports = 0; -			i < HCS_MAX_PORTS(xhci->hcs_params1); i++) { -		u8 port_speed = xhci->port_array[i]; - -		/* -		 * Skip ports that don't have known speeds, or have duplicate -		 * Extended Capabilities port speed entries. -		 */ -		if (port_speed == 0 || port_speed == DUPLICATE_ENTRY) -			continue; -		/* -		 * USB 3.0 ports are always under a USB 3.0 hub.  USB 2.0 and -		 * 1.1 ports are under the USB 2.0 hub.  If the port speed -		 * matches the device speed, it's a similar speed port. -		 */ -		if ((port_speed == 0x03) == (udev->speed == USB_SPEED_SUPER)) -			num_similar_speed_ports++; -		if (num_similar_speed_ports == faked_port_num) -			/* Roothub ports are numbered from 1 to N */ -			return i+1; -	} -	return 0; +	return	xhci_find_raw_port_number(hcd, top_dev->portnum);  }  /* Setup an xHCI virtual device for a Set Address command */ @@ -2325,7 +2305,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)  	 * so we pick the greater alignment need.  	 */  	xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, -			SEGMENT_SIZE, 64, xhci->page_size); +			TRB_SEGMENT_SIZE, 64, xhci->page_size);  	/* See Table 46 and Note on Figure 55 */  	xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev, diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index af259e0ec17..1a30c380043 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -313,6 +313,7 @@ static const struct hc_driver xhci_pci_hc_driver = {  	.set_usb2_hw_lpm =	xhci_set_usb2_hardware_lpm,  	.enable_usb3_lpm_timeout =	xhci_enable_usb3_lpm_timeout,  	.disable_usb3_lpm_timeout =	xhci_disable_usb3_lpm_timeout, +	.find_raw_port_number =	xhci_find_raw_port_number,  };  /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 88287546530..1969c001b3f 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1599,14 +1599,20 @@ static void handle_port_status(struct xhci_hcd *xhci,  	max_ports = HCS_MAX_PORTS(xhci->hcs_params1);  	if ((port_id <= 0) || (port_id > max_ports)) {  		xhci_warn(xhci, "Invalid port id %d\n", port_id); -		bogus_port_status = true; -		goto cleanup; +		inc_deq(xhci, xhci->event_ring); +		return;  	}  	/* Figure out which usb_hcd this port is attached to:  	 * is it a USB 3.0 port or a USB 2.0/1.1 port?  	 */  	major_revision = xhci->port_array[port_id - 1]; + +	/* Find the right roothub. */ +	hcd = xhci_to_hcd(xhci); +	if ((major_revision == 0x03) != (hcd->speed == HCD_USB3)) +		hcd = xhci->shared_hcd; +  	if (major_revision == 0) {  		xhci_warn(xhci, "Event for port %u not in "  				"Extended Capabilities, ignoring.\n", @@ -1629,10 +1635,6 @@ static void handle_port_status(struct xhci_hcd *xhci,  	 * into the index into the ports on the correct split roothub, and the  	 * correct bus_state structure.  	 */ -	/* Find the right roothub. */ -	hcd = xhci_to_hcd(xhci); -	if ((major_revision == 0x03) != (hcd->speed == HCD_USB3)) -		hcd = xhci->shared_hcd;  	bus_state = &xhci->bus_state[hcd_index(hcd)];  	if (hcd->speed == HCD_USB3)  		port_array = xhci->usb3_ports; @@ -2027,8 +2029,8 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,  		if (event_trb != ep_ring->dequeue &&  				event_trb != td->last_trb)  			td->urb->actual_length = -				td->urb->transfer_buffer_length -				- TRB_LEN(le32_to_cpu(event->transfer_len)); +				td->urb->transfer_buffer_length - +				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));  		else  			td->urb->actual_length = 0; @@ -2060,7 +2062,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,  		/* Maybe the event was for the data stage? */  			td->urb->actual_length =  				td->urb->transfer_buffer_length - -				TRB_LEN(le32_to_cpu(event->transfer_len)); +				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));  			xhci_dbg(xhci, "Waiting for status "  					"stage event\n");  			return 0; @@ -2096,7 +2098,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,  	/* handle completion code */  	switch (trb_comp_code) {  	case COMP_SUCCESS: -		if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) { +		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {  			frame->status = 0;  			break;  		} @@ -2141,7 +2143,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,  				len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));  		}  		len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - -			TRB_LEN(le32_to_cpu(event->transfer_len)); +			EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));  		if (trb_comp_code != COMP_STOP_INVAL) {  			frame->actual_length = len; @@ -2199,7 +2201,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,  	case COMP_SUCCESS:  		/* Double check that the HW transferred everything. */  		if (event_trb != td->last_trb || -				TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { +		    EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {  			xhci_warn(xhci, "WARN Successful completion "  					"on short TX\n");  			if (td->urb->transfer_flags & URB_SHORT_NOT_OK) @@ -2227,18 +2229,18 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,  				"%d bytes untransferred\n",  				td->urb->ep->desc.bEndpointAddress,  				td->urb->transfer_buffer_length, -				TRB_LEN(le32_to_cpu(event->transfer_len))); +				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));  	/* Fast path - was this the last TRB in the TD for this URB? */  	if (event_trb == td->last_trb) { -		if (TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { +		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {  			td->urb->actual_length =  				td->urb->transfer_buffer_length - -				TRB_LEN(le32_to_cpu(event->transfer_len)); +				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));  			if (td->urb->transfer_buffer_length <  					td->urb->actual_length) {  				xhci_warn(xhci, "HC gave bad length "  						"of %d bytes left\n", -					  TRB_LEN(le32_to_cpu(event->transfer_len))); +					  EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));  				td->urb->actual_length = 0;  				if (td->urb->transfer_flags & URB_SHORT_NOT_OK)  					*status = -EREMOTEIO; @@ -2280,7 +2282,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,  		if (trb_comp_code != COMP_STOP_INVAL)  			td->urb->actual_length +=  				TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - -				TRB_LEN(le32_to_cpu(event->transfer_len)); +				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));  	}  	return finish_td(xhci, td, event_trb, event, ep, status, false); @@ -2368,7 +2370,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,  	 * transfer type  	 */  	case COMP_SUCCESS: -		if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) +		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)  			break;  		if (xhci->quirks & XHCI_TRUST_TX_LENGTH)  			trb_comp_code = COMP_SHORT_TX; @@ -2461,14 +2463,21 @@ static int handle_tx_event(struct xhci_hcd *xhci,  		 * TD list.  		 */  		if (list_empty(&ep_ring->td_list)) { -			xhci_warn(xhci, "WARN Event TRB for slot %d ep %d " -					"with no TDs queued?\n", -				  TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), -				  ep_index); -			xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", -				 (le32_to_cpu(event->flags) & -				  TRB_TYPE_BITMASK)>>10); -			xhci_print_trb_offsets(xhci, (union xhci_trb *) event); +			/* +			 * A stopped endpoint may generate an extra completion +			 * event if the device was suspended.  Don't print +			 * warnings. +			 */ +			if (!(trb_comp_code == COMP_STOP || +						trb_comp_code == COMP_STOP_INVAL)) { +				xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n", +						TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), +						ep_index); +				xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", +						(le32_to_cpu(event->flags) & +						 TRB_TYPE_BITMASK)>>10); +				xhci_print_trb_offsets(xhci, (union xhci_trb *) event); +			}  			if (ep->skip) {  				ep->skip = false;  				xhci_dbg(xhci, "td_list is empty while skip " diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index f1f01a834ba..b4aa79d154b 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -350,7 +350,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)  	 * generate interrupts.  Don't even try to enable MSI.  	 */  	if (xhci->quirks & XHCI_BROKEN_MSI) -		return 0; +		goto legacy_irq;  	/* unregister the legacy interrupt */  	if (hcd->irq) @@ -371,6 +371,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)  		return -EINVAL;  	} + legacy_irq:  	/* fall back to legacy interrupt*/  	ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,  			hcd->irq_descr, hcd); @@ -416,9 +417,9 @@ static void compliance_mode_recovery(unsigned long arg)  			 * Compliance Mode Detected. Letting USB Core  			 * handle the Warm Reset  			 */ -			xhci_dbg(xhci, "Compliance Mode Detected->Port %d!\n", +			xhci_dbg(xhci, "Compliance mode detected->port %d\n",  					i + 1); -			xhci_dbg(xhci, "Attempting Recovery routine!\n"); +			xhci_dbg(xhci, "Attempting compliance mode recovery\n");  			hcd = xhci->shared_hcd;  			if (hcd->state == HC_STATE_SUSPENDED) @@ -456,7 +457,7 @@ static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci)  	set_timer_slack(&xhci->comp_mode_recovery_timer,  			msecs_to_jiffies(COMP_MODE_RCVRY_MSECS));  	add_timer(&xhci->comp_mode_recovery_timer); -	xhci_dbg(xhci, "Compliance Mode Recovery Timer Initialized.\n"); +	xhci_dbg(xhci, "Compliance mode recovery timer initialized\n");  }  /* @@ -732,8 +733,11 @@ void xhci_stop(struct usb_hcd *hcd)  	/* Deleting Compliance Mode Recovery Timer */  	if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && -			(!(xhci_all_ports_seen_u0(xhci)))) +			(!(xhci_all_ports_seen_u0(xhci)))) {  		del_timer_sync(&xhci->comp_mode_recovery_timer); +		xhci_dbg(xhci, "%s: compliance mode recovery timer deleted\n", +				__func__); +	}  	if (xhci->quirks & XHCI_AMD_PLL_FIX)  		usb_amd_dev_put(); @@ -929,7 +933,8 @@ int xhci_suspend(struct xhci_hcd *xhci)  	if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&  			(!(xhci_all_ports_seen_u0(xhci)))) {  		del_timer_sync(&xhci->comp_mode_recovery_timer); -		xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted!\n"); +		xhci_dbg(xhci, "%s: compliance mode recovery timer deleted\n", +				__func__);  	}  	/* step 5: remove core well power */ @@ -3778,7 +3783,29 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)  	return 0;  } -#ifdef CONFIG_USB_SUSPEND +/* + * Transfer the port index into real index in the HW port status + * registers. Caculate offset between the port's PORTSC register + * and port status base. Divide the number of per port register + * to get the real index. The raw port number bases 1. + */ +int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1) +{ +	struct xhci_hcd *xhci = hcd_to_xhci(hcd); +	__le32 __iomem *base_addr = &xhci->op_regs->port_status_base; +	__le32 __iomem *addr; +	int raw_port; + +	if (hcd->speed != HCD_USB3) +		addr = xhci->usb2_ports[port1 - 1]; +	else +		addr = xhci->usb3_ports[port1 - 1]; + +	raw_port = (addr - base_addr)/NUM_PORT_REGS + 1; +	return raw_port; +} + +#ifdef CONFIG_PM_RUNTIME  /* BESL to HIRD Encoding array for USB2 LPM */  static int xhci_besl_encoding[16] = {125, 150, 200, 300, 400, 500, 1000, 2000, @@ -4028,7 +4055,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)  	return 0;  } -#endif /* CONFIG_USB_SUSPEND */ +#endif /* CONFIG_PM_RUNTIME */  /*---------------------- USB 3.0 Link PM functions ------------------------*/ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index f791bd0aee6..29c978e3713 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -206,8 +206,8 @@ struct xhci_op_regs {  /* bits 12:31 are reserved (and should be preserved on writes). */  /* IMAN - Interrupt Management Register */ -#define IMAN_IP		(1 << 1) -#define IMAN_IE		(1 << 0) +#define IMAN_IE		(1 << 1) +#define IMAN_IP		(1 << 0)  /* USBSTS - USB status - status bitmasks */  /* HC not running - set to 1 when run/stop bit is cleared. */ @@ -972,6 +972,10 @@ struct xhci_transfer_event {  	__le32	flags;  }; +/* Transfer event TRB length bit mask */ +/* bits 0:23 */ +#define	EVENT_TRB_LEN(p)		((p) & 0xffffff) +  /** Transfer Event bit fields **/  #define	TRB_TO_EP_ID(p)	(((p) >> 16) & 0x1f) @@ -1234,8 +1238,8 @@ union xhci_trb {  #define TRBS_PER_SEGMENT	64  /* Allow two commands + a link TRB, along with any reserved command TRBs */  #define MAX_RSVD_CMD_TRBS	(TRBS_PER_SEGMENT - 3) -#define SEGMENT_SIZE		(TRBS_PER_SEGMENT*16) -#define SEGMENT_SHIFT		(__ffs(SEGMENT_SIZE)) +#define TRB_SEGMENT_SIZE	(TRBS_PER_SEGMENT*16) +#define TRB_SEGMENT_SHIFT	(ilog2(TRB_SEGMENT_SIZE))  /* TRB buffer pointers can't cross 64KB boundaries */  #define TRB_MAX_BUFF_SHIFT		16  #define TRB_MAX_BUFF_SIZE	(1 << TRB_MAX_BUFF_SHIFT) @@ -1829,6 +1833,7 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,  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_find_raw_port_number(struct usb_hcd *hcd, int port1);  #ifdef CONFIG_PM  int xhci_bus_suspend(struct usb_hcd *hcd); diff --git a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig index 33350f9dd34..320d368c8da 100644 --- a/drivers/usb/image/Kconfig +++ b/drivers/usb/image/Kconfig @@ -2,11 +2,9 @@  # USB Imaging devices configuration  #  comment "USB Imaging devices" -	depends on USB  config USB_MDC800  	tristate "USB Mustek MDC800 Digital Camera support" -	depends on USB  	---help---  	  Say Y here if you want to connect this type of still camera to  	  your computer's USB port. This driver can be used with gphoto 0.4.3 @@ -19,7 +17,7 @@ config USB_MDC800  config USB_MICROTEK  	tristate "Microtek X6USB scanner support" -	depends on USB && SCSI +	depends on SCSI  	help  	  Say Y here if you want support for the Microtek X6USB and  	  possibly the Phantom 336CX, Phantom C6 and ScanMaker V6U(S)L. diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 3b1a3f4ec5e..a51e7d6afda 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -2,11 +2,9 @@  # USB Miscellaneous driver configuration  #  comment "USB Miscellaneous drivers" -	depends on USB  config USB_EMI62  	tristate "EMI 6|2m USB Audio interface support" -	depends on USB  	---help---  	  This driver loads firmware to Emagic EMI 6|2m low latency USB  	  Audio and Midi interface. @@ -21,7 +19,6 @@ config USB_EMI62  config USB_EMI26  	tristate "EMI 2|6 USB Audio interface support" -	depends on USB  	---help---  	  This driver loads firmware to Emagic EMI 2|6 low latency USB  	  Audio interface. @@ -34,7 +31,6 @@ config USB_EMI26  config USB_ADUTUX  	tristate "ADU devices from Ontrak Control Systems" -	depends on USB  	help  	  Say Y if you want to use an ADU device from Ontrak Control  	  Systems. @@ -44,7 +40,6 @@ config USB_ADUTUX  config USB_SEVSEG  	tristate "USB 7-Segment LED Display" -	depends on USB  	help  	  Say Y here if you have a USB 7-Segment Display by Delcom @@ -53,7 +48,6 @@ config USB_SEVSEG  config USB_RIO500  	tristate "USB Diamond Rio500 support" -	depends on USB  	help  	  Say Y here if you want to connect a USB Rio500 mp3 player to your  	  computer's USB port. Please read <file:Documentation/usb/rio.txt> @@ -64,7 +58,6 @@ config USB_RIO500  config USB_LEGOTOWER  	tristate "USB Lego Infrared Tower support" -	depends on USB  	help  	  Say Y here if you want to connect a USB Lego Infrared Tower to your  	  computer's USB port. @@ -77,7 +70,6 @@ config USB_LEGOTOWER  config USB_LCD  	tristate "USB LCD driver support" -	depends on USB  	help  	  Say Y here if you want to connect an USBLCD to your computer's  	  USB port. The USBLCD is a small USB interface board for @@ -89,7 +81,6 @@ config USB_LCD  config USB_LED  	tristate "USB LED driver support" -	depends on USB  	help  	  Say Y here if you want to connect an USBLED device to your   	  computer's USB port. @@ -99,7 +90,6 @@ config USB_LED  config USB_CYPRESS_CY7C63  	tristate "Cypress CY7C63xxx USB driver support" -	depends on USB  	help  	  Say Y here if you want to connect a Cypress CY7C63xxx  	  micro controller to your computer's USB port. Currently this @@ -113,7 +103,6 @@ config USB_CYPRESS_CY7C63  config USB_CYTHERM  	tristate "Cypress USB thermometer driver support" -	depends on USB  	help  	  Say Y here if you want to connect a Cypress USB thermometer  	  device to your computer's USB port. This device is also known @@ -126,7 +115,6 @@ config USB_CYTHERM  config USB_IDMOUSE  	tristate "Siemens ID USB Mouse Fingerprint sensor support" -	depends on USB  	help  	  Say Y here if you want to use the fingerprint sensor on  	  the Siemens ID Mouse. There is also a Siemens ID Mouse @@ -140,7 +128,6 @@ config USB_IDMOUSE  config USB_FTDI_ELAN  	tristate "Elan PCMCIA CardBus Adapter USB Client" -	depends on USB  	default M  	help  	  ELAN's Uxxx series of adapters are USB to PCMCIA CardBus adapters. @@ -164,7 +151,6 @@ config USB_FTDI_ELAN  config USB_APPLEDISPLAY  	tristate "Apple Cinema Display support" -	depends on USB  	select BACKLIGHT_LCD_SUPPORT  	select BACKLIGHT_CLASS_DEVICE  	help @@ -175,7 +161,6 @@ source "drivers/usb/misc/sisusbvga/Kconfig"  config USB_LD  	tristate "USB LD driver" -	depends on USB  	help  	  This driver is for generic USB devices that use interrupt transfers,  	  like LD Didactic's USB devices. @@ -185,7 +170,6 @@ config USB_LD  config USB_TRANCEVIBRATOR  	tristate "PlayStation 2 Trance Vibrator driver support" -	depends on USB  	help  	  Say Y here if you want to connect a PlayStation 2 Trance Vibrator  	  device to your computer's USB port. @@ -195,7 +179,6 @@ config USB_TRANCEVIBRATOR  config USB_IOWARRIOR  	tristate "IO Warrior driver support" -	depends on USB  	help  	  Say Y here if you want to support the IO Warrior devices from Code  	  Mercenaries.  This includes support for the following devices: @@ -209,7 +192,6 @@ config USB_IOWARRIOR  config USB_TEST  	tristate "USB testing driver" -	depends on USB  	help  	  This driver is for testing host controller software.  It is used  	  with specialized device firmware for regression and stress testing, @@ -220,7 +202,6 @@ config USB_TEST  config USB_ISIGHTFW  	tristate "iSight firmware loading support" -	depends on USB  	select FW_LOADER  	help  	  This driver loads firmware for USB Apple iSight cameras, allowing @@ -233,7 +214,6 @@ config USB_ISIGHTFW  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 @@ -246,7 +226,6 @@ config USB_YUREX  config USB_EZUSB_FX2  	tristate "Functions for loading firmware on EZUSB chips" -	depends on USB  	help  	  Say Y here if you need EZUSB device support.  	  (Cypress FX/FX2/FX2LP microcontrollers) diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 0fc6e5fc745..ba6a5d6e618 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -63,6 +63,7 @@ static const struct usb_device_id appledisplay_table[] = {  	{ APPLEDISPLAY_DEVICE(0x9219) },  	{ APPLEDISPLAY_DEVICE(0x921c) },  	{ APPLEDISPLAY_DEVICE(0x921d) }, +	{ APPLEDISPLAY_DEVICE(0x9236) },  	/* Terminating entry */  	{ } diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index db46143c67a..d36f34e25be 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -672,7 +672,7 @@ static int iowarrior_release(struct inode *inode, struct file *file)  		retval = -ENODEV;	/* close called more than once */  		mutex_unlock(&dev->mutex);  	} else { -		dev->opened = 0;	/* we're closeing now */ +		dev->opened = 0;	/* we're closing now */  		retval = 0;  		if (dev->present) {  			/* @@ -802,7 +802,7 @@ static int iowarrior_probe(struct usb_interface *interface,  			/* this one will match for the IOWarrior56 only */  			dev->int_out_endpoint = endpoint;  	} -	/* we have to check the report_size often, so remember it in the endianess suitable for our machine */ +	/* we have to check the report_size often, so remember it in the endianness suitable for our machine */  	dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint);  	if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) &&  	    (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56)) diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig index 30ea7ca6846..0d03a520048 100644 --- a/drivers/usb/misc/sisusbvga/Kconfig +++ b/drivers/usb/misc/sisusbvga/Kconfig @@ -1,7 +1,7 @@  config USB_SISUSBVGA  	tristate "USB 2.0 SVGA dongle support (Net2280/SiS315)" -	depends on USB && (USB_MUSB_HDRC || USB_EHCI_HCD) +	depends on (USB_MUSB_HDRC || USB_EHCI_HCD)          ---help---  	  Say Y here if you intend to attach a USB2VGA dongle based on a  	  Net2280 and a SiS315 chip. diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index dd573abd2d1..c21386ec5d3 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3084,7 +3084,7 @@ static int sisusb_probe(struct usb_interface *intf,  	/* Allocate memory for our private */  	if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) { -		dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for private data\n"); +		dev_err(&dev->dev, "Failed to allocate memory for private data\n");  		return -ENOMEM;  	}  	kref_init(&sisusb->kref); diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index f713f6aeb6e..d3a1cce1bf9 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -307,18 +307,7 @@ static struct i2c_driver usb3503_driver = {  	.id_table	= usb3503_id,  }; -static int __init usb3503_init(void) -{ -	return i2c_add_driver(&usb3503_driver); -} - -static void __exit usb3503_exit(void) -{ -	i2c_del_driver(&usb3503_driver); -} - -module_init(usb3503_init); -module_exit(usb3503_exit); +module_i2c_driver(usb3503_driver);  MODULE_AUTHOR("Dongjin Kim <tobetter@gmail.com>");  MODULE_DESCRIPTION("USB3503 USB HUB driver"); diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 29cad9e0a7a..e129cf66122 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -705,7 +705,7 @@ static int uss720_probe(struct usb_interface *intf,  		return -ENODEV;  	}  	i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2); -	dev_dbg(&intf->dev, "set inteface result %d\n", i); +	dev_dbg(&intf->dev, "set interface result %d\n", i);  	interface = intf->cur_altsetting; diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig index 635745f57fb..5c6ffa2a612 100644 --- a/drivers/usb/mon/Kconfig +++ b/drivers/usb/mon/Kconfig @@ -4,7 +4,6 @@  config USB_MON  	tristate "USB Monitor" -	depends on USB  	help  	  If you select this option, a component which captures the USB traffic  	  between peripheral-specific drivers and HC drivers will be built. diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 05e51432dd2..06f8d29af1e 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -6,8 +6,7 @@  # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller  config USB_MUSB_HDRC  	tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' -	depends on USB && USB_GADGET -	select USB_OTG_UTILS +	depends on USB_GADGET  	help  	  Say Y here if your system has a dual role high speed USB  	  controller based on the Mentor Graphics silicon IP.  Then @@ -34,10 +33,12 @@ choice  config USB_MUSB_DAVINCI  	tristate "DaVinci"  	depends on ARCH_DAVINCI_DMx +	depends on BROKEN  config USB_MUSB_DA8XX  	tristate "DA8xx/OMAP-L1x"  	depends on ARCH_DAVINCI_DA8XX +	depends on BROKEN  config USB_MUSB_TUSB6010  	tristate "TUSB6010" @@ -53,7 +54,6 @@ config USB_MUSB_AM35X  config USB_MUSB_DSPS  	tristate "TI DSPS platforms" -	depends on SOC_TI81XX || SOC_AM33XX  config USB_MUSB_BLACKFIN  	tristate "Blackfin" @@ -61,12 +61,12 @@ config USB_MUSB_BLACKFIN  config USB_MUSB_UX500  	tristate "U8500 and U5500" -	depends on (ARCH_U8500 && AB8500_USB)  endchoice  choice  	prompt 'MUSB DMA mode' +	default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM  	default USB_UX500_DMA if USB_MUSB_UX500  	default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN  	default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 59eea219034..2231850c062 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -149,7 +149,7 @@ static void otg_timer(unsigned long _musb)  	 */  	devctl = musb_readb(mregs, MUSB_DEVCTL);  	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl, -		otg_state_string(musb->xceiv->state)); +		usb_otg_state_string(musb->xceiv->state));  	spin_lock_irqsave(&musb->lock, flags);  	switch (musb->xceiv->state) { @@ -195,7 +195,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)  	if (musb->is_active || (musb->a_wait_bcon == 0 &&  				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {  		dev_dbg(musb->controller, "%s active, deleting timer\n", -			otg_state_string(musb->xceiv->state)); +			usb_otg_state_string(musb->xceiv->state));  		del_timer(&otg_workaround);  		last_timer = jiffies;  		return; @@ -208,7 +208,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)  	last_timer = timeout;  	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", -		otg_state_string(musb->xceiv->state), +		usb_otg_state_string(musb->xceiv->state),  		jiffies_to_msecs(timeout - jiffies));  	mod_timer(&otg_workaround, timeout);  } @@ -298,7 +298,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)  		/* NOTE: this must complete power-on within 100 ms. */  		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",  				drvvbus ? "on" : "off", -				otg_state_string(musb->xceiv->state), +				usb_otg_state_string(musb->xceiv->state),  				err ? " ERROR" : "",  				devctl);  		ret = IRQ_HANDLED; diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index dbb31b30c7f..5e63b160db0 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -280,13 +280,13 @@ static void musb_conn_timer_handler(unsigned long _musb)  		break;  	default:  		dev_dbg(musb->controller, "%s state not handled\n", -			otg_state_string(musb->xceiv->state)); +			usb_otg_state_string(musb->xceiv->state));  		break;  	}  	spin_unlock_irqrestore(&musb->lock, flags);  	dev_dbg(musb->controller, "state is %s\n", -		otg_state_string(musb->xceiv->state)); +		usb_otg_state_string(musb->xceiv->state));  }  static void bfin_musb_enable(struct musb *musb) @@ -307,7 +307,7 @@ static void bfin_musb_set_vbus(struct musb *musb, int is_on)  	dev_dbg(musb->controller, "VBUS %s, devctl %02x "  		/* otg %3x conf %08x prcm %08x */ "\n", -		otg_state_string(musb->xceiv->state), +		usb_otg_state_string(musb->xceiv->state),  		musb_readb(musb->mregs, MUSB_DEVCTL));  } diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index f522000e8f0..9db211ee15b 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -435,7 +435,6 @@ cppi_rndis_update(struct cppi_channel *c, int is_rx,  	}  } -#ifdef CONFIG_USB_MUSB_DEBUG  static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)  {  	pr_debug("RXBD/%s %08x: " @@ -444,21 +443,16 @@ static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)  			bd->hw_next, bd->hw_bufp, bd->hw_off_len,  			bd->hw_options);  } -#endif  static void cppi_dump_rxq(int level, const char *tag, struct cppi_channel *rx)  { -#ifdef CONFIG_USB_MUSB_DEBUG  	struct cppi_descriptor	*bd; -	if (!_dbg_level(level)) -		return;  	cppi_dump_rx(level, rx, tag);  	if (rx->last_processed)  		cppi_dump_rxbd("last", rx->last_processed);  	for (bd = rx->head; bd; bd = bd->next)  		cppi_dump_rxbd("active", bd); -#endif  } @@ -784,6 +778,7 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)  	void __iomem		*tibase = musb->ctrl_base;  	int			is_rndis = 0;  	struct cppi_rx_stateram	__iomem *rx_ram = rx->state_ram; +	struct cppi_descriptor	*d;  	if (onepacket) {  		/* almost every USB driver, host or peripheral side */ @@ -897,14 +892,8 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)  	bd->hw_options |= CPPI_SOP_SET;  	tail->hw_options |= CPPI_EOP_SET; -#ifdef CONFIG_USB_MUSB_DEBUG -	if (_dbg_level(5)) { -		struct cppi_descriptor	*d; - -		for (d = rx->head; d; d = d->next) -			cppi_dump_rxbd("S", d); -	} -#endif +	for (d = rx->head; d; d = d->next) +		cppi_dump_rxbd("S", d);  	/* in case the preceding transfer left some state... */  	tail = rx->last_processed; diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 7c71769d71f..b903b744a22 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -198,7 +198,7 @@ static void otg_timer(unsigned long _musb)  	 */  	devctl = musb_readb(mregs, MUSB_DEVCTL);  	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl, -		otg_state_string(musb->xceiv->state)); +		usb_otg_state_string(musb->xceiv->state));  	spin_lock_irqsave(&musb->lock, flags);  	switch (musb->xceiv->state) { @@ -267,7 +267,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)  	if (musb->is_active || (musb->a_wait_bcon == 0 &&  				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {  		dev_dbg(musb->controller, "%s active, deleting timer\n", -			otg_state_string(musb->xceiv->state)); +			usb_otg_state_string(musb->xceiv->state));  		del_timer(&otg_workaround);  		last_timer = jiffies;  		return; @@ -280,7 +280,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)  	last_timer = timeout;  	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", -		otg_state_string(musb->xceiv->state), +		usb_otg_state_string(musb->xceiv->state),  		jiffies_to_msecs(timeout - jiffies));  	mod_timer(&otg_workaround, timeout);  } @@ -327,7 +327,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)  		u8 devctl = musb_readb(mregs, MUSB_DEVCTL);  		int err; -		err = musb->int_usb & USB_INTR_VBUSERROR; +		err = musb->int_usb & MUSB_INTR_VBUSERROR;  		if (err) {  			/*  			 * The Mentor core doesn't debounce VBUS as needed @@ -360,7 +360,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)  		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",  				drvvbus ? "on" : "off", -				otg_state_string(musb->xceiv->state), +				usb_otg_state_string(musb->xceiv->state),  				err ? " ERROR" : "",  				devctl);  		ret = IRQ_HANDLED; diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index e040d910373..bea6cc35471 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -215,7 +215,7 @@ static void otg_timer(unsigned long _musb)  	 */  	devctl = musb_readb(mregs, MUSB_DEVCTL);  	dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl, -		otg_state_string(musb->xceiv->state)); +		usb_otg_state_string(musb->xceiv->state));  	spin_lock_irqsave(&musb->lock, flags);  	switch (musb->xceiv->state) { @@ -349,7 +349,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci)  		davinci_musb_source_power(musb, drvvbus, 0);  		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",  				drvvbus ? "on" : "off", -				otg_state_string(musb->xceiv->state), +				usb_otg_state_string(musb->xceiv->state),  				err ? " ERROR" : "",  				devctl);  		retval = IRQ_HANDLED; diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index daec6e0f7e3..37a261a6bb6 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -372,13 +372,13 @@ static void musb_otg_timer_func(unsigned long data)  	case OTG_STATE_A_SUSPEND:  	case OTG_STATE_A_WAIT_BCON:  		dev_dbg(musb->controller, "HNP: %s timeout\n", -			otg_state_string(musb->xceiv->state)); +			usb_otg_state_string(musb->xceiv->state));  		musb_platform_set_vbus(musb, 0);  		musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;  		break;  	default:  		dev_dbg(musb->controller, "HNP: Unhandled mode %s\n", -			otg_state_string(musb->xceiv->state)); +			usb_otg_state_string(musb->xceiv->state));  	}  	musb->ignore_disconnect = 0;  	spin_unlock_irqrestore(&musb->lock, flags); @@ -393,13 +393,14 @@ void musb_hnp_stop(struct musb *musb)  	void __iomem	*mbase = musb->mregs;  	u8	reg; -	dev_dbg(musb->controller, "HNP: stop from %s\n", otg_state_string(musb->xceiv->state)); +	dev_dbg(musb->controller, "HNP: stop from %s\n", +			usb_otg_state_string(musb->xceiv->state));  	switch (musb->xceiv->state) {  	case OTG_STATE_A_PERIPHERAL:  		musb_g_disconnect(musb);  		dev_dbg(musb->controller, "HNP: back to %s\n", -			otg_state_string(musb->xceiv->state)); +			usb_otg_state_string(musb->xceiv->state));  		break;  	case OTG_STATE_B_HOST:  		dev_dbg(musb->controller, "HNP: Disabling HR\n"); @@ -413,7 +414,7 @@ void musb_hnp_stop(struct musb *musb)  		break;  	default:  		dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n", -			otg_state_string(musb->xceiv->state)); +			usb_otg_state_string(musb->xceiv->state));  	}  	/* @@ -451,7 +452,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  	 */  	if (int_usb & MUSB_INTR_RESUME) {  		handled = IRQ_HANDLED; -		dev_dbg(musb->controller, "RESUME (%s)\n", otg_state_string(musb->xceiv->state)); +		dev_dbg(musb->controller, "RESUME (%s)\n", usb_otg_state_string(musb->xceiv->state));  		if (devctl & MUSB_DEVCTL_HM) {  			void __iomem *mbase = musb->mregs; @@ -493,7 +494,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  			default:  				WARNING("bogus %s RESUME (%s)\n",  					"host", -					otg_state_string(musb->xceiv->state)); +					usb_otg_state_string(musb->xceiv->state));  			}  		} else {  			switch (musb->xceiv->state) { @@ -522,7 +523,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  			default:  				WARNING("bogus %s RESUME (%s)\n",  					"peripheral", -					otg_state_string(musb->xceiv->state)); +					usb_otg_state_string(musb->xceiv->state));  			}  		}  	} @@ -538,7 +539,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  		}  		dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n", -			otg_state_string(musb->xceiv->state)); +			usb_otg_state_string(musb->xceiv->state));  		/* IRQ arrives from ID pin sense or (later, if VBUS power  		 * is removed) SRP.  responses are time critical: @@ -602,8 +603,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  			break;  		} -		dev_dbg(musb->controller, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n", -				otg_state_string(musb->xceiv->state), +		dev_printk(ignore ? KERN_DEBUG : KERN_ERR, musb->controller, +				"VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n", +				usb_otg_state_string(musb->xceiv->state),  				devctl,  				({ char *s;  				switch (devctl & MUSB_DEVCTL_VBUS) { @@ -628,7 +630,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  	if (int_usb & MUSB_INTR_SUSPEND) {  		dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n", -			otg_state_string(musb->xceiv->state), devctl); +			usb_otg_state_string(musb->xceiv->state), devctl);  		handled = IRQ_HANDLED;  		switch (musb->xceiv->state) { @@ -745,12 +747,12 @@ b_host:  			usb_hcd_resume_root_hub(hcd);  		dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n", -				otg_state_string(musb->xceiv->state), devctl); +				usb_otg_state_string(musb->xceiv->state), devctl);  	}  	if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {  		dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n", -				otg_state_string(musb->xceiv->state), +				usb_otg_state_string(musb->xceiv->state),  				MUSB_MODE(musb), devctl);  		handled = IRQ_HANDLED; @@ -787,7 +789,7 @@ b_host:  			break;  		default:  			WARNING("unhandled DISCONNECT transition (%s)\n", -				otg_state_string(musb->xceiv->state)); +				usb_otg_state_string(musb->xceiv->state));  			break;  		}  	} @@ -813,7 +815,7 @@ b_host:  			}  		} else {  			dev_dbg(musb->controller, "BUS RESET as %s\n", -				otg_state_string(musb->xceiv->state)); +				usb_otg_state_string(musb->xceiv->state));  			switch (musb->xceiv->state) {  			case OTG_STATE_A_SUSPEND:  				/* We need to ignore disconnect on suspend @@ -826,7 +828,7 @@ b_host:  			case OTG_STATE_A_WAIT_BCON:	/* OPT TD.4.7-900ms */  				/* never use invalid T(a_wait_bcon) */  				dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n", -					otg_state_string(musb->xceiv->state), +					usb_otg_state_string(musb->xceiv->state),  					TA_WAIT_BCON(musb));  				mod_timer(&musb->otg_timer, jiffies  					+ msecs_to_jiffies(TA_WAIT_BCON(musb))); @@ -838,7 +840,7 @@ b_host:  				break;  			case OTG_STATE_B_WAIT_ACON:  				dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n", -					otg_state_string(musb->xceiv->state)); +					usb_otg_state_string(musb->xceiv->state));  				musb->xceiv->state = OTG_STATE_B_PERIPHERAL;  				musb_g_reset(musb);  				break; @@ -850,7 +852,7 @@ b_host:  				break;  			default:  				dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n", -					otg_state_string(musb->xceiv->state)); +					usb_otg_state_string(musb->xceiv->state));  			}  		}  	} @@ -1632,7 +1634,7 @@ musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)  	int ret = -EINVAL;  	spin_lock_irqsave(&musb->lock, flags); -	ret = sprintf(buf, "%s\n", otg_state_string(musb->xceiv->state)); +	ret = sprintf(buf, "%s\n", usb_otg_state_string(musb->xceiv->state));  	spin_unlock_irqrestore(&musb->lock, flags);  	return ret; @@ -1951,9 +1953,13 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)  		musb_write_ulpi_buscontrol(musb->mregs, busctl);  	} -	MUSB_DEV_MODE(musb); -	musb->xceiv->otg->default_a = 0; -	musb->xceiv->state = OTG_STATE_B_IDLE; +	if (musb->xceiv->otg->default_a) { +		MUSB_HST_MODE(musb); +		musb->xceiv->state = OTG_STATE_A_IDLE; +	} else { +		MUSB_DEV_MODE(musb); +		musb->xceiv->state = OTG_STATE_B_IDLE; +	}  	status = musb_gadget_setup(musb); @@ -2008,7 +2014,6 @@ static int musb_probe(struct platform_device *pdev)  {  	struct device	*dev = &pdev->dev;  	int		irq = platform_get_irq_byname(pdev, "mc"); -	int		status;  	struct resource	*iomem;  	void __iomem	*base; @@ -2016,24 +2021,17 @@ static int musb_probe(struct platform_device *pdev)  	if (!iomem || irq <= 0)  		return -ENODEV; -	base = ioremap(iomem->start, resource_size(iomem)); -	if (!base) { -		dev_err(dev, "ioremap failed\n"); -		return -ENOMEM; -	} +	base = devm_ioremap_resource(dev, iomem); +	if (IS_ERR(base)) +		return PTR_ERR(base); -	status = musb_init_controller(dev, irq, base); -	if (status < 0) -		iounmap(base); - -	return status; +	return musb_init_controller(dev, irq, base);  }  static int musb_remove(struct platform_device *pdev)  {  	struct device	*dev = &pdev->dev;  	struct musb	*musb = dev_to_musb(dev); -	void __iomem	*ctrl_base = musb->ctrl_base;  	/* this gets called on rmmod.  	 *  - Host mode: host may still be active @@ -2044,7 +2042,6 @@ static int musb_remove(struct platform_device *pdev)  	musb_shutdown(pdev);  	musb_free(musb); -	iounmap(ctrl_base);  	device_init_wakeup(dev, 0);  #ifndef CONFIG_MUSB_PIO_ONLY  	dma_set_mask(dev, *dev->parent->dma_mask); @@ -2293,8 +2290,6 @@ static int __init musb_init(void)  	if (usb_disabled())  		return 0; -	pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n", -		musb_driver_name);  	return platform_driver_register(&musb_driver);  }  module_init(musb_init); diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 6bb89715b63..3a18e44e939 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -38,6 +38,7 @@  #include <linux/module.h>  #include <linux/usb/nop-usb-xceiv.h>  #include <linux/platform_data/usb-omap.h> +#include <linux/sizes.h>  #include <linux/of.h>  #include <linux/of_device.h> @@ -224,7 +225,7 @@ static void otg_timer(unsigned long _musb)  	 */  	devctl = dsps_readb(mregs, MUSB_DEVCTL);  	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl, -				otg_state_string(musb->xceiv->state)); +				usb_otg_state_string(musb->xceiv->state));  	spin_lock_irqsave(&musb->lock, flags);  	switch (musb->xceiv->state) { @@ -273,7 +274,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)  	if (musb->is_active || (musb->a_wait_bcon == 0 &&  				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {  		dev_dbg(musb->controller, "%s active, deleting timer\n", -				otg_state_string(musb->xceiv->state)); +				usb_otg_state_string(musb->xceiv->state));  		del_timer(&glue->timer[pdev->id]);  		glue->last_timer[pdev->id] = jiffies;  		return; @@ -288,7 +289,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)  	glue->last_timer[pdev->id] = timeout;  	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", -		otg_state_string(musb->xceiv->state), +		usb_otg_state_string(musb->xceiv->state),  			jiffies_to_msecs(timeout - jiffies));  	mod_timer(&glue->timer[pdev->id], timeout);  } @@ -334,7 +335,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)  	 * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.  	 * Also, DRVVBUS pulses for SRP (but not at 5V) ...  	 */ -	if (usbintr & MUSB_INTR_BABBLE) +	if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE)  		pr_info("CAUTION: musb: Babble Interrupt Occurred\n");  	if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) { @@ -377,7 +378,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)  		/* NOTE: this must complete power-on within 100 ms. */  		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",  				drvvbus ? "on" : "off", -				otg_state_string(musb->xceiv->state), +				usb_otg_state_string(musb->xceiv->state),  				err ? " ERROR" : "",  				devctl);  		ret = IRQ_HANDLED; @@ -596,14 +597,13 @@ err0:  static int dsps_probe(struct platform_device *pdev)  { -	struct device_node *np = pdev->dev.of_node;  	const struct of_device_id *match;  	const struct dsps_musb_wrapper *wrp;  	struct dsps_glue *glue;  	struct resource *iomem;  	int ret, i; -	match = of_match_node(musb_dsps_of_match, np); +	match = of_match_node(musb_dsps_of_match, pdev->dev.of_node);  	if (!match) {  		dev_err(&pdev->dev, "fail to get matching of_match struct\n");  		ret = -EINVAL; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index be18537c5f1..ba7092349fa 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -46,48 +46,6 @@  #include "musb_core.h" -/* MUSB PERIPHERAL status 3-mar-2006: - * - * - EP0 seems solid.  It passes both USBCV and usbtest control cases. - *   Minor glitches: - * - *     + remote wakeup to Linux hosts work, but saw USBCV failures; - *       in one test run (operator error?) - *     + endpoint halt tests -- in both usbtest and usbcv -- seem - *       to break when dma is enabled ... is something wrongly - *       clearing SENDSTALL? - * - * - Mass storage behaved ok when last tested.  Network traffic patterns - *   (with lots of short transfers etc) need retesting; they turn up the - *   worst cases of the DMA, since short packets are typical but are not - *   required. - * - * - TX/IN - *     + both pio and dma behave in with network and g_zero tests - *     + no cppi throughput issues other than no-hw-queueing - *     + failed with FLAT_REG (DaVinci) - *     + seems to behave with double buffering, PIO -and- CPPI - *     + with gadgetfs + AIO, requests got lost? - * - * - RX/OUT - *     + both pio and dma behave in with network and g_zero tests - *     + dma is slow in typical case (short_not_ok is clear) - *     + double buffering ok with PIO - *     + double buffering *FAILS* with CPPI, wrong data bytes sometimes - *     + request lossage observed with gadgetfs - * - * - ISO not tested ... might work, but only weakly isochronous - * - * - Gadget driver disabling of softconnect during bind() is ignored; so - *   drivers can't hold off host requests until userspace is ready. - *   (Workaround:  they can turn it off later.) - * - * - PORTABILITY (assumes PIO works): - *     + DaVinci, basically works with cppi dma - *     + OMAP 2430, ditto with mentor dma - *     + TUSB 6010, platform-specific dma in the works - */ -  /* ----------------------------------------------------------------------- */  #define is_buffer_mapped(req) (is_dma_capable() && \ @@ -141,7 +99,9 @@ static inline void map_dma_buffer(struct musb_request *request,  static inline void unmap_dma_buffer(struct musb_request *request,  				struct musb *musb)  { -	if (!is_buffer_mapped(request)) +	struct musb_ep *musb_ep = request->ep; + +	if (!is_buffer_mapped(request) || !musb_ep->dma)  		return;  	if (request->request.dma == DMA_ADDR_INVALID) { @@ -195,7 +155,10 @@ __acquires(ep->musb->lock)  	ep->busy = 1;  	spin_unlock(&musb->lock); -	unmap_dma_buffer(req, musb); + +	if (!dma_mapping_error(&musb->g.dev, request->dma)) +		unmap_dma_buffer(req, musb); +  	if (request->status == 0)  		dev_dbg(musb->controller, "%s done request %p,  %d/%d\n",  				ep->end_point.name, request, @@ -275,41 +238,6 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)  		return ep->packet_sz;  } - -#ifdef CONFIG_USB_INVENTRA_DMA - -/* Peripheral tx (IN) using Mentor DMA works as follows: -	Only mode 0 is used for transfers <= wPktSize, -	mode 1 is used for larger transfers, - -	One of the following happens: -	- Host sends IN token which causes an endpoint interrupt -		-> TxAvail -			-> if DMA is currently busy, exit. -			-> if queue is non-empty, txstate(). - -	- Request is queued by the gadget driver. -		-> if queue was previously empty, txstate() - -	txstate() -		-> start -		  /\	-> setup DMA -		  |     (data is transferred to the FIFO, then sent out when -		  |	IN token(s) are recd from Host. -		  |		-> DMA interrupt on completion -		  |		   calls TxAvail. -		  |		      -> stop DMA, ~DMAENAB, -		  |		      -> set TxPktRdy for last short pkt or zlp -		  |		      -> Complete Request -		  |		      -> Continue next request (call txstate) -		  |___________________________________| - - * Non-Mentor DMA engines can of course work differently, such as by - * upleveling from irq-per-packet to irq-per-buffer. - */ - -#endif -  /*   * An endpoint is transmitting data. This can be called either from   * the IRQ routine or from ep.queue() to kickstart a request on an @@ -616,37 +544,6 @@ void musb_g_tx(struct musb *musb, u8 epnum)  /* ------------------------------------------------------------ */ -#ifdef CONFIG_USB_INVENTRA_DMA - -/* Peripheral rx (OUT) using Mentor DMA works as follows: -	- Only mode 0 is used. - -	- Request is queued by the gadget class driver. -		-> if queue was previously empty, rxstate() - -	- Host sends OUT token which causes an endpoint interrupt -	  /\      -> RxReady -	  |	      -> if request queued, call rxstate -	  |		/\	-> setup DMA -	  |		|	     -> DMA interrupt on completion -	  |		|		-> RxReady -	  |		|		      -> stop DMA -	  |		|		      -> ack the read -	  |		|		      -> if data recd = max expected -	  |		|				by the request, or host -	  |		|				sent a short packet, -	  |		|				complete the request, -	  |		|				and start the next one. -	  |		|_____________________________________| -	  |					 else just wait for the host -	  |					    to send the next OUT token. -	  |__________________________________________________| - - * Non-Mentor DMA engines can of course work differently. - */ - -#endif -  /*   * Context: controller locked, IRQs blocked, endpoint selected   */ @@ -735,7 +632,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)  				struct dma_controller	*c;  				struct dma_channel	*channel;  				int			use_dma = 0; -				int transfer_size; +				unsigned int transfer_size;  				c = musb->dma_controller;  				channel = musb_ep->dma; @@ -777,10 +674,11 @@ static void rxstate(struct musb *musb, struct musb_request *req)  						csr | MUSB_RXCSR_DMAMODE);  					musb_writew(epio, MUSB_RXCSR, csr); -					transfer_size = min(request->length - request->actual, +					transfer_size = min_t(unsigned int, +							request->length - +							request->actual,  							channel->max_len);  					musb_ep->dma->desired_mode = 1; -  				} else {  					if (!musb_ep->hb_mult &&  						musb_ep->hw_ep->rx_double_buffered) @@ -810,7 +708,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)  				struct dma_controller *c;  				struct dma_channel *channel; -				int transfer_size = 0; +				unsigned int transfer_size = 0;  				c = musb->dma_controller;  				channel = musb_ep->dma; @@ -819,11 +717,13 @@ static void rxstate(struct musb *musb, struct musb_request *req)  				if (fifo_count < musb_ep->packet_sz)  					transfer_size = fifo_count;  				else if (request->short_not_ok) -					transfer_size =	min(request->length - +					transfer_size =	min_t(unsigned int, +							request->length -  							request->actual,  							channel->max_len);  				else -					transfer_size = min(request->length - +					transfer_size = min_t(unsigned int, +							request->length -  							request->actual,  							(unsigned)fifo_count); @@ -1676,7 +1576,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget)  		goto done;  	default:  		dev_dbg(musb->controller, "Unhandled wake: %s\n", -			otg_state_string(musb->xceiv->state)); +			usb_otg_state_string(musb->xceiv->state));  		goto done;  	} @@ -1796,13 +1696,6 @@ static const struct usb_gadget_ops musb_gadget_operations = {   * all peripheral ports are external...   */ -static void musb_gadget_release(struct device *dev) -{ -	/* kref_put(WHAT) */ -	dev_dbg(dev, "%s\n", __func__); -} - -  static void  init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)  { @@ -1887,12 +1780,7 @@ int musb_gadget_setup(struct musb *musb)  	musb->g.speed = USB_SPEED_UNKNOWN;  	/* this "gadget" abstracts/virtualizes the controller */ -	dev_set_name(&musb->g.dev, "gadget"); -	musb->g.dev.parent = musb->controller; -	musb->g.dev.dma_mask = musb->controller->dma_mask; -	musb->g.dev.release = musb_gadget_release;  	musb->g.name = musb_driver_name; -  	musb->g.is_otg = 1;  	musb_g_init_endpoints(musb); @@ -1900,11 +1788,6 @@ int musb_gadget_setup(struct musb *musb)  	musb->is_active = 0;  	musb_platform_try_idle(musb, 0); -	status = device_register(&musb->g.dev); -	if (status != 0) { -		put_device(&musb->g.dev); -		return status; -	}  	status = usb_add_gadget_udc(musb->controller, &musb->g);  	if (status)  		goto err; @@ -1919,8 +1802,6 @@ err:  void musb_gadget_cleanup(struct musb *musb)  {  	usb_del_gadget_udc(&musb->g); -	if (musb->g.dev.parent) -		device_unregister(&musb->g.dev);  }  /* @@ -1972,9 +1853,8 @@ static int musb_gadget_start(struct usb_gadget *g,  		goto err;  	} -	if ((musb->xceiv->last_event == USB_EVENT_ID) -				&& otg->set_vbus) -		otg_set_vbus(otg, 1); +	if (musb->xceiv->last_event == USB_EVENT_ID) +		musb_platform_set_vbus(musb, 1);  	hcd->self.uses_pio_for_control = 1; @@ -2058,6 +1938,7 @@ static int musb_gadget_stop(struct usb_gadget *g,  	dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);  	musb->is_active = 0; +	musb->gadget_driver = NULL;  	musb_platform_try_idle(musb, 0);  	spin_unlock_irqrestore(&musb->lock, flags); @@ -2094,7 +1975,7 @@ void musb_g_resume(struct musb *musb)  		break;  	default:  		WARNING("unhandled RESUME transition (%s)\n", -				otg_state_string(musb->xceiv->state)); +				usb_otg_state_string(musb->xceiv->state));  	}  } @@ -2124,7 +2005,7 @@ void musb_g_suspend(struct musb *musb)  		 * A_PERIPHERAL may need care too  		 */  		WARNING("unhandled SUSPEND transition (%s)\n", -				otg_state_string(musb->xceiv->state)); +				usb_otg_state_string(musb->xceiv->state));  	}  } @@ -2158,7 +2039,7 @@ void musb_g_disconnect(struct musb *musb)  	switch (musb->xceiv->state) {  	default:  		dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n", -			otg_state_string(musb->xceiv->state)); +			usb_otg_state_string(musb->xceiv->state));  		musb->xceiv->state = OTG_STATE_A_IDLE;  		MUSB_HST_MODE(musb);  		break; diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index c9c1ac4e075..2af45a0c893 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -505,8 +505,10 @@ static void ep0_rxstate(struct musb *musb)  			req->status = -EOVERFLOW;  			count = len;  		} -		musb_read_fifo(&musb->endpoints[0], count, buf); -		req->actual += count; +		if (count > 0) { +			musb_read_fifo(&musb->endpoints[0], count, buf); +			req->actual += count; +		}  		csr = MUSB_CSR0_P_SVDRXPKTRDY;  		if (count < 64 || req->actual == req->length) {  			musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 1ce1fcf3f3e..8914dec49f0 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2453,7 +2453,7 @@ static int musb_bus_suspend(struct usb_hcd *hcd)  	if (musb->is_active) {  		WARNING("trying to suspend as %s while active\n", -				otg_state_string(musb->xceiv->state)); +				usb_otg_state_string(musb->xceiv->state));  		return -EBUSY;  	} else  		return 0; @@ -2465,6 +2465,118 @@ static int musb_bus_resume(struct usb_hcd *hcd)  	return 0;  } + +#ifndef CONFIG_MUSB_PIO_ONLY + +#define MUSB_USB_DMA_ALIGN 4 + +struct musb_temp_buffer { +	void *kmalloc_ptr; +	void *old_xfer_buffer; +	u8 data[0]; +}; + +static void musb_free_temp_buffer(struct urb *urb) +{ +	enum dma_data_direction dir; +	struct musb_temp_buffer *temp; + +	if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) +		return; + +	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + +	temp = container_of(urb->transfer_buffer, struct musb_temp_buffer, +			    data); + +	if (dir == DMA_FROM_DEVICE) { +		memcpy(temp->old_xfer_buffer, temp->data, +		       urb->transfer_buffer_length); +	} +	urb->transfer_buffer = temp->old_xfer_buffer; +	kfree(temp->kmalloc_ptr); + +	urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; +} + +static int musb_alloc_temp_buffer(struct urb *urb, gfp_t mem_flags) +{ +	enum dma_data_direction dir; +	struct musb_temp_buffer *temp; +	void *kmalloc_ptr; +	size_t kmalloc_size; + +	if (urb->num_sgs || urb->sg || +	    urb->transfer_buffer_length == 0 || +	    !((uintptr_t)urb->transfer_buffer & (MUSB_USB_DMA_ALIGN - 1))) +		return 0; + +	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + +	/* Allocate a buffer with enough padding for alignment */ +	kmalloc_size = urb->transfer_buffer_length + +		sizeof(struct musb_temp_buffer) + MUSB_USB_DMA_ALIGN - 1; + +	kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); +	if (!kmalloc_ptr) +		return -ENOMEM; + +	/* Position our struct temp_buffer such that data is aligned */ +	temp = PTR_ALIGN(kmalloc_ptr, MUSB_USB_DMA_ALIGN); + + +	temp->kmalloc_ptr = kmalloc_ptr; +	temp->old_xfer_buffer = urb->transfer_buffer; +	if (dir == DMA_TO_DEVICE) +		memcpy(temp->data, urb->transfer_buffer, +		       urb->transfer_buffer_length); +	urb->transfer_buffer = temp->data; + +	urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER; + +	return 0; +} + +static int musb_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, +				      gfp_t mem_flags) +{ +	struct musb	*musb = hcd_to_musb(hcd); +	int ret; + +	/* +	 * The DMA engine in RTL1.8 and above cannot handle +	 * DMA addresses that are not aligned to a 4 byte boundary. +	 * For such engine implemented (un)map_urb_for_dma hooks. +	 * Do not use these hooks for RTL<1.8 +	 */ +	if (musb->hwvers < MUSB_HWVERS_1800) +		return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); + +	ret = musb_alloc_temp_buffer(urb, mem_flags); +	if (ret) +		return ret; + +	ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); +	if (ret) +		musb_free_temp_buffer(urb); + +	return ret; +} + +static void musb_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) +{ +	struct musb	*musb = hcd_to_musb(hcd); + +	usb_hcd_unmap_urb_for_dma(hcd, urb); + +	/* Do not use this hook for RTL<1.8 (see description above) */ +	if (musb->hwvers < MUSB_HWVERS_1800) +		return; + +	musb_free_temp_buffer(urb); +} +#endif /* !CONFIG_MUSB_PIO_ONLY */ +  const struct hc_driver musb_hc_driver = {  	.description		= "musb-hcd",  	.product_desc		= "MUSB HDRC host driver", @@ -2484,6 +2596,11 @@ const struct hc_driver musb_hc_driver = {  	.urb_dequeue		= musb_urb_dequeue,  	.endpoint_disable	= musb_h_disable, +#ifndef CONFIG_MUSB_PIO_ONLY +	.map_urb_for_dma	= musb_map_urb_for_dma, +	.unmap_urb_for_dma	= musb_unmap_urb_for_dma, +#endif +  	.hub_status_data	= musb_hub_status_data,  	.hub_control		= musb_hub_control,  	.bus_suspend		= musb_bus_suspend, diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index f70579154de..ef7d11045f5 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -95,7 +95,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend)  			break;  		default:  			dev_dbg(musb->controller, "bogus rh suspend? %s\n", -				otg_state_string(musb->xceiv->state)); +				usb_otg_state_string(musb->xceiv->state));  		}  	} else if (power & MUSB_POWER_SUSPENDM) {  		power &= ~MUSB_POWER_SUSPENDM; @@ -203,7 +203,7 @@ void musb_root_disconnect(struct musb *musb)  		break;  	default:  		dev_dbg(musb->controller, "host disconnect (%s)\n", -			otg_state_string(musb->xceiv->state)); +			usb_otg_state_string(musb->xceiv->state));  	}  } diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 1a42a458f2c..3551f1a30c6 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -117,7 +117,7 @@ static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)  	if (musb->is_active || ((musb->a_wait_bcon == 0)  			&& (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {  		dev_dbg(musb->controller, "%s active, deleting timer\n", -			otg_state_string(musb->xceiv->state)); +			usb_otg_state_string(musb->xceiv->state));  		del_timer(&musb_idle_timer);  		last_timer = jiffies;  		return; @@ -134,7 +134,7 @@ static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)  	last_timer = timeout;  	dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n", -		otg_state_string(musb->xceiv->state), +		usb_otg_state_string(musb->xceiv->state),  		(unsigned long)jiffies_to_msecs(timeout - jiffies));  	mod_timer(&musb_idle_timer, timeout);  } @@ -174,8 +174,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on)  				}  			} -			if (otg->set_vbus) -				otg_set_vbus(otg, 1); +			otg_set_vbus(otg, 1);  		} else {  			musb->is_active = 1;  			otg->default_a = 1; @@ -200,7 +199,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on)  	dev_dbg(musb->controller, "VBUS %s, devctl %02x "  		/* otg %3x conf %08x prcm %08x */ "\n", -		otg_state_string(musb->xceiv->state), +		usb_otg_state_string(musb->xceiv->state),  		musb_readb(musb->mregs, MUSB_DEVCTL));  } @@ -292,14 +291,14 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)  		musb->xceiv->last_event = USB_EVENT_NONE;  		if (musb->gadget_driver) { +			omap2430_musb_set_vbus(musb, 0);  			pm_runtime_mark_last_busy(dev);  			pm_runtime_put_autosuspend(dev);  		} -		if (data->interface_type == MUSB_INTERFACE_UTMI) { -			if (musb->xceiv->otg->set_vbus) -				otg_set_vbus(musb->xceiv->otg, 0); -		} +		if (data->interface_type == MUSB_INTERFACE_UTMI) +			otg_set_vbus(musb->xceiv->otg, 0); +  		omap_control_usb_set_mode(glue->control_otghs,  			USB_MODE_DISCONNECT);  		break; @@ -355,7 +354,12 @@ static int omap2430_musb_init(struct musb *musb)  	else  		musb->xceiv = devm_usb_get_phy_dev(dev, 0); -	if (IS_ERR_OR_NULL(musb->xceiv)) { +	if (IS_ERR(musb->xceiv)) { +		status = PTR_ERR(musb->xceiv); + +		if (status == -ENXIO) +			return status; +  		pr_err("HS USB OTG: no transceiver configured\n");  		return -EPROBE_DEFER;  	} @@ -393,6 +397,8 @@ static int omap2430_musb_init(struct musb *musb)  	if (glue->status != OMAP_MUSB_UNKNOWN)  		omap_musb_set_mailbox(glue); +	usb_phy_init(musb->xceiv); +  	pm_runtime_put_noidle(musb->controller);  	return 0; @@ -526,10 +532,10 @@ static int omap2430_probe(struct platform_device *pdev)  		}  		of_property_read_u32(np, "mode", (u32 *)&pdata->mode); -		of_property_read_u32(np, "interface_type", +		of_property_read_u32(np, "interface-type",  						(u32 *)&data->interface_type); -		of_property_read_u32(np, "num_eps", (u32 *)&config->num_eps); -		of_property_read_u32(np, "ram_bits", (u32 *)&config->ram_bits); +		of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); +		of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);  		of_property_read_u32(np, "power", (u32 *)&pdata->power);  		config->multipoint = of_property_read_bool(np, "multipoint");  		pdata->has_mailbox = of_property_read_bool(np, diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 464bd23cccd..7369ba33c94 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -423,7 +423,7 @@ static void musb_do_idle(unsigned long _musb)  			&& (musb->idle_timeout == 0  				|| time_after(jiffies, musb->idle_timeout))) {  			dev_dbg(musb->controller, "Nothing connected %s, turning off VBUS\n", -					otg_state_string(musb->xceiv->state)); +					usb_otg_state_string(musb->xceiv->state));  		}  		/* FALLTHROUGH */  	case OTG_STATE_A_IDLE: @@ -478,7 +478,7 @@ static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout)  	if (musb->is_active || ((musb->a_wait_bcon == 0)  			&& (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {  		dev_dbg(musb->controller, "%s active, deleting timer\n", -			otg_state_string(musb->xceiv->state)); +			usb_otg_state_string(musb->xceiv->state));  		del_timer(&musb_idle_timer);  		last_timer = jiffies;  		return; @@ -495,7 +495,7 @@ static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout)  	last_timer = timeout;  	dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n", -		otg_state_string(musb->xceiv->state), +		usb_otg_state_string(musb->xceiv->state),  		(unsigned long)jiffies_to_msecs(timeout - jiffies));  	mod_timer(&musb_idle_timer, timeout);  } @@ -571,7 +571,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on)  	musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);  	dev_dbg(musb->controller, "VBUS %s, devctl %02x otg %3x conf %08x prcm %08x\n", -		otg_state_string(musb->xceiv->state), +		usb_otg_state_string(musb->xceiv->state),  		musb_readb(musb->mregs, MUSB_DEVCTL),  		musb_readl(tbase, TUSB_DEV_OTG_STAT),  		conf, prcm); @@ -678,13 +678,13 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)  				musb->is_active = 0;  			}  			dev_dbg(musb->controller, "vbus change, %s, otg %03x\n", -				otg_state_string(musb->xceiv->state), otg_stat); +				usb_otg_state_string(musb->xceiv->state), otg_stat);  			idle_timeout = jiffies + (1 * HZ);  			schedule_work(&musb->irq_work);  		} else /* A-dev state machine */ {  			dev_dbg(musb->controller, "vbus change, %s, otg %03x\n", -				otg_state_string(musb->xceiv->state), otg_stat); +				usb_otg_state_string(musb->xceiv->state), otg_stat);  			switch (musb->xceiv->state) {  			case OTG_STATE_A_IDLE: @@ -733,7 +733,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)  		u8	devctl;  		dev_dbg(musb->controller, "%s timer, %03x\n", -			otg_state_string(musb->xceiv->state), otg_stat); +			usb_otg_state_string(musb->xceiv->state), otg_stat);  		switch (musb->xceiv->state) {  		case OTG_STATE_A_WAIT_VRISE: diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index 13a39291376..2c80004e0a8 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -26,6 +26,7 @@  #include <linux/err.h>  #include <linux/io.h>  #include <linux/platform_device.h> +#include <linux/usb/musb-ux500.h>  #include "musb_core.h" @@ -36,6 +37,98 @@ struct ux500_glue {  };  #define glue_to_musb(g)	platform_get_drvdata(g->musb) +static void ux500_musb_set_vbus(struct musb *musb, int is_on) +{ +	u8            devctl; +	unsigned long timeout = jiffies + msecs_to_jiffies(1000); +	/* HDRC controls CPEN, but beware current surges during device +	 * connect.  They can trigger transient overcurrent conditions +	 * that must be ignored. +	 */ + +	devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + +	if (is_on) { +		if (musb->xceiv->state == OTG_STATE_A_IDLE) { +			/* start the session */ +			devctl |= MUSB_DEVCTL_SESSION; +			musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); +			/* +			 * Wait for the musb to set as A device to enable the +			 * VBUS +			 */ +			while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) { + +				if (time_after(jiffies, timeout)) { +					dev_err(musb->controller, +					"configured as A device timeout"); +					break; +				} +			} + +		} else { +			musb->is_active = 1; +			musb->xceiv->otg->default_a = 1; +			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; +			devctl |= MUSB_DEVCTL_SESSION; +			MUSB_HST_MODE(musb); +		} +	} else { +		musb->is_active = 0; + +		/* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and jumping +		 * right to B_IDLE... +		 */ +		musb->xceiv->otg->default_a = 0; +		devctl &= ~MUSB_DEVCTL_SESSION; +		MUSB_DEV_MODE(musb); +	} +	musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + +	/* +	 * Devctl values will be updated after vbus goes below +	 * session_valid. The time taken depends on the capacitance +	 * on VBUS line. The max discharge time can be upto 1 sec +	 * as per the spec. Typically on our platform, it is 200ms +	 */ +	if (!is_on) +		mdelay(200); + +	dev_dbg(musb->controller, "VBUS %s, devctl %02x\n", +		usb_otg_state_string(musb->xceiv->state), +		musb_readb(musb->mregs, MUSB_DEVCTL)); +} + +static int musb_otg_notifications(struct notifier_block *nb, +		unsigned long event, void *unused) +{ +	struct musb *musb = container_of(nb, struct musb, nb); + +	dev_dbg(musb->controller, "musb_otg_notifications %ld %s\n", +			event, usb_otg_state_string(musb->xceiv->state)); + +	switch (event) { +	case UX500_MUSB_ID: +		dev_dbg(musb->controller, "ID GND\n"); +		ux500_musb_set_vbus(musb, 1); +		break; +	case UX500_MUSB_VBUS: +		dev_dbg(musb->controller, "VBUS Connect\n"); +		break; +	case UX500_MUSB_NONE: +		dev_dbg(musb->controller, "VBUS Disconnect\n"); +		if (is_host_active(musb)) +			ux500_musb_set_vbus(musb, 0); +		else +			musb->xceiv->state = OTG_STATE_B_IDLE; +		break; +	default: +		dev_dbg(musb->controller, "ID float\n"); +		return NOTIFY_DONE; +	} +	return NOTIFY_OK; +} +  static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)  {  	unsigned long   flags; @@ -58,12 +151,21 @@ static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)  static int ux500_musb_init(struct musb *musb)  { +	int status; +  	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);  	if (IS_ERR_OR_NULL(musb->xceiv)) {  		pr_err("HS USB OTG: no transceiver configured\n");  		return -EPROBE_DEFER;  	} +	musb->nb.notifier_call = musb_otg_notifications; +	status = usb_register_notifier(musb->xceiv, &musb->nb); +	if (status < 0) { +		dev_dbg(musb->controller, "notification register failed\n"); +		return status; +	} +  	musb->isr = ux500_musb_interrupt;  	return 0; @@ -71,6 +173,8 @@ static int ux500_musb_init(struct musb *musb)  static int ux500_musb_exit(struct musb *musb)  { +	usb_unregister_notifier(musb->xceiv, &musb->nb); +  	usb_put_phy(musb->xceiv);  	return 0; @@ -79,6 +183,8 @@ static int ux500_musb_exit(struct musb *musb)  static const struct musb_platform_ops ux500_ops = {  	.init		= ux500_musb_init,  	.exit		= ux500_musb_exit, + +	.set_vbus	= ux500_musb_set_vbus,  };  static int ux500_probe(struct platform_device *pdev) diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index 039e567dd3b..33812064114 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -1,7 +1,7 @@  /*   * drivers/usb/musb/ux500_dma.c   * - * U8500 and U5500 DMA support code + * U8500 DMA support code   *   * Copyright (C) 2009 STMicroelectronics   * Copyright (C) 2011 ST-Ericsson SA @@ -30,6 +30,7 @@  #include <linux/dma-mapping.h>  #include <linux/dmaengine.h>  #include <linux/pfn.h> +#include <linux/sizes.h>  #include <linux/platform_data/usb-musb-ux500.h>  #include "musb_core.h" @@ -56,7 +57,7 @@ struct ux500_dma_controller {  };  /* Work function invoked from DMA callback to handle rx transfers. */ -void ux500_dma_callback(void *private_data) +static void ux500_dma_callback(void *private_data)  {  	struct dma_channel *channel = private_data;  	struct ux500_dma_channel *ux500_channel = channel->private_data; @@ -93,8 +94,9 @@ static bool ux500_configure_channel(struct dma_channel *channel,  	struct musb *musb = ux500_channel->controller->private_data;  	dev_dbg(musb->controller, -		"packet_sz=%d, mode=%d, dma_addr=0x%x, len=%d is_tx=%d\n", -		packet_sz, mode, dma_addr, len, ux500_channel->is_tx); +		"packet_sz=%d, mode=%d, dma_addr=0x%llu, len=%d is_tx=%d\n", +		packet_sz, mode, (unsigned long long) dma_addr, +		len, ux500_channel->is_tx);  	ux500_channel->cur_len = len; @@ -191,7 +193,7 @@ static int ux500_dma_is_compatible(struct dma_channel *channel,  		u16 maxpacket, void *buf, u32 length)  {  	if ((maxpacket & 0x3)		|| -		((int)buf & 0x3)	|| +		((unsigned long int) buf & 0x3)	||  		(length < 512)		||  		(length & 0x3))  		return false; @@ -372,12 +374,17 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba  	controller = kzalloc(sizeof(*controller), GFP_KERNEL);  	if (!controller) -		return NULL; +		goto kzalloc_fail;  	controller->private_data = musb;  	/* Save physical address for DMA controller. */  	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!iomem) { +		dev_err(musb->controller, "no memory resource defined\n"); +		goto plat_get_fail; +	} +  	controller->phy_base = (dma_addr_t) iomem->start;  	controller->controller.start = ux500_dma_controller_start; @@ -389,4 +396,9 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba  	controller->controller.is_compatible = ux500_dma_is_compatible;  	return &controller->controller; + +plat_get_fail: +	kfree(controller); +kzalloc_fail: +	return NULL;  } diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig deleted file mode 100644 index 37962c99ff1..00000000000 --- a/drivers/usb/otg/Kconfig +++ /dev/null @@ -1,141 +0,0 @@ -# -# USB OTG infrastructure may be needed for peripheral-only, host-only, -# or OTG-capable configurations when OTG transceivers or controllers -# are used. -# - -comment "OTG and related infrastructure" - -config USB_OTG_UTILS -	bool -	help -	  Select this to make sure the build includes objects from -	  the OTG infrastructure directory. - -if USB || USB_GADGET - -# -# USB Transceiver Drivers -# -config USB_GPIO_VBUS -	tristate "GPIO based peripheral-only VBUS sensing 'transceiver'" -	depends on GENERIC_GPIO -	select USB_OTG_UTILS -	help -	  Provides simple GPIO VBUS sensing for controllers with an -	  internal transceiver via the usb_phy interface, and -	  optionally control of a D+ pullup GPIO as well as a VBUS -	  current limit regulator. - -config ISP1301_OMAP -	tristate "Philips ISP1301 with OMAP OTG" -	depends on I2C && ARCH_OMAP_OTG -	select USB_OTG_UTILS -	help -	  If you say yes here you get support for the Philips ISP1301 -	  USB-On-The-Go transceiver working with the OMAP OTG controller. -	  The ISP1301 is a full speed USB  transceiver which is used in -	  products including H2, H3, and H4 development boards for Texas -	  Instruments OMAP processors. - -	  This driver can also be built as a module.  If so, the module -	  will be called isp1301_omap. - -config USB_ULPI -	bool "Generic ULPI Transceiver Driver" -	depends on ARM -	select USB_OTG_UTILS -	help -	  Enable this to support ULPI connected USB OTG transceivers which -	  are likely found on embedded boards. - -config USB_ULPI_VIEWPORT -	bool -	depends on USB_ULPI -	help -	  Provides read/write operations to the ULPI phy register set for -	  controllers with a viewport register (e.g. Chipidea/ARC controllers). - -config TWL4030_USB -	tristate "TWL4030 USB Transceiver Driver" -	depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS -	select USB_OTG_UTILS -	help -	  Enable this to support the USB OTG transceiver on TWL4030 -	  family chips (including the TWL5030 and TPS659x0 devices). -	  This transceiver supports high and full speed devices plus, -	  in host mode, low speed. - -config TWL6030_USB -	tristate "TWL6030 USB Transceiver Driver" -	depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS -	select USB_OTG_UTILS -	help -	  Enable this to support the USB OTG transceiver on TWL6030 -	  family chips. This TWL6030 transceiver has the VBUS and ID GND -	  and OTG SRP events capabilities. For all other transceiver functionality -	  UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs -	  are hooked to this driver through platform_data structure. -	  The definition of internal PHY APIs are in the mach-omap2 layer. - -config NOP_USB_XCEIV -	tristate "NOP USB Transceiver Driver" -	select USB_OTG_UTILS -	help -	  This driver is to be used by all the usb transceiver which are either -	  built-in with usb ip or which are autonomous and doesn't require any -	  phy programming such as ISP1x04 etc. - -config USB_MSM_OTG -	tristate "OTG support for Qualcomm on-chip USB controller" -	depends on (USB || USB_GADGET) && ARCH_MSM -	select USB_OTG_UTILS -	help -	  Enable this to support the USB OTG transceiver on MSM chips. It -	  handles PHY initialization, clock management, and workarounds -	  required after resetting the hardware and power management. -	  This driver is required even for peripheral only or host only -	  mode configurations. -	  This driver is not supported on boards like trout which -	  has an external PHY. - -config AB8500_USB -	tristate "AB8500 USB Transceiver Driver" -	depends on AB8500_CORE -	select USB_OTG_UTILS -	help -	  Enable this to support the USB OTG transceiver in AB8500 chip. -	  This transceiver supports high and full speed devices plus, -	  in host mode, low speed. - -config FSL_USB2_OTG -	bool "Freescale USB OTG Transceiver Driver" -	depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND -	select USB_OTG -	select USB_OTG_UTILS -	help -	  Enable this to support Freescale USB OTG transceiver. - -config USB_MXS_PHY -	tristate "Freescale MXS USB PHY support" -	depends on ARCH_MXC || ARCH_MXS -	select STMP_DEVICE -	select USB_OTG_UTILS -	help -	  Enable this to support the Freescale MXS USB PHY. - -	  MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x. - -config USB_MV_OTG -	tristate "Marvell USB OTG support" -	depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND -	select USB_OTG -	select USB_OTG_UTILS -	help -	  Say Y here if you want to build Marvell USB OTG transciever -	  driver in kernel (including PXA and MMP series). This driver -	  implements role switch between EHCI host driver and gadget driver. - -	  To compile this driver as a module, choose M here. - -endif # USB || OTG diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile deleted file mode 100644 index a844b8d35d1..00000000000 --- a/drivers/usb/otg/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# -# OTG infrastructure and transceiver drivers -# - -ccflags-$(CONFIG_USB_DEBUG)		:= -DDEBUG -ccflags-$(CONFIG_USB_GADGET_DEBUG)	+= -DDEBUG - -# infrastructure -obj-$(CONFIG_USB_OTG_UTILS)	+= otg.o - -# transceiver drivers -obj-$(CONFIG_USB_GPIO_VBUS)	+= gpio_vbus.o -obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o -obj-$(CONFIG_TWL4030_USB)	+= twl4030-usb.o -obj-$(CONFIG_TWL6030_USB)	+= twl6030-usb.o -obj-$(CONFIG_NOP_USB_XCEIV)	+= nop-usb-xceiv.o -obj-$(CONFIG_USB_ULPI)		+= ulpi.o -obj-$(CONFIG_USB_ULPI_VIEWPORT)	+= ulpi_viewport.o -obj-$(CONFIG_USB_MSM_OTG)	+= msm_otg.o -obj-$(CONFIG_AB8500_USB)	+= ab8500-usb.o -fsl_usb2_otg-objs		:= fsl_otg.o otg_fsm.o -obj-$(CONFIG_FSL_USB2_OTG)	+= fsl_usb2_otg.o -obj-$(CONFIG_USB_MXS_PHY)	+= mxs-phy.o -obj-$(CONFIG_USB_MV_OTG)	+= mv_otg.o diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c deleted file mode 100644 index 2d86f26a018..00000000000 --- a/drivers/usb/otg/ab8500-usb.c +++ /dev/null @@ -1,596 +0,0 @@ -/* - * drivers/usb/otg/ab8500_usb.c - * - * USB transceiver driver for AB8500 chip - * - * Copyright (C) 2010 ST-Ericsson AB - * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/usb/otg.h> -#include <linux/slab.h> -#include <linux/notifier.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/mfd/abx500.h> -#include <linux/mfd/abx500/ab8500.h> - -#define AB8500_MAIN_WD_CTRL_REG 0x01 -#define AB8500_USB_LINE_STAT_REG 0x80 -#define AB8500_USB_PHY_CTRL_REG 0x8A - -#define AB8500_BIT_OTG_STAT_ID (1 << 0) -#define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0) -#define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1) -#define AB8500_BIT_WD_CTRL_ENABLE (1 << 0) -#define AB8500_BIT_WD_CTRL_KICK (1 << 1) - -#define AB8500_V1x_LINK_STAT_WAIT (HZ/10) -#define AB8500_WD_KICK_DELAY_US 100 /* usec */ -#define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */ -#define AB8500_WD_V10_DISABLE_DELAY_MS 100 /* ms */ - -/* Usb line status register */ -enum ab8500_usb_link_status { -	USB_LINK_NOT_CONFIGURED = 0, -	USB_LINK_STD_HOST_NC, -	USB_LINK_STD_HOST_C_NS, -	USB_LINK_STD_HOST_C_S, -	USB_LINK_HOST_CHG_NM, -	USB_LINK_HOST_CHG_HS, -	USB_LINK_HOST_CHG_HS_CHIRP, -	USB_LINK_DEDICATED_CHG, -	USB_LINK_ACA_RID_A, -	USB_LINK_ACA_RID_B, -	USB_LINK_ACA_RID_C_NM, -	USB_LINK_ACA_RID_C_HS, -	USB_LINK_ACA_RID_C_HS_CHIRP, -	USB_LINK_HM_IDGND, -	USB_LINK_RESERVED, -	USB_LINK_NOT_VALID_LINK -}; - -struct ab8500_usb { -	struct usb_phy phy; -	struct device *dev; -	int irq_num_id_rise; -	int irq_num_id_fall; -	int irq_num_vbus_rise; -	int irq_num_vbus_fall; -	int irq_num_link_status; -	unsigned vbus_draw; -	struct delayed_work dwork; -	struct work_struct phy_dis_work; -	unsigned long link_status_wait; -	int rev; -}; - -static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x) -{ -	return container_of(x, struct ab8500_usb, phy); -} - -static void ab8500_usb_wd_workaround(struct ab8500_usb *ab) -{ -	abx500_set_register_interruptible(ab->dev, -		AB8500_SYS_CTRL2_BLOCK, -		AB8500_MAIN_WD_CTRL_REG, -		AB8500_BIT_WD_CTRL_ENABLE); - -	udelay(AB8500_WD_KICK_DELAY_US); - -	abx500_set_register_interruptible(ab->dev, -		AB8500_SYS_CTRL2_BLOCK, -		AB8500_MAIN_WD_CTRL_REG, -		(AB8500_BIT_WD_CTRL_ENABLE -		| AB8500_BIT_WD_CTRL_KICK)); - -	if (ab->rev > 0x10) /* v1.1 v2.0 */ -		udelay(AB8500_WD_V11_DISABLE_DELAY_US); -	else /* v1.0 */ -		msleep(AB8500_WD_V10_DISABLE_DELAY_MS); - -	abx500_set_register_interruptible(ab->dev, -		AB8500_SYS_CTRL2_BLOCK, -		AB8500_MAIN_WD_CTRL_REG, -		0); -} - -static void ab8500_usb_phy_ctrl(struct ab8500_usb *ab, bool sel_host, -					bool enable) -{ -	u8 ctrl_reg; -	abx500_get_register_interruptible(ab->dev, -				AB8500_USB, -				AB8500_USB_PHY_CTRL_REG, -				&ctrl_reg); -	if (sel_host) { -		if (enable) -			ctrl_reg |= AB8500_BIT_PHY_CTRL_HOST_EN; -		else -			ctrl_reg &= ~AB8500_BIT_PHY_CTRL_HOST_EN; -	} else { -		if (enable) -			ctrl_reg |= AB8500_BIT_PHY_CTRL_DEVICE_EN; -		else -			ctrl_reg &= ~AB8500_BIT_PHY_CTRL_DEVICE_EN; -	} - -	abx500_set_register_interruptible(ab->dev, -				AB8500_USB, -				AB8500_USB_PHY_CTRL_REG, -				ctrl_reg); - -	/* Needed to enable the phy.*/ -	if (enable) -		ab8500_usb_wd_workaround(ab); -} - -#define ab8500_usb_host_phy_en(ab)	ab8500_usb_phy_ctrl(ab, true, true) -#define ab8500_usb_host_phy_dis(ab)	ab8500_usb_phy_ctrl(ab, true, false) -#define ab8500_usb_peri_phy_en(ab)	ab8500_usb_phy_ctrl(ab, false, true) -#define ab8500_usb_peri_phy_dis(ab)	ab8500_usb_phy_ctrl(ab, false, false) - -static int ab8500_usb_link_status_update(struct ab8500_usb *ab) -{ -	u8 reg; -	enum ab8500_usb_link_status lsts; -	void *v = NULL; -	enum usb_phy_events event; - -	abx500_get_register_interruptible(ab->dev, -			AB8500_USB, -			AB8500_USB_LINE_STAT_REG, -			®); - -	lsts = (reg >> 3) & 0x0F; - -	switch (lsts) { -	case USB_LINK_NOT_CONFIGURED: -	case USB_LINK_RESERVED: -	case USB_LINK_NOT_VALID_LINK: -		/* TODO: Disable regulators. */ -		ab8500_usb_host_phy_dis(ab); -		ab8500_usb_peri_phy_dis(ab); -		ab->phy.state = OTG_STATE_B_IDLE; -		ab->phy.otg->default_a = false; -		ab->vbus_draw = 0; -		event = USB_EVENT_NONE; -		break; - -	case USB_LINK_STD_HOST_NC: -	case USB_LINK_STD_HOST_C_NS: -	case USB_LINK_STD_HOST_C_S: -	case USB_LINK_HOST_CHG_NM: -	case USB_LINK_HOST_CHG_HS: -	case USB_LINK_HOST_CHG_HS_CHIRP: -		if (ab->phy.otg->gadget) { -			/* TODO: Enable regulators. */ -			ab8500_usb_peri_phy_en(ab); -			v = ab->phy.otg->gadget; -		} -		event = USB_EVENT_VBUS; -		break; - -	case USB_LINK_HM_IDGND: -		if (ab->phy.otg->host) { -			/* TODO: Enable regulators. */ -			ab8500_usb_host_phy_en(ab); -			v = ab->phy.otg->host; -		} -		ab->phy.state = OTG_STATE_A_IDLE; -		ab->phy.otg->default_a = true; -		event = USB_EVENT_ID; -		break; - -	case USB_LINK_ACA_RID_A: -	case USB_LINK_ACA_RID_B: -		/* TODO */ -	case USB_LINK_ACA_RID_C_NM: -	case USB_LINK_ACA_RID_C_HS: -	case USB_LINK_ACA_RID_C_HS_CHIRP: -	case USB_LINK_DEDICATED_CHG: -		/* TODO: vbus_draw */ -		event = USB_EVENT_CHARGER; -		break; -	} - -	atomic_notifier_call_chain(&ab->phy.notifier, event, v); - -	return 0; -} - -static void ab8500_usb_delayed_work(struct work_struct *work) -{ -	struct ab8500_usb *ab = container_of(work, struct ab8500_usb, -						dwork.work); - -	ab8500_usb_link_status_update(ab); -} - -static irqreturn_t ab8500_usb_v1x_common_irq(int irq, void *data) -{ -	struct ab8500_usb *ab = (struct ab8500_usb *) data; - -	/* Wait for link status to become stable. */ -	schedule_delayed_work(&ab->dwork, ab->link_status_wait); - -	return IRQ_HANDLED; -} - -static irqreturn_t ab8500_usb_v1x_vbus_fall_irq(int irq, void *data) -{ -	struct ab8500_usb *ab = (struct ab8500_usb *) data; - -	/* Link status will not be updated till phy is disabled. */ -	ab8500_usb_peri_phy_dis(ab); - -	/* Wait for link status to become stable. */ -	schedule_delayed_work(&ab->dwork, ab->link_status_wait); - -	return IRQ_HANDLED; -} - -static irqreturn_t ab8500_usb_v20_irq(int irq, void *data) -{ -	struct ab8500_usb *ab = (struct ab8500_usb *) data; - -	ab8500_usb_link_status_update(ab); - -	return IRQ_HANDLED; -} - -static void ab8500_usb_phy_disable_work(struct work_struct *work) -{ -	struct ab8500_usb *ab = container_of(work, struct ab8500_usb, -						phy_dis_work); - -	if (!ab->phy.otg->host) -		ab8500_usb_host_phy_dis(ab); - -	if (!ab->phy.otg->gadget) -		ab8500_usb_peri_phy_dis(ab); -} - -static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA) -{ -	struct ab8500_usb *ab; - -	if (!phy) -		return -ENODEV; - -	ab = phy_to_ab(phy); - -	ab->vbus_draw = mA; - -	if (mA) -		atomic_notifier_call_chain(&ab->phy.notifier, -				USB_EVENT_ENUMERATED, ab->phy.otg->gadget); -	return 0; -} - -/* TODO: Implement some way for charging or other drivers to read - * ab->vbus_draw. - */ - -static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend) -{ -	/* TODO */ -	return 0; -} - -static int ab8500_usb_set_peripheral(struct usb_otg *otg, -					struct usb_gadget *gadget) -{ -	struct ab8500_usb *ab; - -	if (!otg) -		return -ENODEV; - -	ab = phy_to_ab(otg->phy); - -	/* Some drivers call this function in atomic context. -	 * Do not update ab8500 registers directly till this -	 * is fixed. -	 */ - -	if (!gadget) { -		/* TODO: Disable regulators. */ -		otg->gadget = NULL; -		schedule_work(&ab->phy_dis_work); -	} else { -		otg->gadget = gadget; -		otg->phy->state = OTG_STATE_B_IDLE; - -		/* Phy will not be enabled if cable is already -		 * plugged-in. Schedule to enable phy. -		 * Use same delay to avoid any race condition. -		 */ -		schedule_delayed_work(&ab->dwork, ab->link_status_wait); -	} - -	return 0; -} - -static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host) -{ -	struct ab8500_usb *ab; - -	if (!otg) -		return -ENODEV; - -	ab = phy_to_ab(otg->phy); - -	/* Some drivers call this function in atomic context. -	 * Do not update ab8500 registers directly till this -	 * is fixed. -	 */ - -	if (!host) { -		/* TODO: Disable regulators. */ -		otg->host = NULL; -		schedule_work(&ab->phy_dis_work); -	} else { -		otg->host = host; -		/* Phy will not be enabled if cable is already -		 * plugged-in. Schedule to enable phy. -		 * Use same delay to avoid any race condition. -		 */ -		schedule_delayed_work(&ab->dwork, ab->link_status_wait); -	} - -	return 0; -} - -static void ab8500_usb_irq_free(struct ab8500_usb *ab) -{ -	if (ab->rev < 0x20) { -		free_irq(ab->irq_num_id_rise, ab); -		free_irq(ab->irq_num_id_fall, ab); -		free_irq(ab->irq_num_vbus_rise, ab); -		free_irq(ab->irq_num_vbus_fall, ab); -	} else { -		free_irq(ab->irq_num_link_status, ab); -	} -} - -static int ab8500_usb_v1x_res_setup(struct platform_device *pdev, -				struct ab8500_usb *ab) -{ -	int err; - -	ab->irq_num_id_rise = platform_get_irq_byname(pdev, "ID_WAKEUP_R"); -	if (ab->irq_num_id_rise < 0) { -		dev_err(&pdev->dev, "ID rise irq not found\n"); -		return ab->irq_num_id_rise; -	} -	err = request_threaded_irq(ab->irq_num_id_rise, NULL, -		ab8500_usb_v1x_common_irq, -		IRQF_NO_SUSPEND | IRQF_SHARED, -		"usb-id-rise", ab); -	if (err < 0) { -		dev_err(ab->dev, "request_irq failed for ID rise irq\n"); -		goto fail0; -	} - -	ab->irq_num_id_fall = platform_get_irq_byname(pdev, "ID_WAKEUP_F"); -	if (ab->irq_num_id_fall < 0) { -		dev_err(&pdev->dev, "ID fall irq not found\n"); -		return ab->irq_num_id_fall; -	} -	err = request_threaded_irq(ab->irq_num_id_fall, NULL, -		ab8500_usb_v1x_common_irq, -		IRQF_NO_SUSPEND | IRQF_SHARED, -		"usb-id-fall", ab); -	if (err < 0) { -		dev_err(ab->dev, "request_irq failed for ID fall irq\n"); -		goto fail1; -	} - -	ab->irq_num_vbus_rise = platform_get_irq_byname(pdev, "VBUS_DET_R"); -	if (ab->irq_num_vbus_rise < 0) { -		dev_err(&pdev->dev, "VBUS rise irq not found\n"); -		return ab->irq_num_vbus_rise; -	} -	err = request_threaded_irq(ab->irq_num_vbus_rise, NULL, -		ab8500_usb_v1x_common_irq, -		IRQF_NO_SUSPEND | IRQF_SHARED, -		"usb-vbus-rise", ab); -	if (err < 0) { -		dev_err(ab->dev, "request_irq failed for Vbus rise irq\n"); -		goto fail2; -	} - -	ab->irq_num_vbus_fall = platform_get_irq_byname(pdev, "VBUS_DET_F"); -	if (ab->irq_num_vbus_fall < 0) { -		dev_err(&pdev->dev, "VBUS fall irq not found\n"); -		return ab->irq_num_vbus_fall; -	} -	err = request_threaded_irq(ab->irq_num_vbus_fall, NULL, -		ab8500_usb_v1x_vbus_fall_irq, -		IRQF_NO_SUSPEND | IRQF_SHARED, -		"usb-vbus-fall", ab); -	if (err < 0) { -		dev_err(ab->dev, "request_irq failed for Vbus fall irq\n"); -		goto fail3; -	} - -	return 0; -fail3: -	free_irq(ab->irq_num_vbus_rise, ab); -fail2: -	free_irq(ab->irq_num_id_fall, ab); -fail1: -	free_irq(ab->irq_num_id_rise, ab); -fail0: -	return err; -} - -static int ab8500_usb_v2_res_setup(struct platform_device *pdev, -				struct ab8500_usb *ab) -{ -	int err; - -	ab->irq_num_link_status = platform_get_irq_byname(pdev, -						"USB_LINK_STATUS"); -	if (ab->irq_num_link_status < 0) { -		dev_err(&pdev->dev, "Link status irq not found\n"); -		return ab->irq_num_link_status; -	} - -	err = request_threaded_irq(ab->irq_num_link_status, NULL, -		ab8500_usb_v20_irq, -		IRQF_NO_SUSPEND | IRQF_SHARED, -		"usb-link-status", ab); -	if (err < 0) { -		dev_err(ab->dev, -			"request_irq failed for link status irq\n"); -		return err; -	} - -	return 0; -} - -static int ab8500_usb_probe(struct platform_device *pdev) -{ -	struct ab8500_usb	*ab; -	struct usb_otg		*otg; -	int err; -	int rev; - -	rev = abx500_get_chip_id(&pdev->dev); -	if (rev < 0) { -		dev_err(&pdev->dev, "Chip id read failed\n"); -		return rev; -	} else if (rev < 0x10) { -		dev_err(&pdev->dev, "Unsupported AB8500 chip\n"); -		return -ENODEV; -	} - -	ab = kzalloc(sizeof *ab, GFP_KERNEL); -	if (!ab) -		return -ENOMEM; - -	otg = kzalloc(sizeof *otg, GFP_KERNEL); -	if (!otg) { -		kfree(ab); -		return -ENOMEM; -	} - -	ab->dev			= &pdev->dev; -	ab->rev			= rev; -	ab->phy.dev		= ab->dev; -	ab->phy.otg		= otg; -	ab->phy.label		= "ab8500"; -	ab->phy.set_suspend	= ab8500_usb_set_suspend; -	ab->phy.set_power	= ab8500_usb_set_power; -	ab->phy.state		= OTG_STATE_UNDEFINED; - -	otg->phy		= &ab->phy; -	otg->set_host		= ab8500_usb_set_host; -	otg->set_peripheral	= ab8500_usb_set_peripheral; - -	platform_set_drvdata(pdev, ab); - -	ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier); - -	/* v1: Wait for link status to become stable. -	 * all: Updates form set_host and set_peripheral as they are atomic. -	 */ -	INIT_DELAYED_WORK(&ab->dwork, ab8500_usb_delayed_work); - -	/* all: Disable phy when called from set_host and set_peripheral */ -	INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work); - -	if (ab->rev < 0x20) { -		err = ab8500_usb_v1x_res_setup(pdev, ab); -		ab->link_status_wait = AB8500_V1x_LINK_STAT_WAIT; -	} else { -		err = ab8500_usb_v2_res_setup(pdev, ab); -	} - -	if (err < 0) -		goto fail0; - -	err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2); -	if (err) { -		dev_err(&pdev->dev, "Can't register transceiver\n"); -		goto fail1; -	} - -	dev_info(&pdev->dev, "AB8500 usb driver initialized\n"); - -	return 0; -fail1: -	ab8500_usb_irq_free(ab); -fail0: -	kfree(otg); -	kfree(ab); -	return err; -} - -static int ab8500_usb_remove(struct platform_device *pdev) -{ -	struct ab8500_usb *ab = platform_get_drvdata(pdev); - -	ab8500_usb_irq_free(ab); - -	cancel_delayed_work_sync(&ab->dwork); - -	cancel_work_sync(&ab->phy_dis_work); - -	usb_remove_phy(&ab->phy); - -	ab8500_usb_host_phy_dis(ab); -	ab8500_usb_peri_phy_dis(ab); - -	platform_set_drvdata(pdev, NULL); - -	kfree(ab->phy.otg); -	kfree(ab); - -	return 0; -} - -static struct platform_driver ab8500_usb_driver = { -	.probe		= ab8500_usb_probe, -	.remove		= ab8500_usb_remove, -	.driver		= { -		.name	= "ab8500-usb", -		.owner	= THIS_MODULE, -	}, -}; - -static int __init ab8500_usb_init(void) -{ -	return platform_driver_register(&ab8500_usb_driver); -} -subsys_initcall(ab8500_usb_init); - -static void __exit ab8500_usb_exit(void) -{ -	platform_driver_unregister(&ab8500_usb_driver); -} -module_exit(ab8500_usb_exit); - -MODULE_ALIAS("platform:ab8500_usb"); -MODULE_AUTHOR("ST-Ericsson AB"); -MODULE_DESCRIPTION("AB8500 usb transceiver driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 65217a59006..aab2ab2fbc9 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -1,13 +1,74 @@  #  # Physical Layer USB driver configuration  # -comment "USB Physical Layer drivers" -	depends on USB || USB_GADGET +menuconfig USB_PHY +	bool "USB Physical Layer drivers" +	help +	  USB controllers (those which are host, device or DRD) need a +	  device to handle the physical layer signalling, commonly called +	  a PHY. + +	  The following drivers add support for such PHY devices. + +if USB_PHY + +# +# USB Transceiver Drivers +# +config AB8500_USB +	tristate "AB8500 USB Transceiver Driver" +	depends on AB8500_CORE +	help +	  Enable this to support the USB OTG transceiver in AB8500 chip. +	  This transceiver supports high and full speed devices plus, +	  in host mode, low speed. + +config FSL_USB2_OTG +	bool "Freescale USB OTG Transceiver Driver" +	depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND +	select USB_OTG +	help +	  Enable this to support Freescale USB OTG transceiver. + +config ISP1301_OMAP +	tristate "Philips ISP1301 with OMAP OTG" +	depends on I2C && ARCH_OMAP_OTG +	help +	  If you say yes here you get support for the Philips ISP1301 +	  USB-On-The-Go transceiver working with the OMAP OTG controller. +	  The ISP1301 is a full speed USB  transceiver which is used in +	  products including H2, H3, and H4 development boards for Texas +	  Instruments OMAP processors. + +	  This driver can also be built as a module.  If so, the module +	  will be called isp1301_omap. + +config MV_U3D_PHY +	bool "Marvell USB 3.0 PHY controller Driver" +	depends on CPU_MMP3 +	help +	  Enable this to support Marvell USB 3.0 phy controller for Marvell +	  SoC. + +config NOP_USB_XCEIV +	tristate "NOP USB Transceiver Driver" +	help +	  This driver is to be used by all the usb transceiver which are either +	  built-in with usb ip or which are autonomous and doesn't require any +	  phy programming such as ISP1x04 etc. + +config OMAP_CONTROL_USB +	tristate "OMAP CONTROL USB Driver" +	help +	  Enable this to add support for the USB part present in the control +	  module. This driver has API to power on the USB2 PHY and to write to +	  the mailbox. The mailbox is present only in omap4 and the register to +	  power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an +	  additional register to power on USB3 PHY.  config OMAP_USB2  	tristate "OMAP USB2 PHY Driver"  	depends on ARCH_OMAP2PLUS -	select USB_OTG_UTILS  	select OMAP_CONTROL_USB  	help  	  Enable this to support the transceiver that is part of SOC. This @@ -17,7 +78,6 @@ config OMAP_USB2  config OMAP_USB3  	tristate "OMAP USB3 PHY Driver" -	select USB_OTG_UTILS  	select OMAP_CONTROL_USB  	help  	  Enable this to support the USB3 PHY that is part of SOC. This @@ -25,19 +85,61 @@ config OMAP_USB3  	  This driver interacts with the "OMAP Control USB Driver" to power  	  on/off the PHY. -config OMAP_CONTROL_USB -	tristate "OMAP CONTROL USB Driver" +config SAMSUNG_USBPHY +	tristate "Samsung USB PHY Driver"  	help -	  Enable this to add support for the USB part present in the control -	  module. This driver has API to power on the USB2 PHY and to write to -	  the mailbox. The mailbox is present only in omap4 and the register to -	  power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an -	  additional register to power on USB3 PHY. +	  Enable this to support Samsung USB phy helper driver for Samsung SoCs. +	  This driver provides common interface to interact, for Samsung USB 2.0 PHY +	  driver and later for Samsung USB 3.0 PHY driver. + +config SAMSUNG_USB2PHY +	tristate "Samsung USB 2.0 PHY controller Driver" +	select SAMSUNG_USBPHY +	help +	  Enable this to support Samsung USB 2.0 (High Speed) PHY controller +	  driver for Samsung SoCs. + +config SAMSUNG_USB3PHY +	tristate "Samsung USB 3.0 PHY controller Driver" +	select SAMSUNG_USBPHY +	help +	  Enable this to support Samsung USB 3.0 (Super Speed) phy controller +	  for samsung SoCs. + +config TWL4030_USB +	tristate "TWL4030 USB Transceiver Driver" +	depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS +	help +	  Enable this to support the USB OTG transceiver on TWL4030 +	  family chips (including the TWL5030 and TPS659x0 devices). +	  This transceiver supports high and full speed devices plus, +	  in host mode, low speed. + +config TWL6030_USB +	tristate "TWL6030 USB Transceiver Driver" +	depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS +	help +	  Enable this to support the USB OTG transceiver on TWL6030 +	  family chips. This TWL6030 transceiver has the VBUS and ID GND +	  and OTG SRP events capabilities. For all other transceiver functionality +	  UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs +	  are hooked to this driver through platform_data structure. +	  The definition of internal PHY APIs are in the mach-omap2 layer. + +config USB_GPIO_VBUS +	tristate "GPIO based peripheral-only VBUS sensing 'transceiver'" +	depends on GENERIC_GPIO +	help +	  Provides simple GPIO VBUS sensing for controllers with an +	  internal transceiver via the usb_phy interface, and +	  optionally control of a D+ pullup GPIO as well as a VBUS +	  current limit regulator.  config USB_ISP1301  	tristate "NXP ISP1301 USB transceiver support"  	depends on USB || USB_GADGET  	depends on I2C +	select USB_OTG_UTILS  	help  	  Say Y here to add support for the NXP ISP1301 USB transceiver driver.  	  This chip is typically used as USB transceiver for USB host, gadget @@ -46,18 +148,41 @@ config USB_ISP1301  	  To compile this driver as a module, choose M here: the  	  module will be called isp1301. -config MV_U3D_PHY -	bool "Marvell USB 3.0 PHY controller Driver" -	depends on USB_MV_U3D -	select USB_OTG_UTILS +config USB_MSM_OTG +	tristate "OTG support for Qualcomm on-chip USB controller" +	depends on (USB || USB_GADGET) && ARCH_MSM  	help -	  Enable this to support Marvell USB 3.0 phy controller for Marvell -	  SoC. +	  Enable this to support the USB OTG transceiver on MSM chips. It +	  handles PHY initialization, clock management, and workarounds +	  required after resetting the hardware and power management. +	  This driver is required even for peripheral only or host only +	  mode configurations. +	  This driver is not supported on boards like trout which +	  has an external PHY. + +config USB_MV_OTG +	tristate "Marvell USB OTG support" +	depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND +	select USB_OTG +	help +	  Say Y here if you want to build Marvell USB OTG transciever +	  driver in kernel (including PXA and MMP series). This driver +	  implements role switch between EHCI host driver and gadget driver. + +	  To compile this driver as a module, choose M here. + +config USB_MXS_PHY +	tristate "Freescale MXS USB PHY support" +	depends on ARCH_MXC || ARCH_MXS +	select STMP_DEVICE +	help +	  Enable this to support the Freescale MXS USB PHY. + +	  MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x.  config USB_RCAR_PHY  	tristate "Renesas R-Car USB phy support"  	depends on USB || USB_GADGET -	select USB_OTG_UTILS  	help  	  Say Y here to add support for the Renesas R-Car USB phy driver.  	  This chip is typically used as USB phy for USB host, gadget. @@ -66,10 +191,18 @@ config USB_RCAR_PHY  	  To compile this driver as a module, choose M here: the  	  module will be called rcar-phy. -config SAMSUNG_USBPHY -	bool "Samsung USB PHY controller Driver" -	depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS -	select USB_OTG_UTILS +config USB_ULPI +	bool "Generic ULPI Transceiver Driver" +	depends on ARM +	help +	  Enable this to support ULPI connected USB OTG transceivers which +	  are likely found on embedded boards. + +config USB_ULPI_VIEWPORT +	bool +	depends on USB_ULPI  	help -	  Enable this to support Samsung USB phy controller for samsung -	  SoCs. +	  Provides read/write operations to the ULPI phy register set for +	  controllers with a viewport register (e.g. Chipidea/ARC controllers). + +endif # USB_PHY diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index b13faa193e0..a9169cb1e6f 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -4,11 +4,30 @@  ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG -obj-$(CONFIG_OMAP_USB2)			+= omap-usb2.o -obj-$(CONFIG_OMAP_USB3)			+= omap-usb3.o -obj-$(CONFIG_OMAP_CONTROL_USB)		+= omap-control-usb.o -obj-$(CONFIG_USB_ISP1301)		+= isp1301.o -obj-$(CONFIG_MV_U3D_PHY)		+= mv_u3d_phy.o -obj-$(CONFIG_USB_EHCI_TEGRA)	+= tegra_usb_phy.o -obj-$(CONFIG_USB_RCAR_PHY)		+= rcar-phy.o -obj-$(CONFIG_SAMSUNG_USBPHY)		+= samsung-usbphy.o +obj-$(CONFIG_USB_PHY)			+= phy.o + +# transceiver drivers, keep the list sorted + +obj-$(CONFIG_AB8500_USB)		+= phy-ab8500-usb.o +phy-fsl-usb2-objs			:= phy-fsl-usb.o phy-fsm-usb.o +obj-$(CONFIG_FSL_USB2_OTG)		+= phy-fsl-usb2.o +obj-$(CONFIG_ISP1301_OMAP)		+= phy-isp1301-omap.o +obj-$(CONFIG_MV_U3D_PHY)		+= phy-mv-u3d-usb.o +obj-$(CONFIG_NOP_USB_XCEIV)		+= phy-nop.o +obj-$(CONFIG_OMAP_CONTROL_USB)		+= phy-omap-control.o +obj-$(CONFIG_OMAP_USB2)			+= phy-omap-usb2.o +obj-$(CONFIG_OMAP_USB3)			+= phy-omap-usb3.o +obj-$(CONFIG_SAMSUNG_USBPHY)		+= phy-samsung-usb.o +obj-$(CONFIG_SAMSUNG_USB2PHY)		+= phy-samsung-usb2.o +obj-$(CONFIG_SAMSUNG_USB3PHY)		+= phy-samsung-usb3.o +obj-$(CONFIG_TWL4030_USB)		+= phy-twl4030-usb.o +obj-$(CONFIG_TWL6030_USB)		+= phy-twl6030-usb.o +obj-$(CONFIG_USB_EHCI_TEGRA)		+= phy-tegra-usb.o +obj-$(CONFIG_USB_GPIO_VBUS)		+= phy-gpio-vbus-usb.o +obj-$(CONFIG_USB_ISP1301)		+= phy-isp1301.o +obj-$(CONFIG_USB_MSM_OTG)		+= phy-msm-usb.o +obj-$(CONFIG_USB_MV_OTG)		+= phy-mv-usb.o +obj-$(CONFIG_USB_MXS_PHY)		+= phy-mxs-usb.o +obj-$(CONFIG_USB_RCAR_PHY)		+= phy-rcar-usb.o +obj-$(CONFIG_USB_ULPI)			+= phy-ulpi.o +obj-$(CONFIG_USB_ULPI_VIEWPORT)		+= phy-ulpi-viewport.o diff --git a/drivers/usb/phy/isp1301.c b/drivers/usb/phy/isp1301.c deleted file mode 100644 index 18dbf7e3760..00000000000 --- a/drivers/usb/phy/isp1301.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * NXP ISP1301 USB transceiver driver - * - * Copyright (C) 2012 Roland Stigge - * - * Author: Roland Stigge <stigge@antcom.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/i2c.h> - -#define DRV_NAME		"isp1301" - -static const struct i2c_device_id isp1301_id[] = { -	{ "isp1301", 0 }, -	{ } -}; - -static struct i2c_client *isp1301_i2c_client; - -static int isp1301_probe(struct i2c_client *client, -			 const struct i2c_device_id *i2c_id) -{ -	isp1301_i2c_client = client; -	return 0; -} - -static int isp1301_remove(struct i2c_client *client) -{ -	return 0; -} - -static struct i2c_driver isp1301_driver = { -	.driver = { -		.name = DRV_NAME, -	}, -	.probe = isp1301_probe, -	.remove = isp1301_remove, -	.id_table = isp1301_id, -}; - -module_i2c_driver(isp1301_driver); - -static int match(struct device *dev, void *data) -{ -	struct device_node *node = (struct device_node *)data; -	return (dev->of_node == node) && -		(dev->driver == &isp1301_driver.driver); -} - -struct i2c_client *isp1301_get_client(struct device_node *node) -{ -	if (node) { /* reference of ISP1301 I2C node via DT */ -		struct device *dev = bus_find_device(&i2c_bus_type, NULL, -						     node, match); -		if (!dev) -			return NULL; -		return to_i2c_client(dev); -	} else { /* non-DT: only one ISP1301 chip supported */ -		return isp1301_i2c_client; -	} -} -EXPORT_SYMBOL_GPL(isp1301_get_client); - -MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); -MODULE_DESCRIPTION("NXP ISP1301 USB transceiver driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c new file mode 100644 index 00000000000..4acef26a2ef --- /dev/null +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -0,0 +1,924 @@ +/* + * drivers/usb/otg/ab8500_usb.c + * + * USB transceiver driver for AB8500 chip + * + * Copyright (C) 2010 ST-Ericsson AB + * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.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; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/usb/otg.h> +#include <linux/slab.h> +#include <linux/notifier.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/mfd/abx500.h> +#include <linux/mfd/abx500/ab8500.h> +#include <linux/usb/musb-ux500.h> +#include <linux/regulator/consumer.h> +#include <linux/pinctrl/consumer.h> + +/* Bank AB8500_SYS_CTRL2_BLOCK */ +#define AB8500_MAIN_WD_CTRL_REG 0x01 + +/* Bank AB8500_USB */ +#define AB8500_USB_LINE_STAT_REG 0x80 +#define AB8505_USB_LINE_STAT_REG 0x94 +#define AB8500_USB_PHY_CTRL_REG 0x8A + +/* Bank AB8500_DEVELOPMENT */ +#define AB8500_BANK12_ACCESS 0x00 + +/* Bank AB8500_DEBUG */ +#define AB8500_USB_PHY_TUNE1 0x05 +#define AB8500_USB_PHY_TUNE2 0x06 +#define AB8500_USB_PHY_TUNE3 0x07 + +#define AB8500_BIT_OTG_STAT_ID (1 << 0) +#define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0) +#define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1) +#define AB8500_BIT_WD_CTRL_ENABLE (1 << 0) +#define AB8500_BIT_WD_CTRL_KICK (1 << 1) + +#define AB8500_WD_KICK_DELAY_US 100 /* usec */ +#define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */ +#define AB8500_V20_31952_DISABLE_DELAY_US 100 /* usec */ + +/* Usb line status register */ +enum ab8500_usb_link_status { +	USB_LINK_NOT_CONFIGURED_8500 = 0, +	USB_LINK_STD_HOST_NC_8500, +	USB_LINK_STD_HOST_C_NS_8500, +	USB_LINK_STD_HOST_C_S_8500, +	USB_LINK_HOST_CHG_NM_8500, +	USB_LINK_HOST_CHG_HS_8500, +	USB_LINK_HOST_CHG_HS_CHIRP_8500, +	USB_LINK_DEDICATED_CHG_8500, +	USB_LINK_ACA_RID_A_8500, +	USB_LINK_ACA_RID_B_8500, +	USB_LINK_ACA_RID_C_NM_8500, +	USB_LINK_ACA_RID_C_HS_8500, +	USB_LINK_ACA_RID_C_HS_CHIRP_8500, +	USB_LINK_HM_IDGND_8500, +	USB_LINK_RESERVED_8500, +	USB_LINK_NOT_VALID_LINK_8500, +}; + +enum ab8505_usb_link_status { +	USB_LINK_NOT_CONFIGURED_8505 = 0, +	USB_LINK_STD_HOST_NC_8505, +	USB_LINK_STD_HOST_C_NS_8505, +	USB_LINK_STD_HOST_C_S_8505, +	USB_LINK_CDP_8505, +	USB_LINK_RESERVED0_8505, +	USB_LINK_RESERVED1_8505, +	USB_LINK_DEDICATED_CHG_8505, +	USB_LINK_ACA_RID_A_8505, +	USB_LINK_ACA_RID_B_8505, +	USB_LINK_ACA_RID_C_NM_8505, +	USB_LINK_RESERVED2_8505, +	USB_LINK_RESERVED3_8505, +	USB_LINK_HM_IDGND_8505, +	USB_LINK_CHARGERPORT_NOT_OK_8505, +	USB_LINK_CHARGER_DM_HIGH_8505, +	USB_LINK_PHYEN_NO_VBUS_NO_IDGND_8505, +	USB_LINK_STD_UPSTREAM_NO_IDGNG_NO_VBUS_8505, +	USB_LINK_STD_UPSTREAM_8505, +	USB_LINK_CHARGER_SE1_8505, +	USB_LINK_CARKIT_CHGR_1_8505, +	USB_LINK_CARKIT_CHGR_2_8505, +	USB_LINK_ACA_DOCK_CHGR_8505, +	USB_LINK_SAMSUNG_BOOT_CBL_PHY_EN_8505, +	USB_LINK_SAMSUNG_BOOT_CBL_PHY_DISB_8505, +	USB_LINK_SAMSUNG_UART_CBL_PHY_EN_8505, +	USB_LINK_SAMSUNG_UART_CBL_PHY_DISB_8505, +	USB_LINK_MOTOROLA_FACTORY_CBL_PHY_EN_8505, +}; + +enum ab8500_usb_mode { +	USB_IDLE = 0, +	USB_PERIPHERAL, +	USB_HOST, +	USB_DEDICATED_CHG +}; + +struct ab8500_usb { +	struct usb_phy phy; +	struct device *dev; +	struct ab8500 *ab8500; +	unsigned vbus_draw; +	struct work_struct phy_dis_work; +	enum ab8500_usb_mode mode; +	struct regulator *v_ape; +	struct regulator *v_musb; +	struct regulator *v_ulpi; +	int saved_v_ulpi; +	int previous_link_status_state; +	struct pinctrl *pinctrl; +	struct pinctrl_state *pins_sleep; +}; + +static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x) +{ +	return container_of(x, struct ab8500_usb, phy); +} + +static void ab8500_usb_wd_workaround(struct ab8500_usb *ab) +{ +	abx500_set_register_interruptible(ab->dev, +		AB8500_SYS_CTRL2_BLOCK, +		AB8500_MAIN_WD_CTRL_REG, +		AB8500_BIT_WD_CTRL_ENABLE); + +	udelay(AB8500_WD_KICK_DELAY_US); + +	abx500_set_register_interruptible(ab->dev, +		AB8500_SYS_CTRL2_BLOCK, +		AB8500_MAIN_WD_CTRL_REG, +		(AB8500_BIT_WD_CTRL_ENABLE +		| AB8500_BIT_WD_CTRL_KICK)); + +	udelay(AB8500_WD_V11_DISABLE_DELAY_US); + +	abx500_set_register_interruptible(ab->dev, +		AB8500_SYS_CTRL2_BLOCK, +		AB8500_MAIN_WD_CTRL_REG, +		0); +} + +static void ab8500_usb_regulator_enable(struct ab8500_usb *ab) +{ +	int ret, volt; + +	ret = regulator_enable(ab->v_ape); +	if (ret) +		dev_err(ab->dev, "Failed to enable v-ape\n"); + +	if (!is_ab8500_2p0_or_earlier(ab->ab8500)) { +		ab->saved_v_ulpi = regulator_get_voltage(ab->v_ulpi); +		if (ab->saved_v_ulpi < 0) +			dev_err(ab->dev, "Failed to get v_ulpi voltage\n"); + +		ret = regulator_set_voltage(ab->v_ulpi, 1300000, 1350000); +		if (ret < 0) +			dev_err(ab->dev, "Failed to set the Vintcore to 1.3V, ret=%d\n", +					ret); + +		ret = regulator_set_optimum_mode(ab->v_ulpi, 28000); +		if (ret < 0) +			dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n", +					ret); +	} + +	ret = regulator_enable(ab->v_ulpi); +	if (ret) +		dev_err(ab->dev, "Failed to enable vddulpivio18\n"); + +	if (!is_ab8500_2p0_or_earlier(ab->ab8500)) { +		volt = regulator_get_voltage(ab->v_ulpi); +		if ((volt != 1300000) && (volt != 1350000)) +			dev_err(ab->dev, "Vintcore is not set to 1.3V volt=%d\n", +					volt); +	} + +	ret = regulator_enable(ab->v_musb); +	if (ret) +		dev_err(ab->dev, "Failed to enable musb_1v8\n"); +} + +static void ab8500_usb_regulator_disable(struct ab8500_usb *ab) +{ +	int ret; + +	regulator_disable(ab->v_musb); + +	regulator_disable(ab->v_ulpi); + +	/* USB is not the only consumer of Vintcore, restore old settings */ +	if (!is_ab8500_2p0_or_earlier(ab->ab8500)) { +		if (ab->saved_v_ulpi > 0) { +			ret = regulator_set_voltage(ab->v_ulpi, +					ab->saved_v_ulpi, ab->saved_v_ulpi); +			if (ret < 0) +				dev_err(ab->dev, "Failed to set the Vintcore to %duV, ret=%d\n", +						ab->saved_v_ulpi, ret); +		} + +		ret = regulator_set_optimum_mode(ab->v_ulpi, 0); +		if (ret < 0) +			dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n", +					ret); +	} + +	regulator_disable(ab->v_ape); +} + +static void ab8500_usb_wd_linkstatus(struct ab8500_usb *ab, u8 bit) +{ +	/* Workaround for v2.0 bug # 31952 */ +	if (is_ab8500_2p0(ab->ab8500)) { +		abx500_mask_and_set_register_interruptible(ab->dev, +				AB8500_USB, AB8500_USB_PHY_CTRL_REG, +				bit, bit); +		udelay(AB8500_V20_31952_DISABLE_DELAY_US); +	} +} + +static void ab8500_usb_phy_enable(struct ab8500_usb *ab, bool sel_host) +{ +	u8 bit; +	bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN : +		AB8500_BIT_PHY_CTRL_DEVICE_EN; + +	/* mux and configure USB pins to DEFAULT state */ +	ab->pinctrl = pinctrl_get_select(ab->dev, PINCTRL_STATE_DEFAULT); +	if (IS_ERR(ab->pinctrl)) +		dev_err(ab->dev, "could not get/set default pinstate\n"); + +	ab8500_usb_regulator_enable(ab); + +	abx500_mask_and_set_register_interruptible(ab->dev, +			AB8500_USB, AB8500_USB_PHY_CTRL_REG, +			bit, bit); +} + +static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host) +{ +	u8 bit; +	bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN : +		AB8500_BIT_PHY_CTRL_DEVICE_EN; + +	ab8500_usb_wd_linkstatus(ab, bit); + +	abx500_mask_and_set_register_interruptible(ab->dev, +			AB8500_USB, AB8500_USB_PHY_CTRL_REG, +			bit, 0); + +	/* Needed to disable the phy.*/ +	ab8500_usb_wd_workaround(ab); + +	ab8500_usb_regulator_disable(ab); + +	if (!IS_ERR(ab->pinctrl)) { +		/* configure USB pins to SLEEP state */ +		ab->pins_sleep = pinctrl_lookup_state(ab->pinctrl, +				PINCTRL_STATE_SLEEP); + +		if (IS_ERR(ab->pins_sleep)) +			dev_dbg(ab->dev, "could not get sleep pinstate\n"); +		else if (pinctrl_select_state(ab->pinctrl, ab->pins_sleep)) +			dev_err(ab->dev, "could not set pins to sleep state\n"); + +		/* as USB pins are shared with idddet, release them to allow +		 * iddet to request them +		 */ +		pinctrl_put(ab->pinctrl); +	} +} + +#define ab8500_usb_host_phy_en(ab)	ab8500_usb_phy_enable(ab, true) +#define ab8500_usb_host_phy_dis(ab)	ab8500_usb_phy_disable(ab, true) +#define ab8500_usb_peri_phy_en(ab)	ab8500_usb_phy_enable(ab, false) +#define ab8500_usb_peri_phy_dis(ab)	ab8500_usb_phy_disable(ab, false) + +static int ab8505_usb_link_status_update(struct ab8500_usb *ab, +		enum ab8505_usb_link_status lsts) +{ +	enum ux500_musb_vbus_id_status event = 0; + +	dev_dbg(ab->dev, "ab8505_usb_link_status_update %d\n", lsts); + +	/* +	 * Spurious link_status interrupts are seen at the time of +	 * disconnection of a device in RIDA state +	 */ +	if (ab->previous_link_status_state == USB_LINK_ACA_RID_A_8505 && +			(lsts == USB_LINK_STD_HOST_NC_8505)) +		return 0; + +	ab->previous_link_status_state = lsts; + +	switch (lsts) { +	case USB_LINK_ACA_RID_B_8505: +		event = UX500_MUSB_RIDB; +	case USB_LINK_NOT_CONFIGURED_8505: +	case USB_LINK_RESERVED0_8505: +	case USB_LINK_RESERVED1_8505: +	case USB_LINK_RESERVED2_8505: +	case USB_LINK_RESERVED3_8505: +		ab->mode = USB_IDLE; +		ab->phy.otg->default_a = false; +		ab->vbus_draw = 0; +		if (event != UX500_MUSB_RIDB) +			event = UX500_MUSB_NONE; +		/* +		 * Fallback to default B_IDLE as nothing +		 * is connected +		 */ +		ab->phy.state = OTG_STATE_B_IDLE; +		break; + +	case USB_LINK_ACA_RID_C_NM_8505: +		event = UX500_MUSB_RIDC; +	case USB_LINK_STD_HOST_NC_8505: +	case USB_LINK_STD_HOST_C_NS_8505: +	case USB_LINK_STD_HOST_C_S_8505: +	case USB_LINK_CDP_8505: +		if (ab->mode == USB_IDLE) { +			ab->mode = USB_PERIPHERAL; +			ab8500_usb_peri_phy_en(ab); +			atomic_notifier_call_chain(&ab->phy.notifier, +					UX500_MUSB_PREPARE, &ab->vbus_draw); +		} +		if (event != UX500_MUSB_RIDC) +			event = UX500_MUSB_VBUS; +		break; + +	case USB_LINK_ACA_RID_A_8505: +	case USB_LINK_ACA_DOCK_CHGR_8505: +		event = UX500_MUSB_RIDA; +	case USB_LINK_HM_IDGND_8505: +		if (ab->mode == USB_IDLE) { +			ab->mode = USB_HOST; +			ab8500_usb_host_phy_en(ab); +			atomic_notifier_call_chain(&ab->phy.notifier, +					UX500_MUSB_PREPARE, &ab->vbus_draw); +		} +		ab->phy.otg->default_a = true; +		if (event != UX500_MUSB_RIDA) +			event = UX500_MUSB_ID; +		atomic_notifier_call_chain(&ab->phy.notifier, +				event, &ab->vbus_draw); +		break; + +	case USB_LINK_DEDICATED_CHG_8505: +		ab->mode = USB_DEDICATED_CHG; +		event = UX500_MUSB_CHARGER; +		atomic_notifier_call_chain(&ab->phy.notifier, +				event, &ab->vbus_draw); +		break; + +	default: +		break; +	} + +	return 0; +} + +static int ab8500_usb_link_status_update(struct ab8500_usb *ab, +		enum ab8500_usb_link_status lsts) +{ +	enum ux500_musb_vbus_id_status event = 0; + +	dev_dbg(ab->dev, "ab8500_usb_link_status_update %d\n", lsts); + +	/* +	 * Spurious link_status interrupts are seen in case of a +	 * disconnection of a device in IDGND and RIDA stage +	 */ +	if (ab->previous_link_status_state == USB_LINK_HM_IDGND_8500 && +			(lsts == USB_LINK_STD_HOST_C_NS_8500 || +			 lsts == USB_LINK_STD_HOST_NC_8500)) +		return 0; + +	if (ab->previous_link_status_state == USB_LINK_ACA_RID_A_8500 && +			lsts == USB_LINK_STD_HOST_NC_8500) +		return 0; + +	ab->previous_link_status_state = lsts; + +	switch (lsts) { +	case USB_LINK_ACA_RID_B_8500: +		event = UX500_MUSB_RIDB; +	case USB_LINK_NOT_CONFIGURED_8500: +	case USB_LINK_NOT_VALID_LINK_8500: +		ab->mode = USB_IDLE; +		ab->phy.otg->default_a = false; +		ab->vbus_draw = 0; +		if (event != UX500_MUSB_RIDB) +			event = UX500_MUSB_NONE; +		/* Fallback to default B_IDLE as nothing is connected */ +		ab->phy.state = OTG_STATE_B_IDLE; +		break; + +	case USB_LINK_ACA_RID_C_NM_8500: +	case USB_LINK_ACA_RID_C_HS_8500: +	case USB_LINK_ACA_RID_C_HS_CHIRP_8500: +		event = UX500_MUSB_RIDC; +	case USB_LINK_STD_HOST_NC_8500: +	case USB_LINK_STD_HOST_C_NS_8500: +	case USB_LINK_STD_HOST_C_S_8500: +	case USB_LINK_HOST_CHG_NM_8500: +	case USB_LINK_HOST_CHG_HS_8500: +	case USB_LINK_HOST_CHG_HS_CHIRP_8500: +		if (ab->mode == USB_IDLE) { +			ab->mode = USB_PERIPHERAL; +			ab8500_usb_peri_phy_en(ab); +			atomic_notifier_call_chain(&ab->phy.notifier, +					UX500_MUSB_PREPARE, &ab->vbus_draw); +		} +		if (event != UX500_MUSB_RIDC) +			event = UX500_MUSB_VBUS; +		break; + +	case USB_LINK_ACA_RID_A_8500: +		event = UX500_MUSB_RIDA; +	case USB_LINK_HM_IDGND_8500: +		if (ab->mode == USB_IDLE) { +			ab->mode = USB_HOST; +			ab8500_usb_host_phy_en(ab); +			atomic_notifier_call_chain(&ab->phy.notifier, +					UX500_MUSB_PREPARE, &ab->vbus_draw); +		} +		ab->phy.otg->default_a = true; +		if (event != UX500_MUSB_RIDA) +			event = UX500_MUSB_ID; +		atomic_notifier_call_chain(&ab->phy.notifier, +				event, &ab->vbus_draw); +		break; + +	case USB_LINK_DEDICATED_CHG_8500: +		ab->mode = USB_DEDICATED_CHG; +		event = UX500_MUSB_CHARGER; +		atomic_notifier_call_chain(&ab->phy.notifier, +				event, &ab->vbus_draw); +		break; + +	case USB_LINK_RESERVED_8500: +		break; +	} + +	return 0; +} + +/* + * Connection Sequence: + *   1. Link Status Interrupt + *   2. Enable AB clock + *   3. Enable AB regulators + *   4. Enable USB phy + *   5. Reset the musb controller + *   6. Switch the ULPI GPIO pins to fucntion mode + *   7. Enable the musb Peripheral5 clock + *   8. Restore MUSB context + */ +static int abx500_usb_link_status_update(struct ab8500_usb *ab) +{ +	u8 reg; +	int ret = 0; + +	if (is_ab8500(ab->ab8500)) { +		enum ab8500_usb_link_status lsts; + +		abx500_get_register_interruptible(ab->dev, +				AB8500_USB, AB8500_USB_LINE_STAT_REG, ®); +		lsts = (reg >> 3) & 0x0F; +		ret = ab8500_usb_link_status_update(ab, lsts); +	} else if (is_ab8505(ab->ab8500)) { +		enum ab8505_usb_link_status lsts; + +		abx500_get_register_interruptible(ab->dev, +				AB8500_USB, AB8505_USB_LINE_STAT_REG, ®); +		lsts = (reg >> 3) & 0x1F; +		ret = ab8505_usb_link_status_update(ab, lsts); +	} + +	return ret; +} + +/* + * Disconnection Sequence: + *   1. Disconect Interrupt + *   2. Disable regulators + *   3. Disable AB clock + *   4. Disable the Phy + *   5. Link Status Interrupt + *   6. Disable Musb Clock + */ +static irqreturn_t ab8500_usb_disconnect_irq(int irq, void *data) +{ +	struct ab8500_usb *ab = (struct ab8500_usb *) data; +	enum usb_phy_events event = UX500_MUSB_NONE; + +	/* Link status will not be updated till phy is disabled. */ +	if (ab->mode == USB_HOST) { +		ab->phy.otg->default_a = false; +		ab->vbus_draw = 0; +		atomic_notifier_call_chain(&ab->phy.notifier, +				event, &ab->vbus_draw); +		ab8500_usb_host_phy_dis(ab); +		ab->mode = USB_IDLE; +	} + +	if (ab->mode == USB_PERIPHERAL) { +		atomic_notifier_call_chain(&ab->phy.notifier, +				event, &ab->vbus_draw); +		ab8500_usb_peri_phy_dis(ab); +		atomic_notifier_call_chain(&ab->phy.notifier, +				UX500_MUSB_CLEAN, &ab->vbus_draw); +		ab->mode = USB_IDLE; +		ab->phy.otg->default_a = false; +		ab->vbus_draw = 0; +	} + +	if (is_ab8500_2p0(ab->ab8500)) { +		if (ab->mode == USB_DEDICATED_CHG) { +			ab8500_usb_wd_linkstatus(ab, +					AB8500_BIT_PHY_CTRL_DEVICE_EN); +			abx500_mask_and_set_register_interruptible(ab->dev, +					AB8500_USB, AB8500_USB_PHY_CTRL_REG, +					AB8500_BIT_PHY_CTRL_DEVICE_EN, 0); +		} +	} + +	return IRQ_HANDLED; +} + +static irqreturn_t ab8500_usb_link_status_irq(int irq, void *data) +{ +	struct ab8500_usb *ab = (struct ab8500_usb *) data; + +	abx500_usb_link_status_update(ab); + +	return IRQ_HANDLED; +} + +static void ab8500_usb_phy_disable_work(struct work_struct *work) +{ +	struct ab8500_usb *ab = container_of(work, struct ab8500_usb, +						phy_dis_work); + +	if (!ab->phy.otg->host) +		ab8500_usb_host_phy_dis(ab); + +	if (!ab->phy.otg->gadget) +		ab8500_usb_peri_phy_dis(ab); +} + +static unsigned ab8500_eyediagram_workaroud(struct ab8500_usb *ab, unsigned mA) +{ +	/* +	 * AB8500 V2 has eye diagram issues when drawing more than 100mA from +	 * VBUS.  Set charging current to 100mA in case of standard host +	 */ +	if (is_ab8500_2p0_or_earlier(ab->ab8500)) +		if (mA > 100) +			mA = 100; + +	return mA; +} + +static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA) +{ +	struct ab8500_usb *ab; + +	if (!phy) +		return -ENODEV; + +	ab = phy_to_ab(phy); + +	mA = ab8500_eyediagram_workaroud(ab, mA); + +	ab->vbus_draw = mA; + +	atomic_notifier_call_chain(&ab->phy.notifier, +			UX500_MUSB_VBUS, &ab->vbus_draw); + +	return 0; +} + +static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend) +{ +	/* TODO */ +	return 0; +} + +static int ab8500_usb_set_peripheral(struct usb_otg *otg, +					struct usb_gadget *gadget) +{ +	struct ab8500_usb *ab; + +	if (!otg) +		return -ENODEV; + +	ab = phy_to_ab(otg->phy); + +	ab->phy.otg->gadget = gadget; + +	/* Some drivers call this function in atomic context. +	 * Do not update ab8500 registers directly till this +	 * is fixed. +	 */ + +	if ((ab->mode != USB_IDLE) && (!gadget)) { +		ab->mode = USB_IDLE; +		schedule_work(&ab->phy_dis_work); +	} + +	return 0; +} + +static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host) +{ +	struct ab8500_usb *ab; + +	if (!otg) +		return -ENODEV; + +	ab = phy_to_ab(otg->phy); + +	ab->phy.otg->host = host; + +	/* Some drivers call this function in atomic context. +	 * Do not update ab8500 registers directly till this +	 * is fixed. +	 */ + +	if ((ab->mode != USB_IDLE) && (!host)) { +		ab->mode = USB_IDLE; +		schedule_work(&ab->phy_dis_work); +	} + +	return 0; +} + +static int ab8500_usb_regulator_get(struct ab8500_usb *ab) +{ +	int err; + +	ab->v_ape = devm_regulator_get(ab->dev, "v-ape"); +	if (IS_ERR(ab->v_ape)) { +		dev_err(ab->dev, "Could not get v-ape supply\n"); +		err = PTR_ERR(ab->v_ape); +		return err; +	} + +	ab->v_ulpi = devm_regulator_get(ab->dev, "vddulpivio18"); +	if (IS_ERR(ab->v_ulpi)) { +		dev_err(ab->dev, "Could not get vddulpivio18 supply\n"); +		err = PTR_ERR(ab->v_ulpi); +		return err; +	} + +	ab->v_musb = devm_regulator_get(ab->dev, "musb_1v8"); +	if (IS_ERR(ab->v_musb)) { +		dev_err(ab->dev, "Could not get musb_1v8 supply\n"); +		err = PTR_ERR(ab->v_musb); +		return err; +	} + +	return 0; +} + +static int ab8500_usb_irq_setup(struct platform_device *pdev, +		struct ab8500_usb *ab) +{ +	int err; +	int irq; + +	irq = platform_get_irq_byname(pdev, "USB_LINK_STATUS"); +	if (irq < 0) { +		dev_err(&pdev->dev, "Link status irq not found\n"); +		return irq; +	} +	err = devm_request_threaded_irq(&pdev->dev, irq, NULL, +			ab8500_usb_link_status_irq, +			IRQF_NO_SUSPEND | IRQF_SHARED, "usb-link-status", ab); +	if (err < 0) { +		dev_err(ab->dev, "request_irq failed for link status irq\n"); +		return err; +	} + +	irq = platform_get_irq_byname(pdev, "ID_WAKEUP_F"); +	if (irq < 0) { +		dev_err(&pdev->dev, "ID fall irq not found\n"); +		return irq; +	} +	err = devm_request_threaded_irq(&pdev->dev, irq, NULL, +			ab8500_usb_disconnect_irq, +			IRQF_NO_SUSPEND | IRQF_SHARED, "usb-id-fall", ab); +	if (err < 0) { +		dev_err(ab->dev, "request_irq failed for ID fall irq\n"); +		return err; +	} + +	irq = platform_get_irq_byname(pdev, "VBUS_DET_F"); +	if (irq < 0) { +		dev_err(&pdev->dev, "VBUS fall irq not found\n"); +		return irq; +	} +	err = devm_request_threaded_irq(&pdev->dev, irq, NULL, +			ab8500_usb_disconnect_irq, +			IRQF_NO_SUSPEND | IRQF_SHARED, "usb-vbus-fall", ab); +	if (err < 0) { +		dev_err(ab->dev, "request_irq failed for Vbus fall irq\n"); +		return err; +	} + +	return 0; +} + +static int ab8500_usb_probe(struct platform_device *pdev) +{ +	struct ab8500_usb	*ab; +	struct ab8500		*ab8500; +	struct usb_otg		*otg; +	int err; +	int rev; + +	ab8500 = dev_get_drvdata(pdev->dev.parent); +	rev = abx500_get_chip_id(&pdev->dev); + +	if (is_ab8500_1p1_or_earlier(ab8500)) { +		dev_err(&pdev->dev, "Unsupported AB8500 chip rev=%d\n", rev); +		return -ENODEV; +	} + +	ab = devm_kzalloc(&pdev->dev, sizeof(*ab), GFP_KERNEL); +	if (!ab) +		return -ENOMEM; + +	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL); +	if (!otg) +		return -ENOMEM; + +	ab->dev			= &pdev->dev; +	ab->ab8500		= ab8500; +	ab->phy.dev		= ab->dev; +	ab->phy.otg		= otg; +	ab->phy.label		= "ab8500"; +	ab->phy.set_suspend	= ab8500_usb_set_suspend; +	ab->phy.set_power	= ab8500_usb_set_power; +	ab->phy.state		= OTG_STATE_UNDEFINED; + +	otg->phy		= &ab->phy; +	otg->set_host		= ab8500_usb_set_host; +	otg->set_peripheral	= ab8500_usb_set_peripheral; + +	platform_set_drvdata(pdev, ab); + +	ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier); + +	/* all: Disable phy when called from set_host and set_peripheral */ +	INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work); + +	err = ab8500_usb_regulator_get(ab); +	if (err) +		return err; + +	err = ab8500_usb_irq_setup(pdev, ab); +	if (err < 0) +		return err; + +	err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2); +	if (err) { +		dev_err(&pdev->dev, "Can't register transceiver\n"); +		return err; +	} + +	/* Phy tuning values for AB8500 */ +	if (!is_ab8500_2p0_or_earlier(ab->ab8500)) { +		/* Enable the PBT/Bank 0x12 access */ +		err = abx500_set_register_interruptible(ab->dev, +				AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x01); +		if (err < 0) +			dev_err(ab->dev, "Failed to enable bank12 access err=%d\n", +					err); + +		err = abx500_set_register_interruptible(ab->dev, +				AB8500_DEBUG, AB8500_USB_PHY_TUNE1, 0xC8); +		if (err < 0) +			dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n", +					err); + +		err = abx500_set_register_interruptible(ab->dev, +				AB8500_DEBUG, AB8500_USB_PHY_TUNE2, 0x00); +		if (err < 0) +			dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n", +					err); + +		err = abx500_set_register_interruptible(ab->dev, +				AB8500_DEBUG, AB8500_USB_PHY_TUNE3, 0x78); +		if (err < 0) +			dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n", +					err); + +		/* Switch to normal mode/disable Bank 0x12 access */ +		err = abx500_set_register_interruptible(ab->dev, +				AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x00); +		if (err < 0) +			dev_err(ab->dev, "Failed to switch bank12 access err=%d\n", +					err); +	} + +	/* Phy tuning values for AB8505 */ +	if (is_ab8505(ab->ab8500)) { +		/* Enable the PBT/Bank 0x12 access */ +		err = abx500_mask_and_set_register_interruptible(ab->dev, +				AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, +				0x01, 0x01); +		if (err < 0) +			dev_err(ab->dev, "Failed to enable bank12 access err=%d\n", +					err); + +		err = abx500_mask_and_set_register_interruptible(ab->dev, +				AB8500_DEBUG, AB8500_USB_PHY_TUNE1, +				0xC8, 0xC8); +		if (err < 0) +			dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n", +					err); + +		err = abx500_mask_and_set_register_interruptible(ab->dev, +				AB8500_DEBUG, AB8500_USB_PHY_TUNE2, +				0x60, 0x60); +		if (err < 0) +			dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n", +					err); + +		err = abx500_mask_and_set_register_interruptible(ab->dev, +				AB8500_DEBUG, AB8500_USB_PHY_TUNE3, +				0xFC, 0x80); + +		if (err < 0) +			dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n", +					err); + +		/* Switch to normal mode/disable Bank 0x12 access */ +		err = abx500_mask_and_set_register_interruptible(ab->dev, +				AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, +				0x00, 0x00); +		if (err < 0) +			dev_err(ab->dev, "Failed to switch bank12 access err=%d\n", +					err); +	} + +	/* Needed to enable ID detection. */ +	ab8500_usb_wd_workaround(ab); + +	abx500_usb_link_status_update(ab); + +	dev_info(&pdev->dev, "revision 0x%2x driver initialized\n", rev); + +	return 0; +} + +static int ab8500_usb_remove(struct platform_device *pdev) +{ +	struct ab8500_usb *ab = platform_get_drvdata(pdev); + +	cancel_work_sync(&ab->phy_dis_work); + +	usb_remove_phy(&ab->phy); + +	if (ab->mode == USB_HOST) +		ab8500_usb_host_phy_dis(ab); +	else if (ab->mode == USB_PERIPHERAL) +		ab8500_usb_peri_phy_dis(ab); + +	platform_set_drvdata(pdev, NULL); + +	return 0; +} + +static struct platform_driver ab8500_usb_driver = { +	.probe		= ab8500_usb_probe, +	.remove		= ab8500_usb_remove, +	.driver		= { +		.name	= "ab8500-usb", +		.owner	= THIS_MODULE, +	}, +}; + +static int __init ab8500_usb_init(void) +{ +	return platform_driver_register(&ab8500_usb_driver); +} +subsys_initcall(ab8500_usb_init); + +static void __exit ab8500_usb_exit(void) +{ +	platform_driver_unregister(&ab8500_usb_driver); +} +module_exit(ab8500_usb_exit); + +MODULE_ALIAS("platform:ab8500_usb"); +MODULE_AUTHOR("ST-Ericsson AB"); +MODULE_DESCRIPTION("AB8500 usb transceiver driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/phy/phy-fsl-usb.c index d16adb41eb2..97b9308507c 100644 --- a/drivers/usb/otg/fsl_otg.c +++ b/drivers/usb/phy/phy-fsl-usb.c @@ -43,7 +43,7 @@  #include <asm/unaligned.h> -#include "fsl_otg.h" +#include "phy-fsl-usb.h"  #define DRIVER_VERSION "Rev. 1.55"  #define DRIVER_AUTHOR "Jerry Huang/Li Yang" @@ -361,28 +361,18 @@ int fsl_otg_init_timers(struct otg_fsm *fsm)  void fsl_otg_uninit_timers(void)  {  	/* FSM used timers */ -	if (a_wait_vrise_tmr != NULL) -		kfree(a_wait_vrise_tmr); -	if (a_wait_bcon_tmr != NULL) -		kfree(a_wait_bcon_tmr); -	if (a_aidl_bdis_tmr != NULL) -		kfree(a_aidl_bdis_tmr); -	if (b_ase0_brst_tmr != NULL) -		kfree(b_ase0_brst_tmr); -	if (b_se0_srp_tmr != NULL) -		kfree(b_se0_srp_tmr); -	if (b_srp_fail_tmr != NULL) -		kfree(b_srp_fail_tmr); -	if (a_wait_enum_tmr != NULL) -		kfree(a_wait_enum_tmr); +	kfree(a_wait_vrise_tmr); +	kfree(a_wait_bcon_tmr); +	kfree(a_aidl_bdis_tmr); +	kfree(b_ase0_brst_tmr); +	kfree(b_se0_srp_tmr); +	kfree(b_srp_fail_tmr); +	kfree(a_wait_enum_tmr);  	/* device driver used timers */ -	if (b_srp_wait_tmr != NULL) -		kfree(b_srp_wait_tmr); -	if (b_data_pulse_tmr != NULL) -		kfree(b_data_pulse_tmr); -	if (b_vbus_pulse_tmr != NULL) -		kfree(b_vbus_pulse_tmr); +	kfree(b_srp_wait_tmr); +	kfree(b_data_pulse_tmr); +	kfree(b_vbus_pulse_tmr);  }  /* Add timer to timer list */ @@ -1002,7 +992,7 @@ static int show_fsl_usb2_otg_state(struct device *dev,  	/* State */  	t = scnprintf(next, size,  		      "OTG state: %s\n\n", -		      otg_state_string(fsl_otg_dev->phy.state)); +		      usb_otg_state_string(fsl_otg_dev->phy.state));  	size -= t;  	next += t; diff --git a/drivers/usb/otg/fsl_otg.h b/drivers/usb/phy/phy-fsl-usb.h index ca266280895..ca266280895 100644 --- a/drivers/usb/otg/fsl_otg.h +++ b/drivers/usb/phy/phy-fsl-usb.h diff --git a/drivers/usb/otg/otg_fsm.c b/drivers/usb/phy/phy-fsm-usb.c index ade131a8ae5..c520b3548e7 100644 --- a/drivers/usb/otg/otg_fsm.c +++ b/drivers/usb/phy/phy-fsm-usb.c @@ -29,7 +29,7 @@  #include <linux/usb/gadget.h>  #include <linux/usb/otg.h> -#include "otg_fsm.h" +#include "phy-otg-fsm.h"  /* Change USB protocol when there is a protocol change */  static int otg_set_protocol(struct otg_fsm *fsm, int protocol) @@ -119,7 +119,7 @@ int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)  	state_changed = 1;  	if (fsm->otg->phy->state == new_state)  		return 0; -	VDBG("Set state: %s\n", otg_state_string(new_state)); +	VDBG("Set state: %s\n", usb_otg_state_string(new_state));  	otg_leave_state(fsm, fsm->otg->phy->state);  	switch (new_state) {  	case OTG_STATE_B_IDLE: diff --git a/drivers/usb/otg/otg_fsm.h b/drivers/usb/phy/phy-fsm-usb.h index c30a2e1d9e4..c30a2e1d9e4 100644 --- a/drivers/usb/otg/otg_fsm.h +++ b/drivers/usb/phy/phy-fsm-usb.h diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/phy/phy-gpio-vbus-usb.c index a7d4ac59198..4c76074e518 100644 --- a/drivers/usb/otg/gpio_vbus.c +++ b/drivers/usb/phy/phy-gpio-vbus-usb.c @@ -61,6 +61,7 @@ static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA)  {  	struct regulator *vbus_draw = gpio_vbus->vbus_draw;  	int enabled; +	int ret;  	if (!vbus_draw)  		return; @@ -69,12 +70,16 @@ static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA)  	if (mA) {  		regulator_set_current_limit(vbus_draw, 0, 1000 * mA);  		if (!enabled) { -			regulator_enable(vbus_draw); +			ret = regulator_enable(vbus_draw); +			if (ret < 0) +				return;  			gpio_vbus->vbus_draw_enabled = 1;  		}  	} else {  		if (enabled) { -			regulator_disable(vbus_draw); +			ret = regulator_disable(vbus_draw); +			if (ret < 0) +				return;  			gpio_vbus->vbus_draw_enabled = 0;  		}  	} diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/phy/phy-isp1301-omap.c index af9cb11626b..ae481afcb3e 100644 --- a/drivers/usb/otg/isp1301_omap.c +++ b/drivers/usb/phy/phy-isp1301-omap.c @@ -236,7 +236,7 @@ isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits)  static inline const char *state_name(struct isp1301 *isp)  { -	return otg_state_string(isp->phy.state); +	return usb_otg_state_string(isp->phy.state);  }  /*-------------------------------------------------------------------------*/ @@ -481,7 +481,7 @@ static void check_state(struct isp1301 *isp, const char *tag)  	if (isp->phy.state == state && !extra)  		return;  	pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag, -		otg_state_string(state), fsm, state_name(isp), +		usb_otg_state_string(state), fsm, state_name(isp),  		omap_readl(OTG_CTRL));  } @@ -1077,7 +1077,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat)  	if (state != isp->phy.state)  		pr_debug("  isp, %s -> %s\n", -				otg_state_string(state), state_name(isp)); +				usb_otg_state_string(state), state_name(isp));  #ifdef	CONFIG_USB_OTG  	/* update the OTG controller state to match the isp1301; may @@ -1212,7 +1212,7 @@ static void isp1301_release(struct device *dev)  static struct isp1301 *the_transceiver; -static int __exit isp1301_remove(struct i2c_client *i2c) +static int isp1301_remove(struct i2c_client *i2c)  {  	struct isp1301	*isp; @@ -1634,7 +1634,7 @@ static struct i2c_driver isp1301_driver = {  		.name	= "isp1301_omap",  	},  	.probe		= isp1301_probe, -	.remove		= __exit_p(isp1301_remove), +	.remove		= isp1301_remove,  	.id_table	= isp1301_id,  }; diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c new file mode 100644 index 00000000000..225ae6c97ee --- /dev/null +++ b/drivers/usb/phy/phy-isp1301.c @@ -0,0 +1,162 @@ +/* + * NXP ISP1301 USB transceiver driver + * + * Copyright (C) 2012 Roland Stigge + * + * Author: Roland Stigge <stigge@antcom.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/i2c.h> +#include <linux/usb/phy.h> +#include <linux/usb/isp1301.h> + +#define DRV_NAME		"isp1301" + +struct isp1301 { +	struct usb_phy		phy; +	struct mutex		mutex; + +	struct i2c_client	*client; +}; + +#define phy_to_isp(p)		(container_of((p), struct isp1301, phy)) + +static const struct i2c_device_id isp1301_id[] = { +	{ "isp1301", 0 }, +	{ } +}; + +static struct i2c_client *isp1301_i2c_client; + +static int __isp1301_write(struct isp1301 *isp, u8 reg, u8 value, u8 clear) +{ +	return i2c_smbus_write_byte_data(isp->client, reg | clear, value); +} + +static int isp1301_write(struct isp1301 *isp, u8 reg, u8 value) +{ +	return __isp1301_write(isp, reg, value, 0); +} + +static int isp1301_clear(struct isp1301 *isp, u8 reg, u8 value) +{ +	return __isp1301_write(isp, reg, value, ISP1301_I2C_REG_CLEAR_ADDR); +} + +static int isp1301_phy_init(struct usb_phy *phy) +{ +	struct isp1301 *isp = phy_to_isp(phy); + +	/* Disable transparent UART mode first */ +	isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_UART_EN); +	isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_1, ~MC1_SPEED_REG); +	isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_SPEED_REG); +	isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_2, ~0); +	isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_2, (MC2_BI_DI | MC2_PSW_EN +				| MC2_SPD_SUSP_CTRL)); + +	isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, ~0); +	isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_DAT_SE0); +	isp1301_write(isp, ISP1301_I2C_OTG_CONTROL_1, (OTG1_DM_PULLDOWN +				| OTG1_DP_PULLDOWN)); +	isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, (OTG1_DM_PULLUP +				| OTG1_DP_PULLUP)); + +	/* mask all interrupts */ +	isp1301_clear(isp, ISP1301_I2C_INTERRUPT_LATCH, ~0); +	isp1301_clear(isp, ISP1301_I2C_INTERRUPT_FALLING, ~0); +	isp1301_clear(isp, ISP1301_I2C_INTERRUPT_RISING, ~0); + +	return 0; +} + +static int isp1301_phy_set_vbus(struct usb_phy *phy, int on) +{ +	struct isp1301 *isp = phy_to_isp(phy); + +	if (on) +		isp1301_write(isp, ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV); +	else +		isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV); + +	return 0; +} + +static int isp1301_probe(struct i2c_client *client, +			 const struct i2c_device_id *i2c_id) +{ +	struct isp1301 *isp; +	struct usb_phy *phy; + +	isp = devm_kzalloc(&client->dev, sizeof(*isp), GFP_KERNEL); +	if (!isp) +		return -ENOMEM; + +	isp->client = client; +	mutex_init(&isp->mutex); + +	phy = &isp->phy; +	phy->label = DRV_NAME; +	phy->init = isp1301_phy_init; +	phy->set_vbus = isp1301_phy_set_vbus; +	phy->type = USB_PHY_TYPE_USB2; + +	i2c_set_clientdata(client, isp); +	usb_add_phy_dev(phy); + +	isp1301_i2c_client = client; + +	return 0; +} + +static int isp1301_remove(struct i2c_client *client) +{ +	struct isp1301 *isp = i2c_get_clientdata(client); + +	usb_remove_phy(&isp->phy); +	isp1301_i2c_client = NULL; + +	return 0; +} + +static struct i2c_driver isp1301_driver = { +	.driver = { +		.name = DRV_NAME, +	}, +	.probe = isp1301_probe, +	.remove = isp1301_remove, +	.id_table = isp1301_id, +}; + +module_i2c_driver(isp1301_driver); + +static int match(struct device *dev, void *data) +{ +	struct device_node *node = (struct device_node *)data; +	return (dev->of_node == node) && +		(dev->driver == &isp1301_driver.driver); +} + +struct i2c_client *isp1301_get_client(struct device_node *node) +{ +	if (node) { /* reference of ISP1301 I2C node via DT */ +		struct device *dev = bus_find_device(&i2c_bus_type, NULL, +						     node, match); +		if (!dev) +			return NULL; +		return to_i2c_client(dev); +	} else { /* non-DT: only one ISP1301 chip supported */ +		return isp1301_i2c_client; +	} +} +EXPORT_SYMBOL_GPL(isp1301_get_client); + +MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); +MODULE_DESCRIPTION("NXP ISP1301 USB transceiver driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/phy/phy-msm-usb.c index 749fbf41fb6..749fbf41fb6 100644 --- a/drivers/usb/otg/msm_otg.c +++ b/drivers/usb/phy/phy-msm-usb.c diff --git a/drivers/usb/phy/mv_u3d_phy.c b/drivers/usb/phy/phy-mv-u3d-usb.c index 9d8599122aa..f7838a43347 100644 --- a/drivers/usb/phy/mv_u3d_phy.c +++ b/drivers/usb/phy/phy-mv-u3d-usb.c @@ -15,7 +15,7 @@  #include <linux/usb/otg.h>  #include <linux/platform_data/mv_usb.h> -#include "mv_u3d_phy.h" +#include "phy-mv-u3d-usb.h"  /*   * struct mv_u3d_phy - transceiver driver state @@ -313,7 +313,7 @@ err:  	return ret;  } -static int __exit mv_u3d_phy_remove(struct platform_device *pdev) +static int mv_u3d_phy_remove(struct platform_device *pdev)  {  	struct mv_u3d_phy *mv_u3d_phy = platform_get_drvdata(pdev); diff --git a/drivers/usb/phy/mv_u3d_phy.h b/drivers/usb/phy/phy-mv-u3d-usb.h index 2a658cb9a52..2a658cb9a52 100644 --- a/drivers/usb/phy/mv_u3d_phy.h +++ b/drivers/usb/phy/phy-mv-u3d-usb.h diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/phy/phy-mv-usb.c index b6a9be31133..c987bbe2785 100644 --- a/drivers/usb/otg/mv_otg.c +++ b/drivers/usb/phy/phy-mv-usb.c @@ -27,7 +27,7 @@  #include <linux/usb/hcd.h>  #include <linux/platform_data/mv_usb.h> -#include "mv_otg.h" +#include "phy-mv-usb.h"  #define	DRIVER_DESC	"Marvell USB OTG transceiver driver"  #define	DRIVER_VERSION	"Jan 20, 2010" @@ -237,18 +237,12 @@ static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on)  static void otg_clock_enable(struct mv_otg *mvotg)  { -	unsigned int i; - -	for (i = 0; i < mvotg->clknum; i++) -		clk_prepare_enable(mvotg->clk[i]); +	clk_prepare_enable(mvotg->clk);  }  static void otg_clock_disable(struct mv_otg *mvotg)  { -	unsigned int i; - -	for (i = 0; i < mvotg->clknum; i++) -		clk_disable_unprepare(mvotg->clk[i]); +	clk_disable_unprepare(mvotg->clk);  }  static int mv_otg_enable_internal(struct mv_otg *mvotg) @@ -684,16 +678,14 @@ static int mv_otg_probe(struct platform_device *pdev)  	struct mv_otg *mvotg;  	struct usb_otg *otg;  	struct resource *r; -	int retval = 0, clk_i, i; -	size_t size; +	int retval = 0, i;  	if (pdata == NULL) {  		dev_err(&pdev->dev, "failed to get platform data\n");  		return -ENODEV;  	} -	size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum; -	mvotg = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); +	mvotg = devm_kzalloc(&pdev->dev, sizeof(*mvotg), GFP_KERNEL);  	if (!mvotg) {  		dev_err(&pdev->dev, "failed to allocate memory!\n");  		return -ENOMEM; @@ -708,15 +700,9 @@ static int mv_otg_probe(struct platform_device *pdev)  	mvotg->pdev = pdev;  	mvotg->pdata = pdata; -	mvotg->clknum = pdata->clknum; -	for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) { -		mvotg->clk[clk_i] = devm_clk_get(&pdev->dev, -						pdata->clkname[clk_i]); -		if (IS_ERR(mvotg->clk[clk_i])) { -			retval = PTR_ERR(mvotg->clk[clk_i]); -			return retval; -		} -	} +	mvotg->clk = devm_clk_get(&pdev->dev, NULL); +	if (IS_ERR(mvotg->clk)) +		return PTR_ERR(mvotg->clk);  	mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");  	if (!mvotg->qwork) { diff --git a/drivers/usb/otg/mv_otg.h b/drivers/usb/phy/phy-mv-usb.h index 8a9e351b36b..551da6eb0ba 100644 --- a/drivers/usb/otg/mv_otg.h +++ b/drivers/usb/phy/phy-mv-usb.h @@ -158,8 +158,7 @@ struct mv_otg {  	unsigned int active;  	unsigned int clock_gating; -	unsigned int clknum; -	struct clk *clk[0]; +	struct clk *clk;  };  #endif diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/phy/phy-mxs-usb.c index b0d9f119c74..9d4381e64d5 100644 --- a/drivers/usb/otg/mxs-phy.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -48,12 +48,12 @@ static void mxs_phy_hw_init(struct mxs_phy *mxs_phy)  	stmp_reset_block(base + HW_USBPHY_CTRL);  	/* Power up the PHY */ -	writel_relaxed(0, base + HW_USBPHY_PWD); +	writel(0, base + HW_USBPHY_PWD);  	/* enable FS/LS device */ -	writel_relaxed(BM_USBPHY_CTRL_ENUTMILEVEL2 | -			BM_USBPHY_CTRL_ENUTMILEVEL3, -			base + HW_USBPHY_CTRL_SET); +	writel(BM_USBPHY_CTRL_ENUTMILEVEL2 | +	       BM_USBPHY_CTRL_ENUTMILEVEL3, +	       base + HW_USBPHY_CTRL_SET);  }  static int mxs_phy_init(struct usb_phy *phy) @@ -70,8 +70,8 @@ static void mxs_phy_shutdown(struct usb_phy *phy)  {  	struct mxs_phy *mxs_phy = to_mxs_phy(phy); -	writel_relaxed(BM_USBPHY_CTRL_CLKGATE, -			phy->io_priv + HW_USBPHY_CTRL_SET); +	writel(BM_USBPHY_CTRL_CLKGATE, +	       phy->io_priv + HW_USBPHY_CTRL_SET);  	clk_disable_unprepare(mxs_phy->clk);  } @@ -81,15 +81,15 @@ static int mxs_phy_suspend(struct usb_phy *x, int suspend)  	struct mxs_phy *mxs_phy = to_mxs_phy(x);  	if (suspend) { -		writel_relaxed(0xffffffff, x->io_priv + HW_USBPHY_PWD); -		writel_relaxed(BM_USBPHY_CTRL_CLKGATE, -			x->io_priv + HW_USBPHY_CTRL_SET); +		writel(0xffffffff, x->io_priv + HW_USBPHY_PWD); +		writel(BM_USBPHY_CTRL_CLKGATE, +		       x->io_priv + HW_USBPHY_CTRL_SET);  		clk_disable_unprepare(mxs_phy->clk);  	} else {  		clk_prepare_enable(mxs_phy->clk); -		writel_relaxed(BM_USBPHY_CTRL_CLKGATE, -			x->io_priv + HW_USBPHY_CTRL_CLR); -		writel_relaxed(0, x->io_priv + HW_USBPHY_PWD); +		writel(BM_USBPHY_CTRL_CLKGATE, +		       x->io_priv + HW_USBPHY_CTRL_CLR); +		writel(0, x->io_priv + HW_USBPHY_PWD);  	}  	return 0; @@ -102,8 +102,8 @@ static int mxs_phy_on_connect(struct usb_phy *phy,  		(speed == USB_SPEED_HIGH) ? "high" : "non-high");  	if (speed == USB_SPEED_HIGH) -		writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, -				phy->io_priv + HW_USBPHY_CTRL_SET); +		writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, +		       phy->io_priv + HW_USBPHY_CTRL_SET);  	return 0;  } @@ -115,8 +115,8 @@ static int mxs_phy_on_disconnect(struct usb_phy *phy,  		(speed == USB_SPEED_HIGH) ? "high" : "non-high");  	if (speed == USB_SPEED_HIGH) -		writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, -				phy->io_priv + HW_USBPHY_CTRL_CLR); +		writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, +		       phy->io_priv + HW_USBPHY_CTRL_CLR);  	return 0;  } @@ -127,6 +127,7 @@ static int mxs_phy_probe(struct platform_device *pdev)  	void __iomem *base;  	struct clk *clk;  	struct mxs_phy *mxs_phy; +	int ret;  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) { @@ -166,11 +167,19 @@ static int mxs_phy_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, &mxs_phy->phy); +	ret = usb_add_phy_dev(&mxs_phy->phy); +	if (ret) +		return ret; +  	return 0;  }  static int mxs_phy_remove(struct platform_device *pdev)  { +	struct mxs_phy *mxs_phy = platform_get_drvdata(pdev); + +	usb_remove_phy(&mxs_phy->phy); +  	platform_set_drvdata(pdev, NULL);  	return 0; diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/phy/phy-nop.c index a3ce24b94a7..2b10cc969bb 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/phy/phy-nop.c @@ -32,10 +32,16 @@  #include <linux/usb/otg.h>  #include <linux/usb/nop-usb-xceiv.h>  #include <linux/slab.h> +#include <linux/clk.h> +#include <linux/regulator/consumer.h> +#include <linux/of.h>  struct nop_usb_xceiv { -	struct usb_phy		phy; -	struct device		*dev; +	struct usb_phy phy; +	struct device *dev; +	struct clk *clk; +	struct regulator *vcc; +	struct regulator *reset;  };  static struct platform_device *pd; @@ -64,6 +70,46 @@ static int nop_set_suspend(struct usb_phy *x, int suspend)  	return 0;  } +static int nop_init(struct usb_phy *phy) +{ +	struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev); + +	if (!IS_ERR(nop->vcc)) { +		if (regulator_enable(nop->vcc)) +			dev_err(phy->dev, "Failed to enable power\n"); +	} + +	if (!IS_ERR(nop->clk)) +		clk_enable(nop->clk); + +	if (!IS_ERR(nop->reset)) { +		/* De-assert RESET */ +		if (regulator_enable(nop->reset)) +			dev_err(phy->dev, "Failed to de-assert reset\n"); +	} + +	return 0; +} + +static void nop_shutdown(struct usb_phy *phy) +{ +	struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev); + +	if (!IS_ERR(nop->reset)) { +		/* Assert RESET */ +		if (regulator_disable(nop->reset)) +			dev_err(phy->dev, "Failed to assert reset\n"); +	} + +	if (!IS_ERR(nop->clk)) +		clk_disable(nop->clk); + +	if (!IS_ERR(nop->vcc)) { +		if (regulator_disable(nop->vcc)) +			dev_err(phy->dev, "Failed to disable power\n"); +	} +} +  static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)  {  	if (!otg) @@ -95,39 +141,96 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)  static int nop_usb_xceiv_probe(struct platform_device *pdev)  { +	struct device *dev = &pdev->dev;  	struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data;  	struct nop_usb_xceiv	*nop;  	enum usb_phy_type	type = USB_PHY_TYPE_USB2;  	int err; +	u32 clk_rate = 0; +	bool needs_vcc = false; +	bool needs_reset = false; -	nop = kzalloc(sizeof *nop, GFP_KERNEL); +	nop = devm_kzalloc(&pdev->dev, sizeof(*nop), GFP_KERNEL);  	if (!nop)  		return -ENOMEM; -	nop->phy.otg = kzalloc(sizeof *nop->phy.otg, GFP_KERNEL); -	if (!nop->phy.otg) { -		kfree(nop); +	nop->phy.otg = devm_kzalloc(&pdev->dev, sizeof(*nop->phy.otg), +							GFP_KERNEL); +	if (!nop->phy.otg)  		return -ENOMEM; -	} -	if (pdata) +	if (dev->of_node) { +		struct device_node *node = dev->of_node; + +		if (of_property_read_u32(node, "clock-frequency", &clk_rate)) +			clk_rate = 0; + +		needs_vcc = of_property_read_bool(node, "vcc-supply"); +		needs_reset = of_property_read_bool(node, "reset-supply"); + +	} else if (pdata) {  		type = pdata->type; +		clk_rate = pdata->clk_rate; +		needs_vcc = pdata->needs_vcc; +		needs_reset = pdata->needs_reset; +	} + +	nop->clk = devm_clk_get(&pdev->dev, "main_clk"); +	if (IS_ERR(nop->clk)) { +		dev_dbg(&pdev->dev, "Can't get phy clock: %ld\n", +					PTR_ERR(nop->clk)); +	} + +	if (!IS_ERR(nop->clk) && clk_rate) { +		err = clk_set_rate(nop->clk, clk_rate); +		if (err) { +			dev_err(&pdev->dev, "Error setting clock rate\n"); +			return err; +		} +	} + +	if (!IS_ERR(nop->clk)) { +		err = clk_prepare(nop->clk); +		if (err) { +			dev_err(&pdev->dev, "Error preparing clock\n"); +			return err; +		} +	} + +	nop->vcc = devm_regulator_get(&pdev->dev, "vcc"); +	if (IS_ERR(nop->vcc)) { +		dev_dbg(&pdev->dev, "Error getting vcc regulator: %ld\n", +					PTR_ERR(nop->vcc)); +		if (needs_vcc) +			return -EPROBE_DEFER; +	} + +	nop->reset = devm_regulator_get(&pdev->dev, "reset"); +	if (IS_ERR(nop->reset)) { +		dev_dbg(&pdev->dev, "Error getting reset regulator: %ld\n", +					PTR_ERR(nop->reset)); +		if (needs_reset) +			return -EPROBE_DEFER; +	}  	nop->dev		= &pdev->dev;  	nop->phy.dev		= nop->dev;  	nop->phy.label		= "nop-xceiv";  	nop->phy.set_suspend	= nop_set_suspend; +	nop->phy.init		= nop_init; +	nop->phy.shutdown	= nop_shutdown;  	nop->phy.state		= OTG_STATE_UNDEFINED; +	nop->phy.type		= type;  	nop->phy.otg->phy		= &nop->phy;  	nop->phy.otg->set_host		= nop_set_host;  	nop->phy.otg->set_peripheral	= nop_set_peripheral; -	err = usb_add_phy(&nop->phy, type); +	err = usb_add_phy_dev(&nop->phy);  	if (err) {  		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",  			err); -		goto exit; +		goto err_add;  	}  	platform_set_drvdata(pdev, nop); @@ -135,9 +238,10 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev)  	ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);  	return 0; -exit: -	kfree(nop->phy.otg); -	kfree(nop); + +err_add: +	if (!IS_ERR(nop->clk)) +		clk_unprepare(nop->clk);  	return err;  } @@ -145,21 +249,30 @@ static int nop_usb_xceiv_remove(struct platform_device *pdev)  {  	struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); +	if (!IS_ERR(nop->clk)) +		clk_unprepare(nop->clk); +  	usb_remove_phy(&nop->phy);  	platform_set_drvdata(pdev, NULL); -	kfree(nop->phy.otg); -	kfree(nop);  	return 0;  } +static const struct of_device_id nop_xceiv_dt_ids[] = { +	{ .compatible = "usb-nop-xceiv" }, +	{ } +}; + +MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids); +  static struct platform_driver nop_usb_xceiv_driver = {  	.probe		= nop_usb_xceiv_probe,  	.remove		= nop_usb_xceiv_remove,  	.driver		= {  		.name	= "nop_usb_xceiv",  		.owner	= THIS_MODULE, +		.of_match_table = of_match_ptr(nop_xceiv_dt_ids),  	},  }; diff --git a/drivers/usb/phy/omap-control-usb.c b/drivers/usb/phy/phy-omap-control.c index 1419ceda975..1419ceda975 100644 --- a/drivers/usb/phy/omap-control-usb.c +++ b/drivers/usb/phy/phy-omap-control.c diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/phy-omap-usb2.c index 844ab68f08d..844ab68f08d 100644 --- a/drivers/usb/phy/omap-usb2.c +++ b/drivers/usb/phy/phy-omap-usb2.c diff --git a/drivers/usb/phy/omap-usb3.c b/drivers/usb/phy/phy-omap-usb3.c index a6e60b1e102..a6e60b1e102 100644 --- a/drivers/usb/phy/omap-usb3.c +++ b/drivers/usb/phy/phy-omap-usb3.c diff --git a/drivers/usb/phy/rcar-phy.c b/drivers/usb/phy/phy-rcar-usb.c index a35681b0c50..a35681b0c50 100644 --- a/drivers/usb/phy/rcar-phy.c +++ b/drivers/usb/phy/phy-rcar-usb.c diff --git a/drivers/usb/phy/phy-samsung-usb.c b/drivers/usb/phy/phy-samsung-usb.c new file mode 100644 index 00000000000..7b118ee5f5e --- /dev/null +++ b/drivers/usb/phy/phy-samsung-usb.c @@ -0,0 +1,236 @@ +/* linux/drivers/usb/phy/phy-samsung-usb.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + *              http://www.samsung.com + * + * Author: Praveen Paneri <p.paneri@samsung.com> + * + * Samsung USB-PHY helper driver with common function calls; + * interacts with Samsung USB 2.0 PHY controller driver and later + * with Samsung USB 3.0 PHY driver. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/usb/samsung_usb_phy.h> + +#include "phy-samsung-usb.h" + +int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy) +{ +	struct device_node *usbphy_sys; + +	/* Getting node for system controller interface for usb-phy */ +	usbphy_sys = of_get_child_by_name(sphy->dev->of_node, "usbphy-sys"); +	if (!usbphy_sys) { +		dev_err(sphy->dev, "No sys-controller interface for usb-phy\n"); +		return -ENODEV; +	} + +	sphy->pmuregs = of_iomap(usbphy_sys, 0); + +	if (sphy->pmuregs == NULL) { +		dev_err(sphy->dev, "Can't get usb-phy pmu control register\n"); +		goto err0; +	} + +	sphy->sysreg = of_iomap(usbphy_sys, 1); + +	/* +	 * Not returning error code here, since this situation is not fatal. +	 * Few SoCs may not have this switch available +	 */ +	if (sphy->sysreg == NULL) +		dev_warn(sphy->dev, "Can't get usb-phy sysreg cfg register\n"); + +	of_node_put(usbphy_sys); + +	return 0; + +err0: +	of_node_put(usbphy_sys); +	return -ENXIO; +} +EXPORT_SYMBOL_GPL(samsung_usbphy_parse_dt); + +/* + * Set isolation here for phy. + * Here 'on = true' would mean USB PHY block is isolated, hence + * de-activated and vice-versa. + */ +void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on) +{ +	void __iomem *reg = NULL; +	u32 reg_val; +	u32 en_mask = 0; + +	if (!sphy->pmuregs) { +		dev_warn(sphy->dev, "Can't set pmu isolation\n"); +		return; +	} + +	switch (sphy->drv_data->cpu_type) { +	case TYPE_S3C64XX: +		/* +		 * Do nothing: We will add here once S3C64xx goes for DT support +		 */ +		break; +	case TYPE_EXYNOS4210: +		/* +		 * Fall through since exynos4210 and exynos5250 have similar +		 * register architecture: two separate registers for host and +		 * device phy control with enable bit at position 0. +		 */ +	case TYPE_EXYNOS5250: +		if (sphy->phy_type == USB_PHY_TYPE_DEVICE) { +			reg = sphy->pmuregs + +				sphy->drv_data->devphy_reg_offset; +			en_mask = sphy->drv_data->devphy_en_mask; +		} else if (sphy->phy_type == USB_PHY_TYPE_HOST) { +			reg = sphy->pmuregs + +				sphy->drv_data->hostphy_reg_offset; +			en_mask = sphy->drv_data->hostphy_en_mask; +		} +		break; +	default: +		dev_err(sphy->dev, "Invalid SoC type\n"); +		return; +	} + +	reg_val = readl(reg); + +	if (on) +		reg_val &= ~en_mask; +	else +		reg_val |= en_mask; + +	writel(reg_val, reg); +} +EXPORT_SYMBOL_GPL(samsung_usbphy_set_isolation); + +/* + * Configure the mode of working of usb-phy here: HOST/DEVICE. + */ +void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy) +{ +	u32 reg; + +	if (!sphy->sysreg) { +		dev_warn(sphy->dev, "Can't configure specified phy mode\n"); +		return; +	} + +	reg = readl(sphy->sysreg); + +	if (sphy->phy_type == USB_PHY_TYPE_DEVICE) +		reg &= ~EXYNOS_USB20PHY_CFG_HOST_LINK; +	else if (sphy->phy_type == USB_PHY_TYPE_HOST) +		reg |= EXYNOS_USB20PHY_CFG_HOST_LINK; + +	writel(reg, sphy->sysreg); +} +EXPORT_SYMBOL_GPL(samsung_usbphy_cfg_sel); + +/* + * PHYs are different for USB Device and USB Host. + * This make sure that correct PHY type is selected before + * any operation on PHY. + */ +int samsung_usbphy_set_type(struct usb_phy *phy, +				enum samsung_usb_phy_type phy_type) +{ +	struct samsung_usbphy *sphy = phy_to_sphy(phy); + +	sphy->phy_type = phy_type; + +	return 0; +} +EXPORT_SYMBOL_GPL(samsung_usbphy_set_type); + +/* + * Returns reference clock frequency selection value + */ +int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy) +{ +	struct clk *ref_clk; +	int refclk_freq = 0; + +	/* +	 * In exynos5250 USB host and device PHY use +	 * external crystal clock XXTI +	 */ +	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) +		ref_clk = devm_clk_get(sphy->dev, "ext_xtal"); +	else +		ref_clk = devm_clk_get(sphy->dev, "xusbxti"); +	if (IS_ERR(ref_clk)) { +		dev_err(sphy->dev, "Failed to get reference clock\n"); +		return PTR_ERR(ref_clk); +	} + +	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) { +		/* set clock frequency for PLL */ +		switch (clk_get_rate(ref_clk)) { +		case 9600 * KHZ: +			refclk_freq = FSEL_CLKSEL_9600K; +			break; +		case 10 * MHZ: +			refclk_freq = FSEL_CLKSEL_10M; +			break; +		case 12 * MHZ: +			refclk_freq = FSEL_CLKSEL_12M; +			break; +		case 19200 * KHZ: +			refclk_freq = FSEL_CLKSEL_19200K; +			break; +		case 20 * MHZ: +			refclk_freq = FSEL_CLKSEL_20M; +			break; +		case 50 * MHZ: +			refclk_freq = FSEL_CLKSEL_50M; +			break; +		case 24 * MHZ: +		default: +			/* default reference clock */ +			refclk_freq = FSEL_CLKSEL_24M; +			break; +		} +	} else { +		switch (clk_get_rate(ref_clk)) { +		case 12 * MHZ: +			refclk_freq = PHYCLK_CLKSEL_12M; +			break; +		case 24 * MHZ: +			refclk_freq = PHYCLK_CLKSEL_24M; +			break; +		case 48 * MHZ: +			refclk_freq = PHYCLK_CLKSEL_48M; +			break; +		default: +			if (sphy->drv_data->cpu_type == TYPE_S3C64XX) +				refclk_freq = PHYCLK_CLKSEL_48M; +			else +				refclk_freq = PHYCLK_CLKSEL_24M; +			break; +		} +	} +	clk_put(ref_clk); + +	return refclk_freq; +} +EXPORT_SYMBOL_GPL(samsung_usbphy_get_refclk_freq); diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h new file mode 100644 index 00000000000..70a9cae5e37 --- /dev/null +++ b/drivers/usb/phy/phy-samsung-usb.h @@ -0,0 +1,327 @@ +/* linux/drivers/usb/phy/phy-samsung-usb.h + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + *              http://www.samsung.com + * + * Samsung USB-PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and + * OHCI-EXYNOS controllers. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ + +#include <linux/usb/phy.h> + +/* Register definitions */ + +#define SAMSUNG_PHYPWR				(0x00) + +#define PHYPWR_NORMAL_MASK			(0x19 << 0) +#define PHYPWR_OTG_DISABLE			(0x1 << 4) +#define PHYPWR_ANALOG_POWERDOWN			(0x1 << 3) +#define PHYPWR_FORCE_SUSPEND			(0x1 << 1) +/* For Exynos4 */ +#define PHYPWR_NORMAL_MASK_PHY0			(0x39 << 0) +#define PHYPWR_SLEEP_PHY0			(0x1 << 5) + +#define SAMSUNG_PHYCLK				(0x04) + +#define PHYCLK_MODE_USB11			(0x1 << 6) +#define PHYCLK_EXT_OSC				(0x1 << 5) +#define PHYCLK_COMMON_ON_N			(0x1 << 4) +#define PHYCLK_ID_PULL				(0x1 << 2) +#define PHYCLK_CLKSEL_MASK			(0x3 << 0) +#define PHYCLK_CLKSEL_48M			(0x0 << 0) +#define PHYCLK_CLKSEL_12M			(0x2 << 0) +#define PHYCLK_CLKSEL_24M			(0x3 << 0) + +#define SAMSUNG_RSTCON				(0x08) + +#define RSTCON_PHYLINK_SWRST			(0x1 << 2) +#define RSTCON_HLINK_SWRST			(0x1 << 1) +#define RSTCON_SWRST				(0x1 << 0) + +/* EXYNOS5 */ +#define EXYNOS5_PHY_HOST_CTRL0			(0x00) + +#define HOST_CTRL0_PHYSWRSTALL			(0x1 << 31) + +#define HOST_CTRL0_REFCLKSEL_MASK		(0x3 << 19) +#define HOST_CTRL0_REFCLKSEL_XTAL		(0x0 << 19) +#define HOST_CTRL0_REFCLKSEL_EXTL		(0x1 << 19) +#define HOST_CTRL0_REFCLKSEL_CLKCORE		(0x2 << 19) + +#define HOST_CTRL0_FSEL_MASK			(0x7 << 16) +#define HOST_CTRL0_FSEL(_x)			((_x) << 16) + +#define FSEL_CLKSEL_50M				(0x7) +#define FSEL_CLKSEL_24M				(0x5) +#define FSEL_CLKSEL_20M				(0x4) +#define FSEL_CLKSEL_19200K			(0x3) +#define FSEL_CLKSEL_12M				(0x2) +#define FSEL_CLKSEL_10M				(0x1) +#define FSEL_CLKSEL_9600K			(0x0) + +#define HOST_CTRL0_TESTBURNIN			(0x1 << 11) +#define HOST_CTRL0_RETENABLE			(0x1 << 10) +#define HOST_CTRL0_COMMONON_N			(0x1 << 9) +#define HOST_CTRL0_SIDDQ			(0x1 << 6) +#define HOST_CTRL0_FORCESLEEP			(0x1 << 5) +#define HOST_CTRL0_FORCESUSPEND			(0x1 << 4) +#define HOST_CTRL0_WORDINTERFACE		(0x1 << 3) +#define HOST_CTRL0_UTMISWRST			(0x1 << 2) +#define HOST_CTRL0_LINKSWRST			(0x1 << 1) +#define HOST_CTRL0_PHYSWRST			(0x1 << 0) + +#define EXYNOS5_PHY_HOST_TUNE0			(0x04) + +#define EXYNOS5_PHY_HSIC_CTRL1			(0x10) + +#define EXYNOS5_PHY_HSIC_TUNE1			(0x14) + +#define EXYNOS5_PHY_HSIC_CTRL2			(0x20) + +#define EXYNOS5_PHY_HSIC_TUNE2			(0x24) + +#define HSIC_CTRL_REFCLKSEL_MASK		(0x3 << 23) +#define HSIC_CTRL_REFCLKSEL			(0x2 << 23) + +#define HSIC_CTRL_REFCLKDIV_MASK		(0x7f << 16) +#define HSIC_CTRL_REFCLKDIV(_x)			((_x) << 16) +#define HSIC_CTRL_REFCLKDIV_12			(0x24 << 16) +#define HSIC_CTRL_REFCLKDIV_15			(0x1c << 16) +#define HSIC_CTRL_REFCLKDIV_16			(0x1a << 16) +#define HSIC_CTRL_REFCLKDIV_19_2		(0x15 << 16) +#define HSIC_CTRL_REFCLKDIV_20			(0x14 << 16) + +#define HSIC_CTRL_SIDDQ				(0x1 << 6) +#define HSIC_CTRL_FORCESLEEP			(0x1 << 5) +#define HSIC_CTRL_FORCESUSPEND			(0x1 << 4) +#define HSIC_CTRL_WORDINTERFACE			(0x1 << 3) +#define HSIC_CTRL_UTMISWRST			(0x1 << 2) +#define HSIC_CTRL_PHYSWRST			(0x1 << 0) + +#define EXYNOS5_PHY_HOST_EHCICTRL		(0x30) + +#define HOST_EHCICTRL_ENAINCRXALIGN		(0x1 << 29) +#define HOST_EHCICTRL_ENAINCR4			(0x1 << 28) +#define HOST_EHCICTRL_ENAINCR8			(0x1 << 27) +#define HOST_EHCICTRL_ENAINCR16			(0x1 << 26) + +#define EXYNOS5_PHY_HOST_OHCICTRL		(0x34) + +#define HOST_OHCICTRL_SUSPLGCY			(0x1 << 3) +#define HOST_OHCICTRL_APPSTARTCLK		(0x1 << 2) +#define HOST_OHCICTRL_CNTSEL			(0x1 << 1) +#define HOST_OHCICTRL_CLKCKTRST			(0x1 << 0) + +#define EXYNOS5_PHY_OTG_SYS			(0x38) + +#define OTG_SYS_PHYLINK_SWRESET			(0x1 << 14) +#define OTG_SYS_LINKSWRST_UOTG			(0x1 << 13) +#define OTG_SYS_PHY0_SWRST			(0x1 << 12) + +#define OTG_SYS_REFCLKSEL_MASK			(0x3 << 9) +#define OTG_SYS_REFCLKSEL_XTAL			(0x0 << 9) +#define OTG_SYS_REFCLKSEL_EXTL			(0x1 << 9) +#define OTG_SYS_REFCLKSEL_CLKCORE		(0x2 << 9) + +#define OTG_SYS_IDPULLUP_UOTG			(0x1 << 8) +#define OTG_SYS_COMMON_ON			(0x1 << 7) + +#define OTG_SYS_FSEL_MASK			(0x7 << 4) +#define OTG_SYS_FSEL(_x)			((_x) << 4) + +#define OTG_SYS_FORCESLEEP			(0x1 << 3) +#define OTG_SYS_OTGDISABLE			(0x1 << 2) +#define OTG_SYS_SIDDQ_UOTG			(0x1 << 1) +#define OTG_SYS_FORCESUSPEND			(0x1 << 0) + +#define EXYNOS5_PHY_OTG_TUNE			(0x40) + +/* EXYNOS5: USB 3.0 DRD */ +#define EXYNOS5_DRD_LINKSYSTEM			(0x04) + +#define LINKSYSTEM_FLADJ_MASK			(0x3f << 1) +#define LINKSYSTEM_FLADJ(_x)			((_x) << 1) +#define LINKSYSTEM_XHCI_VERSION_CONTROL		(0x1 << 27) + +#define EXYNOS5_DRD_PHYUTMI			(0x08) + +#define PHYUTMI_OTGDISABLE			(0x1 << 6) +#define PHYUTMI_FORCESUSPEND			(0x1 << 1) +#define PHYUTMI_FORCESLEEP			(0x1 << 0) + +#define EXYNOS5_DRD_PHYPIPE			(0x0c) + +#define EXYNOS5_DRD_PHYCLKRST			(0x10) + +#define PHYCLKRST_SSC_REFCLKSEL_MASK		(0xff << 23) +#define PHYCLKRST_SSC_REFCLKSEL(_x)		((_x) << 23) + +#define PHYCLKRST_SSC_RANGE_MASK		(0x03 << 21) +#define PHYCLKRST_SSC_RANGE(_x)			((_x) << 21) + +#define PHYCLKRST_SSC_EN			(0x1 << 20) +#define PHYCLKRST_REF_SSP_EN			(0x1 << 19) +#define PHYCLKRST_REF_CLKDIV2			(0x1 << 18) + +#define PHYCLKRST_MPLL_MULTIPLIER_MASK		(0x7f << 11) +#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF	(0x19 << 11) +#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF	(0x02 << 11) +#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF	(0x68 << 11) +#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF	(0x7d << 11) +#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF	(0x02 << 11) + +#define PHYCLKRST_FSEL_MASK			(0x3f << 5) +#define PHYCLKRST_FSEL(_x)			((_x) << 5) +#define PHYCLKRST_FSEL_PAD_100MHZ		(0x27 << 5) +#define PHYCLKRST_FSEL_PAD_24MHZ		(0x2a << 5) +#define PHYCLKRST_FSEL_PAD_20MHZ		(0x31 << 5) +#define PHYCLKRST_FSEL_PAD_19_2MHZ		(0x38 << 5) + +#define PHYCLKRST_RETENABLEN			(0x1 << 4) + +#define PHYCLKRST_REFCLKSEL_MASK		(0x03 << 2) +#define PHYCLKRST_REFCLKSEL_PAD_REFCLK		(0x2 << 2) +#define PHYCLKRST_REFCLKSEL_EXT_REFCLK		(0x3 << 2) + +#define PHYCLKRST_PORTRESET			(0x1 << 1) +#define PHYCLKRST_COMMONONN			(0x1 << 0) + +#define EXYNOS5_DRD_PHYREG0			(0x14) +#define EXYNOS5_DRD_PHYREG1			(0x18) + +#define EXYNOS5_DRD_PHYPARAM0			(0x1c) + +#define PHYPARAM0_REF_USE_PAD			(0x1 << 31) +#define PHYPARAM0_REF_LOSLEVEL_MASK		(0x1f << 26) +#define PHYPARAM0_REF_LOSLEVEL			(0x9 << 26) + +#define EXYNOS5_DRD_PHYPARAM1			(0x20) + +#define PHYPARAM1_PCS_TXDEEMPH_MASK		(0x1f << 0) +#define PHYPARAM1_PCS_TXDEEMPH			(0x1c) + +#define EXYNOS5_DRD_PHYTERM			(0x24) + +#define EXYNOS5_DRD_PHYTEST			(0x28) + +#define PHYTEST_POWERDOWN_SSP			(0x1 << 3) +#define PHYTEST_POWERDOWN_HSP			(0x1 << 2) + +#define EXYNOS5_DRD_PHYADP			(0x2c) + +#define EXYNOS5_DRD_PHYBATCHG			(0x30) + +#define PHYBATCHG_UTMI_CLKSEL			(0x1 << 2) + +#define EXYNOS5_DRD_PHYRESUME			(0x34) +#define EXYNOS5_DRD_LINKPORT			(0x44) + +#ifndef MHZ +#define MHZ (1000*1000) +#endif + +#ifndef KHZ +#define KHZ (1000) +#endif + +#define EXYNOS_USBHOST_PHY_CTRL_OFFSET		(0x4) +#define S3C64XX_USBPHY_ENABLE			(0x1 << 16) +#define EXYNOS_USBPHY_ENABLE			(0x1 << 0) +#define EXYNOS_USB20PHY_CFG_HOST_LINK		(0x1 << 0) + +enum samsung_cpu_type { +	TYPE_S3C64XX, +	TYPE_EXYNOS4210, +	TYPE_EXYNOS5250, +}; + +/* + * struct samsung_usbphy_drvdata - driver data for various SoC variants + * @cpu_type: machine identifier + * @devphy_en_mask: device phy enable mask for PHY CONTROL register + * @hostphy_en_mask: host phy enable mask for PHY CONTROL register + * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from + *		       mapped address of system controller. + * @hostphy_reg_offset: offset to HOST PHY CONTROL register from + *		       mapped address of system controller. + * + *	Here we have a separate mask for device type phy. + *	Having different masks for host and device type phy helps + *	in setting independent masks in case of SoCs like S5PV210, + *	in which PHY0 and PHY1 enable bits belong to same register + *	placed at position 0 and 1 respectively. + *	Although for newer SoCs like exynos these bits belong to + *	different registers altogether placed at position 0. + */ +struct samsung_usbphy_drvdata { +	int cpu_type; +	int devphy_en_mask; +	int hostphy_en_mask; +	u32 devphy_reg_offset; +	u32 hostphy_reg_offset; +}; + +/* + * struct samsung_usbphy - transceiver driver state + * @phy: transceiver structure + * @plat: platform data + * @dev: The parent device supplied to the probe function + * @clk: usb phy clock + * @regs: usb phy controller registers memory base + * @pmuregs: USB device PHY_CONTROL register memory base + * @sysreg: USB2.0 PHY_CFG register memory base + * @ref_clk_freq: reference clock frequency selection + * @drv_data: driver data available for different SoCs + * @phy_type: Samsung SoCs specific phy types:	#HOST + *						#DEVICE + * @phy_usage: usage count for phy + * @lock: lock for phy operations + */ +struct samsung_usbphy { +	struct usb_phy	phy; +	struct samsung_usbphy_data *plat; +	struct device	*dev; +	struct clk	*clk; +	void __iomem	*regs; +	void __iomem	*pmuregs; +	void __iomem	*sysreg; +	int		ref_clk_freq; +	const struct samsung_usbphy_drvdata *drv_data; +	enum samsung_usb_phy_type phy_type; +	atomic_t	phy_usage; +	spinlock_t	lock; +}; + +#define phy_to_sphy(x)		container_of((x), struct samsung_usbphy, phy) + +static const struct of_device_id samsung_usbphy_dt_match[]; + +static inline const struct samsung_usbphy_drvdata +*samsung_usbphy_get_driver_data(struct platform_device *pdev) +{ +	if (pdev->dev.of_node) { +		const struct of_device_id *match; +		match = of_match_node(samsung_usbphy_dt_match, +							pdev->dev.of_node); +		return match->data; +	} + +	return (struct samsung_usbphy_drvdata *) +				platform_get_device_id(pdev)->driver_data; +} + +extern int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy); +extern void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on); +extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy); +extern int samsung_usbphy_set_type(struct usb_phy *phy, +					enum samsung_usb_phy_type phy_type); +extern int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy); diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c new file mode 100644 index 00000000000..45ffe036dac --- /dev/null +++ b/drivers/usb/phy/phy-samsung-usb2.c @@ -0,0 +1,509 @@ +/* linux/drivers/usb/phy/phy-samsung-usb2.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + *              http://www.samsung.com + * + * Author: Praveen Paneri <p.paneri@samsung.com> + * + * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and + * OHCI-EXYNOS controllers. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/usb/otg.h> +#include <linux/usb/samsung_usb_phy.h> +#include <linux/platform_data/samsung-usbphy.h> + +#include "phy-samsung-usb.h" + +static int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host) +{ +	if (!otg) +		return -ENODEV; + +	if (!otg->host) +		otg->host = host; + +	return 0; +} + +static bool exynos5_phyhost_is_on(void __iomem *regs) +{ +	u32 reg; + +	reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0); + +	return !(reg & HOST_CTRL0_SIDDQ); +} + +static void samsung_exynos5_usb2phy_enable(struct samsung_usbphy *sphy) +{ +	void __iomem *regs = sphy->regs; +	u32 phyclk = sphy->ref_clk_freq; +	u32 phyhost; +	u32 phyotg; +	u32 phyhsic; +	u32 ehcictrl; +	u32 ohcictrl; + +	/* +	 * phy_usage helps in keeping usage count for phy +	 * so that the first consumer enabling the phy is also +	 * the last consumer to disable it. +	 */ + +	atomic_inc(&sphy->phy_usage); + +	if (exynos5_phyhost_is_on(regs)) { +		dev_info(sphy->dev, "Already power on PHY\n"); +		return; +	} + +	/* Host configuration */ +	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0); + +	/* phy reference clock configuration */ +	phyhost &= ~HOST_CTRL0_FSEL_MASK; +	phyhost |= HOST_CTRL0_FSEL(phyclk); + +	/* host phy reset */ +	phyhost &= ~(HOST_CTRL0_PHYSWRST | +			HOST_CTRL0_PHYSWRSTALL | +			HOST_CTRL0_SIDDQ | +			/* Enable normal mode of operation */ +			HOST_CTRL0_FORCESUSPEND | +			HOST_CTRL0_FORCESLEEP); + +	/* Link reset */ +	phyhost |= (HOST_CTRL0_LINKSWRST | +			HOST_CTRL0_UTMISWRST | +			/* COMMON Block configuration during suspend */ +			HOST_CTRL0_COMMONON_N); +	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); +	udelay(10); +	phyhost &= ~(HOST_CTRL0_LINKSWRST | +			HOST_CTRL0_UTMISWRST); +	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); + +	/* OTG configuration */ +	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS); + +	/* phy reference clock configuration */ +	phyotg &= ~OTG_SYS_FSEL_MASK; +	phyotg |= OTG_SYS_FSEL(phyclk); + +	/* Enable normal mode of operation */ +	phyotg &= ~(OTG_SYS_FORCESUSPEND | +			OTG_SYS_SIDDQ_UOTG | +			OTG_SYS_FORCESLEEP | +			OTG_SYS_REFCLKSEL_MASK | +			/* COMMON Block configuration during suspend */ +			OTG_SYS_COMMON_ON); + +	/* OTG phy & link reset */ +	phyotg |= (OTG_SYS_PHY0_SWRST | +			OTG_SYS_LINKSWRST_UOTG | +			OTG_SYS_PHYLINK_SWRESET | +			OTG_SYS_OTGDISABLE | +			/* Set phy refclk */ +			OTG_SYS_REFCLKSEL_CLKCORE); + +	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); +	udelay(10); +	phyotg &= ~(OTG_SYS_PHY0_SWRST | +			OTG_SYS_LINKSWRST_UOTG | +			OTG_SYS_PHYLINK_SWRESET); +	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); + +	/* HSIC phy configuration */ +	phyhsic = (HSIC_CTRL_REFCLKDIV_12 | +			HSIC_CTRL_REFCLKSEL | +			HSIC_CTRL_PHYSWRST); +	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); +	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); +	udelay(10); +	phyhsic &= ~HSIC_CTRL_PHYSWRST; +	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); +	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); + +	udelay(80); + +	/* enable EHCI DMA burst */ +	ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL); +	ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN | +				HOST_EHCICTRL_ENAINCR4 | +				HOST_EHCICTRL_ENAINCR8 | +				HOST_EHCICTRL_ENAINCR16); +	writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL); + +	/* set ohci_suspend_on_n */ +	ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL); +	ohcictrl |= HOST_OHCICTRL_SUSPLGCY; +	writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL); +} + +static void samsung_usb2phy_enable(struct samsung_usbphy *sphy) +{ +	void __iomem *regs = sphy->regs; +	u32 phypwr; +	u32 phyclk; +	u32 rstcon; + +	/* set clock frequency for PLL */ +	phyclk = sphy->ref_clk_freq; +	phypwr = readl(regs + SAMSUNG_PHYPWR); +	rstcon = readl(regs + SAMSUNG_RSTCON); + +	switch (sphy->drv_data->cpu_type) { +	case TYPE_S3C64XX: +		phyclk &= ~PHYCLK_COMMON_ON_N; +		phypwr &= ~PHYPWR_NORMAL_MASK; +		rstcon |= RSTCON_SWRST; +		break; +	case TYPE_EXYNOS4210: +		phypwr &= ~PHYPWR_NORMAL_MASK_PHY0; +		rstcon |= RSTCON_SWRST; +	default: +		break; +	} + +	writel(phyclk, regs + SAMSUNG_PHYCLK); +	/* Configure PHY0 for normal operation*/ +	writel(phypwr, regs + SAMSUNG_PHYPWR); +	/* reset all ports of PHY and Link */ +	writel(rstcon, regs + SAMSUNG_RSTCON); +	udelay(10); +	rstcon &= ~RSTCON_SWRST; +	writel(rstcon, regs + SAMSUNG_RSTCON); +} + +static void samsung_exynos5_usb2phy_disable(struct samsung_usbphy *sphy) +{ +	void __iomem *regs = sphy->regs; +	u32 phyhost; +	u32 phyotg; +	u32 phyhsic; + +	if (atomic_dec_return(&sphy->phy_usage) > 0) { +		dev_info(sphy->dev, "still being used\n"); +		return; +	} + +	phyhsic = (HSIC_CTRL_REFCLKDIV_12 | +			HSIC_CTRL_REFCLKSEL | +			HSIC_CTRL_SIDDQ | +			HSIC_CTRL_FORCESLEEP | +			HSIC_CTRL_FORCESUSPEND); +	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); +	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); + +	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0); +	phyhost |= (HOST_CTRL0_SIDDQ | +			HOST_CTRL0_FORCESUSPEND | +			HOST_CTRL0_FORCESLEEP | +			HOST_CTRL0_PHYSWRST | +			HOST_CTRL0_PHYSWRSTALL); +	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); + +	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS); +	phyotg |= (OTG_SYS_FORCESUSPEND | +			OTG_SYS_SIDDQ_UOTG | +			OTG_SYS_FORCESLEEP); +	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); +} + +static void samsung_usb2phy_disable(struct samsung_usbphy *sphy) +{ +	void __iomem *regs = sphy->regs; +	u32 phypwr; + +	phypwr = readl(regs + SAMSUNG_PHYPWR); + +	switch (sphy->drv_data->cpu_type) { +	case TYPE_S3C64XX: +		phypwr |= PHYPWR_NORMAL_MASK; +		break; +	case TYPE_EXYNOS4210: +		phypwr |= PHYPWR_NORMAL_MASK_PHY0; +	default: +		break; +	} + +	/* Disable analog and otg block power */ +	writel(phypwr, regs + SAMSUNG_PHYPWR); +} + +/* + * The function passed to the usb driver for phy initialization + */ +static int samsung_usb2phy_init(struct usb_phy *phy) +{ +	struct samsung_usbphy *sphy; +	struct usb_bus *host = NULL; +	unsigned long flags; +	int ret = 0; + +	sphy = phy_to_sphy(phy); + +	host = phy->otg->host; + +	/* Enable the phy clock */ +	ret = clk_prepare_enable(sphy->clk); +	if (ret) { +		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); +		return ret; +	} + +	spin_lock_irqsave(&sphy->lock, flags); + +	if (host) { +		/* setting default phy-type for USB 2.0 */ +		if (!strstr(dev_name(host->controller), "ehci") || +				!strstr(dev_name(host->controller), "ohci")) +			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST); +	} else { +		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); +	} + +	/* Disable phy isolation */ +	if (sphy->plat && sphy->plat->pmu_isolation) +		sphy->plat->pmu_isolation(false); +	else +		samsung_usbphy_set_isolation(sphy, false); + +	/* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */ +	samsung_usbphy_cfg_sel(sphy); + +	/* Initialize usb phy registers */ +	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) +		samsung_exynos5_usb2phy_enable(sphy); +	else +		samsung_usb2phy_enable(sphy); + +	spin_unlock_irqrestore(&sphy->lock, flags); + +	/* Disable the phy clock */ +	clk_disable_unprepare(sphy->clk); + +	return ret; +} + +/* + * The function passed to the usb driver for phy shutdown + */ +static void samsung_usb2phy_shutdown(struct usb_phy *phy) +{ +	struct samsung_usbphy *sphy; +	struct usb_bus *host = NULL; +	unsigned long flags; + +	sphy = phy_to_sphy(phy); + +	host = phy->otg->host; + +	if (clk_prepare_enable(sphy->clk)) { +		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); +		return; +	} + +	spin_lock_irqsave(&sphy->lock, flags); + +	if (host) { +		/* setting default phy-type for USB 2.0 */ +		if (!strstr(dev_name(host->controller), "ehci") || +				!strstr(dev_name(host->controller), "ohci")) +			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST); +	} else { +		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); +	} + +	/* De-initialize usb phy registers */ +	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) +		samsung_exynos5_usb2phy_disable(sphy); +	else +		samsung_usb2phy_disable(sphy); + +	/* Enable phy isolation */ +	if (sphy->plat && sphy->plat->pmu_isolation) +		sphy->plat->pmu_isolation(true); +	else +		samsung_usbphy_set_isolation(sphy, true); + +	spin_unlock_irqrestore(&sphy->lock, flags); + +	clk_disable_unprepare(sphy->clk); +} + +static int samsung_usb2phy_probe(struct platform_device *pdev) +{ +	struct samsung_usbphy *sphy; +	struct usb_otg *otg; +	struct samsung_usbphy_data *pdata = pdev->dev.platform_data; +	const struct samsung_usbphy_drvdata *drv_data; +	struct device *dev = &pdev->dev; +	struct resource *phy_mem; +	void __iomem	*phy_base; +	struct clk *clk; +	int ret; + +	phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!phy_mem) { +		dev_err(dev, "%s: missing mem resource\n", __func__); +		return -ENODEV; +	} + +	phy_base = devm_ioremap_resource(dev, phy_mem); +	if (IS_ERR(phy_base)) +		return PTR_ERR(phy_base); + +	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL); +	if (!sphy) +		return -ENOMEM; + +	otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL); +	if (!otg) +		return -ENOMEM; + +	drv_data = samsung_usbphy_get_driver_data(pdev); + +	if (drv_data->cpu_type == TYPE_EXYNOS5250) +		clk = devm_clk_get(dev, "usbhost"); +	else +		clk = devm_clk_get(dev, "otg"); + +	if (IS_ERR(clk)) { +		dev_err(dev, "Failed to get otg clock\n"); +		return PTR_ERR(clk); +	} + +	sphy->dev = dev; + +	if (dev->of_node) { +		ret = samsung_usbphy_parse_dt(sphy); +		if (ret < 0) +			return ret; +	} else { +		if (!pdata) { +			dev_err(dev, "no platform data specified\n"); +			return -EINVAL; +		} +	} + +	sphy->plat		= pdata; +	sphy->regs		= phy_base; +	sphy->clk		= clk; +	sphy->drv_data		= drv_data; +	sphy->phy.dev		= sphy->dev; +	sphy->phy.label		= "samsung-usb2phy"; +	sphy->phy.init		= samsung_usb2phy_init; +	sphy->phy.shutdown	= samsung_usb2phy_shutdown; +	sphy->ref_clk_freq	= samsung_usbphy_get_refclk_freq(sphy); + +	sphy->phy.otg		= otg; +	sphy->phy.otg->phy	= &sphy->phy; +	sphy->phy.otg->set_host = samsung_usbphy_set_host; + +	spin_lock_init(&sphy->lock); + +	platform_set_drvdata(pdev, sphy); + +	return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2); +} + +static int samsung_usb2phy_remove(struct platform_device *pdev) +{ +	struct samsung_usbphy *sphy = platform_get_drvdata(pdev); + +	usb_remove_phy(&sphy->phy); + +	if (sphy->pmuregs) +		iounmap(sphy->pmuregs); +	if (sphy->sysreg) +		iounmap(sphy->sysreg); + +	return 0; +} + +static const struct samsung_usbphy_drvdata usb2phy_s3c64xx = { +	.cpu_type		= TYPE_S3C64XX, +	.devphy_en_mask		= S3C64XX_USBPHY_ENABLE, +}; + +static const struct samsung_usbphy_drvdata usb2phy_exynos4 = { +	.cpu_type		= TYPE_EXYNOS4210, +	.devphy_en_mask		= EXYNOS_USBPHY_ENABLE, +	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE, +}; + +static struct samsung_usbphy_drvdata usb2phy_exynos5 = { +	.cpu_type		= TYPE_EXYNOS5250, +	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE, +	.hostphy_reg_offset	= EXYNOS_USBHOST_PHY_CTRL_OFFSET, +}; + +#ifdef CONFIG_OF +static const struct of_device_id samsung_usbphy_dt_match[] = { +	{ +		.compatible = "samsung,s3c64xx-usb2phy", +		.data = &usb2phy_s3c64xx, +	}, { +		.compatible = "samsung,exynos4210-usb2phy", +		.data = &usb2phy_exynos4, +	}, { +		.compatible = "samsung,exynos5250-usb2phy", +		.data = &usb2phy_exynos5 +	}, +	{}, +}; +MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match); +#endif + +static struct platform_device_id samsung_usbphy_driver_ids[] = { +	{ +		.name		= "s3c64xx-usb2phy", +		.driver_data	= (unsigned long)&usb2phy_s3c64xx, +	}, { +		.name		= "exynos4210-usb2phy", +		.driver_data	= (unsigned long)&usb2phy_exynos4, +	}, { +		.name		= "exynos5250-usb2phy", +		.driver_data	= (unsigned long)&usb2phy_exynos5, +	}, +	{}, +}; + +MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids); + +static struct platform_driver samsung_usb2phy_driver = { +	.probe		= samsung_usb2phy_probe, +	.remove		= samsung_usb2phy_remove, +	.id_table	= samsung_usbphy_driver_ids, +	.driver		= { +		.name	= "samsung-usb2phy", +		.owner	= THIS_MODULE, +		.of_match_table = of_match_ptr(samsung_usbphy_dt_match), +	}, +}; + +module_platform_driver(samsung_usb2phy_driver); + +MODULE_DESCRIPTION("Samsung USB 2.0 phy controller"); +MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:samsung-usb2phy"); diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c new file mode 100644 index 00000000000..133f3d0c554 --- /dev/null +++ b/drivers/usb/phy/phy-samsung-usb3.c @@ -0,0 +1,347 @@ +/* linux/drivers/usb/phy/phy-samsung-usb3.c + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + *              http://www.samsung.com + * + * Author: Vivek Gautam <gautam.vivek@samsung.com> + * + * Samsung USB 3.0 PHY transceiver; talks to DWC3 controller. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/usb/samsung_usb_phy.h> +#include <linux/platform_data/samsung-usbphy.h> + +#include "phy-samsung-usb.h" + +/* + * Sets the phy clk as EXTREFCLK (XXTI) which is internal clock from clock core. + */ +static u32 samsung_usb3phy_set_refclk(struct samsung_usbphy *sphy) +{ +	u32 reg; +	u32 refclk; + +	refclk = sphy->ref_clk_freq; + +	reg = PHYCLKRST_REFCLKSEL_EXT_REFCLK | +		PHYCLKRST_FSEL(refclk); + +	switch (refclk) { +	case FSEL_CLKSEL_50M: +		reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF | +			PHYCLKRST_SSC_REFCLKSEL(0x00)); +		break; +	case FSEL_CLKSEL_20M: +		reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF | +			PHYCLKRST_SSC_REFCLKSEL(0x00)); +		break; +	case FSEL_CLKSEL_19200K: +		reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF | +			PHYCLKRST_SSC_REFCLKSEL(0x88)); +		break; +	case FSEL_CLKSEL_24M: +	default: +		reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF | +			PHYCLKRST_SSC_REFCLKSEL(0x88)); +		break; +	} + +	return reg; +} + +static int samsung_exynos5_usb3phy_enable(struct samsung_usbphy *sphy) +{ +	void __iomem *regs = sphy->regs; +	u32 phyparam0; +	u32 phyparam1; +	u32 linksystem; +	u32 phybatchg; +	u32 phytest; +	u32 phyclkrst; + +	/* Reset USB 3.0 PHY */ +	writel(0x0, regs + EXYNOS5_DRD_PHYREG0); + +	phyparam0 = readl(regs + EXYNOS5_DRD_PHYPARAM0); +	/* Select PHY CLK source */ +	phyparam0 &= ~PHYPARAM0_REF_USE_PAD; +	/* Set Loss-of-Signal Detector sensitivity */ +	phyparam0 &= ~PHYPARAM0_REF_LOSLEVEL_MASK; +	phyparam0 |= PHYPARAM0_REF_LOSLEVEL; +	writel(phyparam0, regs + EXYNOS5_DRD_PHYPARAM0); + +	writel(0x0, regs + EXYNOS5_DRD_PHYRESUME); + +	/* +	 * Setting the Frame length Adj value[6:1] to default 0x20 +	 * See xHCI 1.0 spec, 5.2.4 +	 */ +	linksystem = LINKSYSTEM_XHCI_VERSION_CONTROL | +			LINKSYSTEM_FLADJ(0x20); +	writel(linksystem, regs + EXYNOS5_DRD_LINKSYSTEM); + +	phyparam1 = readl(regs + EXYNOS5_DRD_PHYPARAM1); +	/* Set Tx De-Emphasis level */ +	phyparam1 &= ~PHYPARAM1_PCS_TXDEEMPH_MASK; +	phyparam1 |= PHYPARAM1_PCS_TXDEEMPH; +	writel(phyparam1, regs + EXYNOS5_DRD_PHYPARAM1); + +	phybatchg = readl(regs + EXYNOS5_DRD_PHYBATCHG); +	phybatchg |= PHYBATCHG_UTMI_CLKSEL; +	writel(phybatchg, regs + EXYNOS5_DRD_PHYBATCHG); + +	/* PHYTEST POWERDOWN Control */ +	phytest = readl(regs + EXYNOS5_DRD_PHYTEST); +	phytest &= ~(PHYTEST_POWERDOWN_SSP | +			PHYTEST_POWERDOWN_HSP); +	writel(phytest, regs + EXYNOS5_DRD_PHYTEST); + +	/* UTMI Power Control */ +	writel(PHYUTMI_OTGDISABLE, regs + EXYNOS5_DRD_PHYUTMI); + +	phyclkrst = samsung_usb3phy_set_refclk(sphy); + +	phyclkrst |= PHYCLKRST_PORTRESET | +			/* Digital power supply in normal operating mode */ +			PHYCLKRST_RETENABLEN | +			/* Enable ref clock for SS function */ +			PHYCLKRST_REF_SSP_EN | +			/* Enable spread spectrum */ +			PHYCLKRST_SSC_EN | +			/* Power down HS Bias and PLL blocks in suspend mode */ +			PHYCLKRST_COMMONONN; + +	writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST); + +	udelay(10); + +	phyclkrst &= ~(PHYCLKRST_PORTRESET); +	writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST); + +	return 0; +} + +static void samsung_exynos5_usb3phy_disable(struct samsung_usbphy *sphy) +{ +	u32 phyutmi; +	u32 phyclkrst; +	u32 phytest; +	void __iomem *regs = sphy->regs; + +	phyutmi = PHYUTMI_OTGDISABLE | +			PHYUTMI_FORCESUSPEND | +			PHYUTMI_FORCESLEEP; +	writel(phyutmi, regs + EXYNOS5_DRD_PHYUTMI); + +	/* Resetting the PHYCLKRST enable bits to reduce leakage current */ +	phyclkrst = readl(regs + EXYNOS5_DRD_PHYCLKRST); +	phyclkrst &= ~(PHYCLKRST_REF_SSP_EN | +			PHYCLKRST_SSC_EN | +			PHYCLKRST_COMMONONN); +	writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST); + +	/* Control PHYTEST to remove leakage current */ +	phytest = readl(regs + EXYNOS5_DRD_PHYTEST); +	phytest |= (PHYTEST_POWERDOWN_SSP | +			PHYTEST_POWERDOWN_HSP); +	writel(phytest, regs + EXYNOS5_DRD_PHYTEST); +} + +static int samsung_usb3phy_init(struct usb_phy *phy) +{ +	struct samsung_usbphy *sphy; +	unsigned long flags; +	int ret = 0; + +	sphy = phy_to_sphy(phy); + +	/* Enable the phy clock */ +	ret = clk_prepare_enable(sphy->clk); +	if (ret) { +		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); +		return ret; +	} + +	spin_lock_irqsave(&sphy->lock, flags); + +	/* setting default phy-type for USB 3.0 */ +	samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); + +	/* Disable phy isolation */ +	samsung_usbphy_set_isolation(sphy, false); + +	/* Initialize usb phy registers */ +	samsung_exynos5_usb3phy_enable(sphy); + +	spin_unlock_irqrestore(&sphy->lock, flags); + +	/* Disable the phy clock */ +	clk_disable_unprepare(sphy->clk); + +	return ret; +} + +/* + * The function passed to the usb driver for phy shutdown + */ +static void samsung_usb3phy_shutdown(struct usb_phy *phy) +{ +	struct samsung_usbphy *sphy; +	unsigned long flags; + +	sphy = phy_to_sphy(phy); + +	if (clk_prepare_enable(sphy->clk)) { +		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); +		return; +	} + +	spin_lock_irqsave(&sphy->lock, flags); + +	/* setting default phy-type for USB 3.0 */ +	samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); + +	/* De-initialize usb phy registers */ +	samsung_exynos5_usb3phy_disable(sphy); + +	/* Enable phy isolation */ +	samsung_usbphy_set_isolation(sphy, true); + +	spin_unlock_irqrestore(&sphy->lock, flags); + +	clk_disable_unprepare(sphy->clk); +} + +static int samsung_usb3phy_probe(struct platform_device *pdev) +{ +	struct samsung_usbphy *sphy; +	struct samsung_usbphy_data *pdata = pdev->dev.platform_data; +	struct device *dev = &pdev->dev; +	struct resource *phy_mem; +	void __iomem	*phy_base; +	struct clk *clk; +	int ret; + +	phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!phy_mem) { +		dev_err(dev, "%s: missing mem resource\n", __func__); +		return -ENODEV; +	} + +	phy_base = devm_ioremap_resource(dev, phy_mem); +	if (IS_ERR(phy_base)) +		return PTR_ERR(phy_base); + +	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL); +	if (!sphy) +		return -ENOMEM; + +	clk = devm_clk_get(dev, "usbdrd30"); +	if (IS_ERR(clk)) { +		dev_err(dev, "Failed to get device clock\n"); +		return PTR_ERR(clk); +	} + +	sphy->dev = dev; + +	if (dev->of_node) { +		ret = samsung_usbphy_parse_dt(sphy); +		if (ret < 0) +			return ret; +	} else { +		if (!pdata) { +			dev_err(dev, "no platform data specified\n"); +			return -EINVAL; +		} +	} + +	sphy->plat		= pdata; +	sphy->regs		= phy_base; +	sphy->clk		= clk; +	sphy->phy.dev		= sphy->dev; +	sphy->phy.label		= "samsung-usb3phy"; +	sphy->phy.init		= samsung_usb3phy_init; +	sphy->phy.shutdown	= samsung_usb3phy_shutdown; +	sphy->drv_data		= samsung_usbphy_get_driver_data(pdev); +	sphy->ref_clk_freq	= samsung_usbphy_get_refclk_freq(sphy); + +	spin_lock_init(&sphy->lock); + +	platform_set_drvdata(pdev, sphy); + +	return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB3); +} + +static int samsung_usb3phy_remove(struct platform_device *pdev) +{ +	struct samsung_usbphy *sphy = platform_get_drvdata(pdev); + +	usb_remove_phy(&sphy->phy); + +	if (sphy->pmuregs) +		iounmap(sphy->pmuregs); +	if (sphy->sysreg) +		iounmap(sphy->sysreg); + +	return 0; +} + +static struct samsung_usbphy_drvdata usb3phy_exynos5 = { +	.cpu_type		= TYPE_EXYNOS5250, +	.devphy_en_mask		= EXYNOS_USBPHY_ENABLE, +}; + +#ifdef CONFIG_OF +static const struct of_device_id samsung_usbphy_dt_match[] = { +	{ +		.compatible = "samsung,exynos5250-usb3phy", +		.data = &usb3phy_exynos5 +	}, +	{}, +}; +MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match); +#endif + +static struct platform_device_id samsung_usbphy_driver_ids[] = { +	{ +		.name		= "exynos5250-usb3phy", +		.driver_data	= (unsigned long)&usb3phy_exynos5, +	}, +	{}, +}; + +MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids); + +static struct platform_driver samsung_usb3phy_driver = { +	.probe		= samsung_usb3phy_probe, +	.remove		= samsung_usb3phy_remove, +	.id_table	= samsung_usbphy_driver_ids, +	.driver		= { +		.name	= "samsung-usb3phy", +		.owner	= THIS_MODULE, +		.of_match_table = of_match_ptr(samsung_usbphy_dt_match), +	}, +}; + +module_platform_driver(samsung_usb3phy_driver); + +MODULE_DESCRIPTION("Samsung USB 3.0 phy controller"); +MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:samsung-usb3phy"); diff --git a/drivers/usb/phy/tegra_usb_phy.c b/drivers/usb/phy/phy-tegra-usb.c index 5487d38481a..17d811292f3 100644 --- a/drivers/usb/phy/tegra_usb_phy.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -299,7 +299,7 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)  		val &= ~USB_SUSP_SET;  		writel(val, base + USB_SUSP_CTRL);  	} else -		tegra_ehci_set_phcd(&phy->u_phy, true); +		phy->set_phcd(&phy->u_phy, true);  	if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)  		pr_err("%s: timeout waiting for phy to stabilize\n", __func__); @@ -321,7 +321,7 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)  		val &= ~USB_SUSP_CLR;  		writel(val, base + USB_SUSP_CTRL);  	} else -		tegra_ehci_set_phcd(&phy->u_phy, false); +		phy->set_phcd(&phy->u_phy, false);  	if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,  						     USB_PHY_CLK_VALID)) @@ -444,7 +444,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)  	utmi_phy_clk_enable(phy);  	if (!phy->is_legacy_phy) -		tegra_ehci_set_pts(&phy->u_phy, 0); +		phy->set_pts(&phy->u_phy, 0);  	return 0;  } @@ -688,7 +688,10 @@ static int	tegra_usb_phy_suspend(struct usb_phy *x, int suspend)  }  struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, -	void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode) +	void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode, +	void (*set_pts)(struct usb_phy *x, u8 pts_val), +	void (*set_phcd)(struct usb_phy *x, bool enable)) +  {  	struct tegra_usb_phy *phy;  	unsigned long parent_rate; @@ -707,6 +710,8 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,  	phy->dev = dev;  	phy->is_legacy_phy =  		of_property_read_bool(np, "nvidia,has-legacy-mode"); +	phy->set_pts = set_pts; +	phy->set_phcd = set_phcd;  	err = of_property_match_string(np, "phy_type", "ulpi");  	if (err < 0)  		phy->is_ulpi_phy = false; diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c index a994715a310..8f78d2d4072 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/phy/phy-twl4030-usb.c @@ -163,6 +163,8 @@ struct twl4030_usb {  	bool			vbus_supplied;  	u8			asleep;  	bool			irq_enabled; + +	struct delayed_work	id_workaround_work;  };  /* internal define on top of container_of */ @@ -246,6 +248,25 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)  /*-------------------------------------------------------------------------*/ +static bool twl4030_is_driving_vbus(struct twl4030_usb *twl) +{ +	int ret; + +	ret = twl4030_usb_read(twl, PHY_CLK_CTRL_STS); +	if (ret < 0 || !(ret & PHY_DPLL_CLK)) +		/* +		 * if clocks are off, registers are not updated, +		 * but we can assume we don't drive VBUS in this case +		 */ +		return false; + +	ret = twl4030_usb_read(twl, ULPI_OTG_CTRL); +	if (ret < 0) +		return false; + +	return (ret & (ULPI_OTG_DRVVBUS | ULPI_OTG_CHRGVBUS)) ? true : false; +} +  static enum omap_musb_vbus_id_status  	twl4030_usb_linkstat(struct twl4030_usb *twl)  { @@ -268,13 +289,19 @@ static enum omap_musb_vbus_id_status  	if (status < 0)  		dev_err(twl->dev, "USB link status err %d\n", status);  	else if (status & (BIT(7) | BIT(2))) { -		if (status & (BIT(7))) -                        twl->vbus_supplied = true; +		if (status & BIT(7)) { +			if (twl4030_is_driving_vbus(twl)) +				status &= ~BIT(7); +			else +				twl->vbus_supplied = true; +		}  		if (status & BIT(2))  			linkstat = OMAP_MUSB_ID_GROUND; -		else +		else if (status & BIT(7))  			linkstat = OMAP_MUSB_VBUS_VALID; +		else +			linkstat = OMAP_MUSB_VBUS_OFF;  	} else {  		if (twl->linkstat != OMAP_MUSB_UNKNOWN)  			linkstat = OMAP_MUSB_VBUS_OFF; @@ -287,10 +314,6 @@ static enum omap_musb_vbus_id_status  	 * are registered, and that both are active...  	 */ -	spin_lock_irq(&twl->lock); -	twl->linkstat = linkstat; -	spin_unlock_irq(&twl->lock); -  	return linkstat;  } @@ -361,9 +384,17 @@ static void __twl4030_phy_power(struct twl4030_usb *twl, int on)  static void twl4030_phy_power(struct twl4030_usb *twl, int on)  { +	int ret; +  	if (on) { -		regulator_enable(twl->usb3v1); -		regulator_enable(twl->usb1v8); +		ret = regulator_enable(twl->usb3v1); +		if (ret) +			dev_err(twl->dev, "Failed to enable usb3v1\n"); + +		ret = regulator_enable(twl->usb1v8); +		if (ret) +			dev_err(twl->dev, "Failed to enable usb1v8\n"); +  		/*  		 * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP  		 * in twl4030) resets the VUSB_DEDICATED2 register. This reset @@ -372,7 +403,11 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)  		 * is re-activated. This ensures that VUSB3V1 is really active.  		 */  		twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); -		regulator_enable(twl->usb1v5); + +		ret = regulator_enable(twl->usb1v5); +		if (ret) +			dev_err(twl->dev, "Failed to enable usb1v5\n"); +  		__twl4030_phy_power(twl, 1);  		twl4030_usb_write(twl, PHY_CLK_CTRL,  				  twl4030_usb_read(twl, PHY_CLK_CTRL) | @@ -412,6 +447,16 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)  	__twl4030_phy_resume(twl);  	twl->asleep = 0;  	dev_dbg(twl->dev, "%s\n", __func__); + +	/* +	 * XXX When VBUS gets driven after musb goes to A mode, +	 * ID_PRES related interrupts no longer arrive, why? +	 * Register itself is updated fine though, so we must poll. +	 */ +	if (twl->linkstat == OMAP_MUSB_ID_GROUND) { +		cancel_delayed_work(&twl->id_workaround_work); +		schedule_delayed_work(&twl->id_workaround_work, HZ); +	}  }  static int twl4030_usb_ldo_init(struct twl4030_usb *twl) @@ -432,7 +477,7 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl)  	/* Initialize 3.1V regulator */  	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); -	twl->usb3v1 = regulator_get(twl->dev, "usb3v1"); +	twl->usb3v1 = devm_regulator_get(twl->dev, "usb3v1");  	if (IS_ERR(twl->usb3v1))  		return -ENODEV; @@ -441,18 +486,18 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl)  	/* Initialize 1.5V regulator */  	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); -	twl->usb1v5 = regulator_get(twl->dev, "usb1v5"); +	twl->usb1v5 = devm_regulator_get(twl->dev, "usb1v5");  	if (IS_ERR(twl->usb1v5)) -		goto fail1; +		return -ENODEV;  	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);  	/* Initialize 1.8V regulator */  	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); -	twl->usb1v8 = regulator_get(twl->dev, "usb1v8"); +	twl->usb1v8 = devm_regulator_get(twl->dev, "usb1v8");  	if (IS_ERR(twl->usb1v8)) -		goto fail2; +		return -ENODEV;  	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); @@ -461,14 +506,6 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl)  			 TWL4030_PM_MASTER_PROTECT_KEY);  	return 0; - -fail2: -	regulator_put(twl->usb1v5); -	twl->usb1v5 = NULL; -fail1: -	regulator_put(twl->usb3v1); -	twl->usb3v1 = NULL; -	return -ENODEV;  }  static ssize_t twl4030_usb_vbus_show(struct device *dev, @@ -491,9 +528,18 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)  {  	struct twl4030_usb *twl = _twl;  	enum omap_musb_vbus_id_status status; +	bool status_changed = false;  	status = twl4030_usb_linkstat(twl); -	if (status > 0) { + +	spin_lock_irq(&twl->lock); +	if (status >= 0 && status != twl->linkstat) { +		twl->linkstat = status; +		status_changed = true; +	} +	spin_unlock_irq(&twl->lock); + +	if (status_changed) {  		/* FIXME add a set_power() method so that B-devices can  		 * configure the charger appropriately.  It's not always  		 * correct to consume VBUS power, and how much current to @@ -505,37 +551,62 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)  		 * USB_LINK_VBUS state.  musb_hdrc won't care until it  		 * starts to handle softconnect right.  		 */ -		if (status == OMAP_MUSB_VBUS_OFF || -				status == OMAP_MUSB_ID_FLOAT) -			twl4030_phy_suspend(twl, 0); -		else -			twl4030_phy_resume(twl); - -		omap_musb_mailbox(twl->linkstat); +		omap_musb_mailbox(status);  	}  	sysfs_notify(&twl->dev->kobj, NULL, "vbus");  	return IRQ_HANDLED;  } -static void twl4030_usb_phy_init(struct twl4030_usb *twl) +static void twl4030_id_workaround_work(struct work_struct *work)  { +	struct twl4030_usb *twl = container_of(work, struct twl4030_usb, +		id_workaround_work.work);  	enum omap_musb_vbus_id_status status; +	bool status_changed = false;  	status = twl4030_usb_linkstat(twl); -	if (status > 0) { -		if (status == OMAP_MUSB_VBUS_OFF || -				status == OMAP_MUSB_ID_FLOAT) { -			__twl4030_phy_power(twl, 0); -			twl->asleep = 1; -		} else { -			__twl4030_phy_resume(twl); -			twl->asleep = 0; -		} -		omap_musb_mailbox(twl->linkstat); +	spin_lock_irq(&twl->lock); +	if (status >= 0 && status != twl->linkstat) { +		twl->linkstat = status; +		status_changed = true; +	} +	spin_unlock_irq(&twl->lock); + +	if (status_changed) { +		dev_dbg(twl->dev, "handle missing status change to %d\n", +				status); +		omap_musb_mailbox(status);  	} + +	/* don't schedule during sleep - irq works right then */ +	if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) { +		cancel_delayed_work(&twl->id_workaround_work); +		schedule_delayed_work(&twl->id_workaround_work, HZ); +	} +} + +static int twl4030_usb_phy_init(struct usb_phy *phy) +{ +	struct twl4030_usb *twl = phy_to_twl(phy); +	enum omap_musb_vbus_id_status status; + +	/* +	 * Start in sleep state, we'll get called through set_suspend() +	 * callback when musb is runtime resumed and it's time to start. +	 */ +	__twl4030_phy_power(twl, 0); +	twl->asleep = 1; + +	status = twl4030_usb_linkstat(twl); +	twl->linkstat = status; + +	if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) +		omap_musb_mailbox(twl->linkstat); +  	sysfs_notify(&twl->dev->kobj, NULL, "vbus"); +	return 0;  }  static int twl4030_set_suspend(struct usb_phy *x, int suspend) @@ -612,6 +683,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)  	twl->phy.otg		= otg;  	twl->phy.type		= USB_PHY_TYPE_USB2;  	twl->phy.set_suspend	= twl4030_set_suspend; +	twl->phy.init		= twl4030_usb_phy_init;  	otg->phy		= &twl->phy;  	otg->set_host		= twl4030_set_host; @@ -620,6 +692,8 @@ static int twl4030_usb_probe(struct platform_device *pdev)  	/* init spinlock for workqueue */  	spin_lock_init(&twl->lock); +	INIT_DELAYED_WORK(&twl->id_workaround_work, twl4030_id_workaround_work); +  	err = twl4030_usb_ldo_init(twl);  	if (err) {  		dev_err(&pdev->dev, "ldo init failed\n"); @@ -640,30 +714,25 @@ static int twl4030_usb_probe(struct platform_device *pdev)  	 * need both handles, otherwise just one suffices.  	 */  	twl->irq_enabled = true; -	status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq, -			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | -			IRQF_ONESHOT, "twl4030_usb", twl); +	status = devm_request_threaded_irq(twl->dev, twl->irq, NULL, +			twl4030_usb_irq, IRQF_TRIGGER_FALLING | +			IRQF_TRIGGER_RISING | IRQF_ONESHOT, "twl4030_usb", twl);  	if (status < 0) {  		dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",  			twl->irq, status);  		return status;  	} -	/* Power down phy or make it work according to -	 * current link state. -	 */ -	twl4030_usb_phy_init(twl); -  	dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");  	return 0;  } -static int __exit twl4030_usb_remove(struct platform_device *pdev) +static int twl4030_usb_remove(struct platform_device *pdev)  {  	struct twl4030_usb *twl = platform_get_drvdata(pdev);  	int val; -	free_irq(twl->irq, twl); +	cancel_delayed_work(&twl->id_workaround_work);  	device_remove_file(twl->dev, &dev_attr_vbus);  	/* set transceiver mode to power on defaults */ @@ -685,9 +754,6 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev)  	if (!twl->asleep)  		twl4030_phy_power(twl, 0); -	regulator_put(twl->usb1v5); -	regulator_put(twl->usb1v8); -	regulator_put(twl->usb3v1);  	return 0;  } @@ -702,7 +768,7 @@ MODULE_DEVICE_TABLE(of, twl4030_usb_id_table);  static struct platform_driver twl4030_usb_driver = {  	.probe		= twl4030_usb_probe, -	.remove		= __exit_p(twl4030_usb_remove), +	.remove		= twl4030_usb_remove,  	.driver		= {  		.name	= "twl4030_usb",  		.owner	= THIS_MODULE, diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c index 8cd6cf49bdb..9de7ada90a8 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/phy/phy-twl6030-usb.c @@ -211,6 +211,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)  	struct twl6030_usb *twl = _twl;  	enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;  	u8 vbus_state, hw_state; +	int ret;  	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); @@ -218,7 +219,10 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)  						CONTROLLER_STAT1);  	if (!(hw_state & STS_USB_ID)) {  		if (vbus_state & VBUS_DET) { -			regulator_enable(twl->usb3v3); +			ret = regulator_enable(twl->usb3v3); +			if (ret) +				dev_err(twl->dev, "Failed to enable usb3v3\n"); +  			twl->asleep = 1;  			status = OMAP_MUSB_VBUS_VALID;  			twl->linkstat = status; @@ -245,12 +249,15 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)  	struct twl6030_usb *twl = _twl;  	enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;  	u8 hw_state; +	int ret;  	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);  	if (hw_state & STS_USB_ID) { +		ret = regulator_enable(twl->usb3v3); +		if (ret) +			dev_err(twl->dev, "Failed to enable usb3v3\n"); -		regulator_enable(twl->usb3v3);  		twl->asleep = 1;  		twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);  		twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); @@ -393,7 +400,7 @@ static int twl6030_usb_probe(struct platform_device *pdev)  	return 0;  } -static int __exit twl6030_usb_remove(struct platform_device *pdev) +static int twl6030_usb_remove(struct platform_device *pdev)  {  	struct twl6030_usb *twl = platform_get_drvdata(pdev); @@ -420,7 +427,7 @@ MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);  static struct platform_driver twl6030_usb_driver = {  	.probe		= twl6030_usb_probe, -	.remove		= __exit_p(twl6030_usb_remove), +	.remove		= twl6030_usb_remove,  	.driver		= {  		.name	= "twl6030_usb",  		.owner	= THIS_MODULE, diff --git a/drivers/usb/otg/ulpi_viewport.c b/drivers/usb/phy/phy-ulpi-viewport.c index c5ba7e5423f..c5ba7e5423f 100644 --- a/drivers/usb/otg/ulpi_viewport.c +++ b/drivers/usb/phy/phy-ulpi-viewport.c diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/phy/phy-ulpi.c index 217339dd7a9..217339dd7a9 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/phy/phy-ulpi.c diff --git a/drivers/usb/otg/otg.c b/drivers/usb/phy/phy.c index 2bd03d261a5..a9984c700d2 100644 --- a/drivers/usb/otg/otg.c +++ b/drivers/usb/phy/phy.c @@ -1,14 +1,13 @@  /* - * otg.c -- USB OTG utility code + * phy.c -- USB phy handling   * - * Copyright (C) 2004 Texas Instruments + * Copyright (C) 2004-2013 Texas Instruments   *   * 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 <linux/kernel.h>  #include <linux/export.h>  #include <linux/err.h> @@ -17,7 +16,7 @@  #include <linux/slab.h>  #include <linux/of.h> -#include <linux/usb/otg.h> +#include <linux/usb/phy.h>  static LIST_HEAD(phy_list);  static LIST_HEAD(phy_bind_list); @@ -110,7 +109,7 @@ struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type)  	return phy;  } -EXPORT_SYMBOL(devm_usb_get_phy); +EXPORT_SYMBOL_GPL(devm_usb_get_phy);  /**   * usb_get_phy - find the USB PHY @@ -143,7 +142,7 @@ err0:  	return phy;  } -EXPORT_SYMBOL(usb_get_phy); +EXPORT_SYMBOL_GPL(usb_get_phy);   /**   * devm_usb_get_phy_by_phandle - find the USB PHY by phandle @@ -207,7 +206,7 @@ err0:  	return phy;  } -EXPORT_SYMBOL(devm_usb_get_phy_by_phandle); +EXPORT_SYMBOL_GPL(devm_usb_get_phy_by_phandle);  /**   * usb_get_phy_dev - find the USB PHY @@ -240,7 +239,7 @@ err0:  	return phy;  } -EXPORT_SYMBOL(usb_get_phy_dev); +EXPORT_SYMBOL_GPL(usb_get_phy_dev);  /**   * devm_usb_get_phy_dev - find the USB PHY using device ptr and index @@ -270,7 +269,7 @@ struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)  	return phy;  } -EXPORT_SYMBOL(devm_usb_get_phy_dev); +EXPORT_SYMBOL_GPL(devm_usb_get_phy_dev);  /**   * devm_usb_put_phy - release the USB PHY @@ -289,7 +288,7 @@ void devm_usb_put_phy(struct device *dev, struct usb_phy *phy)  	r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy);  	dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");  } -EXPORT_SYMBOL(devm_usb_put_phy); +EXPORT_SYMBOL_GPL(devm_usb_put_phy);  /**   * usb_put_phy - release the USB PHY @@ -308,7 +307,7 @@ void usb_put_phy(struct usb_phy *x)  		module_put(owner);  	}  } -EXPORT_SYMBOL(usb_put_phy); +EXPORT_SYMBOL_GPL(usb_put_phy);  /**   * usb_add_phy - declare the USB PHY @@ -348,7 +347,7 @@ out:  	spin_unlock_irqrestore(&phy_lock, flags);  	return ret;  } -EXPORT_SYMBOL(usb_add_phy); +EXPORT_SYMBOL_GPL(usb_add_phy);  /**   * usb_add_phy_dev - declare the USB PHY @@ -378,7 +377,7 @@ int usb_add_phy_dev(struct usb_phy *x)  	spin_unlock_irqrestore(&phy_lock, flags);  	return 0;  } -EXPORT_SYMBOL(usb_add_phy_dev); +EXPORT_SYMBOL_GPL(usb_add_phy_dev);  /**   * usb_remove_phy - remove the OTG PHY @@ -400,7 +399,7 @@ void usb_remove_phy(struct usb_phy *x)  	}  	spin_unlock_irqrestore(&phy_lock, flags);  } -EXPORT_SYMBOL(usb_remove_phy); +EXPORT_SYMBOL_GPL(usb_remove_phy);  /**   * usb_bind_phy - bind the phy and the controller that uses the phy @@ -414,7 +413,7 @@ EXPORT_SYMBOL(usb_remove_phy);   *   * To be used by platform specific initialization code.   */ -int __init usb_bind_phy(const char *dev_name, u8 index, +int usb_bind_phy(const char *dev_name, u8 index,  				const char *phy_dev_name)  {  	struct usb_phy_bind *phy_bind; @@ -437,38 +436,3 @@ int __init usb_bind_phy(const char *dev_name, u8 index,  	return 0;  }  EXPORT_SYMBOL_GPL(usb_bind_phy); - -const char *otg_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"; -	} -} -EXPORT_SYMBOL(otg_state_string); diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/samsung-usbphy.c deleted file mode 100644 index 967101ec15f..00000000000 --- a/drivers/usb/phy/samsung-usbphy.c +++ /dev/null @@ -1,928 +0,0 @@ -/* linux/drivers/usb/phy/samsung-usbphy.c - * - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - *              http://www.samsung.com - * - * Author: Praveen Paneri <p.paneri@samsung.com> - * - * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and - * OHCI-EXYNOS controllers. - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/clk.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/usb/otg.h> -#include <linux/usb/samsung_usb_phy.h> -#include <linux/platform_data/samsung-usbphy.h> - -/* Register definitions */ - -#define SAMSUNG_PHYPWR				(0x00) - -#define PHYPWR_NORMAL_MASK			(0x19 << 0) -#define PHYPWR_OTG_DISABLE			(0x1 << 4) -#define PHYPWR_ANALOG_POWERDOWN			(0x1 << 3) -#define PHYPWR_FORCE_SUSPEND			(0x1 << 1) -/* For Exynos4 */ -#define PHYPWR_NORMAL_MASK_PHY0			(0x39 << 0) -#define PHYPWR_SLEEP_PHY0			(0x1 << 5) - -#define SAMSUNG_PHYCLK				(0x04) - -#define PHYCLK_MODE_USB11			(0x1 << 6) -#define PHYCLK_EXT_OSC				(0x1 << 5) -#define PHYCLK_COMMON_ON_N			(0x1 << 4) -#define PHYCLK_ID_PULL				(0x1 << 2) -#define PHYCLK_CLKSEL_MASK			(0x3 << 0) -#define PHYCLK_CLKSEL_48M			(0x0 << 0) -#define PHYCLK_CLKSEL_12M			(0x2 << 0) -#define PHYCLK_CLKSEL_24M			(0x3 << 0) - -#define SAMSUNG_RSTCON				(0x08) - -#define RSTCON_PHYLINK_SWRST			(0x1 << 2) -#define RSTCON_HLINK_SWRST			(0x1 << 1) -#define RSTCON_SWRST				(0x1 << 0) - -/* EXYNOS5 */ -#define EXYNOS5_PHY_HOST_CTRL0			(0x00) - -#define HOST_CTRL0_PHYSWRSTALL			(0x1 << 31) - -#define HOST_CTRL0_REFCLKSEL_MASK		(0x3 << 19) -#define HOST_CTRL0_REFCLKSEL_XTAL		(0x0 << 19) -#define HOST_CTRL0_REFCLKSEL_EXTL		(0x1 << 19) -#define HOST_CTRL0_REFCLKSEL_CLKCORE		(0x2 << 19) - -#define HOST_CTRL0_FSEL_MASK			(0x7 << 16) -#define HOST_CTRL0_FSEL(_x)			((_x) << 16) - -#define FSEL_CLKSEL_50M				(0x7) -#define FSEL_CLKSEL_24M				(0x5) -#define FSEL_CLKSEL_20M				(0x4) -#define FSEL_CLKSEL_19200K			(0x3) -#define FSEL_CLKSEL_12M				(0x2) -#define FSEL_CLKSEL_10M				(0x1) -#define FSEL_CLKSEL_9600K			(0x0) - -#define HOST_CTRL0_TESTBURNIN			(0x1 << 11) -#define HOST_CTRL0_RETENABLE			(0x1 << 10) -#define HOST_CTRL0_COMMONON_N			(0x1 << 9) -#define HOST_CTRL0_SIDDQ			(0x1 << 6) -#define HOST_CTRL0_FORCESLEEP			(0x1 << 5) -#define HOST_CTRL0_FORCESUSPEND			(0x1 << 4) -#define HOST_CTRL0_WORDINTERFACE		(0x1 << 3) -#define HOST_CTRL0_UTMISWRST			(0x1 << 2) -#define HOST_CTRL0_LINKSWRST			(0x1 << 1) -#define HOST_CTRL0_PHYSWRST			(0x1 << 0) - -#define EXYNOS5_PHY_HOST_TUNE0			(0x04) - -#define EXYNOS5_PHY_HSIC_CTRL1			(0x10) - -#define EXYNOS5_PHY_HSIC_TUNE1			(0x14) - -#define EXYNOS5_PHY_HSIC_CTRL2			(0x20) - -#define EXYNOS5_PHY_HSIC_TUNE2			(0x24) - -#define HSIC_CTRL_REFCLKSEL_MASK		(0x3 << 23) -#define HSIC_CTRL_REFCLKSEL			(0x2 << 23) - -#define HSIC_CTRL_REFCLKDIV_MASK		(0x7f << 16) -#define HSIC_CTRL_REFCLKDIV(_x)			((_x) << 16) -#define HSIC_CTRL_REFCLKDIV_12			(0x24 << 16) -#define HSIC_CTRL_REFCLKDIV_15			(0x1c << 16) -#define HSIC_CTRL_REFCLKDIV_16			(0x1a << 16) -#define HSIC_CTRL_REFCLKDIV_19_2		(0x15 << 16) -#define HSIC_CTRL_REFCLKDIV_20			(0x14 << 16) - -#define HSIC_CTRL_SIDDQ				(0x1 << 6) -#define HSIC_CTRL_FORCESLEEP			(0x1 << 5) -#define HSIC_CTRL_FORCESUSPEND			(0x1 << 4) -#define HSIC_CTRL_WORDINTERFACE			(0x1 << 3) -#define HSIC_CTRL_UTMISWRST			(0x1 << 2) -#define HSIC_CTRL_PHYSWRST			(0x1 << 0) - -#define EXYNOS5_PHY_HOST_EHCICTRL		(0x30) - -#define HOST_EHCICTRL_ENAINCRXALIGN		(0x1 << 29) -#define HOST_EHCICTRL_ENAINCR4			(0x1 << 28) -#define HOST_EHCICTRL_ENAINCR8			(0x1 << 27) -#define HOST_EHCICTRL_ENAINCR16			(0x1 << 26) - -#define EXYNOS5_PHY_HOST_OHCICTRL		(0x34) - -#define HOST_OHCICTRL_SUSPLGCY			(0x1 << 3) -#define HOST_OHCICTRL_APPSTARTCLK		(0x1 << 2) -#define HOST_OHCICTRL_CNTSEL			(0x1 << 1) -#define HOST_OHCICTRL_CLKCKTRST			(0x1 << 0) - -#define EXYNOS5_PHY_OTG_SYS			(0x38) - -#define OTG_SYS_PHYLINK_SWRESET			(0x1 << 14) -#define OTG_SYS_LINKSWRST_UOTG			(0x1 << 13) -#define OTG_SYS_PHY0_SWRST			(0x1 << 12) - -#define OTG_SYS_REFCLKSEL_MASK			(0x3 << 9) -#define OTG_SYS_REFCLKSEL_XTAL			(0x0 << 9) -#define OTG_SYS_REFCLKSEL_EXTL			(0x1 << 9) -#define OTG_SYS_REFCLKSEL_CLKCORE		(0x2 << 9) - -#define OTG_SYS_IDPULLUP_UOTG			(0x1 << 8) -#define OTG_SYS_COMMON_ON			(0x1 << 7) - -#define OTG_SYS_FSEL_MASK			(0x7 << 4) -#define OTG_SYS_FSEL(_x)			((_x) << 4) - -#define OTG_SYS_FORCESLEEP			(0x1 << 3) -#define OTG_SYS_OTGDISABLE			(0x1 << 2) -#define OTG_SYS_SIDDQ_UOTG			(0x1 << 1) -#define OTG_SYS_FORCESUSPEND			(0x1 << 0) - -#define EXYNOS5_PHY_OTG_TUNE			(0x40) - -#ifndef MHZ -#define MHZ (1000*1000) -#endif - -#ifndef KHZ -#define KHZ (1000) -#endif - -#define EXYNOS_USBHOST_PHY_CTRL_OFFSET		(0x4) -#define S3C64XX_USBPHY_ENABLE			(0x1 << 16) -#define EXYNOS_USBPHY_ENABLE			(0x1 << 0) -#define EXYNOS_USB20PHY_CFG_HOST_LINK		(0x1 << 0) - -enum samsung_cpu_type { -	TYPE_S3C64XX, -	TYPE_EXYNOS4210, -	TYPE_EXYNOS5250, -}; - -/* - * struct samsung_usbphy_drvdata - driver data for various SoC variants - * @cpu_type: machine identifier - * @devphy_en_mask: device phy enable mask for PHY CONTROL register - * @hostphy_en_mask: host phy enable mask for PHY CONTROL register - * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from - *		       mapped address of system controller. - * @hostphy_reg_offset: offset to HOST PHY CONTROL register from - *		       mapped address of system controller. - * - *	Here we have a separate mask for device type phy. - *	Having different masks for host and device type phy helps - *	in setting independent masks in case of SoCs like S5PV210, - *	in which PHY0 and PHY1 enable bits belong to same register - *	placed at position 0 and 1 respectively. - *	Although for newer SoCs like exynos these bits belong to - *	different registers altogether placed at position 0. - */ -struct samsung_usbphy_drvdata { -	int cpu_type; -	int devphy_en_mask; -	int hostphy_en_mask; -	u32 devphy_reg_offset; -	u32 hostphy_reg_offset; -}; - -/* - * struct samsung_usbphy - transceiver driver state - * @phy: transceiver structure - * @plat: platform data - * @dev: The parent device supplied to the probe function - * @clk: usb phy clock - * @regs: usb phy controller registers memory base - * @pmuregs: USB device PHY_CONTROL register memory base - * @sysreg: USB2.0 PHY_CFG register memory base - * @ref_clk_freq: reference clock frequency selection - * @drv_data: driver data available for different SoCs - * @phy_type: Samsung SoCs specific phy types:	#HOST - *						#DEVICE - * @phy_usage: usage count for phy - * @lock: lock for phy operations - */ -struct samsung_usbphy { -	struct usb_phy	phy; -	struct samsung_usbphy_data *plat; -	struct device	*dev; -	struct clk	*clk; -	void __iomem	*regs; -	void __iomem	*pmuregs; -	void __iomem	*sysreg; -	int		ref_clk_freq; -	const struct samsung_usbphy_drvdata *drv_data; -	enum samsung_usb_phy_type phy_type; -	atomic_t	phy_usage; -	spinlock_t	lock; -}; - -#define phy_to_sphy(x)		container_of((x), struct samsung_usbphy, phy) - -int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host) -{ -	if (!otg) -		return -ENODEV; - -	if (!otg->host) -		otg->host = host; - -	return 0; -} - -static int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy) -{ -	struct device_node *usbphy_sys; - -	/* Getting node for system controller interface for usb-phy */ -	usbphy_sys = of_get_child_by_name(sphy->dev->of_node, "usbphy-sys"); -	if (!usbphy_sys) { -		dev_err(sphy->dev, "No sys-controller interface for usb-phy\n"); -		return -ENODEV; -	} - -	sphy->pmuregs = of_iomap(usbphy_sys, 0); - -	if (sphy->pmuregs == NULL) { -		dev_err(sphy->dev, "Can't get usb-phy pmu control register\n"); -		goto err0; -	} - -	sphy->sysreg = of_iomap(usbphy_sys, 1); - -	/* -	 * Not returning error code here, since this situation is not fatal. -	 * Few SoCs may not have this switch available -	 */ -	if (sphy->sysreg == NULL) -		dev_warn(sphy->dev, "Can't get usb-phy sysreg cfg register\n"); - -	of_node_put(usbphy_sys); - -	return 0; - -err0: -	of_node_put(usbphy_sys); -	return -ENXIO; -} - -/* - * Set isolation here for phy. - * Here 'on = true' would mean USB PHY block is isolated, hence - * de-activated and vice-versa. - */ -static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on) -{ -	void __iomem *reg = NULL; -	u32 reg_val; -	u32 en_mask = 0; - -	if (!sphy->pmuregs) { -		dev_warn(sphy->dev, "Can't set pmu isolation\n"); -		return; -	} - -	switch (sphy->drv_data->cpu_type) { -	case TYPE_S3C64XX: -		/* -		 * Do nothing: We will add here once S3C64xx goes for DT support -		 */ -		break; -	case TYPE_EXYNOS4210: -		/* -		 * Fall through since exynos4210 and exynos5250 have similar -		 * register architecture: two separate registers for host and -		 * device phy control with enable bit at position 0. -		 */ -	case TYPE_EXYNOS5250: -		if (sphy->phy_type == USB_PHY_TYPE_DEVICE) { -			reg = sphy->pmuregs + -				sphy->drv_data->devphy_reg_offset; -			en_mask = sphy->drv_data->devphy_en_mask; -		} else if (sphy->phy_type == USB_PHY_TYPE_HOST) { -			reg = sphy->pmuregs + -				sphy->drv_data->hostphy_reg_offset; -			en_mask = sphy->drv_data->hostphy_en_mask; -		} -		break; -	default: -		dev_err(sphy->dev, "Invalid SoC type\n"); -		return; -	} - -	reg_val = readl(reg); - -	if (on) -		reg_val &= ~en_mask; -	else -		reg_val |= en_mask; - -	writel(reg_val, reg); -} - -/* - * Configure the mode of working of usb-phy here: HOST/DEVICE. - */ -static void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy) -{ -	u32 reg; - -	if (!sphy->sysreg) { -		dev_warn(sphy->dev, "Can't configure specified phy mode\n"); -		return; -	} - -	reg = readl(sphy->sysreg); - -	if (sphy->phy_type == USB_PHY_TYPE_DEVICE) -		reg &= ~EXYNOS_USB20PHY_CFG_HOST_LINK; -	else if (sphy->phy_type == USB_PHY_TYPE_HOST) -		reg |= EXYNOS_USB20PHY_CFG_HOST_LINK; - -	writel(reg, sphy->sysreg); -} - -/* - * PHYs are different for USB Device and USB Host. - * This make sure that correct PHY type is selected before - * any operation on PHY. - */ -static int samsung_usbphy_set_type(struct usb_phy *phy, -				enum samsung_usb_phy_type phy_type) -{ -	struct samsung_usbphy *sphy = phy_to_sphy(phy); - -	sphy->phy_type = phy_type; - -	return 0; -} - -/* - * Returns reference clock frequency selection value - */ -static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy) -{ -	struct clk *ref_clk; -	int refclk_freq = 0; - -	/* -	 * In exynos5250 USB host and device PHY use -	 * external crystal clock XXTI -	 */ -	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) -		ref_clk = clk_get(sphy->dev, "ext_xtal"); -	else -		ref_clk = clk_get(sphy->dev, "xusbxti"); -	if (IS_ERR(ref_clk)) { -		dev_err(sphy->dev, "Failed to get reference clock\n"); -		return PTR_ERR(ref_clk); -	} - -	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) { -		/* set clock frequency for PLL */ -		switch (clk_get_rate(ref_clk)) { -		case 9600 * KHZ: -			refclk_freq = FSEL_CLKSEL_9600K; -			break; -		case 10 * MHZ: -			refclk_freq = FSEL_CLKSEL_10M; -			break; -		case 12 * MHZ: -			refclk_freq = FSEL_CLKSEL_12M; -			break; -		case 19200 * KHZ: -			refclk_freq = FSEL_CLKSEL_19200K; -			break; -		case 20 * MHZ: -			refclk_freq = FSEL_CLKSEL_20M; -			break; -		case 50 * MHZ: -			refclk_freq = FSEL_CLKSEL_50M; -			break; -		case 24 * MHZ: -		default: -			/* default reference clock */ -			refclk_freq = FSEL_CLKSEL_24M; -			break; -		} -	} else { -		switch (clk_get_rate(ref_clk)) { -		case 12 * MHZ: -			refclk_freq = PHYCLK_CLKSEL_12M; -			break; -		case 24 * MHZ: -			refclk_freq = PHYCLK_CLKSEL_24M; -			break; -		case 48 * MHZ: -			refclk_freq = PHYCLK_CLKSEL_48M; -			break; -		default: -			if (sphy->drv_data->cpu_type == TYPE_S3C64XX) -				refclk_freq = PHYCLK_CLKSEL_48M; -			else -				refclk_freq = PHYCLK_CLKSEL_24M; -			break; -		} -	} -	clk_put(ref_clk); - -	return refclk_freq; -} - -static bool exynos5_phyhost_is_on(void *regs) -{ -	u32 reg; - -	reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0); - -	return !(reg & HOST_CTRL0_SIDDQ); -} - -static void samsung_exynos5_usbphy_enable(struct samsung_usbphy *sphy) -{ -	void __iomem *regs = sphy->regs; -	u32 phyclk = sphy->ref_clk_freq; -	u32 phyhost; -	u32 phyotg; -	u32 phyhsic; -	u32 ehcictrl; -	u32 ohcictrl; - -	/* -	 * phy_usage helps in keeping usage count for phy -	 * so that the first consumer enabling the phy is also -	 * the last consumer to disable it. -	 */ - -	atomic_inc(&sphy->phy_usage); - -	if (exynos5_phyhost_is_on(regs)) { -		dev_info(sphy->dev, "Already power on PHY\n"); -		return; -	} - -	/* Host configuration */ -	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0); - -	/* phy reference clock configuration */ -	phyhost &= ~HOST_CTRL0_FSEL_MASK; -	phyhost |= HOST_CTRL0_FSEL(phyclk); - -	/* host phy reset */ -	phyhost &= ~(HOST_CTRL0_PHYSWRST | -			HOST_CTRL0_PHYSWRSTALL | -			HOST_CTRL0_SIDDQ | -			/* Enable normal mode of operation */ -			HOST_CTRL0_FORCESUSPEND | -			HOST_CTRL0_FORCESLEEP); - -	/* Link reset */ -	phyhost |= (HOST_CTRL0_LINKSWRST | -			HOST_CTRL0_UTMISWRST | -			/* COMMON Block configuration during suspend */ -			HOST_CTRL0_COMMONON_N); -	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); -	udelay(10); -	phyhost &= ~(HOST_CTRL0_LINKSWRST | -			HOST_CTRL0_UTMISWRST); -	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); - -	/* OTG configuration */ -	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS); - -	/* phy reference clock configuration */ -	phyotg &= ~OTG_SYS_FSEL_MASK; -	phyotg |= OTG_SYS_FSEL(phyclk); - -	/* Enable normal mode of operation */ -	phyotg &= ~(OTG_SYS_FORCESUSPEND | -			OTG_SYS_SIDDQ_UOTG | -			OTG_SYS_FORCESLEEP | -			OTG_SYS_REFCLKSEL_MASK | -			/* COMMON Block configuration during suspend */ -			OTG_SYS_COMMON_ON); - -	/* OTG phy & link reset */ -	phyotg |= (OTG_SYS_PHY0_SWRST | -			OTG_SYS_LINKSWRST_UOTG | -			OTG_SYS_PHYLINK_SWRESET | -			OTG_SYS_OTGDISABLE | -			/* Set phy refclk */ -			OTG_SYS_REFCLKSEL_CLKCORE); - -	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); -	udelay(10); -	phyotg &= ~(OTG_SYS_PHY0_SWRST | -			OTG_SYS_LINKSWRST_UOTG | -			OTG_SYS_PHYLINK_SWRESET); -	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); - -	/* HSIC phy configuration */ -	phyhsic = (HSIC_CTRL_REFCLKDIV_12 | -			HSIC_CTRL_REFCLKSEL | -			HSIC_CTRL_PHYSWRST); -	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); -	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); -	udelay(10); -	phyhsic &= ~HSIC_CTRL_PHYSWRST; -	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); -	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); - -	udelay(80); - -	/* enable EHCI DMA burst */ -	ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL); -	ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN | -				HOST_EHCICTRL_ENAINCR4 | -				HOST_EHCICTRL_ENAINCR8 | -				HOST_EHCICTRL_ENAINCR16); -	writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL); - -	/* set ohci_suspend_on_n */ -	ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL); -	ohcictrl |= HOST_OHCICTRL_SUSPLGCY; -	writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL); -} - -static void samsung_usbphy_enable(struct samsung_usbphy *sphy) -{ -	void __iomem *regs = sphy->regs; -	u32 phypwr; -	u32 phyclk; -	u32 rstcon; - -	/* set clock frequency for PLL */ -	phyclk = sphy->ref_clk_freq; -	phypwr = readl(regs + SAMSUNG_PHYPWR); -	rstcon = readl(regs + SAMSUNG_RSTCON); - -	switch (sphy->drv_data->cpu_type) { -	case TYPE_S3C64XX: -		phyclk &= ~PHYCLK_COMMON_ON_N; -		phypwr &= ~PHYPWR_NORMAL_MASK; -		rstcon |= RSTCON_SWRST; -		break; -	case TYPE_EXYNOS4210: -		phypwr &= ~PHYPWR_NORMAL_MASK_PHY0; -		rstcon |= RSTCON_SWRST; -	default: -		break; -	} - -	writel(phyclk, regs + SAMSUNG_PHYCLK); -	/* Configure PHY0 for normal operation*/ -	writel(phypwr, regs + SAMSUNG_PHYPWR); -	/* reset all ports of PHY and Link */ -	writel(rstcon, regs + SAMSUNG_RSTCON); -	udelay(10); -	rstcon &= ~RSTCON_SWRST; -	writel(rstcon, regs + SAMSUNG_RSTCON); -} - -static void samsung_exynos5_usbphy_disable(struct samsung_usbphy *sphy) -{ -	void __iomem *regs = sphy->regs; -	u32 phyhost; -	u32 phyotg; -	u32 phyhsic; - -	if (atomic_dec_return(&sphy->phy_usage) > 0) { -		dev_info(sphy->dev, "still being used\n"); -		return; -	} - -	phyhsic = (HSIC_CTRL_REFCLKDIV_12 | -			HSIC_CTRL_REFCLKSEL | -			HSIC_CTRL_SIDDQ | -			HSIC_CTRL_FORCESLEEP | -			HSIC_CTRL_FORCESUSPEND); -	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); -	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); - -	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0); -	phyhost |= (HOST_CTRL0_SIDDQ | -			HOST_CTRL0_FORCESUSPEND | -			HOST_CTRL0_FORCESLEEP | -			HOST_CTRL0_PHYSWRST | -			HOST_CTRL0_PHYSWRSTALL); -	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); - -	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS); -	phyotg |= (OTG_SYS_FORCESUSPEND | -			OTG_SYS_SIDDQ_UOTG | -			OTG_SYS_FORCESLEEP); -	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); -} - -static void samsung_usbphy_disable(struct samsung_usbphy *sphy) -{ -	void __iomem *regs = sphy->regs; -	u32 phypwr; - -	phypwr = readl(regs + SAMSUNG_PHYPWR); - -	switch (sphy->drv_data->cpu_type) { -	case TYPE_S3C64XX: -		phypwr |= PHYPWR_NORMAL_MASK; -		break; -	case TYPE_EXYNOS4210: -		phypwr |= PHYPWR_NORMAL_MASK_PHY0; -	default: -		break; -	} - -	/* Disable analog and otg block power */ -	writel(phypwr, regs + SAMSUNG_PHYPWR); -} - -/* - * The function passed to the usb driver for phy initialization - */ -static int samsung_usbphy_init(struct usb_phy *phy) -{ -	struct samsung_usbphy *sphy; -	struct usb_bus *host = NULL; -	unsigned long flags; -	int ret = 0; - -	sphy = phy_to_sphy(phy); - -	host = phy->otg->host; - -	/* Enable the phy clock */ -	ret = clk_prepare_enable(sphy->clk); -	if (ret) { -		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); -		return ret; -	} - -	spin_lock_irqsave(&sphy->lock, flags); - -	if (host) { -		/* setting default phy-type for USB 2.0 */ -		if (!strstr(dev_name(host->controller), "ehci") || -				!strstr(dev_name(host->controller), "ohci")) -			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST); -	} else { -		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); -	} - -	/* Disable phy isolation */ -	if (sphy->plat && sphy->plat->pmu_isolation) -		sphy->plat->pmu_isolation(false); -	else -		samsung_usbphy_set_isolation(sphy, false); - -	/* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */ -	samsung_usbphy_cfg_sel(sphy); - -	/* Initialize usb phy registers */ -	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) -		samsung_exynos5_usbphy_enable(sphy); -	else -		samsung_usbphy_enable(sphy); - -	spin_unlock_irqrestore(&sphy->lock, flags); - -	/* Disable the phy clock */ -	clk_disable_unprepare(sphy->clk); - -	return ret; -} - -/* - * The function passed to the usb driver for phy shutdown - */ -static void samsung_usbphy_shutdown(struct usb_phy *phy) -{ -	struct samsung_usbphy *sphy; -	struct usb_bus *host = NULL; -	unsigned long flags; - -	sphy = phy_to_sphy(phy); - -	host = phy->otg->host; - -	if (clk_prepare_enable(sphy->clk)) { -		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); -		return; -	} - -	spin_lock_irqsave(&sphy->lock, flags); - -	if (host) { -		/* setting default phy-type for USB 2.0 */ -		if (!strstr(dev_name(host->controller), "ehci") || -				!strstr(dev_name(host->controller), "ohci")) -			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST); -	} else { -		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); -	} - -	/* De-initialize usb phy registers */ -	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) -		samsung_exynos5_usbphy_disable(sphy); -	else -		samsung_usbphy_disable(sphy); - -	/* Enable phy isolation */ -	if (sphy->plat && sphy->plat->pmu_isolation) -		sphy->plat->pmu_isolation(true); -	else -		samsung_usbphy_set_isolation(sphy, true); - -	spin_unlock_irqrestore(&sphy->lock, flags); - -	clk_disable_unprepare(sphy->clk); -} - -static const struct of_device_id samsung_usbphy_dt_match[]; - -static inline const struct samsung_usbphy_drvdata -*samsung_usbphy_get_driver_data(struct platform_device *pdev) -{ -	if (pdev->dev.of_node) { -		const struct of_device_id *match; -		match = of_match_node(samsung_usbphy_dt_match, -							pdev->dev.of_node); -		return match->data; -	} - -	return (struct samsung_usbphy_drvdata *) -				platform_get_device_id(pdev)->driver_data; -} - -static int samsung_usbphy_probe(struct platform_device *pdev) -{ -	struct samsung_usbphy *sphy; -	struct usb_otg *otg; -	struct samsung_usbphy_data *pdata = pdev->dev.platform_data; -	const struct samsung_usbphy_drvdata *drv_data; -	struct device *dev = &pdev->dev; -	struct resource *phy_mem; -	void __iomem	*phy_base; -	struct clk *clk; -	int ret; - -	phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!phy_mem) { -		dev_err(dev, "%s: missing mem resource\n", __func__); -		return -ENODEV; -	} - -	phy_base = devm_ioremap_resource(dev, phy_mem); -	if (IS_ERR(phy_base)) -		return PTR_ERR(phy_base); - -	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL); -	if (!sphy) -		return -ENOMEM; - -	otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL); -	if (!otg) -		return -ENOMEM; - -	drv_data = samsung_usbphy_get_driver_data(pdev); - -	if (drv_data->cpu_type == TYPE_EXYNOS5250) -		clk = devm_clk_get(dev, "usbhost"); -	else -		clk = devm_clk_get(dev, "otg"); - -	if (IS_ERR(clk)) { -		dev_err(dev, "Failed to get otg clock\n"); -		return PTR_ERR(clk); -	} - -	sphy->dev = dev; - -	if (dev->of_node) { -		ret = samsung_usbphy_parse_dt(sphy); -		if (ret < 0) -			return ret; -	} else { -		if (!pdata) { -			dev_err(dev, "no platform data specified\n"); -			return -EINVAL; -		} -	} - -	sphy->plat		= pdata; -	sphy->regs		= phy_base; -	sphy->clk		= clk; -	sphy->drv_data		= drv_data; -	sphy->phy.dev		= sphy->dev; -	sphy->phy.label		= "samsung-usbphy"; -	sphy->phy.init		= samsung_usbphy_init; -	sphy->phy.shutdown	= samsung_usbphy_shutdown; -	sphy->ref_clk_freq	= samsung_usbphy_get_refclk_freq(sphy); - -	sphy->phy.otg		= otg; -	sphy->phy.otg->phy	= &sphy->phy; -	sphy->phy.otg->set_host = samsung_usbphy_set_host; - -	spin_lock_init(&sphy->lock); - -	platform_set_drvdata(pdev, sphy); - -	return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2); -} - -static int samsung_usbphy_remove(struct platform_device *pdev) -{ -	struct samsung_usbphy *sphy = platform_get_drvdata(pdev); - -	usb_remove_phy(&sphy->phy); - -	if (sphy->pmuregs) -		iounmap(sphy->pmuregs); -	if (sphy->sysreg) -		iounmap(sphy->sysreg); - -	return 0; -} - -static const struct samsung_usbphy_drvdata usbphy_s3c64xx = { -	.cpu_type		= TYPE_S3C64XX, -	.devphy_en_mask		= S3C64XX_USBPHY_ENABLE, -}; - -static const struct samsung_usbphy_drvdata usbphy_exynos4 = { -	.cpu_type		= TYPE_EXYNOS4210, -	.devphy_en_mask		= EXYNOS_USBPHY_ENABLE, -	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE, -}; - -static struct samsung_usbphy_drvdata usbphy_exynos5 = { -	.cpu_type		= TYPE_EXYNOS5250, -	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE, -	.hostphy_reg_offset	= EXYNOS_USBHOST_PHY_CTRL_OFFSET, -}; - -#ifdef CONFIG_OF -static const struct of_device_id samsung_usbphy_dt_match[] = { -	{ -		.compatible = "samsung,s3c64xx-usbphy", -		.data = &usbphy_s3c64xx, -	}, { -		.compatible = "samsung,exynos4210-usbphy", -		.data = &usbphy_exynos4, -	}, { -		.compatible = "samsung,exynos5250-usbphy", -		.data = &usbphy_exynos5 -	}, -	{}, -}; -MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match); -#endif - -static struct platform_device_id samsung_usbphy_driver_ids[] = { -	{ -		.name		= "s3c64xx-usbphy", -		.driver_data	= (unsigned long)&usbphy_s3c64xx, -	}, { -		.name		= "exynos4210-usbphy", -		.driver_data	= (unsigned long)&usbphy_exynos4, -	}, { -		.name		= "exynos5250-usbphy", -		.driver_data	= (unsigned long)&usbphy_exynos5, -	}, -	{}, -}; - -MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids); - -static struct platform_driver samsung_usbphy_driver = { -	.probe		= samsung_usbphy_probe, -	.remove		= samsung_usbphy_remove, -	.id_table	= samsung_usbphy_driver_ids, -	.driver		= { -		.name	= "samsung-usbphy", -		.owner	= THIS_MODULE, -		.of_match_table = of_match_ptr(samsung_usbphy_dt_match), -	}, -}; - -module_platform_driver(samsung_usbphy_driver); - -MODULE_DESCRIPTION("Samsung USB phy controller"); -MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:samsung-usbphy"); diff --git a/drivers/usb/renesas_usbhs/Kconfig b/drivers/usb/renesas_usbhs/Kconfig index 29feb00d7f3..019bf7e49ee 100644 --- a/drivers/usb/renesas_usbhs/Kconfig +++ b/drivers/usb/renesas_usbhs/Kconfig @@ -4,7 +4,7 @@  config USB_RENESAS_USBHS  	tristate 'Renesas USBHS controller' -	depends on USB && USB_GADGET && GENERIC_HARDIRQS +	depends on USB_GADGET && GENERIC_HARDIRQS  	default n  	help  	  Renesas USBHS is a discrete USB host and peripheral controller chip diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 9538f0feafe..45b94019aec 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -32,7 +32,6 @@   */  void usbhs_pkt_init(struct usbhs_pkt *pkt)  { -	pkt->dma = DMA_ADDR_INVALID;  	INIT_LIST_HEAD(&pkt->node);  } diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h index c31731a843d..a168a1760fc 100644 --- a/drivers/usb/renesas_usbhs/fifo.h +++ b/drivers/usb/renesas_usbhs/fifo.h @@ -23,8 +23,6 @@  #include <asm/dma.h>  #include "pipe.h" -#define	DMA_ADDR_INVALID	(~(dma_addr_t)0) -  struct usbhs_fifo {  	char *name;  	u32 port;	/* xFIFO */ diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 78fca978b2d..ed4949faa70 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -230,7 +230,7 @@ static int usbhsg_recip_handler_std_clear_endpoint(struct usbhs_priv *priv,  	return 0;  } -struct usbhsg_recip_handle req_clear_feature = { +static struct usbhsg_recip_handle req_clear_feature = {  	.name		= "clear feature",  	.device		= usbhsg_recip_handler_std_control_done,  	.interface	= usbhsg_recip_handler_std_control_done, @@ -271,7 +271,7 @@ static int usbhsg_recip_handler_std_set_endpoint(struct usbhs_priv *priv,  	return 0;  } -struct usbhsg_recip_handle req_set_feature = { +static struct usbhsg_recip_handle req_set_feature = {  	.name		= "set feature",  	.device		= usbhsg_recip_handler_std_set_device,  	.interface	= usbhsg_recip_handler_std_control_done, @@ -372,7 +372,7 @@ static int usbhsg_recip_handler_std_get_endpoint(struct usbhs_priv *priv,  	return 0;  } -struct usbhsg_recip_handle req_get_status = { +static struct usbhsg_recip_handle req_get_status = {  	.name		= "get status",  	.device		= usbhsg_recip_handler_std_get_device,  	.interface	= usbhsg_recip_handler_std_get_interface, @@ -845,7 +845,6 @@ static int usbhsg_gadget_start(struct usb_gadget *gadget,  	/* first hook up the driver ... */  	gpriv->driver = driver; -	gpriv->gadget.dev.driver = &driver->driver;  	return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD);  } @@ -861,7 +860,6 @@ static int usbhsg_gadget_stop(struct usb_gadget *gadget,  		return -EINVAL;  	usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD); -	gpriv->gadget.dev.driver = NULL;  	gpriv->driver = NULL;  	return 0; @@ -925,11 +923,6 @@ static int usbhsg_stop(struct usbhs_priv *priv)  	return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);  } -static void usbhs_mod_gadget_release(struct device *pdev) -{ -	/* do nothing */ -} -  int usbhs_mod_gadget_probe(struct usbhs_priv *priv)  {  	struct usbhsg_gpriv *gpriv; @@ -976,15 +969,10 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)  	/*  	 * init gadget  	 */ -	dev_set_name(&gpriv->gadget.dev, "gadget");  	gpriv->gadget.dev.parent	= dev; -	gpriv->gadget.dev.release	= usbhs_mod_gadget_release;  	gpriv->gadget.name		= "renesas_usbhs_udc";  	gpriv->gadget.ops		= &usbhsg_gadget_ops;  	gpriv->gadget.max_speed		= USB_SPEED_HIGH; -	ret = device_register(&gpriv->gadget.dev); -	if (ret < 0) -		goto err_add_udc;  	INIT_LIST_HEAD(&gpriv->gadget.ep_list); @@ -1014,15 +1002,13 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)  	ret = usb_add_gadget_udc(dev, &gpriv->gadget);  	if (ret) -		goto err_register; +		goto err_add_udc;  	dev_info(dev, "gadget probed\n");  	return 0; -err_register: -	device_unregister(&gpriv->gadget.dev);  err_add_udc:  	kfree(gpriv->uep); @@ -1038,8 +1024,6 @@ void usbhs_mod_gadget_remove(struct usbhs_priv *priv)  	usb_del_gadget_udc(&gpriv->gadget); -	device_unregister(&gpriv->gadget.dev); -  	kfree(gpriv->uep);  	kfree(gpriv);  } diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 17b7f9ae36a..1d55762afbb 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -4,7 +4,7 @@  menuconfig USB_SERIAL  	tristate "USB Serial Converter support" -	depends on USB && TTY +	depends on TTY  	---help---  	  Say Y here if you have a USB device that provides normal serial  	  ports, or acts like a serial device, and you want to connect it to @@ -667,6 +667,23 @@ config USB_SERIAL_ZIO  	  To compile this driver as a module, choose M here: the  	  module will be called zio. +config USB_SERIAL_WISHBONE +	tristate "USB-Wishbone adapter interface driver" +	help +	  Say Y here if you want to use a USB attached Wishbone bus. + +	  Wishbone is an open hardware SoC bus commonly used in FPGA +	  designs. Bus access can be serialized using the Etherbone +	  protocol <http://www.ohwr.org/projects/etherbone-core>. + +	  This driver is intended to be used with devices which attach +	  their internal Wishbone bus to a USB serial interface using +	  the Etherbone protocol. A userspace library is required to +	  speak the protocol made available by this driver as ttyUSBx. + +	  To compile this driver as a module, choose M here: the +	  module will be called wishbone-serial. +  config USB_SERIAL_ZTE  	tristate "ZTE USB serial driver"  	help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index eaf5ca14dfe..cec63fa1910 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_USB_SERIAL_SYMBOL)			+= symbolserial.o  obj-$(CONFIG_USB_SERIAL_WWAN)			+= usb_wwan.o  obj-$(CONFIG_USB_SERIAL_TI)			+= ti_usb_3410_5052.o  obj-$(CONFIG_USB_SERIAL_VISOR)			+= visor.o +obj-$(CONFIG_USB_SERIAL_WISHBONE)		+= wishbone-serial.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 diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index cbd904b8fba..3b16118cbf6 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -62,8 +62,6 @@ static int is_irda(struct usb_serial *serial)  }  struct ark3116_private { -	wait_queue_head_t       delta_msr_wait; -	struct async_icount	icount;  	int			irda;	/* 1 for irda device */  	/* protects hw register updates */ @@ -146,7 +144,6 @@ static int ark3116_port_probe(struct usb_serial_port *port)  	if (!priv)  		return -ENOMEM; -	init_waitqueue_head(&priv->delta_msr_wait);  	mutex_init(&priv->hw_lock);  	spin_lock_init(&priv->status_lock); @@ -343,18 +340,15 @@ static void ark3116_close(struct usb_serial_port *port)  {  	struct usb_serial *serial = port->serial; -	if (serial->dev) { -		/* disable DMA */ -		ark3116_write_reg(serial, UART_FCR, 0); - -		/* deactivate interrupts */ -		ark3116_write_reg(serial, UART_IER, 0); +	/* disable DMA */ +	ark3116_write_reg(serial, UART_FCR, 0); -		usb_serial_generic_close(port); -		if (serial->num_interrupt_in) -			usb_kill_urb(port->interrupt_in_urb); -	} +	/* deactivate interrupts */ +	ark3116_write_reg(serial, UART_IER, 0); +	usb_serial_generic_close(port); +	if (serial->num_interrupt_in) +		usb_kill_urb(port->interrupt_in_urb);  }  static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -407,31 +401,10 @@ err_out:  	return result;  } -static int ark3116_get_icount(struct tty_struct *tty, -					struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct ark3116_private *priv = usb_get_serial_port_data(port); -	struct async_icount cnow = priv->icount; -	icount->cts = cnow.cts; -	icount->dsr = cnow.dsr; -	icount->rng = cnow.rng; -	icount->dcd = cnow.dcd; -	icount->rx = cnow.rx; -	icount->tx = cnow.tx; -	icount->frame = cnow.frame; -	icount->overrun = cnow.overrun; -	icount->parity = cnow.parity; -	icount->brk = cnow.brk; -	icount->buf_overrun = cnow.buf_overrun; -	return 0; -} -  static int ark3116_ioctl(struct tty_struct *tty,  			 unsigned int cmd, unsigned long arg)  {  	struct usb_serial_port *port = tty->driver_data; -	struct ark3116_private *priv = usb_get_serial_port_data(port);  	struct serial_struct serstruct;  	void __user *user_arg = (void __user *)arg; @@ -453,29 +426,6 @@ static int ark3116_ioctl(struct tty_struct *tty,  		if (copy_from_user(&serstruct, user_arg, sizeof(serstruct)))  			return -EFAULT;  		return 0; -	case TIOCMIWAIT: -		for (;;) { -			struct async_icount prev = priv->icount; -			interruptible_sleep_on(&priv->delta_msr_wait); -			/* see if a signal did it */ -			if (signal_pending(current)) -				return -ERESTARTSYS; -			if ((prev.rng == priv->icount.rng) && -			    (prev.dsr == priv->icount.dsr) && -			    (prev.dcd == priv->icount.dcd) && -			    (prev.cts == priv->icount.cts)) -				return -EIO; -			if ((arg & TIOCM_RNG && -			     (prev.rng != priv->icount.rng)) || -			    (arg & TIOCM_DSR && -			     (prev.dsr != priv->icount.dsr)) || -			    (arg & TIOCM_CD  && -			     (prev.dcd != priv->icount.dcd)) || -			    (arg & TIOCM_CTS && -			     (prev.cts != priv->icount.cts))) -				return 0; -		} -		break;  	}  	return -ENOIOCTLCMD; @@ -573,14 +523,14 @@ static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr)  	if (msr & UART_MSR_ANY_DELTA) {  		/* update input line counters */  		if (msr & UART_MSR_DCTS) -			priv->icount.cts++; +			port->icount.cts++;  		if (msr & UART_MSR_DDSR) -			priv->icount.dsr++; +			port->icount.dsr++;  		if (msr & UART_MSR_DDCD) -			priv->icount.dcd++; +			port->icount.dcd++;  		if (msr & UART_MSR_TERI) -			priv->icount.rng++; -		wake_up_interruptible(&priv->delta_msr_wait); +			port->icount.rng++; +		wake_up_interruptible(&port->port.delta_msr_wait);  	}  } @@ -596,13 +546,13 @@ static void ark3116_update_lsr(struct usb_serial_port *port, __u8 lsr)  	if (lsr&UART_LSR_BRK_ERROR_BITS) {  		if (lsr & UART_LSR_BI) -			priv->icount.brk++; +			port->icount.brk++;  		if (lsr & UART_LSR_FE) -			priv->icount.frame++; +			port->icount.frame++;  		if (lsr & UART_LSR_PE) -			priv->icount.parity++; +			port->icount.parity++;  		if (lsr & UART_LSR_OE) -			priv->icount.overrun++; +			port->icount.overrun++;  	}  } @@ -720,7 +670,8 @@ static struct usb_serial_driver ark3116_device = {  	.ioctl =		ark3116_ioctl,  	.tiocmget =		ark3116_tiocmget,  	.tiocmset =		ark3116_tiocmset, -	.get_icount =		ark3116_get_icount, +	.tiocmiwait =		usb_serial_generic_tiocmiwait, +	.get_icount =		usb_serial_generic_get_icount,  	.open =			ark3116_open,  	.close =		ark3116_close,  	.break_ctl = 		ark3116_break_ctl, diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 37decb13d7e..3c4db6d196c 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -106,14 +106,15 @@ static int usb_serial_device_remove(struct device *dev)  	/* make sure suspend/resume doesn't race against port_remove */  	usb_autopm_get_interface(port->serial->interface); +	minor = port->number; +	tty_unregister_device(usb_serial_tty_driver, minor); +  	device_remove_file(&port->dev, &dev_attr_port_number);  	driver = port->serial->type;  	if (driver->port_remove)  		retval = driver->port_remove(port); -	minor = port->number; -	tty_unregister_device(usb_serial_tty_driver, minor);  	dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",  		 driver->description, minor); diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index d255f66e708..c2a4171ab9c 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -80,7 +80,6 @@ MODULE_DEVICE_TABLE(usb, id_table);  struct ch341_private {  	spinlock_t lock; /* access lock */ -	wait_queue_head_t delta_msr_wait; /* wait queue for modem status */  	unsigned baud_rate; /* set baud rate */  	u8 line_control; /* set line control value RTS/DTR */  	u8 line_status; /* active status of modem control inputs */ @@ -252,7 +251,6 @@ static int ch341_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->delta_msr_wait);  	priv->baud_rate = DEFAULT_BAUD_RATE;  	priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; @@ -298,7 +296,6 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on)  		priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);  	spin_unlock_irqrestore(&priv->lock, flags);  	ch341_set_handshake(port->serial->dev, priv->line_control); -	wake_up_interruptible(&priv->delta_msr_wait);  }  static void ch341_close(struct usb_serial_port *port) @@ -491,7 +488,7 @@ static void ch341_read_int_callback(struct urb *urb)  			tty_kref_put(tty);  		} -		wake_up_interruptible(&priv->delta_msr_wait); +		wake_up_interruptible(&port->port.delta_msr_wait);  	}  exit: @@ -502,8 +499,9 @@ exit:  			__func__, status);  } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +static int ch341_tiocmiwait(struct tty_struct *tty, unsigned long arg)  { +	struct usb_serial_port *port = tty->driver_data;  	struct ch341_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	u8 prevstatus; @@ -517,11 +515,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	spin_unlock_irqrestore(&priv->lock, flags);  	while (!multi_change) { -		interruptible_sleep_on(&priv->delta_msr_wait); +		interruptible_sleep_on(&port->port.delta_msr_wait);  		/* see if a signal did it */  		if (signal_pending(current))  			return -ERESTARTSYS; +		if (port->serial->disconnected) +			return -EIO; +  		spin_lock_irqsave(&priv->lock, flags);  		status = priv->line_status;  		multi_change = priv->multi_status_change; @@ -541,26 +542,6 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	return 0;  } -static int ch341_ioctl(struct tty_struct *tty, -			unsigned int cmd, unsigned long arg) -{ -	struct usb_serial_port *port = tty->driver_data; - -	dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__, port->number, cmd); - -	switch (cmd) { -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,  port->number); -		return wait_modem_info(port, arg); - -	default: -		dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd); -		break; -	} - -	return -ENOIOCTLCMD; -} -  static int ch341_tiocmget(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; @@ -610,11 +591,11 @@ static struct usb_serial_driver ch341_device = {  	.dtr_rts	   = ch341_dtr_rts,  	.carrier_raised	   = ch341_carrier_raised,  	.close             = ch341_close, -	.ioctl             = ch341_ioctl,  	.set_termios       = ch341_set_termios,  	.break_ctl         = ch341_break_ctl,  	.tiocmget          = ch341_tiocmget,  	.tiocmset          = ch341_tiocmset, +	.tiocmiwait        = ch341_tiocmiwait,  	.read_int_callback = ch341_read_int_callback,  	.port_probe        = ch341_port_probe,  	.port_remove       = ch341_port_remove, diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 4747d1c328f..2c659553c07 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -462,11 +462,7 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)  static void cp210x_close(struct usb_serial_port *port)  {  	usb_serial_generic_close(port); - -	mutex_lock(&port->serial->disc_mutex); -	if (!port->serial->disconnected) -		cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE); -	mutex_unlock(&port->serial->disc_mutex); +	cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE);  }  /* diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 629bd289450..781426230d6 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -51,7 +51,6 @@  #define CYBERJACK_PRODUCT_ID	0x0100  /* Function prototypes */ -static void cyberjack_disconnect(struct usb_serial *serial);  static int cyberjack_port_probe(struct usb_serial_port *port);  static int cyberjack_port_remove(struct usb_serial_port *port);  static int  cyberjack_open(struct tty_struct *tty, @@ -79,7 +78,6 @@ static struct usb_serial_driver cyberjack_device = {  	.description =		"Reiner SCT Cyberjack USB card reader",  	.id_table =		id_table,  	.num_ports =		1, -	.disconnect =		cyberjack_disconnect,  	.port_probe =		cyberjack_port_probe,  	.port_remove =		cyberjack_port_remove,  	.open =			cyberjack_open, @@ -130,20 +128,14 @@ static int cyberjack_port_remove(struct usb_serial_port *port)  {  	struct cyberjack_private *priv; +	usb_kill_urb(port->interrupt_in_urb); +  	priv = usb_get_serial_port_data(port);  	kfree(priv);  	return 0;  } -static void cyberjack_disconnect(struct usb_serial *serial) -{ -	int i; - -	for (i = 0; i < serial->num_ports; ++i) -		usb_kill_urb(serial->port[i]->interrupt_in_urb); -} -  static int  cyberjack_open(struct tty_struct *tty,  					struct usb_serial_port *port)  { @@ -166,11 +158,8 @@ static int  cyberjack_open(struct tty_struct *tty,  static void cyberjack_close(struct usb_serial_port *port)  { -	if (port->serial->dev) { -		/* shutdown any bulk reads that might be going on */ -		usb_kill_urb(port->write_urb); -		usb_kill_urb(port->read_urb); -	} +	usb_kill_urb(port->write_urb); +	usb_kill_urb(port->read_urb);  }  static int cyberjack_write(struct tty_struct *tty, diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 8efa19d0e9f..d341555d37d 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -111,7 +111,6 @@ struct cypress_private {  	int baud_rate;			   /* stores current baud rate in  					      integer form */  	int isthrottled;		   /* if throttled, discard reads */ -	wait_queue_head_t delta_msr_wait;  /* used for TIOCMIWAIT */  	char prev_status, diff_status;	   /* used for TIOCMIWAIT */  	/* we pass a pointer to this as the argument sent to  	   cypress_set_termios old_termios */ @@ -130,13 +129,12 @@ static int  cypress_write(struct tty_struct *tty, struct usb_serial_port *port,  			const unsigned char *buf, int count);  static void cypress_send(struct usb_serial_port *port);  static int  cypress_write_room(struct tty_struct *tty); -static int  cypress_ioctl(struct tty_struct *tty, -			unsigned int cmd, unsigned long arg);  static void cypress_set_termios(struct tty_struct *tty,  			struct usb_serial_port *port, struct ktermios *old);  static int  cypress_tiocmget(struct tty_struct *tty);  static int  cypress_tiocmset(struct tty_struct *tty,  			unsigned int set, unsigned int clear); +static int  cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg);  static int  cypress_chars_in_buffer(struct tty_struct *tty);  static void cypress_throttle(struct tty_struct *tty);  static void cypress_unthrottle(struct tty_struct *tty); @@ -159,10 +157,10 @@ static struct usb_serial_driver cypress_earthmate_device = {  	.dtr_rts =			cypress_dtr_rts,  	.write =			cypress_write,  	.write_room =			cypress_write_room, -	.ioctl =			cypress_ioctl,  	.set_termios =			cypress_set_termios,  	.tiocmget =			cypress_tiocmget,  	.tiocmset =			cypress_tiocmset, +	.tiocmiwait =			cypress_tiocmiwait,  	.chars_in_buffer =		cypress_chars_in_buffer,  	.throttle =		 	cypress_throttle,  	.unthrottle =			cypress_unthrottle, @@ -185,10 +183,10 @@ static struct usb_serial_driver cypress_hidcom_device = {  	.dtr_rts =			cypress_dtr_rts,  	.write =			cypress_write,  	.write_room =			cypress_write_room, -	.ioctl =			cypress_ioctl,  	.set_termios =			cypress_set_termios,  	.tiocmget =			cypress_tiocmget,  	.tiocmset =			cypress_tiocmset, +	.tiocmiwait =			cypress_tiocmiwait,  	.chars_in_buffer =		cypress_chars_in_buffer,  	.throttle =			cypress_throttle,  	.unthrottle =			cypress_unthrottle, @@ -211,10 +209,10 @@ static struct usb_serial_driver cypress_ca42v2_device = {  	.dtr_rts =			cypress_dtr_rts,  	.write =			cypress_write,  	.write_room =			cypress_write_room, -	.ioctl =			cypress_ioctl,  	.set_termios =			cypress_set_termios,  	.tiocmget =			cypress_tiocmget,  	.tiocmset =			cypress_tiocmset, +	.tiocmiwait =			cypress_tiocmiwait,  	.chars_in_buffer =		cypress_chars_in_buffer,  	.throttle =			cypress_throttle,  	.unthrottle =			cypress_unthrottle, @@ -449,7 +447,6 @@ static int cypress_generic_port_probe(struct usb_serial_port *port)  		kfree(priv);  		return -ENOMEM;  	} -	init_waitqueue_head(&priv->delta_msr_wait);  	usb_reset_configuration(serial->dev); @@ -635,12 +632,6 @@ static void cypress_close(struct usb_serial_port *port)  	struct cypress_private *priv = usb_get_serial_port_data(port);  	unsigned long flags; -	/* writing is potentially harmful, lock must be taken */ -	mutex_lock(&port->serial->disc_mutex); -	if (port->serial->disconnected) { -		mutex_unlock(&port->serial->disc_mutex); -		return; -	}  	spin_lock_irqsave(&priv->lock, flags);  	kfifo_reset_out(&priv->write_fifo);  	spin_unlock_irqrestore(&priv->lock, flags); @@ -652,7 +643,6 @@ static void cypress_close(struct usb_serial_port *port)  	if (stats)  		dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",  			priv->bytes_in, priv->bytes_out, priv->cmd_count); -	mutex_unlock(&port->serial->disc_mutex);  } /* cypress_close */ @@ -857,51 +847,43 @@ static int cypress_tiocmset(struct tty_struct *tty,  } -static int cypress_ioctl(struct tty_struct *tty, -					unsigned int cmd, unsigned long arg) +static int cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg)  {  	struct usb_serial_port *port = tty->driver_data;  	struct cypress_private *priv = usb_get_serial_port_data(port); +	char diff; -	dev_dbg(&port->dev, "%s - port %d, cmd 0x%.4x\n", __func__, port->number, cmd); +	for (;;) { +		interruptible_sleep_on(&port->port.delta_msr_wait); +		/* see if a signal did it */ +		if (signal_pending(current)) +			return -ERESTARTSYS; -	switch (cmd) { -	/* This code comes from drivers/char/serial.c and ftdi_sio.c */ -	case TIOCMIWAIT: -		while (priv != NULL) { -			interruptible_sleep_on(&priv->delta_msr_wait); -			/* see if a signal did it */ -			if (signal_pending(current)) -				return -ERESTARTSYS; -			else { -				char diff = priv->diff_status; -				if (diff == 0) -					return -EIO; /* no change => error */ +		if (port->serial->disconnected) +			return -EIO; -				/* consume all events */ -				priv->diff_status = 0; +		diff = priv->diff_status; +		if (diff == 0) +			return -EIO; /* no change => error */ -				/* return 0 if caller wanted to know about -				   these bits */ -				if (((arg & TIOCM_RNG) && (diff & UART_RI)) || -				    ((arg & TIOCM_DSR) && (diff & UART_DSR)) || -				    ((arg & TIOCM_CD) && (diff & UART_CD)) || -				    ((arg & TIOCM_CTS) && (diff & UART_CTS))) -					return 0; -				/* otherwise caller can't care less about what -				 * happened, and so we continue to wait for -				 * more events. -				 */ -			} -		} -		return 0; -	default: -		break; +		/* consume all events */ +		priv->diff_status = 0; + +		/* return 0 if caller wanted to know about +		   these bits */ +		if (((arg & TIOCM_RNG) && (diff & UART_RI))  || +			((arg & TIOCM_DSR) && (diff & UART_DSR)) || +			((arg & TIOCM_CD)  && (diff & UART_CD))  || +			((arg & TIOCM_CTS) && (diff & UART_CTS))) +			return 0; +		/* otherwise caller can't care less about what +		 * happened, and so we continue to wait for +		 * more events. +		 */  	} -	dev_dbg(&port->dev, "%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h\n", __func__, cmd); -	return -ENOIOCTLCMD; -} /* cypress_ioctl */ +	return 0; +}  static void cypress_set_termios(struct tty_struct *tty,  	struct usb_serial_port *port, struct ktermios *old_termios) @@ -1187,7 +1169,7 @@ static void cypress_read_int_callback(struct urb *urb)  	if (priv->current_status != priv->prev_status) {  		priv->diff_status |= priv->current_status ^  			priv->prev_status; -		wake_up_interruptible(&priv->delta_msr_wait); +		wake_up_interruptible(&port->port.delta_msr_wait);  		priv->prev_status = priv->current_status;  	}  	spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index ebe45fa0ed5..7b807d38952 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -196,7 +196,6 @@ struct digi_port {  	unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE];  	int dp_write_urb_in_use;  	unsigned int dp_modem_signals; -	wait_queue_head_t dp_modem_change_wait;  	int dp_transmit_idle;  	wait_queue_head_t dp_transmit_idle_wait;  	int dp_throttled; @@ -210,7 +209,6 @@ struct digi_port {  /* Local Function Declarations */ -static void digi_wakeup_write(struct usb_serial_port *port);  static void digi_wakeup_write_lock(struct work_struct *work);  static int digi_write_oob_command(struct usb_serial_port *port,  	unsigned char *buf, int count, int interruptible); @@ -374,20 +372,10 @@ static void digi_wakeup_write_lock(struct work_struct *work)  	unsigned long flags;  	spin_lock_irqsave(&priv->dp_port_lock, flags); -	digi_wakeup_write(port); +	tty_port_tty_wakeup(&port->port);  	spin_unlock_irqrestore(&priv->dp_port_lock, flags);  } -static void digi_wakeup_write(struct usb_serial_port *port) -{ -	struct tty_struct *tty = tty_port_tty_get(&port->port); -	if (tty) { -		tty_wakeup(tty); -		tty_kref_put(tty); -	} -} - -  /*   *  Digi Write OOB Command   * @@ -1044,7 +1032,7 @@ static void digi_write_bulk_callback(struct urb *urb)  		}  	}  	/* wake up processes sleeping on writes immediately */ -	digi_wakeup_write(port); +	tty_port_tty_wakeup(&port->port);  	/* also queue up a wakeup at scheduler time, in case we */  	/* lost the race in write_chan(). */  	schedule_work(&priv->dp_wakeup_work); @@ -1149,53 +1137,51 @@ static void digi_close(struct usb_serial_port *port)  	if (port->serial->disconnected)  		goto exit; -	if (port->serial->dev) { -		/* FIXME: Transmit idle belongs in the wait_unti_sent path */ -		digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT); - -		/* disable input flow control */ -		buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; -		buf[1] = priv->dp_port_num; -		buf[2] = DIGI_DISABLE; -		buf[3] = 0; +	/* FIXME: Transmit idle belongs in the wait_unti_sent path */ +	digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT); -		/* disable output flow control */ -		buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL; -		buf[5] = priv->dp_port_num; -		buf[6] = DIGI_DISABLE; -		buf[7] = 0; +	/* disable input flow control */ +	buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; +	buf[1] = priv->dp_port_num; +	buf[2] = DIGI_DISABLE; +	buf[3] = 0; -		/* disable reading modem signals automatically */ -		buf[8] = DIGI_CMD_READ_INPUT_SIGNALS; -		buf[9] = priv->dp_port_num; -		buf[10] = DIGI_DISABLE; -		buf[11] = 0; +	/* disable output flow control */ +	buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL; +	buf[5] = priv->dp_port_num; +	buf[6] = DIGI_DISABLE; +	buf[7] = 0; -		/* disable receive */ -		buf[12] = DIGI_CMD_RECEIVE_ENABLE; -		buf[13] = priv->dp_port_num; -		buf[14] = DIGI_DISABLE; -		buf[15] = 0; +	/* disable reading modem signals automatically */ +	buf[8] = DIGI_CMD_READ_INPUT_SIGNALS; +	buf[9] = priv->dp_port_num; +	buf[10] = DIGI_DISABLE; +	buf[11] = 0; -		/* flush fifos */ -		buf[16] = DIGI_CMD_IFLUSH_FIFO; -		buf[17] = priv->dp_port_num; -		buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; -		buf[19] = 0; +	/* disable receive */ +	buf[12] = DIGI_CMD_RECEIVE_ENABLE; +	buf[13] = priv->dp_port_num; +	buf[14] = DIGI_DISABLE; +	buf[15] = 0; -		ret = digi_write_oob_command(port, buf, 20, 0); -		if (ret != 0) -			dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n", ret); +	/* flush fifos */ +	buf[16] = DIGI_CMD_IFLUSH_FIFO; +	buf[17] = priv->dp_port_num; +	buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; +	buf[19] = 0; -		/* wait for final commands on oob port to complete */ -		prepare_to_wait(&priv->dp_flush_wait, &wait, -							TASK_INTERRUPTIBLE); -		schedule_timeout(DIGI_CLOSE_TIMEOUT); -		finish_wait(&priv->dp_flush_wait, &wait); +	ret = digi_write_oob_command(port, buf, 20, 0); +	if (ret != 0) +		dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n", +									ret); +	/* wait for final commands on oob port to complete */ +	prepare_to_wait(&priv->dp_flush_wait, &wait, +			TASK_INTERRUPTIBLE); +	schedule_timeout(DIGI_CLOSE_TIMEOUT); +	finish_wait(&priv->dp_flush_wait, &wait); -		/* shutdown any outstanding bulk writes */ -		usb_kill_urb(port->write_urb); -	} +	/* shutdown any outstanding bulk writes */ +	usb_kill_urb(port->write_urb);  exit:  	spin_lock_irq(&priv->dp_port_lock);  	priv->dp_write_urb_in_use = 0; @@ -1252,7 +1238,6 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num)  	spin_lock_init(&priv->dp_port_lock);  	priv->dp_port_num = port_num; -	init_waitqueue_head(&priv->dp_modem_change_wait);  	init_waitqueue_head(&priv->dp_transmit_idle_wait);  	init_waitqueue_head(&priv->dp_flush_wait);  	init_waitqueue_head(&priv->dp_close_wait); @@ -1522,7 +1507,7 @@ static int digi_read_oob_callback(struct urb *urb)  				/* port must be open to use tty struct */  				if (rts) {  					tty->hw_stopped = 0; -					digi_wakeup_write(port); +					tty_port_tty_wakeup(&port->port);  				}  			} else {  				priv->dp_modem_signals &= ~TIOCM_CTS; @@ -1543,7 +1528,6 @@ static int digi_read_oob_callback(struct urb *urb)  			else  				priv->dp_modem_signals &= ~TIOCM_CD; -			wake_up_interruptible(&priv->dp_modem_change_wait);  			spin_unlock(&priv->dp_port_lock);  		} else if (opcode == DIGI_CMD_TRANSMIT_IDLE) {  			spin_lock(&priv->dp_port_lock); diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index b1b2dc64b50..090b411d893 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -47,7 +47,6 @@ MODULE_DEVICE_TABLE(usb, id_table);  struct f81232_private {  	spinlock_t lock; -	wait_queue_head_t delta_msr_wait;  	u8 line_control;  	u8 line_status;  }; @@ -111,7 +110,7 @@ static void f81232_process_read_urb(struct urb *urb)  	line_status = priv->line_status;  	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;  	spin_unlock_irqrestore(&priv->lock, flags); -	wake_up_interruptible(&priv->delta_msr_wait); +	wake_up_interruptible(&port->port.delta_msr_wait);  	if (!urb->actual_length)  		return; @@ -243,8 +242,9 @@ static int f81232_carrier_raised(struct usb_serial_port *port)  	return 0;  } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +static int f81232_tiocmiwait(struct tty_struct *tty, unsigned long arg)  { +	struct usb_serial_port *port = tty->driver_data;  	struct f81232_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	unsigned int prevstatus; @@ -256,11 +256,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	spin_unlock_irqrestore(&priv->lock, flags);  	while (1) { -		interruptible_sleep_on(&priv->delta_msr_wait); +		interruptible_sleep_on(&port->port.delta_msr_wait);  		/* see if a signal did it */  		if (signal_pending(current))  			return -ERESTARTSYS; +		if (port->serial->disconnected) +			return -EIO; +  		spin_lock_irqsave(&priv->lock, flags);  		status = priv->line_status;  		spin_unlock_irqrestore(&priv->lock, flags); @@ -300,11 +303,6 @@ static int f81232_ioctl(struct tty_struct *tty,  			return -EFAULT;  		return 0; - -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, -			port->number); -		return wait_modem_info(port, arg);  	default:  		dev_dbg(&port->dev, "%s not supported = 0x%04x\n",  			__func__, cmd); @@ -322,7 +320,6 @@ static int f81232_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->delta_msr_wait);  	usb_set_serial_port_data(port, priv); @@ -357,6 +354,7 @@ static struct usb_serial_driver f81232_device = {  	.set_termios =		f81232_set_termios,  	.tiocmget =		f81232_tiocmget,  	.tiocmset =		f81232_tiocmset, +	.tiocmiwait =		f81232_tiocmiwait,  	.process_read_urb =	f81232_process_read_urb,  	.read_int_callback =	f81232_read_int_callback,  	.port_probe =		f81232_port_probe, diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index edd162df49c..242b5776648 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1,7 +1,7 @@  /*   * USB FTDI SIO driver   * - *	Copyright (C) 2009 - 2010 + *	Copyright (C) 2009 - 2013   *	    Johan Hovold (jhovold@gmail.com)   *	Copyright (C) 1999 - 2001   *	    Greg Kroah-Hartman (greg@kroah.com) @@ -55,7 +55,6 @@ static __u16 vendor = FTDI_VID;  static __u16 product;  struct ftdi_private { -	struct kref kref;  	enum ftdi_chip_type chip_type;  				/* type of device, either SIO or FT8U232AM */  	int baud_base;		/* baud base clock for divisor setting */ @@ -68,10 +67,7 @@ struct ftdi_private {  				 */  	int flags;		/* some ASYNC_xxxx flags are supported */  	unsigned long last_dtr_rts;	/* saved modem control outputs */ -	struct async_icount	icount; -	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */  	char prev_status;        /* Used for TIOCMIWAIT */ -	bool dev_gone;        /* Used to abort TIOCMIWAIT */  	char transmit_empty;	/* If transmitter is empty or not */  	__u16 interface;	/* FT2232C, FT2232H or FT4232H port interface  				   (0 for FT232/245) */ @@ -191,6 +187,7 @@ static struct usb_device_id id_table_combined [] = {  	{ 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(FTDI_VID, FTDI_OPENDCC_GBM_BOOST_PID) },  	{ USB_DEVICE(NEWPORT_VID, NEWPORT_AGILIS_PID) },  	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },  	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, @@ -642,6 +639,7 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },  	{ USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) },  	{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) }, +	{ USB_DEVICE(MITSUBISHI_VID, MITSUBISHI_FXUSB_PID) },  	{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },  	{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },  	{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, @@ -871,7 +869,9 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },  	{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),  		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, -	{ USB_DEVICE(ST_VID, ST_STMCLT1030_PID), +	{ USB_DEVICE(ST_VID, ST_STMCLT_2232_PID), +		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, +	{ USB_DEVICE(ST_VID, ST_STMCLT_4232_PID),  		.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },  	{ USB_DEVICE(FTDI_VID, FTDI_RF_R106) },  	{ USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), @@ -912,7 +912,6 @@ static int  ftdi_sio_probe(struct usb_serial *serial,  static int  ftdi_sio_port_probe(struct usb_serial_port *port);  static int  ftdi_sio_port_remove(struct usb_serial_port *port);  static int  ftdi_open(struct tty_struct *tty, struct usb_serial_port *port); -static void ftdi_close(struct usb_serial_port *port);  static void ftdi_dtr_rts(struct usb_serial_port *port, int on);  static void ftdi_process_read_urb(struct urb *urb);  static int ftdi_prepare_write_buffer(struct usb_serial_port *port, @@ -922,8 +921,6 @@ static void ftdi_set_termios(struct tty_struct *tty,  static int  ftdi_tiocmget(struct tty_struct *tty);  static int  ftdi_tiocmset(struct tty_struct *tty,  			unsigned int set, unsigned int clear); -static int ftdi_get_icount(struct tty_struct *tty, -			   struct serial_icounter_struct *icount);  static int  ftdi_ioctl(struct tty_struct *tty,  			unsigned int cmd, unsigned long arg);  static void ftdi_break_ctl(struct tty_struct *tty, int break_state); @@ -952,7 +949,6 @@ static struct usb_serial_driver ftdi_sio_device = {  	.port_probe =		ftdi_sio_port_probe,  	.port_remove =		ftdi_sio_port_remove,  	.open =			ftdi_open, -	.close =		ftdi_close,  	.dtr_rts =		ftdi_dtr_rts,  	.throttle =		usb_serial_generic_throttle,  	.unthrottle =		usb_serial_generic_unthrottle, @@ -960,7 +956,8 @@ static struct usb_serial_driver ftdi_sio_device = {  	.prepare_write_buffer =	ftdi_prepare_write_buffer,  	.tiocmget =		ftdi_tiocmget,  	.tiocmset =		ftdi_tiocmset, -	.get_icount =           ftdi_get_icount, +	.tiocmiwait =		usb_serial_generic_tiocmiwait, +	.get_icount =           usb_serial_generic_get_icount,  	.ioctl =		ftdi_ioctl,  	.set_termios =		ftdi_set_termios,  	.break_ctl =		ftdi_break_ctl, @@ -1689,12 +1686,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	} -	kref_init(&priv->kref);  	mutex_init(&priv->cfg_lock); -	init_waitqueue_head(&priv->delta_msr_wait);  	priv->flags = ASYNC_LOW_LATENCY; -	priv->dev_gone = false;  	if (quirk && quirk->port_probe)  		quirk->port_probe(priv); @@ -1795,20 +1789,24 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)  }  /* - * First and second port on STMCLiteadaptors is reserved for JTAG interface - * and the forth port for pio + * First two ports on JTAG adaptors using an FT4232 such as STMicroelectronics's + * ST Micro Connect Lite are reserved for JTAG or other non-UART interfaces and + * can be accessed from userspace. + * The next two ports are enabled as UARTs by default, where port 2 is + * a conventional RS-232 UART.   */  static int ftdi_stmclite_probe(struct usb_serial *serial)  {  	struct usb_device *udev = serial->dev;  	struct usb_interface *interface = serial->interface; -	if (interface == udev->actconfig->interface[2]) -		return 0; - -	dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n"); +	if (interface == udev->actconfig->interface[0] || +	    interface == udev->actconfig->interface[1]) { +		dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n"); +		return -ENODEV; +	} -	return -ENODEV; +	return 0;  }  /* @@ -1829,23 +1827,13 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)  	return 0;  } -static void ftdi_sio_priv_release(struct kref *k) -{ -	struct ftdi_private *priv = container_of(k, struct ftdi_private, kref); - -	kfree(priv); -} -  static int ftdi_sio_port_remove(struct usb_serial_port *port)  {  	struct ftdi_private *priv = usb_get_serial_port_data(port); -	priv->dev_gone = true; -	wake_up_interruptible_all(&priv->delta_msr_wait); -  	remove_sysfs_attrs(port); -	kref_put(&priv->kref, ftdi_sio_priv_release); +	kfree(priv);  	return 0;  } @@ -1855,7 +1843,6 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)  	struct ktermios dummy;  	struct usb_device *dev = port->serial->dev;  	struct ftdi_private *priv = usb_get_serial_port_data(port); -	int result;  	/* No error checking for this (will get errors later anyway) */  	/* See ftdi_sio.h for description of what is reset */ @@ -1874,12 +1861,7 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)  		ftdi_set_termios(tty, port, &dummy);  	} -	/* Start reading from the device */ -	result = usb_serial_generic_open(tty, port); -	if (!result) -		kref_get(&priv->kref); - -	return result; +	return usb_serial_generic_open(tty, port);  }  static void ftdi_dtr_rts(struct usb_serial_port *port, int on) @@ -1904,19 +1886,6 @@ static void ftdi_dtr_rts(struct usb_serial_port *port, int on)  		clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);  } -/* - * usbserial:__serial_close  only calls ftdi_close if the point is open - * - *   This only gets called when it is the last close - */ -static void ftdi_close(struct usb_serial_port *port) -{ -	struct ftdi_private *priv = usb_get_serial_port_data(port); - -	usb_serial_generic_close(port); -	kref_put(&priv->kref, ftdi_sio_priv_release); -} -  /* The SIO requires the first byte to have:   *  B0 1   *  B1 0 @@ -1944,7 +1913,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,  			c = kfifo_out(&port->write_fifo, &buffer[i + 1], len);  			if (!c)  				break; -			priv->icount.tx += c; +			port->icount.tx += c;  			buffer[i] = (c << 2) + 1;  			count += c + 1;  		} @@ -1952,7 +1921,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,  	} else {  		count = kfifo_out_locked(&port->write_fifo, dest, size,  								&port->lock); -		priv->icount.tx += count; +		port->icount.tx += count;  	}  	return count; @@ -1981,15 +1950,15 @@ static int ftdi_process_packet(struct usb_serial_port *port,  		char diff_status = status ^ priv->prev_status;  		if (diff_status & FTDI_RS0_CTS) -			priv->icount.cts++; +			port->icount.cts++;  		if (diff_status & FTDI_RS0_DSR) -			priv->icount.dsr++; +			port->icount.dsr++;  		if (diff_status & FTDI_RS0_RI) -			priv->icount.rng++; +			port->icount.rng++;  		if (diff_status & FTDI_RS0_RLSD) -			priv->icount.dcd++; +			port->icount.dcd++; -		wake_up_interruptible_all(&priv->delta_msr_wait); +		wake_up_interruptible(&port->port.delta_msr_wait);  		priv->prev_status = status;  	} @@ -1999,18 +1968,18 @@ static int ftdi_process_packet(struct usb_serial_port *port,  		 * over framing errors */  		if (packet[1] & FTDI_RS_BI) {  			flag = TTY_BREAK; -			priv->icount.brk++; +			port->icount.brk++;  			usb_serial_handle_break(port);  		} else if (packet[1] & FTDI_RS_PE) {  			flag = TTY_PARITY; -			priv->icount.parity++; +			port->icount.parity++;  		} else if (packet[1] & FTDI_RS_FE) {  			flag = TTY_FRAME; -			priv->icount.frame++; +			port->icount.frame++;  		}  		/* Overrun is special, not associated with a char */  		if (packet[1] & FTDI_RS_OE) { -			priv->icount.overrun++; +			port->icount.overrun++;  			tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);  		}  	} @@ -2024,7 +1993,7 @@ static int ftdi_process_packet(struct usb_serial_port *port,  	len -= 2;  	if (!len)  		return 0;	/* status only */ -	priv->icount.rx += len; +	port->icount.rx += len;  	ch = packet + 2;  	if (port->port.console && port->sysrq) { @@ -2388,34 +2357,10 @@ static int ftdi_tiocmset(struct tty_struct *tty,  	return update_mctrl(port, set, clear);  } -static int ftdi_get_icount(struct tty_struct *tty, -				struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct ftdi_private *priv = usb_get_serial_port_data(port); -	struct async_icount *ic = &priv->icount; - -	icount->cts = ic->cts; -	icount->dsr = ic->dsr; -	icount->rng = ic->rng; -	icount->dcd = ic->dcd; -	icount->tx = ic->tx; -	icount->rx = ic->rx; -	icount->frame = ic->frame; -	icount->parity = ic->parity; -	icount->overrun = ic->overrun; -	icount->brk = ic->brk; -	icount->buf_overrun = ic->buf_overrun; -	return 0; -} -  static int ftdi_ioctl(struct tty_struct *tty,  					unsigned int cmd, unsigned long arg)  {  	struct usb_serial_port *port = tty->driver_data; -	struct ftdi_private *priv = usb_get_serial_port_data(port); -	struct async_icount cnow; -	struct async_icount cprev;  	dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd); @@ -2429,33 +2374,6 @@ static int ftdi_ioctl(struct tty_struct *tty,  	case TIOCSSERIAL: /* sets serial port data */  		return set_serial_info(tty, port,  					(struct serial_struct __user *) arg); - -	/* -	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change -	 * - mask passed in arg for lines of interest -	 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) -	 * Caller should use TIOCGICOUNT to see which one it was. -	 * -	 * This code is borrowed from linux/drivers/char/serial.c -	 */ -	case TIOCMIWAIT: -		cprev = priv->icount; -		while (!priv->dev_gone) { -			interruptible_sleep_on(&priv->delta_msr_wait); -			/* see if a signal did it */ -			if (signal_pending(current)) -				return -ERESTARTSYS; -			cnow = priv->icount; -			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || -			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || -			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) || -			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { -				return 0; -			} -			cprev = cnow; -		} -		return -EIO; -		break;  	case TIOCSERGETLSR:  		return get_lsr_info(port, (struct serial_struct __user *)arg);  		break; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 9d359e189a6..98528270c43 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -74,6 +74,7 @@  #define FTDI_OPENDCC_THROTTLE_PID	0xBFDA  #define FTDI_OPENDCC_GATEWAY_PID	0xBFDB  #define FTDI_OPENDCC_GBM_PID	0xBFDC +#define FTDI_OPENDCC_GBM_BOOST_PID	0xBFDD  /* NZR SEM 16+ USB (http://www.nzr.de) */  #define FTDI_NZR_SEM_USB_PID	0xC1E0	/* NZR SEM-LOG16+ */ @@ -584,6 +585,13 @@  #define CONTEC_COM1USBH_PID	0x8311	/* COM-1(USB)H */  /* + * Mitsubishi Electric Corp. (http://www.meau.com) + * Submitted by Konstantin Holoborodko + */ +#define MITSUBISHI_VID		0x06D3 +#define MITSUBISHI_FXUSB_PID	0x0284 /* USB/RS422 converters: FX-USB-AW/-BD */ + +/*   * Definitions for B&B Electronics products.   */  #define BANDB_VID		0x0856	/* B&B Electronics Vendor ID */ @@ -1143,7 +1151,8 @@   * STMicroelectonics   */  #define ST_VID			0x0483 -#define ST_STMCLT1030_PID	0x3747 /* ST Micro Connect Lite STMCLT1030 */ +#define ST_STMCLT_2232_PID	0x3746 +#define ST_STMCLT_4232_PID	0x3747  /*   * Papouch products (http://www.papouch.com/) diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 1a07b12ef34..b110c573ea8 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -946,20 +946,13 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port)  static void garmin_close(struct usb_serial_port *port)  { -	struct usb_serial *serial = port->serial;  	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);  	dev_dbg(&port->dev, "%s - port %d - mode=%d state=%d flags=0x%X\n",  		__func__, port->number, garmin_data_p->mode,  		garmin_data_p->state, garmin_data_p->flags); -	if (!serial) -		return; - -	mutex_lock(&port->serial->disc_mutex); - -	if (!port->serial->disconnected) -		garmin_clear(garmin_data_p); +	garmin_clear(garmin_data_p);  	/* shutdown our urbs */  	usb_kill_urb(port->read_urb); @@ -968,8 +961,6 @@ static void garmin_close(struct usb_serial_port *port)  	/* keep reset state so we know that we must start a new session */  	if (garmin_data_p->state != STATE_RESET)  		garmin_data_p->state = STATE_DISCONNECTED; - -	mutex_unlock(&port->serial->disc_mutex);  } @@ -1190,17 +1181,11 @@ static void garmin_read_bulk_callback(struct urb *urb)  {  	unsigned long flags;  	struct usb_serial_port *port = urb->context; -	struct usb_serial *serial =  port->serial;  	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);  	unsigned char *data = urb->transfer_buffer;  	int status = urb->status;  	int retval; -	if (!serial) { -		dev_dbg(&urb->dev->dev, "%s - bad serial pointer, exiting\n", __func__); -		return; -	} -  	if (status) {  		dev_dbg(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n",  			__func__, status); diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 4c5c23f1cae..297665fdd16 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -1,7 +1,7 @@  /*   * USB Serial Converter Generic functions   * - * Copyright (C) 2010 - 2011 Johan Hovold (jhovold@gmail.com) + * Copyright (C) 2010 - 2013 Johan Hovold (jhovold@gmail.com)   * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)   *   *	This program is free software; you can redistribute it and/or @@ -45,8 +45,6 @@ struct usb_serial_driver usb_serial_generic_device = {  	},  	.id_table =		generic_device_ids,  	.num_ports =		1, -	.disconnect =		usb_serial_generic_disconnect, -	.release =		usb_serial_generic_release,  	.throttle =		usb_serial_generic_throttle,  	.unthrottle =		usb_serial_generic_unthrottle,  	.resume =		usb_serial_generic_resume, @@ -102,32 +100,23 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port  }  EXPORT_SYMBOL_GPL(usb_serial_generic_open); -static void generic_cleanup(struct usb_serial_port *port) +void usb_serial_generic_close(struct usb_serial_port *port)  { -	struct usb_serial *serial = port->serial;  	unsigned long flags;  	int i; -	if (serial->dev) { -		/* shutdown any bulk transfers that might be going on */ -		if (port->bulk_out_size) { -			for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) -				usb_kill_urb(port->write_urbs[i]); +	if (port->bulk_out_size) { +		for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) +			usb_kill_urb(port->write_urbs[i]); -			spin_lock_irqsave(&port->lock, flags); -			kfifo_reset_out(&port->write_fifo); -			spin_unlock_irqrestore(&port->lock, flags); -		} -		if (port->bulk_in_size) { -			for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) -				usb_kill_urb(port->read_urbs[i]); -		} +		spin_lock_irqsave(&port->lock, flags); +		kfifo_reset_out(&port->write_fifo); +		spin_unlock_irqrestore(&port->lock, flags); +	} +	if (port->bulk_in_size) { +		for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) +			usb_kill_urb(port->read_urbs[i]);  	} -} - -void usb_serial_generic_close(struct usb_serial_port *port) -{ -	generic_cleanup(port);  }  EXPORT_SYMBOL_GPL(usb_serial_generic_close); @@ -272,8 +261,7 @@ static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,  	if (!test_and_clear_bit(index, &port->read_urbs_free))  		return 0; -	dev_dbg(&port->dev, "%s - port %d, urb %d\n", __func__, -		port->number, index); +	dev_dbg(&port->dev, "%s - urb %d\n", __func__, index);  	res = usb_submit_urb(port->read_urbs[index], mem_flags);  	if (res) { @@ -347,8 +335,8 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)  	}  	set_bit(i, &port->read_urbs_free); -	dev_dbg(&port->dev, "%s - port %d, urb %d, len %d\n", -		__func__, port->number, i, urb->actual_length); +	dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i, +							urb->actual_length);  	if (urb->status) {  		dev_dbg(&port->dev, "%s - non-zero urb status: %d\n", @@ -430,6 +418,91 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)  }  EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle); +static bool usb_serial_generic_msr_changed(struct tty_struct *tty, +				unsigned long arg, struct async_icount *cprev) +{ +	struct usb_serial_port *port = tty->driver_data; +	struct async_icount cnow; +	unsigned long flags; +	bool ret; + +	/* +	 * Use tty-port initialised flag to detect all hangups including the +	 * one generated at USB-device disconnect. +	 * +	 * FIXME: Remove hupping check once tty_port_hangup calls shutdown +	 *        (which clears the initialised flag) before wake up. +	 */ +	if (test_bit(TTY_HUPPING, &tty->flags)) +		return true; +	if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) +		return true; + +	spin_lock_irqsave(&port->lock, flags); +	cnow = port->icount;				/* atomic copy*/ +	spin_unlock_irqrestore(&port->lock, flags); + +	ret =	((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) || +		((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) || +		((arg & TIOCM_CD)  && (cnow.dcd != cprev->dcd)) || +		((arg & TIOCM_CTS) && (cnow.cts != cprev->cts)); + +	*cprev = cnow; + +	return ret; +} + +int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg) +{ +	struct usb_serial_port *port = tty->driver_data; +	struct async_icount cnow; +	unsigned long flags; +	int ret; + +	spin_lock_irqsave(&port->lock, flags); +	cnow = port->icount;				/* atomic copy */ +	spin_unlock_irqrestore(&port->lock, flags); + +	ret = wait_event_interruptible(port->port.delta_msr_wait, +			usb_serial_generic_msr_changed(tty, arg, &cnow)); +	if (!ret) { +		if (test_bit(TTY_HUPPING, &tty->flags)) +			ret = -EIO; +		if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) +			ret = -EIO; +	} + +	return ret; +} +EXPORT_SYMBOL_GPL(usb_serial_generic_tiocmiwait); + +int usb_serial_generic_get_icount(struct tty_struct *tty, +					struct serial_icounter_struct *icount) +{ +	struct usb_serial_port *port = tty->driver_data; +	struct async_icount cnow; +	unsigned long flags; + +	spin_lock_irqsave(&port->lock, flags); +	cnow = port->icount;				/* atomic copy */ +	spin_unlock_irqrestore(&port->lock, flags); + +	icount->cts = cnow.cts; +	icount->dsr = cnow.dsr; +	icount->rng = cnow.rng; +	icount->dcd = cnow.dcd; +	icount->tx = cnow.tx; +	icount->rx = cnow.rx; +	icount->frame = cnow.frame; +	icount->parity = cnow.parity; +	icount->overrun = cnow.overrun; +	icount->brk = cnow.brk; +	icount->buf_overrun = cnow.buf_overrun; + +	return 0; +} +EXPORT_SYMBOL_GPL(usb_serial_generic_get_icount); +  #ifdef CONFIG_MAGIC_SYSRQ  int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)  { @@ -473,8 +546,7 @@ void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,  {  	struct tty_port *port = &usb_port->port; -	dev_dbg(&usb_port->dev, "%s - port %d, status %d\n", __func__, -		usb_port->number, status); +	dev_dbg(&usb_port->dev, "%s - status %d\n", __func__, status);  	if (status)  		wake_up_interruptible(&port->open_wait); @@ -510,17 +582,3 @@ int usb_serial_generic_resume(struct usb_serial *serial)  	return c ? -EIO : 0;  }  EXPORT_SYMBOL_GPL(usb_serial_generic_resume); - -void usb_serial_generic_disconnect(struct usb_serial *serial) -{ -	int i; - -	/* stop reads and writes on all ports */ -	for (i = 0; i < serial->num_ports; ++i) -		generic_cleanup(serial->port[i]); -} -EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect); - -void usb_serial_generic_release(struct usb_serial *serial) -{ -} diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index b00e5cbf741..1477e859347 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -110,9 +110,7 @@ struct edgeport_port {  	wait_queue_head_t	wait_chase;		/* for handling sleeping while waiting for chase to finish */  	wait_queue_head_t	wait_open;		/* for handling sleeping while waiting for open to finish */  	wait_queue_head_t	wait_command;		/* for handling sleeping while waiting for command to finish */ -	wait_queue_head_t	delta_msr_wait;		/* for handling sleeping while waiting for msr change to happen */ -	struct async_icount	icount;  	struct usb_serial_port	*port;			/* loop back to the owner of this object */  }; @@ -216,8 +214,6 @@ static void edge_break(struct tty_struct *tty, int break_state);  static int  edge_tiocmget(struct tty_struct *tty);  static int  edge_tiocmset(struct tty_struct *tty,  					unsigned int set, unsigned int clear); -static int  edge_get_icount(struct tty_struct *tty, -				struct serial_icounter_struct *icount);  static int  edge_startup(struct usb_serial *serial);  static void edge_disconnect(struct usb_serial *serial);  static void edge_release(struct usb_serial *serial); @@ -565,7 +561,6 @@ static void edge_interrupt_callback(struct urb *urb)  	struct device *dev;  	struct edgeport_port *edge_port;  	struct usb_serial_port *port; -	struct tty_struct *tty;  	unsigned char *data = urb->transfer_buffer;  	int length = urb->actual_length;  	int bytes_avail; @@ -644,12 +639,7 @@ static void edge_interrupt_callback(struct urb *urb)  					/* tell the tty driver that something  					   has changed */ -					tty = tty_port_tty_get( -						&edge_port->port->port); -					if (tty) { -						tty_wakeup(tty); -						tty_kref_put(tty); -					} +					tty_port_tty_wakeup(&edge_port->port->port);  					/* Since we have more credit, check  					   if more data can be sent */  					send_more_port_data(edge_serial, @@ -738,7 +728,6 @@ static void edge_bulk_in_callback(struct urb *urb)  static void edge_bulk_out_data_callback(struct urb *urb)  {  	struct edgeport_port *edge_port = urb->context; -	struct tty_struct *tty;  	int status = urb->status;  	if (status) { @@ -747,14 +736,8 @@ static void edge_bulk_out_data_callback(struct urb *urb)  			__func__, status);  	} -	tty = tty_port_tty_get(&edge_port->port->port); - -	if (tty && edge_port->open) { -		/* let the tty driver wakeup if it has a special -		   write_wakeup function */ -		tty_wakeup(tty); -	} -	tty_kref_put(tty); +	if (edge_port->open) +		tty_port_tty_wakeup(&edge_port->port->port);  	/* Release the Write URB */  	edge_port->write_in_progress = false; @@ -773,7 +756,6 @@ static void edge_bulk_out_data_callback(struct urb *urb)  static void edge_bulk_out_cmd_callback(struct urb *urb)  {  	struct edgeport_port *edge_port = urb->context; -	struct tty_struct *tty;  	int status = urb->status;  	atomic_dec(&CmdUrbs); @@ -794,13 +776,9 @@ static void edge_bulk_out_cmd_callback(struct urb *urb)  		return;  	} -	/* Get pointer to tty */ -	tty = tty_port_tty_get(&edge_port->port->port); -  	/* tell the tty driver that something has changed */ -	if (tty && edge_port->open) -		tty_wakeup(tty); -	tty_kref_put(tty); +	if (edge_port->open) +		tty_port_tty_wakeup(&edge_port->port->port);  	/* we have completed the command */  	edge_port->commandPending = false; @@ -884,12 +862,8 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)  	/* initialize our wait queues */  	init_waitqueue_head(&edge_port->wait_open);  	init_waitqueue_head(&edge_port->wait_chase); -	init_waitqueue_head(&edge_port->delta_msr_wait);  	init_waitqueue_head(&edge_port->wait_command); -	/* initialize our icount structure */ -	memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount)); -  	/* initialize our port settings */  	edge_port->txCredits = 0;	/* Can't send any data yet */  	/* Must always set this bit to enable ints! */ @@ -1316,7 +1290,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,  	/* decrement the number of credits we have by the number we just sent */  	edge_port->txCredits -= count; -	edge_port->icount.tx += count; +	edge_port->port->icount.tx += count;  	status = usb_submit_urb(urb, GFP_ATOMIC);  	if (status) { @@ -1328,7 +1302,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,  		/* revert the credits as something bad happened. */  		edge_port->txCredits += count; -		edge_port->icount.tx -= count; +		edge_port->port->icount.tx -= count;  	}  	dev_dbg(dev, "%s wrote %d byte(s) TxCredit %d, Fifo %d\n",  		__func__, count, edge_port->txCredits, fifo->count); @@ -1590,31 +1564,6 @@ static int edge_tiocmget(struct tty_struct *tty)  	return result;  } -static int edge_get_icount(struct tty_struct *tty, -				struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct edgeport_port *edge_port = usb_get_serial_port_data(port); -	struct async_icount cnow; -	cnow = edge_port->icount; - -	icount->cts = cnow.cts; -	icount->dsr = cnow.dsr; -	icount->rng = cnow.rng; -	icount->dcd = cnow.dcd; -	icount->rx = cnow.rx; -	icount->tx = cnow.tx; -	icount->frame = cnow.frame; -	icount->overrun = cnow.overrun; -	icount->parity = cnow.parity; -	icount->brk = cnow.brk; -	icount->buf_overrun = cnow.buf_overrun; - -	dev_dbg(&port->dev, "%s (%d) TIOCGICOUNT RX=%d, TX=%d\n", __func__, -		port->number, icount->rx, icount->tx); -	return 0; -} -  static int get_serial_info(struct edgeport_port *edge_port,  				struct serial_struct __user *retinfo)  { @@ -1651,8 +1600,6 @@ static int edge_ioctl(struct tty_struct *tty,  	struct usb_serial_port *port = tty->driver_data;  	DEFINE_WAIT(wait);  	struct edgeport_port *edge_port = usb_get_serial_port_data(port); -	struct async_icount cnow; -	struct async_icount cprev;  	dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd); @@ -1664,33 +1611,6 @@ static int edge_ioctl(struct tty_struct *tty,  	case TIOCGSERIAL:  		dev_dbg(&port->dev, "%s (%d) TIOCGSERIAL\n", __func__,  port->number);  		return get_serial_info(edge_port, (struct serial_struct __user *) arg); - -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,  port->number); -		cprev = edge_port->icount; -		while (1) { -			prepare_to_wait(&edge_port->delta_msr_wait, -						&wait, TASK_INTERRUPTIBLE); -			schedule(); -			finish_wait(&edge_port->delta_msr_wait, &wait); -			/* see if a signal did it */ -			if (signal_pending(current)) -				return -ERESTARTSYS; -			cnow = edge_port->icount; -			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && -			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) -				return -EIO; /* no change => error */ -			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || -			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || -			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) || -			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { -				return 0; -			} -			cprev = cnow; -		} -		/* NOTREACHED */ -		break; -  	}  	return -ENOIOCTLCMD;  } @@ -1864,7 +1784,7 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,  						edge_serial->rxPort);  					edge_tty_recv(edge_port->port, buffer,  							rxLen); -					edge_port->icount.rx += rxLen; +					edge_port->port->icount.rx += rxLen;  				}  				buffer += rxLen;  			} @@ -2040,7 +1960,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)  	if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |  			EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { -		icount = &edge_port->icount; +		icount = &edge_port->port->icount;  		/* update input line counters */  		if (newMsr & EDGEPORT_MSR_DELTA_CTS) @@ -2051,7 +1971,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)  			icount->dcd++;  		if (newMsr & EDGEPORT_MSR_DELTA_RI)  			icount->rng++; -		wake_up_interruptible(&edge_port->delta_msr_wait); +		wake_up_interruptible(&edge_port->port->port.delta_msr_wait);  	}  	/* Save the new modem status */ @@ -2086,7 +2006,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,  		edge_tty_recv(edge_port->port, &data, 1);  	/* update input line counters */ -	icount = &edge_port->icount; +	icount = &edge_port->port->icount;  	if (newLsr & LSR_BREAK)  		icount->brk++;  	if (newLsr & LSR_OVER_ERR) diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index 1511dd0ad32..ae5fac5656c 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -116,7 +116,8 @@ static struct usb_serial_driver edgeport_2port_device = {  	.set_termios		= edge_set_termios,  	.tiocmget		= edge_tiocmget,  	.tiocmset		= edge_tiocmset, -	.get_icount		= edge_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.write			= edge_write,  	.write_room		= edge_write_room,  	.chars_in_buffer	= edge_chars_in_buffer, @@ -147,7 +148,8 @@ static struct usb_serial_driver edgeport_4port_device = {  	.set_termios		= edge_set_termios,  	.tiocmget		= edge_tiocmget,  	.tiocmset		= edge_tiocmset, -	.get_icount		= edge_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.write			= edge_write,  	.write_room		= edge_write_room,  	.chars_in_buffer	= edge_chars_in_buffer, @@ -178,7 +180,8 @@ static struct usb_serial_driver edgeport_8port_device = {  	.set_termios		= edge_set_termios,  	.tiocmget		= edge_tiocmget,  	.tiocmset		= edge_tiocmset, -	.get_icount		= edge_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.write			= edge_write,  	.write_room		= edge_write_room,  	.chars_in_buffer	= edge_chars_in_buffer, @@ -209,7 +212,8 @@ static struct usb_serial_driver epic_device = {  	.set_termios		= edge_set_termios,  	.tiocmget		= edge_tiocmget,  	.tiocmset		= edge_tiocmset, -	.get_icount		= edge_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.write			= edge_write,  	.write_room		= edge_write_room,  	.chars_in_buffer	= edge_chars_in_buffer, diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index c23776679f7..158bf4bc29c 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -86,10 +86,7 @@ struct edgeport_port {  	int baud_rate;  	int close_pending;  	int lsr_event; -	struct async_icount	icount; -	wait_queue_head_t	delta_msr_wait;	/* for handling sleeping while -						   waiting for msr change to -						   happen */ +  	struct edgeport_serial	*edge_serial;  	struct usb_serial_port	*port;  	__u8 bUartMode;		/* Port type, 0: RS232, etc. */ @@ -209,7 +206,7 @@ static int restart_read(struct edgeport_port *edge_port);  static void edge_set_termios(struct tty_struct *tty,  		struct usb_serial_port *port, struct ktermios *old_termios); -static void edge_send(struct tty_struct *tty); +static void edge_send(struct usb_serial_port *port, struct tty_struct *tty);  /* sysfs attributes */  static int edge_create_sysfs_attrs(struct usb_serial_port *port); @@ -1448,7 +1445,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)  	if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |  			EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { -		icount = &edge_port->icount; +		icount = &edge_port->port->icount;  		/* update input line counters */  		if (msr & EDGEPORT_MSR_DELTA_CTS) @@ -1459,7 +1456,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)  			icount->dcd++;  		if (msr & EDGEPORT_MSR_DELTA_RI)  			icount->rng++; -		wake_up_interruptible(&edge_port->delta_msr_wait); +		wake_up_interruptible(&edge_port->port->port.delta_msr_wait);  	}  	/* Save the new modem status */ @@ -1501,7 +1498,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,  		edge_tty_recv(edge_port->port, &data, 1);  	/* update input line counters */ -	icount = &edge_port->icount; +	icount = &edge_port->port->icount;  	if (new_lsr & LSR_BREAK)  		icount->brk++;  	if (new_lsr & LSR_OVER_ERR) @@ -1660,7 +1657,7 @@ static void edge_bulk_in_callback(struct urb *urb)  		else  			edge_tty_recv(edge_port->port, data,  					urb->actual_length); -		edge_port->icount.rx += urb->actual_length; +		edge_port->port->icount.rx += urb->actual_length;  	}  exit: @@ -1715,7 +1712,7 @@ static void edge_bulk_out_callback(struct urb *urb)  	/* send any buffered data */  	tty = tty_port_tty_get(&port->port); -	edge_send(tty); +	edge_send(port, tty);  	tty_kref_put(tty);  } @@ -1753,9 +1750,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)  	dev = port->serial->dev; -	memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount)); -	init_waitqueue_head(&edge_port->delta_msr_wait); -  	/* turn off loopback */  	status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0);  	if (status) { @@ -1913,21 +1907,10 @@ static void edge_close(struct usb_serial_port *port)  	kfifo_reset_out(&edge_port->write_fifo);  	spin_unlock_irqrestore(&edge_port->ep_lock, flags); -	/* assuming we can still talk to the device, -	 * send a close port command to it */  	dev_dbg(&port->dev, "%s - send umpc_close_port\n", __func__);  	port_number = port->number - port->serial->minor; - -	mutex_lock(&serial->disc_mutex); -	if (!serial->disconnected) { -		send_cmd(serial->dev, -				     UMPC_CLOSE_PORT, -				     (__u8)(UMPM_UART1_PORT + port_number), -				     0, -				     NULL, -				     0); -	} -	mutex_unlock(&serial->disc_mutex); +	send_cmd(serial->dev, UMPC_CLOSE_PORT, +		     (__u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0);  	mutex_lock(&edge_serial->es_lock);  	--edge_port->edge_serial->num_ports_open; @@ -1957,14 +1940,13 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,  	count = kfifo_in_locked(&edge_port->write_fifo, data, count,  							&edge_port->ep_lock); -	edge_send(tty); +	edge_send(port, tty);  	return count;  } -static void edge_send(struct tty_struct *tty) +static void edge_send(struct usb_serial_port *port, struct tty_struct *tty)  { -	struct usb_serial_port *port = tty->driver_data;  	int count, result;  	struct edgeport_port *edge_port = usb_get_serial_port_data(port);  	unsigned long flags; @@ -2003,7 +1985,7 @@ static void edge_send(struct tty_struct *tty)  		edge_port->ep_write_urb_in_use = 0;  		/* TODO: reschedule edge_send */  	} else -		edge_port->icount.tx += count; +		edge_port->port->icount.tx += count;  	/* wakeup any process waiting for writes to complete */  	/* there is now more room in the buffer for new writes */ @@ -2364,27 +2346,6 @@ static int edge_tiocmget(struct tty_struct *tty)  	return result;  } -static int edge_get_icount(struct tty_struct *tty, -				struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct edgeport_port *edge_port = usb_get_serial_port_data(port); -	struct async_icount *ic = &edge_port->icount; - -	icount->cts = ic->cts; -	icount->dsr = ic->dsr; -	icount->rng = ic->rng; -	icount->dcd = ic->dcd; -	icount->tx = ic->tx; -        icount->rx = ic->rx; -        icount->frame = ic->frame; -        icount->parity = ic->parity; -        icount->overrun = ic->overrun; -        icount->brk = ic->brk; -        icount->buf_overrun = ic->buf_overrun; -	return 0; -} -  static int get_serial_info(struct edgeport_port *edge_port,  				struct serial_struct __user *retinfo)  { @@ -2396,7 +2357,7 @@ static int get_serial_info(struct edgeport_port *edge_port,  	cwait = edge_port->port->port.closing_wait;  	if (cwait != ASYNC_CLOSING_WAIT_NONE) -		cwait = jiffies_to_msecs(closing_wait) / 10; +		cwait = jiffies_to_msecs(cwait) / 10;  	memset(&tmp, 0, sizeof(tmp)); @@ -2420,8 +2381,6 @@ static int edge_ioctl(struct tty_struct *tty,  {  	struct usb_serial_port *port = tty->driver_data;  	struct edgeport_port *edge_port = usb_get_serial_port_data(port); -	struct async_icount cnow; -	struct async_icount cprev;  	dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd); @@ -2430,28 +2389,6 @@ static int edge_ioctl(struct tty_struct *tty,  		dev_dbg(&port->dev, "%s - TIOCGSERIAL\n", __func__);  		return get_serial_info(edge_port,  				(struct serial_struct __user *) arg); -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); -		cprev = edge_port->icount; -		while (1) { -			interruptible_sleep_on(&edge_port->delta_msr_wait); -			/* see if a signal did it */ -			if (signal_pending(current)) -				return -ERESTARTSYS; -			cnow = edge_port->icount; -			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && -			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) -				return -EIO; /* no change => error */ -			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || -			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || -			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) || -			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { -				return 0; -			} -			cprev = cnow; -		} -		/* not reached */ -		break;  	}  	return -ENOIOCTLCMD;  } @@ -2463,8 +2400,6 @@ static void edge_break(struct tty_struct *tty, int break_state)  	int status;  	int bv = 0;	/* Off */ -	tty_wait_until_sent(tty, 0); -  	if (break_state == -1)  		bv = 1;	/* On */  	status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv); @@ -2546,7 +2481,6 @@ static int edge_port_remove(struct usb_serial_port *port)  	struct edgeport_port *edge_port;  	edge_port = usb_get_serial_port_data(port); -  	edge_remove_sysfs_attrs(port);  	kfifo_free(&edge_port->write_fifo);  	kfree(edge_port); @@ -2618,7 +2552,8 @@ static struct usb_serial_driver edgeport_1port_device = {  	.set_termios		= edge_set_termios,  	.tiocmget		= edge_tiocmget,  	.tiocmset		= edge_tiocmset, -	.get_icount		= edge_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.write			= edge_write,  	.write_room		= edge_write_room,  	.chars_in_buffer	= edge_chars_in_buffer, @@ -2649,6 +2584,8 @@ static struct usb_serial_driver edgeport_2port_device = {  	.set_termios		= edge_set_termios,  	.tiocmget		= edge_tiocmget,  	.tiocmset		= edge_tiocmset, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.write			= edge_write,  	.write_room		= edge_write_room,  	.chars_in_buffer	= edge_chars_in_buffer, diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index ff77027160a..9d74c278b7b 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -55,7 +55,6 @@ static void read_rxcmd_callback(struct urb *urb);  struct iuu_private {  	spinlock_t lock;	/* store irq state */ -	wait_queue_head_t delta_msr_wait;  	u8 line_status;  	int tiostatus;		/* store IUART SIGNAL for tiocmget call */  	u8 reset;		/* if 1 reset is needed */ @@ -94,7 +93,6 @@ static int iuu_port_probe(struct usb_serial_port *port)  	priv->vcc = vcc_default;  	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->delta_msr_wait);  	usb_set_serial_port_data(port, priv); @@ -944,22 +942,13 @@ static void iuu_set_termios(struct tty_struct *tty,  static void iuu_close(struct usb_serial_port *port)  {  	/* iuu_led (port,255,0,0,0); */ -	struct usb_serial *serial; - -	serial = port->serial; -	if (!serial) -		return;  	iuu_uart_off(port); -	if (serial->dev) { -		/* free writebuf */ -		/* shutdown our urbs */ -		dev_dbg(&port->dev, "%s - shutting down urbs\n", __func__); -		usb_kill_urb(port->write_urb); -		usb_kill_urb(port->read_urb); -		usb_kill_urb(port->interrupt_in_urb); -		iuu_led(port, 0, 0, 0xF000, 0xFF); -	} + +	usb_kill_urb(port->write_urb); +	usb_kill_urb(port->read_urb); + +	iuu_led(port, 0, 0, 0xF000, 0xFF);  }  static void iuu_init_termios(struct tty_struct *tty) diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 1fd1935c831..eb30d7b01f3 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -378,7 +378,6 @@ static void	usa26_instat_callback(struct urb *urb)  	struct usb_serial			*serial;  	struct usb_serial_port			*port;  	struct keyspan_port_private	 	*p_priv; -	struct tty_struct			*tty;  	int old_dcd_state, err;  	int status = urb->status; @@ -421,12 +420,8 @@ static void	usa26_instat_callback(struct urb *urb)  	p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);  	p_priv->ri_state = ((msg->ri) ? 1 : 0); -	if (old_dcd_state != p_priv->dcd_state) { -		tty = tty_port_tty_get(&port->port); -		if (tty && !C_CLOCAL(tty)) -			tty_hangup(tty); -		tty_kref_put(tty); -	} +	if (old_dcd_state != p_priv->dcd_state) +		tty_port_tty_hangup(&port->port, true);  	/* Resubmit urb so we continue receiving */  	err = usb_submit_urb(urb, GFP_ATOMIC); @@ -510,7 +505,6 @@ static void	usa28_instat_callback(struct urb *urb)  	struct usb_serial			*serial;  	struct usb_serial_port			*port;  	struct keyspan_port_private	 	*p_priv; -	struct tty_struct			*tty;  	int old_dcd_state;  	int status = urb->status; @@ -551,12 +545,8 @@ static void	usa28_instat_callback(struct urb *urb)  	p_priv->dcd_state = ((msg->dcd) ? 1 : 0);  	p_priv->ri_state = ((msg->ri) ? 1 : 0); -	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { -		tty = tty_port_tty_get(&port->port); -		if (tty && !C_CLOCAL(tty)) -			tty_hangup(tty); -		tty_kref_put(tty); -	} +	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) +		tty_port_tty_hangup(&port->port, true);  		/* Resubmit urb so we continue receiving */  	err = usb_submit_urb(urb, GFP_ATOMIC); @@ -642,12 +632,8 @@ static void	usa49_instat_callback(struct urb *urb)  	p_priv->dcd_state = ((msg->dcd) ? 1 : 0);  	p_priv->ri_state = ((msg->ri) ? 1 : 0); -	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { -		struct tty_struct *tty = tty_port_tty_get(&port->port); -		if (tty && !C_CLOCAL(tty)) -			tty_hangup(tty); -		tty_kref_put(tty); -	} +	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) +		tty_port_tty_hangup(&port->port, true);  	/* Resubmit urb so we continue receiving */  	err = usb_submit_urb(urb, GFP_ATOMIC); @@ -726,45 +712,45 @@ static void usa49wg_indat_callback(struct urb *urb)  	i = 0;  	len = 0; -	if (urb->actual_length) { -		while (i < urb->actual_length) { +	while (i < urb->actual_length) { -			/* Check port number from message*/ -			if (data[i] >= serial->num_ports) { -				dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", -					__func__, data[i]); -				return; -			} -			port = serial->port[data[i++]]; -			len = data[i++]; +		/* Check port number from message */ +		if (data[i] >= serial->num_ports) { +			dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", +				__func__, data[i]); +			return; +		} +		port = serial->port[data[i++]]; +		len = data[i++]; -			/* 0x80 bit is error flag */ -			if ((data[i] & 0x80) == 0) { -				/* no error on any byte */ -				i++; -				for (x = 1; x < len ; ++x) -					tty_insert_flip_char(&port->port, -							data[i++], 0); -			} else { -				/* -				 * some bytes had errors, every byte has status -				 */ -				for (x = 0; x + 1 < len; x += 2) { -					int stat = data[i], flag = 0; -					if (stat & RXERROR_OVERRUN) -						flag |= TTY_OVERRUN; -					if (stat & RXERROR_FRAMING) -						flag |= TTY_FRAME; -					if (stat & RXERROR_PARITY) -						flag |= TTY_PARITY; -					/* XXX should handle break (0x10) */ -					tty_insert_flip_char(&port->port, -							data[i+1], flag); -					i += 2; -				} +		/* 0x80 bit is error flag */ +		if ((data[i] & 0x80) == 0) { +			/* no error on any byte */ +			i++; +			for (x = 1; x < len && i < urb->actual_length; ++x) +				tty_insert_flip_char(&port->port, +						data[i++], 0); +		} else { +			/* +			 * some bytes had errors, every byte has status +			 */ +			for (x = 0; x + 1 < len && +				    i + 1 < urb->actual_length; x += 2) { +				int stat = data[i], flag = 0; + +				if (stat & RXERROR_OVERRUN) +					flag |= TTY_OVERRUN; +				if (stat & RXERROR_FRAMING) +					flag |= TTY_FRAME; +				if (stat & RXERROR_PARITY) +					flag |= TTY_PARITY; +				/* XXX should handle break (0x10) */ +				tty_insert_flip_char(&port->port, data[i+1], +						     flag); +				i += 2;  			} -			tty_flip_buffer_push(&port->port);  		} +		tty_flip_buffer_push(&port->port);  	}  	/* Resubmit urb so we continue receiving */ @@ -851,7 +837,6 @@ static void	usa90_instat_callback(struct urb *urb)  	struct usb_serial			*serial;  	struct usb_serial_port			*port;  	struct keyspan_port_private	 	*p_priv; -	struct tty_struct			*tty;  	int old_dcd_state, err;  	int status = urb->status; @@ -880,12 +865,8 @@ static void	usa90_instat_callback(struct urb *urb)  	p_priv->dcd_state = ((msg->dcd) ? 1 : 0);  	p_priv->ri_state = ((msg->ri) ? 1 : 0); -	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { -		tty = tty_port_tty_get(&port->port); -		if (tty && !C_CLOCAL(tty)) -			tty_hangup(tty); -		tty_kref_put(tty); -	} +	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) +		tty_port_tty_hangup(&port->port, true);  	/* Resubmit urb so we continue receiving */  	err = usb_submit_urb(urb, GFP_ATOMIC); @@ -953,12 +934,8 @@ static void	usa67_instat_callback(struct urb *urb)  	p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);  	p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); -	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { -		struct tty_struct *tty = tty_port_tty_get(&port->port); -		if (tty && !C_CLOCAL(tty)) -			tty_hangup(tty); -		tty_kref_put(tty); -	} +	if (old_dcd_state != p_priv->dcd_state && old_dcd_state) +		tty_port_tty_hangup(&port->port, true);  	/* Resubmit urb so we continue receiving */  	err = usb_submit_urb(urb, GFP_ATOMIC); @@ -1115,7 +1092,6 @@ static void keyspan_dtr_rts(struct usb_serial_port *port, int on)  static void keyspan_close(struct usb_serial_port *port)  {  	int			i; -	struct usb_serial	*serial = port->serial;  	struct keyspan_port_private 	*p_priv;  	p_priv = usb_get_serial_port_data(port); @@ -1123,28 +1099,17 @@ static void keyspan_close(struct usb_serial_port *port)  	p_priv->rts_state = 0;  	p_priv->dtr_state = 0; -	if (serial->dev) { -		keyspan_send_setup(port, 2); -		/* pilot-xfer seems to work best with this delay */ -		mdelay(100); -		/* keyspan_set_termios(port, NULL); */ -	} - -	/*while (p_priv->outcont_urb->status == -EINPROGRESS) { -		dev_dbg(&port->dev, "%s - urb in progress\n", __func__); -	}*/ +	keyspan_send_setup(port, 2); +	/* pilot-xfer seems to work best with this delay */ +	mdelay(100);  	p_priv->out_flip = 0;  	p_priv->in_flip = 0; -	if (serial->dev) { -		/* Stop reading/writing urbs */ -		stop_urb(p_priv->inack_urb); -		/* stop_urb(p_priv->outcont_urb); */ -		for (i = 0; i < 2; i++) { -			stop_urb(p_priv->in_urbs[i]); -			stop_urb(p_priv->out_urbs[i]); -		} +	stop_urb(p_priv->inack_urb); +	for (i = 0; i < 2; i++) { +		stop_urb(p_priv->in_urbs[i]); +		stop_urb(p_priv->out_urbs[i]);  	}  } diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 3b17d5d13dc..5f1d382e55c 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -104,10 +104,8 @@ static void keyspan_pda_wakeup_write(struct work_struct *work)  	struct keyspan_pda_private *priv =  		container_of(work, struct keyspan_pda_private, wakeup_work);  	struct usb_serial_port *port = priv->port; -	struct tty_struct *tty = tty_port_tty_get(&port->port); -	if (tty) -		tty_wakeup(tty); -	tty_kref_put(tty); + +	tty_port_tty_wakeup(&port->port);  }  static void keyspan_pda_request_unthrottle(struct work_struct *work) @@ -595,12 +593,10 @@ static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on)  {  	struct usb_serial *serial = port->serial; -	if (serial->dev) { -		if (on) -			keyspan_pda_set_modem_info(serial, (1<<7) | (1<< 2)); -		else -			keyspan_pda_set_modem_info(serial, 0); -	} +	if (on) +		keyspan_pda_set_modem_info(serial, (1 << 7) | (1 << 2)); +	else +		keyspan_pda_set_modem_info(serial, 0);  } @@ -651,13 +647,8 @@ error:  }  static void keyspan_pda_close(struct usb_serial_port *port)  { -	struct usb_serial *serial = port->serial; - -	if (serial->dev) { -		/* shutdown our bulk reads and writes */ -		usb_kill_urb(port->write_urb); -		usb_kill_urb(port->interrupt_in_urb); -	} +	usb_kill_urb(port->write_urb); +	usb_kill_urb(port->interrupt_in_urb);  } diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 769d910ae0a..1b4054fe52a 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -341,28 +341,20 @@ static void klsi_105_close(struct usb_serial_port *port)  {  	int rc; -	mutex_lock(&port->serial->disc_mutex); -	if (!port->serial->disconnected) { -		/* send READ_OFF */ -		rc = usb_control_msg(port->serial->dev, -				     usb_sndctrlpipe(port->serial->dev, 0), -				     KL5KUSB105A_SIO_CONFIGURE, -				     USB_TYPE_VENDOR | USB_DIR_OUT, -				     KL5KUSB105A_SIO_CONFIGURE_READ_OFF, -				     0, /* index */ -				     NULL, 0, -				     KLSI_TIMEOUT); -		if (rc < 0) -			dev_err(&port->dev, -				"Disabling read failed (error = %d)\n", rc); -	} -	mutex_unlock(&port->serial->disc_mutex); +	/* send READ_OFF */ +	rc = usb_control_msg(port->serial->dev, +			     usb_sndctrlpipe(port->serial->dev, 0), +			     KL5KUSB105A_SIO_CONFIGURE, +			     USB_TYPE_VENDOR | USB_DIR_OUT, +			     KL5KUSB105A_SIO_CONFIGURE_READ_OFF, +			     0, /* index */ +			     NULL, 0, +			     KLSI_TIMEOUT); +	if (rc < 0) +		dev_err(&port->dev, "failed to disable read: %d\n", rc);  	/* shutdown our bulk reads and writes */  	usb_serial_generic_close(port); - -	/* wgg - do I need this? I think so. */ -	usb_kill_urb(port->interrupt_in_urb);  }  /* We need to write a complete 64-byte data block and encode the diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 903d938e174..78b48c31abf 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -65,7 +65,7 @@ static int  kobil_tiocmget(struct tty_struct *tty);  static int  kobil_tiocmset(struct tty_struct *tty,  			   unsigned int set, unsigned int clear);  static void kobil_read_int_callback(struct urb *urb); -static void kobil_write_callback(struct urb *purb); +static void kobil_write_int_callback(struct urb *urb);  static void kobil_set_termios(struct tty_struct *tty,  			struct usb_serial_port *port, struct ktermios *old);  static void kobil_init_termios(struct tty_struct *tty); @@ -99,6 +99,7 @@ static struct usb_serial_driver kobil_device = {  	.write =		kobil_write,  	.write_room =		kobil_write_room,  	.read_int_callback =	kobil_read_int_callback, +	.write_int_callback =	kobil_write_int_callback,  };  static struct usb_serial_driver * const serial_drivers[] = { @@ -106,8 +107,6 @@ static struct usb_serial_driver * const serial_drivers[] = {  };  struct kobil_private { -	int write_int_endpoint_address; -	int read_int_endpoint_address;  	unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */  	int filled;  /* index of the last char in buf */  	int cur_pos; /* index of the next char to send in buf */ @@ -117,14 +116,8 @@ struct kobil_private {  static int kobil_port_probe(struct usb_serial_port *port)  { -	int i;  	struct usb_serial *serial = port->serial;  	struct kobil_private *priv; -	struct usb_device *pdev; -	struct usb_host_config *actconfig; -	struct usb_interface *interface; -	struct usb_host_interface *altsetting; -	struct usb_host_endpoint *endpoint;  	priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL);  	if (!priv) @@ -150,30 +143,6 @@ static int kobil_port_probe(struct usb_serial_port *port)  	}  	usb_set_serial_port_data(port, priv); -	/* search for the necessary endpoints */ -	pdev = serial->dev; -	actconfig = pdev->actconfig; -	interface = actconfig->interface[0]; -	altsetting = interface->cur_altsetting; -	endpoint = altsetting->endpoint; - -	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { -		endpoint = &altsetting->endpoint[i]; -		if (usb_endpoint_is_int_out(&endpoint->desc)) { -			dev_dbg(&serial->dev->dev, -				"%s Found interrupt out endpoint. Address: %d\n", -				__func__, endpoint->desc.bEndpointAddress); -			priv->write_int_endpoint_address = -				endpoint->desc.bEndpointAddress; -		} -		if (usb_endpoint_is_int_in(&endpoint->desc)) { -			dev_dbg(&serial->dev->dev, -				"%s Found interrupt in  endpoint. Address: %d\n", -				__func__, endpoint->desc.bEndpointAddress); -			priv->read_int_endpoint_address = -				endpoint->desc.bEndpointAddress; -		} -	}  	return 0;  } @@ -205,7 +174,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)  	struct kobil_private *priv;  	unsigned char *transfer_buffer;  	int transfer_buffer_length = 8; -	int write_urb_transfer_buffer_length = 8;  	priv = usb_get_serial_port_data(port); @@ -214,27 +182,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)  	if (!transfer_buffer)  		return -ENOMEM; -	/* allocate write_urb */ -	if (!port->write_urb) { -		dev_dbg(dev, "%s - Allocating port->write_urb\n", __func__); -		port->write_urb = usb_alloc_urb(0, GFP_KERNEL); -		if (!port->write_urb) { -			dev_dbg(dev, "%s - usb_alloc_urb failed\n", __func__); -			kfree(transfer_buffer); -			return -ENOMEM; -		} -	} - -	/* allocate memory for write_urb transfer buffer */ -	port->write_urb->transfer_buffer = -			kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL); -	if (!port->write_urb->transfer_buffer) { -		kfree(transfer_buffer); -		usb_free_urb(port->write_urb); -		port->write_urb = NULL; -		return -ENOMEM; -	} -  	/* get hardware version */  	result = usb_control_msg(port->serial->dev,  			  usb_rcvctrlpipe(port->serial->dev, 0), @@ -310,12 +257,7 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)  static void kobil_close(struct usb_serial_port *port)  {  	/* FIXME: Add rts/dtr methods */ -	if (port->write_urb) { -		usb_poison_urb(port->write_urb); -		kfree(port->write_urb->transfer_buffer); -		usb_free_urb(port->write_urb); -		port->write_urb = NULL; -	} +	usb_kill_urb(port->interrupt_out_urb);  	usb_kill_urb(port->interrupt_in_urb);  } @@ -333,24 +275,8 @@ static void kobil_read_int_callback(struct urb *urb)  	}  	if (urb->actual_length) { - -		/* BEGIN DEBUG */ -		/* -		  char *dbg_data; - -		  dbg_data = kzalloc((3 *  purb->actual_length + 10) -						* sizeof(char), GFP_KERNEL); -		  if (! dbg_data) { -			  return; -		  } -		  for (i = 0; i < purb->actual_length; i++) { -			  sprintf(dbg_data +3*i, "%02X ", data[i]); -		  } -		  dev_dbg(&port->dev, " <-- %s\n", dbg_data); -		  kfree(dbg_data); -		*/ -		/* END DEBUG */ - +		usb_serial_debug_data(&port->dev, __func__, urb->actual_length, +									data);  		tty_insert_flip_string(&port->port, data, urb->actual_length);  		tty_flip_buffer_push(&port->port);  	} @@ -360,7 +286,7 @@ static void kobil_read_int_callback(struct urb *urb)  } -static void kobil_write_callback(struct urb *purb) +static void kobil_write_int_callback(struct urb *urb)  {  } @@ -403,23 +329,14 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,  		while (todo > 0) {  			/* max 8 byte in one urb (endpoint size) */ -			length = (todo < 8) ? todo : 8; +			length = min(todo, port->interrupt_out_size);  			/* copy data to transfer buffer */ -			memcpy(port->write_urb->transfer_buffer, +			memcpy(port->interrupt_out_buffer,  					priv->buf + priv->cur_pos, length); -			usb_fill_int_urb(port->write_urb, -				  port->serial->dev, -				  usb_sndintpipe(port->serial->dev, -					priv->write_int_endpoint_address), -				  port->write_urb->transfer_buffer, -				  length, -				  kobil_write_callback, -				  port, -				  8 -			); +			port->interrupt_out_urb->transfer_buffer_length = length;  			priv->cur_pos = priv->cur_pos + length; -			result = usb_submit_urb(port->write_urb, GFP_NOIO); +			result = usb_submit_urb(port->interrupt_out_urb, GFP_NOIO);  			dev_dbg(&port->dev, "%s - Send write URB returns: %i\n", __func__, result);  			todo = priv->filled - priv->cur_pos; diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index a64d420f687..6a15adf5336 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -35,7 +35,6 @@  #include <linux/usb.h>  #include <linux/usb/serial.h>  #include <linux/serial.h> -#include <linux/ioctl.h>  #include "mct_u232.h"  #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>" @@ -44,7 +43,6 @@  /*   * Function prototypes   */ -static int  mct_u232_startup(struct usb_serial *serial);  static int  mct_u232_port_probe(struct usb_serial_port *port);  static int  mct_u232_port_remove(struct usb_serial_port *remove);  static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port); @@ -57,10 +55,6 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);  static int  mct_u232_tiocmget(struct tty_struct *tty);  static int  mct_u232_tiocmset(struct tty_struct *tty,  			unsigned int set, unsigned int clear); -static int  mct_u232_ioctl(struct tty_struct *tty, -			unsigned int cmd, unsigned long arg); -static int  mct_u232_get_icount(struct tty_struct *tty, -			struct serial_icounter_struct *icount);  static void mct_u232_throttle(struct tty_struct *tty);  static void mct_u232_unthrottle(struct tty_struct *tty); @@ -95,11 +89,10 @@ static struct usb_serial_driver mct_u232_device = {  	.break_ctl =	     mct_u232_break_ctl,  	.tiocmget =	     mct_u232_tiocmget,  	.tiocmset =	     mct_u232_tiocmset, -	.attach =	     mct_u232_startup, +	.tiocmiwait =        usb_serial_generic_tiocmiwait,  	.port_probe =        mct_u232_port_probe,  	.port_remove =       mct_u232_port_remove, -	.ioctl =             mct_u232_ioctl, -	.get_icount =        mct_u232_get_icount, +	.get_icount =        usb_serial_generic_get_icount,  };  static struct usb_serial_driver * const serial_drivers[] = { @@ -107,15 +100,13 @@ static struct usb_serial_driver * const serial_drivers[] = {  };  struct mct_u232_private { +	struct urb *read_urb;  	spinlock_t lock;  	unsigned int	     control_state; /* Modem Line Setting (TIOCM) */  	unsigned char        last_lcr;      /* Line Control Register */  	unsigned char	     last_lsr;      /* Line Status Register */  	unsigned char	     last_msr;      /* Modem Status Register */  	unsigned int	     rx_flags;      /* Throttling flags */ -	struct async_icount  icount; -	wait_queue_head_t    msr_wait;	/* for handling sleeping while waiting -						for msr change to happen */  };  #define THROTTLED		0x01 @@ -384,22 +375,6 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port,   * Driver's tty interface functions   */ -static int mct_u232_startup(struct usb_serial *serial) -{ -	struct usb_serial_port *port, *rport; - -	/* Puh, that's dirty */ -	port = serial->port[0]; -	rport = serial->port[1]; -	/* No unlinking, it wasn't submitted yet. */ -	usb_free_urb(port->read_urb); -	port->read_urb = rport->interrupt_in_urb; -	rport->interrupt_in_urb = NULL; -	port->read_urb->context = port; - -	return 0; -} /* mct_u232_startup */ -  static int mct_u232_port_probe(struct usb_serial_port *port)  {  	struct mct_u232_private *priv; @@ -408,8 +383,11 @@ static int mct_u232_port_probe(struct usb_serial_port *port)  	if (!priv)  		return -ENOMEM; +	/* Use second interrupt-in endpoint for reading. */ +	priv->read_urb = port->serial->port[1]->interrupt_in_urb; +	priv->read_urb->context = port; +  	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->msr_wait);  	usb_set_serial_port_data(port, priv); @@ -472,17 +450,17 @@ static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)  	mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);  	spin_unlock_irqrestore(&priv->lock, flags); -	retval = usb_submit_urb(port->read_urb, GFP_KERNEL); +	retval = usb_submit_urb(priv->read_urb, GFP_KERNEL);  	if (retval) {  		dev_err(&port->dev, -			"usb_submit_urb(read bulk) failed pipe 0x%x err %d\n", +			"usb_submit_urb(read) failed pipe 0x%x err %d\n",  			port->read_urb->pipe, retval);  		goto error;  	}  	retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);  	if (retval) { -		usb_kill_urb(port->read_urb); +		usb_kill_urb(priv->read_urb);  		dev_err(&port->dev,  			"usb_submit_urb(read int) failed pipe 0x%x err %d",  			port->interrupt_in_urb->pipe, retval); @@ -512,11 +490,9 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)  static void mct_u232_close(struct usb_serial_port *port)  { -	/* -	 * Must kill the read urb as it is actually an interrupt urb, which -	 * generic close thus fails to kill. -	 */ -	usb_kill_urb(port->read_urb); +	struct mct_u232_private *priv = usb_get_serial_port_data(port); + +	usb_kill_urb(priv->read_urb);  	usb_kill_urb(port->interrupt_in_urb);  	usb_serial_generic_close(port); @@ -573,7 +549,7 @@ static void mct_u232_read_int_callback(struct urb *urb)  	/* Record Control Line states */  	mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr); -	mct_u232_msr_to_icount(&priv->icount, priv->last_msr); +	mct_u232_msr_to_icount(&port->icount, priv->last_msr);  #if 0  	/* Not yet handled. See belkin_sa.c for further information */ @@ -601,7 +577,7 @@ static void mct_u232_read_int_callback(struct urb *urb)  		tty_kref_put(tty);  	}  #endif -	wake_up_interruptible(&priv->msr_wait); +	wake_up_interruptible(&port->port.delta_msr_wait);  	spin_unlock_irqrestore(&priv->lock, flags);  exit:  	retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -789,82 +765,6 @@ static void mct_u232_unthrottle(struct tty_struct *tty)  	}  } -static int  mct_u232_ioctl(struct tty_struct *tty, -			unsigned int cmd, unsigned long arg) -{ -	DEFINE_WAIT(wait); -	struct usb_serial_port *port = tty->driver_data; -	struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port); -	struct async_icount cnow, cprev; -	unsigned long flags; - -	dev_dbg(&port->dev, "%s - cmd = 0x%x\n", __func__, cmd); - -	switch (cmd) { - -	case TIOCMIWAIT: - -		dev_dbg(&port->dev, "%s TIOCMIWAIT", __func__); - -		spin_lock_irqsave(&mct_u232_port->lock, flags); -		cprev = mct_u232_port->icount; -		spin_unlock_irqrestore(&mct_u232_port->lock, flags); -		for ( ; ; ) { -			prepare_to_wait(&mct_u232_port->msr_wait, -					&wait, TASK_INTERRUPTIBLE); -			schedule(); -			finish_wait(&mct_u232_port->msr_wait, &wait); -			/* see if a signal did it */ -			if (signal_pending(current)) -				return -ERESTARTSYS; -			spin_lock_irqsave(&mct_u232_port->lock, flags); -			cnow = mct_u232_port->icount; -			spin_unlock_irqrestore(&mct_u232_port->lock, flags); -			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && -			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) -				return -EIO; /* no change => error */ -			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || -			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || -			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) || -			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { -				return 0; -			} -			cprev = cnow; -		} - -	} -	return -ENOIOCTLCMD; -} - -static int  mct_u232_get_icount(struct tty_struct *tty, -			struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port); -	struct async_icount *ic = &mct_u232_port->icount; -	unsigned long flags; - -	spin_lock_irqsave(&mct_u232_port->lock, flags); - -	icount->cts = ic->cts; -	icount->dsr = ic->dsr; -	icount->rng = ic->rng; -	icount->dcd = ic->dcd; -	icount->rx = ic->rx; -	icount->tx = ic->tx; -	icount->frame = ic->frame; -	icount->overrun = ic->overrun; -	icount->parity = ic->parity; -	icount->brk = ic->brk; -	icount->buf_overrun = ic->buf_overrun; - -	spin_unlock_irqrestore(&mct_u232_port->lock, flags); - -	dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", -		__func__,  icount->rx, icount->tx); -	return 0; -} -  module_usb_serial_driver(serial_drivers, id_table);  MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index bf3c7a23553..47e247759eb 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -177,10 +177,7 @@ static void metrousb_cleanup(struct usb_serial_port *port)  	usb_unlink_urb(port->interrupt_in_urb);  	usb_kill_urb(port->interrupt_in_urb); -	mutex_lock(&port->serial->disc_mutex); -	if (!port->serial->disconnected) -		metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port); -	mutex_unlock(&port->serial->disc_mutex); +	metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);  }  static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index e0ebec3b5d6..cc0e54345df 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -62,7 +62,6 @@ struct moschip_port {  	__u8	shadowMCR;		/* last MCR value received */  	__u8	shadowMSR;		/* last MSR value received */  	char			open; -	struct async_icount	icount;  	struct usb_serial_port	*port;	/* loop back to the owner */  	struct urb		*write_urb_pool[NUM_URBS];  }; @@ -932,7 +931,6 @@ static void mos7720_bulk_in_callback(struct urb *urb)  static void mos7720_bulk_out_data_callback(struct urb *urb)  {  	struct moschip_port *mos7720_port; -	struct tty_struct *tty;  	int status = urb->status;  	if (status) { @@ -946,11 +944,8 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)  		return ;  	} -	tty = tty_port_tty_get(&mos7720_port->port->port); - -	if (tty && mos7720_port->open) -		tty_wakeup(tty); -	tty_kref_put(tty); +	if (mos7720_port->open) +		tty_port_tty_wakeup(&mos7720_port->port->port);  }  /* @@ -1075,9 +1070,6 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)  		dev_err(&port->dev, "%s - Error %d submitting read urb\n",  							__func__, response); -	/* initialize our icount structure */ -	memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount)); -  	/* initialize our port settings */  	mos7720_port->shadowMCR = UART_MCR_OUT2; /* Must set to enable ints! */ @@ -1144,16 +1136,9 @@ static void mos7720_close(struct usb_serial_port *port)  	usb_kill_urb(port->write_urb);  	usb_kill_urb(port->read_urb); -	mutex_lock(&serial->disc_mutex); -	/* these commands must not be issued if the device has -	 * been disconnected */ -	if (!serial->disconnected) { -		write_mos_reg(serial, port->number - port->serial->minor, -			      MCR, 0x00); -		write_mos_reg(serial, port->number - port->serial->minor, -			      IER, 0x00); -	} -	mutex_unlock(&serial->disc_mutex); +	write_mos_reg(serial, port->number - port->serial->minor, MCR, 0x00); +	write_mos_reg(serial, port->number - port->serial->minor, IER, 0x00); +  	mos7720_port->open = 0;  } @@ -1803,33 +1788,6 @@ static int mos7720_tiocmset(struct tty_struct *tty,  	return 0;  } -static int mos7720_get_icount(struct tty_struct *tty, -				struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct moschip_port *mos7720_port; -	struct async_icount cnow; - -	mos7720_port = usb_get_serial_port_data(port); -	cnow = mos7720_port->icount; - -	icount->cts = cnow.cts; -	icount->dsr = cnow.dsr; -	icount->rng = cnow.rng; -	icount->dcd = cnow.dcd; -	icount->rx = cnow.rx; -	icount->tx = cnow.tx; -	icount->frame = cnow.frame; -	icount->overrun = cnow.overrun; -	icount->parity = cnow.parity; -	icount->brk = cnow.brk; -	icount->buf_overrun = cnow.buf_overrun; - -	dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__, -		icount->rx, icount->tx); -	return 0; -} -  static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,  			  unsigned int __user *value)  { @@ -1905,8 +1863,6 @@ static int mos7720_ioctl(struct tty_struct *tty,  {  	struct usb_serial_port *port = tty->driver_data;  	struct moschip_port *mos7720_port; -	struct async_icount cnow; -	struct async_icount cprev;  	mos7720_port = usb_get_serial_port_data(port);  	if (mos7720_port == NULL) @@ -1931,27 +1887,6 @@ static int mos7720_ioctl(struct tty_struct *tty,  		dev_dbg(&port->dev, "%s TIOCGSERIAL\n", __func__);  		return get_serial_info(mos7720_port,  				       (struct serial_struct __user *)arg); - -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__); -		cprev = mos7720_port->icount; -		while (1) { -			if (signal_pending(current)) -				return -ERESTARTSYS; -			cnow = mos7720_port->icount; -			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && -			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) -				return -EIO; /* no change => error */ -			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || -			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || -			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) || -			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { -				return 0; -			} -			cprev = cnow; -		} -		/* NOTREACHED */ -		break;  	}  	return -ENOIOCTLCMD; @@ -2107,7 +2042,6 @@ static struct usb_serial_driver moschip7720_2port_driver = {  	.ioctl			= mos7720_ioctl,  	.tiocmget		= mos7720_tiocmget,  	.tiocmset		= mos7720_tiocmset, -	.get_icount		= mos7720_get_icount,  	.set_termios		= mos7720_set_termios,  	.write			= mos7720_write,  	.write_room		= mos7720_write_room, diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 809fb329eca..a0d5ea54598 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -219,9 +219,6 @@ struct moschip_port {  	char open;  	char open_ports;  	wait_queue_head_t wait_chase;	/* for handling sleeping while waiting for chase to finish */ -	wait_queue_head_t delta_msr_wait;	/* for handling sleeping while waiting for msr change to happen */ -	int delta_msr_cond; -	struct async_icount icount;  	struct usb_serial_port *port;	/* loop back to the owner of this object */  	/* Offsets */ @@ -400,29 +397,22 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)  	struct moschip_port *mos7840_port;  	struct async_icount *icount;  	mos7840_port = port; -	icount = &mos7840_port->icount;  	if (new_msr &  	    (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI |  	     MOS_MSR_DELTA_CD)) { -		icount = &mos7840_port->icount; +		icount = &mos7840_port->port->icount;  		/* update input line counters */ -		if (new_msr & MOS_MSR_DELTA_CTS) { +		if (new_msr & MOS_MSR_DELTA_CTS)  			icount->cts++; -			smp_wmb(); -		} -		if (new_msr & MOS_MSR_DELTA_DSR) { +		if (new_msr & MOS_MSR_DELTA_DSR)  			icount->dsr++; -			smp_wmb(); -		} -		if (new_msr & MOS_MSR_DELTA_CD) { +		if (new_msr & MOS_MSR_DELTA_CD)  			icount->dcd++; -			smp_wmb(); -		} -		if (new_msr & MOS_MSR_DELTA_RI) { +		if (new_msr & MOS_MSR_DELTA_RI)  			icount->rng++; -			smp_wmb(); -		} + +		wake_up_interruptible(&port->port->port.delta_msr_wait);  	}  } @@ -440,23 +430,15 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)  	}  	/* update input line counters */ -	icount = &port->icount; -	if (new_lsr & SERIAL_LSR_BI) { +	icount = &port->port->icount; +	if (new_lsr & SERIAL_LSR_BI)  		icount->brk++; -		smp_wmb(); -	} -	if (new_lsr & SERIAL_LSR_OE) { +	if (new_lsr & SERIAL_LSR_OE)  		icount->overrun++; -		smp_wmb(); -	} -	if (new_lsr & SERIAL_LSR_PE) { +	if (new_lsr & SERIAL_LSR_PE)  		icount->parity++; -		smp_wmb(); -	} -	if (new_lsr & SERIAL_LSR_FE) { +	if (new_lsr & SERIAL_LSR_FE)  		icount->frame++; -		smp_wmb(); -	}  }  /************************************************************************/ @@ -775,9 +757,8 @@ static void mos7840_bulk_in_callback(struct urb *urb)  		struct tty_port *tport = &mos7840_port->port->port;  		tty_insert_flip_string(tport, data, urb->actual_length);  		tty_flip_buffer_push(tport); -		mos7840_port->icount.rx += urb->actual_length; -		smp_wmb(); -		dev_dbg(&port->dev, "mos7840_port->icount.rx is %d:\n", mos7840_port->icount.rx); +		port->icount.rx += urb->actual_length; +		dev_dbg(&port->dev, "icount.rx is %d:\n", port->icount.rx);  	}  	if (!mos7840_port->read_urb) { @@ -814,7 +795,6 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)  {  	struct moschip_port *mos7840_port;  	struct usb_serial_port *port; -	struct tty_struct *tty;  	int status = urb->status;  	int i; @@ -837,10 +817,8 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)  	if (mos7840_port_paranoia_check(port, __func__))  		return; -	tty = tty_port_tty_get(&port->port); -	if (tty && mos7840_port->open) -		tty_wakeup(tty); -	tty_kref_put(tty); +	if (mos7840_port->open) +		tty_port_tty_wakeup(&port->port);  } @@ -1127,10 +1105,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)  	/* initialize our wait queues */  	init_waitqueue_head(&mos7840_port->wait_chase); -	init_waitqueue_head(&mos7840_port->delta_msr_wait); - -	/* initialize our icount structure */ -	memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));  	/* initialize our port settings */  	/* Must set to enable ints! */ @@ -1138,8 +1112,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)  	/* send a open port command */  	mos7840_port->open = 1;  	/* mos7840_change_port_settings(mos7840_port,old_termios); */ -	mos7840_port->icount.tx = 0; -	mos7840_port->icount.rx = 0;  	return 0;  } @@ -1222,25 +1194,10 @@ static void mos7840_close(struct usb_serial_port *port)  		}  	} -	/* While closing port, shutdown all bulk read, write  * -	 * and interrupt read if they exists                  */ -	if (serial->dev) { -		if (mos7840_port->write_urb) { -			dev_dbg(&port->dev, "%s", "Shutdown bulk write\n"); -			usb_kill_urb(mos7840_port->write_urb); -		} -		if (mos7840_port->read_urb) { -			dev_dbg(&port->dev, "%s", "Shutdown bulk read\n"); -			usb_kill_urb(mos7840_port->read_urb); -			mos7840_port->read_urb_busy = false; -		} -		if ((&mos7840_port->control_urb)) { -			dev_dbg(&port->dev, "%s", "Shutdown control read\n"); -			/*/      usb_kill_urb (mos7840_port->control_urb); */ -		} -	} -/*      if(mos7840_port->ctrl_buf != NULL) */ -/*              kfree(mos7840_port->ctrl_buf); */ +	usb_kill_urb(mos7840_port->write_urb); +	usb_kill_urb(mos7840_port->read_urb); +	mos7840_port->read_urb_busy = false; +  	port0->open_ports--;  	dev_dbg(&port->dev, "%s in close%d:in port%d\n", __func__, port0->open_ports, port->number);  	if (port0->open_ports == 0) { @@ -1252,8 +1209,7 @@ static void mos7840_close(struct usb_serial_port *port)  	if (mos7840_port->write_urb) {  		/* if this urb had a transfer buffer already (old tx) free it */ -		if (mos7840_port->write_urb->transfer_buffer != NULL) -			kfree(mos7840_port->write_urb->transfer_buffer); +		kfree(mos7840_port->write_urb->transfer_buffer);  		usb_free_urb(mos7840_port->write_urb);  	} @@ -1330,9 +1286,8 @@ static void mos7840_break(struct tty_struct *tty, int break_state)  	if (mos7840_port == NULL)  		return; -	if (serial->dev) -		/* flush and block until tx is empty */ -		mos7840_block_until_chase_response(tty, mos7840_port); +	/* flush and block until tx is empty */ +	mos7840_block_until_chase_response(tty, mos7840_port);  	if (break_state == -1)  		data = mos7840_port->shadowLCR | LCR_SET_BREAK; @@ -1522,9 +1477,8 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,  		goto exit;  	}  	bytes_sent = transfer_size; -	mos7840_port->icount.tx += transfer_size; -	smp_wmb(); -	dev_dbg(&port->dev, "mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx); +	port->icount.tx += transfer_size; +	dev_dbg(&port->dev, "icount.tx is %d:\n", port->icount.tx);  exit:  	return bytes_sent; @@ -2017,8 +1971,6 @@ static void mos7840_change_port_settings(struct tty_struct *tty,  			mos7840_port->read_urb_busy = false;  		}  	} -	wake_up(&mos7840_port->delta_msr_wait); -	mos7840_port->delta_msr_cond = 1;  	dev_dbg(&port->dev, "%s - mos7840_port->shadowLCR is End %x\n", __func__,  		mos7840_port->shadowLCR);  } @@ -2145,34 +2097,6 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,  	return 0;  } -static int mos7840_get_icount(struct tty_struct *tty, -			struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct moschip_port *mos7840_port; -	struct async_icount cnow; - -	mos7840_port = mos7840_get_port_private(port); -	cnow = mos7840_port->icount; - -	smp_rmb(); -	icount->cts = cnow.cts; -	icount->dsr = cnow.dsr; -	icount->rng = cnow.rng; -	icount->dcd = cnow.dcd; -	icount->rx = cnow.rx; -	icount->tx = cnow.tx; -	icount->frame = cnow.frame; -	icount->overrun = cnow.overrun; -	icount->parity = cnow.parity; -	icount->brk = cnow.brk; -	icount->buf_overrun = cnow.buf_overrun; - -	dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__, -		icount->rx, icount->tx); -	return 0; -} -  /*****************************************************************************   * SerialIoctl   *	this function handles any ioctl calls to the driver @@ -2185,9 +2109,6 @@ static int mos7840_ioctl(struct tty_struct *tty,  	void __user *argp = (void __user *)arg;  	struct moschip_port *mos7840_port; -	struct async_icount cnow; -	struct async_icount cprev; -  	if (mos7840_port_paranoia_check(port, __func__))  		return -1; @@ -2212,36 +2133,6 @@ static int mos7840_ioctl(struct tty_struct *tty,  	case TIOCSSERIAL:  		dev_dbg(&port->dev, "%s TIOCSSERIAL\n", __func__);  		break; - -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s  TIOCMIWAIT\n", __func__); -		cprev = mos7840_port->icount; -		while (1) { -			/* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */ -			mos7840_port->delta_msr_cond = 0; -			wait_event_interruptible(mos7840_port->delta_msr_wait, -						 (mos7840_port-> -						  delta_msr_cond == 1)); - -			/* see if a signal did it */ -			if (signal_pending(current)) -				return -ERESTARTSYS; -			cnow = mos7840_port->icount; -			smp_rmb(); -			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && -			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) -				return -EIO;	/* no change => error */ -			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || -			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || -			    ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || -			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { -				return 0; -			} -			cprev = cnow; -		} -		/* NOTREACHED */ -		break; -  	default:  		break;  	} @@ -2588,7 +2479,8 @@ static struct usb_serial_driver moschip7840_4port_device = {  	.break_ctl = mos7840_break,  	.tiocmget = mos7840_tiocmget,  	.tiocmset = mos7840_tiocmset, -	.get_icount = mos7840_get_icount, +	.tiocmiwait = usb_serial_generic_tiocmiwait, +	.get_icount = usb_serial_generic_get_icount,  	.port_probe = mos7840_port_probe,  	.port_remove = mos7840_port_remove,  	.read_bulk_callback = mos7840_bulk_in_callback, diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 1e1cafe287e..5739bf6f720 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -33,8 +33,7 @@  /* function prototypes */  static int  omninet_open(struct tty_struct *tty, struct usb_serial_port *port); -static void omninet_close(struct usb_serial_port *port); -static void omninet_read_bulk_callback(struct urb *urb); +static void omninet_process_read_urb(struct urb *urb);  static void omninet_write_bulk_callback(struct urb *urb);  static int  omninet_write(struct tty_struct *tty, struct usb_serial_port *port,  				const unsigned char *buf, int count); @@ -61,11 +60,10 @@ static struct usb_serial_driver zyxel_omninet_device = {  	.port_probe =		omninet_port_probe,  	.port_remove =		omninet_port_remove,  	.open =			omninet_open, -	.close =		omninet_close,  	.write =		omninet_write,  	.write_room =		omninet_write_room, -	.read_bulk_callback =	omninet_read_bulk_callback,  	.write_bulk_callback =	omninet_write_bulk_callback, +	.process_read_urb =	omninet_process_read_urb,  	.disconnect =		omninet_disconnect,  }; @@ -74,29 +72,28 @@ static struct usb_serial_driver * const serial_drivers[] = {  }; -/* The protocol. +/* + * The protocol.   *   * The omni.net always exchange 64 bytes of data with the host. The first - * four bytes are the control header, you can see it in the above structure. + * four bytes are the control header.   *   * oh_seq is a sequence number. Don't know if/how it's used.   * oh_len is the length of the data bytes in the packet.   * oh_xxx Bit-mapped, related to handshaking and status info. - *	I normally set it to 0x03 in trasmitted frames. + *	I normally set it to 0x03 in transmitted frames.   *	7: Active when the TA is in a CONNECTed state.   *	6: unknown   *	5: handshaking, unknown   *	4: handshaking, unknown   *	3: unknown, usually 0   *	2: unknown, usually 0 - *	1: handshaking, unknown, usually set to 1 in trasmitted frames - *	0: handshaking, unknown, usually set to 1 in trasmitted frames + *	1: handshaking, unknown, usually set to 1 in transmitted frames + *	0: handshaking, unknown, usually set to 1 in transmitted frames   * oh_pad Probably a pad byte.   *   * After the header you will find data bytes if oh_len was greater than zero. - *   */ -  struct omninet_header {  	__u8	oh_seq;  	__u8	oh_len; @@ -112,7 +109,7 @@ static int omninet_port_probe(struct usb_serial_port *port)  {  	struct omninet_data *od; -	od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL); +	od = kzalloc(sizeof(*od), GFP_KERNEL);  	if (!od)  		return -ENOMEM; @@ -135,56 +132,32 @@ static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port)  {  	struct usb_serial	*serial = port->serial;  	struct usb_serial_port	*wport; -	int			result = 0;  	wport = serial->port[1];  	tty_port_tty_set(&wport->port, tty); -	/* Start reading from the device */ -	result = usb_submit_urb(port->read_urb, GFP_KERNEL); -	if (result) -		dev_err(&port->dev, -			"%s - failed submitting read urb, error %d\n", -			__func__, result); -	return result; -} - -static void omninet_close(struct usb_serial_port *port) -{ -	usb_kill_urb(port->read_urb); +	return usb_serial_generic_open(tty, port);  } +#define OMNINET_HEADERLEN	4 +#define OMNINET_BULKOUTSIZE	64 +#define OMNINET_PAYLOADSIZE	(OMNINET_BULKOUTSIZE - OMNINET_HEADERLEN) -#define OMNINET_DATAOFFSET	0x04 -#define OMNINET_HEADERLEN	sizeof(struct omninet_header) -#define OMNINET_BULKOUTSIZE 	(64 - OMNINET_HEADERLEN) - -static void omninet_read_bulk_callback(struct urb *urb) +static void omninet_process_read_urb(struct urb *urb)  { -	struct usb_serial_port 	*port 	= urb->context; -	unsigned char 		*data 	= urb->transfer_buffer; -	struct omninet_header 	*header = (struct omninet_header *) &data[0]; -	int status = urb->status; -	int result; +	struct usb_serial_port *port = urb->context; +	const struct omninet_header *hdr = urb->transfer_buffer; +	const unsigned char *data; +	size_t data_len; -	if (status) { -		dev_dbg(&port->dev, "%s - nonzero read bulk status received: %d\n", -			__func__, status); +	if (urb->actual_length <= OMNINET_HEADERLEN || !hdr->oh_len)  		return; -	} - -	if (urb->actual_length && header->oh_len) { -		tty_insert_flip_string(&port->port, data + OMNINET_DATAOFFSET, -				header->oh_len); -		tty_flip_buffer_push(&port->port); -	} -	/* Continue trying to always read  */ -	result = usb_submit_urb(urb, GFP_ATOMIC); -	if (result) -		dev_err(&port->dev, -			"%s - failed resubmitting read urb, error %d\n", -			__func__, result); +	data = (char *)urb->transfer_buffer + OMNINET_HEADERLEN; +	data_len = min_t(size_t, urb->actual_length - OMNINET_HEADERLEN, +								hdr->oh_len); +	tty_insert_flip_string(&port->port, data, data_len); +	tty_flip_buffer_push(&port->port);  }  static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -209,9 +182,9 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,  		return 0;  	} -	count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; +	count = (count > OMNINET_PAYLOADSIZE) ? OMNINET_PAYLOADSIZE : count; -	memcpy(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, +	memcpy(wport->write_urb->transfer_buffer + OMNINET_HEADERLEN,  								buf, count);  	usb_serial_debug_data(&port->dev, __func__, count, @@ -223,7 +196,7 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,  	header->oh_pad 	= 0x00;  	/* send the data out the bulk port, always 64 bytes */ -	wport->write_urb->transfer_buffer_length = 64; +	wport->write_urb->transfer_buffer_length = OMNINET_BULKOUTSIZE;  	result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);  	if (result) { diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index e13e1a4d3e1..5f4b0cd0f6e 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -120,7 +120,10 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,  				0, 0, buffer, 1, 0);  	kfree(buffer); -	return retval; +	if (retval < 0) +		return retval; + +	return 0;  }  static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -306,7 +309,6 @@ static int opticon_tiocmset(struct tty_struct *tty,  			   unsigned int set, unsigned int clear)  {  	struct usb_serial_port *port = tty->driver_data; -	struct usb_serial *serial = port->serial;  	struct opticon_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	bool rts; @@ -327,15 +329,11 @@ static int opticon_tiocmset(struct tty_struct *tty,  	if (!changed)  		return 0; -	/* Send the new RTS state to the connected device */ -	mutex_lock(&serial->disc_mutex); -	if (!serial->disconnected) -		ret = send_control_msg(port, CONTROL_RTS, !rts); -	else -		ret = -ENODEV; -	mutex_unlock(&serial->disc_mutex); +	ret = send_control_msg(port, CONTROL_RTS, !rts); +	if (ret) +		return usb_translate_errors(ret); -	return ret; +	return 0;  }  static int get_serial_info(struct usb_serial_port *port, diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 558adfc0500..734372846ab 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -347,6 +347,7 @@ static void option_instat_callback(struct urb *urb);  /* Olivetti products */  #define OLIVETTI_VENDOR_ID			0x0b3c  #define OLIVETTI_PRODUCT_OLICARD100		0xc000 +#define OLIVETTI_PRODUCT_OLICARD145		0xc003  /* Celot products */  #define CELOT_VENDOR_ID				0x211f @@ -1273,6 +1274,7 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },  	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, +	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) },  	{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */  	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */  	{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/ @@ -1350,6 +1352,12 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),  	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },  	{ USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x02, 0x01) },	/* D-Link DWM-156 (variant) */ +	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x00, 0x00) },	/* D-Link DWM-156 (variant) */ +	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x02, 0x01) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },  	{ } /* Terminating entry */  };  MODULE_DEVICE_TABLE(usb, option_ids); @@ -1537,13 +1545,8 @@ static void option_instat_callback(struct urb *urb)  			portdata->dsr_state = ((signals & 0x02) ? 1 : 0);  			portdata->ri_state = ((signals & 0x08) ? 1 : 0); -			if (old_dcd_state && !portdata->dcd_state) { -				struct tty_struct *tty = -						tty_port_tty_get(&port->port); -				if (tty && !C_CLOCAL(tty)) -					tty_hangup(tty); -				tty_kref_put(tty); -			} +			if (old_dcd_state && !portdata->dcd_state) +				tty_port_tty_hangup(&port->port, true);  		} else {  			dev_dbg(dev, "%s: type %x req %x\n", __func__,  				req_pkt->bRequestType, req_pkt->bRequest); diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index a958fd41b5b..7e3e0782e51 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -124,8 +124,6 @@ static void oti6858_close(struct usb_serial_port *port);  static void oti6858_set_termios(struct tty_struct *tty,  			struct usb_serial_port *port, struct ktermios *old);  static void oti6858_init_termios(struct tty_struct *tty); -static int oti6858_ioctl(struct tty_struct *tty, -			unsigned int cmd, unsigned long arg);  static void oti6858_read_int_callback(struct urb *urb);  static void oti6858_read_bulk_callback(struct urb *urb);  static void oti6858_write_bulk_callback(struct urb *urb); @@ -136,6 +134,7 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty);  static int oti6858_tiocmget(struct tty_struct *tty);  static int oti6858_tiocmset(struct tty_struct *tty,  				unsigned int set, unsigned int clear); +static int oti6858_tiocmiwait(struct tty_struct *tty, unsigned long arg);  static int oti6858_port_probe(struct usb_serial_port *port);  static int oti6858_port_remove(struct usb_serial_port *port); @@ -150,11 +149,11 @@ static struct usb_serial_driver oti6858_device = {  	.open =			oti6858_open,  	.close =		oti6858_close,  	.write =		oti6858_write, -	.ioctl =		oti6858_ioctl,  	.set_termios =		oti6858_set_termios,  	.init_termios = 	oti6858_init_termios,  	.tiocmget =		oti6858_tiocmget,  	.tiocmset =		oti6858_tiocmset, +	.tiocmiwait =		oti6858_tiocmiwait,  	.read_bulk_callback =	oti6858_read_bulk_callback,  	.read_int_callback =	oti6858_read_int_callback,  	.write_bulk_callback =	oti6858_write_bulk_callback, @@ -188,7 +187,6 @@ struct oti6858_private {  	u8 setup_done;  	struct delayed_work delayed_setup_work; -	wait_queue_head_t intr_wait;  	struct usb_serial_port *port;   /* USB port with which associated */  }; @@ -339,7 +337,6 @@ static int oti6858_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->intr_wait);  	priv->port = port;  	INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);  	INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); @@ -652,8 +649,9 @@ static int oti6858_tiocmget(struct tty_struct *tty)  	return result;  } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +static int oti6858_tiocmiwait(struct tty_struct *tty, unsigned long arg)  { +	struct usb_serial_port *port = tty->driver_data;  	struct oti6858_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	unsigned int prev, status; @@ -664,11 +662,15 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	spin_unlock_irqrestore(&priv->lock, flags);  	while (1) { -		wait_event_interruptible(priv->intr_wait, +		wait_event_interruptible(port->port.delta_msr_wait, +					port->serial->disconnected ||  					priv->status.pin_state != prev);  		if (signal_pending(current))  			return -ERESTARTSYS; +		if (port->serial->disconnected) +			return -EIO; +  		spin_lock_irqsave(&priv->lock, flags);  		status = priv->status.pin_state & PIN_MASK;  		spin_unlock_irqrestore(&priv->lock, flags); @@ -687,24 +689,6 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	return 0;  } -static int oti6858_ioctl(struct tty_struct *tty, -			unsigned int cmd, unsigned long arg) -{ -	struct usb_serial_port *port = tty->driver_data; - -	dev_dbg(&port->dev, "%s(cmd = 0x%04x, arg = 0x%08lx)\n", __func__, cmd, arg); - -	switch (cmd) { -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s(): TIOCMIWAIT\n", __func__); -		return wait_modem_info(port, arg); -	default: -		dev_dbg(&port->dev, "%s(): 0x%04x not supported\n", __func__, cmd); -		break; -	} -	return -ENOIOCTLCMD; -} -  static void oti6858_read_int_callback(struct urb *urb)  {  	struct usb_serial_port *port =  urb->context; @@ -763,7 +747,7 @@ static void oti6858_read_int_callback(struct urb *urb)  		if (!priv->transient) {  			if (xs->pin_state != priv->status.pin_state) -				wake_up_interruptible(&priv->intr_wait); +				wake_up_interruptible(&port->port.delta_msr_wait);  			memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);  		} diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 54adc9125e5..7151659367a 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -139,7 +139,6 @@ struct pl2303_serial_private {  struct pl2303_private {  	spinlock_t lock; -	wait_queue_head_t delta_msr_wait;  	u8 line_control;  	u8 line_status;  }; @@ -150,7 +149,7 @@ static int pl2303_vendor_read(__u16 value, __u16 index,  	int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),  			VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE,  			value, index, buf, 1, 100); -	dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x  %d - %x\n", +	dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x  %d - %x\n",  		VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, value, index,  		res, buf[0]);  	return res; @@ -162,7 +161,7 @@ static int pl2303_vendor_write(__u16 value, __u16 index,  	int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),  			VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE,  			value, index, NULL, 0, 100); -	dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x  %d\n", +	dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x  %d\n",  		VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, value, index,  		res);  	return res; @@ -233,7 +232,6 @@ static int pl2303_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->delta_msr_wait);  	usb_set_serial_port_data(port, priv); @@ -250,14 +248,15 @@ static int pl2303_port_remove(struct usb_serial_port *port)  	return 0;  } -static int set_control_lines(struct usb_device *dev, u8 value) +static int pl2303_set_control_lines(struct usb_serial_port *port, u8 value)  { +	struct usb_device *dev = port->serial->dev;  	int retval;  	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),  				 SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,  				 value, 0, NULL, 0, 100); -	dev_dbg(&dev->dev, "%s - value = %d, retval = %d\n", __func__, +	dev_dbg(&port->dev, "%s - value = %d, retval = %d\n", __func__,  		value, retval);  	return retval;  } @@ -439,7 +438,7 @@ static void pl2303_set_termios(struct tty_struct *tty,  	if (control != priv->line_control) {  		control = priv->line_control;  		spin_unlock_irqrestore(&priv->lock, flags); -		set_control_lines(serial->dev, control); +		pl2303_set_control_lines(port, control);  	} else {  		spin_unlock_irqrestore(&priv->lock, flags);  	} @@ -482,7 +481,7 @@ static void pl2303_dtr_rts(struct usb_serial_port *port, int on)  		priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);  	control = priv->line_control;  	spin_unlock_irqrestore(&priv->lock, flags); -	set_control_lines(port->serial->dev, control); +	pl2303_set_control_lines(port, control);  }  static void pl2303_close(struct usb_serial_port *port) @@ -532,7 +531,6 @@ static int pl2303_tiocmset(struct tty_struct *tty,  			   unsigned int set, unsigned int clear)  {  	struct usb_serial_port *port = tty->driver_data; -	struct usb_serial *serial = port->serial;  	struct pl2303_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	u8 control; @@ -550,14 +548,11 @@ static int pl2303_tiocmset(struct tty_struct *tty,  	control = priv->line_control;  	spin_unlock_irqrestore(&priv->lock, flags); -	mutex_lock(&serial->disc_mutex); -	if (!serial->disconnected) -		ret = set_control_lines(serial->dev, control); -	else -		ret = -ENODEV; -	mutex_unlock(&serial->disc_mutex); +	ret = pl2303_set_control_lines(port, control); +	if (ret) +		return usb_translate_errors(ret); -	return ret; +	return 0;  }  static int pl2303_tiocmget(struct tty_struct *tty) @@ -594,8 +589,9 @@ static int pl2303_carrier_raised(struct usb_serial_port *port)  	return 0;  } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +static int pl2303_tiocmiwait(struct tty_struct *tty, unsigned long arg)  { +	struct usb_serial_port *port = tty->driver_data;  	struct pl2303_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	unsigned int prevstatus; @@ -607,11 +603,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)  	spin_unlock_irqrestore(&priv->lock, flags);  	while (1) { -		interruptible_sleep_on(&priv->delta_msr_wait); +		interruptible_sleep_on(&port->port.delta_msr_wait);  		/* see if a signal did it */  		if (signal_pending(current))  			return -ERESTARTSYS; +		if (port->serial->disconnected) +			return -EIO; +  		spin_lock_irqsave(&priv->lock, flags);  		status = priv->line_status;  		spin_unlock_irqrestore(&priv->lock, flags); @@ -650,10 +649,6 @@ static int pl2303_ioctl(struct tty_struct *tty,  			return -EFAULT;  		return 0; - -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__); -		return wait_modem_info(port, arg);  	default:  		dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd);  		break; @@ -719,7 +714,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port,  	spin_unlock_irqrestore(&priv->lock, flags);  	if (priv->line_status & UART_BREAK_ERROR)  		usb_serial_handle_break(port); -	wake_up_interruptible(&priv->delta_msr_wait); +	wake_up_interruptible(&port->port.delta_msr_wait);  	tty = tty_port_tty_get(&port->port);  	if (!tty) @@ -783,7 +778,7 @@ static void pl2303_process_read_urb(struct urb *urb)  	line_status = priv->line_status;  	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;  	spin_unlock_irqrestore(&priv->lock, flags); -	wake_up_interruptible(&priv->delta_msr_wait); +	wake_up_interruptible(&port->port.delta_msr_wait);  	if (!urb->actual_length)  		return; @@ -834,6 +829,7 @@ static struct usb_serial_driver pl2303_device = {  	.set_termios =		pl2303_set_termios,  	.tiocmget =		pl2303_tiocmget,  	.tiocmset =		pl2303_tiocmset, +	.tiocmiwait =		pl2303_tiocmiwait,  	.process_read_urb =	pl2303_process_read_urb,  	.read_int_callback =	pl2303_read_int_callback,  	.attach =		pl2303_startup, diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index d643a4d4d77..02b0803425c 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -116,7 +116,6 @@ struct qt2_serial_private {  };  struct qt2_port_private { -	bool is_open;  	u8   device_port;  	spinlock_t urb_lock; @@ -128,9 +127,6 @@ struct qt2_port_private {  	u8          shadowLSR;  	u8          shadowMSR; -	wait_queue_head_t   delta_msr_wait; /* Used for TIOCMIWAIT */ -	struct async_icount icount; -  	struct usb_serial_port *port;  }; @@ -398,7 +394,6 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port)  		return status;  	} -	port_priv->is_open = true;  	port_priv->device_port = (u8) device_port;  	if (tty) @@ -418,19 +413,11 @@ static void qt2_close(struct usb_serial_port *port)  	serial = port->serial;  	port_priv = usb_get_serial_port_data(port); -	port_priv->is_open = false; -  	spin_lock_irqsave(&port_priv->urb_lock, flags);  	usb_kill_urb(port_priv->write_urb);  	port_priv->urb_in_use = false;  	spin_unlock_irqrestore(&port_priv->urb_lock, flags); -	mutex_lock(&port->serial->disc_mutex); -	if (port->serial->disconnected) { -		mutex_unlock(&port->serial->disc_mutex); -		return; -	} -  	/* flush the port transmit buffer */  	i = usb_control_msg(serial->dev,  			    usb_rcvctrlpipe(serial->dev, 0), @@ -461,8 +448,6 @@ static void qt2_close(struct usb_serial_port *port)  	if (i < 0)  		dev_err(&port->dev, "%s - close port failed %i\n",  			__func__, i); - -	mutex_unlock(&port->serial->disc_mutex);  }  static void qt2_disconnect(struct usb_serial *serial) @@ -495,67 +480,6 @@ static int get_serial_info(struct usb_serial_port *port,  	return 0;  } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) -{ -	struct qt2_port_private *priv = usb_get_serial_port_data(port); -	struct async_icount prev, cur; -	unsigned long flags; - -	spin_lock_irqsave(&priv->lock, flags); -	prev = priv->icount; -	spin_unlock_irqrestore(&priv->lock, flags); - -	while (1) { -		wait_event_interruptible(priv->delta_msr_wait, -					 ((priv->icount.rng != prev.rng) || -					  (priv->icount.dsr != prev.dsr) || -					  (priv->icount.dcd != prev.dcd) || -					  (priv->icount.cts != prev.cts))); - -		if (signal_pending(current)) -			return -ERESTARTSYS; - -		spin_lock_irqsave(&priv->lock, flags); -		cur = priv->icount; -		spin_unlock_irqrestore(&priv->lock, flags); - -		if ((prev.rng == cur.rng) && -		    (prev.dsr == cur.dsr) && -		    (prev.dcd == cur.dcd) && -		    (prev.cts == cur.cts)) -			return -EIO; - -		if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) || -		    (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) || -		    (arg & TIOCM_CD && (prev.dcd != cur.dcd)) || -		    (arg & TIOCM_CTS && (prev.cts != cur.cts))) -			return 0; -	} -	return 0; -} - -static int qt2_get_icount(struct tty_struct *tty, -			  struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct qt2_port_private *priv = usb_get_serial_port_data(port); -	struct async_icount cnow = priv->icount; - -	icount->cts = cnow.cts; -	icount->dsr = cnow.dsr; -	icount->rng = cnow.rng; -	icount->dcd = cnow.dcd; -	icount->rx = cnow.rx; -	icount->tx = cnow.tx; -	icount->frame = cnow.frame; -	icount->overrun = cnow.overrun; -	icount->parity = cnow.parity; -	icount->brk = cnow.brk; -	icount->buf_overrun = cnow.buf_overrun; - -	return 0; -} -  static int qt2_ioctl(struct tty_struct *tty,  		     unsigned int cmd, unsigned long arg)  { @@ -565,10 +489,6 @@ static int qt2_ioctl(struct tty_struct *tty,  	case TIOCGSERIAL:  		return get_serial_info(port,  				       (struct serial_struct __user *)arg); - -	case TIOCMIWAIT: -		return wait_modem_info(port, arg); -  	default:  		break;  	} @@ -661,9 +581,7 @@ void qt2_process_read_urb(struct urb *urb)  						 __func__);  					break;  				} - -				if (port_priv->is_open) -					tty_flip_buffer_push(&port->port); +				tty_flip_buffer_push(&port->port);  				newport = *(ch + 3); @@ -706,8 +624,7 @@ void qt2_process_read_urb(struct urb *urb)  		tty_insert_flip_string(&port->port, ch, 1);  	} -	if (port_priv->is_open) -		tty_flip_buffer_push(&port->port); +	tty_flip_buffer_push(&port->port);  }  static void qt2_write_bulk_callback(struct urb *urb) @@ -827,7 +744,6 @@ static int qt2_port_probe(struct usb_serial_port *port)  	spin_lock_init(&port_priv->lock);  	spin_lock_init(&port_priv->urb_lock); -	init_waitqueue_head(&port_priv->delta_msr_wait);  	port_priv->port = port;  	port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); @@ -908,12 +824,6 @@ static void qt2_break_ctl(struct tty_struct *tty, int break_state)  	port_priv = usb_get_serial_port_data(port); -	if (!port_priv->is_open) { -		dev_err(&port->dev, -			"%s - port is not open\n", __func__); -		return; -	} -  	val = (break_state == -1) ? 1 : 0;  	status = qt2_control_msg(port->serial->dev, QT2_BREAK_CONTROL, @@ -959,18 +869,15 @@ static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)  	if (newMSR & UART_MSR_ANY_DELTA) {  		/* update input line counters */  		if (newMSR & UART_MSR_DCTS) -			port_priv->icount.cts++; - +			port->icount.cts++;  		if (newMSR & UART_MSR_DDSR) -			port_priv->icount.dsr++; - +			port->icount.dsr++;  		if (newMSR & UART_MSR_DDCD) -			port_priv->icount.dcd++; - +			port->icount.dcd++;  		if (newMSR & UART_MSR_TERI) -			port_priv->icount.rng++; +			port->icount.rng++; -		wake_up_interruptible(&port_priv->delta_msr_wait); +		wake_up_interruptible(&port->port.delta_msr_wait);  	}  } @@ -990,7 +897,7 @@ static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch)  	port_priv->shadowLSR = newLSR;  	spin_unlock_irqrestore(&port_priv->lock, flags); -	icount = &port_priv->icount; +	icount = &port->icount;  	if (newLSR & UART_LSR_BRK_ERROR_BITS) { @@ -1100,7 +1007,8 @@ static struct usb_serial_driver qt2_device = {  	.break_ctl           = qt2_break_ctl,  	.tiocmget            = qt2_tiocmget,  	.tiocmset            = qt2_tiocmset, -	.get_icount	     = qt2_get_icount, +	.tiocmiwait          = usb_serial_generic_tiocmiwait, +	.get_icount	     = usb_serial_generic_get_icount,  	.ioctl               = qt2_ioctl,  	.set_termios         = qt2_set_termios,  }; diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index c13f6e74774..8894665cd61 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -628,7 +628,6 @@ static void sierra_instat_callback(struct urb *urb)  			unsigned char signals = *((unsigned char *)  					urb->transfer_buffer +  					sizeof(struct usb_ctrlrequest)); -			struct tty_struct *tty;  			dev_dbg(&port->dev, "%s: signal x%x\n", __func__,  				signals); @@ -639,11 +638,8 @@ static void sierra_instat_callback(struct urb *urb)  			portdata->dsr_state = ((signals & 0x02) ? 1 : 0);  			portdata->ri_state = ((signals & 0x08) ? 1 : 0); -			tty = tty_port_tty_get(&port->port); -			if (tty && !C_CLOCAL(tty) && -					old_dcd_state && !portdata->dcd_state) -				tty_hangup(tty); -			tty_kref_put(tty); +			if (old_dcd_state && !portdata->dcd_state) +				tty_port_tty_hangup(&port->port, true);  		} else {  			dev_dbg(&port->dev, "%s: type %x req %x\n",  				__func__, req_pkt->bRequestType, @@ -778,30 +774,25 @@ static void sierra_close(struct usb_serial_port *port)  	portdata->rts_state = 0;  	portdata->dtr_state = 0; -	if (serial->dev) { -		mutex_lock(&serial->disc_mutex); -		if (!serial->disconnected) { -			serial->interface->needs_remote_wakeup = 0; -			/* odd error handling due to pm counters */ -			if (!usb_autopm_get_interface(serial->interface)) -				sierra_send_setup(port); -			else -				usb_autopm_get_interface_no_resume(serial->interface); -				 -		} -		mutex_unlock(&serial->disc_mutex); -		spin_lock_irq(&intfdata->susp_lock); -		portdata->opened = 0; -		spin_unlock_irq(&intfdata->susp_lock); +	mutex_lock(&serial->disc_mutex); +	if (!serial->disconnected) { +		serial->interface->needs_remote_wakeup = 0; +		/* odd error handling due to pm counters */ +		if (!usb_autopm_get_interface(serial->interface)) +			sierra_send_setup(port); +		else +			usb_autopm_get_interface_no_resume(serial->interface); +	} +	mutex_unlock(&serial->disc_mutex); +	spin_lock_irq(&intfdata->susp_lock); +	portdata->opened = 0; +	spin_unlock_irq(&intfdata->susp_lock); -		/* Stop reading urbs */ -		sierra_stop_rx_urbs(port); -		/* .. and release them */ -		for (i = 0; i < portdata->num_in_urbs; i++) { -			sierra_release_urb(portdata->in_urbs[i]); -			portdata->in_urbs[i] = NULL; -		} +	sierra_stop_rx_urbs(port); +	for (i = 0; i < portdata->num_in_urbs; i++) { +		sierra_release_urb(portdata->in_urbs[i]); +		portdata->in_urbs[i] = NULL;  	}  } diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 91ff8e3bddb..cf3df793c2b 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -1,7 +1,7 @@  /*   * spcp8x5 USB to serial adaptor driver   * - * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com) + * Copyright (C) 2010-2013 Johan Hovold (jhovold@gmail.com)   * Copyright (C) 2006 Linxb (xubin.lin@worldplus.com.cn)   * Copyright (C) 2006 S1 Corp.   * @@ -13,8 +13,6 @@   *	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 <linux/kernel.h>  #include <linux/errno.h> @@ -28,7 +26,10 @@  #include <linux/usb.h>  #include <linux/usb/serial.h> -#define DRIVER_DESC 	"SPCP8x5 USB to serial adaptor driver" +#define DRIVER_DESC	"SPCP8x5 USB to serial adaptor driver" + +#define SPCP825_QUIRK_NO_UART_STATUS	0x01 +#define SPCP825_QUIRK_NO_WORK_MODE	0x02  #define SPCP8x5_007_VID		0x04FC  #define SPCP8x5_007_PID		0x0201 @@ -46,13 +47,15 @@ static const struct usb_device_id id_table[] = {  	{ USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)},  	{ USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)},  	{ USB_DEVICE(SPCP8x5_008_VID, SPCP8x5_008_PID)}, -	{ USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID)}, +	{ USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID), +	  .driver_info = SPCP825_QUIRK_NO_UART_STATUS | +				SPCP825_QUIRK_NO_WORK_MODE },  	{ }					/* Terminating entry */  };  MODULE_DEVICE_TABLE(usb, id_table);  struct spcp8x5_usb_ctrl_arg { -	u8 	type; +	u8	type;  	u8	cmd;  	u8	cmd_type;  	u16	value; @@ -138,51 +141,33 @@ struct spcp8x5_usb_ctrl_arg {  #define UART_OVERRUN_ERROR		0x40  #define UART_CTS			0x80 -enum spcp8x5_type { -	SPCP825_007_TYPE, -	SPCP825_008_TYPE, -	SPCP825_PHILIP_TYPE, -	SPCP825_INTERMATIC_TYPE, -	SPCP835_TYPE, -}; -  struct spcp8x5_private { -	spinlock_t 	lock; -	enum spcp8x5_type	type; -	wait_queue_head_t	delta_msr_wait; -	u8 			line_control; -	u8 			line_status; +	unsigned		quirks; +	spinlock_t		lock; +	u8			line_control;  }; +static int spcp8x5_probe(struct usb_serial *serial, +						const struct usb_device_id *id) +{ +	usb_set_serial_data(serial, (void *)id); + +	return 0; +} +  static int spcp8x5_port_probe(struct usb_serial_port *port)  { -	struct usb_serial *serial = port->serial; +	const struct usb_device_id *id = usb_get_serial_data(port->serial);  	struct spcp8x5_private *priv; -	enum spcp8x5_type type = SPCP825_007_TYPE; -	u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); - -	if (product == 0x0201) -		type = SPCP825_007_TYPE; -	else if (product == 0x0231) -		type = SPCP835_TYPE; -	else if (product == 0x0235) -		type = SPCP825_008_TYPE; -	else if (product == 0x0204) -		type = SPCP825_INTERMATIC_TYPE; -	else if (product == 0x0471 && -		 serial->dev->descriptor.idVendor == cpu_to_le16(0x081e)) -		type = SPCP825_PHILIP_TYPE; -	dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);  	priv = kzalloc(sizeof(*priv), GFP_KERNEL);  	if (!priv)  		return -ENOMEM;  	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->delta_msr_wait); -	priv->type = type; +	priv->quirks = id->driver_info; -	usb_set_serial_port_data(port , priv); +	usb_set_serial_port_data(port, priv);  	return 0;  } @@ -197,86 +182,79 @@ static int spcp8x5_port_remove(struct usb_serial_port *port)  	return 0;  } -/* set the modem control line of the device. - * NOTE spcp825-007 not supported this */ -static int spcp8x5_set_ctrlLine(struct usb_device *dev, u8 value, -				enum spcp8x5_type type) +static int spcp8x5_set_ctrl_line(struct usb_serial_port *port, u8 mcr)  { +	struct spcp8x5_private *priv = usb_get_serial_port_data(port); +	struct usb_device *dev = port->serial->dev;  	int retval; -	u8 mcr = 0 ; -	if (type == SPCP825_007_TYPE) +	if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)  		return -EPERM; -	mcr = (unsigned short)value;  	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),  				 SET_UART_STATUS_TYPE, SET_UART_STATUS,  				 mcr, 0x04, NULL, 0, 100); -	if (retval != 0) -		dev_dbg(&dev->dev, "usb_control_msg return %#x\n", retval); +	if (retval != 0) { +		dev_err(&port->dev, "failed to set control lines: %d\n", +								retval); +	}  	return retval;  } -/* get the modem status register of the device - * NOTE spcp825-007 not supported this */ -static int spcp8x5_get_msr(struct usb_device *dev, u8 *status, -			   enum spcp8x5_type type) +static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status)  { -	u8 *status_buffer; +	struct spcp8x5_private *priv = usb_get_serial_port_data(port); +	struct usb_device *dev = port->serial->dev; +	u8 *buf;  	int ret; -	/* I return Permited not support here but seem inval device -	 * is more fix */ -	if (type == SPCP825_007_TYPE) +	if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)  		return -EPERM; -	if (status == NULL) -		return -EINVAL; -	status_buffer = kmalloc(1, GFP_KERNEL); -	if (!status_buffer) +	buf = kzalloc(1, GFP_KERNEL); +	if (!buf)  		return -ENOMEM; -	status_buffer[0] = status[0];  	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),  			      GET_UART_STATUS, GET_UART_STATUS_TYPE, -			      0, GET_UART_STATUS_MSR, status_buffer, 1, 100); +			      0, GET_UART_STATUS_MSR, buf, 1, 100);  	if (ret < 0) -		dev_dbg(&dev->dev, "Get MSR = 0x%p failed (error = %d)", -			status_buffer, ret); +		dev_err(&port->dev, "failed to get modem status: %d", ret); -	dev_dbg(&dev->dev, "0xc0:0x22:0:6  %d - 0x%p ", ret, status_buffer); -	status[0] = status_buffer[0]; -	kfree(status_buffer); +	dev_dbg(&port->dev, "0xc0:0x22:0:6  %d - 0x02%x", ret, *buf); +	*status = *buf; +	kfree(buf);  	return ret;  } -/* select the work mode. - * NOTE this function not supported by spcp825-007 */ -static void spcp8x5_set_workMode(struct usb_device *dev, u16 value, -				 u16 index, enum spcp8x5_type type) +static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value, +								 u16 index)  { +	struct spcp8x5_private *priv = usb_get_serial_port_data(port); +	struct usb_device *dev = port->serial->dev;  	int ret; -	/* I return Permited not support here but seem inval device -	 * is more fix */ -	if (type == SPCP825_007_TYPE) +	if (priv->quirks & SPCP825_QUIRK_NO_WORK_MODE)  		return;  	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),  			      SET_WORKING_MODE_TYPE, SET_WORKING_MODE,  			      value, index, NULL, 0, 100); -	dev_dbg(&dev->dev, "value = %#x , index = %#x\n", value, index); +	dev_dbg(&port->dev, "value = %#x , index = %#x\n", value, index);  	if (ret < 0) -		dev_dbg(&dev->dev, -			"RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret); +		dev_err(&port->dev, "failed to set work mode: %d\n", ret);  }  static int spcp8x5_carrier_raised(struct usb_serial_port *port)  { -	struct spcp8x5_private *priv = usb_get_serial_port_data(port); -	if (priv->line_status & MSR_STATUS_LINE_DCD) +	u8 msr; +	int ret; + +	ret = spcp8x5_get_msr(port, &msr); +	if (ret || msr & MSR_STATUS_LINE_DCD)  		return 1; +  	return 0;  } @@ -295,20 +273,17 @@ static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on)  						| MCR_CONTROL_LINE_RTS);  	control = priv->line_control;  	spin_unlock_irqrestore(&priv->lock, flags); -	spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); +	spcp8x5_set_ctrl_line(port, control);  }  static void spcp8x5_init_termios(struct tty_struct *tty)  { -	/* for the 1st time call this function */  	tty->termios = tty_std_termios;  	tty->termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;  	tty->termios.c_ispeed = 115200;  	tty->termios.c_ospeed = 115200;  } -/* set the serial param for transfer. we should check if we really need to - * transfer. if we set flow control we should do this too. */  static void spcp8x5_set_termios(struct tty_struct *tty,  		struct usb_serial_port *port, struct ktermios *old_termios)  { @@ -323,7 +298,6 @@ static void spcp8x5_set_termios(struct tty_struct *tty,  	int i;  	u8 control; -  	/* check that they really want us to change something */  	if (!tty_termios_hw_change(&tty->termios, old_termios))  		return; @@ -339,7 +313,7 @@ static void spcp8x5_set_termios(struct tty_struct *tty,  	if (control != priv->line_control) {  		control = priv->line_control;  		spin_unlock_irqrestore(&priv->lock, flags); -		spcp8x5_set_ctrlLine(serial->dev, control , priv->type); +		spcp8x5_set_ctrl_line(port, control);  	} else {  		spin_unlock_irqrestore(&priv->lock, flags);  	} @@ -399,9 +373,9 @@ static void spcp8x5_set_termios(struct tty_struct *tty,  	if (cflag & PARENB) {  		buf[1] |= (cflag & PARODD) ?  		SET_UART_FORMAT_PAR_ODD : SET_UART_FORMAT_PAR_EVEN ; -	} else +	} else {  		buf[1] |= SET_UART_FORMAT_PAR_NONE; - +	}  	uartdata = buf[0] | buf[1]<<8;  	i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), @@ -414,22 +388,16 @@ static void spcp8x5_set_termios(struct tty_struct *tty,  	if (cflag & CRTSCTS) {  		/* enable hardware flow control */ -		spcp8x5_set_workMode(serial->dev, 0x000a, -				     SET_WORKING_MODE_U2C, priv->type); +		spcp8x5_set_work_mode(port, 0x000a, SET_WORKING_MODE_U2C);  	}  } -/* open the serial port. do some usb system call. set termios and get the line - * status of the device. */  static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)  {  	struct ktermios tmp_termios;  	struct usb_serial *serial = port->serial;  	struct spcp8x5_private *priv = usb_get_serial_port_data(port);  	int ret; -	unsigned long flags; -	u8 status = 0x30; -	/* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */  	usb_clear_halt(serial->dev, port->write_urb->pipe);  	usb_clear_halt(serial->dev, port->read_urb->pipe); @@ -440,139 +408,16 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)  	if (ret)  		return ret; -	spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type); +	spcp8x5_set_ctrl_line(port, priv->line_control); -	/* Setup termios */  	if (tty)  		spcp8x5_set_termios(tty, port, &tmp_termios); -	spcp8x5_get_msr(serial->dev, &status, priv->type); - -	/* may be we should update uart status here but now we did not do */ -	spin_lock_irqsave(&priv->lock, flags); -	priv->line_status = status & 0xf0 ; -	spin_unlock_irqrestore(&priv->lock, flags); -  	port->port.drain_delay = 256;  	return usb_serial_generic_open(tty, port);  } -static void spcp8x5_process_read_urb(struct urb *urb) -{ -	struct usb_serial_port *port = urb->context; -	struct spcp8x5_private *priv = usb_get_serial_port_data(port); -	unsigned char *data = urb->transfer_buffer; -	unsigned long flags; -	u8 status; -	char tty_flag; - -	/* get tty_flag from status */ -	tty_flag = TTY_NORMAL; - -	spin_lock_irqsave(&priv->lock, flags); -	status = priv->line_status; -	priv->line_status &= ~UART_STATE_TRANSIENT_MASK; -	spin_unlock_irqrestore(&priv->lock, flags); -	/* wake up the wait for termios */ -	wake_up_interruptible(&priv->delta_msr_wait); - -	if (!urb->actual_length) -		return; - - -	if (status & UART_STATE_TRANSIENT_MASK) { -		/* break takes precedence over parity, which takes precedence -		 * over framing errors */ -		if (status & UART_BREAK_ERROR) -			tty_flag = TTY_BREAK; -		else if (status & UART_PARITY_ERROR) -			tty_flag = TTY_PARITY; -		else if (status & UART_FRAME_ERROR) -			tty_flag = TTY_FRAME; -		dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag); - -		/* overrun is special, not associated with a char */ -		if (status & UART_OVERRUN_ERROR) -			tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); - -		if (status & UART_DCD) { -			struct tty_struct *tty = tty_port_tty_get(&port->port); -			if (tty) { -				usb_serial_handle_dcd_change(port, tty, -				       priv->line_status & MSR_STATUS_LINE_DCD); -				tty_kref_put(tty); -			} -		} -	} - -	tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag, -							urb->actual_length); -	tty_flip_buffer_push(&port->port); -} - -static int spcp8x5_wait_modem_info(struct usb_serial_port *port, -				   unsigned int arg) -{ -	struct spcp8x5_private *priv = usb_get_serial_port_data(port); -	unsigned long flags; -	unsigned int prevstatus; -	unsigned int status; -	unsigned int changed; - -	spin_lock_irqsave(&priv->lock, flags); -	prevstatus = priv->line_status; -	spin_unlock_irqrestore(&priv->lock, flags); - -	while (1) { -		/* wake up in bulk read */ -		interruptible_sleep_on(&priv->delta_msr_wait); - -		/* see if a signal did it */ -		if (signal_pending(current)) -			return -ERESTARTSYS; - -		spin_lock_irqsave(&priv->lock, flags); -		status = priv->line_status; -		spin_unlock_irqrestore(&priv->lock, flags); - -		changed = prevstatus^status; - -		if (((arg & TIOCM_RNG) && (changed & MSR_STATUS_LINE_RI)) || -		    ((arg & TIOCM_DSR) && (changed & MSR_STATUS_LINE_DSR)) || -		    ((arg & TIOCM_CD)  && (changed & MSR_STATUS_LINE_DCD)) || -		    ((arg & TIOCM_CTS) && (changed & MSR_STATUS_LINE_CTS))) -			return 0; - -		prevstatus = status; -	} -	/* NOTREACHED */ -	return 0; -} - -static int spcp8x5_ioctl(struct tty_struct *tty, -			 unsigned int cmd, unsigned long arg) -{ -	struct usb_serial_port *port = tty->driver_data; - -	dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__, -		port->number, cmd); - -	switch (cmd) { -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, -			port->number); -		return spcp8x5_wait_modem_info(port, arg); - -	default: -		dev_dbg(&port->dev, "%s not supported = 0x%04x", __func__, -			cmd); -		break; -	} - -	return -ENOIOCTLCMD; -} -  static int spcp8x5_tiocmset(struct tty_struct *tty,  			    unsigned int set, unsigned int clear)  { @@ -593,7 +438,7 @@ static int spcp8x5_tiocmset(struct tty_struct *tty,  	control = priv->line_control;  	spin_unlock_irqrestore(&priv->lock, flags); -	return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); +	return spcp8x5_set_ctrl_line(port, control);  }  static int spcp8x5_tiocmget(struct tty_struct *tty) @@ -602,12 +447,15 @@ static int spcp8x5_tiocmget(struct tty_struct *tty)  	struct spcp8x5_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	unsigned int mcr; -	unsigned int status; +	u8 status;  	unsigned int result; +	result = spcp8x5_get_msr(port, &status); +	if (result) +		return result; +  	spin_lock_irqsave(&priv->lock, flags);  	mcr = priv->line_control; -	status = priv->line_status;  	spin_unlock_irqrestore(&priv->lock, flags);  	result = ((mcr & MCR_DTR)			? TIOCM_DTR : 0) @@ -620,7 +468,6 @@ static int spcp8x5_tiocmget(struct tty_struct *tty)  	return result;  } -/* All of the device info needed for the spcp8x5 SIO serial converter */  static struct usb_serial_driver spcp8x5_device = {  	.driver = {  		.owner =	THIS_MODULE, @@ -628,17 +475,16 @@ static struct usb_serial_driver spcp8x5_device = {  	},  	.id_table		= id_table,  	.num_ports		= 1, -	.open 			= spcp8x5_open, +	.open			= spcp8x5_open,  	.dtr_rts		= spcp8x5_dtr_rts,  	.carrier_raised		= spcp8x5_carrier_raised, -	.set_termios 		= spcp8x5_set_termios, +	.set_termios		= spcp8x5_set_termios,  	.init_termios		= spcp8x5_init_termios, -	.ioctl 			= spcp8x5_ioctl, -	.tiocmget 		= spcp8x5_tiocmget, -	.tiocmset 		= spcp8x5_tiocmset, +	.tiocmget		= spcp8x5_tiocmget, +	.tiocmset		= spcp8x5_tiocmset, +	.probe			= spcp8x5_probe,  	.port_probe		= spcp8x5_port_probe,  	.port_remove		= spcp8x5_port_remove, -	.process_read_urb	= spcp8x5_process_read_urb,  };  static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index b57cf841c5b..5b62dbbdf99 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -61,8 +61,6 @@ struct ssu100_port_private {  	spinlock_t status_lock;  	u8 shadowLSR;  	u8 shadowMSR; -	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ -	struct async_icount icount;  };  static inline int ssu100_control_msg(struct usb_device *dev, @@ -316,11 +314,6 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)  	return usb_serial_generic_open(tty, port);  } -static void ssu100_close(struct usb_serial_port *port) -{ -	usb_serial_generic_close(port); -} -  static int get_serial_info(struct usb_serial_port *port,  			   struct serial_struct __user *retinfo)  { @@ -344,69 +337,6 @@ static int get_serial_info(struct usb_serial_port *port,  	return 0;  } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) -{ -	struct ssu100_port_private *priv = usb_get_serial_port_data(port); -	struct async_icount prev, cur; -	unsigned long flags; - -	spin_lock_irqsave(&priv->status_lock, flags); -	prev = priv->icount; -	spin_unlock_irqrestore(&priv->status_lock, flags); - -	while (1) { -		wait_event_interruptible(priv->delta_msr_wait, -					 ((priv->icount.rng != prev.rng) || -					  (priv->icount.dsr != prev.dsr) || -					  (priv->icount.dcd != prev.dcd) || -					  (priv->icount.cts != prev.cts))); - -		if (signal_pending(current)) -			return -ERESTARTSYS; - -		spin_lock_irqsave(&priv->status_lock, flags); -		cur = priv->icount; -		spin_unlock_irqrestore(&priv->status_lock, flags); - -		if ((prev.rng == cur.rng) && -		    (prev.dsr == cur.dsr) && -		    (prev.dcd == cur.dcd) && -		    (prev.cts == cur.cts)) -			return -EIO; - -		if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) || -		    (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) || -		    (arg & TIOCM_CD  && (prev.dcd != cur.dcd)) || -		    (arg & TIOCM_CTS && (prev.cts != cur.cts))) -			return 0; -	} -	return 0; -} - -static int ssu100_get_icount(struct tty_struct *tty, -			struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct ssu100_port_private *priv = usb_get_serial_port_data(port); -	struct async_icount cnow = priv->icount; - -	icount->cts = cnow.cts; -	icount->dsr = cnow.dsr; -	icount->rng = cnow.rng; -	icount->dcd = cnow.dcd; -	icount->rx = cnow.rx; -	icount->tx = cnow.tx; -	icount->frame = cnow.frame; -	icount->overrun = cnow.overrun; -	icount->parity = cnow.parity; -	icount->brk = cnow.brk; -	icount->buf_overrun = cnow.buf_overrun; - -	return 0; -} - - -  static int ssu100_ioctl(struct tty_struct *tty,  		    unsigned int cmd, unsigned long arg)  { @@ -418,10 +348,6 @@ static int ssu100_ioctl(struct tty_struct *tty,  	case TIOCGSERIAL:  		return get_serial_info(port,  				       (struct serial_struct __user *) arg); - -	case TIOCMIWAIT: -		return wait_modem_info(port, arg); -  	default:  		break;  	} @@ -445,7 +371,6 @@ static int ssu100_port_probe(struct usb_serial_port *port)  		return -ENOMEM;  	spin_lock_init(&priv->status_lock); -	init_waitqueue_head(&priv->delta_msr_wait);  	usb_set_serial_port_data(port, priv); @@ -530,14 +455,14 @@ static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)  	if (msr & UART_MSR_ANY_DELTA) {  		/* update input line counters */  		if (msr & UART_MSR_DCTS) -			priv->icount.cts++; +			port->icount.cts++;  		if (msr & UART_MSR_DDSR) -			priv->icount.dsr++; +			port->icount.dsr++;  		if (msr & UART_MSR_DDCD) -			priv->icount.dcd++; +			port->icount.dcd++;  		if (msr & UART_MSR_TERI) -			priv->icount.rng++; -		wake_up_interruptible(&priv->delta_msr_wait); +			port->icount.rng++; +		wake_up_interruptible(&port->port.delta_msr_wait);  	}  } @@ -556,22 +481,22 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,  		/* we always want to update icount, but we only want to  		 * update tty_flag for one case */  		if (lsr & UART_LSR_BI) { -			priv->icount.brk++; +			port->icount.brk++;  			*tty_flag = TTY_BREAK;  			usb_serial_handle_break(port);  		}  		if (lsr & UART_LSR_PE) { -			priv->icount.parity++; +			port->icount.parity++;  			if (*tty_flag == TTY_NORMAL)  				*tty_flag = TTY_PARITY;  		}  		if (lsr & UART_LSR_FE) { -			priv->icount.frame++; +			port->icount.frame++;  			if (*tty_flag == TTY_NORMAL)  				*tty_flag = TTY_FRAME;  		}  		if (lsr & UART_LSR_OE){ -			priv->icount.overrun++; +			port->icount.overrun++;  			if (*tty_flag == TTY_NORMAL)  				*tty_flag = TTY_OVERRUN;  		} @@ -628,7 +553,6 @@ static struct usb_serial_driver ssu100_device = {  	.id_table	     = id_table,  	.num_ports	     = 1,  	.open		     = ssu100_open, -	.close		     = ssu100_close,  	.attach              = ssu100_attach,  	.port_probe          = ssu100_port_probe,  	.port_remove         = ssu100_port_remove, @@ -636,10 +560,10 @@ static struct usb_serial_driver ssu100_device = {  	.process_read_urb    = ssu100_process_read_urb,  	.tiocmget            = ssu100_tiocmget,  	.tiocmset            = ssu100_tiocmset, -	.get_icount	     = ssu100_get_icount, +	.tiocmiwait          = usb_serial_generic_tiocmiwait, +	.get_icount	     = usb_serial_generic_get_icount,  	.ioctl               = ssu100_ioctl,  	.set_termios         = ssu100_set_termios, -	.disconnect          = usb_serial_generic_disconnect,  };  static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index be05e6caf9a..9b1648945e7 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -1,6 +1,7 @@  /*   * Symbol USB barcode to serial driver   * + * Copyright (C) 2013 Johan Hovold <jhovold@gmail.com>   * Copyright (C) 2009 Greg Kroah-Hartman <gregkh@suse.de>   * Copyright (C) 2009 Novell Inc.   * @@ -26,27 +27,17 @@ static const struct usb_device_id id_table[] = {  };  MODULE_DEVICE_TABLE(usb, id_table); -/* This structure holds all of the individual device information */  struct symbol_private { -	struct usb_device *udev; -	struct usb_serial *serial; -	struct usb_serial_port *port; -	unsigned char *int_buffer; -	struct urb *int_urb; -	int buffer_size; -	u8 bInterval; -	u8 int_address;  	spinlock_t lock;	/* protects the following flags */  	bool throttled;  	bool actually_throttled; -	bool rts;  };  static void symbol_int_callback(struct urb *urb)  { -	struct symbol_private *priv = urb->context; +	struct usb_serial_port *port = urb->context; +	struct symbol_private *priv = usb_get_serial_port_data(port);  	unsigned char *data = urb->transfer_buffer; -	struct usb_serial_port *port = priv->port;  	int status = urb->status;  	int result;  	int data_length; @@ -84,7 +75,7 @@ static void symbol_int_callback(struct urb *urb)  		tty_insert_flip_string(&port->port, &data[1], data_length);  		tty_flip_buffer_push(&port->port);  	} else { -		dev_dbg(&priv->udev->dev, +		dev_dbg(&port->dev,  			"Improper amount of data received from the device, "  			"%d bytes", urb->actual_length);  	} @@ -94,12 +85,7 @@ exit:  	/* Continue trying to always read if we should */  	if (!priv->throttled) { -		usb_fill_int_urb(priv->int_urb, priv->udev, -				 usb_rcvintpipe(priv->udev, -				 		priv->int_address), -				 priv->int_buffer, priv->buffer_size, -				 symbol_int_callback, priv, priv->bInterval); -		result = usb_submit_urb(priv->int_urb, GFP_ATOMIC); +		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);  		if (result)  			dev_err(&port->dev,  			    "%s - failed resubmitting read urb, error %d\n", @@ -118,15 +104,10 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)  	spin_lock_irqsave(&priv->lock, flags);  	priv->throttled = false;  	priv->actually_throttled = false; -	priv->port = port;  	spin_unlock_irqrestore(&priv->lock, flags);  	/* Start reading from the device */ -	usb_fill_int_urb(priv->int_urb, priv->udev, -			 usb_rcvintpipe(priv->udev, priv->int_address), -			 priv->int_buffer, priv->buffer_size, -			 symbol_int_callback, priv, priv->bInterval); -	result = usb_submit_urb(priv->int_urb, GFP_KERNEL); +	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);  	if (result)  		dev_err(&port->dev,  			"%s - failed resubmitting read urb, error %d\n", @@ -136,10 +117,7 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)  static void symbol_close(struct usb_serial_port *port)  { -	struct symbol_private *priv = usb_get_serial_data(port->serial); - -	/* shutdown our urbs */ -	usb_kill_urb(priv->int_urb); +	usb_kill_urb(port->interrupt_in_urb);  }  static void symbol_throttle(struct tty_struct *tty) @@ -166,7 +144,7 @@ static void symbol_unthrottle(struct tty_struct *tty)  	spin_unlock_irq(&priv->lock);  	if (was_throttled) { -		result = usb_submit_urb(priv->int_urb, GFP_KERNEL); +		result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);  		if (result)  			dev_err(&port->dev,  				"%s - failed submitting read urb, error %d\n", @@ -176,89 +154,36 @@ static void symbol_unthrottle(struct tty_struct *tty)  static int symbol_startup(struct usb_serial *serial)  { -	struct symbol_private *priv; -	struct usb_host_interface *intf; -	int i; -	int retval = -ENOMEM; -	bool int_in_found = false; - -	/* create our private serial structure */ -	priv = kzalloc(sizeof(*priv), GFP_KERNEL); -	if (priv == NULL) { -		dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__); -		return -ENOMEM; +	if (!serial->num_interrupt_in) { +		dev_err(&serial->dev->dev, "no interrupt-in endpoint\n"); +		return -ENODEV;  	} -	spin_lock_init(&priv->lock); -	priv->serial = serial; -	priv->port = serial->port[0]; -	priv->udev = serial->dev; -	/* find our interrupt endpoint */ -	intf = serial->interface->altsetting; -	for (i = 0; i < intf->desc.bNumEndpoints; ++i) { -		struct usb_endpoint_descriptor *endpoint; - -		endpoint = &intf->endpoint[i].desc; -		if (!usb_endpoint_is_int_in(endpoint)) -			continue; - -		priv->int_urb = usb_alloc_urb(0, GFP_KERNEL); -		if (!priv->int_urb) { -			dev_err(&priv->udev->dev, "out of memory\n"); -			goto error; -		} - -		priv->buffer_size = usb_endpoint_maxp(endpoint) * 2; -		priv->int_buffer = kmalloc(priv->buffer_size, GFP_KERNEL); -		if (!priv->int_buffer) { -			dev_err(&priv->udev->dev, "out of memory\n"); -			goto error; -		} +	return 0; +} -		priv->int_address = endpoint->bEndpointAddress; -		priv->bInterval = endpoint->bInterval; +static int symbol_port_probe(struct usb_serial_port *port) +{ +	struct symbol_private *priv; -		/* set up our int urb */ -		usb_fill_int_urb(priv->int_urb, priv->udev, -				 usb_rcvintpipe(priv->udev, -				 		endpoint->bEndpointAddress), -				 priv->int_buffer, priv->buffer_size, -				 symbol_int_callback, priv, priv->bInterval); +	priv = kzalloc(sizeof(*priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; -		int_in_found = true; -		break; -		} +	spin_lock_init(&priv->lock); -	if (!int_in_found) { -		dev_err(&priv->udev->dev, -			"Error - the proper endpoints were not found!\n"); -		goto error; -	} +	usb_set_serial_port_data(port, priv); -	usb_set_serial_data(serial, priv);  	return 0; - -error: -	usb_free_urb(priv->int_urb); -	kfree(priv->int_buffer); -	kfree(priv); -	return retval;  } -static void symbol_disconnect(struct usb_serial *serial) +static int symbol_port_remove(struct usb_serial_port *port)  { -	struct symbol_private *priv = usb_get_serial_data(serial); +	struct symbol_private *priv = usb_get_serial_port_data(port); -	usb_kill_urb(priv->int_urb); -	usb_free_urb(priv->int_urb); -} - -static void symbol_release(struct usb_serial *serial) -{ -	struct symbol_private *priv = usb_get_serial_data(serial); - -	kfree(priv->int_buffer);  	kfree(priv); + +	return 0;  }  static struct usb_serial_driver symbol_device = { @@ -269,12 +194,13 @@ static struct usb_serial_driver symbol_device = {  	.id_table =		id_table,  	.num_ports =		1,  	.attach =		symbol_startup, +	.port_probe =		symbol_port_probe, +	.port_remove =		symbol_port_remove,  	.open =			symbol_open,  	.close =		symbol_close, -	.disconnect =		symbol_disconnect, -	.release =		symbol_release,  	.throttle = 		symbol_throttle,  	.unthrottle =		symbol_unthrottle, +	.read_int_callback =	symbol_int_callback,  };  static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 39cb9b807c3..cac47aef291 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -67,14 +67,10 @@  struct ti_port {  	int			tp_is_open;  	__u8			tp_msr; -	__u8			tp_lsr;  	__u8			tp_shadow_mcr;  	__u8			tp_uart_mode;	/* 232 or 485 modes */  	unsigned int		tp_uart_base_addr;  	int			tp_flags; -	int			tp_closing_wait;/* in .01 secs */ -	struct async_icount	tp_icount; -	wait_queue_head_t	tp_msr_wait;	/* wait for msr change */  	wait_queue_head_t	tp_write_wait;  	struct ti_device	*tp_tdev;  	struct usb_serial_port	*tp_port; @@ -109,8 +105,6 @@ static void ti_throttle(struct tty_struct *tty);  static void ti_unthrottle(struct tty_struct *tty);  static int ti_ioctl(struct tty_struct *tty,  		unsigned int cmd, unsigned long arg); -static int ti_get_icount(struct tty_struct *tty, -		struct serial_icounter_struct *icount);  static void ti_set_termios(struct tty_struct *tty,  		struct usb_serial_port *port, struct ktermios *old_termios);  static int ti_tiocmget(struct tty_struct *tty); @@ -125,15 +119,13 @@ static void ti_recv(struct usb_serial_port *port, unsigned char *data,  		int length);  static void ti_send(struct ti_port *tport);  static int ti_set_mcr(struct ti_port *tport, unsigned int mcr); -static int ti_get_lsr(struct ti_port *tport); +static int ti_get_lsr(struct ti_port *tport, u8 *lsr);  static int ti_get_serial_info(struct ti_port *tport,  	struct serial_struct __user *ret_arg);  static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,  	struct serial_struct __user *new_arg);  static void ti_handle_new_msr(struct ti_port *tport, __u8 msr); -static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush); -  static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty);  static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty); @@ -236,7 +228,8 @@ static struct usb_serial_driver ti_1port_device = {  	.set_termios		= ti_set_termios,  	.tiocmget		= ti_tiocmget,  	.tiocmset		= ti_tiocmset, -	.get_icount		= ti_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.break_ctl		= ti_break,  	.read_int_callback	= ti_interrupt_callback,  	.read_bulk_callback	= ti_bulk_in_callback, @@ -266,7 +259,8 @@ static struct usb_serial_driver ti_2port_device = {  	.set_termios		= ti_set_termios,  	.tiocmget		= ti_tiocmget,  	.tiocmset		= ti_tiocmset, -	.get_icount		= ti_get_icount, +	.tiocmiwait		= usb_serial_generic_tiocmiwait, +	.get_icount		= usb_serial_generic_get_icount,  	.break_ctl		= ti_break,  	.read_int_callback	= ti_interrupt_callback,  	.read_bulk_callback	= ti_bulk_in_callback, @@ -431,8 +425,7 @@ static int ti_port_probe(struct usb_serial_port *port)  		tport->tp_uart_base_addr = TI_UART1_BASE_ADDR;  	else  		tport->tp_uart_base_addr = TI_UART2_BASE_ADDR; -	tport->tp_closing_wait = closing_wait; -	init_waitqueue_head(&tport->tp_msr_wait); +	port->port.closing_wait = msecs_to_jiffies(10 * closing_wait);  	init_waitqueue_head(&tport->tp_write_wait);  	if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {  		kfree(tport); @@ -482,8 +475,6 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)  	port_number = port->number - port->serial->minor; -	memset(&(tport->tp_icount), 0x00, sizeof(tport->tp_icount)); -  	tport->tp_msr = 0;  	tport->tp_shadow_mcr |= (TI_MCR_RTS | TI_MCR_DTR); @@ -587,6 +578,8 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)  	tport->tp_is_open = 1;  	++tdev->td_open_port_count; +	port->port.drain_delay = 3; +  	goto release_lock;  unlink_int_urb: @@ -606,6 +599,7 @@ static void ti_close(struct usb_serial_port *port)  	int port_number;  	int status;  	int do_unlock; +	unsigned long flags;  	tdev = usb_get_serial_data(port->serial);  	tport = usb_get_serial_port_data(port); @@ -614,11 +608,12 @@ static void ti_close(struct usb_serial_port *port)  	tport->tp_is_open = 0; -	ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 1); -  	usb_kill_urb(port->read_urb);  	usb_kill_urb(port->write_urb);  	tport->tp_write_urb_in_use = 0; +	spin_lock_irqsave(&tport->tp_lock, flags); +	kfifo_reset_out(&tport->write_fifo); +	spin_unlock_irqrestore(&tport->tp_lock, flags);  	port_number = port->number - port->serial->minor; @@ -689,6 +684,8 @@ static int ti_chars_in_buffer(struct tty_struct *tty)  	struct ti_port *tport = usb_get_serial_port_data(port);  	int chars = 0;  	unsigned long flags; +	int ret; +	u8 lsr;  	if (tport == NULL)  		return 0; @@ -697,6 +694,12 @@ static int ti_chars_in_buffer(struct tty_struct *tty)  	chars = kfifo_len(&tport->write_fifo);  	spin_unlock_irqrestore(&tport->tp_lock, flags); +	if (!chars) { +		ret = ti_get_lsr(tport, &lsr); +		if (!ret && !(lsr & TI_LSR_TX_EMPTY)) +			chars = 1; +	} +  	dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);  	return chars;  } @@ -733,38 +736,11 @@ static void ti_unthrottle(struct tty_struct *tty)  	}  } -static int ti_get_icount(struct tty_struct *tty, -		struct serial_icounter_struct *icount) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct ti_port *tport = usb_get_serial_port_data(port); -	struct async_icount cnow = tport->tp_icount; - -	dev_dbg(&port->dev, "%s - TIOCGICOUNT RX=%d, TX=%d\n", __func__, -		cnow.rx, cnow.tx); - -	icount->cts = cnow.cts; -	icount->dsr = cnow.dsr; -	icount->rng = cnow.rng; -	icount->dcd = cnow.dcd; -	icount->rx = cnow.rx; -	icount->tx = cnow.tx; -	icount->frame = cnow.frame; -	icount->overrun = cnow.overrun; -	icount->parity = cnow.parity; -	icount->brk = cnow.brk; -	icount->buf_overrun = cnow.buf_overrun; - -	return 0; -} -  static int ti_ioctl(struct tty_struct *tty,  	unsigned int cmd, unsigned long arg)  {  	struct usb_serial_port *port = tty->driver_data;  	struct ti_port *tport = usb_get_serial_port_data(port); -	struct async_icount cnow; -	struct async_icount cprev;  	dev_dbg(&port->dev, "%s - cmd = 0x%04X\n", __func__, cmd); @@ -780,25 +756,6 @@ static int ti_ioctl(struct tty_struct *tty,  		dev_dbg(&port->dev, "%s - TIOCSSERIAL\n", __func__);  		return ti_set_serial_info(tty, tport,  				(struct serial_struct __user *)arg); -	case TIOCMIWAIT: -		dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); -		cprev = tport->tp_icount; -		while (1) { -			interruptible_sleep_on(&tport->tp_msr_wait); -			if (signal_pending(current)) -				return -ERESTARTSYS; -			cnow = tport->tp_icount; -			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && -			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) -				return -EIO; /* no change => error */ -			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || -			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || -			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) || -			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) -				return 0; -			cprev = cnow; -		} -		break;  	}  	return -ENOIOCTLCMD;  } @@ -1016,8 +973,6 @@ static void ti_break(struct tty_struct *tty, int break_state)  	if (tport == NULL)  		return; -	ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 0); -  	status = ti_write_byte(port, tport->tp_tdev,  		tport->tp_uart_base_addr + TI_UART_OFFSET_LCR,  		TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0); @@ -1154,7 +1109,7 @@ static void ti_bulk_in_callback(struct urb *urb)  		else  			ti_recv(port, urb->transfer_buffer, urb->actual_length);  		spin_lock(&tport->tp_lock); -		tport->tp_icount.rx += urb->actual_length; +		port->icount.rx += urb->actual_length;  		spin_unlock(&tport->tp_lock);  	} @@ -1227,7 +1182,6 @@ static void ti_send(struct ti_port *tport)  {  	int count, result;  	struct usb_serial_port *port = tport->tp_port; -	struct tty_struct *tty = tty_port_tty_get(&port->port);	/* FIXME */  	unsigned long flags;  	spin_lock_irqsave(&tport->tp_lock, flags); @@ -1263,19 +1217,17 @@ static void ti_send(struct ti_port *tport)  		/* TODO: reschedule ti_send */  	} else {  		spin_lock_irqsave(&tport->tp_lock, flags); -		tport->tp_icount.tx += count; +		port->icount.tx += count;  		spin_unlock_irqrestore(&tport->tp_lock, flags);  	}  	/* more room in the buffer for new writes, wakeup */ -	if (tty) -		tty_wakeup(tty); -	tty_kref_put(tty); +	tty_port_tty_wakeup(&port->port); +  	wake_up_interruptible(&tport->tp_write_wait);  	return;  unlock:  	spin_unlock_irqrestore(&tport->tp_lock, flags); -	tty_kref_put(tty);  	return;  } @@ -1298,7 +1250,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr)  } -static int ti_get_lsr(struct ti_port *tport) +static int ti_get_lsr(struct ti_port *tport, u8 *lsr)  {  	int size, status;  	struct ti_device *tdev = tport->tp_tdev; @@ -1324,7 +1276,7 @@ static int ti_get_lsr(struct ti_port *tport)  	dev_dbg(&port->dev, "%s - lsr 0x%02X\n", __func__, data->bLSR); -	tport->tp_lsr = data->bLSR; +	*lsr = data->bLSR;  free_data:  	kfree(data); @@ -1337,10 +1289,15 @@ static int ti_get_serial_info(struct ti_port *tport,  {  	struct usb_serial_port *port = tport->tp_port;  	struct serial_struct ret_serial; +	unsigned cwait;  	if (!ret_arg)  		return -EFAULT; +	cwait = port->port.closing_wait; +	if (cwait != ASYNC_CLOSING_WAIT_NONE) +		cwait = jiffies_to_msecs(cwait) / 10; +  	memset(&ret_serial, 0, sizeof(ret_serial));  	ret_serial.type = PORT_16550A; @@ -1349,7 +1306,7 @@ static int ti_get_serial_info(struct ti_port *tport,  	ret_serial.flags = tport->tp_flags;  	ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE;  	ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800; -	ret_serial.closing_wait = tport->tp_closing_wait; +	ret_serial.closing_wait = cwait;  	if (copy_to_user(ret_arg, &ret_serial, sizeof(*ret_arg)))  		return -EFAULT; @@ -1362,12 +1319,17 @@ static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,  	struct serial_struct __user *new_arg)  {  	struct serial_struct new_serial; +	unsigned cwait;  	if (copy_from_user(&new_serial, new_arg, sizeof(new_serial)))  		return -EFAULT; +	cwait = new_serial.closing_wait; +	if (cwait != ASYNC_CLOSING_WAIT_NONE) +		cwait = msecs_to_jiffies(10 * new_serial.closing_wait); +  	tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS; -	tport->tp_closing_wait = new_serial.closing_wait; +	tport->tp_port->port.closing_wait = cwait;  	return 0;  } @@ -1383,7 +1345,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)  	if (msr & TI_MSR_DELTA_MASK) {  		spin_lock_irqsave(&tport->tp_lock, flags); -		icount = &tport->tp_icount; +		icount = &tport->tp_port->icount;  		if (msr & TI_MSR_DELTA_CTS)  			icount->cts++;  		if (msr & TI_MSR_DELTA_DSR) @@ -1392,7 +1354,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)  			icount->dcd++;  		if (msr & TI_MSR_DELTA_RI)  			icount->rng++; -		wake_up_interruptible(&tport->tp_msr_wait); +		wake_up_interruptible(&tport->tp_port->port.delta_msr_wait);  		spin_unlock_irqrestore(&tport->tp_lock, flags);  	} @@ -1412,56 +1374,6 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)  } -static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush) -{ -	struct ti_device *tdev = tport->tp_tdev; -	struct usb_serial_port *port = tport->tp_port; -	wait_queue_t wait; - -	spin_lock_irq(&tport->tp_lock); - -	/* wait for data to drain from the buffer */ -	tdev->td_urb_error = 0; -	init_waitqueue_entry(&wait, current); -	add_wait_queue(&tport->tp_write_wait, &wait); -	for (;;) { -		set_current_state(TASK_INTERRUPTIBLE); -		if (kfifo_len(&tport->write_fifo) == 0 -		|| timeout == 0 || signal_pending(current) -		|| tdev->td_urb_error -		|| port->serial->disconnected)  /* disconnect */ -			break; -		spin_unlock_irq(&tport->tp_lock); -		timeout = schedule_timeout(timeout); -		spin_lock_irq(&tport->tp_lock); -	} -	set_current_state(TASK_RUNNING); -	remove_wait_queue(&tport->tp_write_wait, &wait); - -	/* flush any remaining data in the buffer */ -	if (flush) -		kfifo_reset_out(&tport->write_fifo); - -	spin_unlock_irq(&tport->tp_lock); - -	mutex_lock(&port->serial->disc_mutex); -	/* wait for data to drain from the device */ -	/* wait for empty tx register, plus 20 ms */ -	timeout += jiffies; -	tport->tp_lsr &= ~TI_LSR_TX_EMPTY; -	while ((long)(jiffies - timeout) < 0 && !signal_pending(current) -	&& !(tport->tp_lsr&TI_LSR_TX_EMPTY) && !tdev->td_urb_error -	&& !port->serial->disconnected) { -		if (ti_get_lsr(tport)) -			break; -		mutex_unlock(&port->serial->disc_mutex); -		msleep_interruptible(20); -		mutex_lock(&port->serial->disc_mutex); -	} -	mutex_unlock(&port->serial->disc_mutex); -} - -  static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty)  {  	unsigned long flags; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index a19ed74d770..cf75beb1251 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1,6 +1,7 @@  /*   * USB Serial Converter driver   * + * Copyright (C) 2009 - 2013 Johan Hovold (jhovold@gmail.com)   * Copyright (C) 1999 - 2012 Greg Kroah-Hartman (greg@kroah.com)   * Copyright (C) 2000 Peter Berger (pberger@brimson.com)   * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com) @@ -14,7 +15,6 @@   *   * See Documentation/usb/usb-serial.txt for more information on using this   * driver - *   */  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -49,7 +49,6 @@     drivers depend on it.  */ -/* initially all NULL */  static struct usb_serial *serial_table[SERIAL_TTY_MINORS];  static DEFINE_MUTEX(table_lock);  static LIST_HEAD(usb_serial_driver_list); @@ -139,7 +138,7 @@ static void destroy_serial(struct kref *kref)  	if (serial->minor != SERIAL_TTY_NO_MINOR)  		return_serial(serial); -	if (serial->attached) +	if (serial->attached && serial->type->release)  		serial->type->release(serial);  	/* Now that nothing is using the ports, they can be freed */ @@ -151,6 +150,7 @@ static void destroy_serial(struct kref *kref)  		}  	} +	usb_put_intf(serial->interface);  	usb_put_dev(serial->dev);  	kfree(serial);  } @@ -224,7 +224,7 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)  	return retval;  } -static int serial_activate(struct tty_port *tport, struct tty_struct *tty) +static int serial_port_activate(struct tty_port *tport, struct tty_struct *tty)  {  	struct usb_serial_port *port =  		container_of(tport, struct usb_serial_port, port); @@ -248,30 +248,27 @@ static int serial_open(struct tty_struct *tty, struct file *filp)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__); +  	return tty_port_open(&port->port, tty, filp);  }  /** - * serial_down - shut down hardware + * serial_port_shutdown - shut down hardware   * @tport: tty port to shut down   * - * Shut down a USB serial port unless it is the console.  We never - * shut down the console hardware as it will always be in use. Serialized - * against activate by the tport mutex and kept to matching open/close pairs + * Shut down a USB serial port. Serialized against activate by the + * tport mutex and kept to matching open/close pairs   * of calls by the ASYNCB_INITIALIZED flag. + * + * Not called if tty is console.   */ -static void serial_down(struct tty_port *tport) +static void serial_port_shutdown(struct tty_port *tport)  {  	struct usb_serial_port *port =  		container_of(tport, struct usb_serial_port, port);  	struct usb_serial_driver *drv = port->serial->type; -	/* -	 * The console is magical.  Do not hang up the console hardware -	 * or there will be tears. -	 */ -	if (port->port.console) -		return; +  	if (drv->close)  		drv->close(port);  } @@ -280,7 +277,8 @@ static void serial_hangup(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__); +  	tty_port_hangup(&port->port);  } @@ -288,7 +286,8 @@ static void serial_close(struct tty_struct *tty, struct file *filp)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__); +  	tty_port_close(&port->port, tty, filp);  } @@ -307,14 +306,14 @@ static void serial_cleanup(struct tty_struct *tty)  	struct usb_serial *serial;  	struct module *owner; +	dev_dbg(tty->dev, "%s\n", __func__); +  	/* The console is magical.  Do not hang up the console hardware  	 * or there will be tears.  	 */  	if (port->port.console)  		return; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); -  	tty->driver_data = NULL;  	serial = port->serial; @@ -338,10 +337,8 @@ static int serial_write(struct tty_struct *tty, const unsigned char *buf,  	if (port->serial->dev->state == USB_STATE_NOTATTACHED)  		goto exit; -	dev_dbg(tty->dev, "%s - port %d, %d byte(s)\n", __func__, -		port->number, count); +	dev_dbg(tty->dev, "%s - %d byte(s)\n", __func__, count); -	/* pass on to the driver specific version of this function */  	retval = port->serial->type->write(tty, port, buf, count);  	if (retval < 0)  		retval = usb_translate_errors(retval); @@ -353,8 +350,8 @@ static int serial_write_room(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); -	/* pass on to the driver specific version of this function */ +	dev_dbg(tty->dev, "%s\n", __func__); +  	return port->serial->type->write_room(tty);  } @@ -364,7 +361,7 @@ static int serial_chars_in_buffer(struct tty_struct *tty)  	struct usb_serial *serial = port->serial;  	int count = 0; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__);  	mutex_lock(&serial->disc_mutex);  	/* if the device was unplugged then any remaining characters @@ -382,9 +379,8 @@ static void serial_throttle(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__); -	/* pass on to the driver specific version of this function */  	if (port->serial->type->throttle)  		port->serial->type->throttle(tty);  } @@ -393,9 +389,8 @@ static void serial_unthrottle(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__); -	/* pass on to the driver specific version of this function */  	if (port->serial->type->unthrottle)  		port->serial->type->unthrottle(tty);  } @@ -406,15 +401,20 @@ static int serial_ioctl(struct tty_struct *tty,  	struct usb_serial_port *port = tty->driver_data;  	int retval = -ENODEV; -	dev_dbg(tty->dev, "%s - port %d, cmd 0x%.4x\n", __func__, -		port->number, cmd); +	dev_dbg(tty->dev, "%s - cmd 0x%.4x\n", __func__, cmd); + +	switch (cmd) { +	case TIOCMIWAIT: +		if (port->serial->type->tiocmiwait) +			retval = port->serial->type->tiocmiwait(tty, arg); +		break; +	default: +		if (port->serial->type->ioctl) +			retval = port->serial->type->ioctl(tty, cmd, arg); +		else +			retval = -ENOIOCTLCMD; +	} -	/* pass on to the driver specific version of this function -	   if it is available */ -	if (port->serial->type->ioctl) { -		retval = port->serial->type->ioctl(tty, cmd, arg); -	} else -		retval = -ENOIOCTLCMD;  	return retval;  } @@ -422,10 +422,8 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__); -	/* pass on to the driver specific version of this function -	   if it is available */  	if (port->serial->type->set_termios)  		port->serial->type->set_termios(tty, port, old);  	else @@ -436,12 +434,11 @@ static int serial_break(struct tty_struct *tty, int break_state)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__); -	/* pass on to the driver specific version of this function -	   if it is available */  	if (port->serial->type->break_ctl)  		port->serial->type->break_ctl(tty, break_state); +  	return 0;  } @@ -495,7 +492,7 @@ static int serial_tiocmget(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__);  	if (port->serial->type->tiocmget)  		return port->serial->type->tiocmget(tty); @@ -507,7 +504,7 @@ static int serial_tiocmset(struct tty_struct *tty,  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__);  	if (port->serial->type->tiocmset)  		return port->serial->type->tiocmset(tty, set, clear); @@ -519,7 +516,7 @@ static int serial_get_icount(struct tty_struct *tty,  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	dev_dbg(tty->dev, "%s\n", __func__);  	if (port->serial->type->get_icount)  		return port->serial->type->get_icount(tty, icount); @@ -541,55 +538,43 @@ static void usb_serial_port_work(struct work_struct *work)  {  	struct usb_serial_port *port =  		container_of(work, struct usb_serial_port, work); -	struct tty_struct *tty; -	tty = tty_port_tty_get(&port->port); -	if (!tty) -		return; +	tty_port_tty_wakeup(&port->port); +} + +static void usb_serial_port_poison_urbs(struct usb_serial_port *port) +{ +	int i; -	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); +	for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) +		usb_poison_urb(port->read_urbs[i]); +	for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) +		usb_poison_urb(port->write_urbs[i]); -	tty_wakeup(tty); -	tty_kref_put(tty); +	usb_poison_urb(port->interrupt_in_urb); +	usb_poison_urb(port->interrupt_out_urb);  } -static void kill_traffic(struct usb_serial_port *port) +static void usb_serial_port_unpoison_urbs(struct usb_serial_port *port)  {  	int i;  	for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) -		usb_kill_urb(port->read_urbs[i]); +		usb_unpoison_urb(port->read_urbs[i]);  	for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) -		usb_kill_urb(port->write_urbs[i]); -	/* -	 * This is tricky. -	 * Some drivers submit the read_urb in the -	 * handler for the write_urb or vice versa -	 * this order determines the order in which -	 * usb_kill_urb() must be used to reliably -	 * kill the URBs. As it is unknown here, -	 * both orders must be used in turn. -	 * The call below is not redundant. -	 */ -	usb_kill_urb(port->read_urb); -	usb_kill_urb(port->interrupt_in_urb); -	usb_kill_urb(port->interrupt_out_urb); +		usb_unpoison_urb(port->write_urbs[i]); + +	usb_unpoison_urb(port->interrupt_in_urb); +	usb_unpoison_urb(port->interrupt_out_urb);  } -static void port_release(struct device *dev) +static void usb_serial_port_release(struct device *dev)  {  	struct usb_serial_port *port = to_usb_serial_port(dev);  	int i;  	dev_dbg(dev, "%s\n", __func__); -	/* -	 * Stop all the traffic before cancelling the work, so that -	 * nobody will restart it by calling usb_serial_port_softint. -	 */ -	kill_traffic(port); -	cancel_work_sync(&port->work); -  	usb_free_urb(port->interrupt_in_urb);  	usb_free_urb(port->interrupt_out_urb);  	for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) { @@ -614,13 +599,11 @@ static struct usb_serial *create_serial(struct usb_device *dev,  	struct usb_serial *serial;  	serial = kzalloc(sizeof(*serial), GFP_KERNEL); -	if (!serial) { -		dev_err(&dev->dev, "%s - out of memory\n", __func__); +	if (!serial)  		return NULL; -	}  	serial->dev = usb_get_dev(dev);  	serial->type = driver; -	serial->interface = interface; +	serial->interface = usb_get_intf(interface);  	kref_init(&serial->kref);  	mutex_init(&serial->disc_mutex);  	serial->minor = SERIAL_TTY_NO_MINOR; @@ -680,7 +663,7 @@ static struct usb_serial_driver *search_serial_device(  	return NULL;  } -static int serial_carrier_raised(struct tty_port *port) +static int serial_port_carrier_raised(struct tty_port *port)  {  	struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);  	struct usb_serial_driver *drv = p->serial->type; @@ -691,7 +674,7 @@ static int serial_carrier_raised(struct tty_port *port)  	return 1;  } -static void serial_dtr_rts(struct tty_port *port, int on) +static void serial_port_dtr_rts(struct tty_port *port, int on)  {  	struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);  	struct usb_serial *serial = p->serial; @@ -711,10 +694,10 @@ static void serial_dtr_rts(struct tty_port *port, int on)  }  static const struct tty_port_operations serial_port_ops = { -	.carrier_raised = serial_carrier_raised, -	.dtr_rts = serial_dtr_rts, -	.activate = serial_activate, -	.shutdown = serial_down, +	.carrier_raised		= serial_port_carrier_raised, +	.dtr_rts		= serial_port_dtr_rts, +	.activate		= serial_port_activate, +	.shutdown		= serial_port_shutdown,  };  static int usb_serial_probe(struct usb_interface *interface, @@ -761,7 +744,6 @@ static int usb_serial_probe(struct usb_interface *interface,  	serial = create_serial(dev, interface, type);  	if (!serial) {  		module_put(type->driver.owner); -		dev_err(ddev, "%s - out of memory\n", __func__);  		return -ENOMEM;  	} @@ -909,7 +891,7 @@ static int usb_serial_probe(struct usb_interface *interface,  		port->dev.parent = &interface->dev;  		port->dev.driver = NULL;  		port->dev.bus = &usb_serial_bus_type; -		port->dev.release = &port_release; +		port->dev.release = &usb_serial_port_release;  		device_initialize(&port->dev);  	} @@ -925,16 +907,12 @@ static int usb_serial_probe(struct usb_interface *interface,  		for (j = 0; j < ARRAY_SIZE(port->read_urbs); ++j) {  			set_bit(j, &port->read_urbs_free);  			port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL); -			if (!port->read_urbs[j]) { -				dev_err(ddev, "No free urbs available\n"); +			if (!port->read_urbs[j])  				goto probe_error; -			}  			port->bulk_in_buffers[j] = kmalloc(buffer_size,  								GFP_KERNEL); -			if (!port->bulk_in_buffers[j]) { -				dev_err(ddev, "Couldn't allocate bulk_in_buffer\n"); +			if (!port->bulk_in_buffers[j])  				goto probe_error; -			}  			usb_fill_bulk_urb(port->read_urbs[j], dev,  					usb_rcvbulkpipe(dev,  						endpoint->bEndpointAddress), @@ -961,16 +939,12 @@ static int usb_serial_probe(struct usb_interface *interface,  		for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {  			set_bit(j, &port->write_urbs_free);  			port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL); -			if (!port->write_urbs[j]) { -				dev_err(ddev, "No free urbs available\n"); +			if (!port->write_urbs[j])  				goto probe_error; -			}  			port->bulk_out_buffers[j] = kmalloc(buffer_size,  								GFP_KERNEL); -			if (!port->bulk_out_buffers[j]) { -				dev_err(ddev, "Couldn't allocate bulk_out_buffer\n"); +			if (!port->bulk_out_buffers[j])  				goto probe_error; -			}  			usb_fill_bulk_urb(port->write_urbs[j], dev,  					usb_sndbulkpipe(dev,  						endpoint->bEndpointAddress), @@ -988,19 +962,15 @@ static int usb_serial_probe(struct usb_interface *interface,  			endpoint = interrupt_in_endpoint[i];  			port = serial->port[i];  			port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); -			if (!port->interrupt_in_urb) { -				dev_err(ddev, "No free urbs available\n"); +			if (!port->interrupt_in_urb)  				goto probe_error; -			}  			buffer_size = usb_endpoint_maxp(endpoint);  			port->interrupt_in_endpointAddress =  						endpoint->bEndpointAddress;  			port->interrupt_in_buffer = kmalloc(buffer_size,  								GFP_KERNEL); -			if (!port->interrupt_in_buffer) { -				dev_err(ddev, "Couldn't allocate interrupt_in_buffer\n"); +			if (!port->interrupt_in_buffer)  				goto probe_error; -			}  			usb_fill_int_urb(port->interrupt_in_urb, dev,  				usb_rcvintpipe(dev,  						endpoint->bEndpointAddress), @@ -1017,20 +987,16 @@ static int usb_serial_probe(struct usb_interface *interface,  			endpoint = interrupt_out_endpoint[i];  			port = serial->port[i];  			port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); -			if (!port->interrupt_out_urb) { -				dev_err(ddev, "No free urbs available\n"); +			if (!port->interrupt_out_urb)  				goto probe_error; -			}  			buffer_size = usb_endpoint_maxp(endpoint);  			port->interrupt_out_size = buffer_size;  			port->interrupt_out_endpointAddress =  						endpoint->bEndpointAddress;  			port->interrupt_out_buffer = kmalloc(buffer_size,  								GFP_KERNEL); -			if (!port->interrupt_out_buffer) { -				dev_err(ddev, "Couldn't allocate interrupt_out_buffer\n"); +			if (!port->interrupt_out_buffer)  				goto probe_error; -			}  			usb_fill_int_urb(port->interrupt_out_urb, dev,  				usb_sndintpipe(dev,  						  endpoint->bEndpointAddress), @@ -1119,13 +1085,15 @@ static void usb_serial_disconnect(struct usb_interface *interface)  				tty_vhangup(tty);  				tty_kref_put(tty);  			} -			kill_traffic(port); +			usb_serial_port_poison_urbs(port); +			wake_up_interruptible(&port->port.delta_msr_wait);  			cancel_work_sync(&port->work);  			if (device_is_registered(&port->dev))  				device_del(&port->dev);  		}  	} -	serial->type->disconnect(serial); +	if (serial->type->disconnect) +		serial->type->disconnect(serial);  	/* let the last holder of this object cause it to be cleaned up */  	usb_serial_put(serial); @@ -1140,6 +1108,11 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)  	serial->suspending = 1; +	/* +	 * serial->type->suspend() MUST return 0 in system sleep context, +	 * otherwise, the resume callback has to recover device from +	 * previous suspend failure. +	 */  	if (serial->type->suspend) {  		r = serial->type->suspend(serial, message);  		if (r < 0) { @@ -1151,7 +1124,7 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)  	for (i = 0; i < serial->num_ports; ++i) {  		port = serial->port[i];  		if (port) -			kill_traffic(port); +			usb_serial_port_poison_urbs(port);  	}  err_out: @@ -1159,11 +1132,25 @@ err_out:  }  EXPORT_SYMBOL(usb_serial_suspend); +static void usb_serial_unpoison_port_urbs(struct usb_serial *serial) +{ +	struct usb_serial_port *port; +	int i; + +	for (i = 0; i < serial->num_ports; ++i) { +		port = serial->port[i]; +		if (port) +			usb_serial_port_unpoison_urbs(port); +	} +} +  int usb_serial_resume(struct usb_interface *intf)  {  	struct usb_serial *serial = usb_get_intfdata(intf);  	int rv; +	usb_serial_unpoison_port_urbs(serial); +  	serial->suspending = 0;  	if (serial->type->resume)  		rv = serial->type->resume(serial); @@ -1179,6 +1166,8 @@ static int usb_serial_reset_resume(struct usb_interface *intf)  	struct usb_serial *serial = usb_get_intfdata(intf);  	int rv; +	usb_serial_unpoison_port_urbs(serial); +  	serial->suspending = 0;  	if (serial->type->reset_resume)  		rv = serial->type->reset_resume(serial); @@ -1315,12 +1304,12 @@ module_exit(usb_serial_exit);  	do {								\  		if (!type->function) {					\  			type->function = usb_serial_generic_##function;	\ -			pr_debug("Had to override the " #function	\ -				" usb serial operation with the generic one.");\ -			}						\ +			pr_debug("%s: using generic " #function	"\n",	\ +						type->driver.name);	\ +		}							\  	} while (0) -static void fixup_generic(struct usb_serial_driver *device) +static void usb_serial_operations_init(struct usb_serial_driver *device)  {  	set_to_generic_if_null(device, open);  	set_to_generic_if_null(device, write); @@ -1329,8 +1318,6 @@ static void fixup_generic(struct usb_serial_driver *device)  	set_to_generic_if_null(device, chars_in_buffer);  	set_to_generic_if_null(device, read_bulk_callback);  	set_to_generic_if_null(device, write_bulk_callback); -	set_to_generic_if_null(device, disconnect); -	set_to_generic_if_null(device, release);  	set_to_generic_if_null(device, process_read_urb);  	set_to_generic_if_null(device, prepare_write_buffer);  } @@ -1342,8 +1329,6 @@ static int usb_serial_register(struct usb_serial_driver *driver)  	if (usb_disabled())  		return -ENODEV; -	fixup_generic(driver); -  	if (!driver->description)  		driver->description = driver->driver.name;  	if (!driver->usb_driver) { @@ -1352,6 +1337,8 @@ static int usb_serial_register(struct usb_serial_driver *driver)  		return -EINVAL;  	} +	usb_serial_operations_init(driver); +  	/* Add this device to our list of devices */  	mutex_lock(&table_lock);  	list_add(&driver->driver_list, &usb_serial_driver_list); @@ -1469,7 +1456,6 @@ void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_driver  }  EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers); -/* Module information */  MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 571965aa1cc..ece326ef63a 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -421,20 +421,19 @@ void usb_wwan_close(struct usb_serial_port *port)  	portdata = usb_get_serial_port_data(port); -	if (serial->dev) { -		/* Stop reading/writing urbs */ -		spin_lock_irq(&intfdata->susp_lock); -		portdata->opened = 0; -		spin_unlock_irq(&intfdata->susp_lock); +	/* Stop reading/writing urbs */ +	spin_lock_irq(&intfdata->susp_lock); +	portdata->opened = 0; +	spin_unlock_irq(&intfdata->susp_lock); -		for (i = 0; i < N_IN_URB; i++) -			usb_kill_urb(portdata->in_urbs[i]); -		for (i = 0; i < N_OUT_URB; i++) -			usb_kill_urb(portdata->out_urbs[i]); -		/* balancing - important as an error cannot be handled*/ -		usb_autopm_get_interface_no_resume(serial->interface); -		serial->interface->needs_remote_wakeup = 0; -	} +	for (i = 0; i < N_IN_URB; i++) +		usb_kill_urb(portdata->in_urbs[i]); +	for (i = 0; i < N_OUT_URB; i++) +		usb_kill_urb(portdata->out_urbs[i]); + +	/* balancing - important as an error cannot be handled*/ +	usb_autopm_get_interface_no_resume(serial->interface); +	serial->interface->needs_remote_wakeup = 0;  }  EXPORT_SYMBOL(usb_wwan_close); diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 1129aa73c23..7573ec8a084 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -257,24 +257,18 @@ static void visor_close(struct usb_serial_port *port)  {  	unsigned char *transfer_buffer; -	/* shutdown our urbs */  	usb_serial_generic_close(port);  	usb_kill_urb(port->interrupt_in_urb); -	mutex_lock(&port->serial->disc_mutex); -	if (!port->serial->disconnected) { -		/* Try to send shutdown message, unless the device is gone */ -		transfer_buffer =  kmalloc(0x12, GFP_KERNEL); -		if (transfer_buffer) { -			usb_control_msg(port->serial->dev, +	transfer_buffer = kmalloc(0x12, GFP_KERNEL); +	if (!transfer_buffer) +		return; +	usb_control_msg(port->serial->dev,  					 usb_rcvctrlpipe(port->serial->dev, 0),  					 VISOR_CLOSE_NOTIFICATION, 0xc2,  					 0x0000, 0x0000,  					 transfer_buffer, 0x12, 300); -			kfree(transfer_buffer); -		} -	} -	mutex_unlock(&port->serial->disc_mutex); +	kfree(transfer_buffer);  }  static void visor_read_int_callback(struct urb *urb) diff --git a/drivers/usb/serial/wishbone-serial.c b/drivers/usb/serial/wishbone-serial.c new file mode 100644 index 00000000000..100573c6f19 --- /dev/null +++ b/drivers/usb/serial/wishbone-serial.c @@ -0,0 +1,95 @@ +/* + * USB Wishbone-Serial adapter driver + * + * Copyright (C) 2013 Wesley W. Terpstra <w.terpstra@gsi.de> + * Copyright (C) 2013 GSI Helmholtz Centre for Heavy Ion Research GmbH + * + * 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 <linux/kernel.h> +#include <linux/init.h> +#include <linux/tty.h> +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/usb/serial.h> +#include <linux/uaccess.h> + +#define GSI_VENDOR_OPENCLOSE 0xB0 + +static const struct usb_device_id id_table[] = { +	{ USB_DEVICE_AND_INTERFACE_INFO(0x1D50, 0x6062, 0xFF, 0xFF, 0xFF) }, +	{ }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* + * Etherbone must be told that a new stream has begun before data arrives. + * This is necessary to restart the negotiation of Wishbone bus parameters. + * Similarly, when the stream ends, Etherbone must be told so that the cycle + * line can be driven low in the case that userspace failed to do so. + */ +static int usb_gsi_openclose(struct usb_serial_port *port, int value) +{ +	struct usb_device *dev = port->serial->dev; + +	return usb_control_msg( +		dev, +		usb_sndctrlpipe(dev, 0), /* Send to EP0OUT */ +		GSI_VENDOR_OPENCLOSE, +		USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, +		value, /* wValue = device is open(1) or closed(0) */ +		port->serial->interface->cur_altsetting->desc.bInterfaceNumber, +		NULL, 0,  /* There is no data stage */ +		5000); /* Timeout till operation fails */ +} + +static int wishbone_serial_open(struct tty_struct *tty, +				struct usb_serial_port *port) +{ +	int retval; + +	retval = usb_gsi_openclose(port, 1); +	if (retval) { +		dev_err(&port->serial->dev->dev, +		       "Could not mark device as open (%d)\n", +		       retval); +		return retval; +	} + +	retval = usb_serial_generic_open(tty, port); +	if (retval) +		usb_gsi_openclose(port, 0); + +	return retval; +} + +static void wishbone_serial_close(struct usb_serial_port *port) +{ +	usb_serial_generic_close(port); +	usb_gsi_openclose(port, 0); +} + +static struct usb_serial_driver wishbone_serial_device = { +	.driver = { +		.owner =	THIS_MODULE, +		.name =		"wishbone_serial", +	}, +	.id_table =		id_table, +	.num_ports =		1, +	.open =			&wishbone_serial_open, +	.close =		&wishbone_serial_close, +}; + +static struct usb_serial_driver * const serial_drivers[] = { +	&wishbone_serial_device, NULL +}; + +module_usb_serial_driver(serial_drivers, id_table); + +MODULE_AUTHOR("Wesley W. Terpstra <w.terpstra@gsi.de>"); +MODULE_DESCRIPTION("USB Wishbone-Serial adapter"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index eab04a6b5fb..8470e1b114f 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -4,11 +4,10 @@  comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may"  comment "also be needed; see USB_STORAGE Help for more info" -	depends on USB  config USB_STORAGE  	tristate "USB Mass Storage support" -	depends on USB && SCSI +	depends on SCSI  	---help---  	  Say Y here if you want to connect USB mass storage devices to your  	  computer's USB port. This is the driver you need for USB @@ -188,7 +187,7 @@ config USB_STORAGE_CYPRESS_ATACB  config USB_STORAGE_ENE_UB6250  	tristate "USB ENE card reader support" -	depends on USB && SCSI +	depends on SCSI  	depends on USB_STORAGE  	---help---  	  Say Y here if you wish to control a ENE SD/MS Card reader. @@ -203,7 +202,7 @@ config USB_STORAGE_ENE_UB6250  config USB_UAS  	tristate "USB Attached SCSI" -	depends on USB && SCSI && BROKEN +	depends on SCSI && BROKEN  	help  	  The USB Attached SCSI protocol is supported by some USB  	  storage devices.  It permits higher performance by supporting diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index be5564cc8e0..77a2ddfe648 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -326,8 +326,7 @@ static int alauda_get_media_status(struct us_data *us, unsigned char *data)  	rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,  		command, 0xc0, 0, 1, data, 2); -	US_DEBUGP("alauda_get_media_status: Media status %02X %02X\n", -		data[0], data[1]); +	usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);  	return rc;  } @@ -402,7 +401,7 @@ static int alauda_init_media(struct us_data *us)  			ready = 1;  	} -	US_DEBUGP("alauda_init_media: We are ready for action!\n"); +	usb_stor_dbg(us, "We are ready for action!\n");  	if (alauda_ack_media(us) != USB_STOR_XFER_GOOD)  		return USB_STOR_TRANSPORT_ERROR; @@ -413,15 +412,15 @@ static int alauda_init_media(struct us_data *us)  		return USB_STOR_TRANSPORT_ERROR;  	if (data[0] != 0x14) { -		US_DEBUGP("alauda_init_media: Media not ready after ack\n"); +		usb_stor_dbg(us, "Media not ready after ack\n");  		return USB_STOR_TRANSPORT_ERROR;  	}  	if (alauda_get_media_signature(us, data) != USB_STOR_XFER_GOOD)  		return USB_STOR_TRANSPORT_ERROR; -	US_DEBUGP("alauda_init_media: Media signature: %02X %02X %02X %02X\n", -		data[0], data[1], data[2], data[3]); +	usb_stor_dbg(us, "Media signature: %02X %02X %02X %02X\n", +		     data[0], data[1], data[2], data[3]);  	media_info = alauda_card_find_id(data[1]);  	if (media_info == NULL) {  		printk(KERN_WARNING @@ -432,8 +431,8 @@ static int alauda_init_media(struct us_data *us)  	}  	MEDIA_INFO(us).capacity = 1 << media_info->chipshift; -	US_DEBUGP("Found media with capacity: %ldMB\n", -		MEDIA_INFO(us).capacity >> 20); +	usb_stor_dbg(us, "Found media with capacity: %ldMB\n", +		     MEDIA_INFO(us).capacity >> 20);  	MEDIA_INFO(us).pageshift = media_info->pageshift;  	MEDIA_INFO(us).blockshift = media_info->blockshift; @@ -472,7 +471,7 @@ static int alauda_check_media(struct us_data *us)  	/* Check for no media or door open */  	if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10)  		|| ((status[1] & 0x01) == 0)) { -		US_DEBUGP("alauda_check_media: No media, or door open\n"); +		usb_stor_dbg(us, "No media, or door open\n");  		alauda_free_maps(&MEDIA_INFO(us));  		info->sense_key = 0x02;  		info->sense_asc = 0x3A; @@ -482,7 +481,7 @@ static int alauda_check_media(struct us_data *us)  	/* Check for media change */  	if (status[0] & 0x08) { -		US_DEBUGP("alauda_check_media: Media change detected\n"); +		usb_stor_dbg(us, "Media change detected\n");  		alauda_free_maps(&MEDIA_INFO(us));  		alauda_init_media(us); @@ -518,7 +517,7 @@ static int alauda_check_status2(struct us_data *us)  	if (rc != USB_STOR_XFER_GOOD)  		return rc; -	US_DEBUGP("alauda_check_status2: %02X %02X %02X\n", data[0], data[1], data[2]); +	usb_stor_dbg(us, "%02X %02X %02X\n", data[0], data[1], data[2]);  	if (data[0] & ALAUDA_STATUS_ERROR)  		return USB_STOR_XFER_ERROR; @@ -584,7 +583,7 @@ static int alauda_read_map(struct us_data *us, unsigned int zone)  		goto error;  	} -	US_DEBUGP("alauda_read_map: Mapping blocks for zone %d\n", zone); +	usb_stor_dbg(us, "Mapping blocks for zone %d\n", zone);  	/* 1024 PBA's per zone */  	for (i = 0; i < zonesize; i++) @@ -604,7 +603,7 @@ static int alauda_read_map(struct us_data *us, unsigned int zone)  			if (data[j] != 0)  				goto nonz;  		pba_to_lba[i] = UNUSABLE; -		US_DEBUGP("alauda_read_map: PBA %d has no logical mapping\n", blocknum); +		usb_stor_dbg(us, "PBA %d has no logical mapping\n", blocknum);  		continue;  	nonz: @@ -617,19 +616,18 @@ static int alauda_read_map(struct us_data *us, unsigned int zone)  	nonff:  		/* normal PBAs start with six FFs */  		if (j < 6) { -			US_DEBUGP("alauda_read_map: PBA %d has no logical mapping: " -			       "reserved area = %02X%02X%02X%02X " -			       "data status %02X block status %02X\n", -			       blocknum, data[0], data[1], data[2], data[3], -			       data[4], data[5]); +			usb_stor_dbg(us, "PBA %d has no logical mapping: reserved area = %02X%02X%02X%02X data status %02X block status %02X\n", +				     blocknum, +				     data[0], data[1], data[2], data[3], +				     data[4], data[5]);  			pba_to_lba[i] = UNUSABLE;  			continue;  		}  		if ((data[6] >> 4) != 0x01) { -			US_DEBUGP("alauda_read_map: PBA %d has invalid address " -			       "field %02X%02X/%02X%02X\n", -			       blocknum, data[6], data[7], data[11], data[12]); +			usb_stor_dbg(us, "PBA %d has invalid address field %02X%02X/%02X%02X\n", +				     blocknum, data[6], data[7], +				     data[11], data[12]);  			pba_to_lba[i] = UNUSABLE;  			continue;  		} @@ -711,7 +709,7 @@ static int alauda_erase_block(struct us_data *us, u16 pba)  	};  	unsigned char buf[2]; -	US_DEBUGP("alauda_erase_block: Erasing PBA %d\n", pba); +	usb_stor_dbg(us, "Erasing PBA %d\n", pba);  	rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,  		command, 9, NULL); @@ -723,8 +721,7 @@ static int alauda_erase_block(struct us_data *us, u16 pba)  	if (rc != USB_STOR_XFER_GOOD)  		return rc; -	US_DEBUGP("alauda_erase_block: Erase result: %02X %02X\n", -		buf[0], buf[1]); +	usb_stor_dbg(us, "Erase result: %02X %02X\n", buf[0], buf[1]);  	return rc;  } @@ -741,8 +738,7 @@ static int alauda_read_block_raw(struct us_data *us, u16 pba,  		PBA_ZONE(pba), 0, PBA_LO(pba) + page, pages, 0, MEDIA_PORT(us)  	}; -	US_DEBUGP("alauda_read_block: pba %d page %d count %d\n", -		pba, page, pages); +	usb_stor_dbg(us, "pba %d page %d count %d\n", pba, page, pages);  	rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,  		command, 9, NULL); @@ -793,7 +789,7 @@ static int alauda_write_block(struct us_data *us, u16 pba, unsigned char *data)  		PBA_ZONE(pba), 0, PBA_LO(pba), 32, 0, MEDIA_PORT(us)  	}; -	US_DEBUGP("alauda_write_block: pba %d\n", pba); +	usb_stor_dbg(us, "pba %d\n", pba);  	rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,  		command, 9, NULL); @@ -866,14 +862,14 @@ static int alauda_write_lba(struct us_data *us, u16 lba,  		cptr = bptr + pagesize;  		nand_compute_ecc(bptr, ecc);  		if (!nand_compare_ecc(cptr+13, ecc)) { -			US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n", -				  i, pba); +			usb_stor_dbg(us, "Warning: bad ecc in page %d- of pba %d\n", +				     i, pba);  			nand_store_ecc(cptr+13, ecc);  		}  		nand_compute_ecc(bptr + (pagesize / 2), ecc);  		if (!nand_compare_ecc(cptr+8, ecc)) { -			US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n", -				  i, pba); +			usb_stor_dbg(us, "Warning: bad ecc in page %d+ of pba %d\n", +				     i, pba);  			nand_store_ecc(cptr+8, ecc);  		}  		cptr[6] = cptr[11] = MSB_of(lbap); @@ -900,8 +896,7 @@ static int alauda_write_lba(struct us_data *us, u16 lba,  	new_pba_offset = new_pba - (zone * zonesize);  	MEDIA_INFO(us).pba_to_lba[zone][new_pba_offset] = lba;  	MEDIA_INFO(us).lba_to_pba[zone][lba_offset] = new_pba; -	US_DEBUGP("alauda_write_lba: Remapped LBA %d to PBA %d\n", -		lba, new_pba); +	usb_stor_dbg(us, "Remapped LBA %d to PBA %d\n", lba, new_pba);  	if (pba != UNDEF) {  		unsigned int pba_offset = pba - (zone * zonesize); @@ -964,8 +959,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,  		/* Not overflowing capacity? */  		if (lba >= max_lba) { -			US_DEBUGP("Error: Requested lba %u exceeds " -				  "maximum %u\n", lba, max_lba); +			usb_stor_dbg(us, "Error: Requested lba %u exceeds maximum %u\n", +				     lba, max_lba);  			result = USB_STOR_TRANSPORT_ERROR;  			break;  		} @@ -978,8 +973,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,  		pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset];  		if (pba == UNDEF) {	/* this lba was never written */ -			US_DEBUGP("Read %d zero pages (LBA %d) page %d\n", -				  pages, lba, page); +			usb_stor_dbg(us, "Read %d zero pages (LBA %d) page %d\n", +				     pages, lba, page);  			/* This is not really an error. It just means  			   that the block has never been written. @@ -988,9 +983,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,  			memset(buffer, 0, len);  		} else { -			US_DEBUGP("Read %d pages, from PBA %d" -				  " (LBA %d) page %d\n", -				  pages, pba, lba, page); +			usb_stor_dbg(us, "Read %d pages, from PBA %d (LBA %d) page %d\n", +				     pages, pba, lba, page);  			result = alauda_read_block(us, pba, page, pages, buffer);  			if (result != USB_STOR_TRANSPORT_GOOD) @@ -1066,8 +1060,8 @@ static int alauda_write_data(struct us_data *us, unsigned long address,  		/* Not overflowing capacity? */  		if (lba >= max_lba) { -			US_DEBUGP("alauda_write_data: Requested lba %u exceeds " -				  "maximum %u\n", lba, max_lba); +			usb_stor_dbg(us, "Requested lba %u exceeds maximum %u\n", +				     lba, max_lba);  			result = USB_STOR_TRANSPORT_ERROR;  			break;  		} @@ -1122,11 +1116,9 @@ static int init_alauda(struct us_data *us)  	nand_init_ecc();  	us->extra = kzalloc(sizeof(struct alauda_info), GFP_NOIO); -	if (!us->extra) { -		US_DEBUGP("init_alauda: Gah! Can't allocate storage for" -			"alauda info struct!\n"); +	if (!us->extra)  		return USB_STOR_TRANSPORT_ERROR; -	} +  	info = (struct alauda_info *) us->extra;  	us->extra_destructor = alauda_info_destructor; @@ -1147,15 +1139,14 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)  	};  	if (srb->cmnd[0] == INQUIRY) { -		US_DEBUGP("alauda_transport: INQUIRY. " -			"Returning bogus response.\n"); +		usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");  		memcpy(ptr, inquiry_response, sizeof(inquiry_response));  		fill_inquiry_response(us, ptr, 36);  		return USB_STOR_TRANSPORT_GOOD;  	}  	if (srb->cmnd[0] == TEST_UNIT_READY) { -		US_DEBUGP("alauda_transport: TEST_UNIT_READY.\n"); +		usb_stor_dbg(us, "TEST_UNIT_READY\n");  		return alauda_check_media(us);  	} @@ -1193,8 +1184,7 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)  		page |= short_pack(srb->cmnd[5], srb->cmnd[4]);  		pages = short_pack(srb->cmnd[8], srb->cmnd[7]); -		US_DEBUGP("alauda_transport: READ_10: page %d pagect %d\n", -			  page, pages); +		usb_stor_dbg(us, "READ_10: page %d pagect %d\n", page, pages);  		return alauda_read_data(us, page, pages);  	} @@ -1211,14 +1201,13 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)  		page |= short_pack(srb->cmnd[5], srb->cmnd[4]);  		pages = short_pack(srb->cmnd[8], srb->cmnd[7]); -		US_DEBUGP("alauda_transport: WRITE_10: page %d pagect %d\n", -			  page, pages); +		usb_stor_dbg(us, "WRITE_10: page %d pagect %d\n", page, pages);  		return alauda_write_data(us, page, pages);  	}  	if (srb->cmnd[0] == REQUEST_SENSE) { -		US_DEBUGP("alauda_transport: REQUEST_SENSE.\n"); +		usb_stor_dbg(us, "REQUEST_SENSE\n");  		memset(ptr, 0, 18);  		ptr[0] = 0xF0; @@ -1237,8 +1226,8 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)  		return USB_STOR_TRANSPORT_GOOD;  	} -	US_DEBUGP("alauda_transport: Gah! Unknown command: %d (0x%x)\n", -		srb->cmnd[0], srb->cmnd[0]); +	usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n", +		     srb->cmnd[0], srb->cmnd[0]);  	info->sense_key = 0x05;  	info->sense_asc = 0x20;  	info->sense_ascq = 0x00; diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 070b5c0ebbf..8514a2d82b7 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -159,7 +159,7 @@ static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)  	if (srb->result == SAM_STAT_CHECK_CONDITION &&  			memcmp(srb->sense_buffer, usb_stor_sense_invalidCDB,  				sizeof(usb_stor_sense_invalidCDB)) == 0) { -		US_DEBUGP("cypress atacb not supported ???\n"); +		usb_stor_dbg(us, "cypress atacb not supported ???\n");  		goto end;  	} @@ -248,14 +248,26 @@ static int cypress_probe(struct usb_interface *intf,  {  	struct us_data *us;  	int result; +	struct usb_device *device;  	result = usb_stor_probe1(&us, intf, id,  			(id - cypress_usb_ids) + cypress_unusual_dev_list);  	if (result)  		return result; -	us->protocol_name = "Transparent SCSI with Cypress ATACB"; -	us->proto_handler = cypress_atacb_passthrough; +	/* Among CY7C68300 chips, the A revision does not support Cypress ATACB +	 * Filter out this revision from EEPROM default descriptor values +	 */ +	device = interface_to_usbdev(intf); +	if (device->descriptor.iManufacturer != 0x38 || +	    device->descriptor.iProduct != 0x4e || +	    device->descriptor.iSerialNumber != 0x64) { +		us->protocol_name = "Transparent SCSI with Cypress ATACB"; +		us->proto_handler = cypress_atacb_passthrough; +	} else { +		us->protocol_name = "Transparent SCSI"; +		us->proto_handler = usb_stor_transparent_scsi_command; +	}  	result = usb_stor_probe2(us);  	return result; diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 494fee5af41..7b17c216981 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -123,7 +123,7 @@ datafab_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) {  	if (len == 0)  		return USB_STOR_XFER_GOOD; -	US_DEBUGP("datafab_bulk_read:  len = %d\n", len); +	usb_stor_dbg(us, "len = %d\n", len);  	return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,  			data, len, NULL);  } @@ -134,7 +134,7 @@ datafab_bulk_write(struct us_data *us, unsigned char *data, unsigned int len) {  	if (len == 0)  		return USB_STOR_XFER_GOOD; -	US_DEBUGP("datafab_bulk_write:  len = %d\n", len); +	usb_stor_dbg(us, "len = %d\n", len);  	return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,  			data, len, NULL);  } @@ -300,9 +300,8 @@ static int datafab_write_data(struct us_data *us,  			goto leave;  		if (reply[0] != 0x50 && reply[1] != 0) { -			US_DEBUGP("datafab_write_data:  Gah! " -				  "write return code: %02x %02x\n", -				  reply[0], reply[1]); +			usb_stor_dbg(us, "Gah! write return code: %02x %02x\n", +				     reply[0], reply[1]);  			result = USB_STOR_TRANSPORT_ERROR;  			goto leave;  		} @@ -342,7 +341,7 @@ static int datafab_determine_lun(struct us_data *us,  	if (!buf)  		return USB_STOR_TRANSPORT_ERROR; -	US_DEBUGP("datafab_determine_lun:  locating...\n"); +	usb_stor_dbg(us, "locating...\n");  	// we'll try 3 times before giving up...  	// @@ -474,16 +473,16 @@ static int datafab_handle_mode_sense(struct us_data *us,  	switch (pc) {  	   case 0x0: -		US_DEBUGP("datafab_handle_mode_sense:  Current values\n"); +		   usb_stor_dbg(us, "Current values\n");  		break;  	   case 0x1: -		US_DEBUGP("datafab_handle_mode_sense:  Changeable values\n"); +		   usb_stor_dbg(us, "Changeable values\n");  		break;  	   case 0x2: -		US_DEBUGP("datafab_handle_mode_sense:  Default values\n"); +		   usb_stor_dbg(us, "Default values\n");  		break;  	   case 0x3: -		US_DEBUGP("datafab_handle_mode_sense:  Saves values\n"); +		   usb_stor_dbg(us, "Saves values\n");  		break;  	} @@ -566,11 +565,9 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)  	if (!us->extra) {  		us->extra = kzalloc(sizeof(struct datafab_info), GFP_NOIO); -		if (!us->extra) { -			US_DEBUGP("datafab_transport:  Gah! " -				  "Can't allocate storage for Datafab info struct!\n"); +		if (!us->extra)  			return USB_STOR_TRANSPORT_ERROR; -		} +  		us->extra_destructor = datafab_info_destructor;    		((struct datafab_info *)us->extra)->lun = -1;  	} @@ -578,7 +575,7 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)  	info = (struct datafab_info *) (us->extra);  	if (srb->cmnd[0] == INQUIRY) { -		US_DEBUGP("datafab_transport:  INQUIRY.  Returning bogus response"); +		usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");  		memcpy(ptr, inquiry_reply, sizeof(inquiry_reply));  		fill_inquiry_response(us, ptr, 36);  		return USB_STOR_TRANSPORT_GOOD; @@ -590,8 +587,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)  		if (rc != USB_STOR_TRANSPORT_GOOD)  			return rc; -		US_DEBUGP("datafab_transport:  READ_CAPACITY:  %ld sectors, %ld bytes per sector\n", -			  info->sectors, info->ssize); +		usb_stor_dbg(us, "READ_CAPACITY:  %ld sectors, %ld bytes per sector\n", +			     info->sectors, info->ssize);  		// build the reply  		// we need the last sector, not the number of sectors @@ -603,7 +600,7 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)  	}  	if (srb->cmnd[0] == MODE_SELECT_10) { -		US_DEBUGP("datafab_transport:  Gah! MODE_SELECT_10.\n"); +		usb_stor_dbg(us, "Gah! MODE_SELECT_10\n");  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -615,7 +612,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)  		blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); -		US_DEBUGP("datafab_transport:  READ_10: read block 0x%04lx  count %ld\n", block, blocks); +		usb_stor_dbg(us, "READ_10: read block 0x%04lx  count %ld\n", +			     block, blocks);  		return datafab_read_data(us, info, block, blocks);  	} @@ -628,7 +626,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)  		blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |  			 ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9])); -		US_DEBUGP("datafab_transport:  READ_12: read block 0x%04lx  count %ld\n", block, blocks); +		usb_stor_dbg(us, "READ_12: read block 0x%04lx  count %ld\n", +			     block, blocks);  		return datafab_read_data(us, info, block, blocks);  	} @@ -638,7 +637,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)  		blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); -		US_DEBUGP("datafab_transport:  WRITE_10: write block 0x%04lx  count %ld\n", block, blocks); +		usb_stor_dbg(us, "WRITE_10: write block 0x%04lx count %ld\n", +			     block, blocks);  		return datafab_write_data(us, info, block, blocks);  	} @@ -651,17 +651,18 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)  		blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |  			 ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9])); -		US_DEBUGP("datafab_transport:  WRITE_12: write block 0x%04lx  count %ld\n", block, blocks); +		usb_stor_dbg(us, "WRITE_12: write block 0x%04lx count %ld\n", +			     block, blocks);  		return datafab_write_data(us, info, block, blocks);  	}  	if (srb->cmnd[0] == TEST_UNIT_READY) { -		US_DEBUGP("datafab_transport:  TEST_UNIT_READY.\n"); +		usb_stor_dbg(us, "TEST_UNIT_READY\n");  		return datafab_id_device(us, info);  	}  	if (srb->cmnd[0] == REQUEST_SENSE) { -		US_DEBUGP("datafab_transport:  REQUEST_SENSE.  Returning faked response\n"); +		usb_stor_dbg(us, "REQUEST_SENSE - Returning faked response\n");  		// this response is pretty bogus right now.  eventually if necessary  		// we can set the correct sense data.  so far though it hasn't been @@ -679,12 +680,12 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)  	}  	if (srb->cmnd[0] == MODE_SENSE) { -		US_DEBUGP("datafab_transport:  MODE_SENSE_6 detected\n"); +		usb_stor_dbg(us, "MODE_SENSE_6 detected\n");  		return datafab_handle_mode_sense(us, srb, 1);  	}  	if (srb->cmnd[0] == MODE_SENSE_10) { -		US_DEBUGP("datafab_transport:  MODE_SENSE_10 detected\n"); +		usb_stor_dbg(us, "MODE_SENSE_10 detected\n");  		return datafab_handle_mode_sense(us, srb, 0);  	} @@ -698,7 +699,7 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)  	if (srb->cmnd[0] == START_STOP) {  		/* this is used by sd.c'check_scsidisk_media_change to detect  		   media change */ -		US_DEBUGP("datafab_transport:  START_STOP.\n"); +		usb_stor_dbg(us, "START_STOP\n");  		/* the first datafab_id_device after a media change returns  		   an error (determined experimentally) */  		rc = datafab_id_device(us, info); @@ -712,8 +713,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)  		return rc;  	} -	US_DEBUGP("datafab_transport:  Gah! Unknown command: %d (0x%x)\n", -		  srb->cmnd[0], srb->cmnd[0]); +	usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n", +		     srb->cmnd[0], srb->cmnd[0]);  	info->sense_key = 0x05;  	info->sense_asc = 0x20;  	info->sense_ascq = 0x00; diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c index a2b5526c9fa..e08f64780e3 100644 --- a/drivers/usb/storage/debug.c +++ b/drivers/usb/storage/debug.c @@ -42,16 +42,19 @@   * 675 Mass Ave, Cambridge, MA 02139, USA.   */ +#include <linux/device.h>  #include <linux/cdrom.h> +#include <linux/export.h>  #include <scsi/scsi.h>  #include <scsi/scsi_cmnd.h>  #include <scsi/scsi_dbg.h> +#include "usb.h"  #include "debug.h"  #include "scsi.h" -void usb_stor_show_command(struct scsi_cmnd *srb) +void usb_stor_show_command(const struct us_data *us, struct scsi_cmnd *srb)  {  	char *what = NULL;  	int i; @@ -149,18 +152,18 @@ void usb_stor_show_command(struct scsi_cmnd *srb)  	case WRITE_LONG_2: what = "WRITE_LONG_2"; break;  	default: what = "(unknown command)"; break;  	} -	US_DEBUGP("Command %s (%d bytes)\n", what, srb->cmd_len); -	US_DEBUGP(""); +	usb_stor_dbg(us, "Command %s (%d bytes)\n", what, srb->cmd_len); +	usb_stor_dbg(us, "bytes: ");  	for (i = 0; i < srb->cmd_len && i < 16; i++)  		US_DEBUGPX(" %02x", srb->cmnd[i]);  	US_DEBUGPX("\n");  } -void usb_stor_show_sense( -		unsigned char key, -		unsigned char asc, -		unsigned char ascq) { - +void usb_stor_show_sense(const struct us_data *us, +			 unsigned char key, +			 unsigned char asc, +			 unsigned char ascq) +{  	const char *what, *keystr;  	keystr = scsi_sense_key_string(key); @@ -171,7 +174,22 @@ void usb_stor_show_sense(  	if (what == NULL)  		what = "(unknown ASC/ASCQ)"; -	US_DEBUGP("%s: ", keystr); +	usb_stor_dbg(us, "%s: ", keystr);  	US_DEBUGPX(what, ascq);  	US_DEBUGPX("\n");  } + +int usb_stor_dbg(const struct us_data *us, const char *fmt, ...) +{ +	va_list args; +	int r; + +	va_start(args, fmt); + +	r = dev_vprintk_emit(7, &us->pusb_dev->dev, fmt, args); + +	va_end(args); + +	return r; +} +EXPORT_SYMBOL_GPL(usb_stor_dbg); diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h index dbb985d5242..b1273f03e22 100644 --- a/drivers/usb/storage/debug.h +++ b/drivers/usb/storage/debug.h @@ -47,15 +47,22 @@  #define USB_STORAGE "usb-storage: "  #ifdef CONFIG_USB_STORAGE_DEBUG -void usb_stor_show_command(struct scsi_cmnd *srb); -void usb_stor_show_sense( unsigned char key, -		unsigned char asc, unsigned char ascq ); -#define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE x ) -#define US_DEBUGPX(x...) printk( x ) -#define US_DEBUG(x) x  +void usb_stor_show_command(const struct us_data *us, struct scsi_cmnd *srb); +void usb_stor_show_sense(const struct us_data *us, unsigned char key, +			 unsigned char asc, unsigned char ascq); +__printf(2, 3) int usb_stor_dbg(const struct us_data *us, +				const char *fmt, ...); + +#define US_DEBUGPX(fmt, ...)	printk(fmt, ##__VA_ARGS__) +#define US_DEBUG(x)		x  #else -#define US_DEBUGP(x...) -#define US_DEBUGPX(x...) +__printf(2, 3) +static inline int _usb_stor_dbg(const struct us_data *us, +				const char *fmt, ...) {return 1;} +#define usb_stor_dbg(us, fmt, ...)				\ +	do { if (0) _usb_stor_dbg(us, fmt, ##__VA_ARGS__); } while (0) +#define US_DEBUGPX(fmt, ...)					\ +	do { if (0) printk(fmt, ##__VA_ARGS__); } while (0)  #define US_DEBUG(x)  #endif diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index 118b134a1da..1bfc9a6cab5 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -504,12 +504,12 @@ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)  	unsigned int cswlen = 0, partial = 0;  	unsigned int transfer_length = bcb->DataTransferLength; -	/* US_DEBUGP("transport --- ene_send_scsi_cmd\n"); */ +	/* usb_stor_dbg(us, "transport --- ene_send_scsi_cmd\n"); */  	/* send cmd to out endpoint */  	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,  					    bcb, US_BULK_CB_WRAP_LEN, NULL);  	if (result != USB_STOR_XFER_GOOD) { -		US_DEBUGP("send cmd to out endpoint fail ---\n"); +		usb_stor_dbg(us, "send cmd to out endpoint fail ---\n");  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -529,7 +529,7 @@ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)  						transfer_length, 0, &partial);  		}  		if (result != USB_STOR_XFER_GOOD) { -			US_DEBUGP("data transfer fail ---\n"); +			usb_stor_dbg(us, "data transfer fail ---\n");  			return USB_STOR_TRANSPORT_ERROR;  		}  	} @@ -539,14 +539,14 @@ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)  					    US_BULK_CS_WRAP_LEN, &cswlen);  	if (result == USB_STOR_XFER_SHORT && cswlen == 0) { -		US_DEBUGP("Received 0-length CSW; retrying...\n"); +		usb_stor_dbg(us, "Received 0-length CSW; retrying...\n");  		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,  					    bcs, US_BULK_CS_WRAP_LEN, &cswlen);  	}  	if (result == USB_STOR_XFER_STALLED) {  		/* get the status again */ -		US_DEBUGP("Attempting to get CSW (2nd try)...\n"); +		usb_stor_dbg(us, "Attempting to get CSW (2nd try)...\n");  		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,  						bcs, US_BULK_CS_WRAP_LEN, NULL);  	} @@ -626,7 +626,7 @@ static int sd_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)  	struct scatterlist *sg = NULL;  	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; -	US_DEBUGP("sd_scsi_read_capacity\n"); +	usb_stor_dbg(us, "sd_scsi_read_capacity\n");  	if (info->SD_Status.HiCapacity) {  		bl_len = 0x200;  		if (info->SD_Status.IsMMC) @@ -639,8 +639,8 @@ static int sd_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)  				* (1 << (info->SD_C_SIZE_MULT + 2)) - 1;  	}  	info->bl_num = bl_num; -	US_DEBUGP("bl_len = %x\n", bl_len); -	US_DEBUGP("bl_num = %x\n", bl_num); +	usb_stor_dbg(us, "bl_len = %x\n", bl_len); +	usb_stor_dbg(us, "bl_num = %x\n", bl_num);  	/*srb->request_bufflen = 8; */  	buf[0] = (bl_num >> 24) & 0xff; @@ -675,7 +675,7 @@ static int sd_scsi_read(struct us_data *us, struct scsi_cmnd *srb)  	result = ene_load_bincode(us, SD_RW_PATTERN);  	if (result != USB_STOR_XFER_GOOD) { -		US_DEBUGP("Load SD RW pattern Fail !!\n"); +		usb_stor_dbg(us, "Load SD RW pattern Fail !!\n");  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -715,7 +715,7 @@ static int sd_scsi_write(struct us_data *us, struct scsi_cmnd *srb)  	result = ene_load_bincode(us, SD_RW_PATTERN);  	if (result != USB_STOR_XFER_GOOD) { -		US_DEBUGP("Load SD RW pattern Fail !!\n"); +		usb_stor_dbg(us, "Load SD RW pattern Fail !!\n");  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -1493,7 +1493,7 @@ static int ms_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)  	struct scatterlist *sg = NULL;  	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; -	US_DEBUGP("ms_scsi_read_capacity\n"); +	usb_stor_dbg(us, "ms_scsi_read_capacity\n");  	bl_len = 0x200;  	if (info->MS_Status.IsMSPro)  		bl_num = info->MSP_TotalBlock - 1; @@ -1501,8 +1501,8 @@ static int ms_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)  		bl_num = info->MS_Lib.NumberOfLogBlock * info->MS_Lib.blockSize * 2 - 1;  	info->bl_num = bl_num; -	US_DEBUGP("bl_len = %x\n", bl_len); -	US_DEBUGP("bl_num = %x\n", bl_num); +	usb_stor_dbg(us, "bl_len = %x\n", bl_len); +	usb_stor_dbg(us, "bl_num = %x\n", bl_num);  	/*srb->request_bufflen = 8; */  	buf[0] = (bl_num >> 24) & 0xff; @@ -1654,7 +1654,7 @@ static int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb)  	if (info->MS_Status.IsMSPro) {  		result = ene_load_bincode(us, MSP_RW_PATTERN);  		if (result != USB_STOR_XFER_GOOD) { -			US_DEBUGP("Load MPS RW pattern Fail !!\n"); +			usb_stor_dbg(us, "Load MPS RW pattern Fail !!\n");  			return USB_STOR_TRANSPORT_ERROR;  		} @@ -1854,7 +1854,7 @@ static int ene_get_card_status(struct us_data *us, u8 *buf)  	u32 reg4b;  	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; -	/*US_DEBUGP("transport --- ENE_ReadSDReg\n");*/ +	/*usb_stor_dbg(us, "transport --- ENE_ReadSDReg\n");*/  	reg4b = *(u32 *)&buf[0x18];  	info->SD_READ_BL_LEN = (u8)((reg4b >> 8) & 0x0f); @@ -1894,45 +1894,44 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag)  	switch (flag) {  	/* For SD */  	case SD_INIT1_PATTERN: -		US_DEBUGP("SD_INIT1_PATTERN\n"); +		usb_stor_dbg(us, "SD_INIT1_PATTERN\n");  		fw_name = SD_INIT1_FIRMWARE;  		break;  	case SD_INIT2_PATTERN: -		US_DEBUGP("SD_INIT2_PATTERN\n"); +		usb_stor_dbg(us, "SD_INIT2_PATTERN\n");  		fw_name = SD_INIT2_FIRMWARE;  		break;  	case SD_RW_PATTERN: -		US_DEBUGP("SD_RW_PATTERN\n"); +		usb_stor_dbg(us, "SD_RW_PATTERN\n");  		fw_name = SD_RW_FIRMWARE;  		break;  	/* For MS */  	case MS_INIT_PATTERN: -		US_DEBUGP("MS_INIT_PATTERN\n"); +		usb_stor_dbg(us, "MS_INIT_PATTERN\n");  		fw_name = MS_INIT_FIRMWARE;  		break;  	case MSP_RW_PATTERN: -		US_DEBUGP("MSP_RW_PATTERN\n"); +		usb_stor_dbg(us, "MSP_RW_PATTERN\n");  		fw_name = MSP_RW_FIRMWARE;  		break;  	case MS_RW_PATTERN: -		US_DEBUGP("MS_RW_PATTERN\n"); +		usb_stor_dbg(us, "MS_RW_PATTERN\n");  		fw_name = MS_RW_FIRMWARE;  		break;  	default: -		US_DEBUGP("----------- Unknown PATTERN ----------\n"); +		usb_stor_dbg(us, "----------- Unknown PATTERN ----------\n");  		goto nofw;  	}  	err = request_firmware(&sd_fw, fw_name, &us->pusb_dev->dev);  	if (err) { -		US_DEBUGP("load firmware %s failed\n", fw_name); +		usb_stor_dbg(us, "load firmware %s failed\n", fw_name);  		goto nofw;  	}  	buf = kmalloc(sd_fw->size, GFP_KERNEL); -	if (buf == NULL) { -		US_DEBUGP("Malloc memory for fireware failed!\n"); +	if (buf == NULL)  		goto nofw; -	} +  	memcpy(buf, sd_fw->data, sd_fw->size);  	memset(bcb, 0, sizeof(struct bulk_cb_wrap));  	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); @@ -2116,9 +2115,9 @@ static int ene_ms_init(struct us_data *us)  		} else {  			ms_card_init(us); /* Card is MS (to ms.c)*/  		} -		US_DEBUGP("MS Init Code OK !!\n"); +		usb_stor_dbg(us, "MS Init Code OK !!\n");  	} else { -		US_DEBUGP("MS Card Not Ready --- %x\n", buf[0]); +		usb_stor_dbg(us, "MS Card Not Ready --- %x\n", buf[0]);  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -2132,11 +2131,11 @@ static int ene_sd_init(struct us_data *us)  	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;  	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; -	US_DEBUGP("transport --- ENE_SDInit\n"); +	usb_stor_dbg(us, "transport --- ENE_SDInit\n");  	/* SD Init Part-1 */  	result = ene_load_bincode(us, SD_INIT1_PATTERN);  	if (result != USB_STOR_XFER_GOOD) { -		US_DEBUGP("Load SD Init Code Part-1 Fail !!\n"); +		usb_stor_dbg(us, "Load SD Init Code Part-1 Fail !!\n");  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -2147,14 +2146,14 @@ static int ene_sd_init(struct us_data *us)  	result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0);  	if (result != USB_STOR_XFER_GOOD) { -		US_DEBUGP("Execution SD Init Code Fail !!\n"); +		usb_stor_dbg(us, "Execution SD Init Code Fail !!\n");  		return USB_STOR_TRANSPORT_ERROR;  	}  	/* SD Init Part-2 */  	result = ene_load_bincode(us, SD_INIT2_PATTERN);  	if (result != USB_STOR_XFER_GOOD) { -		US_DEBUGP("Load SD Init Code Part-2 Fail !!\n"); +		usb_stor_dbg(us, "Load SD Init Code Part-2 Fail !!\n");  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -2166,21 +2165,23 @@ static int ene_sd_init(struct us_data *us)  	result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);  	if (result != USB_STOR_XFER_GOOD) { -		US_DEBUGP("Execution SD Init Code Fail !!\n"); +		usb_stor_dbg(us, "Execution SD Init Code Fail !!\n");  		return USB_STOR_TRANSPORT_ERROR;  	}  	info->SD_Status =  *(struct SD_STATUS *)&buf[0];  	if (info->SD_Status.Insert && info->SD_Status.Ready) { +		struct SD_STATUS *s = &info->SD_Status; +  		ene_get_card_status(us, (unsigned char *)&buf); -		US_DEBUGP("Insert     = %x\n", info->SD_Status.Insert); -		US_DEBUGP("Ready      = %x\n", info->SD_Status.Ready); -		US_DEBUGP("IsMMC      = %x\n", info->SD_Status.IsMMC); -		US_DEBUGP("HiCapacity = %x\n", info->SD_Status.HiCapacity); -		US_DEBUGP("HiSpeed    = %x\n", info->SD_Status.HiSpeed); -		US_DEBUGP("WtP        = %x\n", info->SD_Status.WtP); +		usb_stor_dbg(us, "Insert     = %x\n", s->Insert); +		usb_stor_dbg(us, "Ready      = %x\n", s->Ready); +		usb_stor_dbg(us, "IsMMC      = %x\n", s->IsMMC); +		usb_stor_dbg(us, "HiCapacity = %x\n", s->HiCapacity); +		usb_stor_dbg(us, "HiSpeed    = %x\n", s->HiSpeed); +		usb_stor_dbg(us, "WtP        = %x\n", s->WtP);  	} else { -		US_DEBUGP("SD Card Not Ready --- %x\n", buf[0]); +		usb_stor_dbg(us, "SD Card Not Ready --- %x\n", buf[0]);  		return USB_STOR_TRANSPORT_ERROR;  	}  	return USB_STOR_TRANSPORT_GOOD; @@ -2293,7 +2294,7 @@ static int ene_transport(struct scsi_cmnd *srb, struct us_data *us)  	int result = 0;  	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); -	/*US_DEBUG(usb_stor_show_command(srb)); */ +	/*US_DEBUG(usb_stor_show_command(us, srb)); */  	scsi_set_resid(srb, 0);  	if (unlikely(!(info->SD_Status.Ready || info->MS_Status.Ready))) {  		result = ene_init(us); @@ -2362,7 +2363,6 @@ static int ene_ub6250_resume(struct usb_interface *iface)  	mutex_lock(&us->dev_mutex); -	US_DEBUGP("%s\n", __func__);  	if (us->suspend_resume_hook)  		(us->suspend_resume_hook)(us, US_RESUME); @@ -2382,7 +2382,7 @@ static int ene_ub6250_reset_resume(struct usb_interface *iface)  	u8 tmp = 0;  	struct us_data *us = usb_get_intfdata(iface);  	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); -	US_DEBUGP("%s\n", __func__); +  	/* Report the reset to the SCSI core */  	usb_stor_reset_resume(iface); diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index e6df087dca9..ef16068b708 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -40,7 +40,7 @@ MODULE_AUTHOR("David Brown <usb-storage@davidb.org>");  MODULE_LICENSE("GPL");  #ifdef CONFIG_USB_STORAGE_DEBUG -static void pdump (void *, int); +static void pdump(struct us_data *us, void *ibuffer, int length);  #endif  /* Bits of HD_STATUS */ @@ -161,20 +161,20 @@ freecom_readdata (struct scsi_cmnd *srb, struct us_data *us,  	fxfr->Count = cpu_to_le32 (count);  	memset (fxfr->Pad, 0, sizeof (fxfr->Pad)); -	US_DEBUGP("Read data Freecom! (c=%d)\n", count); +	usb_stor_dbg(us, "Read data Freecom! (c=%d)\n", count);  	/* Issue the transfer command. */  	result = usb_stor_bulk_transfer_buf (us, opipe, fxfr,  			FCM_PACKET_LENGTH, NULL);  	if (result != USB_STOR_XFER_GOOD) { -		US_DEBUGP ("Freecom readdata transport error\n"); +		usb_stor_dbg(us, "Freecom readdata transport error\n");  		return USB_STOR_TRANSPORT_ERROR;  	}  	/* Now transfer all of our blocks. */ -	US_DEBUGP("Start of read\n"); +	usb_stor_dbg(us, "Start of read\n");  	result = usb_stor_bulk_srb(us, ipipe, srb); -	US_DEBUGP("freecom_readdata done!\n"); +	usb_stor_dbg(us, "freecom_readdata done!\n");  	if (result > USB_STOR_XFER_SHORT)  		return USB_STOR_TRANSPORT_ERROR; @@ -194,21 +194,21 @@ freecom_writedata (struct scsi_cmnd *srb, struct us_data *us,  	fxfr->Count = cpu_to_le32 (count);  	memset (fxfr->Pad, 0, sizeof (fxfr->Pad)); -	US_DEBUGP("Write data Freecom! (c=%d)\n", count); +	usb_stor_dbg(us, "Write data Freecom! (c=%d)\n", count);  	/* Issue the transfer command. */  	result = usb_stor_bulk_transfer_buf (us, opipe, fxfr,  			FCM_PACKET_LENGTH, NULL);  	if (result != USB_STOR_XFER_GOOD) { -		US_DEBUGP ("Freecom writedata transport error\n"); +		usb_stor_dbg(us, "Freecom writedata transport error\n");  		return USB_STOR_TRANSPORT_ERROR;  	}  	/* Now transfer all of our blocks. */ -	US_DEBUGP("Start of write\n"); +	usb_stor_dbg(us, "Start of write\n");  	result = usb_stor_bulk_srb(us, opipe, srb); -	US_DEBUGP("freecom_writedata done!\n"); +	usb_stor_dbg(us, "freecom_writedata done!\n");  	if (result > USB_STOR_XFER_SHORT)  		return USB_STOR_TRANSPORT_ERROR;  	return USB_STOR_TRANSPORT_GOOD; @@ -230,7 +230,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)  	fcb = (struct freecom_cb_wrap *) us->iobuf;  	fst = (struct freecom_status *) us->iobuf; -	US_DEBUGP("Freecom TRANSPORT STARTED\n"); +	usb_stor_dbg(us, "Freecom TRANSPORT STARTED\n");  	/* Get handles for both transports. */  	opipe = us->send_bulk_pipe; @@ -242,7 +242,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)  	memcpy (fcb->Atapi, srb->cmnd, 12);  	memset (fcb->Filler, 0, sizeof (fcb->Filler)); -	US_DEBUG(pdump (srb->cmnd, 12)); +	US_DEBUG(pdump(us, srb->cmnd, 12));  	/* Send it out. */  	result = usb_stor_bulk_transfer_buf (us, opipe, fcb, @@ -252,7 +252,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)  	 * USB land.  It returns the status in its own registers, which  	 * come back in the bulk pipe. */  	if (result != USB_STOR_XFER_GOOD) { -		US_DEBUGP ("freecom transport error\n"); +		usb_stor_dbg(us, "freecom transport error\n");  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -260,11 +260,11 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)  	 * doesn't hurt us to always do it now. */  	result = usb_stor_bulk_transfer_buf (us, ipipe, fst,  			FCM_STATUS_PACKET_LENGTH, &partial); -	US_DEBUGP("foo Status result %d %u\n", result, partial); +	usb_stor_dbg(us, "foo Status result %d %u\n", result, partial);  	if (result != USB_STOR_XFER_GOOD)  		return USB_STOR_TRANSPORT_ERROR; -	US_DEBUG(pdump ((void *) fst, partial)); +	US_DEBUG(pdump(us, (void *)fst, partial));  	/* The firmware will time-out commands after 20 seconds. Some commands  	 * can legitimately take longer than this, so we use a different @@ -275,8 +275,8 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)  	 * may not work, but that is a condition that should never happen.  	 */  	while (fst->Status & FCM_STATUS_BUSY) { -		US_DEBUGP("20 second USB/ATAPI bridge TIMEOUT occurred!\n"); -		US_DEBUGP("fst->Status is %x\n", fst->Status); +		usb_stor_dbg(us, "20 second USB/ATAPI bridge TIMEOUT occurred!\n"); +		usb_stor_dbg(us, "fst->Status is %x\n", fst->Status);  		/* Get the status again */  		fcb->Type = FCM_PACKET_STATUS; @@ -293,7 +293,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)  		 * registers, which come back in the bulk pipe.  		 */  		if (result != USB_STOR_XFER_GOOD) { -			US_DEBUGP ("freecom transport error\n"); +			usb_stor_dbg(us, "freecom transport error\n");  			return USB_STOR_TRANSPORT_ERROR;  		} @@ -301,26 +301,26 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)  		result = usb_stor_bulk_transfer_buf (us, ipipe, fst,  				FCM_STATUS_PACKET_LENGTH, &partial); -		US_DEBUGP("bar Status result %d %u\n", result, partial); +		usb_stor_dbg(us, "bar Status result %d %u\n", result, partial);  		if (result != USB_STOR_XFER_GOOD)  			return USB_STOR_TRANSPORT_ERROR; -		US_DEBUG(pdump ((void *) fst, partial)); +		US_DEBUG(pdump(us, (void *)fst, partial));  	}  	if (partial != 4)  		return USB_STOR_TRANSPORT_ERROR;  	if ((fst->Status & 1) != 0) { -		US_DEBUGP("operation failed\n"); +		usb_stor_dbg(us, "operation failed\n");  		return USB_STOR_TRANSPORT_FAILED;  	}  	/* The device might not have as much data available as we  	 * requested.  If you ask for more than the device has, this reads  	 * and such will hang. */ -	US_DEBUGP("Device indicates that it has %d bytes available\n", -			le16_to_cpu (fst->Count)); -	US_DEBUGP("SCSI requested %d\n", scsi_bufflen(srb)); +	usb_stor_dbg(us, "Device indicates that it has %d bytes available\n", +		     le16_to_cpu(fst->Count)); +	usb_stor_dbg(us, "SCSI requested %d\n", scsi_bufflen(srb));  	/* Find the length we desire to read. */  	switch (srb->cmnd[0]) { @@ -337,7 +337,8 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)  	/* verify that this amount is legal */  	if (length > scsi_bufflen(srb)) {  		length = scsi_bufflen(srb); -		US_DEBUGP("Truncating request to match buffer length: %d\n", length); +		usb_stor_dbg(us, "Truncating request to match buffer length: %d\n", +			     length);  	}  	/* What we do now depends on what direction the data is supposed to @@ -351,29 +352,29 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)  		/* Make sure that the status indicates that the device  		 * wants data as well. */  		if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) { -			US_DEBUGP("SCSI wants data, drive doesn't have any\n"); +			usb_stor_dbg(us, "SCSI wants data, drive doesn't have any\n");  			return USB_STOR_TRANSPORT_FAILED;  		}  		result = freecom_readdata (srb, us, ipipe, opipe, length);  		if (result != USB_STOR_TRANSPORT_GOOD)  			return result; -		US_DEBUGP("FCM: Waiting for status\n"); +		usb_stor_dbg(us, "Waiting for status\n");  		result = usb_stor_bulk_transfer_buf (us, ipipe, fst,  				FCM_PACKET_LENGTH, &partial); -		US_DEBUG(pdump ((void *) fst, partial)); +		US_DEBUG(pdump(us, (void *)fst, partial));  		if (partial != 4 || result > USB_STOR_XFER_SHORT)  			return USB_STOR_TRANSPORT_ERROR;  		if ((fst->Status & ERR_STAT) != 0) { -			US_DEBUGP("operation failed\n"); +			usb_stor_dbg(us, "operation failed\n");  			return USB_STOR_TRANSPORT_FAILED;  		}  		if ((fst->Reason & 3) != 3) { -			US_DEBUGP("Drive seems still hungry\n"); +			usb_stor_dbg(us, "Drive seems still hungry\n");  			return USB_STOR_TRANSPORT_FAILED;  		} -		US_DEBUGP("Transfer happy\n"); +		usb_stor_dbg(us, "Transfer happy\n");  		break;  	case DMA_TO_DEVICE: @@ -387,22 +388,22 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)  		if (result != USB_STOR_TRANSPORT_GOOD)  			return result; -		US_DEBUGP("FCM: Waiting for status\n"); +		usb_stor_dbg(us, "Waiting for status\n");  		result = usb_stor_bulk_transfer_buf (us, ipipe, fst,  				FCM_PACKET_LENGTH, &partial);  		if (partial != 4 || result > USB_STOR_XFER_SHORT)  			return USB_STOR_TRANSPORT_ERROR;  		if ((fst->Status & ERR_STAT) != 0) { -			US_DEBUGP("operation failed\n"); +			usb_stor_dbg(us, "operation failed\n");  			return USB_STOR_TRANSPORT_FAILED;  		}  		if ((fst->Reason & 3) != 3) { -			US_DEBUGP("Drive seems still hungry\n"); +			usb_stor_dbg(us, "Drive seems still hungry\n");  			return USB_STOR_TRANSPORT_FAILED;  		} -		US_DEBUGP("Transfer happy\n"); +		usb_stor_dbg(us, "Transfer happy\n");  		break; @@ -412,8 +413,8 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)  	default:  		/* should never hit here -- filtered in usb.c */ -		US_DEBUGP ("freecom unimplemented direction: %d\n", -				us->srb->sc_data_direction); +		usb_stor_dbg(us, "freecom unimplemented direction: %d\n", +			     us->srb->sc_data_direction);  		/* Return fail, SCSI seems to handle this better. */  		return USB_STOR_TRANSPORT_FAILED;  		break; @@ -434,7 +435,7 @@ static int init_freecom(struct us_data *us)  	result = usb_stor_control_msg(us, us->recv_ctrl_pipe,  			0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ);  	buffer[32] = '\0'; -	US_DEBUGP("String returned from FC init is: %s\n", buffer); +	usb_stor_dbg(us, "String returned from FC init is: %s\n", buffer);  	/* Special thanks to the people at Freecom for providing me with  	 * this "magic sequence", which they use in their Windows and MacOS @@ -445,7 +446,7 @@ static int init_freecom(struct us_data *us)  	/* send reset */  	result = usb_stor_control_msg(us, us->send_ctrl_pipe,  			0x4d, 0x40, 0x24d8, 0x0, NULL, 0x0, 3*HZ); -	US_DEBUGP("result from activate reset is %d\n", result); +	usb_stor_dbg(us, "result from activate reset is %d\n", result);  	/* wait 250ms */  	mdelay(250); @@ -453,7 +454,7 @@ static int init_freecom(struct us_data *us)  	/* clear reset */  	result = usb_stor_control_msg(us, us->send_ctrl_pipe,  			0x4d, 0x40, 0x24f8, 0x0, NULL, 0x0, 3*HZ); -	US_DEBUGP("result from clear reset is %d\n", result); +	usb_stor_dbg(us, "result from clear reset is %d\n", result);  	/* wait 3 seconds */  	mdelay(3 * 1000); @@ -470,7 +471,7 @@ static int usb_stor_freecom_reset(struct us_data *us)  }  #ifdef CONFIG_USB_STORAGE_DEBUG -static void pdump (void *ibuffer, int length) +static void pdump(struct us_data *us, void *ibuffer, int length)  {  	static char line[80];  	int offset = 0; @@ -490,7 +491,7 @@ static void pdump (void *ibuffer, int length)  						line[offset++] = '.';  				}  				line[offset] = 0; -				US_DEBUGP("%s\n", line); +				usb_stor_dbg(us, "%s\n", line);  				offset = 0;  			}  			offset += sprintf (line+offset, "%08x:", i); @@ -517,7 +518,7 @@ static void pdump (void *ibuffer, int length)  			line[offset++] = '.';  	}  	line[offset] = 0; -	US_DEBUGP("%s\n", line); +	usb_stor_dbg(us, "%s\n", line);  	offset = 0;  }  #endif diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 105d900150c..5a8b5ff1e45 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c @@ -48,12 +48,12 @@ int usb_stor_euscsi_init(struct us_data *us)  {  	int result; -	US_DEBUGP("Attempting to init eUSCSI bridge...\n"); +	usb_stor_dbg(us, "Attempting to init eUSCSI bridge...\n");  	us->iobuf[0] = 0x1;  	result = usb_stor_control_msg(us, us->send_ctrl_pipe,  			0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR,  			0x01, 0x0, us->iobuf, 0x1, 5000); -	US_DEBUGP("-- result is %d\n", result); +	usb_stor_dbg(us, "-- result is %d\n", result);  	return 0;  } @@ -68,7 +68,7 @@ int usb_stor_ucr61s2b_init(struct us_data *us)  	unsigned int partial;  	static char init_string[] = "\xec\x0a\x06\x00$PCCHIPS"; -	US_DEBUGP("Sending UCR-61S2B initialization packet...\n"); +	usb_stor_dbg(us, "Sending UCR-61S2B initialization packet...\n");  	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);  	bcb->Tag = 0; @@ -83,7 +83,7 @@ int usb_stor_ucr61s2b_init(struct us_data *us)  	if (res)  		return -EIO; -	US_DEBUGP("Getting status packet...\n"); +	usb_stor_dbg(us, "Getting status packet...\n");  	res = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,  			US_BULK_CS_WRAP_LEN, &partial);  	if (res) @@ -101,6 +101,6 @@ int usb_stor_huawei_e220_init(struct us_data *us)  				      USB_REQ_SET_FEATURE,  				      USB_TYPE_STANDARD | USB_RECIP_DEVICE,  				      0x01, 0x0, NULL, 0x0, 1000); -	US_DEBUGP("Huawei mode set result is %d\n", result); +	usb_stor_dbg(us, "Huawei mode set result is %d\n", result);  	return 0;  } diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index ecea4787736..599d8bff26c 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -503,7 +503,7 @@ static int isd200_action( struct us_data *us, int action,  	switch ( action ) {  	case ACTION_READ_STATUS: -		US_DEBUGP("   isd200_action(READ_STATUS)\n"); +		usb_stor_dbg(us, "   isd200_action(READ_STATUS)\n");  		ata.generic.ActionSelect = ACTION_SELECT_0|ACTION_SELECT_2;  		ata.generic.RegisterSelect =  		  REG_CYLINDER_LOW | REG_CYLINDER_HIGH | @@ -512,7 +512,7 @@ static int isd200_action( struct us_data *us, int action,  		break;  	case ACTION_ENUM: -		US_DEBUGP("   isd200_action(ENUM,0x%02x)\n",value); +		usb_stor_dbg(us, "   isd200_action(ENUM,0x%02x)\n", value);  		ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|  					   ACTION_SELECT_3|ACTION_SELECT_4|  					   ACTION_SELECT_5; @@ -522,7 +522,7 @@ static int isd200_action( struct us_data *us, int action,  		break;  	case ACTION_RESET: -		US_DEBUGP("   isd200_action(RESET)\n"); +		usb_stor_dbg(us, "   isd200_action(RESET)\n");  		ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|  					   ACTION_SELECT_3|ACTION_SELECT_4;  		ata.generic.RegisterSelect = REG_DEVICE_CONTROL; @@ -531,7 +531,7 @@ static int isd200_action( struct us_data *us, int action,  		break;  	case ACTION_REENABLE: -		US_DEBUGP("   isd200_action(REENABLE)\n"); +		usb_stor_dbg(us, "   isd200_action(REENABLE)\n");  		ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|  					   ACTION_SELECT_3|ACTION_SELECT_4;  		ata.generic.RegisterSelect = REG_DEVICE_CONTROL; @@ -540,7 +540,7 @@ static int isd200_action( struct us_data *us, int action,  		break;  	case ACTION_SOFT_RESET: -		US_DEBUGP("   isd200_action(SOFT_RESET)\n"); +		usb_stor_dbg(us, "   isd200_action(SOFT_RESET)\n");  		ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_5;  		ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND;  		ata.write.DeviceHeadByte = info->DeviceHead; @@ -549,7 +549,7 @@ static int isd200_action( struct us_data *us, int action,  		break;  	case ACTION_IDENTIFY: -		US_DEBUGP("   isd200_action(IDENTIFY)\n"); +		usb_stor_dbg(us, "   isd200_action(IDENTIFY)\n");  		ata.generic.RegisterSelect = REG_COMMAND;  		ata.write.CommandByte = ATA_CMD_ID_ATA;  		isd200_set_srb(info, DMA_FROM_DEVICE, info->id, @@ -557,7 +557,7 @@ static int isd200_action( struct us_data *us, int action,  		break;  	default: -		US_DEBUGP("Error: Undefined action %d\n",action); +		usb_stor_dbg(us, "Error: Undefined action %d\n", action);  		return ISD200_ERROR;  	} @@ -567,7 +567,8 @@ static int isd200_action( struct us_data *us, int action,  	if (status == USB_STOR_TRANSPORT_GOOD)  		status = ISD200_GOOD;  	else { -		US_DEBUGP("   isd200_action(0x%02x) error: %d\n",action,status); +		usb_stor_dbg(us, "   isd200_action(0x%02x) error: %d\n", +			     action, status);  		status = ISD200_ERROR;  		/* need to reset device here */  	} @@ -589,17 +590,17 @@ static int isd200_read_regs( struct us_data *us )  	int retStatus = ISD200_GOOD;  	int transferStatus; -	US_DEBUGP("Entering isd200_IssueATAReadRegs\n"); +	usb_stor_dbg(us, "Entering isd200_IssueATAReadRegs\n");  	transferStatus = isd200_action( us, ACTION_READ_STATUS,  				    info->RegsBuf, sizeof(info->ATARegs) );  	if (transferStatus != ISD200_TRANSPORT_GOOD) { -		US_DEBUGP("   Error reading ATA registers\n"); +		usb_stor_dbg(us, "   Error reading ATA registers\n");  		retStatus = ISD200_ERROR;  	} else {  		memcpy(info->ATARegs, info->RegsBuf, sizeof(info->ATARegs)); -		US_DEBUGP("   Got ATA Register[ATA_REG_ERROR_OFFSET] = 0x%x\n", -			  info->ATARegs[ATA_REG_ERROR_OFFSET]); +		usb_stor_dbg(us, "   Got ATA Register[ATA_REG_ERROR_OFFSET] = 0x%x\n", +			     info->ATARegs[ATA_REG_ERROR_OFFSET]);  	}  	return retStatus; @@ -629,7 +630,7 @@ static void isd200_invoke_transport( struct us_data *us,  	 * short-circuit all other processing  	 */  	if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { -		US_DEBUGP("-- command was aborted\n"); +		usb_stor_dbg(us, "-- command was aborted\n");  		goto Handle_Abort;  	} @@ -641,23 +642,23 @@ static void isd200_invoke_transport( struct us_data *us,  		break;  	case USB_STOR_TRANSPORT_NO_SENSE: -		US_DEBUGP("-- transport indicates protocol failure\n"); +		usb_stor_dbg(us, "-- transport indicates protocol failure\n");  		srb->result = SAM_STAT_CHECK_CONDITION;  		return;  	case USB_STOR_TRANSPORT_FAILED: -		US_DEBUGP("-- transport indicates command failure\n"); +		usb_stor_dbg(us, "-- transport indicates command failure\n");  		need_auto_sense = 1;  		break;  	case USB_STOR_TRANSPORT_ERROR: -		US_DEBUGP("-- transport indicates transport error\n"); +		usb_stor_dbg(us, "-- transport indicates transport error\n");  		srb->result = DID_ERROR << 16;  		/* Need reset here */  		return;  	default: -		US_DEBUGP("-- transport indicates unknown error\n");    +		usb_stor_dbg(us, "-- transport indicates unknown error\n");  		srb->result = DID_ERROR << 16;  		/* Need reset here */  		return; @@ -669,14 +670,14 @@ static void isd200_invoke_transport( struct us_data *us,  	      (srb->cmnd[0] == MODE_SENSE) ||  	      (srb->cmnd[0] == LOG_SENSE) ||  	      (srb->cmnd[0] == MODE_SENSE_10))) { -		US_DEBUGP("-- unexpectedly short transfer\n"); +		usb_stor_dbg(us, "-- unexpectedly short transfer\n");  		need_auto_sense = 1;  	}  	if (need_auto_sense) {  		result = isd200_read_regs(us);  		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { -			US_DEBUGP("-- auto-sense aborted\n"); +			usb_stor_dbg(us, "-- auto-sense aborted\n");  			goto Handle_Abort;  		}  		if (result == ISD200_GOOD) { @@ -710,40 +711,40 @@ static void isd200_invoke_transport( struct us_data *us,  }  #ifdef CONFIG_USB_STORAGE_DEBUG -static void isd200_log_config( struct isd200_info* info ) +static void isd200_log_config(struct us_data *us, struct isd200_info *info)  { -	US_DEBUGP("      Event Notification: 0x%x\n",  -		  info->ConfigData.EventNotification); -	US_DEBUGP("      External Clock: 0x%x\n",  -		  info->ConfigData.ExternalClock); -	US_DEBUGP("      ATA Init Timeout: 0x%x\n",  -		  info->ConfigData.ATAInitTimeout); -	US_DEBUGP("      ATAPI Command Block Size: 0x%x\n",  -		  (info->ConfigData.ATAConfig & ATACFG_BLOCKSIZE) >> 6); -	US_DEBUGP("      Master/Slave Selection: 0x%x\n",  -		  info->ConfigData.ATAConfig & ATACFG_MASTER); -	US_DEBUGP("      ATAPI Reset: 0x%x\n", -		  info->ConfigData.ATAConfig & ATACFG_ATAPI_RESET); -	US_DEBUGP("      ATA Timing: 0x%x\n", -		  info->ConfigData.ATAConfig & ATACFG_TIMING); -	US_DEBUGP("      ATA Major Command: 0x%x\n",  -		  info->ConfigData.ATAMajorCommand); -	US_DEBUGP("      ATA Minor Command: 0x%x\n",  -		  info->ConfigData.ATAMinorCommand); -	US_DEBUGP("      Init Status: 0x%x\n",  -		  info->ConfigData.ATAExtraConfig & ATACFGE_INIT_STATUS); -	US_DEBUGP("      Config Descriptor 2: 0x%x\n",  -		  info->ConfigData.ATAExtraConfig & ATACFGE_CONF_DESC2); -	US_DEBUGP("      Skip Device Boot: 0x%x\n", -		  info->ConfigData.ATAExtraConfig & ATACFGE_SKIP_BOOT); -	US_DEBUGP("      ATA 3 State Supsend: 0x%x\n", -		  info->ConfigData.ATAExtraConfig & ATACFGE_STATE_SUSPEND); -	US_DEBUGP("      Descriptor Override: 0x%x\n",  -		  info->ConfigData.ATAExtraConfig & ATACFGE_DESC_OVERRIDE); -	US_DEBUGP("      Last LUN Identifier: 0x%x\n", -		  info->ConfigData.ATAExtraConfig & ATACFGE_LAST_LUN); -	US_DEBUGP("      SRST Enable: 0x%x\n",  -		  info->ConfigData.ATAExtraConfig & CFG_CAPABILITY_SRST); +	usb_stor_dbg(us, "      Event Notification: 0x%x\n", +		     info->ConfigData.EventNotification); +	usb_stor_dbg(us, "      External Clock: 0x%x\n", +		     info->ConfigData.ExternalClock); +	usb_stor_dbg(us, "      ATA Init Timeout: 0x%x\n", +		     info->ConfigData.ATAInitTimeout); +	usb_stor_dbg(us, "      ATAPI Command Block Size: 0x%x\n", +		     (info->ConfigData.ATAConfig & ATACFG_BLOCKSIZE) >> 6); +	usb_stor_dbg(us, "      Master/Slave Selection: 0x%x\n", +		     info->ConfigData.ATAConfig & ATACFG_MASTER); +	usb_stor_dbg(us, "      ATAPI Reset: 0x%x\n", +		     info->ConfigData.ATAConfig & ATACFG_ATAPI_RESET); +	usb_stor_dbg(us, "      ATA Timing: 0x%x\n", +		     info->ConfigData.ATAConfig & ATACFG_TIMING); +	usb_stor_dbg(us, "      ATA Major Command: 0x%x\n", +		     info->ConfigData.ATAMajorCommand); +	usb_stor_dbg(us, "      ATA Minor Command: 0x%x\n", +		     info->ConfigData.ATAMinorCommand); +	usb_stor_dbg(us, "      Init Status: 0x%x\n", +		     info->ConfigData.ATAExtraConfig & ATACFGE_INIT_STATUS); +	usb_stor_dbg(us, "      Config Descriptor 2: 0x%x\n", +		     info->ConfigData.ATAExtraConfig & ATACFGE_CONF_DESC2); +	usb_stor_dbg(us, "      Skip Device Boot: 0x%x\n", +		     info->ConfigData.ATAExtraConfig & ATACFGE_SKIP_BOOT); +	usb_stor_dbg(us, "      ATA 3 State Supsend: 0x%x\n", +		     info->ConfigData.ATAExtraConfig & ATACFGE_STATE_SUSPEND); +	usb_stor_dbg(us, "      Descriptor Override: 0x%x\n", +		     info->ConfigData.ATAExtraConfig & ATACFGE_DESC_OVERRIDE); +	usb_stor_dbg(us, "      Last LUN Identifier: 0x%x\n", +		     info->ConfigData.ATAExtraConfig & ATACFGE_LAST_LUN); +	usb_stor_dbg(us, "      SRST Enable: 0x%x\n", +		     info->ConfigData.ATAExtraConfig & CFG_CAPABILITY_SRST);  }  #endif @@ -762,9 +763,9 @@ static int isd200_write_config( struct us_data *us )  	int result;  #ifdef CONFIG_USB_STORAGE_DEBUG -	US_DEBUGP("Entering isd200_write_config\n"); -	US_DEBUGP("   Writing the following ISD200 Config Data:\n"); -	isd200_log_config(info); +	usb_stor_dbg(us, "Entering isd200_write_config\n"); +	usb_stor_dbg(us, "   Writing the following ISD200 Config Data:\n"); +	isd200_log_config(us, info);  #endif  	/* let's send the command via the control pipe */ @@ -779,13 +780,13 @@ static int isd200_write_config( struct us_data *us )  		sizeof(info->ConfigData));  	if (result >= 0) { -		US_DEBUGP("   ISD200 Config Data was written successfully\n"); +		usb_stor_dbg(us, "   ISD200 Config Data was written successfully\n");  	} else { -		US_DEBUGP("   Request to write ISD200 Config Data failed!\n"); +		usb_stor_dbg(us, "   Request to write ISD200 Config Data failed!\n");  		retStatus = ISD200_ERROR;  	} -	US_DEBUGP("Leaving isd200_write_config %08X\n", retStatus); +	usb_stor_dbg(us, "Leaving isd200_write_config %08X\n", retStatus);  	return retStatus;  } @@ -804,7 +805,7 @@ static int isd200_read_config( struct us_data *us )  	int retStatus = ISD200_GOOD;  	int result; -	US_DEBUGP("Entering isd200_read_config\n"); +	usb_stor_dbg(us, "Entering isd200_read_config\n");  	/* read the configuration information from ISD200.  Use this to */  	/* determine what the special ATA CDB bytes are.		*/ @@ -821,16 +822,16 @@ static int isd200_read_config( struct us_data *us )  	if (result >= 0) { -		US_DEBUGP("   Retrieved the following ISD200 Config Data:\n"); +		usb_stor_dbg(us, "   Retrieved the following ISD200 Config Data:\n");  #ifdef CONFIG_USB_STORAGE_DEBUG -		isd200_log_config(info); +		isd200_log_config(us, info);  #endif  	} else { -		US_DEBUGP("   Request to get ISD200 Config Data failed!\n"); +		usb_stor_dbg(us, "   Request to get ISD200 Config Data failed!\n");  		retStatus = ISD200_ERROR;  	} -	US_DEBUGP("Leaving isd200_read_config %08X\n", retStatus); +	usb_stor_dbg(us, "Leaving isd200_read_config %08X\n", retStatus);  	return retStatus;  } @@ -848,15 +849,15 @@ static int isd200_atapi_soft_reset( struct us_data *us )  	int retStatus = ISD200_GOOD;  	int transferStatus; -	US_DEBUGP("Entering isd200_atapi_soft_reset\n"); +	usb_stor_dbg(us, "Entering isd200_atapi_soft_reset\n");  	transferStatus = isd200_action( us, ACTION_SOFT_RESET, NULL, 0 );  	if (transferStatus != ISD200_TRANSPORT_GOOD) { -		US_DEBUGP("   Error issuing Atapi Soft Reset\n"); +		usb_stor_dbg(us, "   Error issuing Atapi Soft Reset\n");  		retStatus = ISD200_ERROR;  	} -	US_DEBUGP("Leaving isd200_atapi_soft_reset %08X\n", retStatus); +	usb_stor_dbg(us, "Leaving isd200_atapi_soft_reset %08X\n", retStatus);  	return retStatus;  } @@ -874,13 +875,13 @@ static int isd200_srst( struct us_data *us )  	int retStatus = ISD200_GOOD;  	int transferStatus; -	US_DEBUGP("Entering isd200_SRST\n"); +	usb_stor_dbg(us, "Entering isd200_SRST\n");  	transferStatus = isd200_action( us, ACTION_RESET, NULL, 0 );  	/* check to see if this request failed */  	if (transferStatus != ISD200_TRANSPORT_GOOD) { -		US_DEBUGP("   Error issuing SRST\n"); +		usb_stor_dbg(us, "   Error issuing SRST\n");  		retStatus = ISD200_ERROR;  	} else {  		/* delay 10ms to give the drive a chance to see it */ @@ -888,7 +889,7 @@ static int isd200_srst( struct us_data *us )  		transferStatus = isd200_action( us, ACTION_REENABLE, NULL, 0 );  		if (transferStatus != ISD200_TRANSPORT_GOOD) { -			US_DEBUGP("   Error taking drive out of reset\n"); +			usb_stor_dbg(us, "   Error taking drive out of reset\n");  			retStatus = ISD200_ERROR;  		} else {  			/* delay 50ms to give the drive a chance to recover after SRST */ @@ -896,7 +897,7 @@ static int isd200_srst( struct us_data *us )  		}  	} -	US_DEBUGP("Leaving isd200_srst %08X\n", retStatus); +	usb_stor_dbg(us, "Leaving isd200_srst %08X\n", retStatus);  	return retStatus;  } @@ -926,10 +927,6 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,  	/* loop until we detect !BSY or timeout */  	while(1) { -#ifdef CONFIG_USB_STORAGE_DEBUG -		char* mstr = master_slave == ATA_ADDRESS_DEVHEAD_STD ? -			"Master" : "Slave"; -#endif  		status = isd200_action( us, ACTION_ENUM, NULL, master_slave );  		if ( status != ISD200_GOOD ) @@ -942,9 +939,13 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,  		if (!detect) {  			if (regs[ATA_REG_STATUS_OFFSET] & ATA_BUSY) { -				US_DEBUGP("   %s status is still BSY, try again...\n",mstr); +				usb_stor_dbg(us, "   %s status is still BSY, try again...\n", +					     master_slave == ATA_ADDRESS_DEVHEAD_STD ? +					     "Master" : "Slave");  			} else { -				US_DEBUGP("   %s status !BSY, continue with next operation\n",mstr); +				usb_stor_dbg(us, "   %s status !BSY, continue with next operation\n", +					     master_slave == ATA_ADDRESS_DEVHEAD_STD ? +					     "Master" : "Slave");  				break;  			}  		} @@ -953,11 +954,11 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,  		/* ATA_ERR (workaround for Archos CD-ROM) */  		else if (regs[ATA_REG_STATUS_OFFSET] &  			 (ATA_BUSY | ATA_DF | ATA_ERR)) { -			US_DEBUGP("   Status indicates it is not ready, try again...\n"); +			usb_stor_dbg(us, "   Status indicates it is not ready, try again...\n");  		}  		/* check for DRDY, ATA devices set DRDY after SRST */  		else if (regs[ATA_REG_STATUS_OFFSET] & ATA_DRDY) { -			US_DEBUGP("   Identified ATA device\n"); +			usb_stor_dbg(us, "   Identified ATA device\n");  			info->DeviceFlags |= DF_ATA_DEVICE;  			info->DeviceHead = master_slave;  			break; @@ -978,27 +979,27 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,  			*/  			if ((master_slave & ATA_ADDRESS_DEVHEAD_SLAVE) &&  			    !recheckAsMaster) { -				US_DEBUGP("   Identified ATAPI device as slave.  Rechecking again as master\n"); +				usb_stor_dbg(us, "   Identified ATAPI device as slave.  Rechecking again as master\n");  				recheckAsMaster = 1;  				master_slave = ATA_ADDRESS_DEVHEAD_STD;  			} else { -				US_DEBUGP("   Identified ATAPI device\n"); +				usb_stor_dbg(us, "   Identified ATAPI device\n");  				info->DeviceHead = master_slave;  				status = isd200_atapi_soft_reset(us);  				break;  			}  		} else { - 			US_DEBUGP("   Not ATA, not ATAPI. Weird.\n"); +			usb_stor_dbg(us, "   Not ATA, not ATAPI - Weird\n");  			break;  		}  		/* check for timeout on this request */  		if (time_after_eq(jiffies, endTime)) {  			if (!detect) -				US_DEBUGP("   BSY check timeout, just continue with next operation...\n"); +				usb_stor_dbg(us, "   BSY check timeout, just continue with next operation...\n");  			else -				US_DEBUGP("   Device detect timeout!\n"); +				usb_stor_dbg(us, "   Device detect timeout!\n");  			break;  		}  	} @@ -1020,7 +1021,7 @@ static int isd200_manual_enum(struct us_data *us)  	struct isd200_info *info = (struct isd200_info *)us->extra;  	int retStatus = ISD200_GOOD; -	US_DEBUGP("Entering isd200_manual_enum\n"); +	usb_stor_dbg(us, "Entering isd200_manual_enum\n");  	retStatus = isd200_read_config(us);  	if (retStatus == ISD200_GOOD) { @@ -1039,14 +1040,15 @@ static int isd200_manual_enum(struct us_data *us)  		isslave = (info->DeviceHead & ATA_ADDRESS_DEVHEAD_SLAVE) ? 1 : 0;  		if (!(info->ConfigData.ATAConfig & ATACFG_MASTER)) { -			US_DEBUGP("   Setting Master/Slave selection to %d\n", isslave); +			usb_stor_dbg(us, "   Setting Master/Slave selection to %d\n", +				     isslave);  			info->ConfigData.ATAConfig &= 0x3f;  			info->ConfigData.ATAConfig |= (isslave<<6);  			retStatus = isd200_write_config(us);  		}  	} -	US_DEBUGP("Leaving isd200_manual_enum %08X\n", retStatus); +	usb_stor_dbg(us, "Leaving isd200_manual_enum %08X\n", retStatus);  	return(retStatus);  } @@ -1064,35 +1066,35 @@ static void isd200_fix_driveid(u16 *id)  #endif  } -static void isd200_dump_driveid(u16 *id) +static void isd200_dump_driveid(struct us_data *us, u16 *id)  { -	US_DEBUGP("   Identify Data Structure:\n"); -	US_DEBUGP("      config = 0x%x\n",	  id[ATA_ID_CONFIG]); -	US_DEBUGP("      cyls = 0x%x\n",	  id[ATA_ID_CYLS]); -	US_DEBUGP("      heads = 0x%x\n",	  id[ATA_ID_HEADS]); -	US_DEBUGP("      track_bytes = 0x%x\n",	  id[4]); -	US_DEBUGP("      sector_bytes = 0x%x\n",  id[5]); -	US_DEBUGP("      sectors = 0x%x\n",	  id[ATA_ID_SECTORS]); -	US_DEBUGP("      serial_no[0] = 0x%x\n",  *(char *)&id[ATA_ID_SERNO]); -	US_DEBUGP("      buf_type = 0x%x\n",	  id[20]); -	US_DEBUGP("      buf_size = 0x%x\n",	  id[ATA_ID_BUF_SIZE]); -	US_DEBUGP("      ecc_bytes = 0x%x\n",	  id[22]); -	US_DEBUGP("      fw_rev[0] = 0x%x\n",	  *(char *)&id[ATA_ID_FW_REV]); -	US_DEBUGP("      model[0] = 0x%x\n",	  *(char *)&id[ATA_ID_PROD]); -	US_DEBUGP("      max_multsect = 0x%x\n",  id[ATA_ID_MAX_MULTSECT] & 0xff); -	US_DEBUGP("      dword_io = 0x%x\n",	  id[ATA_ID_DWORD_IO]); -	US_DEBUGP("      capability = 0x%x\n",	  id[ATA_ID_CAPABILITY] >> 8); -	US_DEBUGP("      tPIO = 0x%x\n",	  id[ATA_ID_OLD_PIO_MODES] >> 8); -	US_DEBUGP("      tDMA = 0x%x\n",	  id[ATA_ID_OLD_DMA_MODES] >> 8); -	US_DEBUGP("      field_valid = 0x%x\n",	  id[ATA_ID_FIELD_VALID]); -	US_DEBUGP("      cur_cyls = 0x%x\n",	  id[ATA_ID_CUR_CYLS]); -	US_DEBUGP("      cur_heads = 0x%x\n",	  id[ATA_ID_CUR_HEADS]); -	US_DEBUGP("      cur_sectors = 0x%x\n",	  id[ATA_ID_CUR_SECTORS]); -	US_DEBUGP("      cur_capacity = 0x%x\n",  ata_id_u32(id, 57)); -	US_DEBUGP("      multsect = 0x%x\n",	  id[ATA_ID_MULTSECT] & 0xff); -	US_DEBUGP("      lba_capacity = 0x%x\n",  ata_id_u32(id, ATA_ID_LBA_CAPACITY)); -	US_DEBUGP("      command_set_1 = 0x%x\n", id[ATA_ID_COMMAND_SET_1]); -	US_DEBUGP("      command_set_2 = 0x%x\n", id[ATA_ID_COMMAND_SET_2]); +	usb_stor_dbg(us, "   Identify Data Structure:\n"); +	usb_stor_dbg(us, "      config = 0x%x\n",	id[ATA_ID_CONFIG]); +	usb_stor_dbg(us, "      cyls = 0x%x\n",		id[ATA_ID_CYLS]); +	usb_stor_dbg(us, "      heads = 0x%x\n",	id[ATA_ID_HEADS]); +	usb_stor_dbg(us, "      track_bytes = 0x%x\n",	id[4]); +	usb_stor_dbg(us, "      sector_bytes = 0x%x\n", id[5]); +	usb_stor_dbg(us, "      sectors = 0x%x\n",	id[ATA_ID_SECTORS]); +	usb_stor_dbg(us, "      serial_no[0] = 0x%x\n", *(char *)&id[ATA_ID_SERNO]); +	usb_stor_dbg(us, "      buf_type = 0x%x\n",	id[20]); +	usb_stor_dbg(us, "      buf_size = 0x%x\n",	id[ATA_ID_BUF_SIZE]); +	usb_stor_dbg(us, "      ecc_bytes = 0x%x\n",	id[22]); +	usb_stor_dbg(us, "      fw_rev[0] = 0x%x\n",	*(char *)&id[ATA_ID_FW_REV]); +	usb_stor_dbg(us, "      model[0] = 0x%x\n",	*(char *)&id[ATA_ID_PROD]); +	usb_stor_dbg(us, "      max_multsect = 0x%x\n", id[ATA_ID_MAX_MULTSECT] & 0xff); +	usb_stor_dbg(us, "      dword_io = 0x%x\n",	id[ATA_ID_DWORD_IO]); +	usb_stor_dbg(us, "      capability = 0x%x\n",	id[ATA_ID_CAPABILITY] >> 8); +	usb_stor_dbg(us, "      tPIO = 0x%x\n",	  id[ATA_ID_OLD_PIO_MODES] >> 8); +	usb_stor_dbg(us, "      tDMA = 0x%x\n",	  id[ATA_ID_OLD_DMA_MODES] >> 8); +	usb_stor_dbg(us, "      field_valid = 0x%x\n",	id[ATA_ID_FIELD_VALID]); +	usb_stor_dbg(us, "      cur_cyls = 0x%x\n",	id[ATA_ID_CUR_CYLS]); +	usb_stor_dbg(us, "      cur_heads = 0x%x\n",	id[ATA_ID_CUR_HEADS]); +	usb_stor_dbg(us, "      cur_sectors = 0x%x\n",	id[ATA_ID_CUR_SECTORS]); +	usb_stor_dbg(us, "      cur_capacity = 0x%x\n", ata_id_u32(id, 57)); +	usb_stor_dbg(us, "      multsect = 0x%x\n",	id[ATA_ID_MULTSECT] & 0xff); +	usb_stor_dbg(us, "      lba_capacity = 0x%x\n", ata_id_u32(id, ATA_ID_LBA_CAPACITY)); +	usb_stor_dbg(us, "      command_set_1 = 0x%x\n", id[ATA_ID_COMMAND_SET_1]); +	usb_stor_dbg(us, "      command_set_2 = 0x%x\n", id[ATA_ID_COMMAND_SET_2]);  }  /************************************************************************** @@ -1109,7 +1111,7 @@ static int isd200_get_inquiry_data( struct us_data *us )  	int retStatus = ISD200_GOOD;  	u16 *id = info->id; -	US_DEBUGP("Entering isd200_get_inquiry_data\n"); +	usb_stor_dbg(us, "Entering isd200_get_inquiry_data\n");  	/* set default to Master */  	info->DeviceHead = ATA_ADDRESS_DEVHEAD_STD; @@ -1127,7 +1129,7 @@ static int isd200_get_inquiry_data( struct us_data *us )  							id, ATA_ID_WORDS * 2);  			if (transferStatus != ISD200_TRANSPORT_GOOD) {  				/* Error issuing ATA Command Identify */ -				US_DEBUGP("   Error issuing ATA Command Identify\n"); +				usb_stor_dbg(us, "   Error issuing ATA Command Identify\n");  				retStatus = ISD200_ERROR;  			} else {  				/* ATA Command Identify successful */ @@ -1136,7 +1138,7 @@ static int isd200_get_inquiry_data( struct us_data *us )  				__u16 *dest;  				isd200_fix_driveid(id); -				isd200_dump_driveid(id); +				isd200_dump_driveid(us, id);  				memset(&info->InquiryData, 0, sizeof(info->InquiryData)); @@ -1170,7 +1172,7 @@ static int isd200_get_inquiry_data( struct us_data *us )  				/* determine if it supports Media Status Notification */  				if (id[ATA_ID_COMMAND_SET_2] & COMMANDSET_MEDIA_STATUS) { -					US_DEBUGP("   Device supports Media Status Notification\n"); +					usb_stor_dbg(us, "   Device supports Media Status Notification\n");  					/* Indicate that it is enabled, even though it is not  					 * This allows the lock/unlock of the media to work @@ -1190,7 +1192,8 @@ static int isd200_get_inquiry_data( struct us_data *us )  			us->protocol_name = "Transparent SCSI";  			us->proto_handler = usb_stor_transparent_scsi_command; -			US_DEBUGP("Protocol changed to: %s\n", us->protocol_name); +			usb_stor_dbg(us, "Protocol changed to: %s\n", +				     us->protocol_name);  			/* Free driver structure */	      			us->extra_destructor(info); @@ -1200,7 +1203,7 @@ static int isd200_get_inquiry_data( struct us_data *us )  		}  	} -	US_DEBUGP("Leaving isd200_get_inquiry_data %08X\n", retStatus); +	usb_stor_dbg(us, "Leaving isd200_get_inquiry_data %08X\n", retStatus);  	return(retStatus);  } @@ -1231,7 +1234,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,  	/* SCSI Command */  	switch (srb->cmnd[0]) {  	case INQUIRY: -		US_DEBUGP("   ATA OUT - INQUIRY\n"); +		usb_stor_dbg(us, "   ATA OUT - INQUIRY\n");  		/* copy InquiryData */  		usb_stor_set_xfer_buf((unsigned char *) &info->InquiryData, @@ -1241,7 +1244,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,  		break;  	case MODE_SENSE: -		US_DEBUGP("   ATA OUT - SCSIOP_MODE_SENSE\n"); +		usb_stor_dbg(us, "   ATA OUT - SCSIOP_MODE_SENSE\n");  		/* Initialize the return buffer */  		usb_stor_set_xfer_buf(senseData, sizeof(senseData), srb); @@ -1255,14 +1258,14 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,  			ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;  			isd200_srb_set_bufflen(srb, 0);  		} else { -			US_DEBUGP("   Media Status not supported, just report okay\n"); +			usb_stor_dbg(us, "   Media Status not supported, just report okay\n");  			srb->result = SAM_STAT_GOOD;  			sendToTransport = 0;  		}  		break;  	case TEST_UNIT_READY: -		US_DEBUGP("   ATA OUT - SCSIOP_TEST_UNIT_READY\n"); +		usb_stor_dbg(us, "   ATA OUT - SCSIOP_TEST_UNIT_READY\n");  		if (info->DeviceFlags & DF_MEDIA_STATUS_ENABLED)  		{ @@ -1273,7 +1276,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,  			ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;  			isd200_srb_set_bufflen(srb, 0);  		} else { -			US_DEBUGP("   Media Status not supported, just report okay\n"); +			usb_stor_dbg(us, "   Media Status not supported, just report okay\n");  			srb->result = SAM_STAT_GOOD;  			sendToTransport = 0;  		} @@ -1284,7 +1287,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,  		unsigned long capacity;  		struct read_capacity_data readCapacityData; -		US_DEBUGP("   ATA OUT - SCSIOP_READ_CAPACITY\n"); +		usb_stor_dbg(us, "   ATA OUT - SCSIOP_READ_CAPACITY\n");  		if (ata_id_has_lba(id))  			capacity = ata_id_u32(id, ATA_ID_LBA_CAPACITY) - 1; @@ -1303,7 +1306,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,  	break;  	case READ_10: -		US_DEBUGP("   ATA OUT - SCSIOP_READ\n"); +		usb_stor_dbg(us, "   ATA OUT - SCSIOP_READ\n");  		lba = be32_to_cpu(*(__be32 *)&srb->cmnd[2]);  		blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8]; @@ -1335,7 +1338,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,  		break;  	case WRITE_10: -		US_DEBUGP("   ATA OUT - SCSIOP_WRITE\n"); +		usb_stor_dbg(us, "   ATA OUT - SCSIOP_WRITE\n");  		lba = be32_to_cpu(*(__be32 *)&srb->cmnd[2]);  		blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8]; @@ -1367,10 +1370,11 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,  		break;  	case ALLOW_MEDIUM_REMOVAL: -		US_DEBUGP("   ATA OUT - SCSIOP_MEDIUM_REMOVAL\n"); +		usb_stor_dbg(us, "   ATA OUT - SCSIOP_MEDIUM_REMOVAL\n");  		if (info->DeviceFlags & DF_REMOVABLE_MEDIA) { -			US_DEBUGP("   srb->cmnd[4] = 0x%X\n", srb->cmnd[4]); +			usb_stor_dbg(us, "   srb->cmnd[4] = 0x%X\n", +				     srb->cmnd[4]);  			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;  			ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand; @@ -1380,25 +1384,25 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,  				ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;  			isd200_srb_set_bufflen(srb, 0);  		} else { -			US_DEBUGP("   Not removeable media, just report okay\n"); +			usb_stor_dbg(us, "   Not removeable media, just report okay\n");  			srb->result = SAM_STAT_GOOD;  			sendToTransport = 0;  		}  		break;  	case START_STOP:     -		US_DEBUGP("   ATA OUT - SCSIOP_START_STOP_UNIT\n"); -		US_DEBUGP("   srb->cmnd[4] = 0x%X\n", srb->cmnd[4]); +		usb_stor_dbg(us, "   ATA OUT - SCSIOP_START_STOP_UNIT\n"); +		usb_stor_dbg(us, "   srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);  		if ((srb->cmnd[4] & 0x3) == 0x2) { -			US_DEBUGP("   Media Eject\n"); +			usb_stor_dbg(us, "   Media Eject\n");  			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;  			ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;  			ataCdb->generic.TransferBlockSize = 0;  			ataCdb->generic.RegisterSelect = REG_COMMAND;  			ataCdb->write.CommandByte = ATA_COMMAND_MEDIA_EJECT;  		} else if ((srb->cmnd[4] & 0x3) == 0x1) { -			US_DEBUGP("   Get Media Status\n"); +			usb_stor_dbg(us, "   Get Media Status\n");  			ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;  			ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;  			ataCdb->generic.TransferBlockSize = 1; @@ -1406,14 +1410,15 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,  			ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;  			isd200_srb_set_bufflen(srb, 0);  		} else { -			US_DEBUGP("   Nothing to do, just report okay\n"); +			usb_stor_dbg(us, "   Nothing to do, just report okay\n");  			srb->result = SAM_STAT_GOOD;  			sendToTransport = 0;  		}  		break;  	default: -		US_DEBUGP("Unsupported SCSI command - 0x%X\n", srb->cmnd[0]); +		usb_stor_dbg(us, "Unsupported SCSI command - 0x%X\n", +			     srb->cmnd[0]);  		srb->result = DID_ERROR << 16;  		sendToTransport = 0;  		break; @@ -1457,8 +1462,7 @@ static int isd200_init_info(struct us_data *us)  		retStatus = ISD200_ERROR;  	else {  		info->id = kzalloc(ATA_ID_WORDS * 2, GFP_KERNEL); -		info->RegsBuf = (unsigned char *) -				kmalloc(sizeof(info->ATARegs), GFP_KERNEL); +		info->RegsBuf = kmalloc(sizeof(info->ATARegs), GFP_KERNEL);  		info->srb.sense_buffer =  				kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);  		if (!info->id || !info->RegsBuf || !info->srb.sense_buffer) { @@ -1471,8 +1475,7 @@ static int isd200_init_info(struct us_data *us)  	if (retStatus == ISD200_GOOD) {  		us->extra = info;  		us->extra_destructor = isd200_free_info_ptrs; -	} else -		US_DEBUGP("ERROR - kmalloc failure\n"); +	}  	return retStatus;  } @@ -1483,19 +1486,19 @@ static int isd200_init_info(struct us_data *us)  static int isd200_Initialization(struct us_data *us)  { -	US_DEBUGP("ISD200 Initialization...\n"); +	usb_stor_dbg(us, "ISD200 Initialization...\n");  	/* Initialize ISD200 info struct */  	if (isd200_init_info(us) == ISD200_ERROR) { -		US_DEBUGP("ERROR Initializing ISD200 Info struct\n"); +		usb_stor_dbg(us, "ERROR Initializing ISD200 Info struct\n");  	} else {  		/* Get device specific data */  		if (isd200_get_inquiry_data(us) != ISD200_GOOD) -			US_DEBUGP("ISD200 Initialization Failure\n"); +			usb_stor_dbg(us, "ISD200 Initialization Failure\n");  		else -			US_DEBUGP("ISD200 Initialization complete\n"); +			usb_stor_dbg(us, "ISD200 Initialization complete\n");  	}  	return 0; @@ -1520,7 +1523,7 @@ static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)  	/* Make sure driver was initialized */  	if (us->extra == NULL) -		US_DEBUGP("ERROR Driver not initialized\n"); +		usb_stor_dbg(us, "ERROR Driver not initialized\n");  	scsi_set_resid(srb, 0);  	/* scsi_bufflen might change in protocol translation to ata */ diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index ddc78780b1a..563078be654 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -118,7 +118,7 @@ static inline int jumpshot_bulk_read(struct us_data *us,  	if (len == 0)  		return USB_STOR_XFER_GOOD; -	US_DEBUGP("jumpshot_bulk_read:  len = %d\n", len); +	usb_stor_dbg(us, "len = %d\n", len);  	return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,  			data, len, NULL);  } @@ -131,7 +131,7 @@ static inline int jumpshot_bulk_write(struct us_data *us,  	if (len == 0)  		return USB_STOR_XFER_GOOD; -	US_DEBUGP("jumpshot_bulk_write:  len = %d\n", len); +	usb_stor_dbg(us, "len = %d\n", len);  	return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,  			data, len, NULL);  } @@ -152,8 +152,7 @@ static int jumpshot_get_status(struct us_data  *us)  		return USB_STOR_TRANSPORT_ERROR;  	if (us->iobuf[0] != 0x50) { -		US_DEBUGP("jumpshot_get_status:  0x%2x\n", -			  us->iobuf[0]); +		usb_stor_dbg(us, "0x%2x\n", us->iobuf[0]);  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -218,7 +217,7 @@ static int jumpshot_read_data(struct us_data *us,  		if (result != USB_STOR_XFER_GOOD)  			goto leave; -		US_DEBUGP("jumpshot_read_data:  %d bytes\n", len); +		usb_stor_dbg(us, "%d bytes\n", len);  		// Store the data in the transfer buffer  		usb_stor_access_xfer_buf(buffer, len, us->srb, @@ -314,7 +313,7 @@ static int jumpshot_write_data(struct us_data *us,  		} while ((result != USB_STOR_TRANSPORT_GOOD) && (waitcount < 10));  		if (result != USB_STOR_TRANSPORT_GOOD) -			US_DEBUGP("jumpshot_write_data:  Gah!  Waitcount = 10.  Bad write!?\n"); +			usb_stor_dbg(us, "Gah!  Waitcount = 10.  Bad write!?\n");  		sector += thistime;  		totallen -= len; @@ -349,8 +348,7 @@ static int jumpshot_id_device(struct us_data *us,  				   0, 0x20, 0, 6, command, 2);  	if (rc != USB_STOR_XFER_GOOD) { -		US_DEBUGP("jumpshot_id_device:  Gah! " -			  "send_control for read_capacity failed\n"); +		usb_stor_dbg(us, "Gah! send_control for read_capacity failed\n");  		rc = USB_STOR_TRANSPORT_ERROR;  		goto leave;  	} @@ -400,17 +398,17 @@ static int jumpshot_handle_mode_sense(struct us_data *us,  	switch (pc) {  	   case 0x0: -		US_DEBUGP("jumpshot_handle_mode_sense:  Current values\n"); -		break; +		   usb_stor_dbg(us, "Current values\n"); +		   break;  	   case 0x1: -		US_DEBUGP("jumpshot_handle_mode_sense:  Changeable values\n"); -		break; +		   usb_stor_dbg(us, "Changeable values\n"); +		   break;  	   case 0x2: -		US_DEBUGP("jumpshot_handle_mode_sense:  Default values\n"); -		break; +		   usb_stor_dbg(us, "Default values\n"); +		   break;  	   case 0x3: -		US_DEBUGP("jumpshot_handle_mode_sense:  Saves values\n"); -		break; +		   usb_stor_dbg(us, "Saves values\n"); +		   break;  	}  	memset(ptr, 0, 8); @@ -494,17 +492,16 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)  	if (!us->extra) {  		us->extra = kzalloc(sizeof(struct jumpshot_info), GFP_NOIO); -		if (!us->extra) { -			US_DEBUGP("jumpshot_transport:  Gah! Can't allocate storage for jumpshot info struct!\n"); +		if (!us->extra)  			return USB_STOR_TRANSPORT_ERROR; -		} +  		us->extra_destructor = jumpshot_info_destructor;  	}  	info = (struct jumpshot_info *) (us->extra);  	if (srb->cmnd[0] == INQUIRY) { -		US_DEBUGP("jumpshot_transport:  INQUIRY.  Returning bogus response.\n"); +		usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");  		memcpy(ptr, inquiry_response, sizeof(inquiry_response));  		fill_inquiry_response(us, ptr, 36);  		return USB_STOR_TRANSPORT_GOOD; @@ -521,8 +518,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)  		if (rc != USB_STOR_TRANSPORT_GOOD)  			return rc; -		US_DEBUGP("jumpshot_transport:  READ_CAPACITY:  %ld sectors, %ld bytes per sector\n", -			  info->sectors, info->ssize); +		usb_stor_dbg(us, "READ_CAPACITY:  %ld sectors, %ld bytes per sector\n", +			     info->sectors, info->ssize);  		// build the reply  		// @@ -534,7 +531,7 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)  	}  	if (srb->cmnd[0] == MODE_SELECT_10) { -		US_DEBUGP("jumpshot_transport:  Gah! MODE_SELECT_10.\n"); +		usb_stor_dbg(us, "Gah! MODE_SELECT_10\n");  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -544,7 +541,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)  		blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); -		US_DEBUGP("jumpshot_transport:  READ_10: read block 0x%04lx  count %ld\n", block, blocks); +		usb_stor_dbg(us, "READ_10: read block 0x%04lx  count %ld\n", +			     block, blocks);  		return jumpshot_read_data(us, info, block, blocks);  	} @@ -557,7 +555,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)  		blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |  			 ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9])); -		US_DEBUGP("jumpshot_transport:  READ_12: read block 0x%04lx  count %ld\n", block, blocks); +		usb_stor_dbg(us, "READ_12: read block 0x%04lx  count %ld\n", +			     block, blocks);  		return jumpshot_read_data(us, info, block, blocks);  	} @@ -567,7 +566,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)  		blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); -		US_DEBUGP("jumpshot_transport:  WRITE_10: write block 0x%04lx  count %ld\n", block, blocks); +		usb_stor_dbg(us, "WRITE_10: write block 0x%04lx  count %ld\n", +			     block, blocks);  		return jumpshot_write_data(us, info, block, blocks);  	} @@ -580,18 +580,19 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)  		blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |  			 ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9])); -		US_DEBUGP("jumpshot_transport:  WRITE_12: write block 0x%04lx  count %ld\n", block, blocks); +		usb_stor_dbg(us, "WRITE_12: write block 0x%04lx  count %ld\n", +			     block, blocks);  		return jumpshot_write_data(us, info, block, blocks);  	}  	if (srb->cmnd[0] == TEST_UNIT_READY) { -		US_DEBUGP("jumpshot_transport:  TEST_UNIT_READY.\n"); +		usb_stor_dbg(us, "TEST_UNIT_READY\n");  		return jumpshot_get_status(us);  	}  	if (srb->cmnd[0] == REQUEST_SENSE) { -		US_DEBUGP("jumpshot_transport:  REQUEST_SENSE.\n"); +		usb_stor_dbg(us, "REQUEST_SENSE\n");  		memset(ptr, 0, 18);  		ptr[0] = 0xF0; @@ -605,12 +606,12 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)  	}  	if (srb->cmnd[0] == MODE_SENSE) { -		US_DEBUGP("jumpshot_transport:  MODE_SENSE_6 detected\n"); +		usb_stor_dbg(us, "MODE_SENSE_6 detected\n");  		return jumpshot_handle_mode_sense(us, srb, 1);  	}  	if (srb->cmnd[0] == MODE_SENSE_10) { -		US_DEBUGP("jumpshot_transport:  MODE_SENSE_10 detected\n"); +		usb_stor_dbg(us, "MODE_SENSE_10 detected\n");  		return jumpshot_handle_mode_sense(us, srb, 0);  	} @@ -624,7 +625,7 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)  	if (srb->cmnd[0] == START_STOP) {  		/* this is used by sd.c'check_scsidisk_media_change to detect  		   media change */ -		US_DEBUGP("jumpshot_transport:  START_STOP.\n"); +		usb_stor_dbg(us, "START_STOP\n");  		/* the first jumpshot_id_device after a media change returns  		   an error (determined experimentally) */  		rc = jumpshot_id_device(us, info); @@ -638,8 +639,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)  		return rc;  	} -	US_DEBUGP("jumpshot_transport:  Gah! Unknown command: %d (0x%x)\n", -		  srb->cmnd[0], srb->cmnd[0]); +	usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n", +		     srb->cmnd[0], srb->cmnd[0]);  	info->sense_key = 0x05;  	info->sense_asc = 0x20;  	info->sense_ascq = 0x00; diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c index f085ffb606c..94d16ee5e84 100644 --- a/drivers/usb/storage/karma.c +++ b/drivers/usb/storage/karma.c @@ -106,7 +106,7 @@ static int rio_karma_send_command(char cmd, struct us_data *us)  	static unsigned char seq = 1;  	struct karma_data *data = (struct karma_data *) us->extra; -	US_DEBUGP("karma: sending command %04x\n", cmd); +	usb_stor_dbg(us, "sending command %04x\n", cmd);  	memset(us->iobuf, 0, RIO_SEND_LEN);  	memcpy(us->iobuf, RIO_PREFIX, RIO_PREFIX_LEN);  	us->iobuf[5] = cmd; @@ -139,10 +139,10 @@ static int rio_karma_send_command(char cmd, struct us_data *us)  	if (seq == 0)  		seq = 1; -	US_DEBUGP("karma: sent command %04x\n", cmd); +	usb_stor_dbg(us, "sent command %04x\n", cmd);  	return 0;  err: -	US_DEBUGP("karma: command %04x failed\n", cmd); +	usb_stor_dbg(us, "command %04x failed\n", cmd);  	return USB_STOR_TRANSPORT_FAILED;  } diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index cb79de61f4c..26964895c88 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -195,6 +195,7 @@ static int onetouch_connect_input(struct us_data *ss)  	pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);  	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); +	maxp = min(maxp, ONETOUCH_PKT_LEN);  	onetouch = kzalloc(sizeof(struct usb_onetouch), GFP_KERNEL);  	input_dev = input_allocate_device(); @@ -245,8 +246,7 @@ static int onetouch_connect_input(struct us_data *ss)  	input_dev->open = usb_onetouch_open;  	input_dev->close = usb_onetouch_close; -	usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data, -			 (maxp > 8 ? 8 : maxp), +	usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data, maxp,  			 usb_onetouch_irq, onetouch, endpoint->bInterval);  	onetouch->irq->transfer_dma = onetouch->data_dma;  	onetouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; diff --git a/drivers/usb/storage/option_ms.c b/drivers/usb/storage/option_ms.c index e0f76bb0591..b2b35b1d7de 100644 --- a/drivers/usb/storage/option_ms.c +++ b/drivers/usb/storage/option_ms.c @@ -50,7 +50,7 @@ static int option_rezero(struct us_data *us)  	char *buffer;  	int result; -	US_DEBUGP("Option MS: %s", "DEVICE MODE SWITCH\n"); +	usb_stor_dbg(us, "Option MS: %s\n", "DEVICE MODE SWITCH");  	buffer = kzalloc(RESPONSE_LEN, GFP_KERNEL);  	if (buffer == NULL) @@ -95,7 +95,7 @@ static int option_inquiry(struct us_data *us)  	char *buffer;  	int result; -	US_DEBUGP("Option MS: %s", "device inquiry for vendor name\n"); +	usb_stor_dbg(us, "Option MS: %s\n", "device inquiry for vendor name");  	buffer = kzalloc(0x24, GFP_KERNEL);  	if (buffer == NULL) @@ -138,31 +138,32 @@ int option_ms_init(struct us_data *us)  {  	int result; -	US_DEBUGP("Option MS: option_ms_init called\n"); +	usb_stor_dbg(us, "Option MS: %s\n", "option_ms_init called");  	/* Additional test for vendor information via INQUIRY,  	 * because some vendor/product IDs are ambiguous  	 */  	result = option_inquiry(us);  	if (result != 0) { -		US_DEBUGP("Option MS: vendor is not Option or not determinable," -			  " no action taken\n"); +		usb_stor_dbg(us, "Option MS: %s\n", +			     "vendor is not Option or not determinable, no action taken");  		return 0;  	} else -		US_DEBUGP("Option MS: this is a genuine Option device," -			  " proceeding\n"); +		usb_stor_dbg(us, "Option MS: %s\n", +			     "this is a genuine Option device, proceeding");  	/* Force Modem mode */  	if (option_zero_cd == ZCD_FORCE_MODEM) { -		US_DEBUGP("Option MS: %s", "Forcing Modem Mode\n"); +		usb_stor_dbg(us, "Option MS: %s\n", "Forcing Modem Mode");  		result = option_rezero(us);  		if (result != USB_STOR_XFER_GOOD) -			US_DEBUGP("Option MS: Failed to switch to modem mode.\n"); +			usb_stor_dbg(us, "Option MS: %s\n", +				     "Failed to switch to modem mode");  		return -EIO;  	} else if (option_zero_cd == ZCD_ALLOW_MS) {  		/* Allow Mass Storage mode (keep CD-Rom) */ -		US_DEBUGP("Option MS: %s", "Allowing Mass Storage Mode if device" -		          " requests it\n"); +		usb_stor_dbg(us, "Option MS: %s\n", +			     "Allowing Mass Storage Mode if device requests it");  	}  	return 0; diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index 6c3586a4c95..8623577bbbe 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -254,8 +254,8 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun,  	/* check bulk status */  	if (bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN)) { -		US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n", -			  le32_to_cpu(bcs->Signature), US_BULK_CS_SIGN); +		usb_stor_dbg(us, "Signature mismatch: got %08X, expecting %08X\n", +			     le32_to_cpu(bcs->Signature), US_BULK_CS_SIGN);  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -351,8 +351,8 @@ static int rts51x_get_max_lun(struct us_data *us)  				      USB_RECIP_INTERFACE,  				      0, us->ifnum, us->iobuf, 1, 10 * HZ); -	US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", -		  result, us->iobuf[0]); +	usb_stor_dbg(us, "GetMaxLUN command result is %d, data is %d\n", +		     result, us->iobuf[0]);  	/* if we have a successful request, return the result */  	if (result > 0) @@ -371,7 +371,7 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len)  	if (buf == NULL)  		return USB_STOR_TRANSPORT_ERROR; -	US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); +	usb_stor_dbg(us, "addr = 0x%x, len = %d\n", addr, len);  	cmnd[0] = 0xF0;  	cmnd[1] = 0x0D; @@ -402,7 +402,7 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len)  	if (buf == NULL)  		return USB_STOR_TRANSPORT_ERROR; -	US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len); +	usb_stor_dbg(us, "addr = 0x%x, len = %d\n", addr, len);  	cmnd[0] = 0xF0;  	cmnd[1] = 0x0E; @@ -431,7 +431,7 @@ static int rts51x_read_status(struct us_data *us,  	if (buf == NULL)  		return USB_STOR_TRANSPORT_ERROR; -	US_DEBUGP("%s, lun = %d\n", __func__, lun); +	usb_stor_dbg(us, "lun = %d\n", lun);  	cmnd[0] = 0xF0;  	cmnd[1] = 0x09; @@ -458,7 +458,7 @@ static int rts51x_check_status(struct us_data *us, u8 lun)  	if (retval != STATUS_SUCCESS)  		return -EIO; -	US_DEBUGP("chip->status_len = %d\n", chip->status_len); +	usb_stor_dbg(us, "chip->status_len = %d\n", chip->status_len);  	chip->status[lun].vid = ((u16) buf[0] << 8) | buf[1];  	chip->status[lun].pid = ((u16) buf[2] << 8) | buf[3]; @@ -509,7 +509,7 @@ static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len)  	u8 cmnd[12] = {0};  	u8 *buf; -	US_DEBUGP("%s, addr = 0xfe47, len = %d\n", __FUNCTION__, len); +	usb_stor_dbg(us, "addr = 0xfe47, len = %d\n", len);  	buf = kmemdup(data, len, GFP_NOIO);  	if (!buf) @@ -549,7 +549,7 @@ static int do_config_autodelink(struct us_data *us, int enable, int force)  		value &= ~0x03;  	} -	US_DEBUGP("In %s,set 0xfe47 to 0x%x\n", __func__, value); +	usb_stor_dbg(us, "set 0xfe47 to 0x%x\n", value);  	/* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */  	retval = __do_config_autodelink(us, &value, 1); @@ -565,8 +565,6 @@ static int config_autodelink_after_power_on(struct us_data *us)  	int retval;  	u8 value; -	US_DEBUGP("%s: <---\n", __func__); -  	if (!CHK_AUTO_DELINK(chip))  		return 0; @@ -624,8 +622,6 @@ static int config_autodelink_after_power_on(struct us_data *us)  		}  	} -	US_DEBUGP("%s: --->\n", __func__); -  	return 0;  } @@ -635,8 +631,6 @@ static int config_autodelink_before_power_down(struct us_data *us)  	int retval;  	u8 value; -	US_DEBUGP("%s: <---\n", __func__); -  	if (!CHK_AUTO_DELINK(chip))  		return 0; @@ -698,8 +692,6 @@ static int config_autodelink_before_power_down(struct us_data *us)  		}  	} -	US_DEBUGP("%s: --->\n", __func__); -  	return 0;  } @@ -709,23 +701,19 @@ static void fw5895_init(struct us_data *us)  	int retval;  	u8 val; -	US_DEBUGP("%s: <---\n", __func__); -  	if ((PRODUCT_ID(chip) != 0x0158) || (FW_VERSION(chip) != 0x5895)) { -		US_DEBUGP("Not the specified device, return immediately!\n"); +		usb_stor_dbg(us, "Not the specified device, return immediately!\n");  	} else {  		retval = rts51x_read_mem(us, 0xFD6F, &val, 1);  		if (retval == STATUS_SUCCESS && (val & 0x1F) == 0) {  			val = 0x1F;  			retval = rts51x_write_mem(us, 0xFD70, &val, 1);  			if (retval != STATUS_SUCCESS) -				US_DEBUGP("Write memory fail\n"); +				usb_stor_dbg(us, "Write memory fail\n");  		} else { -			US_DEBUGP("Read memory fail, OR (val & 0x1F) != 0\n"); +			usb_stor_dbg(us, "Read memory fail, OR (val & 0x1F) != 0\n");  		}  	} - -	US_DEBUGP("%s: --->\n", __func__);  }  #ifdef CONFIG_REALTEK_AUTOPM @@ -735,10 +723,8 @@ static void fw5895_set_mmc_wp(struct us_data *us)  	int retval;  	u8 buf[13]; -	US_DEBUGP("%s: <---\n", __func__); -  	if ((PRODUCT_ID(chip) != 0x0158) || (FW_VERSION(chip) != 0x5895)) { -		US_DEBUGP("Not the specified device, return immediately!\n"); +		usb_stor_dbg(us, "Not the specified device, return immediately!\n");  	} else {  		retval = rts51x_read_mem(us, 0xFD6F, buf, 1);  		if (retval == STATUS_SUCCESS && (buf[0] & 0x24) == 0x24) { @@ -748,26 +734,24 @@ static void fw5895_set_mmc_wp(struct us_data *us)  				buf[0] |= 0x04;  				retval = rts51x_write_mem(us, 0xFD70, buf, 1);  				if (retval != STATUS_SUCCESS) -					US_DEBUGP("Write memory fail\n"); +					usb_stor_dbg(us, "Write memory fail\n");  			} else { -				US_DEBUGP("Read memory fail\n"); +				usb_stor_dbg(us, "Read memory fail\n");  			}  		} else { -			US_DEBUGP("Read memory fail, OR (buf[0]&0x24)!=0x24\n"); +			usb_stor_dbg(us, "Read memory fail, OR (buf[0]&0x24)!=0x24\n");  		}  	} - -	US_DEBUGP("%s: --->\n", __func__);  }  static void rts51x_modi_suspend_timer(struct rts51x_chip *chip)  { -	US_DEBUGP("%s: <---, state:%d\n", __func__, rts51x_get_stat(chip)); +	struct us_data *us = chip->us; + +	usb_stor_dbg(us, "state:%d\n", rts51x_get_stat(chip));  	chip->timer_expires = jiffies + msecs_to_jiffies(1000*ss_delay);  	mod_timer(&chip->rts51x_suspend_timer, chip->timer_expires); - -	US_DEBUGP("%s: --->\n", __func__);  }  static void rts51x_suspend_timer_fn(unsigned long data) @@ -775,8 +759,6 @@ static void rts51x_suspend_timer_fn(unsigned long data)  	struct rts51x_chip *chip = (struct rts51x_chip *)data;  	struct us_data *us = chip->us; -	US_DEBUGP("%s: <---\n", __func__); -  	switch (rts51x_get_stat(chip)) {  	case RTS51X_STAT_INIT:  	case RTS51X_STAT_RUN: @@ -784,32 +766,25 @@ static void rts51x_suspend_timer_fn(unsigned long data)  		break;  	case RTS51X_STAT_IDLE:  	case RTS51X_STAT_SS: -		US_DEBUGP("%s: RTS51X_STAT_SS, intf->pm_usage_cnt:%d," -			"power.usage:%d\n", __func__, -			atomic_read(&us->pusb_intf->pm_usage_cnt), -			atomic_read(&us->pusb_intf->dev.power.usage_count)); +		usb_stor_dbg(us, "RTS51X_STAT_SS, intf->pm_usage_cnt:%d, power.usage:%d\n", +			     atomic_read(&us->pusb_intf->pm_usage_cnt), +			     atomic_read(&us->pusb_intf->dev.power.usage_count));  		if (atomic_read(&us->pusb_intf->pm_usage_cnt) > 0) { -			US_DEBUGP("%s: Ready to enter SS state.\n", -				  __func__); +			usb_stor_dbg(us, "Ready to enter SS state\n");  			rts51x_set_stat(chip, RTS51X_STAT_SS);  			/* ignore mass storage interface's children */  			pm_suspend_ignore_children(&us->pusb_intf->dev, true);  			usb_autopm_put_interface_async(us->pusb_intf); -			US_DEBUGP("%s: RTS51X_STAT_SS 01," -				"intf->pm_usage_cnt:%d, power.usage:%d\n", -				__func__, -				atomic_read(&us->pusb_intf->pm_usage_cnt), -				atomic_read( -					&us->pusb_intf->dev.power.usage_count)); +			usb_stor_dbg(us, "RTS51X_STAT_SS 01, intf->pm_usage_cnt:%d, power.usage:%d\n", +				     atomic_read(&us->pusb_intf->pm_usage_cnt), +				     atomic_read(&us->pusb_intf->dev.power.usage_count));  		}  		break;  	default: -		US_DEBUGP("%s: Unknonwn state !!!\n", __func__); +		usb_stor_dbg(us, "Unknown state !!!\n");  		break;  	} - -	US_DEBUGP("%s: --->\n", __func__);  }  static inline int working_scsi(struct scsi_cmnd *srb) @@ -834,24 +809,21 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)  	};  	int ret; -	US_DEBUGP("%s: <---\n", __func__); -  	if (working_scsi(srb)) { -		US_DEBUGP("%s: working scsi, intf->pm_usage_cnt:%d," -			"power.usage:%d\n", __func__, -			atomic_read(&us->pusb_intf->pm_usage_cnt), -			atomic_read(&us->pusb_intf->dev.power.usage_count)); +		usb_stor_dbg(us, "working scsi, intf->pm_usage_cnt:%d, power.usage:%d\n", +			     atomic_read(&us->pusb_intf->pm_usage_cnt), +			     atomic_read(&us->pusb_intf->dev.power.usage_count));  		if (atomic_read(&us->pusb_intf->pm_usage_cnt) <= 0) {  			ret = usb_autopm_get_interface(us->pusb_intf); -			US_DEBUGP("%s: working scsi, ret=%d\n", __func__, ret); +			usb_stor_dbg(us, "working scsi, ret=%d\n", ret);  		}  		if (rts51x_get_stat(chip) != RTS51X_STAT_RUN)  			rts51x_set_stat(chip, RTS51X_STAT_RUN);  		chip->proto_handler_backup(srb, us);  	} else {  		if (rts51x_get_stat(chip) == RTS51X_STAT_SS) { -			US_DEBUGP("%s: NOT working scsi\n", __func__); +			usb_stor_dbg(us, "NOT working scsi\n");  			if ((srb->cmnd[0] == TEST_UNIT_READY) &&  			    (chip->pwr_state == US_SUSPEND)) {  				if (TST_LUN_READY(chip, srb->device->lun)) { @@ -862,8 +834,7 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)  					       media_not_present,  					       US_SENSE_SIZE);  				} -				US_DEBUGP("%s: TEST_UNIT_READY--->\n", -					  __func__); +				usb_stor_dbg(us, "TEST_UNIT_READY\n");  				goto out;  			}  			if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { @@ -876,12 +847,11 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)  				} else {  					srb->result = SAM_STAT_GOOD;  				} -				US_DEBUGP("%s: ALLOW_MEDIUM_REMOVAL--->\n", -					  __func__); +				usb_stor_dbg(us, "ALLOW_MEDIUM_REMOVAL\n");  				goto out;  			}  		} else { -			US_DEBUGP("%s: NOT working scsi, not SS\n", __func__); +			usb_stor_dbg(us, "NOT working scsi, not SS\n");  			chip->proto_handler_backup(srb, us);  			/* Check whether card is plugged in */  			if (srb->cmnd[0] == TEST_UNIT_READY) { @@ -901,11 +871,9 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)  		}  	}  out: -	US_DEBUGP("%s: state:%d\n", __func__, rts51x_get_stat(chip)); +	usb_stor_dbg(us, "state:%d\n", rts51x_get_stat(chip));  	if (rts51x_get_stat(chip) == RTS51X_STAT_RUN)  		rts51x_modi_suspend_timer(chip); - -	US_DEBUGP("%s: --->\n", __func__);  }  static int realtek_cr_autosuspend_setup(struct us_data *us) @@ -923,7 +891,7 @@ static int realtek_cr_autosuspend_setup(struct us_data *us)  	retval = rts51x_read_status(us, 0, buf, 16, &(chip->status_len));  	if (retval != STATUS_SUCCESS) { -		US_DEBUGP("Read status fail\n"); +		usb_stor_dbg(us, "Read status fail\n");  		return -EIO;  	}  	status = chip->status; @@ -965,12 +933,11 @@ static int realtek_cr_autosuspend_setup(struct us_data *us)  static void realtek_cr_destructor(void *extra)  { -	struct rts51x_chip *chip = (struct rts51x_chip *)extra; - -	US_DEBUGP("%s: <---\n", __func__); +	struct rts51x_chip *chip = extra;  	if (!chip)  		return; +  #ifdef CONFIG_REALTEK_AUTOPM  	if (ss_en) {  		del_timer(&chip->rts51x_suspend_timer); @@ -985,8 +952,6 @@ static int realtek_cr_suspend(struct usb_interface *iface, pm_message_t message)  {  	struct us_data *us = usb_get_intfdata(iface); -	US_DEBUGP("%s: <---\n", __func__); -  	/* wait until no command is running */  	mutex_lock(&us->dev_mutex); @@ -994,8 +959,6 @@ static int realtek_cr_suspend(struct usb_interface *iface, pm_message_t message)  	mutex_unlock(&us->dev_mutex); -	US_DEBUGP("%s: --->\n", __func__); -  	return 0;  } @@ -1003,13 +966,9 @@ static int realtek_cr_resume(struct usb_interface *iface)  {  	struct us_data *us = usb_get_intfdata(iface); -	US_DEBUGP("%s: <---\n", __func__); -  	fw5895_init(us);  	config_autodelink_after_power_on(us); -	US_DEBUGP("%s: --->\n", __func__); -  	return 0;  }  #else @@ -1030,7 +989,7 @@ static int init_realtek_cr(struct us_data *us)  	us->extra_destructor = realtek_cr_destructor;  	us->max_lun = chip->max_lun = rts51x_get_max_lun(us); -	US_DEBUGP("chip->max_lun = %d\n", chip->max_lun); +	usb_stor_dbg(us, "chip->max_lun = %d\n", chip->max_lun);  	size = (chip->max_lun + 1) * sizeof(struct rts51x_status);  	chip->status = kzalloc(size, GFP_KERNEL); @@ -1057,7 +1016,7 @@ static int init_realtek_cr(struct us_data *us)  	}  #endif -	US_DEBUGP("chip->flag = 0x%x\n", chip->flag); +	usb_stor_dbg(us, "chip->flag = 0x%x\n", chip->flag);  	(void)config_autodelink_after_power_on(us); @@ -1079,7 +1038,7 @@ static int realtek_cr_probe(struct usb_interface *intf,  	struct us_data *us;  	int result; -	US_DEBUGP("Probe Realtek Card Reader!\n"); +	dev_dbg(&intf->dev, "Probe Realtek Card Reader!\n");  	result = usb_stor_probe1(&us, intf, id,  				 (id - realtek_cr_ids) + diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 92f35abee92..4faa982807f 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -313,8 +313,6 @@ static int queuecommand_lck(struct scsi_cmnd *srb,  {  	struct us_data *us = host_to_us(srb->device->host); -	US_DEBUGP("%s called\n", __func__); -  	/* check for state-transition errors */  	if (us->srb != NULL) {  		printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n", @@ -324,7 +322,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb,  	/* fail the command if we are disconnecting */  	if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { -		US_DEBUGP("Fail command during disconnect\n"); +		usb_stor_dbg(us, "Fail command during disconnect\n");  		srb->result = DID_NO_CONNECT << 16;  		done(srb);  		return 0; @@ -349,7 +347,7 @@ static int command_abort(struct scsi_cmnd *srb)  {  	struct us_data *us = host_to_us(srb->device->host); -	US_DEBUGP("%s called\n", __func__); +	usb_stor_dbg(us, "%s called\n", __func__);  	/* us->srb together with the TIMED_OUT, RESETTING, and ABORTING  	 * bits are protected by the host lock. */ @@ -358,7 +356,7 @@ static int command_abort(struct scsi_cmnd *srb)  	/* Is this command still active? */  	if (us->srb != srb) {  		scsi_unlock(us_to_host(us)); -		US_DEBUGP ("-- nothing to abort\n"); +		usb_stor_dbg(us, "-- nothing to abort\n");  		return FAILED;  	} @@ -386,7 +384,7 @@ static int device_reset(struct scsi_cmnd *srb)  	struct us_data *us = host_to_us(srb->device->host);  	int result; -	US_DEBUGP("%s called\n", __func__); +	usb_stor_dbg(us, "%s called\n", __func__);  	/* lock the device pointers and do the reset */  	mutex_lock(&(us->dev_mutex)); @@ -402,7 +400,8 @@ static int bus_reset(struct scsi_cmnd *srb)  	struct us_data *us = host_to_us(srb->device->host);  	int result; -	US_DEBUGP("%s called\n", __func__); +	usb_stor_dbg(us, "%s called\n", __func__); +  	result = usb_stor_port_reset(us);  	return result < 0 ? FAILED : SUCCESS;  } diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 7bd54e0d512..732027f3320 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -105,8 +105,6 @@ static struct us_unusual_dev sddr09_unusual_dev_list[] = {  #define LSB_of(s) ((s)&0xFF)  #define MSB_of(s) ((s)>>8) -/* #define US_DEBUGP printk */ -  /*   * First some stuff that does not belong here:   * data on SmartMedia and other cards, completely @@ -347,7 +345,7 @@ sddr09_test_unit_ready(struct us_data *us) {  	result = sddr09_send_scsi_command(us, command, 6); -	US_DEBUGP("sddr09_test_unit_ready returns %d\n", result); +	usb_stor_dbg(us, "sddr09_test_unit_ready returns %d\n", result);  	return result;  } @@ -423,8 +421,8 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress,  	result = sddr09_send_scsi_command(us, command, 12);  	if (result) { -		US_DEBUGP("Result for send_control in sddr09_read2%d %d\n", -			  x, result); +		usb_stor_dbg(us, "Result for send_control in sddr09_read2%d %d\n", +			     x, result);  		return result;  	} @@ -432,8 +430,8 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress,  				       buf, bulklen, use_sg, NULL);  	if (result != USB_STOR_XFER_GOOD) { -		US_DEBUGP("Result for bulk_transfer in sddr09_read2%d %d\n", -			  x, result); +		usb_stor_dbg(us, "Result for bulk_transfer in sddr09_read2%d %d\n", +			     x, result);  		return -EIO;  	}  	return 0; @@ -494,8 +492,7 @@ sddr09_read22(struct us_data *us, unsigned long fromaddress,  	      int nr_of_pages, int pageshift, unsigned char *buf, int use_sg) {  	int bulklen = (nr_of_pages << pageshift) + (nr_of_pages << CONTROL_SHIFT); -	US_DEBUGP("sddr09_read22: reading %d pages, %d bytes\n", -		  nr_of_pages, bulklen); +	usb_stor_dbg(us, "reading %d pages, %d bytes\n", nr_of_pages, bulklen);  	return sddr09_readX(us, 2, fromaddress, nr_of_pages, bulklen,  			    buf, use_sg);  } @@ -538,7 +535,7 @@ sddr09_erase(struct us_data *us, unsigned long Eaddress) {  	unsigned char *command = us->iobuf;  	int result; -	US_DEBUGP("sddr09_erase: erase address %lu\n", Eaddress); +	usb_stor_dbg(us, "erase address %lu\n", Eaddress);  	memset(command, 0, 12);  	command[0] = 0xEA; @@ -551,8 +548,8 @@ sddr09_erase(struct us_data *us, unsigned long Eaddress) {  	result = sddr09_send_scsi_command(us, command, 12);  	if (result) -		US_DEBUGP("Result for send_control in sddr09_erase %d\n", -			  result); +		usb_stor_dbg(us, "Result for send_control in sddr09_erase %d\n", +			     result);  	return result;  } @@ -609,8 +606,8 @@ sddr09_writeX(struct us_data *us,  	result = sddr09_send_scsi_command(us, command, 12);  	if (result) { -		US_DEBUGP("Result for send_control in sddr09_writeX %d\n", -			  result); +		usb_stor_dbg(us, "Result for send_control in sddr09_writeX %d\n", +			     result);  		return result;  	} @@ -618,8 +615,8 @@ sddr09_writeX(struct us_data *us,  				       buf, bulklen, use_sg, NULL);  	if (result != USB_STOR_XFER_GOOD) { -		US_DEBUGP("Result for bulk_transfer in sddr09_writeX %d\n", -			  result); +		usb_stor_dbg(us, "Result for bulk_transfer in sddr09_writeX %d\n", +			     result);  		return -EIO;  	}  	return 0; @@ -687,8 +684,8 @@ sddr09_read_sg_test_only(struct us_data *us) {  	result = sddr09_send_scsi_command(us, command, 4*nsg+3);  	if (result) { -		US_DEBUGP("Result for send_control in sddr09_read_sg %d\n", -			  result); +		usb_stor_dbg(us, "Result for send_control in sddr09_read_sg %d\n", +			     result);  		return result;  	} @@ -700,8 +697,8 @@ sddr09_read_sg_test_only(struct us_data *us) {  				       buf, bulklen, NULL);  	kfree(buf);  	if (result != USB_STOR_XFER_GOOD) { -		US_DEBUGP("Result for bulk_transfer in sddr09_read_sg %d\n", -			  result); +		usb_stor_dbg(us, "Result for bulk_transfer in sddr09_read_sg %d\n", +			     result);  		return -EIO;  	} @@ -727,7 +724,7 @@ sddr09_read_status(struct us_data *us, unsigned char *status) {  	unsigned char *data = us->iobuf;  	int result; -	US_DEBUGP("Reading status...\n"); +	usb_stor_dbg(us, "Reading status...\n");  	memset(command, 0, 12);  	command[0] = 0xEC; @@ -789,8 +786,8 @@ sddr09_read_data(struct us_data *us,  		/* Not overflowing capacity? */  		if (lba >= maxlba) { -			US_DEBUGP("Error: Requested lba %u exceeds " -				  "maximum %u\n", lba, maxlba); +			usb_stor_dbg(us, "Error: Requested lba %u exceeds maximum %u\n", +				     lba, maxlba);  			result = -EIO;  			break;  		} @@ -800,8 +797,8 @@ sddr09_read_data(struct us_data *us,  		if (pba == UNDEF) {	/* this lba was never written */ -			US_DEBUGP("Read %d zero pages (LBA %d) page %d\n", -				  pages, lba, page); +			usb_stor_dbg(us, "Read %d zero pages (LBA %d) page %d\n", +				     pages, lba, page);  			/* This is not really an error. It just means  			   that the block has never been written. @@ -811,9 +808,8 @@ sddr09_read_data(struct us_data *us,  			memset(buffer, 0, len);  		} else { -			US_DEBUGP("Read %d pages, from PBA %d" -				  " (LBA %d) page %d\n", -				  pages, pba, lba, page); +			usb_stor_dbg(us, "Read %d pages, from PBA %d (LBA %d) page %d\n", +				     pages, pba, lba, page);  			address = ((pba << info->blockshift) + page) <<   				info->pageshift; @@ -916,14 +912,14 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,  		cptr = bptr + info->pagesize;  		nand_compute_ecc(bptr, ecc);  		if (!nand_compare_ecc(cptr+13, ecc)) { -			US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n", -				  i, pba); +			usb_stor_dbg(us, "Warning: bad ecc in page %d- of pba %d\n", +				     i, pba);  			nand_store_ecc(cptr+13, ecc);  		}  		nand_compute_ecc(bptr+(info->pagesize / 2), ecc);  		if (!nand_compare_ecc(cptr+8, ecc)) { -			US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n", -				  i, pba); +			usb_stor_dbg(us, "Warning: bad ecc in page %d+ of pba %d\n", +				     i, pba);  			nand_store_ecc(cptr+8, ecc);  		}  		cptr[6] = cptr[11] = MSB_of(lbap); @@ -943,22 +939,21 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,  		nand_store_ecc(cptr+8, ecc);  	} -	US_DEBUGP("Rewrite PBA %d (LBA %d)\n", pba, lba); +	usb_stor_dbg(us, "Rewrite PBA %d (LBA %d)\n", pba, lba);  	result = sddr09_write_inplace(us, address>>1, info->blocksize,  				      info->pageshift, blockbuffer, 0); -	US_DEBUGP("sddr09_write_inplace returns %d\n", result); +	usb_stor_dbg(us, "sddr09_write_inplace returns %d\n", result);  #if 0  	{  		unsigned char status = 0;  		int result2 = sddr09_read_status(us, &status);  		if (result2) -			US_DEBUGP("sddr09_write_inplace: cannot read status\n"); +			usb_stor_dbg(us, "cannot read status\n");  		else if (status != 0xc0) -			US_DEBUGP("sddr09_write_inplace: status after write: 0x%x\n", -				  status); +			usb_stor_dbg(us, "status after write: 0x%x\n", status);  	}  #endif @@ -1031,8 +1026,8 @@ sddr09_write_data(struct us_data *us,  		/* Not overflowing capacity? */  		if (lba >= maxlba) { -			US_DEBUGP("Error: Requested lba %u exceeds " -				  "maximum %u\n", lba, maxlba); +			usb_stor_dbg(us, "Error: Requested lba %u exceeds maximum %u\n", +				     lba, maxlba);  			result = -EIO;  			break;  		} @@ -1064,8 +1059,8 @@ sddr09_read_control(struct us_data *us,  		unsigned char *content,  		int use_sg) { -	US_DEBUGP("Read control address %lu, blocks %d\n", -		address, blocks); +	usb_stor_dbg(us, "Read control address %lu, blocks %d\n", +		     address, blocks);  	return sddr09_read21(us, address, blocks,  			     CONTROL_SHIFT, content, use_sg); @@ -1111,21 +1106,21 @@ sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) {  	result = sddr09_read_status(us, &status);  	if (result) { -		US_DEBUGP("sddr09_get_wp: read_status fails\n"); +		usb_stor_dbg(us, "read_status fails\n");  		return result;  	} -	US_DEBUGP("sddr09_get_wp: status 0x%02X", status); +	usb_stor_dbg(us, "status 0x%02X", status);  	if ((status & 0x80) == 0) {  		info->flags |= SDDR09_WP;	/* write protected */ -		US_DEBUGP(" WP"); +		US_DEBUGPX(" WP");  	}  	if (status & 0x40) -		US_DEBUGP(" Ready"); +		US_DEBUGPX(" Ready");  	if (status & LUNBITS) -		US_DEBUGP(" Suspended"); +		US_DEBUGPX(" Suspended");  	if (status & 0x1) -		US_DEBUGP(" Error"); -	US_DEBUGP("\n"); +		US_DEBUGPX(" Error"); +	US_DEBUGPX("\n");  	return 0;  } @@ -1154,12 +1149,12 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) {  	char blurbtxt[256];  	int result; -	US_DEBUGP("Reading capacity...\n"); +	usb_stor_dbg(us, "Reading capacity...\n");  	result = sddr09_read_deviceID(us, deviceID);  	if (result) { -		US_DEBUGP("Result of read_deviceID is %d\n", result); +		usb_stor_dbg(us, "Result of read_deviceID is %d\n", result);  		printk(KERN_WARNING "sddr09: could not read card info\n");  		return NULL;  	} @@ -1392,7 +1387,7 @@ sddr09_read_map(struct us_data *us) {  		lbact += ct;  	}  	info->lbact = lbact; -	US_DEBUGP("Found %d LBA's\n", lbact); +	usb_stor_dbg(us, "Found %d LBA's\n", lbact);  	result = 0;   done: @@ -1423,18 +1418,18 @@ sddr09_common_init(struct us_data *us) {  	/* set the configuration -- STALL is an acceptable response here */  	if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) { -		US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev -				->actconfig->desc.bConfigurationValue); +		usb_stor_dbg(us, "active config #%d != 1 ??\n", +			     us->pusb_dev->actconfig->desc.bConfigurationValue);  		return -EINVAL;  	}  	result = usb_reset_configuration(us->pusb_dev); -	US_DEBUGP("Result of usb_reset_configuration is %d\n", result); +	usb_stor_dbg(us, "Result of usb_reset_configuration is %d\n", result);  	if (result == -EPIPE) { -		US_DEBUGP("-- stall on control interface\n"); +		usb_stor_dbg(us, "-- stall on control interface\n");  	} else if (result != 0) {  		/* it's not a stall, but another error -- time to bail */ -		US_DEBUGP("-- Unknown error.  Rejecting device\n"); +		usb_stor_dbg(us, "-- Unknown error.  Rejecting device\n");  		return -EINVAL;  	} @@ -1464,20 +1459,20 @@ usb_stor_sddr09_dpcm_init(struct us_data *us) {  	result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2);  	if (result) { -		US_DEBUGP("sddr09_init: send_command fails\n"); +		usb_stor_dbg(us, "send_command fails\n");  		return result;  	} -	US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]); +	usb_stor_dbg(us, "%02X %02X\n", data[0], data[1]);  	// get 07 02  	result = sddr09_send_command(us, 0x08, USB_DIR_IN, data, 2);  	if (result) { -		US_DEBUGP("sddr09_init: 2nd send_command fails\n"); +		usb_stor_dbg(us, "2nd send_command fails\n");  		return result;  	} -	US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]); +	usb_stor_dbg(us, "%02X %02X\n", data[0], data[1]);  	// get 07 00  	result = sddr09_request_sense(us, data, 18); @@ -1507,7 +1502,7 @@ static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)  {  	int ret; -	US_DEBUGP("dpcm_transport: LUN=%d\n", srb->device->lun); +	usb_stor_dbg(us, "LUN=%d\n", srb->device->lun);  	switch (srb->device->lun) {  	case 0: @@ -1533,8 +1528,7 @@ static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)  		break;  	default: -		US_DEBUGP("dpcm_transport: Invalid LUN %d\n", -				srb->device->lun); +		usb_stor_dbg(us, "Invalid LUN %d\n", srb->device->lun);  		ret = USB_STOR_TRANSPORT_ERROR;  		break;  	} @@ -1640,8 +1634,8 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)  		   or for all pages. */  		/* %% We should check DBD %% */  		if (modepage == 0x01 || modepage == 0x3F) { -			US_DEBUGP("SDDR09: Dummy up request for " -				  "mode page 0x%x\n", modepage); +			usb_stor_dbg(us, "Dummy up request for mode page 0x%x\n", +				     modepage);  			memcpy(ptr, mode_page_01, sizeof(mode_page_01));  			((__be16*)ptr)[0] = cpu_to_be16(sizeof(mode_page_01) - 2); @@ -1667,8 +1661,8 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)  		page |= short_pack(srb->cmnd[5], srb->cmnd[4]);  		pages = short_pack(srb->cmnd[8], srb->cmnd[7]); -		US_DEBUGP("READ_10: read page %d pagect %d\n", -			  page, pages); +		usb_stor_dbg(us, "READ_10: read page %d pagect %d\n", +			     page, pages);  		result = sddr09_read_data(us, page, pages);  		return (result == 0 ? USB_STOR_TRANSPORT_GOOD : @@ -1682,8 +1676,8 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)  		page |= short_pack(srb->cmnd[5], srb->cmnd[4]);  		pages = short_pack(srb->cmnd[8], srb->cmnd[7]); -		US_DEBUGP("WRITE_10: write page %d pagect %d\n", -			  page, pages); +		usb_stor_dbg(us, "WRITE_10: write page %d pagect %d\n", +			     page, pages);  		result = sddr09_write_data(us, page, pages);  		return (result == 0 ? USB_STOR_TRANSPORT_GOOD : @@ -1710,12 +1704,12 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)  	for (i=0; i<12; i++)  		sprintf(ptr+strlen(ptr), "%02X ", srb->cmnd[i]); -	US_DEBUGP("SDDR09: Send control for command %s\n", ptr); +	usb_stor_dbg(us, "Send control for command %s\n", ptr);  	result = sddr09_send_scsi_command(us, srb->cmnd, 12);  	if (result) { -		US_DEBUGP("sddr09_transport: sddr09_send_scsi_command " -			  "returns %d\n", result); +		usb_stor_dbg(us, "sddr09_send_scsi_command returns %d\n", +			     result);  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -1727,10 +1721,10 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)  		unsigned int pipe = (srb->sc_data_direction == DMA_TO_DEVICE)  				? us->send_bulk_pipe : us->recv_bulk_pipe; -		US_DEBUGP("SDDR09: %s %d bytes\n", -			  (srb->sc_data_direction == DMA_TO_DEVICE) ? -			  "sending" : "receiving", -			  scsi_bufflen(srb)); +		usb_stor_dbg(us, "%s %d bytes\n", +			     (srb->sc_data_direction == DMA_TO_DEVICE) ? +			     "sending" : "receiving", +			     scsi_bufflen(srb));  		result = usb_stor_bulk_srb(us, pipe, srb); diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index d278c5a99b7..aacedef9667 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -145,8 +145,7 @@ static int sddr55_status(struct us_data *us)  	result = sddr55_bulk_transport(us,  		DMA_TO_DEVICE, command, 8); -	US_DEBUGP("Result for send_command in status %d\n", -		result); +	usb_stor_dbg(us, "Result for send_command in status %d\n", result);  	if (result != USB_STOR_XFER_GOOD) {  		set_sense_info (4, 0, 0);	/* hardware error */ @@ -236,9 +235,8 @@ static int sddr55_read_data(struct us_data *us,  				info->blocksize - page);  		len = pages << info->pageshift; -		US_DEBUGP("Read %02X pages, from PBA %04X" -			" (LBA %04X) page %02X\n", -			pages, pba, lba, page); +		usb_stor_dbg(us, "Read %02X pages, from PBA %04X (LBA %04X) page %02X\n", +			     pages, pba, lba, page);  		if (pba == NOT_ALLOCATED) {  			/* no pba for this lba, fill with zeroes */ @@ -261,8 +259,8 @@ static int sddr55_read_data(struct us_data *us,  			result = sddr55_bulk_transport(us,  				DMA_TO_DEVICE, command, 8); -			US_DEBUGP("Result for send_command in read_data %d\n", -				result); +			usb_stor_dbg(us, "Result for send_command in read_data %d\n", +				     result);  			if (result != USB_STOR_XFER_GOOD) {  				result = USB_STOR_TRANSPORT_ERROR; @@ -368,9 +366,8 @@ static int sddr55_write_data(struct us_data *us,  		usb_stor_access_xfer_buf(buffer, len, us->srb,  				&sg, &offset, FROM_XFER_BUF); -		US_DEBUGP("Write %02X pages, to PBA %04X" -			" (LBA %04X) page %02X\n", -			pages, pba, lba, page); +		usb_stor_dbg(us, "Write %02X pages, to PBA %04X (LBA %04X) page %02X\n", +			     pages, pba, lba, page);  		command[4] = 0; @@ -384,7 +381,7 @@ static int sddr55_write_data(struct us_data *us,  			/* set pba to first block in zone lba is in */  			pba = (lba / 1000) * 1024; -			US_DEBUGP("No PBA for LBA %04X\n",lba); +			usb_stor_dbg(us, "No PBA for LBA %04X\n", lba);  			if (max_pba > 1024)  				max_pba = 1024; @@ -407,14 +404,15 @@ static int sddr55_write_data(struct us_data *us,  			if (pba == -1) {  				/* oh dear */ -				US_DEBUGP("Couldn't find unallocated block\n"); +				usb_stor_dbg(us, "Couldn't find unallocated block\n");  				set_sense_info (3, 0x31, 0);	/* medium error */  				result = USB_STOR_TRANSPORT_FAILED;  				goto leave;  			} -			US_DEBUGP("Allocating PBA %04X for LBA %04X\n", pba, lba); +			usb_stor_dbg(us, "Allocating PBA %04X for LBA %04X\n", +				     pba, lba);  			/* set writing to unallocated block flag */  			command[4] = 0x40; @@ -439,8 +437,8 @@ static int sddr55_write_data(struct us_data *us,  			DMA_TO_DEVICE, command, 8);  		if (result != USB_STOR_XFER_GOOD) { -			US_DEBUGP("Result for send_command in write_data %d\n", -			result); +			usb_stor_dbg(us, "Result for send_command in write_data %d\n", +				     result);  			/* set_sense_info is superfluous here? */  			set_sense_info (3, 0x3, 0);/* peripheral write error */ @@ -453,8 +451,8 @@ static int sddr55_write_data(struct us_data *us,  			DMA_TO_DEVICE, buffer, len);  		if (result != USB_STOR_XFER_GOOD) { -			US_DEBUGP("Result for send_data in write_data %d\n", -				  result); +			usb_stor_dbg(us, "Result for send_data in write_data %d\n", +				     result);  			/* set_sense_info is superfluous here? */  			set_sense_info (3, 0x3, 0);/* peripheral write error */ @@ -466,8 +464,8 @@ static int sddr55_write_data(struct us_data *us,  		result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, status, 6);  		if (result != USB_STOR_XFER_GOOD) { -			US_DEBUGP("Result for get_status in write_data %d\n", -				  result); +			usb_stor_dbg(us, "Result for get_status in write_data %d\n", +				     result);  			/* set_sense_info is superfluous here? */  			set_sense_info (3, 0x3, 0);/* peripheral write error */ @@ -487,8 +485,8 @@ static int sddr55_write_data(struct us_data *us,  			goto leave;  		} -		US_DEBUGP("Updating maps for LBA %04X: old PBA %04X, new PBA %04X\n", -			lba, pba, new_pba); +		usb_stor_dbg(us, "Updating maps for LBA %04X: old PBA %04X, new PBA %04X\n", +			     lba, pba, new_pba);  		/* update the lba<->pba maps, note new_pba might be the same as pba */  		info->lba_to_pba[lba] = new_pba; @@ -531,8 +529,8 @@ static int sddr55_read_deviceID(struct us_data *us,  	command[7] = 0x84;  	result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8); -	US_DEBUGP("Result of send_control for device ID is %d\n", -		result); +	usb_stor_dbg(us, "Result of send_control for device ID is %d\n", +		     result);  	if (result != USB_STOR_XFER_GOOD)  		return USB_STOR_TRANSPORT_ERROR; @@ -568,20 +566,19 @@ static unsigned long sddr55_get_capacity(struct us_data *us) {  	int result;  	struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; -	US_DEBUGP("Reading capacity...\n"); +	usb_stor_dbg(us, "Reading capacity...\n");  	result = sddr55_read_deviceID(us,  		&manufacturerID,  		&deviceID); -	US_DEBUGP("Result of read_deviceID is %d\n", -		result); +	usb_stor_dbg(us, "Result of read_deviceID is %d\n", result);  	if (result != USB_STOR_XFER_GOOD)  		return 0; -	US_DEBUGP("Device ID = %02X\n", deviceID); -	US_DEBUGP("Manuf  ID = %02X\n", manufacturerID); +	usb_stor_dbg(us, "Device ID = %02X\n", deviceID); +	usb_stor_dbg(us, "Manuf  ID = %02X\n", manufacturerID);  	info->pageshift = 9;  	info->smallpageshift = 0; @@ -753,7 +750,7 @@ static int sddr55_read_map(struct us_data *us) {  		}  		if (lba<0x10 || (lba>=0x3E0 && lba<0x3EF)) -			US_DEBUGP("LBA %04X <-> PBA %04X\n", lba, i); +			usb_stor_dbg(us, "LBA %04X <-> PBA %04X\n", lba, i);  		info->lba_to_pba[lba + zone * 1000] = i;  	} @@ -808,7 +805,10 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)  	info = (struct sddr55_card_info *)(us->extra);  	if (srb->cmnd[0] == REQUEST_SENSE) { -		US_DEBUGP("SDDR55: request sense %02x/%02x/%02x\n", info->sense_data[2], info->sense_data[12], info->sense_data[13]); +		usb_stor_dbg(us, "request sense %02x/%02x/%02x\n", +			     info->sense_data[2], +			     info->sense_data[12], +			     info->sense_data[13]);  		memcpy (ptr, info->sense_data, sizeof info->sense_data);  		ptr[0] = 0x70; @@ -892,13 +892,11 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)  		usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb);  		if ( (srb->cmnd[2] & 0x3F) == 0x01 ) { -			US_DEBUGP( -			  "SDDR55: Dummy up request for mode page 1\n"); +			usb_stor_dbg(us, "Dummy up request for mode page 1\n");  			return USB_STOR_TRANSPORT_GOOD;  		} else if ( (srb->cmnd[2] & 0x3F) == 0x3F ) { -			US_DEBUGP( -			  "SDDR55: Dummy up request for all mode pages\n"); +			usb_stor_dbg(us, "Dummy up request for all mode pages\n");  			return USB_STOR_TRANSPORT_GOOD;  		} @@ -908,10 +906,8 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)  	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) { -		US_DEBUGP( -		  "SDDR55: %s medium removal. Not that I can do" -		  " anything about it...\n", -		  (srb->cmnd[4]&0x03) ? "Prevent" : "Allow"); +		usb_stor_dbg(us, "%s medium removal. Not that I can do anything about it...\n", +			     (srb->cmnd[4]&0x03) ? "Prevent" : "Allow");  		return USB_STOR_TRANSPORT_GOOD; @@ -935,8 +931,8 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)  		if (lba >= info->max_log_blks) { -			US_DEBUGP("Error: Requested LBA %04X exceeds maximum " -			  "block %04X\n", lba, info->max_log_blks-1); +			usb_stor_dbg(us, "Error: Requested LBA %04X exceeds maximum block %04X\n", +				     lba, info->max_log_blks - 1);  			set_sense_info (5, 0x24, 0);	/* invalid field in command */ @@ -946,15 +942,13 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)  		pba = info->lba_to_pba[lba];  		if (srb->cmnd[0] == WRITE_10) { -			US_DEBUGP("WRITE_10: write block %04X (LBA %04X) page %01X" -				" pages %d\n", -				pba, lba, page, pages); +			usb_stor_dbg(us, "WRITE_10: write block %04X (LBA %04X) page %01X pages %d\n", +				     pba, lba, page, pages);  			return sddr55_write_data(us, lba, page, pages);  		} else { -			US_DEBUGP("READ_10: read block %04X (LBA %04X) page %01X" -				" pages %d\n", -				pba, lba, page, pages); +			usb_stor_dbg(us, "READ_10: read block %04X (LBA %04X) page %01X pages %d\n", +				     pba, lba, page, pages);  			return sddr55_read_data(us, lba, page, pages);  		} diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index daf2fc58ae0..4ef2a80728f 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -271,7 +271,7 @@ static int usbat_bulk_read(struct us_data *us,  	if (len == 0)  		return USB_STOR_XFER_GOOD; -	US_DEBUGP("usbat_bulk_read: len = %d\n", len); +	usb_stor_dbg(us, "len = %d\n", len);  	return usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe, buf, len, use_sg, NULL);  } @@ -286,7 +286,7 @@ static int usbat_bulk_write(struct us_data *us,  	if (len == 0)  		return USB_STOR_XFER_GOOD; -	US_DEBUGP("usbat_bulk_write:  len = %d\n", len); +	usb_stor_dbg(us, "len = %d\n", len);  	return usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe, buf, len, use_sg, NULL);  } @@ -312,7 +312,7 @@ static int usbat_get_status(struct us_data *us, unsigned char *status)  	int rc;  	rc = usbat_read(us, USBAT_ATA, USBAT_ATA_STATUS, status); -	US_DEBUGP("usbat_get_status: 0x%02X\n", (unsigned short) (*status)); +	usb_stor_dbg(us, "0x%02X\n", *status);  	return rc;  } @@ -425,7 +425,7 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes)  			return USB_STOR_TRANSPORT_FAILED;  		if ((*status & 0x80)==0x00) { /* not busy */ -			US_DEBUGP("Waited not busy for %d steps\n", i); +			usb_stor_dbg(us, "Waited not busy for %d steps\n", i);  			return USB_STOR_TRANSPORT_GOOD;  		} @@ -439,8 +439,8 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes)  			msleep(1000); /* X minutes */  	} -	US_DEBUGP("Waited not busy for %d minutes, timing out.\n", -		minutes); +	usb_stor_dbg(us, "Waited not busy for %d minutes, timing out\n", +		     minutes);  	return USB_STOR_TRANSPORT_FAILED;  } @@ -657,8 +657,9 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,  			if (*status & 0x20) /* device fault */  				return USB_STOR_TRANSPORT_FAILED; -			US_DEBUGP("Redoing %s\n", -			  direction==DMA_TO_DEVICE ? "write" : "read"); +			usb_stor_dbg(us, "Redoing %s\n", +				     direction == DMA_TO_DEVICE +				     ? "write" : "read");  		} else if (result != USB_STOR_XFER_GOOD)  			return USB_STOR_TRANSPORT_ERROR; @@ -667,8 +668,8 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,  	} -	US_DEBUGP("Bummer! %s bulk data 20 times failed.\n", -		direction==DMA_TO_DEVICE ? "Writing" : "Reading"); +	usb_stor_dbg(us, "Bummer! %s bulk data 20 times failed\n", +		     direction == DMA_TO_DEVICE ? "Writing" : "Reading");  	return USB_STOR_TRANSPORT_FAILED;  } @@ -827,7 +828,7 @@ static int usbat_read_user_io(struct us_data *us, unsigned char *data_flags)  		data_flags,  		USBAT_UIO_READ); -	US_DEBUGP("usbat_read_user_io: UIO register reads %02X\n", (unsigned short) (*data_flags)); +	usb_stor_dbg(us, "UIO register reads %02X\n", *data_flags);  	return result;  } @@ -900,10 +901,11 @@ static int usbat_device_enable_cdt(struct us_data *us)  /*   * Determine if media is present.   */ -static int usbat_flash_check_media_present(unsigned char *uio) +static int usbat_flash_check_media_present(struct us_data *us, +					   unsigned char *uio)  {  	if (*uio & USBAT_UIO_UI0) { -		US_DEBUGP("usbat_flash_check_media_present: no media detected\n"); +		usb_stor_dbg(us, "no media detected\n");  		return USBAT_FLASH_MEDIA_NONE;  	} @@ -913,10 +915,11 @@ static int usbat_flash_check_media_present(unsigned char *uio)  /*   * Determine if media has changed since last operation   */ -static int usbat_flash_check_media_changed(unsigned char *uio) +static int usbat_flash_check_media_changed(struct us_data *us, +					   unsigned char *uio)  {  	if (*uio & USBAT_UIO_0) { -		US_DEBUGP("usbat_flash_check_media_changed: media change detected\n"); +		usb_stor_dbg(us, "media change detected\n");  		return USBAT_FLASH_MEDIA_CHANGED;  	} @@ -937,7 +940,7 @@ static int usbat_flash_check_media(struct us_data *us,  		return USB_STOR_TRANSPORT_ERROR;  	/* Check for media existence */ -	rc = usbat_flash_check_media_present(uio); +	rc = usbat_flash_check_media_present(us, uio);  	if (rc == USBAT_FLASH_MEDIA_NONE) {  		info->sense_key = 0x02;  		info->sense_asc = 0x3A; @@ -946,7 +949,7 @@ static int usbat_flash_check_media(struct us_data *us,  	}  	/* Check for media change */ -	rc = usbat_flash_check_media_changed(uio); +	rc = usbat_flash_check_media_changed(us, uio);  	if (rc == USBAT_FLASH_MEDIA_CHANGED) {  		/* Reset and re-enable card detect */ @@ -1008,11 +1011,11 @@ static int usbat_identify_device(struct us_data *us,  	/* Check for error bit, or if the command 'fell through' */  	if (status == 0xA1 || !(status & 0x01)) {  		/* Device is HP 8200 */ -		US_DEBUGP("usbat_identify_device: Detected HP8200 CDRW\n"); +		usb_stor_dbg(us, "Detected HP8200 CDRW\n");  		info->devicetype = USBAT_DEV_HP8200;  	} else {  		/* Device is a CompactFlash reader/writer */ -		US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n"); +		usb_stor_dbg(us, "Detected Flash reader/writer\n");  		info->devicetype = USBAT_DEV_FLASH;  	} @@ -1075,7 +1078,7 @@ static int usbat_flash_get_sector_count(struct us_data *us,  	/* ATA command : IDENTIFY DEVICE */  	rc = usbat_multiple_write(us, registers, command, 3);  	if (rc != USB_STOR_XFER_GOOD) { -		US_DEBUGP("usbat_flash_get_sector_count: Gah! identify_device failed\n"); +		usb_stor_dbg(us, "Gah! identify_device failed\n");  		rc = USB_STOR_TRANSPORT_ERROR;  		goto leave;  	} @@ -1178,7 +1181,7 @@ static int usbat_flash_read_data(struct us_data *us,  		if (result != USB_STOR_TRANSPORT_GOOD)  			goto leave; -		US_DEBUGP("usbat_flash_read_data:  %d bytes\n", len); +		usb_stor_dbg(us, "%d bytes\n", len);  		/* Store the data in the transfer buffer */  		usb_stor_access_xfer_buf(buffer, len, us->srb, @@ -1301,8 +1304,7 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,  	unsigned int sg_offset = 0;  	struct scatterlist *sg = NULL; -	US_DEBUGP("handle_read10: transfersize %d\n", -		srb->transfersize); +	usb_stor_dbg(us, "transfersize %d\n", srb->transfersize);  	if (scsi_bufflen(srb) < 0x10000) { @@ -1329,14 +1331,14 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,  		len = short_pack(data[7+9], data[7+8]);  		len <<= 16;  		len |= data[7+7]; -		US_DEBUGP("handle_read10: GPCMD_READ_CD: len %d\n", len); +		usb_stor_dbg(us, "GPCMD_READ_CD: len %d\n", len);  		srb->transfersize = scsi_bufflen(srb)/len;  	}  	if (!srb->transfersize)  {  		srb->transfersize = 2048; /* A guess */ -		US_DEBUGP("handle_read10: transfersize 0, forcing %d\n", -			srb->transfersize); +		usb_stor_dbg(us, "transfersize 0, forcing %d\n", +			     srb->transfersize);  	}  	/* @@ -1346,7 +1348,7 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,  	 */  	len = (65535/srb->transfersize) * srb->transfersize; -	US_DEBUGP("Max read is %d bytes\n", len); +	usb_stor_dbg(us, "Max read is %d bytes\n", len);  	len = min(len, scsi_bufflen(srb));  	buffer = kmalloc(len, GFP_NOIO);  	if (buffer == NULL) /* bloody hell! */ @@ -1460,10 +1462,9 @@ static int init_usbat(struct us_data *us, int devicetype)  	unsigned char *status = us->iobuf;  	us->extra = kzalloc(sizeof(struct usbat_info), GFP_NOIO); -	if (!us->extra) { -		US_DEBUGP("init_usbat: Gah! Can't allocate storage for usbat info struct!\n"); +	if (!us->extra)  		return 1; -	} +  	info = (struct usbat_info *) (us->extra);  	/* Enable peripheral control signals */ @@ -1473,7 +1474,7 @@ static int init_usbat(struct us_data *us, int devicetype)  	if (rc != USB_STOR_XFER_GOOD)  		return USB_STOR_TRANSPORT_ERROR; -	US_DEBUGP("INIT 1\n"); +	usb_stor_dbg(us, "INIT 1\n");  	msleep(2000); @@ -1481,7 +1482,7 @@ static int init_usbat(struct us_data *us, int devicetype)  	if (rc != USB_STOR_TRANSPORT_GOOD)  		return rc; -	US_DEBUGP("INIT 2\n"); +	usb_stor_dbg(us, "INIT 2\n");  	rc = usbat_read_user_io(us, status);  	if (rc != USB_STOR_XFER_GOOD) @@ -1491,32 +1492,32 @@ static int init_usbat(struct us_data *us, int devicetype)  	if (rc != USB_STOR_XFER_GOOD)  		return USB_STOR_TRANSPORT_ERROR; -	US_DEBUGP("INIT 3\n"); +	usb_stor_dbg(us, "INIT 3\n");  	rc = usbat_select_and_test_registers(us);  	if (rc != USB_STOR_TRANSPORT_GOOD)  		return rc; -	US_DEBUGP("INIT 4\n"); +	usb_stor_dbg(us, "INIT 4\n");  	rc = usbat_read_user_io(us, status);  	if (rc != USB_STOR_XFER_GOOD)  		return USB_STOR_TRANSPORT_ERROR; -	US_DEBUGP("INIT 5\n"); +	usb_stor_dbg(us, "INIT 5\n");  	/* Enable peripheral control signals and card detect */  	rc = usbat_device_enable_cdt(us);  	if (rc != USB_STOR_TRANSPORT_GOOD)  		return rc; -	US_DEBUGP("INIT 6\n"); +	usb_stor_dbg(us, "INIT 6\n");  	rc = usbat_read_user_io(us, status);  	if (rc != USB_STOR_XFER_GOOD)  		return USB_STOR_TRANSPORT_ERROR; -	US_DEBUGP("INIT 7\n"); +	usb_stor_dbg(us, "INIT 7\n");  	msleep(1400); @@ -1524,19 +1525,19 @@ static int init_usbat(struct us_data *us, int devicetype)  	if (rc != USB_STOR_XFER_GOOD)  		return USB_STOR_TRANSPORT_ERROR; -	US_DEBUGP("INIT 8\n"); +	usb_stor_dbg(us, "INIT 8\n");  	rc = usbat_select_and_test_registers(us);  	if (rc != USB_STOR_TRANSPORT_GOOD)  		return rc; -	US_DEBUGP("INIT 9\n"); +	usb_stor_dbg(us, "INIT 9\n");  	/* At this point, we need to detect which device we are using */  	if (usbat_set_transport(us, info, devicetype))  		return USB_STOR_TRANSPORT_ERROR; -	US_DEBUGP("INIT 10\n"); +	usb_stor_dbg(us, "INIT 10\n");  	if (usbat_get_device_type(us) == USBAT_DEV_FLASH) {   		subcountH = 0x02; @@ -1547,7 +1548,7 @@ static int init_usbat(struct us_data *us, int devicetype)  	if (rc != USB_STOR_XFER_GOOD)  		return USB_STOR_TRANSPORT_ERROR; -	US_DEBUGP("INIT 11\n"); +	usb_stor_dbg(us, "INIT 11\n");  	return USB_STOR_TRANSPORT_GOOD;  } @@ -1592,7 +1593,7 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)  	}  	result = usbat_get_status(us, status); -	US_DEBUGP("Status = %02X\n", *status); +	usb_stor_dbg(us, "Status = %02X\n", *status);  	if (result != USB_STOR_XFER_GOOD)  		return USB_STOR_TRANSPORT_ERROR;  	if (srb->cmnd[0] == TEST_UNIT_READY) @@ -1610,7 +1611,7 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)  		if (result == USB_STOR_TRANSPORT_GOOD) {  			transferred += len; -			US_DEBUGP("Wrote %08X bytes\n", transferred); +			usb_stor_dbg(us, "Wrote %08X bytes\n", transferred);  		}  		return result; @@ -1623,8 +1624,8 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)  	}  	if (len > 0xFFFF) { -		US_DEBUGP("Error: len = %08X... what do I do now?\n", -			len); +		usb_stor_dbg(us, "Error: len = %08X... what do I do now?\n", +			     len);  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -1693,7 +1694,7 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)  	};  	if (srb->cmnd[0] == INQUIRY) { -		US_DEBUGP("usbat_flash_transport: INQUIRY. Returning bogus response.\n"); +		usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");  		memcpy(ptr, inquiry_response, sizeof(inquiry_response));  		fill_inquiry_response(us, ptr, 36);  		return USB_STOR_TRANSPORT_GOOD; @@ -1710,8 +1711,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)  		/* hard coded 512 byte sectors as per ATA spec */  		info->ssize = 0x200; -		US_DEBUGP("usbat_flash_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n", -			  info->sectors, info->ssize); +		usb_stor_dbg(us, "READ_CAPACITY: %ld sectors, %ld bytes per sector\n", +			     info->sectors, info->ssize);  		/*  		 * build the reply @@ -1726,7 +1727,7 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)  	}  	if (srb->cmnd[0] == MODE_SELECT_10) { -		US_DEBUGP("usbat_flash_transport:  Gah! MODE_SELECT_10.\n"); +		usb_stor_dbg(us, "Gah! MODE_SELECT_10\n");  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -1736,7 +1737,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)  		blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); -		US_DEBUGP("usbat_flash_transport:  READ_10: read block 0x%04lx  count %ld\n", block, blocks); +		usb_stor_dbg(us, "READ_10: read block 0x%04lx  count %ld\n", +			     block, blocks);  		return usbat_flash_read_data(us, info, block, blocks);  	} @@ -1750,7 +1752,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)  		blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |  		         ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9])); -		US_DEBUGP("usbat_flash_transport: READ_12: read block 0x%04lx  count %ld\n", block, blocks); +		usb_stor_dbg(us, "READ_12: read block 0x%04lx  count %ld\n", +			     block, blocks);  		return usbat_flash_read_data(us, info, block, blocks);  	} @@ -1760,7 +1763,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)  		blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); -		US_DEBUGP("usbat_flash_transport: WRITE_10: write block 0x%04lx  count %ld\n", block, blocks); +		usb_stor_dbg(us, "WRITE_10: write block 0x%04lx  count %ld\n", +			     block, blocks);  		return usbat_flash_write_data(us, info, block, blocks);  	} @@ -1774,13 +1778,14 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)  		blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |  		         ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9])); -		US_DEBUGP("usbat_flash_transport: WRITE_12: write block 0x%04lx  count %ld\n", block, blocks); +		usb_stor_dbg(us, "WRITE_12: write block 0x%04lx  count %ld\n", +			     block, blocks);  		return usbat_flash_write_data(us, info, block, blocks);  	}  	if (srb->cmnd[0] == TEST_UNIT_READY) { -		US_DEBUGP("usbat_flash_transport: TEST_UNIT_READY.\n"); +		usb_stor_dbg(us, "TEST_UNIT_READY\n");  		rc = usbat_flash_check_media(us, info);  		if (rc != USB_STOR_TRANSPORT_GOOD) @@ -1790,7 +1795,7 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)  	}  	if (srb->cmnd[0] == REQUEST_SENSE) { -		US_DEBUGP("usbat_flash_transport: REQUEST_SENSE.\n"); +		usb_stor_dbg(us, "REQUEST_SENSE\n");  		memset(ptr, 0, 18);  		ptr[0] = 0xF0; @@ -1811,8 +1816,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)  		return USB_STOR_TRANSPORT_GOOD;  	} -	US_DEBUGP("usbat_flash_transport: Gah! Unknown command: %d (0x%x)\n", -			  srb->cmnd[0], srb->cmnd[0]); +	usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n", +		     srb->cmnd[0], srb->cmnd[0]);  	info->sense_key = 0x05;  	info->sense_asc = 0x20;  	info->sense_ascq = 0x00; diff --git a/drivers/usb/storage/sierra_ms.c b/drivers/usb/storage/sierra_ms.c index 17e36952bce..2ea657be14c 100644 --- a/drivers/usb/storage/sierra_ms.c +++ b/drivers/usb/storage/sierra_ms.c @@ -47,7 +47,7 @@ static bool containsFullLinuxPackage(struct swoc_info *swocInfo)  static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode)  {  	int result; -	US_DEBUGP("SWIMS: %s", "DEVICE MODE SWITCH\n"); +	dev_dbg(&udev->dev, "SWIMS: %s", "DEVICE MODE SWITCH\n");  	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),  			SWIMS_USB_REQUEST_SetSwocMode,	/* __u8 request      */  			USB_TYPE_VENDOR | USB_DIR_OUT,	/* __u8 request type */ @@ -65,7 +65,7 @@ static int sierra_get_swoc_info(struct usb_device *udev,  {  	int result; -	US_DEBUGP("SWIMS: Attempting to get TRU-Install info.\n"); +	dev_dbg(&udev->dev, "SWIMS: Attempting to get TRU-Install info\n");  	result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),  			SWIMS_USB_REQUEST_GetSwocInfo,	/* __u8 request      */ @@ -81,11 +81,11 @@ static int sierra_get_swoc_info(struct usb_device *udev,  	return result;  } -static void debug_swoc(struct swoc_info *swocInfo) +static void debug_swoc(const struct device *dev, struct swoc_info *swocInfo)  { -	US_DEBUGP("SWIMS: SWoC Rev: %02d \n", swocInfo->rev); -	US_DEBUGP("SWIMS: Linux SKU: %04X \n", swocInfo->LinuxSKU); -	US_DEBUGP("SWIMS: Linux Version: %04X \n", swocInfo->LinuxVer); +	dev_dbg(dev, "SWIMS: SWoC Rev: %02d\n", swocInfo->rev); +	dev_dbg(dev, "SWIMS: Linux SKU: %04X\n", swocInfo->LinuxSKU); +	dev_dbg(dev, "SWIMS: Linux Version: %04X\n", swocInfo->LinuxVer);  } @@ -101,18 +101,17 @@ static ssize_t show_truinst(struct device *dev, struct device_attribute *attr,  	} else {  		swocInfo = kmalloc(sizeof(struct swoc_info), GFP_KERNEL);  		if (!swocInfo) { -			US_DEBUGP("SWIMS: Allocation failure\n");  			snprintf(buf, PAGE_SIZE, "Error\n");  			return -ENOMEM;  		}  		result = sierra_get_swoc_info(udev, swocInfo);  		if (result < 0) { -			US_DEBUGP("SWIMS: failed SWoC query\n"); +			dev_dbg(dev, "SWIMS: failed SWoC query\n");  			kfree(swocInfo);  			snprintf(buf, PAGE_SIZE, "Error\n");  			return -EIO;  		} -		debug_swoc(swocInfo); +		debug_swoc(dev, swocInfo);  		result = snprintf(buf, PAGE_SIZE,  			"REV=%02d SKU=%04X VER=%04X\n",  			swocInfo->rev, @@ -138,61 +137,55 @@ int sierra_ms_init(struct us_data *us)  	sh = us_to_host(us);  	scsi_get_host_dev(sh); -	US_DEBUGP("SWIMS: sierra_ms_init called\n"); -  	/* Force Modem mode */  	if (swi_tru_install == TRU_FORCE_MODEM) { -		US_DEBUGP("SWIMS: %s", "Forcing Modem Mode\n"); +		usb_stor_dbg(us, "SWIMS: Forcing Modem Mode\n");  		result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem);  		if (result < 0) -			US_DEBUGP("SWIMS: Failed to switch to modem mode.\n"); +			usb_stor_dbg(us, "SWIMS: Failed to switch to modem mode\n");  		return -EIO;  	}  	/* Force Mass Storage mode (keep CD-Rom) */  	else if (swi_tru_install == TRU_FORCE_MS) { -		US_DEBUGP("SWIMS: %s", "Forcing Mass Storage Mode\n"); +		usb_stor_dbg(us, "SWIMS: Forcing Mass Storage Mode\n");  		goto complete;  	}  	/* Normal TRU-Install Logic */  	else { -		US_DEBUGP("SWIMS: %s", "Normal SWoC Logic\n"); +		usb_stor_dbg(us, "SWIMS: Normal SWoC Logic\n");  		swocInfo = kmalloc(sizeof(struct swoc_info),  				GFP_KERNEL); -		if (!swocInfo) { -			US_DEBUGP("SWIMS: %s", "Allocation failure\n"); +		if (!swocInfo)  			return -ENOMEM; -		}  		retries = 3;  		do {  			retries--;  			result = sierra_get_swoc_info(udev, swocInfo);  			if (result < 0) { -				US_DEBUGP("SWIMS: %s", "Failed SWoC query\n"); +				usb_stor_dbg(us, "SWIMS: Failed SWoC query\n");  				schedule_timeout_uninterruptible(2*HZ);  			}  		} while (retries && result < 0);  		if (result < 0) { -			US_DEBUGP("SWIMS: %s", -				  "Completely failed SWoC query\n"); +			usb_stor_dbg(us, "SWIMS: Completely failed SWoC query\n");  			kfree(swocInfo);  			return -EIO;  		} -		debug_swoc(swocInfo); +		debug_swoc(&us->pusb_dev->dev, swocInfo);  		/* If there is not Linux software on the TRU-Install device  		 * then switch to modem mode  		 */  		if (!containsFullLinuxPackage(swocInfo)) { -			US_DEBUGP("SWIMS: %s", -				"Switching to Modem Mode\n"); +			usb_stor_dbg(us, "SWIMS: Switching to Modem Mode\n");  			result = sierra_set_ms_mode(udev,  				SWIMS_SET_MODE_Modem);  			if (result < 0) -				US_DEBUGP("SWIMS: Failed to switch modem\n"); +				usb_stor_dbg(us, "SWIMS: Failed to switch modem\n");  			kfree(swocInfo);  			return -EIO;  		} diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index c0543c83923..22c7d4360fa 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -166,7 +166,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)  		/* cancel the URB, if it hasn't been cancelled already */  		if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) { -			US_DEBUGP("-- cancelling URB\n"); +			usb_stor_dbg(us, "-- cancelling URB\n");  			usb_unlink_urb(us->current_urb);  		}  	} @@ -178,8 +178,8 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)  	clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags);  	if (timeleft <= 0) { -		US_DEBUGP("%s -- cancelling URB\n", -			  timeleft == 0 ? "Timeout" : "Signal"); +		usb_stor_dbg(us, "%s -- cancelling URB\n", +			     timeleft == 0 ? "Timeout" : "Signal");  		usb_kill_urb(us->current_urb);  	} @@ -197,9 +197,8 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,  {  	int status; -	US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n", -			__func__, request, requesttype, -			value, index, size); +	usb_stor_dbg(us, "rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n", +		     request, requesttype, value, index, size);  	/* fill in the devrequest structure */  	us->cr->bRequestType = requesttype; @@ -249,7 +248,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)  	if (result >= 0)  		usb_reset_endpoint(us->pusb_dev, endp); -	US_DEBUGP("%s: result = %d\n", __func__, result); +	usb_stor_dbg(us, "result = %d\n", result);  	return result;  }  EXPORT_SYMBOL_GPL(usb_stor_clear_halt); @@ -265,18 +264,18 @@ EXPORT_SYMBOL_GPL(usb_stor_clear_halt);  static int interpret_urb_result(struct us_data *us, unsigned int pipe,  		unsigned int length, int result, unsigned int partial)  { -	US_DEBUGP("Status code %d; transferred %u/%u\n", -			result, partial, length); +	usb_stor_dbg(us, "Status code %d; transferred %u/%u\n", +		     result, partial, length);  	switch (result) {  	/* no error code; did we send all the data? */  	case 0:  		if (partial != length) { -			US_DEBUGP("-- short transfer\n"); +			usb_stor_dbg(us, "-- short transfer\n");  			return USB_STOR_XFER_SHORT;  		} -		US_DEBUGP("-- transfer complete\n"); +		usb_stor_dbg(us, "-- transfer complete\n");  		return USB_STOR_XFER_GOOD;  	/* stalled */ @@ -284,39 +283,40 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe,  		/* for control endpoints, (used by CB[I]) a stall indicates  		 * a failed command */  		if (usb_pipecontrol(pipe)) { -			US_DEBUGP("-- stall on control pipe\n"); +			usb_stor_dbg(us, "-- stall on control pipe\n");  			return USB_STOR_XFER_STALLED;  		}  		/* for other sorts of endpoint, clear the stall */ -		US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); +		usb_stor_dbg(us, "clearing endpoint halt for pipe 0x%x\n", +			     pipe);  		if (usb_stor_clear_halt(us, pipe) < 0)  			return USB_STOR_XFER_ERROR;  		return USB_STOR_XFER_STALLED;  	/* babble - the device tried to send more than we wanted to read */  	case -EOVERFLOW: -		US_DEBUGP("-- babble\n"); +		usb_stor_dbg(us, "-- babble\n");  		return USB_STOR_XFER_LONG;  	/* the transfer was cancelled by abort, disconnect, or timeout */  	case -ECONNRESET: -		US_DEBUGP("-- transfer cancelled\n"); +		usb_stor_dbg(us, "-- transfer cancelled\n");  		return USB_STOR_XFER_ERROR;  	/* short scatter-gather read transfer */  	case -EREMOTEIO: -		US_DEBUGP("-- short read transfer\n"); +		usb_stor_dbg(us, "-- short read transfer\n");  		return USB_STOR_XFER_SHORT;  	/* abort or disconnect in progress */  	case -EIO: -		US_DEBUGP("-- abort or disconnect in progress\n"); +		usb_stor_dbg(us, "-- abort or disconnect in progress\n");  		return USB_STOR_XFER_ERROR;  	/* the catch-all error case */  	default: -		US_DEBUGP("-- unknown error\n"); +		usb_stor_dbg(us, "-- unknown error\n");  		return USB_STOR_XFER_ERROR;  	}  } @@ -331,9 +331,8 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,  {  	int result; -	US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n", -			__func__, request, requesttype, -			value, index, size); +	usb_stor_dbg(us, "rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n", +		     request, requesttype, value, index, size);  	/* fill in the devrequest structure */  	us->cr->bRequestType = requesttype; @@ -367,7 +366,7 @@ static int usb_stor_intr_transfer(struct us_data *us, void *buf,  	unsigned int pipe = us->recv_intr_pipe;  	unsigned int maxp; -	US_DEBUGP("%s: xfer %u bytes\n", __func__, length); +	usb_stor_dbg(us, "xfer %u bytes\n", length);  	/* calculate the max packet size */  	maxp = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe)); @@ -394,7 +393,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,  {  	int result; -	US_DEBUGP("%s: xfer %u bytes\n", __func__, length); +	usb_stor_dbg(us, "xfer %u bytes\n", length);  	/* fill and submit the URB */  	usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length, @@ -426,12 +425,11 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,  		return USB_STOR_XFER_ERROR;  	/* initialize the scatter-gather request block */ -	US_DEBUGP("%s: xfer %u bytes, %d entries\n", __func__, -			length, num_sg); +	usb_stor_dbg(us, "xfer %u bytes, %d entries\n", length, num_sg);  	result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,  			sg, num_sg, length, GFP_NOIO);  	if (result) { -		US_DEBUGP("usb_sg_init returned %d\n", result); +		usb_stor_dbg(us, "usb_sg_init returned %d\n", result);  		return USB_STOR_XFER_ERROR;  	} @@ -444,7 +442,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,  		/* cancel the request, if it hasn't been cancelled already */  		if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) { -			US_DEBUGP("-- cancelling sg request\n"); +			usb_stor_dbg(us, "-- cancelling sg request\n");  			usb_sg_cancel(&us->current_sg);  		}  	} @@ -609,14 +607,14 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)  	 * short-circuit all other processing  	 */  	if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { -		US_DEBUGP("-- command was aborted\n"); +		usb_stor_dbg(us, "-- command was aborted\n");  		srb->result = DID_ABORT << 16;  		goto Handle_Errors;  	}  	/* if there is a transport error, reset and don't auto-sense */  	if (result == USB_STOR_TRANSPORT_ERROR) { -		US_DEBUGP("-- transport indicates error, resetting\n"); +		usb_stor_dbg(us, "-- transport indicates error, resetting\n");  		srb->result = DID_ERROR << 16;  		goto Handle_Errors;  	} @@ -645,7 +643,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)  	 */  	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"); +		usb_stor_dbg(us, "-- CB transport device requiring auto-sense\n");  		need_auto_sense = 1;  	} @@ -655,7 +653,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)  	 * "failure" and an "error" in the transport mechanism.  	 */  	if (result == USB_STOR_TRANSPORT_FAILED) { -		US_DEBUGP("-- transport indicates command failure\n"); +		usb_stor_dbg(us, "-- transport indicates command failure\n");  		need_auto_sense = 1;  	} @@ -670,7 +668,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)  	    !(us->fflags & US_FL_SANE_SENSE) &&  	    !(us->fflags & US_FL_BAD_SENSE) &&  	    !(srb->cmnd[2] & 0x20))) { -		US_DEBUGP("-- SAT supported, increasing auto-sense\n"); +		usb_stor_dbg(us, "-- SAT supported, increasing auto-sense\n");  		us->fflags |= US_FL_SANE_SENSE;  	} @@ -684,7 +682,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)  	      (srb->cmnd[0] == MODE_SENSE) ||  	      (srb->cmnd[0] == LOG_SENSE) ||  	      (srb->cmnd[0] == MODE_SENSE_10))) { -		US_DEBUGP("-- unexpectedly short transfer\n"); +		usb_stor_dbg(us, "-- unexpectedly short transfer\n");  	}  	/* Now, if we need to do the auto-sense, let's do it */ @@ -700,7 +698,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)  		if (us->fflags & US_FL_SANE_SENSE)  			sense_size = ~0;  Retry_Sense: -		US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); +		usb_stor_dbg(us, "Issuing auto-REQUEST_SENSE\n");  		scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size); @@ -719,7 +717,7 @@ Retry_Sense:  		scsi_eh_restore_cmnd(srb, &ses);  		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { -			US_DEBUGP("-- auto-sense aborted\n"); +			usb_stor_dbg(us, "-- auto-sense aborted\n");  			srb->result = DID_ABORT << 16;  			/* If SANE_SENSE caused this problem, disable it */ @@ -737,7 +735,7 @@ Retry_Sense:  		 */  		if (temp_result == USB_STOR_TRANSPORT_FAILED &&  				sense_size != US_SENSE_SIZE) { -			US_DEBUGP("-- auto-sense failure, retry small sense\n"); +			usb_stor_dbg(us, "-- auto-sense failure, retry small sense\n");  			sense_size = US_SENSE_SIZE;  			us->fflags &= ~US_FL_SANE_SENSE;  			us->fflags |= US_FL_BAD_SENSE; @@ -746,7 +744,7 @@ Retry_Sense:  		/* Other failures */  		if (temp_result != USB_STOR_TRANSPORT_GOOD) { -			US_DEBUGP("-- auto-sense failure\n"); +			usb_stor_dbg(us, "-- auto-sense failure\n");  			/* we skip the reset if this happens to be a  			 * multi-target device, since failure of an @@ -766,27 +764,28 @@ Retry_Sense:  		    !(us->fflags & US_FL_SANE_SENSE) &&  		    !(us->fflags & US_FL_BAD_SENSE) &&  		    (srb->sense_buffer[0] & 0x7C) == 0x70) { -			US_DEBUGP("-- SANE_SENSE support enabled\n"); +			usb_stor_dbg(us, "-- SANE_SENSE support enabled\n");  			us->fflags |= US_FL_SANE_SENSE;  			/* Indicate to the user that we truncated their sense  			 * because we didn't know it supported larger sense.  			 */ -			US_DEBUGP("-- Sense data truncated to %i from %i\n", -			          US_SENSE_SIZE, -			          srb->sense_buffer[7] + 8); +			usb_stor_dbg(us, "-- Sense data truncated to %i from %i\n", +				     US_SENSE_SIZE, +				     srb->sense_buffer[7] + 8);  			srb->sense_buffer[7] = (US_SENSE_SIZE - 8);  		}  		scsi_normalize_sense(srb->sense_buffer, SCSI_SENSE_BUFFERSIZE,  				     &sshdr); -		US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); -		US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", -			  sshdr.response_code, sshdr.sense_key, -			  sshdr.asc, sshdr.ascq); +		usb_stor_dbg(us, "-- Result from auto-sense is %d\n", +			     temp_result); +		usb_stor_dbg(us, "-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", +			     sshdr.response_code, sshdr.sense_key, +			     sshdr.asc, sshdr.ascq);  #ifdef CONFIG_USB_STORAGE_DEBUG -		usb_stor_show_sense(sshdr.sense_key, sshdr.asc, sshdr.ascq); +		usb_stor_show_sense(us, sshdr.sense_key, sshdr.asc, sshdr.ascq);  #endif  		/* set the result so the higher layers expect this data */ @@ -892,20 +891,18 @@ Retry_Sense:  /* Stop the current URB transfer */  void usb_stor_stop_transport(struct us_data *us)  { -	US_DEBUGP("%s called\n", __func__); -  	/* If the state machine is blocked waiting for an URB,  	 * let's wake it up.  The test_and_clear_bit() call  	 * guarantees that if a URB has just been submitted,  	 * it won't be cancelled more than once. */  	if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) { -		US_DEBUGP("-- cancelling URB\n"); +		usb_stor_dbg(us, "-- cancelling URB\n");  		usb_unlink_urb(us->current_urb);  	}  	/* If we are waiting for a scatter-gather operation, cancel it. */  	if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) { -		US_DEBUGP("-- cancelling sg request\n"); +		usb_stor_dbg(us, "-- cancelling sg request\n");  		usb_sg_cancel(&us->current_sg);  	}  } @@ -928,7 +925,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)  				      us->ifnum, srb->cmnd, srb->cmd_len);  	/* check the return code for the command */ -	US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result); +	usb_stor_dbg(us, "Call to usb_stor_ctrl_transfer() returned %d\n", +		     result);  	/* if we stalled the command, it means command failed */  	if (result == USB_STOR_XFER_STALLED) { @@ -946,7 +944,7 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)  		pipe = srb->sc_data_direction == DMA_FROM_DEVICE ?   				us->recv_bulk_pipe : us->send_bulk_pipe;  		result = usb_stor_bulk_srb(us, pipe, srb); -		US_DEBUGP("CBI data stage result is 0x%x\n", result); +		usb_stor_dbg(us, "CBI data stage result is 0x%x\n", result);  		/* if we stalled the data transfer it means command failed */  		if (result == USB_STOR_XFER_STALLED) @@ -964,8 +962,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)  		return USB_STOR_TRANSPORT_GOOD;  	result = usb_stor_intr_transfer(us, us->iobuf, 2); -	US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n",  -			us->iobuf[0], us->iobuf[1]); +	usb_stor_dbg(us, "Got interrupt data (0x%x, 0x%x)\n", +		     us->iobuf[0], us->iobuf[1]);  	if (result != USB_STOR_XFER_GOOD)  		return USB_STOR_TRANSPORT_ERROR; @@ -992,8 +990,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)  	 * into the first byte -- so if it's non-zero, call it a failure.  	 */  	if (us->iobuf[0]) { -		US_DEBUGP("CBI IRQ data showed reserved bType 0x%x\n", -				us->iobuf[0]); +		usb_stor_dbg(us, "CBI IRQ data showed reserved bType 0x%x\n", +			     us->iobuf[0]);  		goto Failed;  	} @@ -1034,8 +1032,8 @@ int usb_stor_Bulk_max_lun(struct us_data *us)  				 USB_RECIP_INTERFACE,  				 0, us->ifnum, us->iobuf, 1, 10*HZ); -	US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",  -		  result, us->iobuf[0]); +	usb_stor_dbg(us, "GetMaxLUN command result is %d, data is %d\n", +		     result, us->iobuf[0]);  	/* if we have a successful request, return the result */  	if (result > 0) @@ -1084,14 +1082,14 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)  	memcpy(bcb->CDB, srb->cmnd, bcb->Length);  	/* send it to out endpoint */ -	US_DEBUGP("Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n", -			le32_to_cpu(bcb->Signature), bcb->Tag, -			le32_to_cpu(bcb->DataTransferLength), bcb->Flags, -			(bcb->Lun >> 4), (bcb->Lun & 0x0F),  -			bcb->Length); +	usb_stor_dbg(us, "Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n", +		     le32_to_cpu(bcb->Signature), bcb->Tag, +		     le32_to_cpu(bcb->DataTransferLength), bcb->Flags, +		     (bcb->Lun >> 4), (bcb->Lun & 0x0F), +		     bcb->Length);  	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,  				bcb, cbwlen, NULL); -	US_DEBUGP("Bulk command transfer result=%d\n", result); +	usb_stor_dbg(us, "Bulk command transfer result=%d\n", result);  	if (result != USB_STOR_XFER_GOOD)  		return USB_STOR_TRANSPORT_ERROR; @@ -1108,7 +1106,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)  		unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ?   				us->recv_bulk_pipe : us->send_bulk_pipe;  		result = usb_stor_bulk_srb(us, pipe, srb); -		US_DEBUGP("Bulk data transfer result 0x%x\n", result); +		usb_stor_dbg(us, "Bulk data transfer result 0x%x\n", result);  		if (result == USB_STOR_XFER_ERROR)  			return USB_STOR_TRANSPORT_ERROR; @@ -1127,7 +1125,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)  	 */  	/* get CSW for device status */ -	US_DEBUGP("Attempting to get CSW...\n"); +	usb_stor_dbg(us, "Attempting to get CSW...\n");  	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,  				bcs, US_BULK_CS_WRAP_LEN, &cswlen); @@ -1136,7 +1134,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)  	 * CSWs.  If we encounter such a thing, try to read the CSW again.  	 */  	if (result == USB_STOR_XFER_SHORT && cswlen == 0) { -		US_DEBUGP("Received 0-length CSW; retrying...\n"); +		usb_stor_dbg(us, "Received 0-length CSW; retrying...\n");  		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,  				bcs, US_BULK_CS_WRAP_LEN, &cswlen);  	} @@ -1145,24 +1143,24 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)  	if (result == USB_STOR_XFER_STALLED) {  		/* get the status again */ -		US_DEBUGP("Attempting to get CSW (2nd try)...\n"); +		usb_stor_dbg(us, "Attempting to get CSW (2nd try)...\n");  		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,  				bcs, US_BULK_CS_WRAP_LEN, NULL);  	}  	/* if we still have a failure at this point, we're in trouble */ -	US_DEBUGP("Bulk status result = %d\n", result); +	usb_stor_dbg(us, "Bulk status result = %d\n", result);  	if (result != USB_STOR_XFER_GOOD)  		return USB_STOR_TRANSPORT_ERROR;  	/* check bulk status */  	residue = le32_to_cpu(bcs->Residue); -	US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", -			le32_to_cpu(bcs->Signature), bcs->Tag,  -			residue, bcs->Status); +	usb_stor_dbg(us, "Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", +		     le32_to_cpu(bcs->Signature), bcs->Tag, +		     residue, bcs->Status);  	if (!(bcs->Tag == us->tag || (us->fflags & US_FL_BULK_IGNORE_TAG)) ||  		bcs->Status > US_BULK_STAT_PHASE) { -		US_DEBUGP("Bulk logical error\n"); +		usb_stor_dbg(us, "Bulk logical error\n");  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -1173,12 +1171,12 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)  	if (!us->bcs_signature) {  		us->bcs_signature = bcs->Signature;  		if (us->bcs_signature != cpu_to_le32(US_BULK_CS_SIGN)) -			US_DEBUGP("Learnt BCS signature 0x%08X\n", -					le32_to_cpu(us->bcs_signature)); +			usb_stor_dbg(us, "Learnt BCS signature 0x%08X\n", +				     le32_to_cpu(us->bcs_signature));  	} else if (bcs->Signature != us->bcs_signature) { -		US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n", -			  le32_to_cpu(bcs->Signature), -			  le32_to_cpu(us->bcs_signature)); +		usb_stor_dbg(us, "Signature mismatch: got %08X, expecting %08X\n", +			     le32_to_cpu(bcs->Signature), +			     le32_to_cpu(us->bcs_signature));  		return USB_STOR_TRANSPORT_ERROR;  	} @@ -1255,7 +1253,7 @@ static int usb_stor_reset_common(struct us_data *us,  	int result2;  	if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { -		US_DEBUGP("No reset during disconnect\n"); +		usb_stor_dbg(us, "No reset during disconnect\n");  		return -EIO;  	} @@ -1263,7 +1261,7 @@ static int usb_stor_reset_common(struct us_data *us,  			request, requesttype, value, index, data, size,  			5*HZ);  	if (result < 0) { -		US_DEBUGP("Soft reset failed: %d\n", result); +		usb_stor_dbg(us, "Soft reset failed: %d\n", result);  		return result;  	} @@ -1273,23 +1271,23 @@ static int usb_stor_reset_common(struct us_data *us,  			test_bit(US_FLIDX_DISCONNECTING, &us->dflags),  			HZ*6);  	if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { -		US_DEBUGP("Reset interrupted by disconnect\n"); +		usb_stor_dbg(us, "Reset interrupted by disconnect\n");  		return -EIO;  	} -	US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n"); +	usb_stor_dbg(us, "Soft reset: clearing bulk-in endpoint halt\n");  	result = usb_stor_clear_halt(us, us->recv_bulk_pipe); -	US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n"); +	usb_stor_dbg(us, "Soft reset: clearing bulk-out endpoint halt\n");  	result2 = usb_stor_clear_halt(us, us->send_bulk_pipe);  	/* return a result code based on the result of the clear-halts */  	if (result >= 0)  		result = result2;  	if (result < 0) -		US_DEBUGP("Soft reset failed\n"); +		usb_stor_dbg(us, "Soft reset failed\n");  	else -		US_DEBUGP("Soft reset done\n"); +		usb_stor_dbg(us, "Soft reset done\n");  	return result;  } @@ -1299,8 +1297,6 @@ static int usb_stor_reset_common(struct us_data *us,  int usb_stor_CB_reset(struct us_data *us)  { -	US_DEBUGP("%s called\n", __func__); -  	memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE);  	us->iobuf[0] = SEND_DIAGNOSTIC;  	us->iobuf[1] = 4; @@ -1315,8 +1311,6 @@ EXPORT_SYMBOL_GPL(usb_stor_CB_reset);   */  int usb_stor_Bulk_reset(struct us_data *us)  { -	US_DEBUGP("%s called\n", __func__); -  	return usb_stor_reset_common(us, US_BULK_RESET_REQUEST,   				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,  				 0, us->ifnum, NULL, 0); @@ -1336,16 +1330,17 @@ int usb_stor_port_reset(struct us_data *us)  	result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);  	if (result < 0) -		US_DEBUGP("unable to lock device for reset: %d\n", result); +		usb_stor_dbg(us, "unable to lock device for reset: %d\n", +			     result);  	else {  		/* Were we disconnected while waiting for the lock? */  		if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {  			result = -EIO; -			US_DEBUGP("No reset during disconnect\n"); +			usb_stor_dbg(us, "No reset during disconnect\n");  		} else {  			result = usb_reset_device(us->pusb_dev); -			US_DEBUGP("usb_reset_device returns %d\n", -					result); +			usb_stor_dbg(us, "usb_reset_device returns %d\n", +				     result);  		}  		usb_unlock_device(us->pusb_dev);  	} diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index da04a074e79..1799335288b 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -496,6 +496,13 @@ UNUSUAL_DEV(  0x04e8, 0x5122, 0x0000, 0x9999,  		USB_SC_DEVICE, USB_PR_DEVICE, NULL,  		US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG), +/* Added by Dmitry Artamonow <mad_soft@inbox.ru> */ +UNUSUAL_DEV(  0x04e8, 0x5136, 0x0000, 0x9999, +		"Samsung", +		"YP-Z3", +		USB_SC_DEVICE, USB_PR_DEVICE, NULL, +		US_FL_MAX_SECTORS_64), +  /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.   * Device uses standards-violating 32-byte Bulk Command Block Wrappers and   * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011. diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index d6bee407af0..5c4fe0749af 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -183,7 +183,6 @@ int usb_stor_suspend(struct usb_interface *iface, pm_message_t message)  	/* Wait until no command is running */  	mutex_lock(&us->dev_mutex); -	US_DEBUGP("%s\n", __func__);  	if (us->suspend_resume_hook)  		(us->suspend_resume_hook)(us, US_SUSPEND); @@ -201,7 +200,6 @@ int usb_stor_resume(struct usb_interface *iface)  	mutex_lock(&us->dev_mutex); -	US_DEBUGP("%s\n", __func__);  	if (us->suspend_resume_hook)  		(us->suspend_resume_hook)(us, US_RESUME); @@ -214,8 +212,6 @@ int usb_stor_reset_resume(struct usb_interface *iface)  {  	struct us_data *us = usb_get_intfdata(iface); -	US_DEBUGP("%s\n", __func__); -  	/* Report the reset to the SCSI core */  	usb_stor_report_bus_reset(us); @@ -236,8 +232,6 @@ int usb_stor_pre_reset(struct usb_interface *iface)  {  	struct us_data *us = usb_get_intfdata(iface); -	US_DEBUGP("%s\n", __func__); -  	/* Make sure no command runs during the reset */  	mutex_lock(&us->dev_mutex);  	return 0; @@ -248,8 +242,6 @@ int usb_stor_post_reset(struct usb_interface *iface)  {  	struct us_data *us = usb_get_intfdata(iface); -	US_DEBUGP("%s\n", __func__); -  	/* Report the reset to the SCSI core */  	usb_stor_report_bus_reset(us); @@ -311,11 +303,11 @@ static int usb_stor_control_thread(void * __us)  	struct Scsi_Host *host = us_to_host(us);  	for (;;) { -		US_DEBUGP("*** thread sleeping.\n"); +		usb_stor_dbg(us, "*** thread sleeping\n");  		if (wait_for_completion_interruptible(&us->cmnd_ready))  			break; -		US_DEBUGP("*** thread awakened.\n"); +		usb_stor_dbg(us, "*** thread awakened\n");  		/* lock the device pointers */  		mutex_lock(&(us->dev_mutex)); @@ -327,7 +319,7 @@ static int usb_stor_control_thread(void * __us)  		if (us->srb == NULL) {  			scsi_unlock(host);  			mutex_unlock(&us->dev_mutex); -			US_DEBUGP("-- exiting\n"); +			usb_stor_dbg(us, "-- exiting\n");  			break;  		} @@ -343,7 +335,7 @@ static int usb_stor_control_thread(void * __us)  		 * is UNKNOWN  		 */  		if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) { -			US_DEBUGP("UNKNOWN data direction\n"); +			usb_stor_dbg(us, "UNKNOWN data direction\n");  			us->srb->result = DID_ERROR << 16;  		} @@ -352,14 +344,14 @@ static int usb_stor_control_thread(void * __us)  		 */  		else if (us->srb->device->id &&  				!(us->fflags & US_FL_SCM_MULT_TARG)) { -			US_DEBUGP("Bad target number (%d:%d)\n", -				  us->srb->device->id, us->srb->device->lun); +			usb_stor_dbg(us, "Bad target number (%d:%d)\n", +				     us->srb->device->id, us->srb->device->lun);  			us->srb->result = DID_BAD_TARGET << 16;  		}  		else if (us->srb->device->lun > us->max_lun) { -			US_DEBUGP("Bad LUN (%d:%d)\n", -				  us->srb->device->id, us->srb->device->lun); +			usb_stor_dbg(us, "Bad LUN (%d:%d)\n", +				     us->srb->device->id, us->srb->device->lun);  			us->srb->result = DID_BAD_TARGET << 16;  		} @@ -371,14 +363,14 @@ static int usb_stor_control_thread(void * __us)  			    0x00, 0x80, 0x02, 0x02,  			    0x1F, 0x00, 0x00, 0x00}; -			US_DEBUGP("Faking INQUIRY command\n"); +			usb_stor_dbg(us, "Faking INQUIRY command\n");  			fill_inquiry_response(us, data_ptr, 36);  			us->srb->result = SAM_STAT_GOOD;  		}  		/* we've got a command, let's do it! */  		else { -			US_DEBUG(usb_stor_show_command(us->srb)); +			US_DEBUG(usb_stor_show_command(us, us->srb));  			us->proto_handler(us->srb, us);  			usb_mark_last_busy(us->pusb_dev);  		} @@ -388,12 +380,12 @@ static int usb_stor_control_thread(void * __us)  		/* indicate that the command is done */  		if (us->srb->result != DID_ABORT << 16) { -			US_DEBUGP("scsi cmd done, result=0x%x\n", -				   us->srb->result); +			usb_stor_dbg(us, "scsi cmd done, result=0x%x\n", +				     us->srb->result);  			us->srb->scsi_done(us->srb);  		} else {  SkipForAbort: -			US_DEBUGP("scsi command aborted\n"); +			usb_stor_dbg(us, "scsi command aborted\n");  		}  		/* If an abort request was received we need to signal that @@ -435,34 +427,30 @@ SkipForAbort:  /* Associate our private data with the USB device */  static int associate_dev(struct us_data *us, struct usb_interface *intf)  { -	US_DEBUGP("-- %s\n", __func__); -  	/* Fill in the device-related fields */  	us->pusb_dev = interface_to_usbdev(intf);  	us->pusb_intf = intf;  	us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; -	US_DEBUGP("Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n", -			le16_to_cpu(us->pusb_dev->descriptor.idVendor), -			le16_to_cpu(us->pusb_dev->descriptor.idProduct), -			le16_to_cpu(us->pusb_dev->descriptor.bcdDevice)); -	US_DEBUGP("Interface Subclass: 0x%02x, Protocol: 0x%02x\n", -			intf->cur_altsetting->desc.bInterfaceSubClass, -			intf->cur_altsetting->desc.bInterfaceProtocol); +	usb_stor_dbg(us, "Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n", +		     le16_to_cpu(us->pusb_dev->descriptor.idVendor), +		     le16_to_cpu(us->pusb_dev->descriptor.idProduct), +		     le16_to_cpu(us->pusb_dev->descriptor.bcdDevice)); +	usb_stor_dbg(us, "Interface Subclass: 0x%02x, Protocol: 0x%02x\n", +		     intf->cur_altsetting->desc.bInterfaceSubClass, +		     intf->cur_altsetting->desc.bInterfaceProtocol);  	/* Store our private data in the interface */  	usb_set_intfdata(intf, us);  	/* Allocate the control/setup and DMA-mapped buffers */  	us->cr = kmalloc(sizeof(*us->cr), GFP_KERNEL); -	if (!us->cr) { -		US_DEBUGP("usb_ctrlrequest allocation failed\n"); +	if (!us->cr)  		return -ENOMEM; -	}  	us->iobuf = usb_alloc_coherent(us->pusb_dev, US_IOBUF_SIZE,  			GFP_KERNEL, &us->iobuf_dma);  	if (!us->iobuf) { -		US_DEBUGP("I/O buffer allocation failed\n"); +		usb_stor_dbg(us, "I/O buffer allocation failed\n");  		return -ENOMEM;  	}  	return 0; @@ -738,7 +726,7 @@ static int get_pipes(struct us_data *us)  	}  	if (!ep_in || !ep_out || (us->protocol == USB_PR_CBI && !ep_int)) { -		US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n"); +		usb_stor_dbg(us, "Endpoint sanity check failed! Rejecting dev.\n");  		return -EIO;  	} @@ -765,7 +753,7 @@ static int usb_stor_acquire_resources(struct us_data *us)  	us->current_urb = usb_alloc_urb(0, GFP_KERNEL);  	if (!us->current_urb) { -		US_DEBUGP("URB allocation failed\n"); +		usb_stor_dbg(us, "URB allocation failed\n");  		return -ENOMEM;  	} @@ -792,20 +780,18 @@ static int usb_stor_acquire_resources(struct us_data *us)  /* Release all our dynamic resources */  static void usb_stor_release_resources(struct us_data *us)  { -	US_DEBUGP("-- %s\n", __func__); -  	/* Tell the control thread to exit.  The SCSI host must  	 * already have been removed and the DISCONNECTING flag set  	 * so that we won't accept any more commands.  	 */ -	US_DEBUGP("-- sending exit command to thread\n"); +	usb_stor_dbg(us, "-- sending exit command to thread\n");  	complete(&us->cmnd_ready);  	if (us->ctl_thread)  		kthread_stop(us->ctl_thread);  	/* Call the destructor routine, if it exists */  	if (us->extra_destructor) { -		US_DEBUGP("-- calling extra_destructor()\n"); +		usb_stor_dbg(us, "-- calling extra_destructor()\n");  		us->extra_destructor(us->extra);  	} @@ -817,8 +803,6 @@ static void usb_stor_release_resources(struct us_data *us)  /* Dissociate from the USB device */  static void dissociate_dev(struct us_data *us)  { -	US_DEBUGP("-- %s\n", __func__); -  	/* Free the buffers */  	kfree(us->cr);  	usb_free_coherent(us->pusb_dev, US_IOBUF_SIZE, us->iobuf, us->iobuf_dma); @@ -918,7 +902,7 @@ int usb_stor_probe1(struct us_data **pus,  	struct us_data *us;  	int result; -	US_DEBUGP("USB Mass Storage device detected\n"); +	dev_info(&intf->dev, "USB Mass Storage device detected\n");  	/*  	 * Ask the SCSI layer to allocate a host structure, with extra @@ -926,8 +910,7 @@ int usb_stor_probe1(struct us_data **pus,  	 */  	host = scsi_host_alloc(&usb_stor_host_template, sizeof(*us));  	if (!host) { -		dev_warn(&intf->dev, -				"Unable to allocate the scsi host\n"); +		dev_warn(&intf->dev, "Unable to allocate the scsi host\n");  		return -ENOMEM;  	} @@ -964,7 +947,7 @@ int usb_stor_probe1(struct us_data **pus,  	return 0;  BadDevice: -	US_DEBUGP("storage_probe() failed\n"); +	usb_stor_dbg(us, "storage_probe() failed\n");  	release_everything(us);  	return result;  } @@ -981,8 +964,8 @@ int usb_stor_probe2(struct us_data *us)  		result = -ENXIO;  		goto BadDevice;  	} -	US_DEBUGP("Transport: %s\n", us->transport_name); -	US_DEBUGP("Protocol: %s\n", us->protocol_name); +	usb_stor_dbg(us, "Transport: %s\n", us->transport_name); +	usb_stor_dbg(us, "Protocol: %s\n", us->protocol_name);  	/* fix for single-lun devices */  	if (us->fflags & US_FL_SINGLE_LUN) @@ -1028,7 +1011,7 @@ int usb_stor_probe2(struct us_data *us)  	/* We come here if there are any problems */  BadDevice: -	US_DEBUGP("storage_probe() failed\n"); +	usb_stor_dbg(us, "storage_probe() failed\n");  	release_everything(us);  	return result;  } @@ -1039,7 +1022,6 @@ void usb_stor_disconnect(struct usb_interface *intf)  {  	struct us_data *us = usb_get_intfdata(intf); -	US_DEBUGP("storage_disconnect() called\n");  	quiesce_and_remove_host(us);  	release_everything(us);  } @@ -1075,8 +1057,7 @@ static int storage_probe(struct usb_interface *intf,  	} else {  		unusual_dev = &for_dynamic_ids; -		US_DEBUGP("%s %s 0x%04x 0x%04x\n", "Use Bulk-Only transport", -			"with the Transparent SCSI protocol for dynamic id:", +		dev_dbg(&intf->dev, "Use Bulk-Only transport with the Transparent SCSI protocol for dynamic id: 0x%04x 0x%04x\n",  			id->idVendor, id->idProduct);  	} @@ -1090,10 +1071,6 @@ static int storage_probe(struct usb_interface *intf,  	return result;  } -/*********************************************************************** - * Initialization and registration - ***********************************************************************/ -  static struct usb_driver usb_storage_driver = {  	.name =		"usb-storage",  	.probe =	storage_probe, @@ -1108,30 +1085,4 @@ static struct usb_driver usb_storage_driver = {  	.soft_unbind =	1,  }; -static int __init usb_stor_init(void) -{ -	int retval; - -	pr_info("Initializing USB Mass Storage driver...\n"); - -	/* register the driver, return usb_register return code if error */ -	retval = usb_register(&usb_storage_driver); -	if (retval == 0) -		pr_info("USB Mass Storage support registered.\n"); -	return retval; -} - -static void __exit usb_stor_exit(void) -{ -	US_DEBUGP("usb_stor_exit() called\n"); - -	/* Deregister the driver -	 * This will cause disconnect() to be called for each -	 * attached unit -	 */ -	US_DEBUGP("-- calling usb_deregister()\n"); -	usb_deregister(&usb_storage_driver) ; -} - -module_init(usb_stor_init); -module_exit(usb_stor_exit); +module_usb_driver(usb_storage_driver); diff --git a/drivers/usb/usb-common.c b/drivers/usb/usb-common.c index d29503e954a..0db0a919d72 100644 --- a/drivers/usb/usb-common.c +++ b/drivers/usb/usb-common.c @@ -14,6 +14,32 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/usb/ch9.h> +#include <linux/usb/otg.h> + +const char *usb_otg_state_string(enum usb_otg_state state) +{ +	static const char *const names[] = { +		[OTG_STATE_A_IDLE] = "a_idle", +		[OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise", +		[OTG_STATE_A_WAIT_BCON] = "a_wait_bcon", +		[OTG_STATE_A_HOST] = "a_host", +		[OTG_STATE_A_SUSPEND] = "a_suspend", +		[OTG_STATE_A_PERIPHERAL] = "a_peripheral", +		[OTG_STATE_A_WAIT_VFALL] = "a_wait_vfall", +		[OTG_STATE_A_VBUS_ERR] = "a_vbus_err", +		[OTG_STATE_B_IDLE] = "b_idle", +		[OTG_STATE_B_SRP_INIT] = "b_srp_init", +		[OTG_STATE_B_PERIPHERAL] = "b_peripheral", +		[OTG_STATE_B_WAIT_ACON] = "b_wait_acon", +		[OTG_STATE_B_HOST] = "b_host", +	}; + +	if (state < 0 || state >= ARRAY_SIZE(names)) +		return "UNDEFINED"; + +	return names[state]; +} +EXPORT_SYMBOL_GPL(usb_otg_state_string);  const char *usb_speed_string(enum usb_device_speed speed)  { @@ -32,4 +58,25 @@ const char *usb_speed_string(enum usb_device_speed speed)  }  EXPORT_SYMBOL_GPL(usb_speed_string); +const char *usb_state_string(enum usb_device_state state) +{ +	static const char *const names[] = { +		[USB_STATE_NOTATTACHED] = "not attached", +		[USB_STATE_ATTACHED] = "attached", +		[USB_STATE_POWERED] = "powered", +		[USB_STATE_RECONNECTING] = "reconnecting", +		[USB_STATE_UNAUTHENTICATED] = "unauthenticated", +		[USB_STATE_DEFAULT] = "default", +		[USB_STATE_ADDRESS] = "addresssed", +		[USB_STATE_CONFIGURED] = "configured", +		[USB_STATE_SUSPENDED] = "suspended", +	}; + +	if (state < 0 || state >= ARRAY_SIZE(names)) +		return "UNKNOWN"; + +	return names[state]; +} +EXPORT_SYMBOL_GPL(usb_state_string); +  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index ce310170829..7ed3b039dbe 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -61,11 +61,10 @@ struct usb_skel {  	__u8			bulk_out_endpointAddr;	/* the address of the bulk out endpoint */  	int			errors;			/* the last request tanked */  	bool			ongoing_read;		/* a read is going on */ -	bool			processed_urb;		/* indicates we haven't processed the urb */  	spinlock_t		err_lock;		/* lock for errors */  	struct kref		kref;  	struct mutex		io_mutex;		/* synchronize I/O with disconnect */ -	struct completion	bulk_in_completion;	/* to wait for an ongoing read */ +	wait_queue_head_t	bulk_in_wait;		/* to wait for an ongoing read */  };  #define to_skel_dev(d) container_of(d, struct usb_skel, kref) @@ -185,7 +184,7 @@ static void skel_read_bulk_callback(struct urb *urb)  	dev->ongoing_read = 0;  	spin_unlock(&dev->err_lock); -	complete(&dev->bulk_in_completion); +	wake_up_interruptible(&dev->bulk_in_wait);  }  static int skel_do_read_io(struct usb_skel *dev, size_t count) @@ -206,13 +205,16 @@ static int skel_do_read_io(struct usb_skel *dev, size_t count)  	dev->ongoing_read = 1;  	spin_unlock_irq(&dev->err_lock); +	/* submit bulk in urb, which means no data to deliver */ +	dev->bulk_in_filled = 0; +	dev->bulk_in_copied = 0; +  	/* do it */  	rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL);  	if (rv < 0) {  		dev_err(&dev->interface->dev,  			"%s - failed submitting read urb, error %d\n",  			__func__, rv); -		dev->bulk_in_filled = 0;  		rv = (rv == -ENOMEM) ? rv : -EIO;  		spin_lock_irq(&dev->err_lock);  		dev->ongoing_read = 0; @@ -261,25 +263,9 @@ retry:  		 * IO may take forever  		 * hence wait in an interruptible state  		 */ -		rv = wait_for_completion_interruptible(&dev->bulk_in_completion); +		rv = wait_event_interruptible(dev->bulk_in_wait, (!dev->ongoing_read));  		if (rv < 0)  			goto exit; -		/* -		 * by waiting we also semiprocessed the urb -		 * we must finish now -		 */ -		dev->bulk_in_copied = 0; -		dev->processed_urb = 1; -	} - -	if (!dev->processed_urb) { -		/* -		 * the URB hasn't been processed -		 * do it now -		 */ -		wait_for_completion(&dev->bulk_in_completion); -		dev->bulk_in_copied = 0; -		dev->processed_urb = 1;  	}  	/* errors must be reported */ @@ -289,8 +275,6 @@ retry:  		dev->errors = 0;  		/* to preserve notifications about reset */  		rv = (rv == -EPIPE) ? rv : -EIO; -		/* no data to deliver */ -		dev->bulk_in_filled = 0;  		/* report it */  		goto exit;  	} @@ -526,7 +510,7 @@ static int skel_probe(struct usb_interface *interface,  	mutex_init(&dev->io_mutex);  	spin_lock_init(&dev->err_lock);  	init_usb_anchor(&dev->submitted); -	init_completion(&dev->bulk_in_completion); +	init_waitqueue_head(&dev->bulk_in_wait);  	dev->udev = usb_get_dev(interface_to_usbdev(interface));  	dev->interface = interface; diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/usb/wusbcore/Kconfig index 8bf19760d44..0e17b966e1b 100644 --- a/drivers/usb/wusbcore/Kconfig +++ b/drivers/usb/wusbcore/Kconfig @@ -3,7 +3,6 @@  #  config USB_WUSB  	tristate "Enable Wireless USB extensions" -	depends on USB  	depends on PCI  	depends on UWB          select CRYPTO @@ -19,7 +18,6 @@ config USB_WUSB  config USB_WUSB_CBAF  	tristate "Support WUSB Cable Based Association (CBA)" -	depends on USB  	help  	  Some WUSB devices support Cable Based Association. It's used to  	  enable the secure communication between the host and the  |