diff options
Diffstat (limited to 'drivers/usb')
243 files changed, 2732 insertions, 9849 deletions
diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c index 6f3b6e26739..fe815ecd557 100644 --- a/drivers/usb/c67x00/c67x00-drv.c +++ b/drivers/usb/c67x00/c67x00-drv.c @@ -116,7 +116,7 @@ static irqreturn_t c67x00_irq(int irq, void *__dev)  /* ------------------------------------------------------------------------- */ -static int __devinit c67x00_drv_probe(struct platform_device *pdev) +static int c67x00_drv_probe(struct platform_device *pdev)  {  	struct c67x00_device *c67x00;  	struct c67x00_platform_data *pdata; @@ -191,7 +191,7 @@ static int __devinit c67x00_drv_probe(struct platform_device *pdev)  	return ret;  } -static int __devexit c67x00_drv_remove(struct platform_device *pdev) +static int c67x00_drv_remove(struct platform_device *pdev)  {  	struct c67x00_device *c67x00 = platform_get_drvdata(pdev);  	struct resource *res; @@ -219,7 +219,7 @@ static int __devexit c67x00_drv_remove(struct platform_device *pdev)  static struct platform_driver c67x00_driver = {  	.probe	= c67x00_drv_probe, -	.remove	= __devexit_p(c67x00_drv_remove), +	.remove	= c67x00_drv_remove,  	.driver	= {  		.owner = THIS_MODULE,  		.name = "c67x00", diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig index 1ea932a1368..608a2aeb400 100644 --- a/drivers/usb/chipidea/Kconfig +++ b/drivers/usb/chipidea/Kconfig @@ -20,6 +20,7 @@ config USB_CHIPIDEA_UDC  config USB_CHIPIDEA_HOST  	bool "ChipIdea host controller"  	depends on USB=y || USB=USB_CHIPIDEA +	depends on USB_EHCI_HCD  	select USB_EHCI_ROOT_HUB_TT  	help  	  Say Y here to enable host controller functionality of the diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c index 0f5ca4bea17..8c291220be7 100644 --- a/drivers/usb/chipidea/ci13xxx_imx.c +++ b/drivers/usb/chipidea/ci13xxx_imx.c @@ -85,7 +85,7 @@ EXPORT_SYMBOL_GPL(usbmisc_get_init_data);  /* End of common functions shared by usbmisc drivers*/ -static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata  = { +static struct ci13xxx_platform_data ci13xxx_imx_platdata  = {  	.name			= "ci13xxx_imx",  	.flags			= CI13XXX_REQUIRE_TRANSCEIVER |  				  CI13XXX_PULLUP_ON_VBUS | @@ -93,7 +93,7 @@ static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata  = {  	.capoffset		= DEF_CAPOFFSET,  }; -static int __devinit ci13xxx_imx_probe(struct platform_device *pdev) +static int ci13xxx_imx_probe(struct platform_device *pdev)  {  	struct ci13xxx_imx_data *data;  	struct platform_device *plat_ci, *phy_pdev; @@ -220,7 +220,7 @@ put_np:  	return ret;  } -static int __devexit ci13xxx_imx_remove(struct platform_device *pdev) +static int ci13xxx_imx_remove(struct platform_device *pdev)  {  	struct ci13xxx_imx_data *data = platform_get_drvdata(pdev); @@ -252,7 +252,7 @@ MODULE_DEVICE_TABLE(of, ci13xxx_imx_dt_ids);  static struct platform_driver ci13xxx_imx_driver = {  	.probe = ci13xxx_imx_probe, -	.remove = __devexit_p(ci13xxx_imx_remove), +	.remove = ci13xxx_imx_remove,  	.driver = {  		.name = "imx_usb",  		.owner = THIS_MODULE, diff --git a/drivers/usb/chipidea/ci13xxx_msm.c b/drivers/usb/chipidea/ci13xxx_msm.c index b01feb3be92..7d16681fd3d 100644 --- a/drivers/usb/chipidea/ci13xxx_msm.c +++ b/drivers/usb/chipidea/ci13xxx_msm.c @@ -55,7 +55,7 @@ static struct ci13xxx_platform_data ci13xxx_msm_platdata = {  	.notify_event		= ci13xxx_msm_notify_event,  }; -static int __devinit ci13xxx_msm_probe(struct platform_device *pdev) +static int ci13xxx_msm_probe(struct platform_device *pdev)  {  	struct platform_device *plat_ci; @@ -77,7 +77,7 @@ static int __devinit ci13xxx_msm_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit ci13xxx_msm_remove(struct platform_device *pdev) +static int ci13xxx_msm_remove(struct platform_device *pdev)  {  	struct platform_device *plat_ci = platform_get_drvdata(pdev); @@ -89,7 +89,7 @@ static int __devexit ci13xxx_msm_remove(struct platform_device *pdev)  static struct platform_driver ci13xxx_msm_driver = {  	.probe = ci13xxx_msm_probe, -	.remove = __devexit_p(ci13xxx_msm_remove), +	.remove = ci13xxx_msm_remove,  	.driver = { .name = "msm_hsusb", },  }; diff --git a/drivers/usb/chipidea/ci13xxx_pci.c b/drivers/usb/chipidea/ci13xxx_pci.c index 918e14971f2..9b227e39299 100644 --- a/drivers/usb/chipidea/ci13xxx_pci.c +++ b/drivers/usb/chipidea/ci13xxx_pci.c @@ -48,7 +48,7 @@ struct ci13xxx_platform_data penwell_pci_platdata = {   * Allocates basic PCI resources for this USB device controller, and then   * invokes the udc_probe() method to start the UDC associated with it   */ -static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev, +static int ci13xxx_pci_probe(struct pci_dev *pdev,  				       const struct pci_device_id *id)  {  	struct ci13xxx_platform_data *platdata = (void *)id->driver_data; @@ -107,7 +107,7 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,   * first invoking the udc_remove() and then releases   * all PCI resources allocated for this USB device controller   */ -static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev) +static void ci13xxx_pci_remove(struct pci_dev *pdev)  {  	struct platform_device *plat_ci = pci_get_drvdata(pdev); @@ -147,7 +147,7 @@ static struct pci_driver ci13xxx_pci_driver = {  	.name         =	UDC_DRIVER_NAME,  	.id_table     =	ci13xxx_pci_id_table,  	.probe        =	ci13xxx_pci_probe, -	.remove       =	__devexit_p(ci13xxx_pci_remove), +	.remove       =	ci13xxx_pci_remove,  };  module_pci_driver(ci13xxx_pci_driver); diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index f69d029b460..aebf695a934 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -385,12 +385,13 @@ EXPORT_SYMBOL_GPL(ci13xxx_add_device);  void ci13xxx_remove_device(struct platform_device *pdev)  { +	int id = pdev->id;  	platform_device_unregister(pdev); -	ida_simple_remove(&ci_ida, pdev->id); +	ida_simple_remove(&ci_ida, id);  }  EXPORT_SYMBOL_GPL(ci13xxx_remove_device); -static int __devinit ci_hdrc_probe(struct platform_device *pdev) +static int ci_hdrc_probe(struct platform_device *pdev)  {  	struct device	*dev = &pdev->dev;  	struct ci13xxx	*ci; @@ -508,7 +509,7 @@ rm_wq:  	return ret;  } -static int __devexit ci_hdrc_remove(struct platform_device *pdev) +static int ci_hdrc_remove(struct platform_device *pdev)  {  	struct ci13xxx *ci = platform_get_drvdata(pdev); @@ -523,7 +524,7 @@ static int __devexit ci_hdrc_remove(struct platform_device *pdev)  static struct platform_driver ci_hdrc_driver = {  	.probe	= ci_hdrc_probe, -	.remove	= __devexit_p(ci_hdrc_remove), +	.remove	= ci_hdrc_remove,  	.driver	= {  		.name	= "ci_hdrc",  	}, diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index c6f50a25756..3bc244d2636 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -160,9 +160,6 @@ static ssize_t show_device(struct device *dev, struct device_attribute *attr,  		       gadget->speed);  	n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed         = %d\n",  		       gadget->max_speed); -	/* TODO: Scheduled for removal in 3.8. */ -	n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed      = %d\n", -		       gadget_is_dualspeed(gadget));  	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", diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index ebff9f4f56e..caecad9213f 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -20,77 +20,18 @@   */  #include <linux/kernel.h> +#include <linux/io.h>  #include <linux/usb.h>  #include <linux/usb/hcd.h>  #include <linux/usb/chipidea.h> -#define CHIPIDEA_EHCI -#include "../host/ehci-hcd.c" +#include "../host/ehci.h"  #include "ci.h"  #include "bits.h"  #include "host.h" -static int ci_ehci_setup(struct usb_hcd *hcd) -{ -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); -	int ret; - -	hcd->has_tt = 1; - -	ret = ehci_setup(hcd); -	if (ret) -		return ret; - -	ehci_port_power(ehci, 0); - -	return ret; -} - -static const struct hc_driver ci_ehci_hc_driver = { -	.description	= "ehci_hcd", -	.product_desc	= "ChipIdea HDRC EHCI", -	.hcd_priv_size	= sizeof(struct ehci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq	= ehci_irq, -	.flags	= HCD_MEMORY | HCD_USB2, - -	/* -	 * basic lifecycle operations -	 */ -	.reset		= ci_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 struct hc_driver __read_mostly ci_ehci_hc_driver;  static irqreturn_t host_irq(struct ci13xxx *ci)  { @@ -157,5 +98,7 @@ int ci_hdrc_host_init(struct ci13xxx *ci)  	rdrv->name	= "host";  	ci->roles[CI_ROLE_HOST] = rdrv; +	ehci_init_driver(&ci_ehci_hc_driver, NULL); +  	return 0;  } diff --git a/drivers/usb/chipidea/usbmisc_imx6q.c b/drivers/usb/chipidea/usbmisc_imx6q.c index 416e3fc58fd..845efe29e6b 100644 --- a/drivers/usb/chipidea/usbmisc_imx6q.c +++ b/drivers/usb/chipidea/usbmisc_imx6q.c @@ -82,7 +82,7 @@ static const struct of_device_id usbmisc_imx6q_dt_ids[] = {  	{ /* sentinel */ }  }; -static int __devinit usbmisc_imx6q_probe(struct platform_device *pdev) +static int usbmisc_imx6q_probe(struct platform_device *pdev)  {  	struct resource	*res;  	struct imx6q_usbmisc *data; @@ -127,7 +127,7 @@ static int __devinit usbmisc_imx6q_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit usbmisc_imx6q_remove(struct platform_device *pdev) +static int usbmisc_imx6q_remove(struct platform_device *pdev)  {  	usbmisc_unset_ops(&imx6q_usbmisc_ops);  	clk_disable_unprepare(usbmisc->clk); @@ -136,7 +136,7 @@ static int __devexit usbmisc_imx6q_remove(struct platform_device *pdev)  static struct platform_driver usbmisc_imx6q_driver = {  	.probe = usbmisc_imx6q_probe, -	.remove = __devexit_p(usbmisc_imx6q_remove), +	.remove = usbmisc_imx6q_remove,  	.driver = {  		.name = "usbmisc_imx6q",  		.owner = THIS_MODULE, diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 6e49ec6f3ad..8d809a811e1 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -787,6 +787,10 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info)  	tmp.flags = ASYNC_LOW_LATENCY;  	tmp.xmit_fifo_size = acm->writesize;  	tmp.baud_base = le32_to_cpu(acm->line.dwDTERate); +	tmp.close_delay	= acm->port.close_delay / 10; +	tmp.closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? +				ASYNC_CLOSING_WAIT_NONE : +				acm->port.closing_wait / 10;  	if (copy_to_user(info, &tmp, sizeof(tmp)))  		return -EFAULT; @@ -794,6 +798,37 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info)  		return 0;  } +static int set_serial_info(struct acm *acm, +				struct serial_struct __user *newinfo) +{ +	struct serial_struct new_serial; +	unsigned int closing_wait, close_delay; +	int retval = 0; + +	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) +		return -EFAULT; + +	close_delay = new_serial.close_delay * 10; +	closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? +			ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; + +	mutex_lock(&acm->port.mutex); + +	if (!capable(CAP_SYS_ADMIN)) { +		if ((close_delay != acm->port.close_delay) || +		    (closing_wait != acm->port.closing_wait)) +			retval = -EPERM; +		else +			retval = -EOPNOTSUPP; +	} else { +		acm->port.close_delay  = close_delay; +		acm->port.closing_wait = closing_wait; +	} + +	mutex_unlock(&acm->port.mutex); +	return retval; +} +  static int acm_tty_ioctl(struct tty_struct *tty,  					unsigned int cmd, unsigned long arg)  { @@ -804,6 +839,9 @@ static int acm_tty_ioctl(struct tty_struct *tty,  	case TIOCGSERIAL: /* gets serial port data */  		rv = get_serial_info(acm, (struct serial_struct __user *) arg);  		break; +	case TIOCSSERIAL: +		rv = set_serial_info(acm, (struct serial_struct __user *) arg); +		break;  	}  	return rv; diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index f460de31ace..cbacea933b1 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -591,16 +591,14 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,  	/* Now look at all of this device's children. */  	usb_hub_for_each_child(usbdev, chix, childdev) { -		if (childdev) { -			usb_lock_device(childdev); -			ret = usb_device_dump(buffer, nbytes, skip_bytes, -					      file_offset, childdev, bus, -					      level + 1, chix - 1, ++cnt); -			usb_unlock_device(childdev); -			if (ret == -EFAULT) -				return total_written; -			total_written += ret; -		} +		usb_lock_device(childdev); +		ret = usb_device_dump(buffer, nbytes, skip_bytes, +				      file_offset, childdev, bus, +				      level + 1, chix - 1, ++cnt); +		usb_unlock_device(childdev); +		if (ret == -EFAULT) +			return total_written; +		total_written += ret;  	}  	return total_written;  } diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 6056db7af41..88dde95b679 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -32,8 +32,6 @@  #include "usb.h" -#ifdef CONFIG_HOTPLUG -  /*   * Adds a new dynamic USBdevice ID to this driver,   * and cause the driver to probe for all devices again. @@ -194,20 +192,6 @@ static void usb_free_dynids(struct usb_driver *usb_drv)  	}  	spin_unlock(&usb_drv->dynids.lock);  } -#else -static inline int usb_create_newid_files(struct usb_driver *usb_drv) -{ -	return 0; -} - -static void usb_remove_newid_files(struct usb_driver *usb_drv) -{ -} - -static inline void usb_free_dynids(struct usb_driver *usb_drv) -{ -} -#endif  static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,  							struct usb_driver *drv) @@ -790,7 +774,6 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)  	return 0;  } -#ifdef	CONFIG_HOTPLUG  static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)  {  	struct usb_device *usb_dev; @@ -832,14 +815,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)  	return 0;  } -#else - -static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) -{ -	return -ENODEV; -} -#endif	/* CONFIG_HOTPLUG */ -  /**   * usb_register_device_driver - register a USB device (not interface) driver   * @new_udriver: USB operations for the device driver diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 69ecd3c9231..eff2010eb63 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -47,6 +47,9 @@ int usb_choose_configuration(struct usb_device *udev)  	int insufficient_power = 0;  	struct usb_host_config *c, *best; +	if (usb_device_is_owned(udev)) +		return 0; +  	best = NULL;  	c = udev->config;  	num_configs = udev->descriptor.bNumConfigurations; @@ -160,9 +163,7 @@ static int generic_probe(struct usb_device *udev)  	/* Choose and set the configuration.  This registers the interfaces  	 * with the driver core and lets interface drivers bind to them.  	 */ -	if (usb_device_is_owned(udev)) -		;		/* Don't configure if the device is owned */ -	else if (udev->authorized == 0) +	if (udev->authorized == 0)  		dev_err(&udev->dev, "Device is not authorized for usage\n");  	else {  		c = usb_choose_configuration(udev); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index f034716190f..4225d5e7213 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2039,8 +2039,9 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)  	status = hcd->driver->bus_resume(hcd);  	clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);  	if (status == 0) { -		/* TRSMRCY = 10 msec */ -		msleep(10); +		struct usb_device *udev; +		int port1; +  		spin_lock_irq(&hcd_root_hub_lock);  		if (!HCD_DEAD(hcd)) {  			usb_set_device_state(rhdev, rhdev->actconfig @@ -2050,6 +2051,20 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)  			hcd->state = HC_STATE_RUNNING;  		}  		spin_unlock_irq(&hcd_root_hub_lock); + +		/* +		 * Check whether any of the enabled ports on the root hub are +		 * unsuspended.  If they are then a TRSMRCY delay is needed +		 * (this is what the USB-2 spec calls a "global resume"). +		 * Otherwise we can skip the delay. +		 */ +		usb_hub_for_each_child(rhdev, port1, udev) { +			if (udev->state != USB_STATE_NOTATTACHED && +					!udev->port_is_suspended) { +				usleep_range(10000, 11000);	/* TRSMRCY */ +				break; +			} +		}  	} else {  		hcd->state = old_state;  		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 1af04bdeaf0..a815fd2cc5e 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -39,6 +39,9 @@  #endif  #endif +#define USB_VENDOR_GENESYS_LOGIC		0x05e3 +#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND	0x01 +  struct usb_port {  	struct usb_device *child;  	struct device dev; @@ -86,6 +89,8 @@ struct usb_hub {  	unsigned		quiescing:1;  	unsigned		disconnected:1; +	unsigned		quirk_check_port_auto_suspend:1; +  	unsigned		has_indicators:1;  	u8			indicator[USB_MAXCHILDREN];  	struct delayed_work	leds; @@ -736,7 +741,6 @@ static void hub_tt_work(struct work_struct *work)  	struct usb_hub		*hub =  		container_of(work, struct usb_hub, tt.clear_work);  	unsigned long		flags; -	int			limit = 100;  	spin_lock_irqsave (&hub->tt.lock, flags);  	while (!list_empty(&hub->tt.clear_list)) { @@ -746,9 +750,6 @@ static void hub_tt_work(struct work_struct *work)  		const struct hc_driver	*drv;  		int			status; -		if (!hub->quiescing && --limit < 0) -			break; -  		next = hub->tt.clear_list.next;  		clear = list_entry (next, struct usb_tt_clear, clear_list);  		list_del (&clear->clear_list); @@ -1612,6 +1613,41 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)  	desc = intf->cur_altsetting;  	hdev = interface_to_usbdev(intf); +	/* +	 * Set default autosuspend delay as 0 to speedup bus suspend, +	 * based on the below considerations: +	 * +	 * - Unlike other drivers, the hub driver does not rely on the +	 *   autosuspend delay to provide enough time to handle a wakeup +	 *   event, and the submitted status URB is just to check future +	 *   change on hub downstream ports, so it is safe to do it. +	 * +	 * - The patch might cause one or more auto supend/resume for +	 *   below very rare devices when they are plugged into hub +	 *   first time: +	 * +	 *   	devices having trouble initializing, and disconnect +	 *   	themselves from the bus and then reconnect a second +	 *   	or so later +	 * +	 *   	devices just for downloading firmware, and disconnects +	 *   	themselves after completing it +	 * +	 *   For these quite rare devices, their drivers may change the +	 *   autosuspend delay of their parent hub in the probe() to one +	 *   appropriate value to avoid the subtle problem if someone +	 *   does care it. +	 * +	 * - The patch may cause one or more auto suspend/resume on +	 *   hub during running 'lsusb', but it is probably too +	 *   infrequent to worry about. +	 * +	 * - Change autosuspend delay of hub can avoid unnecessary auto +	 *   suspend timer for hub, also may decrease power consumption +	 *   of USB bus. +	 */ +	pm_runtime_set_autosuspend_delay(&hdev->dev, 0); +  	/* Hubs have proper suspend/resume support. */  	usb_enable_autosuspend(hdev); @@ -1670,6 +1706,9 @@ descriptor_error:  	if (hdev->speed == USB_SPEED_HIGH)  		highspeed_hubs++; +	if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND) +		hub->quirk_check_port_auto_suspend = 1; +  	if (hub_configure(hub, endpoint) >= 0)  		return 0; @@ -2012,7 +2051,7 @@ static void show_string(struct usb_device *udev, char *id, char *string)  {  	if (!string)  		return; -	dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, string); +	dev_info(&udev->dev, "%s: %s\n", id, string);  }  static void announce_device(struct usb_device *udev) @@ -2879,6 +2918,7 @@ 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);  	}  	usb_mark_last_busy(hub->hdev); @@ -3043,6 +3083,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)   SuspendCleared:  	if (status == 0) { +		udev->port_is_suspended = 0;  		if (hub_is_superspeed(hub->hdev)) {  			if (portchange & USB_PORT_STAT_C_LINK_STATE)  				clear_port_feature(hub->hdev, port1, @@ -3126,6 +3167,21 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)  #endif +static int check_ports_changed(struct usb_hub *hub) +{ +	int port1; + +	for (port1 = 1; port1 <= hub->hdev->maxchild; ++port1) { +		u16 portstatus, portchange; +		int status; + +		status = hub_port_status(hub, port1, &portstatus, &portchange); +		if (!status && portchange) +			return 1; +	} +	return 0; +} +  static int hub_suspend(struct usb_interface *intf, pm_message_t msg)  {  	struct usb_hub		*hub = usb_get_intfdata (intf); @@ -3144,6 +3200,16 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)  				return -EBUSY;  		}  	} + +	if (hdev->do_remote_wakeup && hub->quirk_check_port_auto_suspend) { +		/* check if there are changes pending on hub ports */ +		if (check_ports_changed(hub)) { +			if (PMSG_IS_AUTO(msg)) +				return -EBUSY; +			pm_wakeup_event(&hdev->dev, 2000); +		} +	} +  	if (hub_is_superspeed(hdev) && hdev->do_remote_wakeup) {  		/* Enable hub to send remote wakeup for all ports. */  		for (port1 = 1; port1 <= hdev->maxchild; port1++) { @@ -3972,6 +4038,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,  	if (retval)  		goto fail; +	if (hcd->phy && !hdev->parent) +		usb_phy_notify_connect(hcd->phy, udev->speed); +  	/*  	 * Some superspeed devices have finished the link training process  	 * and attached to a superspeed hub port, but the device descriptor @@ -4166,8 +4235,12 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  	}  	/* Disconnect any existing devices under this port */ -	if (udev) +	if (udev) { +		if (hcd->phy && !hdev->parent && +				!(portstatus & USB_PORT_STAT_CONNECTION)) +			usb_phy_notify_disconnect(hcd->phy, udev->speed);  		usb_disconnect(&hub->ports[port1 - 1]->child); +	}  	clear_bit(port1, hub->change_bits);  	/* We can forget about a "removed" device when there's a physical @@ -4190,13 +4263,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,  		}  	} -	if (hcd->phy && !hdev->parent) { -		if (portstatus & USB_PORT_STAT_CONNECTION) -			usb_phy_notify_connect(hcd->phy, port1); -		else -			usb_phy_notify_disconnect(hcd->phy, port1); -	} -  	/* Return now if debouncing failed or nothing is connected or  	 * the device was "removed".  	 */ @@ -4648,6 +4714,11 @@ static int hub_thread(void *__unused)  }  static const struct usb_device_id hub_id_table[] = { +    { .match_flags = USB_DEVICE_ID_MATCH_VENDOR +	           | USB_DEVICE_ID_MATCH_INT_CLASS, +      .idVendor = USB_VENDOR_GENESYS_LOGIC, +      .bInterfaceClass = USB_CLASS_HUB, +      .driver_info = HUB_QUIRK_CHECK_PORT_AUTOSUSPEND},      { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS,        .bDeviceClass = USB_CLASS_HUB},      { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 1ed5afd91e6..131f73649b6 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1540,7 +1540,6 @@ static void usb_release_interface(struct device *dev)  	kfree(intf);  } -#ifdef	CONFIG_HOTPLUG  static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)  {  	struct usb_device *usb_dev; @@ -1575,14 +1574,6 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)  	return 0;  } -#else - -static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) -{ -	return -ENODEV; -} -#endif	/* CONFIG_HOTPLUG */ -  struct device_type usb_if_device_type = {  	.name =		"usb_interface",  	.release =	usb_release_interface, @@ -1795,7 +1786,8 @@ free_interfaces:  	if (dev->actconfig && usb_disable_lpm(dev)) {  		dev_err(&dev->dev, "%s Failed to disable LPM\n.", __func__);  		mutex_unlock(hcd->bandwidth_mutex); -		return -ENOMEM; +		ret = -ENOMEM; +		goto free_interfaces;  	}  	ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);  	if (ret < 0) { @@ -1806,29 +1798,8 @@ free_interfaces:  		goto free_interfaces;  	} -	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), -			      USB_REQ_SET_CONFIGURATION, 0, configuration, 0, -			      NULL, 0, USB_CTRL_SET_TIMEOUT); -	if (ret < 0) { -		/* All the old state is gone, so what else can we do? -		 * The device is probably useless now anyway. -		 */ -		cp = NULL; -	} - -	dev->actconfig = cp; -	if (!cp) { -		usb_set_device_state(dev, USB_STATE_ADDRESS); -		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); -		/* Leave LPM disabled while the device is unconfigured. */ -		mutex_unlock(hcd->bandwidth_mutex); -		usb_autosuspend_device(dev); -		goto free_interfaces; -	} -	mutex_unlock(hcd->bandwidth_mutex); -	usb_set_device_state(dev, USB_STATE_CONFIGURED); - -	/* Initialize the new interface structures and the +	/* +	 * Initialize the new interface structures and the  	 * hc/hcd/usbcore interface/endpoint state.  	 */  	for (i = 0; i < nintf; ++i) { @@ -1872,6 +1843,35 @@ free_interfaces:  	}  	kfree(new_interfaces); +	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), +			      USB_REQ_SET_CONFIGURATION, 0, configuration, 0, +			      NULL, 0, USB_CTRL_SET_TIMEOUT); +	if (ret < 0 && cp) { +		/* +		 * All the old state is gone, so what else can we do? +		 * The device is probably useless now anyway. +		 */ +		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); +		for (i = 0; i < nintf; ++i) { +			usb_disable_interface(dev, cp->interface[i], true); +			put_device(&cp->interface[i]->dev); +			cp->interface[i] = NULL; +		} +		cp = NULL; +	} + +	dev->actconfig = cp; +	mutex_unlock(hcd->bandwidth_mutex); + +	if (!cp) { +		usb_set_device_state(dev, USB_STATE_ADDRESS); + +		/* Leave LPM disabled while the device is unconfigured. */ +		usb_autosuspend_device(dev); +		return ret; +	} +	usb_set_device_state(dev, USB_STATE_CONFIGURED); +  	if (cp->string == NULL &&  			!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))  		cp->string = usb_cache_string(dev, cp->desc.iConfiguration); diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 9d912bfdcff..e0d9d948218 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -214,9 +214,25 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);   * urb->interval is modified to reflect the actual transfer period used   * (normally some power of two units).  And for isochronous urbs,   * urb->start_frame is modified to reflect when the URB's transfers were - * scheduled to start.  Not all isochronous transfer scheduling policies - * will work, but most host controller drivers should easily handle ISO - * queues going from now until 10-200 msec into the future. + * scheduled to start. + * + * Not all isochronous transfer scheduling policies will work, but most + * host controller drivers should easily handle ISO queues going from now + * until 10-200 msec into the future.  Drivers should try to keep at + * least one or two msec of data in the queue; many controllers require + * that new transfers start at least 1 msec in the future when they are + * added.  If the driver is unable to keep up and the queue empties out, + * the behavior for new submissions is governed by the URB_ISO_ASAP flag. + * If the flag is set, or if the queue is idle, then the URB is always + * assigned to the first available (and not yet expired) slot in the + * endpoint's schedule.  If the flag is not set and the queue is active + * then the URB is always assigned to the next slot in the schedule + * following the end of the endpoint's previous URB, even if that slot is + * in the past.  When a packet is assigned in this way to a slot that has + * already expired, the packet is not transmitted and the corresponding + * usb_iso_packet_descriptor's status field will return -EXDEV.  If this + * would happen to all the packets in the URB, submission fails with a + * -EXDEV error code.   *   * For control endpoints, the synchronous usb_control_msg() call is   * often used (in non-interrupt context) instead of this call. @@ -305,8 +321,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)  	struct usb_host_endpoint	*ep;  	int				is_out; -	if (!urb || urb->hcpriv || !urb->complete) +	if (!urb || !urb->complete)  		return -EINVAL; +	if (urb->hcpriv) { +		WARN_ONCE(1, "URB %p submitted while active\n", urb); +		return -EBUSY; +	} +  	dev = urb->dev;  	if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))  		return -ENODEV; diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index cd8fb44a3e1..f81b9257273 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -233,7 +233,6 @@ static void usb_release_dev(struct device *dev)  	kfree(udev);  } -#ifdef	CONFIG_HOTPLUG  static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)  {  	struct usb_device *usb_dev; @@ -249,14 +248,6 @@ static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)  	return 0;  } -#else - -static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env) -{ -	return -ENODEV; -} -#endif	/* CONFIG_HOTPLUG */ -  #ifdef	CONFIG_PM  /* USB device Power-Management thunks. @@ -370,14 +361,14 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,  				 struct usb_bus *bus, unsigned port1)  {  	struct usb_device *dev; -	struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self); +	struct usb_hcd *usb_hcd = bus_to_hcd(bus);  	unsigned root_hub = 0;  	dev = kzalloc(sizeof(*dev), GFP_KERNEL);  	if (!dev)  		return NULL; -	if (!usb_get_hcd(bus_to_hcd(bus))) { +	if (!usb_get_hcd(usb_hcd)) {  		kfree(dev);  		return NULL;  	} diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index d441fe4c180..4502648b817 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -27,19 +27,7 @@ endif  ##  obj-$(CONFIG_USB_DWC3)		+= dwc3-omap.o - -## -# REVISIT Samsung Exynos platform needs the clk API which isn't -# defined on all architectures. If we allow dwc3-exynos.c compile -# always we will fail the linking phase on those architectures -# which don't provide clk api implementation and that's unnaceptable. -# -# When Samsung's platform start supporting pm_runtime, this check -# for HAVE_CLK should be removed. -## -ifneq ($(CONFIG_HAVE_CLK),) -	obj-$(CONFIG_USB_DWC3)		+= dwc3-exynos.o -endif +obj-$(CONFIG_USB_DWC3)		+= dwc3-exynos.o  ifneq ($(CONFIG_PCI),)  	obj-$(CONFIG_USB_DWC3)		+= dwc3-pci.o diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c14ebc975ba..3a4004a620a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -66,45 +66,6 @@ MODULE_PARM_DESC(maximum_speed, "Maximum supported speed.");  /* -------------------------------------------------------------------------- */ -#define DWC3_DEVS_POSSIBLE	32 - -static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE); - -int dwc3_get_device_id(void) -{ -	int		id; - -again: -	id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE); -	if (id < DWC3_DEVS_POSSIBLE) { -		int old; - -		old = test_and_set_bit(id, dwc3_devs); -		if (old) -			goto again; -	} else { -		pr_err("dwc3: no space for new device\n"); -		id = -ENOMEM; -	} - -	return id; -} -EXPORT_SYMBOL_GPL(dwc3_get_device_id); - -void dwc3_put_device_id(int id) -{ -	int			ret; - -	if (id < 0) -		return; - -	ret = test_bit(id, dwc3_devs); -	WARN(!ret, "dwc3: ID %d not in use\n", id); -	smp_mb__before_clear_bit(); -	clear_bit(id, dwc3_devs); -} -EXPORT_SYMBOL_GPL(dwc3_put_device_id); -  void dwc3_set_mode(struct dwc3 *dwc, u32 mode)  {  	u32 reg; @@ -169,7 +130,6 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,  		struct dwc3_event_buffer *evt)  {  	dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); -	kfree(evt);  }  /** @@ -180,12 +140,11 @@ 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 *__devinit -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; -	evt = kzalloc(sizeof(*evt), GFP_KERNEL); +	evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL);  	if (!evt)  		return ERR_PTR(-ENOMEM); @@ -193,10 +152,8 @@ dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)  	evt->length	= length;  	evt->buf	= dma_alloc_coherent(dwc->dev, length,  			&evt->dma, GFP_KERNEL); -	if (!evt->buf) { -		kfree(evt); +	if (!evt->buf)  		return ERR_PTR(-ENOMEM); -	}  	return evt;  } @@ -215,8 +172,6 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)  		if (evt)  			dwc3_free_one_event_buffer(dwc, evt);  	} - -	kfree(dwc->ev_buffs);  }  /** @@ -227,7 +182,7 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)   * Returns 0 on success otherwise negative errno. In the error case, dwc   * may contain some buffers allocated but not all which were requested.   */ -static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) +static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)  {  	int			num;  	int			i; @@ -235,7 +190,8 @@ static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)  	num = DWC3_NUM_INT(dwc->hwparams.hwparams1);  	dwc->num_event_buffers = num; -	dwc->ev_buffs = kzalloc(sizeof(*dwc->ev_buffs) * num, GFP_KERNEL); +	dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num, +			GFP_KERNEL);  	if (!dwc->ev_buffs) {  		dev_err(dwc->dev, "can't allocate event buffers array\n");  		return -ENOMEM; @@ -303,7 +259,7 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)  	}  } -static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc) +static void dwc3_cache_hwparams(struct dwc3 *dwc)  {  	struct dwc3_hwparams	*parms = &dwc->hwparams; @@ -324,7 +280,7 @@ static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)   *   * Returns 0 on success otherwise negative errno.   */ -static int __devinit dwc3_core_init(struct dwc3 *dwc) +static int dwc3_core_init(struct dwc3 *dwc)  {  	unsigned long		timeout;  	u32			reg; @@ -358,8 +314,6 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc)  	dwc3_core_soft_reset(dwc); -	dwc3_cache_hwparams(dwc); -  	reg = dwc3_readl(dwc->regs, DWC3_GCTL);  	reg &= ~DWC3_GCTL_SCALEDOWN_MASK;  	reg &= ~DWC3_GCTL_DISSCRAMBLE; @@ -383,24 +337,14 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc)  	dwc3_writel(dwc->regs, DWC3_GCTL, reg); -	ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); -	if (ret) { -		dev_err(dwc->dev, "failed to allocate event buffers\n"); -		ret = -ENOMEM; -		goto err1; -	} -  	ret = dwc3_event_buffers_setup(dwc);  	if (ret) {  		dev_err(dwc->dev, "failed to setup event buffers\n"); -		goto err1; +		goto err0;  	}  	return 0; -err1: -	dwc3_free_event_buffers(dwc); -  err0:  	return ret;  } @@ -408,16 +352,14 @@ err0:  static void dwc3_core_exit(struct dwc3 *dwc)  {  	dwc3_event_buffers_cleanup(dwc); -	dwc3_free_event_buffers(dwc);  	usb_phy_shutdown(dwc->usb2_phy);  	usb_phy_shutdown(dwc->usb3_phy); -  }  #define DWC3_ALIGN_MASK		(16 - 1) -static int __devinit dwc3_probe(struct platform_device *pdev) +static int dwc3_probe(struct platform_device *pdev)  {  	struct device_node	*node = pdev->dev.of_node;  	struct resource		*res; @@ -515,10 +457,19 @@ static int __devinit dwc3_probe(struct platform_device *pdev)  	pm_runtime_get_sync(dev);  	pm_runtime_forbid(dev); +	dwc3_cache_hwparams(dwc); + +	ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); +	if (ret) { +		dev_err(dwc->dev, "failed to allocate event buffers\n"); +		ret = -ENOMEM; +		goto err0; +	} +  	ret = dwc3_core_init(dwc);  	if (ret) {  		dev_err(dev, "failed to initialize core\n"); -		return ret; +		goto err0;  	}  	mode = DWC3_MODE(dwc->hwparams.hwparams0); @@ -590,10 +541,13 @@ err2:  err1:  	dwc3_core_exit(dwc); +err0: +	dwc3_free_event_buffers(dwc); +  	return ret;  } -static int __devexit dwc3_remove(struct platform_device *pdev) +static int dwc3_remove(struct platform_device *pdev)  {  	struct dwc3	*dwc = platform_get_drvdata(pdev);  	struct resource	*res; @@ -628,7 +582,7 @@ static int __devexit dwc3_remove(struct platform_device *pdev)  static struct platform_driver dwc3_driver = {  	.probe		= dwc3_probe, -	.remove		= __devexit_p(dwc3_remove), +	.remove		= dwc3_remove,  	.driver		= {  		.name	= "dwc3",  	}, diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 243affc9343..49995634426 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -868,7 +868,4 @@ void dwc3_host_exit(struct dwc3 *dwc);  int dwc3_gadget_init(struct dwc3 *dwc);  void dwc3_gadget_exit(struct dwc3 *dwc); -extern int dwc3_get_device_id(void); -extern void dwc3_put_device_id(int id); -  #endif /* __DRIVERS_USB_DWC3_CORE_H */ diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index d4a30f11872..92604b4f971 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -652,7 +652,7 @@ static const struct file_operations dwc3_link_state_fops = {  	.release		= single_release,  }; -int __devinit dwc3_debugfs_init(struct dwc3 *dwc) +int dwc3_debugfs_init(struct dwc3 *dwc)  {  	struct dentry		*root;  	struct dentry		*file; @@ -703,7 +703,7 @@ err0:  	return ret;  } -void __devexit dwc3_debugfs_exit(struct dwc3 *dwc) +void dwc3_debugfs_exit(struct dwc3 *dwc)  {  	debugfs_remove_recursive(dwc->root);  	dwc->root = NULL; diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index ca6597853f9..aae5328ac77 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -21,6 +21,7 @@  #include <linux/clk.h>  #include <linux/usb/otg.h>  #include <linux/usb/nop-usb-xceiv.h> +#include <linux/of.h>  #include "core.h" @@ -33,7 +34,7 @@ struct dwc3_exynos {  	struct clk		*clk;  }; -static int __devinit dwc3_exynos_register_phys(struct dwc3_exynos *exynos) +static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)  {  	struct nop_usb_xceiv_platform_data pdata;  	struct platform_device	*pdev; @@ -87,14 +88,14 @@ err1:  	return ret;  } -static int __devinit dwc3_exynos_probe(struct platform_device *pdev) +static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32); + +static int dwc3_exynos_probe(struct platform_device *pdev)  { -	struct dwc3_exynos_data	*pdata = pdev->dev.platform_data;  	struct platform_device	*dwc3;  	struct dwc3_exynos	*exynos;  	struct clk		*clk; -	int			devid;  	int			ret = -ENOMEM;  	exynos = kzalloc(sizeof(*exynos), GFP_KERNEL); @@ -103,11 +104,15 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)  		goto err0;  	} -	platform_set_drvdata(pdev, exynos); +	/* +	 * 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 move to full device tree support this will vanish off. +	 */ +	if (!pdev->dev.dma_mask) +		pdev->dev.dma_mask = &dwc3_exynos_dma_mask; -	devid = dwc3_get_device_id(); -	if (devid < 0) -		goto err1; +	platform_set_drvdata(pdev, exynos);  	ret = dwc3_exynos_register_phys(exynos);  	if (ret) { @@ -115,10 +120,10 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)  		goto err1;  	} -	dwc3 = platform_device_alloc("dwc3", devid); +	dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);  	if (!dwc3) {  		dev_err(&pdev->dev, "couldn't allocate dwc3 device\n"); -		goto err2; +		goto err1;  	}  	clk = clk_get(&pdev->dev, "usbdrd30"); @@ -139,14 +144,6 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)  	clk_enable(exynos->clk); -	/* PHY initialization */ -	if (!pdata) { -		dev_dbg(&pdev->dev, "missing platform data\n"); -	} else { -		if (pdata->phy_init) -			pdata->phy_init(pdev, pdata->phy_type); -	} -  	ret = platform_device_add_resources(dwc3, pdev->resource,  			pdev->num_resources);  	if (ret) { @@ -163,35 +160,24 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)  	return 0;  err4: -	if (pdata && pdata->phy_exit) -		pdata->phy_exit(pdev, pdata->phy_type); -  	clk_disable(clk);  	clk_put(clk);  err3:  	platform_device_put(dwc3); -err2: -	dwc3_put_device_id(devid);  err1:  	kfree(exynos);  err0:  	return ret;  } -static int __devexit dwc3_exynos_remove(struct platform_device *pdev) +static int dwc3_exynos_remove(struct platform_device *pdev)  {  	struct dwc3_exynos	*exynos = platform_get_drvdata(pdev); -	struct dwc3_exynos_data *pdata = pdev->dev.platform_data;  	platform_device_unregister(exynos->dwc3);  	platform_device_unregister(exynos->usb2_phy);  	platform_device_unregister(exynos->usb3_phy); -	dwc3_put_device_id(exynos->dwc3->id); - -	if (pdata && pdata->phy_exit) -		pdata->phy_exit(pdev, pdata->phy_type); -  	clk_disable(exynos->clk);  	clk_put(exynos->clk); @@ -200,11 +186,20 @@ static int __devexit dwc3_exynos_remove(struct platform_device *pdev)  	return 0;  } +#ifdef CONFIG_OF +static const struct of_device_id exynos_dwc3_match[] = { +	{ .compatible = "samsung,exynos-dwc3" }, +	{}, +}; +MODULE_DEVICE_TABLE(of, exynos_dwc3_match); +#endif +  static struct platform_driver dwc3_exynos_driver = {  	.probe		= dwc3_exynos_probe, -	.remove		= __devexit_p(dwc3_exynos_remove), +	.remove		= dwc3_exynos_remove,  	.driver		= {  		.name	= "exynos-dwc3", +		.of_match_table = of_match_ptr(exynos_dwc3_match),  	},  }; diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index ee57a10d90d..f31867fd257 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -157,7 +157,7 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)  	writel(value, base + offset);  } -static int __devinit dwc3_omap_register_phys(struct dwc3_omap *omap) +static int dwc3_omap_register_phys(struct dwc3_omap *omap)  {  	struct nop_usb_xceiv_platform_data pdata;  	struct platform_device	*pdev; @@ -262,7 +262,7 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)  	return IRQ_HANDLED;  } -static int __devinit dwc3_omap_probe(struct platform_device *pdev) +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; @@ -272,7 +272,6 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)  	struct resource		*res;  	struct device		*dev = &pdev->dev; -	int			devid;  	int			size;  	int			ret = -ENOMEM;  	int			irq; @@ -315,14 +314,10 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)  		return ret;  	} -	devid = dwc3_get_device_id(); -	if (devid < 0) -		return -ENODEV; - -	dwc3 = platform_device_alloc("dwc3", devid); +	dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);  	if (!dwc3) {  		dev_err(dev, "couldn't allocate dwc3 device\n"); -		goto err1; +		return -ENOMEM;  	}  	context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL); @@ -423,23 +418,16 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)  err2:  	platform_device_put(dwc3); - -err1: -	dwc3_put_device_id(devid); -  	return ret;  } -static int __devexit dwc3_omap_remove(struct platform_device *pdev) +static int dwc3_omap_remove(struct platform_device *pdev)  {  	struct dwc3_omap	*omap = platform_get_drvdata(pdev);  	platform_device_unregister(omap->dwc3);  	platform_device_unregister(omap->usb2_phy);  	platform_device_unregister(omap->usb3_phy); - -	dwc3_put_device_id(omap->dwc3->id); -  	return 0;  } @@ -453,7 +441,7 @@ MODULE_DEVICE_TABLE(of, of_dwc3_matach);  static struct platform_driver dwc3_omap_driver = {  	.probe		= dwc3_omap_probe, -	.remove		= __devexit_p(dwc3_omap_remove), +	.remove		= dwc3_omap_remove,  	.driver		= {  		.name	= "omap-dwc3",  		.of_match_table	= of_dwc3_matach, diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 94f550e37f9..7d70f44567d 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -58,7 +58,7 @@ struct dwc3_pci {  	struct platform_device	*usb3_phy;  }; -static int __devinit dwc3_pci_register_phys(struct dwc3_pci *glue) +static int dwc3_pci_register_phys(struct dwc3_pci *glue)  {  	struct nop_usb_xceiv_platform_data pdata;  	struct platform_device	*pdev; @@ -112,14 +112,13 @@ err1:  	return ret;  } -static int __devinit dwc3_pci_probe(struct pci_dev *pci, +static int dwc3_pci_probe(struct pci_dev *pci,  		const struct pci_device_id *id)  {  	struct resource		res[2];  	struct platform_device	*dwc3;  	struct dwc3_pci		*glue;  	int			ret = -ENOMEM; -	int			devid;  	struct device		*dev = &pci->dev;  	glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL); @@ -145,13 +144,7 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci,  		return ret;  	} -	devid = dwc3_get_device_id(); -	if (devid < 0) { -		ret = -ENOMEM; -		goto err1; -	} - -	dwc3 = platform_device_alloc("dwc3", devid); +	dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);  	if (!dwc3) {  		dev_err(dev, "couldn't allocate dwc3 device\n");  		ret = -ENOMEM; @@ -172,7 +165,7 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci,  	ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res));  	if (ret) {  		dev_err(dev, "couldn't add resources to dwc3 device\n"); -		goto err2; +		goto err1;  	}  	pci_set_drvdata(pci, glue); @@ -195,23 +188,18 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci,  err3:  	pci_set_drvdata(pci, NULL);  	platform_device_put(dwc3); - -err2: -	dwc3_put_device_id(devid); -  err1:  	pci_disable_device(pci);  	return ret;  } -static void __devexit dwc3_pci_remove(struct pci_dev *pci) +static void dwc3_pci_remove(struct pci_dev *pci)  {  	struct dwc3_pci	*glue = pci_get_drvdata(pci);  	platform_device_unregister(glue->usb2_phy);  	platform_device_unregister(glue->usb3_phy); -	dwc3_put_device_id(glue->dwc3->id);  	platform_device_unregister(glue->dwc3);  	pci_set_drvdata(pci, NULL);  	pci_disable_device(pci); @@ -230,7 +218,7 @@ static struct pci_driver dwc3_pci_driver = {  	.name		= "dwc3-pci",  	.id_table	= dwc3_pci_id_table,  	.probe		= dwc3_pci_probe, -	.remove		= __devexit_p(dwc3_pci_remove), +	.remove		= dwc3_pci_remove,  };  MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 7b7deddf6a5..2e43b332aae 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1579,7 +1579,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {  /* -------------------------------------------------------------------------- */ -static int __devinit dwc3_gadget_init_endpoints(struct dwc3 *dwc) +static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)  {  	struct dwc3_ep			*dep;  	u8				epnum; @@ -2374,7 +2374,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)   *   * Returns 0 on success otherwise negative errno.   */ -int __devinit dwc3_gadget_init(struct dwc3 *dwc) +int dwc3_gadget_init(struct dwc3 *dwc)  {  	u32					reg;  	int					ret; diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 4bfa78af379..5e29ddeb4d3 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -974,7 +974,7 @@ struct console early_dbgp_console = {  	.index =	-1,  }; -#if IS_ENABLED(CONFIG_USB_EHCI_HCD) +#if IS_ENABLED(CONFIG_USB)  int dbgp_reset_prep(struct usb_hcd *hcd)  {  	int ret = xen_dbgp_reset_prep(hcd); @@ -1008,7 +1008,7 @@ int dbgp_external_startup(struct usb_hcd *hcd)  	return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();  }  EXPORT_SYMBOL_GPL(dbgp_external_startup); -#endif /* USB_EHCI_HCD */ +#endif /* USB */  #ifdef CONFIG_KGDB diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index e0ff51b8952..14625fd2cec 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -721,31 +721,6 @@ config USB_FUNCTIONFS_GENERIC  	  Include a configuration with the Function Filesystem alone with  	  no Ethernet interface. -config USB_FILE_STORAGE -	tristate "File-backed Storage Gadget (DEPRECATED)" -	depends on BLOCK -	help -	  The File-backed Storage Gadget acts as a USB Mass Storage -	  disk drive.  As its storage repository it can use a regular -	  file or a block device (in much the same way as the "loop" -	  device driver), specified as a module parameter. - -	  Say "y" to link the driver statically, or "m" to build a -	  dynamically linked module called "g_file_storage". - -	  NOTE: This driver is deprecated.  Its replacement is the -	  Mass Storage Gadget. - -config USB_FILE_STORAGE_TEST -	bool "File-backed Storage Gadget testing version" -	depends on USB_FILE_STORAGE -	default n -	help -	  Say "y" to generate the larger testing version of the -	  File-backed Storage Gadget, useful for probing the -	  behavior of USB Mass Storage hosts.  Not needed for -	  normal operation. -  config USB_MASS_STORAGE  	tristate "Mass Storage Gadget"  	depends on BLOCK @@ -756,8 +731,8 @@ config USB_MASS_STORAGE  	  device (in much the same way as the "loop" device driver),  	  specified as a module parameter or sysfs option. -	  This driver is an updated replacement for the deprecated -	  File-backed Storage Gadget (g_file_storage). +	  This driver is a replacement for now removed File-backed +	  Storage Gadget (g_file_storage).  	  Say "y" to link the driver statically, or "m" to build  	  a dynamically linked module called "g_mass_storage". diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 307be5fa824..8b4acfd92aa 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -44,7 +44,6 @@ g_ether-y			:= ether.o  g_serial-y			:= serial.o  g_midi-y			:= gmidi.o  gadgetfs-y			:= inode.o -g_file_storage-y		:= file_storage.o  g_mass_storage-y		:= mass_storage.o  g_printer-y			:= printer.o  g_cdc-y				:= cdc2.o @@ -62,7 +61,6 @@ obj-$(CONFIG_USB_AUDIO)		+= g_audio.o  obj-$(CONFIG_USB_ETH)		+= g_ether.o  obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o  obj-$(CONFIG_USB_FUNCTIONFS)	+= g_ffs.o -obj-$(CONFIG_USB_FILE_STORAGE)	+= g_file_storage.o  obj-$(CONFIG_USB_MASS_STORAGE)	+= g_mass_storage.o  obj-$(CONFIG_USB_G_SERIAL)	+= g_serial.o  obj-$(CONFIG_USB_G_PRINTER)	+= g_printer.o diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 89d90b5fb78..59dcea2f695 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -31,6 +31,7 @@  #include <linux/usb/gadget.h>  #include <linux/of.h>  #include <linux/of_gpio.h> +#include <linux/platform_data/atmel.h>  #include <asm/byteorder.h>  #include <mach/hardware.h> @@ -38,7 +39,6 @@  #include <asm/irq.h>  #include <asm/gpio.h> -#include <mach/board.h>  #include <mach/cpu.h>  #include <mach/at91sam9261_matrix.h>  #include <mach/at91_matrix.h> @@ -1673,7 +1673,7 @@ static void at91udc_shutdown(struct platform_device *dev)  	spin_unlock_irqrestore(&udc->lock, flags);  } -static void __devinit at91udc_of_init(struct at91_udc *udc, +static void at91udc_of_init(struct at91_udc *udc,  				     struct device_node *np)  {  	struct at91_udc_data *board = &udc->board; @@ -1693,7 +1693,7 @@ static void __devinit at91udc_of_init(struct at91_udc *udc,  	board->pullup_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;  } -static int __devinit at91udc_probe(struct platform_device *pdev) +static int at91udc_probe(struct platform_device *pdev)  {  	struct device	*dev = &pdev->dev;  	struct at91_udc	*udc; diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 9a9bced813e..a7aed84d98c 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -21,9 +21,9 @@  #include <linux/usb/gadget.h>  #include <linux/usb/atmel_usba_udc.h>  #include <linux/delay.h> +#include <linux/platform_data/atmel.h>  #include <asm/gpio.h> -#include <mach/board.h>  #include "atmel_usba_udc.h" diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c index 9ca792224cd..47a49931361 100644 --- a/drivers/usb/gadget/bcm63xx_udc.c +++ b/drivers/usb/gadget/bcm63xx_udc.c @@ -2323,7 +2323,7 @@ static void bcm63xx_udc_gadget_release(struct device *dev)   * Note that platform data is required, because pd.port_no varies from chip   * to chip and is used to switch the correct USB port to device mode.   */ -static int __devinit bcm63xx_udc_probe(struct platform_device *pdev) +static int bcm63xx_udc_probe(struct platform_device *pdev)  {  	struct device *dev = &pdev->dev;  	struct bcm63xx_usbd_platform_data *pd = dev->platform_data; @@ -2433,7 +2433,7 @@ out_uninit:   * bcm63xx_udc_remove - Remove the device from the system.   * @pdev: Platform device struct from the bcm63xx BSP code.   */ -static int __devexit bcm63xx_udc_remove(struct platform_device *pdev) +static int bcm63xx_udc_remove(struct platform_device *pdev)  {  	struct bcm63xx_udc *udc = platform_get_drvdata(pdev); @@ -2450,7 +2450,7 @@ static int __devexit bcm63xx_udc_remove(struct platform_device *pdev)  static struct platform_driver bcm63xx_udc_driver = {  	.probe		= bcm63xx_udc_probe, -	.remove		= __devexit_p(bcm63xx_udc_remove), +	.remove		= bcm63xx_udc_remove,  	.driver		= {  		.name	= DRV_MODULE_NAME,  		.owner	= THIS_MODULE, diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 957f973dd96..2a6bfe759c2 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -107,7 +107,7 @@ int config_ep_by_speed(struct usb_gadget *g,  		}  		/* else: fall through */  	default: -		speed_desc = f->descriptors; +		speed_desc = f->fs_descriptors;  	}  	/* find descriptors */  	for_each_ep_desc(speed_desc, d_spd) { @@ -200,7 +200,7 @@ int usb_add_function(struct usb_configuration *config,  	 * as full speed ... it's the function drivers that will need  	 * to avoid bulk and ISO transfers.  	 */ -	if (!config->fullspeed && function->descriptors) +	if (!config->fullspeed && function->fs_descriptors)  		config->fullspeed = true;  	if (!config->highspeed && function->hs_descriptors)  		config->highspeed = true; @@ -363,7 +363,7 @@ static int config_buf(struct usb_configuration *config,  			descriptors = f->hs_descriptors;  			break;  		default: -			descriptors = f->descriptors; +			descriptors = f->fs_descriptors;  		}  		if (!descriptors) @@ -620,7 +620,7 @@ static int set_config(struct usb_composite_dev *cdev,  			descriptors = f->hs_descriptors;  			break;  		default: -			descriptors = f->descriptors; +			descriptors = f->fs_descriptors;  		}  		for (; *descriptors; ++descriptors) { diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c index e3a98929d34..34e12fc52c2 100644 --- a/drivers/usb/gadget/config.c +++ b/drivers/usb/gadget/config.c @@ -19,7 +19,7 @@  #include <linux/usb/ch9.h>  #include <linux/usb/gadget.h> - +#include <linux/usb/composite.h>  /**   * usb_descriptor_fillbuf - fill buffer with descriptors @@ -158,3 +158,40 @@ usb_copy_descriptors(struct usb_descriptor_header **src)  	return ret;  }  EXPORT_SYMBOL_GPL(usb_copy_descriptors); + +int usb_assign_descriptors(struct usb_function *f, +		struct usb_descriptor_header **fs, +		struct usb_descriptor_header **hs, +		struct usb_descriptor_header **ss) +{ +	struct usb_gadget *g = f->config->cdev->gadget; + +	if (fs) { +		f->fs_descriptors = usb_copy_descriptors(fs); +		if (!f->fs_descriptors) +			goto err; +	} +	if (hs && gadget_is_dualspeed(g)) { +		f->hs_descriptors = usb_copy_descriptors(hs); +		if (!f->hs_descriptors) +			goto err; +	} +	if (ss && gadget_is_superspeed(g)) { +		f->ss_descriptors = usb_copy_descriptors(ss); +		if (!f->ss_descriptors) +			goto err; +	} +	return 0; +err: +	usb_free_all_descriptors(f); +	return -ENOMEM; +} +EXPORT_SYMBOL_GPL(usb_assign_descriptors); + +void usb_free_all_descriptors(struct usb_function *f) +{ +	usb_free_descriptors(f->fs_descriptors); +	usb_free_descriptors(f->hs_descriptors); +	usb_free_descriptors(f->ss_descriptors); +} +EXPORT_SYMBOL_GPL(usb_free_all_descriptors); diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 0f7541be28f..95d584dbed1 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -63,16 +63,20 @@ MODULE_LICENSE("GPL");  struct dummy_hcd_module_parameters {  	bool is_super_speed;  	bool is_high_speed; +	unsigned int num;  };  static struct dummy_hcd_module_parameters mod_data = {  	.is_super_speed = false,  	.is_high_speed = true, +	.num = 1,  };  module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO);  MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection");  module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO);  MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection"); +module_param_named(num, mod_data.num, uint, S_IRUGO); +MODULE_PARM_DESC(num, "number of emulated controllers");  /*-------------------------------------------------------------------------*/  /* gadget side driver data structres */ @@ -238,8 +242,6 @@ static inline struct dummy *gadget_dev_to_dummy(struct device *dev)  	return container_of(dev, struct dummy, gadget.dev);  } -static struct dummy			the_controller; -  /*-------------------------------------------------------------------------*/  /* SLAVE/GADGET SIDE UTILITY ROUTINES */ @@ -973,9 +975,10 @@ static void init_dummy_udc_hw(struct dummy *dum)  static int dummy_udc_probe(struct platform_device *pdev)  { -	struct dummy	*dum = &the_controller; +	struct dummy	*dum;  	int		rc; +	dum = *((void **)dev_get_platdata(&pdev->dev));  	dum->gadget.name = gadget_name;  	dum->gadget.ops = &dummy_ops;  	dum->gadget.max_speed = USB_SPEED_SUPER; @@ -2398,10 +2401,13 @@ static int dummy_h_get_frame(struct usb_hcd *hcd)  static int dummy_setup(struct usb_hcd *hcd)  { +	struct dummy *dum; + +	dum = *((void **)dev_get_platdata(hcd->self.controller));  	hcd->self.sg_tablesize = ~0;  	if (usb_hcd_is_primary_hcd(hcd)) { -		the_controller.hs_hcd = hcd_to_dummy_hcd(hcd); -		the_controller.hs_hcd->dum = &the_controller; +		dum->hs_hcd = hcd_to_dummy_hcd(hcd); +		dum->hs_hcd->dum = dum;  		/*  		 * Mark the first roothub as being USB 2.0.  		 * The USB 3.0 roothub will be registered later by @@ -2410,8 +2416,8 @@ static int dummy_setup(struct usb_hcd *hcd)  		hcd->speed = HCD_USB2;  		hcd->self.root_hub->speed = USB_SPEED_HIGH;  	} else { -		the_controller.ss_hcd = hcd_to_dummy_hcd(hcd); -		the_controller.ss_hcd->dum = &the_controller; +		dum->ss_hcd = hcd_to_dummy_hcd(hcd); +		dum->ss_hcd->dum = dum;  		hcd->speed = HCD_USB3;  		hcd->self.root_hub->speed = USB_SPEED_SUPER;  	} @@ -2524,11 +2530,13 @@ static struct hc_driver dummy_hcd = {  static int dummy_hcd_probe(struct platform_device *pdev)  { +	struct dummy		*dum;  	struct usb_hcd		*hs_hcd;  	struct usb_hcd		*ss_hcd;  	int			retval;  	dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); +	dum = *((void **)dev_get_platdata(&pdev->dev));  	if (!mod_data.is_super_speed)  		dummy_hcd.flags = HCD_USB2; @@ -2561,7 +2569,7 @@ dealloc_usb2_hcd:  	usb_remove_hcd(hs_hcd);  put_usb2_hcd:  	usb_put_hcd(hs_hcd); -	the_controller.hs_hcd = the_controller.ss_hcd = NULL; +	dum->hs_hcd = dum->ss_hcd = NULL;  	return retval;  } @@ -2579,8 +2587,8 @@ static int dummy_hcd_remove(struct platform_device *pdev)  	usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd));  	usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd)); -	the_controller.hs_hcd = NULL; -	the_controller.ss_hcd = NULL; +	dum->hs_hcd = NULL; +	dum->ss_hcd = NULL;  	return 0;  } @@ -2627,13 +2635,15 @@ static struct platform_driver dummy_hcd_driver = {  };  /*-------------------------------------------------------------------------*/ - -static struct platform_device *the_udc_pdev; -static struct platform_device *the_hcd_pdev; +#define MAX_NUM_UDC	2 +static struct platform_device *the_udc_pdev[MAX_NUM_UDC]; +static struct platform_device *the_hcd_pdev[MAX_NUM_UDC];  static int __init init(void)  {  	int	retval = -ENOMEM; +	int	i; +	struct	dummy *dum[MAX_NUM_UDC];  	if (usb_disabled())  		return -ENODEV; @@ -2641,65 +2651,129 @@ static int __init init(void)  	if (!mod_data.is_high_speed && mod_data.is_super_speed)  		return -EINVAL; -	the_hcd_pdev = platform_device_alloc(driver_name, -1); -	if (!the_hcd_pdev) -		return retval; -	the_udc_pdev = platform_device_alloc(gadget_name, -1); -	if (!the_udc_pdev) -		goto err_alloc_udc; +	if (mod_data.num < 1 || mod_data.num > MAX_NUM_UDC) { +		pr_err("Number of emulated UDC must be in range of 1…%d\n", +				MAX_NUM_UDC); +		return -EINVAL; +	} + +	for (i = 0; i < mod_data.num; i++) { +		the_hcd_pdev[i] = platform_device_alloc(driver_name, i); +		if (!the_hcd_pdev[i]) { +			i--; +			while (i >= 0) +				platform_device_put(the_hcd_pdev[i--]); +			return retval; +		} +	} +	for (i = 0; i < mod_data.num; i++) { +		the_udc_pdev[i] = platform_device_alloc(gadget_name, i); +		if (!the_udc_pdev[i]) { +			i--; +			while (i >= 0) +				platform_device_put(the_udc_pdev[i--]); +			goto err_alloc_udc; +		} +	} +	for (i = 0; i < mod_data.num; i++) { +		dum[i] = kzalloc(sizeof(struct dummy), GFP_KERNEL); +		if (!dum[i]) +			goto err_add_pdata; +		retval = platform_device_add_data(the_hcd_pdev[i], &dum[i], +				sizeof(void *)); +		if (retval) +			goto err_add_pdata; +		retval = platform_device_add_data(the_udc_pdev[i], &dum[i], +				sizeof(void *)); +		if (retval) +			goto err_add_pdata; +	}  	retval = platform_driver_register(&dummy_hcd_driver);  	if (retval < 0) -		goto err_register_hcd_driver; +		goto err_add_pdata;  	retval = platform_driver_register(&dummy_udc_driver);  	if (retval < 0)  		goto err_register_udc_driver; -	retval = platform_device_add(the_hcd_pdev); -	if (retval < 0) -		goto err_add_hcd; -	if (!the_controller.hs_hcd || -	    (!the_controller.ss_hcd && mod_data.is_super_speed)) { -		/* -		 * The hcd was added successfully but its probe function failed -		 * for some reason. -		 */ -		retval = -EINVAL; -		goto err_add_udc; +	for (i = 0; i < mod_data.num; i++) { +		retval = platform_device_add(the_hcd_pdev[i]); +		if (retval < 0) { +			i--; +			while (i >= 0) +				platform_device_del(the_hcd_pdev[i--]); +			goto err_add_hcd; +		}  	} -	retval = platform_device_add(the_udc_pdev); -	if (retval < 0) -		goto err_add_udc; -	if (!platform_get_drvdata(the_udc_pdev)) { -		/* -		 * The udc was added successfully but its probe function failed -		 * for some reason. -		 */ -		retval = -EINVAL; -		goto err_probe_udc; +	for (i = 0; i < mod_data.num; i++) { +		if (!dum[i]->hs_hcd || +				(!dum[i]->ss_hcd && mod_data.is_super_speed)) { +			/* +			 * The hcd was added successfully but its probe +			 * function failed for some reason. +			 */ +			retval = -EINVAL; +			goto err_add_udc; +		} +	} + +	for (i = 0; i < mod_data.num; i++) { +		retval = platform_device_add(the_udc_pdev[i]); +		if (retval < 0) { +			i--; +			while (i >= 0) +				platform_device_del(the_udc_pdev[i]); +			goto err_add_udc; +		} +	} + +	for (i = 0; i < mod_data.num; i++) { +		if (!platform_get_drvdata(the_udc_pdev[i])) { +			/* +			 * The udc was added successfully but its probe +			 * function failed for some reason. +			 */ +			retval = -EINVAL; +			goto err_probe_udc; +		}  	}  	return retval;  err_probe_udc: -	platform_device_del(the_udc_pdev); +	for (i = 0; i < mod_data.num; i++) +		platform_device_del(the_udc_pdev[i]);  err_add_udc: -	platform_device_del(the_hcd_pdev); +	for (i = 0; i < mod_data.num; i++) +		platform_device_del(the_hcd_pdev[i]);  err_add_hcd:  	platform_driver_unregister(&dummy_udc_driver);  err_register_udc_driver:  	platform_driver_unregister(&dummy_hcd_driver); -err_register_hcd_driver: -	platform_device_put(the_udc_pdev); +err_add_pdata: +	for (i = 0; i < mod_data.num; i++) +		kfree(dum[i]); +	for (i = 0; i < mod_data.num; i++) +		platform_device_put(the_udc_pdev[i]);  err_alloc_udc: -	platform_device_put(the_hcd_pdev); +	for (i = 0; i < mod_data.num; i++) +		platform_device_put(the_hcd_pdev[i]);  	return retval;  }  module_init(init);  static void __exit cleanup(void)  { -	platform_device_unregister(the_udc_pdev); -	platform_device_unregister(the_hcd_pdev); +	int i; + +	for (i = 0; i < mod_data.num; i++) { +		struct dummy *dum; + +		dum = *((void **)dev_get_platdata(&the_udc_pdev[i]->dev)); + +		platform_device_unregister(the_udc_pdev[i]); +		platform_device_unregister(the_hcd_pdev[i]); +		kfree(dum); +	}  	platform_driver_unregister(&dummy_udc_driver);  	platform_driver_unregister(&dummy_hcd_driver);  } diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index d672250a61f..549174466c2 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -87,7 +87,7 @@ static inline struct f_acm *port_to_acm(struct gserial *p)  /* notification endpoint uses smallish and infrequent fixed-size messages */ -#define GS_LOG2_NOTIFY_INTERVAL		5	/* 1 << 5 == 32 msec */ +#define GS_NOTIFY_INTERVAL_MS		32  #define GS_NOTIFY_MAXPACKET		10	/* notification + 2 bytes */  /* interface and class descriptors: */ @@ -167,7 +167,7 @@ static struct usb_endpoint_descriptor acm_fs_notify_desc = {  	.bEndpointAddress =	USB_DIR_IN,  	.bmAttributes =		USB_ENDPOINT_XFER_INT,  	.wMaxPacketSize =	cpu_to_le16(GS_NOTIFY_MAXPACKET), -	.bInterval =		1 << GS_LOG2_NOTIFY_INTERVAL, +	.bInterval =		GS_NOTIFY_INTERVAL_MS,  };  static struct usb_endpoint_descriptor acm_fs_in_desc = { @@ -199,14 +199,13 @@ static struct usb_descriptor_header *acm_fs_function[] = {  };  /* high speed support: */ -  static struct usb_endpoint_descriptor acm_hs_notify_desc = {  	.bLength =		USB_DT_ENDPOINT_SIZE,  	.bDescriptorType =	USB_DT_ENDPOINT,  	.bEndpointAddress =	USB_DIR_IN,  	.bmAttributes =		USB_ENDPOINT_XFER_INT,  	.wMaxPacketSize =	cpu_to_le16(GS_NOTIFY_MAXPACKET), -	.bInterval =		GS_LOG2_NOTIFY_INTERVAL+4, +	.bInterval =		USB_MS_TO_HS_INTERVAL(GS_NOTIFY_INTERVAL_MS),  };  static struct usb_endpoint_descriptor acm_hs_in_desc = { @@ -659,37 +658,22 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)  	acm->notify_req->complete = acm_cdc_notify_complete;  	acm->notify_req->context = acm; -	/* copy descriptors */ -	f->descriptors = usb_copy_descriptors(acm_fs_function); -	if (!f->descriptors) -		goto fail; -  	/* support all relevant hardware speeds... we expect that when  	 * hardware is dual speed, all bulk-capable endpoints work at  	 * both speeds  	 */ -	if (gadget_is_dualspeed(c->cdev->gadget)) { -		acm_hs_in_desc.bEndpointAddress = -				acm_fs_in_desc.bEndpointAddress; -		acm_hs_out_desc.bEndpointAddress = -				acm_fs_out_desc.bEndpointAddress; -		acm_hs_notify_desc.bEndpointAddress = -				acm_fs_notify_desc.bEndpointAddress; - -		/* copy descriptors */ -		f->hs_descriptors = usb_copy_descriptors(acm_hs_function); -	} -	if (gadget_is_superspeed(c->cdev->gadget)) { -		acm_ss_in_desc.bEndpointAddress = -			acm_fs_in_desc.bEndpointAddress; -		acm_ss_out_desc.bEndpointAddress = -			acm_fs_out_desc.bEndpointAddress; - -		/* copy descriptors, and track endpoint copies */ -		f->ss_descriptors = usb_copy_descriptors(acm_ss_function); -		if (!f->ss_descriptors) -			goto fail; -	} +	acm_hs_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress; +	acm_hs_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress; +	acm_hs_notify_desc.bEndpointAddress = +		acm_fs_notify_desc.bEndpointAddress; + +	acm_ss_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress; +	acm_ss_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress; + +	status = usb_assign_descriptors(f, acm_fs_function, acm_hs_function, +			acm_ss_function); +	if (status) +		goto fail;  	DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",  			acm->port_num, @@ -721,11 +705,8 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)  {  	struct f_acm		*acm = func_to_acm(f); -	if (gadget_is_dualspeed(c->cdev->gadget)) -		usb_free_descriptors(f->hs_descriptors); -	if (gadget_is_superspeed(c->cdev->gadget)) -		usb_free_descriptors(f->ss_descriptors); -	usb_free_descriptors(f->descriptors); +	acm_string_defs[0].id = 0; +	usb_free_all_descriptors(f);  	gs_free_req(acm->notify, acm->notify_req);  	kfree(acm);  } @@ -762,27 +743,15 @@ int acm_bind_config(struct usb_configuration *c, u8 port_num)  	 */  	/* maybe allocate device-global string IDs, and patch descriptors */ -	if (acm_string_defs[ACM_CTRL_IDX].id == 0) { -		status = usb_string_id(c->cdev); +	if (acm_string_defs[0].id == 0) { +		status = usb_string_ids_tab(c->cdev, acm_string_defs);  		if (status < 0)  			return status; -		acm_string_defs[ACM_CTRL_IDX].id = status; - -		acm_control_interface_desc.iInterface = status; - -		status = usb_string_id(c->cdev); -		if (status < 0) -			return status; -		acm_string_defs[ACM_DATA_IDX].id = status; - -		acm_data_interface_desc.iInterface = status; - -		status = usb_string_id(c->cdev); -		if (status < 0) -			return status; -		acm_string_defs[ACM_IAD_IDX].id = status; - -		acm_iad_descriptor.iFunction = status; +		acm_control_interface_desc.iInterface = +			acm_string_defs[ACM_CTRL_IDX].id; +		acm_data_interface_desc.iInterface = +			acm_string_defs[ACM_DATA_IDX].id; +		acm_iad_descriptor.iFunction = acm_string_defs[ACM_IAD_IDX].id;  	}  	/* allocate and initialize one new instance */ diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index 95bc94f8e57..83420a310fb 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -91,7 +91,7 @@ static inline unsigned ecm_bitrate(struct usb_gadget *g)   * encapsulated commands (vendor-specific, using control-OUT).   */ -#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */ +#define ECM_STATUS_INTERVAL_MS		32  #define ECM_STATUS_BYTECOUNT		16	/* 8 byte header + data */ @@ -192,7 +192,7 @@ static struct usb_endpoint_descriptor fs_ecm_notify_desc = {  	.bEndpointAddress =	USB_DIR_IN,  	.bmAttributes =		USB_ENDPOINT_XFER_INT,  	.wMaxPacketSize =	cpu_to_le16(ECM_STATUS_BYTECOUNT), -	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC, +	.bInterval =		ECM_STATUS_INTERVAL_MS,  };  static struct usb_endpoint_descriptor fs_ecm_in_desc = { @@ -239,7 +239,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc = {  	.bEndpointAddress =	USB_DIR_IN,  	.bmAttributes =		USB_ENDPOINT_XFER_INT,  	.wMaxPacketSize =	cpu_to_le16(ECM_STATUS_BYTECOUNT), -	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4, +	.bInterval =		USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),  };  static struct usb_endpoint_descriptor hs_ecm_in_desc = { @@ -288,7 +288,7 @@ static struct usb_endpoint_descriptor ss_ecm_notify_desc = {  	.bEndpointAddress =	USB_DIR_IN,  	.bmAttributes =		USB_ENDPOINT_XFER_INT,  	.wMaxPacketSize =	cpu_to_le16(ECM_STATUS_BYTECOUNT), -	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4, +	.bInterval =		USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),  };  static struct usb_ss_ep_comp_descriptor ss_ecm_intr_comp_desc = { @@ -330,6 +330,7 @@ static struct usb_ss_ep_comp_descriptor ss_ecm_bulk_comp_desc = {  static struct usb_descriptor_header *ecm_ss_function[] = {  	/* CDC ECM control descriptors */ +	(struct usb_descriptor_header *) &ecm_iad_descriptor,  	(struct usb_descriptor_header *) &ecm_control_intf,  	(struct usb_descriptor_header *) &ecm_header_desc,  	(struct usb_descriptor_header *) &ecm_union_desc, @@ -353,7 +354,7 @@ static struct usb_descriptor_header *ecm_ss_function[] = {  static struct usb_string ecm_string_defs[] = {  	[0].s = "CDC Ethernet Control Model (ECM)", -	[1].s = NULL /* DYNAMIC */, +	[1].s = "",  	[2].s = "CDC Ethernet Data",  	[3].s = "CDC ECM",  	{  } /* end of list */ @@ -742,42 +743,24 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)  	ecm->notify_req->context = ecm;  	ecm->notify_req->complete = ecm_notify_complete; -	/* copy descriptors, and track endpoint copies */ -	f->descriptors = usb_copy_descriptors(ecm_fs_function); -	if (!f->descriptors) -		goto fail; -  	/* support all relevant hardware speeds... we expect that when  	 * hardware is dual speed, all bulk-capable endpoints work at  	 * both speeds  	 */ -	if (gadget_is_dualspeed(c->cdev->gadget)) { -		hs_ecm_in_desc.bEndpointAddress = -				fs_ecm_in_desc.bEndpointAddress; -		hs_ecm_out_desc.bEndpointAddress = -				fs_ecm_out_desc.bEndpointAddress; -		hs_ecm_notify_desc.bEndpointAddress = -				fs_ecm_notify_desc.bEndpointAddress; - -		/* copy descriptors, and track endpoint copies */ -		f->hs_descriptors = usb_copy_descriptors(ecm_hs_function); -		if (!f->hs_descriptors) -			goto fail; -	} - -	if (gadget_is_superspeed(c->cdev->gadget)) { -		ss_ecm_in_desc.bEndpointAddress = -				fs_ecm_in_desc.bEndpointAddress; -		ss_ecm_out_desc.bEndpointAddress = -				fs_ecm_out_desc.bEndpointAddress; -		ss_ecm_notify_desc.bEndpointAddress = -				fs_ecm_notify_desc.bEndpointAddress; - -		/* copy descriptors, and track endpoint copies */ -		f->ss_descriptors = usb_copy_descriptors(ecm_ss_function); -		if (!f->ss_descriptors) -			goto fail; -	} +	hs_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress; +	hs_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress; +	hs_ecm_notify_desc.bEndpointAddress = +		fs_ecm_notify_desc.bEndpointAddress; + +	ss_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress; +	ss_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress; +	ss_ecm_notify_desc.bEndpointAddress = +		fs_ecm_notify_desc.bEndpointAddress; + +	status = usb_assign_descriptors(f, ecm_fs_function, ecm_hs_function, +			ecm_ss_function); +	if (status) +		goto fail;  	/* NOTE:  all that is done without knowing or caring about  	 * the network link ... which is unavailable to this code @@ -795,11 +778,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)  	return 0;  fail: -	if (f->descriptors) -		usb_free_descriptors(f->descriptors); -	if (f->hs_descriptors) -		usb_free_descriptors(f->hs_descriptors); -  	if (ecm->notify_req) {  		kfree(ecm->notify_req->buf);  		usb_ep_free_request(ecm->notify, ecm->notify_req); @@ -808,9 +786,9 @@ fail:  	/* we might as well release our claims on endpoints */  	if (ecm->notify)  		ecm->notify->driver_data = NULL; -	if (ecm->port.out_ep->desc) +	if (ecm->port.out_ep)  		ecm->port.out_ep->driver_data = NULL; -	if (ecm->port.in_ep->desc) +	if (ecm->port.in_ep)  		ecm->port.in_ep->driver_data = NULL;  	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); @@ -825,16 +803,11 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)  	DBG(c->cdev, "ecm unbind\n"); -	if (gadget_is_superspeed(c->cdev->gadget)) -		usb_free_descriptors(f->ss_descriptors); -	if (gadget_is_dualspeed(c->cdev->gadget)) -		usb_free_descriptors(f->hs_descriptors); -	usb_free_descriptors(f->descriptors); +	ecm_string_defs[0].id = 0; +	usb_free_all_descriptors(f);  	kfree(ecm->notify_req->buf);  	usb_ep_free_request(ecm->notify, ecm->notify_req); - -	ecm_string_defs[1].s = NULL;  	kfree(ecm);  } @@ -859,36 +832,15 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])  	if (!can_support_ecm(c->cdev->gadget) || !ethaddr)  		return -EINVAL; -	/* maybe allocate device-global string IDs */  	if (ecm_string_defs[0].id == 0) { - -		/* control interface label */ -		status = usb_string_id(c->cdev); -		if (status < 0) -			return status; -		ecm_string_defs[0].id = status; -		ecm_control_intf.iInterface = status; - -		/* data interface label */ -		status = usb_string_id(c->cdev); -		if (status < 0) +		status = usb_string_ids_tab(c->cdev, ecm_string_defs); +		if (status)  			return status; -		ecm_string_defs[2].id = status; -		ecm_data_intf.iInterface = status; -		/* MAC address */ -		status = usb_string_id(c->cdev); -		if (status < 0) -			return status; -		ecm_string_defs[1].id = status; -		ecm_desc.iMACAddress = status; - -		/* IAD label */ -		status = usb_string_id(c->cdev); -		if (status < 0) -			return status; -		ecm_string_defs[3].id = status; -		ecm_iad_descriptor.iFunction = status; +		ecm_control_intf.iInterface = ecm_string_defs[0].id; +		ecm_data_intf.iInterface = ecm_string_defs[2].id; +		ecm_desc.iMACAddress = ecm_string_defs[1].id; +		ecm_iad_descriptor.iFunction = ecm_string_defs[3].id;  	}  	/* allocate and initialize one new instance */ @@ -913,9 +865,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])  	ecm->port.func.disable = ecm_disable;  	status = usb_add_function(c, &ecm->port.func); -	if (status) { -		ecm_string_defs[1].s = NULL; +	if (status)  		kfree(ecm); -	}  	return status;  } diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c index 1a7b2dd7d40..cf0ebee8556 100644 --- a/drivers/usb/gadget/f_eem.c +++ b/drivers/usb/gadget/f_eem.c @@ -274,38 +274,20 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)  	status = -ENOMEM; -	/* copy descriptors, and track endpoint copies */ -	f->descriptors = usb_copy_descriptors(eem_fs_function); -	if (!f->descriptors) -		goto fail; -  	/* support all relevant hardware speeds... we expect that when  	 * hardware is dual speed, all bulk-capable endpoints work at  	 * both speeds  	 */ -	if (gadget_is_dualspeed(c->cdev->gadget)) { -		eem_hs_in_desc.bEndpointAddress = -				eem_fs_in_desc.bEndpointAddress; -		eem_hs_out_desc.bEndpointAddress = -				eem_fs_out_desc.bEndpointAddress; - -		/* copy descriptors, and track endpoint copies */ -		f->hs_descriptors = usb_copy_descriptors(eem_hs_function); -		if (!f->hs_descriptors) -			goto fail; -	} +	eem_hs_in_desc.bEndpointAddress = eem_fs_in_desc.bEndpointAddress; +	eem_hs_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress; -	if (gadget_is_superspeed(c->cdev->gadget)) { -		eem_ss_in_desc.bEndpointAddress = -				eem_fs_in_desc.bEndpointAddress; -		eem_ss_out_desc.bEndpointAddress = -				eem_fs_out_desc.bEndpointAddress; +	eem_ss_in_desc.bEndpointAddress = eem_fs_in_desc.bEndpointAddress; +	eem_ss_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress; -		/* copy descriptors, and track endpoint copies */ -		f->ss_descriptors = usb_copy_descriptors(eem_ss_function); -		if (!f->ss_descriptors) -			goto fail; -	} +	status = usb_assign_descriptors(f, eem_fs_function, eem_hs_function, +			eem_ss_function); +	if (status) +		goto fail;  	DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n",  			gadget_is_superspeed(c->cdev->gadget) ? "super" : @@ -314,15 +296,10 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)  	return 0;  fail: -	if (f->descriptors) -		usb_free_descriptors(f->descriptors); -	if (f->hs_descriptors) -		usb_free_descriptors(f->hs_descriptors); - -	/* we might as well release our claims on endpoints */ -	if (eem->port.out_ep->desc) +	usb_free_all_descriptors(f); +	if (eem->port.out_ep)  		eem->port.out_ep->driver_data = NULL; -	if (eem->port.in_ep->desc) +	if (eem->port.in_ep)  		eem->port.in_ep->driver_data = NULL;  	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); @@ -337,11 +314,7 @@ eem_unbind(struct usb_configuration *c, struct usb_function *f)  	DBG(c->cdev, "eem unbind\n"); -	if (gadget_is_superspeed(c->cdev->gadget)) -		usb_free_descriptors(f->ss_descriptors); -	if (gadget_is_dualspeed(c->cdev->gadget)) -		usb_free_descriptors(f->hs_descriptors); -	usb_free_descriptors(f->descriptors); +	usb_free_all_descriptors(f);  	kfree(eem);  } diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 64c4ec10d1f..4a6961c517f 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -2097,7 +2097,7 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,  	if (isHS)  		func->function.hs_descriptors[(long)valuep] = desc;  	else -		func->function.descriptors[(long)valuep]    = desc; +		func->function.fs_descriptors[(long)valuep]    = desc;  	if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT)  		return 0; @@ -2249,7 +2249,7 @@ static int ffs_func_bind(struct usb_configuration *c,  	 * numbers without worrying that it may be described later on.  	 */  	if (likely(full)) { -		func->function.descriptors = data->fs_descs; +		func->function.fs_descriptors = data->fs_descs;  		ret = ffs_do_descs(ffs->fs_descs_count,  				   data->raw_descs,  				   sizeof data->raw_descs, diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c index 511e527178e..6e69a8e8d22 100644 --- a/drivers/usb/gadget/f_hid.c +++ b/drivers/usb/gadget/f_hid.c @@ -573,7 +573,6 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)  		goto fail;  	hidg_interface_desc.bInterfaceNumber = status; -  	/* allocate instance-specific endpoints */  	status = -ENODEV;  	ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc); @@ -609,20 +608,15 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)  	hidg_desc.desc[0].wDescriptorLength =  		cpu_to_le16(hidg->report_desc_length); -	/* copy descriptors */ -	f->descriptors = usb_copy_descriptors(hidg_fs_descriptors); -	if (!f->descriptors) -		goto fail; +	hidg_hs_in_ep_desc.bEndpointAddress = +		hidg_fs_in_ep_desc.bEndpointAddress; +	hidg_hs_out_ep_desc.bEndpointAddress = +		hidg_fs_out_ep_desc.bEndpointAddress; -	if (gadget_is_dualspeed(c->cdev->gadget)) { -		hidg_hs_in_ep_desc.bEndpointAddress = -			hidg_fs_in_ep_desc.bEndpointAddress; -		hidg_hs_out_ep_desc.bEndpointAddress = -			hidg_fs_out_ep_desc.bEndpointAddress; -		f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors); -		if (!f->hs_descriptors) -			goto fail; -	} +	status = usb_assign_descriptors(f, hidg_fs_descriptors, +			hidg_hs_descriptors, NULL); +	if (status) +		goto fail;  	mutex_init(&hidg->lock);  	spin_lock_init(&hidg->spinlock); @@ -649,9 +643,7 @@ fail:  			usb_ep_free_request(hidg->in_ep, hidg->req);  	} -	usb_free_descriptors(f->hs_descriptors); -	usb_free_descriptors(f->descriptors); - +	usb_free_all_descriptors(f);  	return status;  } @@ -668,9 +660,7 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)  	kfree(hidg->req->buf);  	usb_ep_free_request(hidg->in_ep, hidg->req); -	/* free descriptors copies */ -	usb_free_descriptors(f->hs_descriptors); -	usb_free_descriptors(f->descriptors); +	usb_free_all_descriptors(f);  	kfree(hidg->report_desc);  	kfree(hidg); diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 7275706caeb..bb39cb2bb3a 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -177,6 +177,7 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)  	struct usb_composite_dev *cdev = c->cdev;  	struct f_loopback	*loop = func_to_loop(f);  	int			id; +	int ret;  	/* allocate interface ID(s) */  	id = usb_interface_id(c, f); @@ -201,22 +202,19 @@ autoconf_fail:  	loop->out_ep->driver_data = cdev;	/* claim */  	/* support high speed hardware */ -	if (gadget_is_dualspeed(c->cdev->gadget)) { -		hs_loop_source_desc.bEndpointAddress = -				fs_loop_source_desc.bEndpointAddress; -		hs_loop_sink_desc.bEndpointAddress = -				fs_loop_sink_desc.bEndpointAddress; -		f->hs_descriptors = hs_loopback_descs; -	} +	hs_loop_source_desc.bEndpointAddress = +		fs_loop_source_desc.bEndpointAddress; +	hs_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;  	/* support super speed hardware */ -	if (gadget_is_superspeed(c->cdev->gadget)) { -		ss_loop_source_desc.bEndpointAddress = -				fs_loop_source_desc.bEndpointAddress; -		ss_loop_sink_desc.bEndpointAddress = -				fs_loop_sink_desc.bEndpointAddress; -		f->ss_descriptors = ss_loopback_descs; -	} +	ss_loop_source_desc.bEndpointAddress = +		fs_loop_source_desc.bEndpointAddress; +	ss_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress; + +	ret = usb_assign_descriptors(f, fs_loopback_descs, hs_loopback_descs, +			ss_loopback_descs); +	if (ret) +		return ret;  	DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",  	    (gadget_is_superspeed(c->cdev->gadget) ? "super" : @@ -228,6 +226,7 @@ autoconf_fail:  static void  loopback_unbind(struct usb_configuration *c, struct usb_function *f)  { +	usb_free_all_descriptors(f);  	kfree(func_to_loop(f));  } @@ -379,7 +378,6 @@ static int __init loopback_bind_config(struct usb_configuration *c)  		return -ENOMEM;  	loop->function.name = "loopback"; -	loop->function.descriptors = fs_loopback_descs;  	loop->function.bind = loopback_bind;  	loop->function.unbind = loopback_unbind;  	loop->function.set_alt = loopback_set_alt; diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 3a7668bde3e..5d027b3e1ef 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -228,10 +228,6 @@  static const char fsg_string_interface[] = "Mass Storage"; -#define FSG_NO_DEVICE_STRINGS    1 -#define FSG_NO_OTG               1 -#define FSG_NO_INTR_EP           1 -  #include "storage_common.c" @@ -2904,9 +2900,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)  	}  	fsg_common_put(common); -	usb_free_descriptors(fsg->function.descriptors); -	usb_free_descriptors(fsg->function.hs_descriptors); -	usb_free_descriptors(fsg->function.ss_descriptors); +	usb_free_all_descriptors(&fsg->function);  	kfree(fsg);  } @@ -2916,6 +2910,8 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)  	struct usb_gadget	*gadget = c->cdev->gadget;  	int			i;  	struct usb_ep		*ep; +	unsigned		max_burst; +	int			ret;  	fsg->gadget = gadget; @@ -2939,45 +2935,27 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)  	ep->driver_data = fsg->common;	/* claim the endpoint */  	fsg->bulk_out = ep; -	/* Copy descriptors */ -	f->descriptors = usb_copy_descriptors(fsg_fs_function); -	if (unlikely(!f->descriptors)) -		return -ENOMEM; - -	if (gadget_is_dualspeed(gadget)) { -		/* Assume endpoint addresses are the same for both speeds */ -		fsg_hs_bulk_in_desc.bEndpointAddress = -			fsg_fs_bulk_in_desc.bEndpointAddress; -		fsg_hs_bulk_out_desc.bEndpointAddress = -			fsg_fs_bulk_out_desc.bEndpointAddress; -		f->hs_descriptors = usb_copy_descriptors(fsg_hs_function); -		if (unlikely(!f->hs_descriptors)) { -			usb_free_descriptors(f->descriptors); -			return -ENOMEM; -		} -	} - -	if (gadget_is_superspeed(gadget)) { -		unsigned	max_burst; +	/* Assume endpoint addresses are the same for both speeds */ +	fsg_hs_bulk_in_desc.bEndpointAddress = +		fsg_fs_bulk_in_desc.bEndpointAddress; +	fsg_hs_bulk_out_desc.bEndpointAddress = +		fsg_fs_bulk_out_desc.bEndpointAddress; -		/* Calculate bMaxBurst, we know packet size is 1024 */ -		max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15); +	/* Calculate bMaxBurst, we know packet size is 1024 */ +	max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15); -		fsg_ss_bulk_in_desc.bEndpointAddress = -			fsg_fs_bulk_in_desc.bEndpointAddress; -		fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst; +	fsg_ss_bulk_in_desc.bEndpointAddress = +		fsg_fs_bulk_in_desc.bEndpointAddress; +	fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst; -		fsg_ss_bulk_out_desc.bEndpointAddress = -			fsg_fs_bulk_out_desc.bEndpointAddress; -		fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; +	fsg_ss_bulk_out_desc.bEndpointAddress = +		fsg_fs_bulk_out_desc.bEndpointAddress; +	fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; -		f->ss_descriptors = usb_copy_descriptors(fsg_ss_function); -		if (unlikely(!f->ss_descriptors)) { -			usb_free_descriptors(f->hs_descriptors); -			usb_free_descriptors(f->descriptors); -			return -ENOMEM; -		} -	} +	ret = usb_assign_descriptors(f, fsg_fs_function, fsg_hs_function, +			fsg_ss_function); +	if (ret) +		goto autoconf_fail;  	return 0; @@ -2986,7 +2964,6 @@ autoconf_fail:  	return -ENOTSUPP;  } -  /****************************** ADD FUNCTION ******************************/  static struct usb_gadget_strings *fsg_strings_array[] = { diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c index 8ed1259fe80..263e721c269 100644 --- a/drivers/usb/gadget/f_midi.c +++ b/drivers/usb/gadget/f_midi.c @@ -414,7 +414,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)  	kfree(midi->id);  	midi->id = NULL; -	usb_free_descriptors(f->descriptors); +	usb_free_all_descriptors(f);  	kfree(midi);  } @@ -881,19 +881,25 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)  	 * both speeds  	 */  	/* copy descriptors, and track endpoint copies */ +	f->fs_descriptors = usb_copy_descriptors(midi_function); +	if (!f->fs_descriptors) +		goto fail_f_midi; +  	if (gadget_is_dualspeed(c->cdev->gadget)) { -		c->highspeed = true;  		bulk_in_desc.wMaxPacketSize = cpu_to_le16(512);  		bulk_out_desc.wMaxPacketSize = cpu_to_le16(512);  		f->hs_descriptors = usb_copy_descriptors(midi_function); -	} else { -		f->descriptors = usb_copy_descriptors(midi_function); +		if (!f->hs_descriptors) +			goto fail_f_midi;  	}  	kfree(midi_function);  	return 0; +fail_f_midi: +	kfree(midi_function); +	usb_free_descriptors(f->hs_descriptors);  fail:  	/* we might as well release our claims on endpoints */  	if (midi->out_ep) diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c index b651b529c67..6c8362f937b 100644 --- a/drivers/usb/gadget/f_ncm.c +++ b/drivers/usb/gadget/f_ncm.c @@ -102,7 +102,7 @@ static inline unsigned ncm_bitrate(struct usb_gadget *g)  				 USB_CDC_NCM_NTB32_SUPPORTED)  static struct usb_cdc_ncm_ntb_parameters ntb_parameters = { -	.wLength = sizeof ntb_parameters, +	.wLength = cpu_to_le16(sizeof(ntb_parameters)),  	.bmNtbFormatsSupported = cpu_to_le16(FORMATS_SUPPORTED),  	.dwNtbInMaxSize = cpu_to_le32(NTB_DEFAULT_IN_SIZE),  	.wNdpInDivisor = cpu_to_le16(4), @@ -121,7 +121,7 @@ static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {   * waste less bandwidth.   */ -#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */ +#define NCM_STATUS_INTERVAL_MS		32  #define NCM_STATUS_BYTECOUNT		16	/* 8 byte header + data */  static struct usb_interface_assoc_descriptor ncm_iad_desc __initdata = { @@ -230,7 +230,7 @@ static struct usb_endpoint_descriptor fs_ncm_notify_desc __initdata = {  	.bEndpointAddress =	USB_DIR_IN,  	.bmAttributes =		USB_ENDPOINT_XFER_INT,  	.wMaxPacketSize =	cpu_to_le16(NCM_STATUS_BYTECOUNT), -	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC, +	.bInterval =		NCM_STATUS_INTERVAL_MS,  };  static struct usb_endpoint_descriptor fs_ncm_in_desc __initdata = { @@ -275,7 +275,7 @@ static struct usb_endpoint_descriptor hs_ncm_notify_desc __initdata = {  	.bEndpointAddress =	USB_DIR_IN,  	.bmAttributes =		USB_ENDPOINT_XFER_INT,  	.wMaxPacketSize =	cpu_to_le16(NCM_STATUS_BYTECOUNT), -	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4, +	.bInterval =		USB_MS_TO_HS_INTERVAL(NCM_STATUS_INTERVAL_MS),  };  static struct usb_endpoint_descriptor hs_ncm_in_desc __initdata = {  	.bLength =		USB_DT_ENDPOINT_SIZE, @@ -321,7 +321,7 @@ static struct usb_descriptor_header *ncm_hs_function[] __initdata = {  static struct usb_string ncm_string_defs[] = {  	[STRING_CTRL_IDX].s = "CDC Network Control Model (NCM)", -	[STRING_MAC_IDX].s = NULL /* DYNAMIC */, +	[STRING_MAC_IDX].s = "",  	[STRING_DATA_IDX].s = "CDC Network Data",  	[STRING_IAD_IDX].s = "CDC NCM",  	{  } /* end of list */ @@ -869,15 +869,19 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,  	struct sk_buff	*skb2;  	int		ncb_len = 0;  	__le16		*tmp; -	int		div = ntb_parameters.wNdpInDivisor; -	int		rem = ntb_parameters.wNdpInPayloadRemainder; +	int		div; +	int		rem;  	int		pad; -	int		ndp_align = ntb_parameters.wNdpInAlignment; +	int		ndp_align;  	int		ndp_pad;  	unsigned	max_size = ncm->port.fixed_in_len;  	struct ndp_parser_opts *opts = ncm->parser_opts;  	unsigned	crc_len = ncm->is_crc ? sizeof(uint32_t) : 0; +	div = le16_to_cpu(ntb_parameters.wNdpInDivisor); +	rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder); +	ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment); +  	ncb_len += opts->nth_size;  	ndp_pad = ALIGN(ncb_len, ndp_align) - ncb_len;  	ncb_len += ndp_pad; @@ -1208,30 +1212,18 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)  	ncm->notify_req->context = ncm;  	ncm->notify_req->complete = ncm_notify_complete; -	/* copy descriptors, and track endpoint copies */ -	f->descriptors = usb_copy_descriptors(ncm_fs_function); -	if (!f->descriptors) -		goto fail; -  	/*  	 * support all relevant hardware speeds... we expect that when  	 * hardware is dual speed, all bulk-capable endpoints work at  	 * both speeds  	 */ -	if (gadget_is_dualspeed(c->cdev->gadget)) { -		hs_ncm_in_desc.bEndpointAddress = -				fs_ncm_in_desc.bEndpointAddress; -		hs_ncm_out_desc.bEndpointAddress = -				fs_ncm_out_desc.bEndpointAddress; -		hs_ncm_notify_desc.bEndpointAddress = -				fs_ncm_notify_desc.bEndpointAddress; - -		/* copy descriptors, and track endpoint copies */ -		f->hs_descriptors = usb_copy_descriptors(ncm_hs_function); -		if (!f->hs_descriptors) -			goto fail; -	} +	hs_ncm_in_desc.bEndpointAddress = fs_ncm_in_desc.bEndpointAddress; +	hs_ncm_out_desc.bEndpointAddress = fs_ncm_out_desc.bEndpointAddress; +	hs_ncm_notify_desc.bEndpointAddress = +		fs_ncm_notify_desc.bEndpointAddress; +	status = usb_assign_descriptors(f, ncm_fs_function, ncm_hs_function, +			NULL);  	/*  	 * NOTE:  all that is done without knowing or caring about  	 * the network link ... which is unavailable to this code @@ -1248,9 +1240,7 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)  	return 0;  fail: -	if (f->descriptors) -		usb_free_descriptors(f->descriptors); - +	usb_free_all_descriptors(f);  	if (ncm->notify_req) {  		kfree(ncm->notify_req->buf);  		usb_ep_free_request(ncm->notify, ncm->notify_req); @@ -1259,9 +1249,9 @@ fail:  	/* we might as well release our claims on endpoints */  	if (ncm->notify)  		ncm->notify->driver_data = NULL; -	if (ncm->port.out_ep->desc) +	if (ncm->port.out_ep)  		ncm->port.out_ep->driver_data = NULL; -	if (ncm->port.in_ep->desc) +	if (ncm->port.in_ep)  		ncm->port.in_ep->driver_data = NULL;  	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); @@ -1276,14 +1266,12 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f)  	DBG(c->cdev, "ncm unbind\n"); -	if (gadget_is_dualspeed(c->cdev->gadget)) -		usb_free_descriptors(f->hs_descriptors); -	usb_free_descriptors(f->descriptors); +	ncm_string_defs[0].id = 0; +	usb_free_all_descriptors(f);  	kfree(ncm->notify_req->buf);  	usb_ep_free_request(ncm->notify, ncm->notify_req); -	ncm_string_defs[1].s = NULL;  	kfree(ncm);  } @@ -1307,37 +1295,19 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])  	if (!can_support_ecm(c->cdev->gadget) || !ethaddr)  		return -EINVAL; -	/* maybe allocate device-global string IDs */  	if (ncm_string_defs[0].id == 0) { - -		/* control interface label */ -		status = usb_string_id(c->cdev); +		status = usb_string_ids_tab(c->cdev, ncm_string_defs);  		if (status < 0)  			return status; -		ncm_string_defs[STRING_CTRL_IDX].id = status; -		ncm_control_intf.iInterface = status; +		ncm_control_intf.iInterface = +			ncm_string_defs[STRING_CTRL_IDX].id; -		/* data interface label */ -		status = usb_string_id(c->cdev); -		if (status < 0) -			return status; -		ncm_string_defs[STRING_DATA_IDX].id = status; +		status = ncm_string_defs[STRING_DATA_IDX].id;  		ncm_data_nop_intf.iInterface = status;  		ncm_data_intf.iInterface = status; -		/* MAC address */ -		status = usb_string_id(c->cdev); -		if (status < 0) -			return status; -		ncm_string_defs[STRING_MAC_IDX].id = status; -		ecm_desc.iMACAddress = status; - -		/* IAD */ -		status = usb_string_id(c->cdev); -		if (status < 0) -			return status; -		ncm_string_defs[STRING_IAD_IDX].id = status; -		ncm_iad_desc.iFunction = status; +		ecm_desc.iMACAddress = ncm_string_defs[STRING_MAC_IDX].id; +		ncm_iad_desc.iFunction = ncm_string_defs[STRING_IAD_IDX].id;  	}  	/* allocate and initialize one new instance */ @@ -1347,7 +1317,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])  	/* export host's Ethernet address in CDC format */  	snprintf(ncm->ethaddr, sizeof ncm->ethaddr, "%pm", ethaddr); -	ncm_string_defs[1].s = ncm->ethaddr; +	ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr;  	spin_lock_init(&ncm->lock);  	ncm_reset_values(ncm); @@ -1367,9 +1337,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])  	ncm->port.unwrap = ncm_unwrap_ntb;  	status = usb_add_function(c, &ncm->port.func); -	if (status) { -		ncm_string_defs[1].s = NULL; +	if (status)  		kfree(ncm); -	}  	return status;  } diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c index 5f400f66aa9..d8dd8782768 100644 --- a/drivers/usb/gadget/f_obex.c +++ b/drivers/usb/gadget/f_obex.c @@ -331,23 +331,19 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)  	obex->port.out = ep;  	ep->driver_data = cdev;	/* claim */ -	/* copy descriptors, and track endpoint copies */ -	f->descriptors = usb_copy_descriptors(fs_function); -  	/* support all relevant hardware speeds... we expect that when  	 * hardware is dual speed, all bulk-capable endpoints work at  	 * both speeds  	 */ -	if (gadget_is_dualspeed(c->cdev->gadget)) { -		obex_hs_ep_in_desc.bEndpointAddress = -				obex_fs_ep_in_desc.bEndpointAddress; -		obex_hs_ep_out_desc.bEndpointAddress = -				obex_fs_ep_out_desc.bEndpointAddress; +	obex_hs_ep_in_desc.bEndpointAddress = +		obex_fs_ep_in_desc.bEndpointAddress; +	obex_hs_ep_out_desc.bEndpointAddress = +		obex_fs_ep_out_desc.bEndpointAddress; -		/* copy descriptors, and track endpoint copies */ -		f->hs_descriptors = usb_copy_descriptors(hs_function); -	} +	status = usb_assign_descriptors(f, fs_function, hs_function, NULL); +	if (status) +		goto fail;  	/* Avoid letting this gadget enumerate until the userspace  	 * OBEX server is active. @@ -368,6 +364,7 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)  	return 0;  fail: +	usb_free_all_descriptors(f);  	/* we might as well release our claims on endpoints */  	if (obex->port.out)  		obex->port.out->driver_data = NULL; @@ -382,9 +379,8 @@ fail:  static void  obex_unbind(struct usb_configuration *c, struct usb_function *f)  { -	if (gadget_is_dualspeed(c->cdev->gadget)) -		usb_free_descriptors(f->hs_descriptors); -	usb_free_descriptors(f->descriptors); +	obex_string_defs[OBEX_CTRL_IDX].id = 0; +	usb_free_all_descriptors(f);  	kfree(func_to_obex(f));  } @@ -423,22 +419,16 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)  	if (!can_support_obex(c))  		return -EINVAL; -	/* maybe allocate device-global string IDs, and patch descriptors */  	if (obex_string_defs[OBEX_CTRL_IDX].id == 0) { -		status = usb_string_id(c->cdev); -		if (status < 0) -			return status; -		obex_string_defs[OBEX_CTRL_IDX].id = status; - -		obex_control_intf.iInterface = status; - -		status = usb_string_id(c->cdev); +		status = usb_string_ids_tab(c->cdev, obex_string_defs);  		if (status < 0)  			return status; -		obex_string_defs[OBEX_DATA_IDX].id = status; +		obex_control_intf.iInterface = +			obex_string_defs[OBEX_CTRL_IDX].id; -		obex_data_nop_intf.iInterface = -			obex_data_intf.iInterface = status; +		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 */ diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c index 8ee9268fe25..b21ab558b6c 100644 --- a/drivers/usb/gadget/f_phonet.c +++ b/drivers/usb/gadget/f_phonet.c @@ -515,14 +515,14 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)  	fp->in_ep = ep;  	ep->driver_data = fp; /* Claim */ -	pn_hs_sink_desc.bEndpointAddress = -		pn_fs_sink_desc.bEndpointAddress; -	pn_hs_source_desc.bEndpointAddress = -		pn_fs_source_desc.bEndpointAddress; +	pn_hs_sink_desc.bEndpointAddress = pn_fs_sink_desc.bEndpointAddress; +	pn_hs_source_desc.bEndpointAddress = pn_fs_source_desc.bEndpointAddress;  	/* Do not try to bind Phonet twice... */ -	fp->function.descriptors = fs_pn_function; -	fp->function.hs_descriptors = hs_pn_function; +	status = usb_assign_descriptors(f, fs_pn_function, hs_pn_function, +			NULL); +	if (status) +		goto err;  	/* Incoming USB requests */  	status = -ENOMEM; @@ -531,7 +531,7 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)  		req = usb_ep_alloc_request(fp->out_ep, GFP_KERNEL);  		if (!req) -			goto err; +			goto err_req;  		req->complete = pn_rx_complete;  		fp->out_reqv[i] = req; @@ -540,14 +540,18 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)  	/* Outgoing USB requests */  	fp->in_req = usb_ep_alloc_request(fp->in_ep, GFP_KERNEL);  	if (!fp->in_req) -		goto err; +		goto err_req;  	INFO(cdev, "USB CDC Phonet function\n");  	INFO(cdev, "using %s, OUT %s, IN %s\n", cdev->gadget->name,  		fp->out_ep->name, fp->in_ep->name);  	return 0; +err_req: +	for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++) +		usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);  err: +	usb_free_all_descriptors(f);  	if (fp->out_ep)  		fp->out_ep->driver_data = NULL;  	if (fp->in_ep) @@ -569,6 +573,7 @@ pn_unbind(struct usb_configuration *c, struct usb_function *f)  		if (fp->out_reqv[i])  			usb_ep_free_request(fp->out_ep, fp->out_reqv[i]); +	usb_free_all_descriptors(f);  	kfree(fp);  } diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index b1681e45aca..71beeb83355 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -101,7 +101,7 @@ static unsigned int bitrate(struct usb_gadget *g)  /*   */ -#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */ +#define RNDIS_STATUS_INTERVAL_MS	32  #define STATUS_BYTECOUNT		8	/* 8 bytes data */ @@ -190,7 +190,7 @@ static struct usb_endpoint_descriptor fs_notify_desc = {  	.bEndpointAddress =	USB_DIR_IN,  	.bmAttributes =		USB_ENDPOINT_XFER_INT,  	.wMaxPacketSize =	cpu_to_le16(STATUS_BYTECOUNT), -	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC, +	.bInterval =		RNDIS_STATUS_INTERVAL_MS,  };  static struct usb_endpoint_descriptor fs_in_desc = { @@ -236,7 +236,7 @@ static struct usb_endpoint_descriptor hs_notify_desc = {  	.bEndpointAddress =	USB_DIR_IN,  	.bmAttributes =		USB_ENDPOINT_XFER_INT,  	.wMaxPacketSize =	cpu_to_le16(STATUS_BYTECOUNT), -	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4, +	.bInterval =		USB_MS_TO_HS_INTERVAL(RNDIS_STATUS_INTERVAL_MS)  };  static struct usb_endpoint_descriptor hs_in_desc = { @@ -284,7 +284,7 @@ static struct usb_endpoint_descriptor ss_notify_desc = {  	.bEndpointAddress =	USB_DIR_IN,  	.bmAttributes =		USB_ENDPOINT_XFER_INT,  	.wMaxPacketSize =	cpu_to_le16(STATUS_BYTECOUNT), -	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4, +	.bInterval =		USB_MS_TO_HS_INTERVAL(RNDIS_STATUS_INTERVAL_MS)  };  static struct usb_ss_ep_comp_descriptor ss_intr_comp_desc = { @@ -722,42 +722,22 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)  	rndis->notify_req->context = rndis;  	rndis->notify_req->complete = rndis_response_complete; -	/* copy descriptors, and track endpoint copies */ -	f->descriptors = usb_copy_descriptors(eth_fs_function); -	if (!f->descriptors) -		goto fail; -  	/* support all relevant hardware speeds... we expect that when  	 * hardware is dual speed, all bulk-capable endpoints work at  	 * both speeds  	 */ -	if (gadget_is_dualspeed(c->cdev->gadget)) { -		hs_in_desc.bEndpointAddress = -				fs_in_desc.bEndpointAddress; -		hs_out_desc.bEndpointAddress = -				fs_out_desc.bEndpointAddress; -		hs_notify_desc.bEndpointAddress = -				fs_notify_desc.bEndpointAddress; - -		/* copy descriptors, and track endpoint copies */ -		f->hs_descriptors = usb_copy_descriptors(eth_hs_function); -		if (!f->hs_descriptors) -			goto fail; -	} +	hs_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress; +	hs_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress; +	hs_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress; -	if (gadget_is_superspeed(c->cdev->gadget)) { -		ss_in_desc.bEndpointAddress = -				fs_in_desc.bEndpointAddress; -		ss_out_desc.bEndpointAddress = -				fs_out_desc.bEndpointAddress; -		ss_notify_desc.bEndpointAddress = -				fs_notify_desc.bEndpointAddress; - -		/* copy descriptors, and track endpoint copies */ -		f->ss_descriptors = usb_copy_descriptors(eth_ss_function); -		if (!f->ss_descriptors) -			goto fail; -	} +	ss_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress; +	ss_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress; +	ss_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress; + +	status = usb_assign_descriptors(f, eth_fs_function, eth_hs_function, +			eth_ss_function); +	if (status) +		goto fail;  	rndis->port.open = rndis_open;  	rndis->port.close = rndis_close; @@ -788,12 +768,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)  	return 0;  fail: -	if (gadget_is_superspeed(c->cdev->gadget) && f->ss_descriptors) -		usb_free_descriptors(f->ss_descriptors); -	if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors) -		usb_free_descriptors(f->hs_descriptors); -	if (f->descriptors) -		usb_free_descriptors(f->descriptors); +	usb_free_all_descriptors(f);  	if (rndis->notify_req) {  		kfree(rndis->notify_req->buf); @@ -803,9 +778,9 @@ fail:  	/* we might as well release our claims on endpoints */  	if (rndis->notify)  		rndis->notify->driver_data = NULL; -	if (rndis->port.out_ep->desc) +	if (rndis->port.out_ep)  		rndis->port.out_ep->driver_data = NULL; -	if (rndis->port.in_ep->desc) +	if (rndis->port.in_ep)  		rndis->port.in_ep->driver_data = NULL;  	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); @@ -820,13 +795,9 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f)  	rndis_deregister(rndis->config);  	rndis_exit(); -	rndis_string_defs[0].id = 0; -	if (gadget_is_superspeed(c->cdev->gadget)) -		usb_free_descriptors(f->ss_descriptors); -	if (gadget_is_dualspeed(c->cdev->gadget)) -		usb_free_descriptors(f->hs_descriptors); -	usb_free_descriptors(f->descriptors); +	rndis_string_defs[0].id = 0; +	usb_free_all_descriptors(f);  	kfree(rndis->notify_req->buf);  	usb_ep_free_request(rndis->notify, rndis->notify_req); @@ -851,34 +822,19 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],  	if (!can_support_rndis(c) || !ethaddr)  		return -EINVAL; -	/* maybe allocate device-global string IDs */  	if (rndis_string_defs[0].id == 0) { -  		/* ... and setup RNDIS itself */  		status = rndis_init();  		if (status < 0)  			return status; -		/* control interface label */ -		status = usb_string_id(c->cdev); -		if (status < 0) +		status = usb_string_ids_tab(c->cdev, rndis_string_defs); +		if (status)  			return status; -		rndis_string_defs[0].id = status; -		rndis_control_intf.iInterface = status; -		/* data interface label */ -		status = usb_string_id(c->cdev); -		if (status < 0) -			return status; -		rndis_string_defs[1].id = status; -		rndis_data_intf.iInterface = status; - -		/* IAD iFunction label */ -		status = usb_string_id(c->cdev); -		if (status < 0) -			return status; -		rndis_string_defs[2].id = status; -		rndis_iad_descriptor.iFunction = status; +		rndis_control_intf.iInterface = rndis_string_defs[0].id; +		rndis_data_intf.iInterface = rndis_string_defs[1].id; +		rndis_iad_descriptor.iFunction = rndis_string_defs[2].id;  	}  	/* allocate and initialize one new instance */ diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index 07197d63d9b..98fa7795df5 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -213,34 +213,20 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)  	gser->port.out = ep;  	ep->driver_data = cdev;	/* claim */ -	/* copy descriptors, and track endpoint copies */ -	f->descriptors = usb_copy_descriptors(gser_fs_function); -  	/* support all relevant hardware speeds... we expect that when  	 * hardware is dual speed, all bulk-capable endpoints work at  	 * both speeds  	 */ -	if (gadget_is_dualspeed(c->cdev->gadget)) { -		gser_hs_in_desc.bEndpointAddress = -				gser_fs_in_desc.bEndpointAddress; -		gser_hs_out_desc.bEndpointAddress = -				gser_fs_out_desc.bEndpointAddress; - -		/* copy descriptors, and track endpoint copies */ -		f->hs_descriptors = usb_copy_descriptors(gser_hs_function); -	} -	if (gadget_is_superspeed(c->cdev->gadget)) { -		gser_ss_in_desc.bEndpointAddress = -			gser_fs_in_desc.bEndpointAddress; -		gser_ss_out_desc.bEndpointAddress = -			gser_fs_out_desc.bEndpointAddress; - -		/* copy descriptors, and track endpoint copies */ -		f->ss_descriptors = usb_copy_descriptors(gser_ss_function); -		if (!f->ss_descriptors) -			goto fail; -	} +	gser_hs_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress; +	gser_hs_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress; +	gser_ss_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress; +	gser_ss_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress; + +	status = usb_assign_descriptors(f, gser_fs_function, gser_hs_function, +			gser_ss_function); +	if (status) +		goto fail;  	DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",  			gser->port_num,  			gadget_is_superspeed(c->cdev->gadget) ? "super" : @@ -263,11 +249,7 @@ fail:  static void  gser_unbind(struct usb_configuration *c, struct usb_function *f)  { -	if (gadget_is_dualspeed(c->cdev->gadget)) -		usb_free_descriptors(f->hs_descriptors); -	if (gadget_is_superspeed(c->cdev->gadget)) -		usb_free_descriptors(f->ss_descriptors); -	usb_free_descriptors(f->descriptors); +	usb_free_all_descriptors(f);  	kfree(func_to_gser(f));  } diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index 3c126fde6e7..102d49beb9d 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -319,6 +319,7 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)  	struct usb_composite_dev *cdev = c->cdev;  	struct f_sourcesink	*ss = func_to_ss(f);  	int	id; +	int ret;  	/* allocate interface ID(s) */  	id = usb_interface_id(c, f); @@ -387,64 +388,57 @@ no_iso:  		isoc_maxpacket = 1024;  	/* support high speed hardware */ -	if (gadget_is_dualspeed(c->cdev->gadget)) { -		hs_source_desc.bEndpointAddress = -				fs_source_desc.bEndpointAddress; -		hs_sink_desc.bEndpointAddress = -				fs_sink_desc.bEndpointAddress; +	hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; +	hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; -		/* -		 * Fill in the HS isoc descriptors from the module parameters. -		 * We assume that the user knows what they are doing and won't -		 * give parameters that their UDC doesn't support. -		 */ -		hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket; -		hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11; -		hs_iso_source_desc.bInterval = isoc_interval; -		hs_iso_source_desc.bEndpointAddress = -				fs_iso_source_desc.bEndpointAddress; - -		hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket; -		hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11; -		hs_iso_sink_desc.bInterval = isoc_interval; -		hs_iso_sink_desc.bEndpointAddress = -				fs_iso_sink_desc.bEndpointAddress; - -		f->hs_descriptors = hs_source_sink_descs; -	} +	/* +	 * Fill in the HS isoc descriptors from the module parameters. +	 * We assume that the user knows what they are doing and won't +	 * give parameters that their UDC doesn't support. +	 */ +	hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket; +	hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11; +	hs_iso_source_desc.bInterval = isoc_interval; +	hs_iso_source_desc.bEndpointAddress = +		fs_iso_source_desc.bEndpointAddress; + +	hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket; +	hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11; +	hs_iso_sink_desc.bInterval = isoc_interval; +	hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;  	/* support super speed hardware */ -	if (gadget_is_superspeed(c->cdev->gadget)) { -		ss_source_desc.bEndpointAddress = -				fs_source_desc.bEndpointAddress; -		ss_sink_desc.bEndpointAddress = -				fs_sink_desc.bEndpointAddress; +	ss_source_desc.bEndpointAddress = +		fs_source_desc.bEndpointAddress; +	ss_sink_desc.bEndpointAddress = +		fs_sink_desc.bEndpointAddress; -		/* -		 * Fill in the SS isoc descriptors from the module parameters. -		 * We assume that the user knows what they are doing and won't -		 * give parameters that their UDC doesn't support. -		 */ -		ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket; -		ss_iso_source_desc.bInterval = isoc_interval; -		ss_iso_source_comp_desc.bmAttributes = isoc_mult; -		ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst; -		ss_iso_source_comp_desc.wBytesPerInterval = -			isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); -		ss_iso_source_desc.bEndpointAddress = -				fs_iso_source_desc.bEndpointAddress; - -		ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket; -		ss_iso_sink_desc.bInterval = isoc_interval; -		ss_iso_sink_comp_desc.bmAttributes = isoc_mult; -		ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst; -		ss_iso_sink_comp_desc.wBytesPerInterval = -			isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); -		ss_iso_sink_desc.bEndpointAddress = -				fs_iso_sink_desc.bEndpointAddress; - -		f->ss_descriptors = ss_source_sink_descs; -	} +	/* +	 * Fill in the SS isoc descriptors from the module parameters. +	 * We assume that the user knows what they are doing and won't +	 * give parameters that their UDC doesn't support. +	 */ +	ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket; +	ss_iso_source_desc.bInterval = isoc_interval; +	ss_iso_source_comp_desc.bmAttributes = isoc_mult; +	ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst; +	ss_iso_source_comp_desc.wBytesPerInterval = +		isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); +	ss_iso_source_desc.bEndpointAddress = +		fs_iso_source_desc.bEndpointAddress; + +	ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket; +	ss_iso_sink_desc.bInterval = isoc_interval; +	ss_iso_sink_comp_desc.bmAttributes = isoc_mult; +	ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst; +	ss_iso_sink_comp_desc.wBytesPerInterval = +		isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); +	ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress; + +	ret = usb_assign_descriptors(f, fs_source_sink_descs, +			hs_source_sink_descs, ss_source_sink_descs); +	if (ret) +		return ret;  	DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n",  	    (gadget_is_superspeed(c->cdev->gadget) ? "super" : @@ -458,6 +452,7 @@ no_iso:  static void  sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)  { +	usb_free_all_descriptors(f);  	kfree(func_to_ss(f));  } @@ -773,7 +768,6 @@ static int __init sourcesink_bind_config(struct usb_configuration *c)  		return -ENOMEM;  	ss->function.name = "source/sink"; -	ss->function.descriptors = fs_source_sink_descs;  	ss->function.bind = sourcesink_bind;  	ss->function.unbind = sourcesink_unbind;  	ss->function.set_alt = sourcesink_set_alt; diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index 4060c0bd978..f172bd152fb 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c @@ -236,7 +236,7 @@ static struct usb_descriptor_header *ss_eth_function[] = {  static struct usb_string geth_string_defs[] = {  	[0].s = "CDC Ethernet Subset/SAFE", -	[1].s = NULL /* DYNAMIC */, +	[1].s = "",  	{  } /* end of list */  }; @@ -319,38 +319,22 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)  	geth->port.out_ep = ep;  	ep->driver_data = cdev;	/* claim */ -	/* copy descriptors, and track endpoint copies */ -	f->descriptors = usb_copy_descriptors(fs_eth_function); -	if (!f->descriptors) -		goto fail; -  	/* support all relevant hardware speeds... we expect that when  	 * hardware is dual speed, all bulk-capable endpoints work at  	 * both speeds  	 */ -	if (gadget_is_dualspeed(c->cdev->gadget)) { -		hs_subset_in_desc.bEndpointAddress = -				fs_subset_in_desc.bEndpointAddress; -		hs_subset_out_desc.bEndpointAddress = -				fs_subset_out_desc.bEndpointAddress; - -		/* copy descriptors, and track endpoint copies */ -		f->hs_descriptors = usb_copy_descriptors(hs_eth_function); -		if (!f->hs_descriptors) -			goto fail; -	} +	hs_subset_in_desc.bEndpointAddress = fs_subset_in_desc.bEndpointAddress; +	hs_subset_out_desc.bEndpointAddress = +		fs_subset_out_desc.bEndpointAddress; -	if (gadget_is_superspeed(c->cdev->gadget)) { -		ss_subset_in_desc.bEndpointAddress = -				fs_subset_in_desc.bEndpointAddress; -		ss_subset_out_desc.bEndpointAddress = -				fs_subset_out_desc.bEndpointAddress; +	ss_subset_in_desc.bEndpointAddress = fs_subset_in_desc.bEndpointAddress; +	ss_subset_out_desc.bEndpointAddress = +		fs_subset_out_desc.bEndpointAddress; -		/* copy descriptors, and track endpoint copies */ -		f->ss_descriptors = usb_copy_descriptors(ss_eth_function); -		if (!f->ss_descriptors) -			goto fail; -	} +	status = usb_assign_descriptors(f, fs_eth_function, hs_eth_function, +			ss_eth_function); +	if (status) +		goto fail;  	/* NOTE:  all that is done without knowing or caring about  	 * the network link ... which is unavailable to this code @@ -364,15 +348,11 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)  	return 0;  fail: -	if (f->descriptors) -		usb_free_descriptors(f->descriptors); -	if (f->hs_descriptors) -		usb_free_descriptors(f->hs_descriptors); - +	usb_free_all_descriptors(f);  	/* we might as well release our claims on endpoints */ -	if (geth->port.out_ep->desc) +	if (geth->port.out_ep)  		geth->port.out_ep->driver_data = NULL; -	if (geth->port.in_ep->desc) +	if (geth->port.in_ep)  		geth->port.in_ep->driver_data = NULL;  	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); @@ -383,12 +363,8 @@ fail:  static void  geth_unbind(struct usb_configuration *c, struct usb_function *f)  { -	if (gadget_is_superspeed(c->cdev->gadget)) -		usb_free_descriptors(f->ss_descriptors); -	if (gadget_is_dualspeed(c->cdev->gadget)) -		usb_free_descriptors(f->hs_descriptors); -	usb_free_descriptors(f->descriptors); -	geth_string_defs[1].s = NULL; +	geth_string_defs[0].id = 0; +	usb_free_all_descriptors(f);  	kfree(func_to_geth(f));  } @@ -414,20 +390,11 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])  	/* maybe allocate device-global string IDs */  	if (geth_string_defs[0].id == 0) { - -		/* interface label */ -		status = usb_string_id(c->cdev); +		status = usb_string_ids_tab(c->cdev, geth_string_defs);  		if (status < 0)  			return status; -		geth_string_defs[0].id = status; -		subset_data_intf.iInterface = status; - -		/* MAC address */ -		status = usb_string_id(c->cdev); -		if (status < 0) -			return status; -		geth_string_defs[1].id = status; -		ether_desc.iMACAddress = status; +		subset_data_intf.iInterface = geth_string_defs[0].id; +		ether_desc.iMACAddress = geth_string_defs[1].id;  	}  	/* allocate and initialize one new instance */ @@ -449,9 +416,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])  	geth->port.func.disable = geth_disable;  	status = usb_add_function(c, &geth->port.func); -	if (status) { -		geth_string_defs[1].s = NULL; +	if (status)  		kfree(geth); -	}  	return status;  } diff --git a/drivers/usb/gadget/f_uac1.c b/drivers/usb/gadget/f_uac1.c index 1a5dcd5565e..f570e667a64 100644 --- a/drivers/usb/gadget/f_uac1.c +++ b/drivers/usb/gadget/f_uac1.c @@ -630,7 +630,7 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)  	struct usb_composite_dev *cdev = c->cdev;  	struct f_audio		*audio = func_to_audio(f);  	int			status; -	struct usb_ep		*ep; +	struct usb_ep		*ep = NULL;  	f_audio_build_desc(audio); @@ -659,22 +659,14 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)  	status = -ENOMEM;  	/* copy descriptors, and track endpoint copies */ -	f->descriptors = usb_copy_descriptors(f_audio_desc); - -	/* -	 * support all relevant hardware speeds... we expect that when -	 * hardware is dual speed, all bulk-capable endpoints work at -	 * both speeds -	 */ -	if (gadget_is_dualspeed(c->cdev->gadget)) { -		c->highspeed = true; -		f->hs_descriptors = usb_copy_descriptors(f_audio_desc); -	} - +	status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL); +	if (status) +		goto fail;  	return 0;  fail: - +	if (ep) +		ep->driver_data = NULL;  	return status;  } @@ -683,8 +675,7 @@ f_audio_unbind(struct usb_configuration *c, struct usb_function *f)  {  	struct f_audio		*audio = func_to_audio(f); -	usb_free_descriptors(f->descriptors); -	usb_free_descriptors(f->hs_descriptors); +	usb_free_all_descriptors(f);  	kfree(audio);  } diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c index d3c6cffccb7..d7da258fa3f 100644 --- a/drivers/usb/gadget/f_uac2.c +++ b/drivers/usb/gadget/f_uac2.c @@ -50,13 +50,6 @@ static int c_ssize = 2;  module_param(c_ssize, uint, S_IRUGO);  MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); -#define DMA_ADDR_INVALID	(~(dma_addr_t)0) - -#define ALT_SET(x, a)	do {(x) &= ~0xff; (x) |= (a); } while (0) -#define ALT_GET(x)	((x) & 0xff) -#define INTF_SET(x, i)	do {(x) &= 0xff; (x) |= ((i) << 8); } while (0) -#define INTF_GET(x)	((x >> 8) & 0xff) -  /* Keep everyone on toes */  #define USB_XFERS	2 @@ -144,8 +137,9 @@ static struct snd_pcm_hardware uac2_pcm_hardware = {  };  struct audio_dev { -	/* Currently active {Interface[15:8] | AltSettings[7:0]} */ -	__u16 ac_alt, as_out_alt, as_in_alt; +	u8 ac_intf, ac_alt; +	u8 as_out_intf, as_out_alt; +	u8 as_in_intf, as_in_alt;  	struct usb_ep *in_ep, *out_ep;  	struct usb_function func; @@ -408,7 +402,7 @@ static struct snd_pcm_ops uac2_pcm_ops = {  	.prepare = uac2_pcm_null,  }; -static int __devinit snd_uac2_probe(struct platform_device *pdev) +static int snd_uac2_probe(struct platform_device *pdev)  {  	struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev);  	struct snd_card *card; @@ -526,32 +520,22 @@ enum {  	STR_AS_IN_ALT1,  }; -static const char ifassoc[] = "Source/Sink"; -static const char ifctrl[] = "Topology Control";  static char clksrc_in[8];  static char clksrc_out[8]; -static const char usb_it[] = "USBH Out"; -static const char io_it[] = "USBD Out"; -static const char usb_ot[] = "USBH In"; -static const char io_ot[] = "USBD In"; -static const char out_alt0[] = "Playback Inactive"; -static const char out_alt1[] = "Playback Active"; -static const char in_alt0[] = "Capture Inactive"; -static const char in_alt1[] = "Capture Active";  static struct usb_string strings_fn[] = { -	[STR_ASSOC].s = ifassoc, -	[STR_IF_CTRL].s = ifctrl, +	[STR_ASSOC].s = "Source/Sink", +	[STR_IF_CTRL].s = "Topology Control",  	[STR_CLKSRC_IN].s = clksrc_in,  	[STR_CLKSRC_OUT].s = clksrc_out, -	[STR_USB_IT].s = usb_it, -	[STR_IO_IT].s = io_it, -	[STR_USB_OT].s = usb_ot, -	[STR_IO_OT].s = io_ot, -	[STR_AS_OUT_ALT0].s = out_alt0, -	[STR_AS_OUT_ALT1].s = out_alt1, -	[STR_AS_IN_ALT0].s = in_alt0, -	[STR_AS_IN_ALT1].s = in_alt1, +	[STR_USB_IT].s = "USBH Out", +	[STR_IO_IT].s = "USBD Out", +	[STR_USB_OT].s = "USBH In", +	[STR_IO_OT].s = "USBD In", +	[STR_AS_OUT_ALT0].s = "Playback Inactive", +	[STR_AS_OUT_ALT1].s = "Playback Active", +	[STR_AS_IN_ALT0].s = "Capture Inactive", +	[STR_AS_IN_ALT1].s = "Capture Active",  	{ },  }; @@ -952,8 +936,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)  		return ret;  	}  	std_ac_if_desc.bInterfaceNumber = ret; -	ALT_SET(agdev->ac_alt, 0); -	INTF_SET(agdev->ac_alt, ret); +	agdev->ac_intf = ret; +	agdev->ac_alt = 0;  	ret = usb_interface_id(cfg, fn);  	if (ret < 0) { @@ -963,8 +947,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)  	}  	std_as_out_if0_desc.bInterfaceNumber = ret;  	std_as_out_if1_desc.bInterfaceNumber = ret; -	ALT_SET(agdev->as_out_alt, 0); -	INTF_SET(agdev->as_out_alt, ret); +	agdev->as_out_intf = ret; +	agdev->as_out_alt = 0;  	ret = usb_interface_id(cfg, fn);  	if (ret < 0) { @@ -974,19 +958,23 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)  	}  	std_as_in_if0_desc.bInterfaceNumber = ret;  	std_as_in_if1_desc.bInterfaceNumber = ret; -	ALT_SET(agdev->as_in_alt, 0); -	INTF_SET(agdev->as_in_alt, ret); +	agdev->as_in_intf = ret; +	agdev->as_in_alt = 0;  	agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc); -	if (!agdev->out_ep) +	if (!agdev->out_ep) {  		dev_err(&uac2->pdev.dev,  			"%s:%d Error!\n", __func__, __LINE__); +		goto err; +	}  	agdev->out_ep->driver_data = agdev;  	agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc); -	if (!agdev->in_ep) +	if (!agdev->in_ep) {  		dev_err(&uac2->pdev.dev,  			"%s:%d Error!\n", __func__, __LINE__); +		goto err; +	}  	agdev->in_ep->driver_data = agdev;  	hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; @@ -994,9 +982,9 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)  	hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;  	hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize; -	fn->descriptors = usb_copy_descriptors(fs_audio_desc); -	if (gadget_is_dualspeed(gadget)) -		fn->hs_descriptors = usb_copy_descriptors(hs_audio_desc); +	ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL); +	if (ret) +		goto err;  	prm = &agdev->uac2.c_prm;  	prm->max_psize = hs_epout_desc.wMaxPacketSize; @@ -1005,6 +993,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)  		prm->max_psize = 0;  		dev_err(&uac2->pdev.dev,  			"%s:%d Error!\n", __func__, __LINE__); +		goto err;  	}  	prm = &agdev->uac2.p_prm; @@ -1014,17 +1003,28 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)  		prm->max_psize = 0;  		dev_err(&uac2->pdev.dev,  			"%s:%d Error!\n", __func__, __LINE__); +		goto err;  	} -	return alsa_uac2_init(agdev); +	ret = alsa_uac2_init(agdev); +	if (ret) +		goto err; +	return 0; +err: +	kfree(agdev->uac2.p_prm.rbuf); +	kfree(agdev->uac2.c_prm.rbuf); +	usb_free_all_descriptors(fn); +	if (agdev->in_ep) +		agdev->in_ep->driver_data = NULL; +	if (agdev->out_ep) +		agdev->out_ep->driver_data = NULL; +	return -EINVAL;  }  static void  afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn)  {  	struct audio_dev *agdev = func_to_agdev(fn); -	struct usb_composite_dev *cdev = cfg->cdev; -	struct usb_gadget *gadget = cdev->gadget;  	struct uac2_rtd_params *prm;  	alsa_uac2_exit(agdev); @@ -1034,10 +1034,7 @@ afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn)  	prm = &agdev->uac2.c_prm;  	kfree(prm->rbuf); - -	if (gadget_is_dualspeed(gadget)) -		usb_free_descriptors(fn->hs_descriptors); -	usb_free_descriptors(fn->descriptors); +	usb_free_all_descriptors(fn);  	if (agdev->in_ep)  		agdev->in_ep->driver_data = NULL; @@ -1064,7 +1061,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)  		return -EINVAL;  	} -	if (intf == INTF_GET(agdev->ac_alt)) { +	if (intf == agdev->ac_intf) {  		/* Control I/f has only 1 AltSetting - 0 */  		if (alt) {  			dev_err(&uac2->pdev.dev, @@ -1074,16 +1071,16 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)  		return 0;  	} -	if (intf == INTF_GET(agdev->as_out_alt)) { +	if (intf == agdev->as_out_intf) {  		ep = agdev->out_ep;  		prm = &uac2->c_prm;  		config_ep_by_speed(gadget, fn, ep); -		ALT_SET(agdev->as_out_alt, alt); -	} else if (intf == INTF_GET(agdev->as_in_alt)) { +		agdev->as_out_alt = alt; +	} else if (intf == agdev->as_in_intf) {  		ep = agdev->in_ep;  		prm = &uac2->p_prm;  		config_ep_by_speed(gadget, fn, ep); -		ALT_SET(agdev->as_in_alt, alt); +		agdev->as_in_alt = alt;  	} else {  		dev_err(&uac2->pdev.dev,  			"%s:%d Error!\n", __func__, __LINE__); @@ -1117,7 +1114,6 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)  		prm->ureq[i].pp = prm;  		req->zero = 0; -		req->dma = DMA_ADDR_INVALID;  		req->context = &prm->ureq[i];  		req->length = prm->max_psize;  		req->complete =	agdev_iso_complete; @@ -1136,12 +1132,12 @@ afunc_get_alt(struct usb_function *fn, unsigned intf)  	struct audio_dev *agdev = func_to_agdev(fn);  	struct snd_uac2_chip *uac2 = &agdev->uac2; -	if (intf == INTF_GET(agdev->ac_alt)) -		return ALT_GET(agdev->ac_alt); -	else if (intf == INTF_GET(agdev->as_out_alt)) -		return ALT_GET(agdev->as_out_alt); -	else if (intf == INTF_GET(agdev->as_in_alt)) -		return ALT_GET(agdev->as_in_alt); +	if (intf == agdev->ac_intf) +		return agdev->ac_alt; +	else if (intf == agdev->as_out_intf) +		return agdev->as_out_alt; +	else if (intf == agdev->as_in_intf) +		return agdev->as_in_alt;  	else  		dev_err(&uac2->pdev.dev,  			"%s:%d Invalid Interface %d!\n", @@ -1157,10 +1153,10 @@ afunc_disable(struct usb_function *fn)  	struct snd_uac2_chip *uac2 = &agdev->uac2;  	free_ep(&uac2->p_prm, agdev->in_ep); -	ALT_SET(agdev->as_in_alt, 0); +	agdev->as_in_alt = 0;  	free_ep(&uac2->c_prm, agdev->out_ep); -	ALT_SET(agdev->as_out_alt, 0); +	agdev->as_out_alt = 0;  }  static int @@ -1267,7 +1263,7 @@ setup_rq_inf(struct usb_function *fn, const struct usb_ctrlrequest *cr)  	u16 w_index = le16_to_cpu(cr->wIndex);  	u8 intf = w_index & 0xff; -	if (intf != INTF_GET(agdev->ac_alt)) { +	if (intf != agdev->ac_intf) {  		dev_err(&uac2->pdev.dev,  			"%s:%d Error!\n", __func__, __LINE__);  		return -EOPNOTSUPP; @@ -1316,7 +1312,7 @@ afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr)  static int audio_bind_config(struct usb_configuration *cfg)  { -	int id, res; +	int res;  	agdev_g = kzalloc(sizeof *agdev_g, GFP_KERNEL);  	if (agdev_g == NULL) { @@ -1324,89 +1320,21 @@ static int audio_bind_config(struct usb_configuration *cfg)  		return -ENOMEM;  	} -	id = usb_string_id(cfg->cdev); -	if (id < 0) -		return id; - -	strings_fn[STR_ASSOC].id = id; -	iad_desc.iFunction = id, - -	id = usb_string_id(cfg->cdev); -	if (id < 0) -		return id; - -	strings_fn[STR_IF_CTRL].id = id; -	std_ac_if_desc.iInterface = id, - -	id = usb_string_id(cfg->cdev); -	if (id < 0) -		return id; - -	strings_fn[STR_CLKSRC_IN].id = id; -	in_clk_src_desc.iClockSource = id, - -	id = usb_string_id(cfg->cdev); -	if (id < 0) -		return id; - -	strings_fn[STR_CLKSRC_OUT].id = id; -	out_clk_src_desc.iClockSource = id, - -	id = usb_string_id(cfg->cdev); -	if (id < 0) -		return id; - -	strings_fn[STR_USB_IT].id = id; -	usb_out_it_desc.iTerminal = id, - -	id = usb_string_id(cfg->cdev); -	if (id < 0) -		return id; - -	strings_fn[STR_IO_IT].id = id; -	io_in_it_desc.iTerminal = id; - -	id = usb_string_id(cfg->cdev); -	if (id < 0) -		return id; - -	strings_fn[STR_USB_OT].id = id; -	usb_in_ot_desc.iTerminal = id; - -	id = usb_string_id(cfg->cdev); -	if (id < 0) -		return id; - -	strings_fn[STR_IO_OT].id = id; -	io_out_ot_desc.iTerminal = id; - -	id = usb_string_id(cfg->cdev); -	if (id < 0) -		return id; - -	strings_fn[STR_AS_OUT_ALT0].id = id; -	std_as_out_if0_desc.iInterface = id; - -	id = usb_string_id(cfg->cdev); -	if (id < 0) -		return id; - -	strings_fn[STR_AS_OUT_ALT1].id = id; -	std_as_out_if1_desc.iInterface = id; - -	id = usb_string_id(cfg->cdev); -	if (id < 0) -		return id; - -	strings_fn[STR_AS_IN_ALT0].id = id; -	std_as_in_if0_desc.iInterface = id; - -	id = usb_string_id(cfg->cdev); -	if (id < 0) -		return id; - -	strings_fn[STR_AS_IN_ALT1].id = id; -	std_as_in_if1_desc.iInterface = id; +	res = usb_string_ids_tab(cfg->cdev, strings_fn); +	if (res) +		return res; +	iad_desc.iFunction = strings_fn[STR_ASSOC].id; +	std_ac_if_desc.iInterface = strings_fn[STR_IF_CTRL].id; +	in_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_IN].id; +	out_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_OUT].id; +	usb_out_it_desc.iTerminal = strings_fn[STR_USB_IT].id; +	io_in_it_desc.iTerminal = strings_fn[STR_IO_IT].id; +	usb_in_ot_desc.iTerminal = strings_fn[STR_USB_OT].id; +	io_out_ot_desc.iTerminal = strings_fn[STR_IO_OT].id; +	std_as_out_if0_desc.iInterface = strings_fn[STR_AS_OUT_ALT0].id; +	std_as_out_if1_desc.iInterface = strings_fn[STR_AS_OUT_ALT1].id; +	std_as_in_if0_desc.iInterface = strings_fn[STR_AS_IN_ALT0].id; +	std_as_in_if1_desc.iInterface = strings_fn[STR_AS_IN_ALT1].id;  	agdev_g->func.name = "uac2_func";  	agdev_g->func.strings = fn_strings; diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 2a8bf0655c6..5b629876941 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -417,7 +417,6 @@ uvc_register_video(struct uvc_device *uvc)  		return -ENOMEM;  	video->parent = &cdev->gadget->dev; -	video->minor = -1;  	video->fops = &uvc_v4l2_fops;  	video->release = video_device_release;  	strncpy(video->name, cdev->gadget->name, sizeof(video->name)); @@ -577,27 +576,15 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)  	INFO(cdev, "uvc_function_unbind\n"); -	if (uvc->vdev) { -		if (uvc->vdev->minor == -1) -			video_device_release(uvc->vdev); -		else -			video_unregister_device(uvc->vdev); -		uvc->vdev = NULL; -	} +	video_unregister_device(uvc->vdev); +	uvc->control_ep->driver_data = NULL; +	uvc->video.ep->driver_data = NULL; -	if (uvc->control_ep) -		uvc->control_ep->driver_data = NULL; -	if (uvc->video.ep) -		uvc->video.ep->driver_data = NULL; - -	if (uvc->control_req) { -		usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); -		kfree(uvc->control_buf); -	} +	uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0; +	usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); +	kfree(uvc->control_buf); -	kfree(f->descriptors); -	kfree(f->hs_descriptors); -	kfree(f->ss_descriptors); +	usb_free_all_descriptors(f);  	kfree(uvc);  } @@ -663,49 +650,40 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)  	/* 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; -	/* Copy descriptors for FS. */ -	f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); - -	/* support high speed hardware */ -	if (gadget_is_dualspeed(cdev->gadget)) { -		/* -		 * 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; - -		/* Copy descriptors. */ -		f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); -	} +	/* +	 * 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; -	/* support super speed hardware */ -	if (gadget_is_superspeed(c->cdev->gadget)) { -		/* -		 * 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. */ +	/* Copy descriptors */ +	f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); +	if (gadget_is_dualspeed(cdev->gadget)) +		f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); +	if (gadget_is_superspeed(c->cdev->gadget))  		f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER); -	}  	/* Preallocate control endpoint request. */  	uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); @@ -740,7 +718,20 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)  	return 0;  error: -	uvc_function_unbind(c, f); +	if (uvc->vdev) +		video_device_release(uvc->vdev); + +	if (uvc->control_ep) +		uvc->control_ep->driver_data = NULL; +	if (uvc->video.ep) +		uvc->video.ep->driver_data = NULL; + +	if (uvc->control_req) { +		usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); +		kfree(uvc->control_buf); +	} + +	usb_free_all_descriptors(f);  	return ret;  } @@ -808,25 +799,16 @@ uvc_bind_config(struct usb_configuration *c,  	uvc->desc.hs_streaming = hs_streaming;  	uvc->desc.ss_streaming = ss_streaming; -	/* maybe allocate device-global string IDs, and patch descriptors */ +	/* Allocate string descriptor numbers. */  	if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) { -		/* Allocate string descriptor numbers. */ -		ret = usb_string_id(c->cdev); -		if (ret < 0) -			goto error; -		uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret; -		uvc_iad.iFunction = ret; - -		ret = usb_string_id(c->cdev); -		if (ret < 0) -			goto error; -		uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret; -		uvc_control_intf.iInterface = ret; - -		ret = usb_string_id(c->cdev); -		if (ret < 0) +		ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings); +		if (ret)  			goto error; -		uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret; +		uvc_iad.iFunction = +			uvc_en_us_strings[UVC_STRING_ASSOCIATION_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;  		uvc_streaming_intf_alt0.iInterface = ret;  		uvc_streaming_intf_alt1.iInterface = ret;  	} diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c deleted file mode 100644 index 3f7d640b675..00000000000 --- a/drivers/usb/gadget/file_storage.c +++ /dev/null @@ -1,3656 +0,0 @@ -/* - * file_storage.c -- File-backed USB Storage Gadget, for USB development - * - * Copyright (C) 2003-2008 Alan Stern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions, and the following disclaimer, - *    without modification. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - *    to endorse or promote products derived from this software without - *    specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") as published by the Free Software - * Foundation, either version 2 of that License or (at your option) any - * later version. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -/* - * The File-backed Storage Gadget acts as a USB Mass Storage device, - * appearing to the host as a disk drive or as a CD-ROM drive.  In addition - * to providing an example of a genuinely useful gadget driver for a USB - * device, it also illustrates a technique of double-buffering for increased - * throughput.  Last but not least, it gives an easy way to probe the - * behavior of the Mass Storage drivers in a USB host. - * - * Backing storage is provided by a regular file or a block device, specified - * by the "file" module parameter.  Access can be limited to read-only by - * setting the optional "ro" module parameter.  (For CD-ROM emulation, - * access is always read-only.)  The gadget will indicate that it has - * removable media if the optional "removable" module parameter is set. - * - * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI), - * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected - * by the optional "transport" module parameter.  It also supports the - * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03), - * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by - * the optional "protocol" module parameter.  In addition, the default - * Vendor ID, Product ID, release number and serial number can be overridden. - * - * There is support for multiple logical units (LUNs), each of which has - * its own backing file.  The number of LUNs can be set using the optional - * "luns" module parameter (anywhere from 1 to 8), and the corresponding - * files are specified using comma-separated lists for "file" and "ro". - * The default number of LUNs is taken from the number of "file" elements; - * it is 1 if "file" is not given.  If "removable" is not set then a backing - * file must be specified for each LUN.  If it is set, then an unspecified - * or empty backing filename means the LUN's medium is not loaded.  Ideally - * each LUN would be settable independently as a disk drive or a CD-ROM - * drive, but currently all LUNs have to be the same type.  The CD-ROM - * emulation includes a single data track and no audio tracks; hence there - * need be only one backing file per LUN. - * - * Requirements are modest; only a bulk-in and a bulk-out endpoint are - * needed (an interrupt-out endpoint is also needed for CBI).  The memory - * requirement amounts to two 16K buffers, size configurable by a parameter. - * Support is included for both full-speed and high-speed operation. - * - * Note that the driver is slightly non-portable in that it assumes a - * single memory/DMA buffer will be useable for bulk-in, bulk-out, and - * interrupt-in endpoints.  With most device controllers this isn't an - * issue, but there may be some with hardware restrictions that prevent - * a buffer from being used by more than one endpoint. - * - * Module options: - * - *	file=filename[,filename...] - *				Required if "removable" is not set, names of - *					the files or block devices used for - *					backing storage - *	serial=HHHH...		Required serial number (string of hex chars) - *	ro=b[,b...]		Default false, booleans for read-only access - *	removable		Default false, boolean for removable media - *	luns=N			Default N = number of filenames, number of - *					LUNs to support - *	nofua=b[,b...]		Default false, booleans for ignore FUA flag - *					in SCSI WRITE(10,12) commands - *	stall			Default determined according to the type of - *					USB device controller (usually true), - *					boolean to permit the driver to halt - *					bulk endpoints - *	cdrom			Default false, boolean for whether to emulate - *					a CD-ROM drive - *	transport=XXX		Default BBB, transport name (CB, CBI, or BBB) - *	protocol=YYY		Default SCSI, protocol name (RBC, 8020 or - *					ATAPI, QIC, UFI, 8070, or SCSI; - *					also 1 - 6) - *	vendor=0xVVVV		Default 0x0525 (NetChip), USB Vendor ID - *	product=0xPPPP		Default 0xa4a5 (FSG), USB Product ID - *	release=0xRRRR		Override the USB release number (bcdDevice) - *	buflen=N		Default N=16384, buffer size used (will be - *					rounded down to a multiple of - *					PAGE_CACHE_SIZE) - * - * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro", - * "removable", "luns", "nofua", "stall", and "cdrom" options are available; - * default values are used for everything else. - * - * The pathnames of the backing files and the ro settings are available in - * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of - * the gadget's sysfs directory.  If the "removable" option is set, writing to - * these files will simulate ejecting/loading the medium (writing an empty - * line means eject) and adjusting a write-enable tab.  Changes to the ro - * setting are not allowed when the medium is loaded or if CD-ROM emulation - * is being used. - * - * This gadget driver is heavily based on "Gadget Zero" by David Brownell. - * The driver's SCSI command interface was based on the "Information - * technology - Small Computer System Interface - 2" document from - * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at - * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>.  The single exception - * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the - * "Universal Serial Bus Mass Storage Class UFI Command Specification" - * document, Revision 1.0, December 14, 1998, available at - * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>. - */ - - -/* - *				Driver Design - * - * The FSG driver is fairly straightforward.  There is a main kernel - * thread that handles most of the work.  Interrupt routines field - * callbacks from the controller driver: bulk- and interrupt-request - * completion notifications, endpoint-0 events, and disconnect events. - * Completion events are passed to the main thread by wakeup calls.  Many - * ep0 requests are handled at interrupt time, but SetInterface, - * SetConfiguration, and device reset requests are forwarded to the - * thread in the form of "exceptions" using SIGUSR1 signals (since they - * should interrupt any ongoing file I/O operations). - * - * The thread's main routine implements the standard command/data/status - * parts of a SCSI interaction.  It and its subroutines are full of tests - * for pending signals/exceptions -- all this polling is necessary since - * the kernel has no setjmp/longjmp equivalents.  (Maybe this is an - * indication that the driver really wants to be running in userspace.) - * An important point is that so long as the thread is alive it keeps an - * open reference to the backing file.  This will prevent unmounting - * the backing file's underlying filesystem and could cause problems - * during system shutdown, for example.  To prevent such problems, the - * thread catches INT, TERM, and KILL signals and converts them into - * an EXIT exception. - * - * In normal operation the main thread is started during the gadget's - * fsg_bind() callback and stopped during fsg_unbind().  But it can also - * exit when it receives a signal, and there's no point leaving the - * gadget running when the thread is dead.  So just before the thread - * exits, it deregisters the gadget driver.  This makes things a little - * tricky: The driver is deregistered at two places, and the exiting - * thread can indirectly call fsg_unbind() which in turn can tell the - * thread to exit.  The first problem is resolved through the use of the - * REGISTERED atomic bitflag; the driver will only be deregistered once. - * The second problem is resolved by having fsg_unbind() check - * fsg->state; it won't try to stop the thread if the state is already - * FSG_STATE_TERMINATED. - * - * To provide maximum throughput, the driver uses a circular pipeline of - * buffer heads (struct fsg_buffhd).  In principle the pipeline can be - * arbitrarily long; in practice the benefits don't justify having more - * than 2 stages (i.e., double buffering).  But it helps to think of the - * pipeline as being a long one.  Each buffer head contains a bulk-in and - * a bulk-out request pointer (since the buffer can be used for both - * output and input -- directions always are given from the host's - * point of view) as well as a pointer to the buffer and various state - * variables. - * - * Use of the pipeline follows a simple protocol.  There is a variable - * (fsg->next_buffhd_to_fill) that points to the next buffer head to use. - * At any time that buffer head may still be in use from an earlier - * request, so each buffer head has a state variable indicating whether - * it is EMPTY, FULL, or BUSY.  Typical use involves waiting for the - * buffer head to be EMPTY, filling the buffer either by file I/O or by - * USB I/O (during which the buffer head is BUSY), and marking the buffer - * head FULL when the I/O is complete.  Then the buffer will be emptied - * (again possibly by USB I/O, during which it is marked BUSY) and - * finally marked EMPTY again (possibly by a completion routine). - * - * A module parameter tells the driver to avoid stalling the bulk - * endpoints wherever the transport specification allows.  This is - * necessary for some UDCs like the SuperH, which cannot reliably clear a - * halt on a bulk endpoint.  However, under certain circumstances the - * Bulk-only specification requires a stall.  In such cases the driver - * will halt the endpoint and set a flag indicating that it should clear - * the halt in software during the next device reset.  Hopefully this - * will permit everything to work correctly.  Furthermore, although the - * specification allows the bulk-out endpoint to halt when the host sends - * too much data, implementing this would cause an unavoidable race. - * The driver will always use the "no-stall" approach for OUT transfers. - * - * One subtle point concerns sending status-stage responses for ep0 - * requests.  Some of these requests, such as device reset, can involve - * interrupting an ongoing file I/O operation, which might take an - * arbitrarily long time.  During that delay the host might give up on - * the original ep0 request and issue a new one.  When that happens the - * driver should not notify the host about completion of the original - * request, as the host will no longer be waiting for it.  So the driver - * assigns to each ep0 request a unique tag, and it keeps track of the - * tag value of the request associated with a long-running exception - * (device-reset, interface-change, or configuration-change).  When the - * exception handler is finished, the status-stage response is submitted - * only if the current ep0 request tag is equal to the exception request - * tag.  Thus only the most recently received ep0 request will get a - * status-stage response. - * - * Warning: This driver source file is too long.  It ought to be split up - * into a header file plus about 3 separate .c files, to handle the details - * of the Gadget, USB Mass Storage, and SCSI protocols. - */ - - -/* #define VERBOSE_DEBUG */ -/* #define DUMP_MSGS */ - - -#include <linux/blkdev.h> -#include <linux/completion.h> -#include <linux/dcache.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/fcntl.h> -#include <linux/file.h> -#include <linux/fs.h> -#include <linux/kref.h> -#include <linux/kthread.h> -#include <linux/limits.h> -#include <linux/module.h> -#include <linux/rwsem.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/string.h> -#include <linux/freezer.h> -#include <linux/utsname.h> - -#include <linux/usb/composite.h> -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> - -#include "gadget_chips.h" - -#define DRIVER_DESC		"File-backed Storage Gadget" -#define DRIVER_NAME		"g_file_storage" -#define DRIVER_VERSION		"1 September 2010" - -static       char fsg_string_manufacturer[64]; -static const char fsg_string_product[] = DRIVER_DESC; -static const char fsg_string_config[] = "Self-powered"; -static const char fsg_string_interface[] = "Mass Storage"; - - -#include "storage_common.c" - - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR("Alan Stern"); -MODULE_LICENSE("Dual BSD/GPL"); - -/* - * This driver assumes self-powered hardware and has no way for users to - * trigger remote wakeup.  It uses autoconfiguration to select endpoints - * and endpoint addresses. - */ - - -/*-------------------------------------------------------------------------*/ - - -/* Encapsulate the module parameter settings */ - -static struct { -	char		*file[FSG_MAX_LUNS]; -	char		*serial; -	bool		ro[FSG_MAX_LUNS]; -	bool		nofua[FSG_MAX_LUNS]; -	unsigned int	num_filenames; -	unsigned int	num_ros; -	unsigned int	num_nofuas; -	unsigned int	nluns; - -	bool		removable; -	bool		can_stall; -	bool		cdrom; - -	char		*transport_parm; -	char		*protocol_parm; -	unsigned short	vendor; -	unsigned short	product; -	unsigned short	release; -	unsigned int	buflen; - -	int		transport_type; -	char		*transport_name; -	int		protocol_type; -	char		*protocol_name; - -} mod_data = {					// Default values -	.transport_parm		= "BBB", -	.protocol_parm		= "SCSI", -	.removable		= 0, -	.can_stall		= 1, -	.cdrom			= 0, -	.vendor			= FSG_VENDOR_ID, -	.product		= FSG_PRODUCT_ID, -	.release		= 0xffff,	// Use controller chip type -	.buflen			= 16384, -	}; - - -module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames, -		S_IRUGO); -MODULE_PARM_DESC(file, "names of backing files or devices"); - -module_param_named(serial, mod_data.serial, charp, S_IRUGO); -MODULE_PARM_DESC(serial, "USB serial number"); - -module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO); -MODULE_PARM_DESC(ro, "true to force read-only"); - -module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas, -		S_IRUGO); -MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit"); - -module_param_named(luns, mod_data.nluns, uint, S_IRUGO); -MODULE_PARM_DESC(luns, "number of LUNs"); - -module_param_named(removable, mod_data.removable, bool, S_IRUGO); -MODULE_PARM_DESC(removable, "true to simulate removable media"); - -module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); -MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); - -module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO); -MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk"); - -/* In the non-TEST version, only the module parameters listed above - * are available. */ -#ifdef CONFIG_USB_FILE_STORAGE_TEST - -module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO); -MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)"); - -module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO); -MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, " -		"8070, or SCSI)"); - -module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO); -MODULE_PARM_DESC(vendor, "USB Vendor ID"); - -module_param_named(product, mod_data.product, ushort, S_IRUGO); -MODULE_PARM_DESC(product, "USB Product ID"); - -module_param_named(release, mod_data.release, ushort, S_IRUGO); -MODULE_PARM_DESC(release, "USB release number"); - -module_param_named(buflen, mod_data.buflen, uint, S_IRUGO); -MODULE_PARM_DESC(buflen, "I/O buffer size"); - -#endif /* CONFIG_USB_FILE_STORAGE_TEST */ - - -/* - * These definitions will permit the compiler to avoid generating code for - * parts of the driver that aren't used in the non-TEST version.  Even gcc - * can recognize when a test of a constant expression yields a dead code - * path. - */ - -#ifdef CONFIG_USB_FILE_STORAGE_TEST - -#define transport_is_bbb()	(mod_data.transport_type == USB_PR_BULK) -#define transport_is_cbi()	(mod_data.transport_type == USB_PR_CBI) -#define protocol_is_scsi()	(mod_data.protocol_type == USB_SC_SCSI) - -#else - -#define transport_is_bbb()	1 -#define transport_is_cbi()	0 -#define protocol_is_scsi()	1 - -#endif /* CONFIG_USB_FILE_STORAGE_TEST */ - - -/*-------------------------------------------------------------------------*/ - - -struct fsg_dev { -	/* lock protects: state, all the req_busy's, and cbbuf_cmnd */ -	spinlock_t		lock; -	struct usb_gadget	*gadget; - -	/* filesem protects: backing files in use */ -	struct rw_semaphore	filesem; - -	/* reference counting: wait until all LUNs are released */ -	struct kref		ref; - -	struct usb_ep		*ep0;		// Handy copy of gadget->ep0 -	struct usb_request	*ep0req;	// For control responses -	unsigned int		ep0_req_tag; -	const char		*ep0req_name; - -	struct usb_request	*intreq;	// For interrupt responses -	int			intreq_busy; -	struct fsg_buffhd	*intr_buffhd; - -	unsigned int		bulk_out_maxpacket; -	enum fsg_state		state;		// For exception handling -	unsigned int		exception_req_tag; - -	u8			config, new_config; - -	unsigned int		running : 1; -	unsigned int		bulk_in_enabled : 1; -	unsigned int		bulk_out_enabled : 1; -	unsigned int		intr_in_enabled : 1; -	unsigned int		phase_error : 1; -	unsigned int		short_packet_received : 1; -	unsigned int		bad_lun_okay : 1; - -	unsigned long		atomic_bitflags; -#define REGISTERED		0 -#define IGNORE_BULK_OUT		1 -#define SUSPENDED		2 - -	struct usb_ep		*bulk_in; -	struct usb_ep		*bulk_out; -	struct usb_ep		*intr_in; - -	struct fsg_buffhd	*next_buffhd_to_fill; -	struct fsg_buffhd	*next_buffhd_to_drain; - -	int			thread_wakeup_needed; -	struct completion	thread_notifier; -	struct task_struct	*thread_task; - -	int			cmnd_size; -	u8			cmnd[MAX_COMMAND_SIZE]; -	enum data_direction	data_dir; -	u32			data_size; -	u32			data_size_from_cmnd; -	u32			tag; -	unsigned int		lun; -	u32			residue; -	u32			usb_amount_left; - -	/* The CB protocol offers no way for a host to know when a command -	 * has completed.  As a result the next command may arrive early, -	 * and we will still have to handle it.  For that reason we need -	 * a buffer to store new commands when using CB (or CBI, which -	 * does not oblige a host to wait for command completion either). */ -	int			cbbuf_cmnd_size; -	u8			cbbuf_cmnd[MAX_COMMAND_SIZE]; - -	unsigned int		nluns; -	struct fsg_lun		*luns; -	struct fsg_lun		*curlun; -	/* Must be the last entry */ -	struct fsg_buffhd	buffhds[]; -}; - -typedef void (*fsg_routine_t)(struct fsg_dev *); - -static int exception_in_progress(struct fsg_dev *fsg) -{ -	return (fsg->state > FSG_STATE_IDLE); -} - -/* Make bulk-out requests be divisible by the maxpacket size */ -static void set_bulk_out_req_length(struct fsg_dev *fsg, -		struct fsg_buffhd *bh, unsigned int length) -{ -	unsigned int	rem; - -	bh->bulk_out_intended_length = length; -	rem = length % fsg->bulk_out_maxpacket; -	if (rem > 0) -		length += fsg->bulk_out_maxpacket - rem; -	bh->outreq->length = length; -} - -static struct fsg_dev			*the_fsg; -static struct usb_gadget_driver		fsg_driver; - - -/*-------------------------------------------------------------------------*/ - -static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) -{ -	const char	*name; - -	if (ep == fsg->bulk_in) -		name = "bulk-in"; -	else if (ep == fsg->bulk_out) -		name = "bulk-out"; -	else -		name = ep->name; -	DBG(fsg, "%s set halt\n", name); -	return usb_ep_set_halt(ep); -} - - -/*-------------------------------------------------------------------------*/ - -/* - * DESCRIPTORS ... most are static, but strings and (full) configuration - * descriptors are built on demand.  Also the (static) config and interface - * descriptors are adjusted during fsg_bind(). - */ - -/* There is only one configuration. */ -#define	CONFIG_VALUE		1 - -static struct usb_device_descriptor -device_desc = { -	.bLength =		sizeof device_desc, -	.bDescriptorType =	USB_DT_DEVICE, - -	.bcdUSB =		cpu_to_le16(0x0200), -	.bDeviceClass =		USB_CLASS_PER_INTERFACE, - -	/* The next three values can be overridden by module parameters */ -	.idVendor =		cpu_to_le16(FSG_VENDOR_ID), -	.idProduct =		cpu_to_le16(FSG_PRODUCT_ID), -	.bcdDevice =		cpu_to_le16(0xffff), - -	.iManufacturer =	FSG_STRING_MANUFACTURER, -	.iProduct =		FSG_STRING_PRODUCT, -	.iSerialNumber =	FSG_STRING_SERIAL, -	.bNumConfigurations =	1, -}; - -static struct usb_config_descriptor -config_desc = { -	.bLength =		sizeof config_desc, -	.bDescriptorType =	USB_DT_CONFIG, - -	/* wTotalLength computed by usb_gadget_config_buf() */ -	.bNumInterfaces =	1, -	.bConfigurationValue =	CONFIG_VALUE, -	.iConfiguration =	FSG_STRING_CONFIG, -	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, -	.bMaxPower =		CONFIG_USB_GADGET_VBUS_DRAW / 2, -}; - - -static struct usb_qualifier_descriptor -dev_qualifier = { -	.bLength =		sizeof dev_qualifier, -	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER, - -	.bcdUSB =		cpu_to_le16(0x0200), -	.bDeviceClass =		USB_CLASS_PER_INTERFACE, - -	.bNumConfigurations =	1, -}; - -static int populate_bos(struct fsg_dev *fsg, u8 *buf) -{ -	memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE); -	buf += USB_DT_BOS_SIZE; - -	memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE); -	buf += USB_DT_USB_EXT_CAP_SIZE; - -	memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE); - -	return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE -		+ USB_DT_USB_EXT_CAP_SIZE; -} - -/* - * Config descriptors must agree with the code that sets configurations - * and with code managing interfaces and their altsettings.  They must - * also handle different speeds and other-speed requests. - */ -static int populate_config_buf(struct usb_gadget *gadget, -		u8 *buf, u8 type, unsigned index) -{ -	enum usb_device_speed			speed = gadget->speed; -	int					len; -	const struct usb_descriptor_header	**function; - -	if (index > 0) -		return -EINVAL; - -	if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG) -		speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed; -	function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH -		? (const struct usb_descriptor_header **)fsg_hs_function -		: (const struct usb_descriptor_header **)fsg_fs_function; - -	/* for now, don't advertise srp-only devices */ -	if (!gadget_is_otg(gadget)) -		function++; - -	len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function); -	((struct usb_config_descriptor *) buf)->bDescriptorType = type; -	return len; -} - - -/*-------------------------------------------------------------------------*/ - -/* These routines may be called in process context or in_irq */ - -/* Caller must hold fsg->lock */ -static void wakeup_thread(struct fsg_dev *fsg) -{ -	/* Tell the main thread that something has happened */ -	fsg->thread_wakeup_needed = 1; -	if (fsg->thread_task) -		wake_up_process(fsg->thread_task); -} - - -static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state) -{ -	unsigned long		flags; - -	/* Do nothing if a higher-priority exception is already in progress. -	 * If a lower-or-equal priority exception is in progress, preempt it -	 * and notify the main thread by sending it a signal. */ -	spin_lock_irqsave(&fsg->lock, flags); -	if (fsg->state <= new_state) { -		fsg->exception_req_tag = fsg->ep0_req_tag; -		fsg->state = new_state; -		if (fsg->thread_task) -			send_sig_info(SIGUSR1, SEND_SIG_FORCED, -					fsg->thread_task); -	} -	spin_unlock_irqrestore(&fsg->lock, flags); -} - - -/*-------------------------------------------------------------------------*/ - -/* The disconnect callback and ep0 routines.  These always run in_irq, - * except that ep0_queue() is called in the main thread to acknowledge - * completion of various requests: set config, set interface, and - * Bulk-only device reset. */ - -static void fsg_disconnect(struct usb_gadget *gadget) -{ -	struct fsg_dev		*fsg = get_gadget_data(gadget); - -	DBG(fsg, "disconnect or port reset\n"); -	raise_exception(fsg, FSG_STATE_DISCONNECT); -} - - -static int ep0_queue(struct fsg_dev *fsg) -{ -	int	rc; - -	rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC); -	if (rc != 0 && rc != -ESHUTDOWN) { - -		/* We can't do much more than wait for a reset */ -		WARNING(fsg, "error in submission: %s --> %d\n", -				fsg->ep0->name, rc); -	} -	return rc; -} - -static void ep0_complete(struct usb_ep *ep, struct usb_request *req) -{ -	struct fsg_dev		*fsg = ep->driver_data; - -	if (req->actual > 0) -		dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual); -	if (req->status || req->actual != req->length) -		DBG(fsg, "%s --> %d, %u/%u\n", __func__, -				req->status, req->actual, req->length); -	if (req->status == -ECONNRESET)		// Request was cancelled -		usb_ep_fifo_flush(ep); - -	if (req->status == 0 && req->context) -		((fsg_routine_t) (req->context))(fsg); -} - - -/*-------------------------------------------------------------------------*/ - -/* Bulk and interrupt endpoint completion handlers. - * These always run in_irq. */ - -static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) -{ -	struct fsg_dev		*fsg = ep->driver_data; -	struct fsg_buffhd	*bh = req->context; - -	if (req->status || req->actual != req->length) -		DBG(fsg, "%s --> %d, %u/%u\n", __func__, -				req->status, req->actual, req->length); -	if (req->status == -ECONNRESET)		// Request was cancelled -		usb_ep_fifo_flush(ep); - -	/* Hold the lock while we update the request and buffer states */ -	smp_wmb(); -	spin_lock(&fsg->lock); -	bh->inreq_busy = 0; -	bh->state = BUF_STATE_EMPTY; -	wakeup_thread(fsg); -	spin_unlock(&fsg->lock); -} - -static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) -{ -	struct fsg_dev		*fsg = ep->driver_data; -	struct fsg_buffhd	*bh = req->context; - -	dump_msg(fsg, "bulk-out", req->buf, req->actual); -	if (req->status || req->actual != bh->bulk_out_intended_length) -		DBG(fsg, "%s --> %d, %u/%u\n", __func__, -				req->status, req->actual, -				bh->bulk_out_intended_length); -	if (req->status == -ECONNRESET)		// Request was cancelled -		usb_ep_fifo_flush(ep); - -	/* Hold the lock while we update the request and buffer states */ -	smp_wmb(); -	spin_lock(&fsg->lock); -	bh->outreq_busy = 0; -	bh->state = BUF_STATE_FULL; -	wakeup_thread(fsg); -	spin_unlock(&fsg->lock); -} - - -#ifdef CONFIG_USB_FILE_STORAGE_TEST -static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) -{ -	struct fsg_dev		*fsg = ep->driver_data; -	struct fsg_buffhd	*bh = req->context; - -	if (req->status || req->actual != req->length) -		DBG(fsg, "%s --> %d, %u/%u\n", __func__, -				req->status, req->actual, req->length); -	if (req->status == -ECONNRESET)		// Request was cancelled -		usb_ep_fifo_flush(ep); - -	/* Hold the lock while we update the request and buffer states */ -	smp_wmb(); -	spin_lock(&fsg->lock); -	fsg->intreq_busy = 0; -	bh->state = BUF_STATE_EMPTY; -	wakeup_thread(fsg); -	spin_unlock(&fsg->lock); -} - -#else -static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) -{} -#endif /* CONFIG_USB_FILE_STORAGE_TEST */ - - -/*-------------------------------------------------------------------------*/ - -/* Ep0 class-specific handlers.  These always run in_irq. */ - -#ifdef CONFIG_USB_FILE_STORAGE_TEST -static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) -{ -	struct usb_request	*req = fsg->ep0req; -	static u8		cbi_reset_cmnd[6] = { -			SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff}; - -	/* Error in command transfer? */ -	if (req->status || req->length != req->actual || -			req->actual < 6 || req->actual > MAX_COMMAND_SIZE) { - -		/* Not all controllers allow a protocol stall after -		 * receiving control-out data, but we'll try anyway. */ -		fsg_set_halt(fsg, fsg->ep0); -		return;			// Wait for reset -	} - -	/* Is it the special reset command? */ -	if (req->actual >= sizeof cbi_reset_cmnd && -			memcmp(req->buf, cbi_reset_cmnd, -				sizeof cbi_reset_cmnd) == 0) { - -		/* Raise an exception to stop the current operation -		 * and reinitialize our state. */ -		DBG(fsg, "cbi reset request\n"); -		raise_exception(fsg, FSG_STATE_RESET); -		return; -	} - -	VDBG(fsg, "CB[I] accept device-specific command\n"); -	spin_lock(&fsg->lock); - -	/* Save the command for later */ -	if (fsg->cbbuf_cmnd_size) -		WARNING(fsg, "CB[I] overwriting previous command\n"); -	fsg->cbbuf_cmnd_size = req->actual; -	memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size); - -	wakeup_thread(fsg); -	spin_unlock(&fsg->lock); -} - -#else -static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) -{} -#endif /* CONFIG_USB_FILE_STORAGE_TEST */ - - -static int class_setup_req(struct fsg_dev *fsg, -		const struct usb_ctrlrequest *ctrl) -{ -	struct usb_request	*req = fsg->ep0req; -	int			value = -EOPNOTSUPP; -	u16			w_index = le16_to_cpu(ctrl->wIndex); -	u16                     w_value = le16_to_cpu(ctrl->wValue); -	u16			w_length = le16_to_cpu(ctrl->wLength); - -	if (!fsg->config) -		return value; - -	/* Handle Bulk-only class-specific requests */ -	if (transport_is_bbb()) { -		switch (ctrl->bRequest) { - -		case US_BULK_RESET_REQUEST: -			if (ctrl->bRequestType != (USB_DIR_OUT | -					USB_TYPE_CLASS | USB_RECIP_INTERFACE)) -				break; -			if (w_index != 0 || w_value != 0 || w_length != 0) { -				value = -EDOM; -				break; -			} - -			/* Raise an exception to stop the current operation -			 * and reinitialize our state. */ -			DBG(fsg, "bulk reset request\n"); -			raise_exception(fsg, FSG_STATE_RESET); -			value = DELAYED_STATUS; -			break; - -		case US_BULK_GET_MAX_LUN: -			if (ctrl->bRequestType != (USB_DIR_IN | -					USB_TYPE_CLASS | USB_RECIP_INTERFACE)) -				break; -			if (w_index != 0 || w_value != 0 || w_length != 1) { -				value = -EDOM; -				break; -			} -			VDBG(fsg, "get max LUN\n"); -			*(u8 *) req->buf = fsg->nluns - 1; -			value = 1; -			break; -		} -	} - -	/* Handle CBI class-specific requests */ -	else { -		switch (ctrl->bRequest) { - -		case USB_CBI_ADSC_REQUEST: -			if (ctrl->bRequestType != (USB_DIR_OUT | -					USB_TYPE_CLASS | USB_RECIP_INTERFACE)) -				break; -			if (w_index != 0 || w_value != 0) { -				value = -EDOM; -				break; -			} -			if (w_length > MAX_COMMAND_SIZE) { -				value = -EOVERFLOW; -				break; -			} -			value = w_length; -			fsg->ep0req->context = received_cbi_adsc; -			break; -		} -	} - -	if (value == -EOPNOTSUPP) -		VDBG(fsg, -			"unknown class-specific control req " -			"%02x.%02x v%04x i%04x l%u\n", -			ctrl->bRequestType, ctrl->bRequest, -			le16_to_cpu(ctrl->wValue), w_index, w_length); -	return value; -} - - -/*-------------------------------------------------------------------------*/ - -/* Ep0 standard request handlers.  These always run in_irq. */ - -static int standard_setup_req(struct fsg_dev *fsg, -		const struct usb_ctrlrequest *ctrl) -{ -	struct usb_request	*req = fsg->ep0req; -	int			value = -EOPNOTSUPP; -	u16			w_index = le16_to_cpu(ctrl->wIndex); -	u16			w_value = le16_to_cpu(ctrl->wValue); - -	/* Usually this just stores reply data in the pre-allocated ep0 buffer, -	 * but config change events will also reconfigure hardware. */ -	switch (ctrl->bRequest) { - -	case USB_REQ_GET_DESCRIPTOR: -		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | -				USB_RECIP_DEVICE)) -			break; -		switch (w_value >> 8) { - -		case USB_DT_DEVICE: -			VDBG(fsg, "get device descriptor\n"); -			device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket; -			value = sizeof device_desc; -			memcpy(req->buf, &device_desc, value); -			break; -		case USB_DT_DEVICE_QUALIFIER: -			VDBG(fsg, "get device qualifier\n"); -			if (!gadget_is_dualspeed(fsg->gadget) || -					fsg->gadget->speed == USB_SPEED_SUPER) -				break; -			/* -			 * Assume ep0 uses the same maxpacket value for both -			 * speeds -			 */ -			dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket; -			value = sizeof dev_qualifier; -			memcpy(req->buf, &dev_qualifier, value); -			break; - -		case USB_DT_OTHER_SPEED_CONFIG: -			VDBG(fsg, "get other-speed config descriptor\n"); -			if (!gadget_is_dualspeed(fsg->gadget) || -					fsg->gadget->speed == USB_SPEED_SUPER) -				break; -			goto get_config; -		case USB_DT_CONFIG: -			VDBG(fsg, "get configuration descriptor\n"); -get_config: -			value = populate_config_buf(fsg->gadget, -					req->buf, -					w_value >> 8, -					w_value & 0xff); -			break; - -		case USB_DT_STRING: -			VDBG(fsg, "get string descriptor\n"); - -			/* wIndex == language code */ -			value = usb_gadget_get_string(&fsg_stringtab, -					w_value & 0xff, req->buf); -			break; - -		case USB_DT_BOS: -			VDBG(fsg, "get bos descriptor\n"); - -			if (gadget_is_superspeed(fsg->gadget)) -				value = populate_bos(fsg, req->buf); -			break; -		} - -		break; - -	/* One config, two speeds */ -	case USB_REQ_SET_CONFIGURATION: -		if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD | -				USB_RECIP_DEVICE)) -			break; -		VDBG(fsg, "set configuration\n"); -		if (w_value == CONFIG_VALUE || w_value == 0) { -			fsg->new_config = w_value; - -			/* Raise an exception to wipe out previous transaction -			 * state (queued bufs, etc) and set the new config. */ -			raise_exception(fsg, FSG_STATE_CONFIG_CHANGE); -			value = DELAYED_STATUS; -		} -		break; -	case USB_REQ_GET_CONFIGURATION: -		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | -				USB_RECIP_DEVICE)) -			break; -		VDBG(fsg, "get configuration\n"); -		*(u8 *) req->buf = fsg->config; -		value = 1; -		break; - -	case USB_REQ_SET_INTERFACE: -		if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD | -				USB_RECIP_INTERFACE)) -			break; -		if (fsg->config && w_index == 0) { - -			/* Raise an exception to wipe out previous transaction -			 * state (queued bufs, etc) and install the new -			 * interface altsetting. */ -			raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE); -			value = DELAYED_STATUS; -		} -		break; -	case USB_REQ_GET_INTERFACE: -		if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | -				USB_RECIP_INTERFACE)) -			break; -		if (!fsg->config) -			break; -		if (w_index != 0) { -			value = -EDOM; -			break; -		} -		VDBG(fsg, "get interface\n"); -		*(u8 *) req->buf = 0; -		value = 1; -		break; - -	default: -		VDBG(fsg, -			"unknown control req %02x.%02x v%04x i%04x l%u\n", -			ctrl->bRequestType, ctrl->bRequest, -			w_value, w_index, le16_to_cpu(ctrl->wLength)); -	} - -	return value; -} - - -static int fsg_setup(struct usb_gadget *gadget, -		const struct usb_ctrlrequest *ctrl) -{ -	struct fsg_dev		*fsg = get_gadget_data(gadget); -	int			rc; -	int			w_length = le16_to_cpu(ctrl->wLength); - -	++fsg->ep0_req_tag;		// Record arrival of a new request -	fsg->ep0req->context = NULL; -	fsg->ep0req->length = 0; -	dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl)); - -	if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) -		rc = class_setup_req(fsg, ctrl); -	else -		rc = standard_setup_req(fsg, ctrl); - -	/* Respond with data/status or defer until later? */ -	if (rc >= 0 && rc != DELAYED_STATUS) { -		rc = min(rc, w_length); -		fsg->ep0req->length = rc; -		fsg->ep0req->zero = rc < w_length; -		fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ? -				"ep0-in" : "ep0-out"); -		rc = ep0_queue(fsg); -	} - -	/* Device either stalls (rc < 0) or reports success */ -	return rc; -} - - -/*-------------------------------------------------------------------------*/ - -/* All the following routines run in process context */ - - -/* Use this for bulk or interrupt transfers, not ep0 */ -static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, -		struct usb_request *req, int *pbusy, -		enum fsg_buffer_state *state) -{ -	int	rc; - -	if (ep == fsg->bulk_in) -		dump_msg(fsg, "bulk-in", req->buf, req->length); -	else if (ep == fsg->intr_in) -		dump_msg(fsg, "intr-in", req->buf, req->length); - -	spin_lock_irq(&fsg->lock); -	*pbusy = 1; -	*state = BUF_STATE_BUSY; -	spin_unlock_irq(&fsg->lock); -	rc = usb_ep_queue(ep, req, GFP_KERNEL); -	if (rc != 0) { -		*pbusy = 0; -		*state = BUF_STATE_EMPTY; - -		/* We can't do much more than wait for a reset */ - -		/* Note: currently the net2280 driver fails zero-length -		 * submissions if DMA is enabled. */ -		if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && -						req->length == 0)) -			WARNING(fsg, "error in submission: %s --> %d\n", -					ep->name, rc); -	} -} - - -static int sleep_thread(struct fsg_dev *fsg) -{ -	int	rc = 0; - -	/* Wait until a signal arrives or we are woken up */ -	for (;;) { -		try_to_freeze(); -		set_current_state(TASK_INTERRUPTIBLE); -		if (signal_pending(current)) { -			rc = -EINTR; -			break; -		} -		if (fsg->thread_wakeup_needed) -			break; -		schedule(); -	} -	__set_current_state(TASK_RUNNING); -	fsg->thread_wakeup_needed = 0; -	return rc; -} - - -/*-------------------------------------------------------------------------*/ - -static int do_read(struct fsg_dev *fsg) -{ -	struct fsg_lun		*curlun = fsg->curlun; -	u32			lba; -	struct fsg_buffhd	*bh; -	int			rc; -	u32			amount_left; -	loff_t			file_offset, file_offset_tmp; -	unsigned int		amount; -	ssize_t			nread; - -	/* Get the starting Logical Block Address and check that it's -	 * not too big */ -	if (fsg->cmnd[0] == READ_6) -		lba = get_unaligned_be24(&fsg->cmnd[1]); -	else { -		lba = get_unaligned_be32(&fsg->cmnd[2]); - -		/* We allow DPO (Disable Page Out = don't save data in the -		 * cache) and FUA (Force Unit Access = don't read from the -		 * cache), but we don't implement them. */ -		if ((fsg->cmnd[1] & ~0x18) != 0) { -			curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -			return -EINVAL; -		} -	} -	if (lba >= curlun->num_sectors) { -		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; -		return -EINVAL; -	} -	file_offset = ((loff_t) lba) << curlun->blkbits; - -	/* Carry out the file reads */ -	amount_left = fsg->data_size_from_cmnd; -	if (unlikely(amount_left == 0)) -		return -EIO;		// No default reply - -	for (;;) { - -		/* Figure out how much we need to read: -		 * Try to read the remaining amount. -		 * But don't read more than the buffer size. -		 * And don't try to read past the end of the file. -		 */ -		amount = min((unsigned int) amount_left, mod_data.buflen); -		amount = min((loff_t) amount, -				curlun->file_length - file_offset); - -		/* Wait for the next buffer to become available */ -		bh = fsg->next_buffhd_to_fill; -		while (bh->state != BUF_STATE_EMPTY) { -			rc = sleep_thread(fsg); -			if (rc) -				return rc; -		} - -		/* If we were asked to read past the end of file, -		 * end with an empty buffer. */ -		if (amount == 0) { -			curlun->sense_data = -					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; -			curlun->sense_data_info = file_offset >> curlun->blkbits; -			curlun->info_valid = 1; -			bh->inreq->length = 0; -			bh->state = BUF_STATE_FULL; -			break; -		} - -		/* Perform the read */ -		file_offset_tmp = file_offset; -		nread = vfs_read(curlun->filp, -				(char __user *) bh->buf, -				amount, &file_offset_tmp); -		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, -				(unsigned long long) file_offset, -				(int) nread); -		if (signal_pending(current)) -			return -EINTR; - -		if (nread < 0) { -			LDBG(curlun, "error in file read: %d\n", -					(int) nread); -			nread = 0; -		} else if (nread < amount) { -			LDBG(curlun, "partial file read: %d/%u\n", -					(int) nread, amount); -			nread = round_down(nread, curlun->blksize); -		} -		file_offset  += nread; -		amount_left  -= nread; -		fsg->residue -= nread; - -		/* Except at the end of the transfer, nread will be -		 * equal to the buffer size, which is divisible by the -		 * bulk-in maxpacket size. -		 */ -		bh->inreq->length = nread; -		bh->state = BUF_STATE_FULL; - -		/* If an error occurred, report it and its position */ -		if (nread < amount) { -			curlun->sense_data = SS_UNRECOVERED_READ_ERROR; -			curlun->sense_data_info = file_offset >> curlun->blkbits; -			curlun->info_valid = 1; -			break; -		} - -		if (amount_left == 0) -			break;		// No more left to read - -		/* Send this buffer and go read some more */ -		bh->inreq->zero = 0; -		start_transfer(fsg, fsg->bulk_in, bh->inreq, -				&bh->inreq_busy, &bh->state); -		fsg->next_buffhd_to_fill = bh->next; -	} - -	return -EIO;		// No default reply -} - - -/*-------------------------------------------------------------------------*/ - -static int do_write(struct fsg_dev *fsg) -{ -	struct fsg_lun		*curlun = fsg->curlun; -	u32			lba; -	struct fsg_buffhd	*bh; -	int			get_some_more; -	u32			amount_left_to_req, amount_left_to_write; -	loff_t			usb_offset, file_offset, file_offset_tmp; -	unsigned int		amount; -	ssize_t			nwritten; -	int			rc; - -	if (curlun->ro) { -		curlun->sense_data = SS_WRITE_PROTECTED; -		return -EINVAL; -	} -	spin_lock(&curlun->filp->f_lock); -	curlun->filp->f_flags &= ~O_SYNC;	// Default is not to wait -	spin_unlock(&curlun->filp->f_lock); - -	/* Get the starting Logical Block Address and check that it's -	 * not too big */ -	if (fsg->cmnd[0] == WRITE_6) -		lba = get_unaligned_be24(&fsg->cmnd[1]); -	else { -		lba = get_unaligned_be32(&fsg->cmnd[2]); - -		/* We allow DPO (Disable Page Out = don't save data in the -		 * cache) and FUA (Force Unit Access = write directly to the -		 * medium).  We don't implement DPO; we implement FUA by -		 * performing synchronous output. */ -		if ((fsg->cmnd[1] & ~0x18) != 0) { -			curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -			return -EINVAL; -		} -		/* FUA */ -		if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) { -			spin_lock(&curlun->filp->f_lock); -			curlun->filp->f_flags |= O_DSYNC; -			spin_unlock(&curlun->filp->f_lock); -		} -	} -	if (lba >= curlun->num_sectors) { -		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; -		return -EINVAL; -	} - -	/* Carry out the file writes */ -	get_some_more = 1; -	file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits; -	amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd; - -	while (amount_left_to_write > 0) { - -		/* Queue a request for more data from the host */ -		bh = fsg->next_buffhd_to_fill; -		if (bh->state == BUF_STATE_EMPTY && get_some_more) { - -			/* Figure out how much we want to get: -			 * Try to get the remaining amount, -			 * but not more than the buffer size. -			 */ -			amount = min(amount_left_to_req, mod_data.buflen); - -			/* Beyond the end of the backing file? */ -			if (usb_offset >= curlun->file_length) { -				get_some_more = 0; -				curlun->sense_data = -					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; -				curlun->sense_data_info = usb_offset >> curlun->blkbits; -				curlun->info_valid = 1; -				continue; -			} - -			/* Get the next buffer */ -			usb_offset += amount; -			fsg->usb_amount_left -= amount; -			amount_left_to_req -= amount; -			if (amount_left_to_req == 0) -				get_some_more = 0; - -			/* Except at the end of the transfer, amount will be -			 * equal to the buffer size, which is divisible by -			 * the bulk-out maxpacket size. -			 */ -			set_bulk_out_req_length(fsg, bh, amount); -			start_transfer(fsg, fsg->bulk_out, bh->outreq, -					&bh->outreq_busy, &bh->state); -			fsg->next_buffhd_to_fill = bh->next; -			continue; -		} - -		/* Write the received data to the backing file */ -		bh = fsg->next_buffhd_to_drain; -		if (bh->state == BUF_STATE_EMPTY && !get_some_more) -			break;			// We stopped early -		if (bh->state == BUF_STATE_FULL) { -			smp_rmb(); -			fsg->next_buffhd_to_drain = bh->next; -			bh->state = BUF_STATE_EMPTY; - -			/* Did something go wrong with the transfer? */ -			if (bh->outreq->status != 0) { -				curlun->sense_data = SS_COMMUNICATION_FAILURE; -				curlun->sense_data_info = file_offset >> curlun->blkbits; -				curlun->info_valid = 1; -				break; -			} - -			amount = bh->outreq->actual; -			if (curlun->file_length - file_offset < amount) { -				LERROR(curlun, -	"write %u @ %llu beyond end %llu\n", -	amount, (unsigned long long) file_offset, -	(unsigned long long) curlun->file_length); -				amount = curlun->file_length - file_offset; -			} - -			/* Don't accept excess data.  The spec doesn't say -			 * what to do in this case.  We'll ignore the error. -			 */ -			amount = min(amount, bh->bulk_out_intended_length); - -			/* Don't write a partial block */ -			amount = round_down(amount, curlun->blksize); -			if (amount == 0) -				goto empty_write; - -			/* Perform the write */ -			file_offset_tmp = file_offset; -			nwritten = vfs_write(curlun->filp, -					(char __user *) bh->buf, -					amount, &file_offset_tmp); -			VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, -					(unsigned long long) file_offset, -					(int) nwritten); -			if (signal_pending(current)) -				return -EINTR;		// Interrupted! - -			if (nwritten < 0) { -				LDBG(curlun, "error in file write: %d\n", -						(int) nwritten); -				nwritten = 0; -			} else if (nwritten < amount) { -				LDBG(curlun, "partial file write: %d/%u\n", -						(int) nwritten, amount); -				nwritten = round_down(nwritten, curlun->blksize); -			} -			file_offset += nwritten; -			amount_left_to_write -= nwritten; -			fsg->residue -= nwritten; - -			/* If an error occurred, report it and its position */ -			if (nwritten < amount) { -				curlun->sense_data = SS_WRITE_ERROR; -				curlun->sense_data_info = file_offset >> curlun->blkbits; -				curlun->info_valid = 1; -				break; -			} - - empty_write: -			/* Did the host decide to stop early? */ -			if (bh->outreq->actual < bh->bulk_out_intended_length) { -				fsg->short_packet_received = 1; -				break; -			} -			continue; -		} - -		/* Wait for something to happen */ -		rc = sleep_thread(fsg); -		if (rc) -			return rc; -	} - -	return -EIO;		// No default reply -} - - -/*-------------------------------------------------------------------------*/ - -static int do_synchronize_cache(struct fsg_dev *fsg) -{ -	struct fsg_lun	*curlun = fsg->curlun; -	int		rc; - -	/* We ignore the requested LBA and write out all file's -	 * dirty data buffers. */ -	rc = fsg_lun_fsync_sub(curlun); -	if (rc) -		curlun->sense_data = SS_WRITE_ERROR; -	return 0; -} - - -/*-------------------------------------------------------------------------*/ - -static void invalidate_sub(struct fsg_lun *curlun) -{ -	struct file	*filp = curlun->filp; -	struct inode	*inode = filp->f_path.dentry->d_inode; -	unsigned long	rc; - -	rc = invalidate_mapping_pages(inode->i_mapping, 0, -1); -	VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc); -} - -static int do_verify(struct fsg_dev *fsg) -{ -	struct fsg_lun		*curlun = fsg->curlun; -	u32			lba; -	u32			verification_length; -	struct fsg_buffhd	*bh = fsg->next_buffhd_to_fill; -	loff_t			file_offset, file_offset_tmp; -	u32			amount_left; -	unsigned int		amount; -	ssize_t			nread; - -	/* Get the starting Logical Block Address and check that it's -	 * not too big */ -	lba = get_unaligned_be32(&fsg->cmnd[2]); -	if (lba >= curlun->num_sectors) { -		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; -		return -EINVAL; -	} - -	/* We allow DPO (Disable Page Out = don't save data in the -	 * cache) but we don't implement it. */ -	if ((fsg->cmnd[1] & ~0x10) != 0) { -		curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -		return -EINVAL; -	} - -	verification_length = get_unaligned_be16(&fsg->cmnd[7]); -	if (unlikely(verification_length == 0)) -		return -EIO;		// No default reply - -	/* Prepare to carry out the file verify */ -	amount_left = verification_length << curlun->blkbits; -	file_offset = ((loff_t) lba) << curlun->blkbits; - -	/* Write out all the dirty buffers before invalidating them */ -	fsg_lun_fsync_sub(curlun); -	if (signal_pending(current)) -		return -EINTR; - -	invalidate_sub(curlun); -	if (signal_pending(current)) -		return -EINTR; - -	/* Just try to read the requested blocks */ -	while (amount_left > 0) { - -		/* Figure out how much we need to read: -		 * Try to read the remaining amount, but not more than -		 * the buffer size. -		 * And don't try to read past the end of the file. -		 */ -		amount = min((unsigned int) amount_left, mod_data.buflen); -		amount = min((loff_t) amount, -				curlun->file_length - file_offset); -		if (amount == 0) { -			curlun->sense_data = -					SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; -			curlun->sense_data_info = file_offset >> curlun->blkbits; -			curlun->info_valid = 1; -			break; -		} - -		/* Perform the read */ -		file_offset_tmp = file_offset; -		nread = vfs_read(curlun->filp, -				(char __user *) bh->buf, -				amount, &file_offset_tmp); -		VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, -				(unsigned long long) file_offset, -				(int) nread); -		if (signal_pending(current)) -			return -EINTR; - -		if (nread < 0) { -			LDBG(curlun, "error in file verify: %d\n", -					(int) nread); -			nread = 0; -		} else if (nread < amount) { -			LDBG(curlun, "partial file verify: %d/%u\n", -					(int) nread, amount); -			nread = round_down(nread, curlun->blksize); -		} -		if (nread == 0) { -			curlun->sense_data = SS_UNRECOVERED_READ_ERROR; -			curlun->sense_data_info = file_offset >> curlun->blkbits; -			curlun->info_valid = 1; -			break; -		} -		file_offset += nread; -		amount_left -= nread; -	} -	return 0; -} - - -/*-------------------------------------------------------------------------*/ - -static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) -{ -	u8	*buf = (u8 *) bh->buf; - -	static char vendor_id[] = "Linux   "; -	static char product_disk_id[] = "File-Stor Gadget"; -	static char product_cdrom_id[] = "File-CD Gadget  "; - -	if (!fsg->curlun) {		// Unsupported LUNs are okay -		fsg->bad_lun_okay = 1; -		memset(buf, 0, 36); -		buf[0] = 0x7f;		// Unsupported, no device-type -		buf[4] = 31;		// Additional length -		return 36; -	} - -	memset(buf, 0, 8); -	buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK); -	if (mod_data.removable) -		buf[1] = 0x80; -	buf[2] = 2;		// ANSI SCSI level 2 -	buf[3] = 2;		// SCSI-2 INQUIRY data format -	buf[4] = 31;		// Additional length -				// No special options -	sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, -			(mod_data.cdrom ? product_cdrom_id : -				product_disk_id), -			mod_data.release); -	return 36; -} - - -static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) -{ -	struct fsg_lun	*curlun = fsg->curlun; -	u8		*buf = (u8 *) bh->buf; -	u32		sd, sdinfo; -	int		valid; - -	/* -	 * From the SCSI-2 spec., section 7.9 (Unit attention condition): -	 * -	 * If a REQUEST SENSE command is received from an initiator -	 * with a pending unit attention condition (before the target -	 * generates the contingent allegiance condition), then the -	 * target shall either: -	 *   a) report any pending sense data and preserve the unit -	 *	attention condition on the logical unit, or, -	 *   b) report the unit attention condition, may discard any -	 *	pending sense data, and clear the unit attention -	 *	condition on the logical unit for that initiator. -	 * -	 * FSG normally uses option a); enable this code to use option b). -	 */ -#if 0 -	if (curlun && curlun->unit_attention_data != SS_NO_SENSE) { -		curlun->sense_data = curlun->unit_attention_data; -		curlun->unit_attention_data = SS_NO_SENSE; -	} -#endif - -	if (!curlun) {		// Unsupported LUNs are okay -		fsg->bad_lun_okay = 1; -		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; -		sdinfo = 0; -		valid = 0; -	} else { -		sd = curlun->sense_data; -		sdinfo = curlun->sense_data_info; -		valid = curlun->info_valid << 7; -		curlun->sense_data = SS_NO_SENSE; -		curlun->sense_data_info = 0; -		curlun->info_valid = 0; -	} - -	memset(buf, 0, 18); -	buf[0] = valid | 0x70;			// Valid, current error -	buf[2] = SK(sd); -	put_unaligned_be32(sdinfo, &buf[3]);	/* Sense information */ -	buf[7] = 18 - 8;			// Additional sense length -	buf[12] = ASC(sd); -	buf[13] = ASCQ(sd); -	return 18; -} - - -static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh) -{ -	struct fsg_lun	*curlun = fsg->curlun; -	u32		lba = get_unaligned_be32(&fsg->cmnd[2]); -	int		pmi = fsg->cmnd[8]; -	u8		*buf = (u8 *) bh->buf; - -	/* Check the PMI and LBA fields */ -	if (pmi > 1 || (pmi == 0 && lba != 0)) { -		curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -		return -EINVAL; -	} - -	put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); -						/* Max logical block */ -	put_unaligned_be32(curlun->blksize, &buf[4]);	/* Block length */ -	return 8; -} - - -static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh) -{ -	struct fsg_lun	*curlun = fsg->curlun; -	int		msf = fsg->cmnd[1] & 0x02; -	u32		lba = get_unaligned_be32(&fsg->cmnd[2]); -	u8		*buf = (u8 *) bh->buf; - -	if ((fsg->cmnd[1] & ~0x02) != 0) {		/* Mask away MSF */ -		curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -		return -EINVAL; -	} -	if (lba >= curlun->num_sectors) { -		curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; -		return -EINVAL; -	} - -	memset(buf, 0, 8); -	buf[0] = 0x01;		/* 2048 bytes of user data, rest is EC */ -	store_cdrom_address(&buf[4], msf, lba); -	return 8; -} - - -static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh) -{ -	struct fsg_lun	*curlun = fsg->curlun; -	int		msf = fsg->cmnd[1] & 0x02; -	int		start_track = fsg->cmnd[6]; -	u8		*buf = (u8 *) bh->buf; - -	if ((fsg->cmnd[1] & ~0x02) != 0 ||		/* Mask away MSF */ -			start_track > 1) { -		curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -		return -EINVAL; -	} - -	memset(buf, 0, 20); -	buf[1] = (20-2);		/* TOC data length */ -	buf[2] = 1;			/* First track number */ -	buf[3] = 1;			/* Last track number */ -	buf[5] = 0x16;			/* Data track, copying allowed */ -	buf[6] = 0x01;			/* Only track is number 1 */ -	store_cdrom_address(&buf[8], msf, 0); - -	buf[13] = 0x16;			/* Lead-out track is data */ -	buf[14] = 0xAA;			/* Lead-out track number */ -	store_cdrom_address(&buf[16], msf, curlun->num_sectors); -	return 20; -} - - -static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) -{ -	struct fsg_lun	*curlun = fsg->curlun; -	int		mscmnd = fsg->cmnd[0]; -	u8		*buf = (u8 *) bh->buf; -	u8		*buf0 = buf; -	int		pc, page_code; -	int		changeable_values, all_pages; -	int		valid_page = 0; -	int		len, limit; - -	if ((fsg->cmnd[1] & ~0x08) != 0) {		// Mask away DBD -		curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -		return -EINVAL; -	} -	pc = fsg->cmnd[2] >> 6; -	page_code = fsg->cmnd[2] & 0x3f; -	if (pc == 3) { -		curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; -		return -EINVAL; -	} -	changeable_values = (pc == 1); -	all_pages = (page_code == 0x3f); - -	/* Write the mode parameter header.  Fixed values are: default -	 * medium type, no cache control (DPOFUA), and no block descriptors. -	 * The only variable value is the WriteProtect bit.  We will fill in -	 * the mode data length later. */ -	memset(buf, 0, 8); -	if (mscmnd == MODE_SENSE) { -		buf[2] = (curlun->ro ? 0x80 : 0x00);		// WP, DPOFUA -		buf += 4; -		limit = 255; -	} else {			// MODE_SENSE_10 -		buf[3] = (curlun->ro ? 0x80 : 0x00);		// WP, DPOFUA -		buf += 8; -		limit = 65535;		// Should really be mod_data.buflen -	} - -	/* No block descriptors */ - -	/* The mode pages, in numerical order.  The only page we support -	 * is the Caching page. */ -	if (page_code == 0x08 || all_pages) { -		valid_page = 1; -		buf[0] = 0x08;		// Page code -		buf[1] = 10;		// Page length -		memset(buf+2, 0, 10);	// None of the fields are changeable - -		if (!changeable_values) { -			buf[2] = 0x04;	// Write cache enable, -					// Read cache not disabled -					// No cache retention priorities -			put_unaligned_be16(0xffff, &buf[4]); -					/* Don't disable prefetch */ -					/* Minimum prefetch = 0 */ -			put_unaligned_be16(0xffff, &buf[8]); -					/* Maximum prefetch */ -			put_unaligned_be16(0xffff, &buf[10]); -					/* Maximum prefetch ceiling */ -		} -		buf += 12; -	} - -	/* Check that a valid page was requested and the mode data length -	 * isn't too long. */ -	len = buf - buf0; -	if (!valid_page || len > limit) { -		curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -		return -EINVAL; -	} - -	/*  Store the mode data length */ -	if (mscmnd == MODE_SENSE) -		buf0[0] = len - 1; -	else -		put_unaligned_be16(len - 2, buf0); -	return len; -} - - -static int do_start_stop(struct fsg_dev *fsg) -{ -	struct fsg_lun	*curlun = fsg->curlun; -	int		loej, start; - -	if (!mod_data.removable) { -		curlun->sense_data = SS_INVALID_COMMAND; -		return -EINVAL; -	} - -	// int immed = fsg->cmnd[1] & 0x01; -	loej = fsg->cmnd[4] & 0x02; -	start = fsg->cmnd[4] & 0x01; - -#ifdef CONFIG_USB_FILE_STORAGE_TEST -	if ((fsg->cmnd[1] & ~0x01) != 0 ||		// Mask away Immed -			(fsg->cmnd[4] & ~0x03) != 0) {	// Mask LoEj, Start -		curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -		return -EINVAL; -	} - -	if (!start) { - -		/* Are we allowed to unload the media? */ -		if (curlun->prevent_medium_removal) { -			LDBG(curlun, "unload attempt prevented\n"); -			curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED; -			return -EINVAL; -		} -		if (loej) {		// Simulate an unload/eject -			up_read(&fsg->filesem); -			down_write(&fsg->filesem); -			fsg_lun_close(curlun); -			up_write(&fsg->filesem); -			down_read(&fsg->filesem); -		} -	} else { - -		/* Our emulation doesn't support mounting; the medium is -		 * available for use as soon as it is loaded. */ -		if (!fsg_lun_is_open(curlun)) { -			curlun->sense_data = SS_MEDIUM_NOT_PRESENT; -			return -EINVAL; -		} -	} -#endif -	return 0; -} - - -static int do_prevent_allow(struct fsg_dev *fsg) -{ -	struct fsg_lun	*curlun = fsg->curlun; -	int		prevent; - -	if (!mod_data.removable) { -		curlun->sense_data = SS_INVALID_COMMAND; -		return -EINVAL; -	} - -	prevent = fsg->cmnd[4] & 0x01; -	if ((fsg->cmnd[4] & ~0x01) != 0) {		// Mask away Prevent -		curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -		return -EINVAL; -	} - -	if (curlun->prevent_medium_removal && !prevent) -		fsg_lun_fsync_sub(curlun); -	curlun->prevent_medium_removal = prevent; -	return 0; -} - - -static int do_read_format_capacities(struct fsg_dev *fsg, -			struct fsg_buffhd *bh) -{ -	struct fsg_lun	*curlun = fsg->curlun; -	u8		*buf = (u8 *) bh->buf; - -	buf[0] = buf[1] = buf[2] = 0; -	buf[3] = 8;		// Only the Current/Maximum Capacity Descriptor -	buf += 4; - -	put_unaligned_be32(curlun->num_sectors, &buf[0]); -						/* Number of blocks */ -	put_unaligned_be32(curlun->blksize, &buf[4]);	/* Block length */ -	buf[4] = 0x02;				/* Current capacity */ -	return 12; -} - - -static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh) -{ -	struct fsg_lun	*curlun = fsg->curlun; - -	/* We don't support MODE SELECT */ -	curlun->sense_data = SS_INVALID_COMMAND; -	return -EINVAL; -} - - -/*-------------------------------------------------------------------------*/ - -static int halt_bulk_in_endpoint(struct fsg_dev *fsg) -{ -	int	rc; - -	rc = fsg_set_halt(fsg, fsg->bulk_in); -	if (rc == -EAGAIN) -		VDBG(fsg, "delayed bulk-in endpoint halt\n"); -	while (rc != 0) { -		if (rc != -EAGAIN) { -			WARNING(fsg, "usb_ep_set_halt -> %d\n", rc); -			rc = 0; -			break; -		} - -		/* Wait for a short time and then try again */ -		if (msleep_interruptible(100) != 0) -			return -EINTR; -		rc = usb_ep_set_halt(fsg->bulk_in); -	} -	return rc; -} - -static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) -{ -	int	rc; - -	DBG(fsg, "bulk-in set wedge\n"); -	rc = usb_ep_set_wedge(fsg->bulk_in); -	if (rc == -EAGAIN) -		VDBG(fsg, "delayed bulk-in endpoint wedge\n"); -	while (rc != 0) { -		if (rc != -EAGAIN) { -			WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc); -			rc = 0; -			break; -		} - -		/* Wait for a short time and then try again */ -		if (msleep_interruptible(100) != 0) -			return -EINTR; -		rc = usb_ep_set_wedge(fsg->bulk_in); -	} -	return rc; -} - -static int throw_away_data(struct fsg_dev *fsg) -{ -	struct fsg_buffhd	*bh; -	u32			amount; -	int			rc; - -	while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY || -			fsg->usb_amount_left > 0) { - -		/* Throw away the data in a filled buffer */ -		if (bh->state == BUF_STATE_FULL) { -			smp_rmb(); -			bh->state = BUF_STATE_EMPTY; -			fsg->next_buffhd_to_drain = bh->next; - -			/* A short packet or an error ends everything */ -			if (bh->outreq->actual < bh->bulk_out_intended_length || -					bh->outreq->status != 0) { -				raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); -				return -EINTR; -			} -			continue; -		} - -		/* Try to submit another request if we need one */ -		bh = fsg->next_buffhd_to_fill; -		if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) { -			amount = min(fsg->usb_amount_left, -					(u32) mod_data.buflen); - -			/* Except at the end of the transfer, amount will be -			 * equal to the buffer size, which is divisible by -			 * the bulk-out maxpacket size. -			 */ -			set_bulk_out_req_length(fsg, bh, amount); -			start_transfer(fsg, fsg->bulk_out, bh->outreq, -					&bh->outreq_busy, &bh->state); -			fsg->next_buffhd_to_fill = bh->next; -			fsg->usb_amount_left -= amount; -			continue; -		} - -		/* Otherwise wait for something to happen */ -		rc = sleep_thread(fsg); -		if (rc) -			return rc; -	} -	return 0; -} - - -static int finish_reply(struct fsg_dev *fsg) -{ -	struct fsg_buffhd	*bh = fsg->next_buffhd_to_fill; -	int			rc = 0; - -	switch (fsg->data_dir) { -	case DATA_DIR_NONE: -		break;			// Nothing to send - -	/* If we don't know whether the host wants to read or write, -	 * this must be CB or CBI with an unknown command.  We mustn't -	 * try to send or receive any data.  So stall both bulk pipes -	 * if we can and wait for a reset. */ -	case DATA_DIR_UNKNOWN: -		if (mod_data.can_stall) { -			fsg_set_halt(fsg, fsg->bulk_out); -			rc = halt_bulk_in_endpoint(fsg); -		} -		break; - -	/* All but the last buffer of data must have already been sent */ -	case DATA_DIR_TO_HOST: -		if (fsg->data_size == 0) -			;		// Nothing to send - -		/* If there's no residue, simply send the last buffer */ -		else if (fsg->residue == 0) { -			bh->inreq->zero = 0; -			start_transfer(fsg, fsg->bulk_in, bh->inreq, -					&bh->inreq_busy, &bh->state); -			fsg->next_buffhd_to_fill = bh->next; -		} - -		/* There is a residue.  For CB and CBI, simply mark the end -		 * of the data with a short packet.  However, if we are -		 * allowed to stall, there was no data at all (residue == -		 * data_size), and the command failed (invalid LUN or -		 * sense data is set), then halt the bulk-in endpoint -		 * instead. */ -		else if (!transport_is_bbb()) { -			if (mod_data.can_stall && -					fsg->residue == fsg->data_size && -	(!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) { -				bh->state = BUF_STATE_EMPTY; -				rc = halt_bulk_in_endpoint(fsg); -			} else { -				bh->inreq->zero = 1; -				start_transfer(fsg, fsg->bulk_in, bh->inreq, -						&bh->inreq_busy, &bh->state); -				fsg->next_buffhd_to_fill = bh->next; -			} -		} - -		/* -		 * For Bulk-only, mark the end of the data with a short -		 * packet.  If we are allowed to stall, halt the bulk-in -		 * endpoint.  (Note: This violates the Bulk-Only Transport -		 * specification, which requires us to pad the data if we -		 * don't halt the endpoint.  Presumably nobody will mind.) -		 */ -		else { -			bh->inreq->zero = 1; -			start_transfer(fsg, fsg->bulk_in, bh->inreq, -					&bh->inreq_busy, &bh->state); -			fsg->next_buffhd_to_fill = bh->next; -			if (mod_data.can_stall) -				rc = halt_bulk_in_endpoint(fsg); -		} -		break; - -	/* We have processed all we want from the data the host has sent. -	 * There may still be outstanding bulk-out requests. */ -	case DATA_DIR_FROM_HOST: -		if (fsg->residue == 0) -			;		// Nothing to receive - -		/* Did the host stop sending unexpectedly early? */ -		else if (fsg->short_packet_received) { -			raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); -			rc = -EINTR; -		} - -		/* We haven't processed all the incoming data.  Even though -		 * we may be allowed to stall, doing so would cause a race. -		 * The controller may already have ACK'ed all the remaining -		 * bulk-out packets, in which case the host wouldn't see a -		 * STALL.  Not realizing the endpoint was halted, it wouldn't -		 * clear the halt -- leading to problems later on. */ -#if 0 -		else if (mod_data.can_stall) { -			fsg_set_halt(fsg, fsg->bulk_out); -			raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); -			rc = -EINTR; -		} -#endif - -		/* We can't stall.  Read in the excess data and throw it -		 * all away. */ -		else -			rc = throw_away_data(fsg); -		break; -	} -	return rc; -} - - -static int send_status(struct fsg_dev *fsg) -{ -	struct fsg_lun		*curlun = fsg->curlun; -	struct fsg_buffhd	*bh; -	int			rc; -	u8			status = US_BULK_STAT_OK; -	u32			sd, sdinfo = 0; - -	/* Wait for the next buffer to become available */ -	bh = fsg->next_buffhd_to_fill; -	while (bh->state != BUF_STATE_EMPTY) { -		rc = sleep_thread(fsg); -		if (rc) -			return rc; -	} - -	if (curlun) { -		sd = curlun->sense_data; -		sdinfo = curlun->sense_data_info; -	} else if (fsg->bad_lun_okay) -		sd = SS_NO_SENSE; -	else -		sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; - -	if (fsg->phase_error) { -		DBG(fsg, "sending phase-error status\n"); -		status = US_BULK_STAT_PHASE; -		sd = SS_INVALID_COMMAND; -	} else if (sd != SS_NO_SENSE) { -		DBG(fsg, "sending command-failure status\n"); -		status = US_BULK_STAT_FAIL; -		VDBG(fsg, "  sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" -				"  info x%x\n", -				SK(sd), ASC(sd), ASCQ(sd), sdinfo); -	} - -	if (transport_is_bbb()) { -		struct bulk_cs_wrap	*csw = bh->buf; - -		/* Store and send the Bulk-only CSW */ -		csw->Signature = cpu_to_le32(US_BULK_CS_SIGN); -		csw->Tag = fsg->tag; -		csw->Residue = cpu_to_le32(fsg->residue); -		csw->Status = status; - -		bh->inreq->length = US_BULK_CS_WRAP_LEN; -		bh->inreq->zero = 0; -		start_transfer(fsg, fsg->bulk_in, bh->inreq, -				&bh->inreq_busy, &bh->state); - -	} else if (mod_data.transport_type == USB_PR_CB) { - -		/* Control-Bulk transport has no status phase! */ -		return 0; - -	} else {			// USB_PR_CBI -		struct interrupt_data	*buf = bh->buf; - -		/* Store and send the Interrupt data.  UFI sends the ASC -		 * and ASCQ bytes.  Everything else sends a Type (which -		 * is always 0) and the status Value. */ -		if (mod_data.protocol_type == USB_SC_UFI) { -			buf->bType = ASC(sd); -			buf->bValue = ASCQ(sd); -		} else { -			buf->bType = 0; -			buf->bValue = status; -		} -		fsg->intreq->length = CBI_INTERRUPT_DATA_LEN; - -		fsg->intr_buffhd = bh;		// Point to the right buffhd -		fsg->intreq->buf = bh->inreq->buf; -		fsg->intreq->context = bh; -		start_transfer(fsg, fsg->intr_in, fsg->intreq, -				&fsg->intreq_busy, &bh->state); -	} - -	fsg->next_buffhd_to_fill = bh->next; -	return 0; -} - - -/*-------------------------------------------------------------------------*/ - -/* Check whether the command is properly formed and whether its data size - * and direction agree with the values we already have. */ -static int check_command(struct fsg_dev *fsg, int cmnd_size, -		enum data_direction data_dir, unsigned int mask, -		int needs_medium, const char *name) -{ -	int			i; -	int			lun = fsg->cmnd[1] >> 5; -	static const char	dirletter[4] = {'u', 'o', 'i', 'n'}; -	char			hdlen[20]; -	struct fsg_lun		*curlun; - -	/* Adjust the expected cmnd_size for protocol encapsulation padding. -	 * Transparent SCSI doesn't pad. */ -	if (protocol_is_scsi()) -		; - -	/* There's some disagreement as to whether RBC pads commands or not. -	 * We'll play it safe and accept either form. */ -	else if (mod_data.protocol_type == USB_SC_RBC) { -		if (fsg->cmnd_size == 12) -			cmnd_size = 12; - -	/* All the other protocols pad to 12 bytes */ -	} else -		cmnd_size = 12; - -	hdlen[0] = 0; -	if (fsg->data_dir != DATA_DIR_UNKNOWN) -		sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir], -				fsg->data_size); -	VDBG(fsg, "SCSI command: %s;  Dc=%d, D%c=%u;  Hc=%d%s\n", -			name, cmnd_size, dirletter[(int) data_dir], -			fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen); - -	/* We can't reply at all until we know the correct data direction -	 * and size. */ -	if (fsg->data_size_from_cmnd == 0) -		data_dir = DATA_DIR_NONE; -	if (fsg->data_dir == DATA_DIR_UNKNOWN) {	// CB or CBI -		fsg->data_dir = data_dir; -		fsg->data_size = fsg->data_size_from_cmnd; - -	} else {					// Bulk-only -		if (fsg->data_size < fsg->data_size_from_cmnd) { - -			/* Host data size < Device data size is a phase error. -			 * Carry out the command, but only transfer as much -			 * as we are allowed. */ -			fsg->data_size_from_cmnd = fsg->data_size; -			fsg->phase_error = 1; -		} -	} -	fsg->residue = fsg->usb_amount_left = fsg->data_size; - -	/* Conflicting data directions is a phase error */ -	if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) { -		fsg->phase_error = 1; -		return -EINVAL; -	} - -	/* Verify the length of the command itself */ -	if (cmnd_size != fsg->cmnd_size) { - -		/* Special case workaround: There are plenty of buggy SCSI -		 * implementations. Many have issues with cbw->Length -		 * field passing a wrong command size. For those cases we -		 * always try to work around the problem by using the length -		 * sent by the host side provided it is at least as large -		 * as the correct command length. -		 * Examples of such cases would be MS-Windows, which issues -		 * REQUEST SENSE with cbw->Length == 12 where it should -		 * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and -		 * REQUEST SENSE with cbw->Length == 10 where it should -		 * be 6 as well. -		 */ -		if (cmnd_size <= fsg->cmnd_size) { -			DBG(fsg, "%s is buggy! Expected length %d " -					"but we got %d\n", name, -					cmnd_size, fsg->cmnd_size); -			cmnd_size = fsg->cmnd_size; -		} else { -			fsg->phase_error = 1; -			return -EINVAL; -		} -	} - -	/* Check that the LUN values are consistent */ -	if (transport_is_bbb()) { -		if (fsg->lun != lun) -			DBG(fsg, "using LUN %d from CBW, " -					"not LUN %d from CDB\n", -					fsg->lun, lun); -	} - -	/* Check the LUN */ -	curlun = fsg->curlun; -	if (curlun) { -		if (fsg->cmnd[0] != REQUEST_SENSE) { -			curlun->sense_data = SS_NO_SENSE; -			curlun->sense_data_info = 0; -			curlun->info_valid = 0; -		} -	} else { -		fsg->bad_lun_okay = 0; - -		/* INQUIRY and REQUEST SENSE commands are explicitly allowed -		 * to use unsupported LUNs; all others may not. */ -		if (fsg->cmnd[0] != INQUIRY && -				fsg->cmnd[0] != REQUEST_SENSE) { -			DBG(fsg, "unsupported LUN %d\n", fsg->lun); -			return -EINVAL; -		} -	} - -	/* If a unit attention condition exists, only INQUIRY and -	 * REQUEST SENSE commands are allowed; anything else must fail. */ -	if (curlun && curlun->unit_attention_data != SS_NO_SENSE && -			fsg->cmnd[0] != INQUIRY && -			fsg->cmnd[0] != REQUEST_SENSE) { -		curlun->sense_data = curlun->unit_attention_data; -		curlun->unit_attention_data = SS_NO_SENSE; -		return -EINVAL; -	} - -	/* Check that only command bytes listed in the mask are non-zero */ -	fsg->cmnd[1] &= 0x1f;			// Mask away the LUN -	for (i = 1; i < cmnd_size; ++i) { -		if (fsg->cmnd[i] && !(mask & (1 << i))) { -			if (curlun) -				curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -			return -EINVAL; -		} -	} - -	/* If the medium isn't mounted and the command needs to access -	 * it, return an error. */ -	if (curlun && !fsg_lun_is_open(curlun) && needs_medium) { -		curlun->sense_data = SS_MEDIUM_NOT_PRESENT; -		return -EINVAL; -	} - -	return 0; -} - -/* wrapper of check_command for data size in blocks handling */ -static int check_command_size_in_blocks(struct fsg_dev *fsg, int cmnd_size, -		enum data_direction data_dir, unsigned int mask, -		int needs_medium, const char *name) -{ -	if (fsg->curlun) -		fsg->data_size_from_cmnd <<= fsg->curlun->blkbits; -	return check_command(fsg, cmnd_size, data_dir, -			mask, needs_medium, name); -} - -static int do_scsi_command(struct fsg_dev *fsg) -{ -	struct fsg_buffhd	*bh; -	int			rc; -	int			reply = -EINVAL; -	int			i; -	static char		unknown[16]; - -	dump_cdb(fsg); - -	/* Wait for the next buffer to become available for data or status */ -	bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill; -	while (bh->state != BUF_STATE_EMPTY) { -		rc = sleep_thread(fsg); -		if (rc) -			return rc; -	} -	fsg->phase_error = 0; -	fsg->short_packet_received = 0; - -	down_read(&fsg->filesem);	// We're using the backing file -	switch (fsg->cmnd[0]) { - -	case INQUIRY: -		fsg->data_size_from_cmnd = fsg->cmnd[4]; -		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, -				(1<<4), 0, -				"INQUIRY")) == 0) -			reply = do_inquiry(fsg, bh); -		break; - -	case MODE_SELECT: -		fsg->data_size_from_cmnd = fsg->cmnd[4]; -		if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST, -				(1<<1) | (1<<4), 0, -				"MODE SELECT(6)")) == 0) -			reply = do_mode_select(fsg, bh); -		break; - -	case MODE_SELECT_10: -		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); -		if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST, -				(1<<1) | (3<<7), 0, -				"MODE SELECT(10)")) == 0) -			reply = do_mode_select(fsg, bh); -		break; - -	case MODE_SENSE: -		fsg->data_size_from_cmnd = fsg->cmnd[4]; -		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, -				(1<<1) | (1<<2) | (1<<4), 0, -				"MODE SENSE(6)")) == 0) -			reply = do_mode_sense(fsg, bh); -		break; - -	case MODE_SENSE_10: -		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); -		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, -				(1<<1) | (1<<2) | (3<<7), 0, -				"MODE SENSE(10)")) == 0) -			reply = do_mode_sense(fsg, bh); -		break; - -	case ALLOW_MEDIUM_REMOVAL: -		fsg->data_size_from_cmnd = 0; -		if ((reply = check_command(fsg, 6, DATA_DIR_NONE, -				(1<<4), 0, -				"PREVENT-ALLOW MEDIUM REMOVAL")) == 0) -			reply = do_prevent_allow(fsg); -		break; - -	case READ_6: -		i = fsg->cmnd[4]; -		fsg->data_size_from_cmnd = (i == 0) ? 256 : i; -		if ((reply = check_command_size_in_blocks(fsg, 6, -				DATA_DIR_TO_HOST, -				(7<<1) | (1<<4), 1, -				"READ(6)")) == 0) -			reply = do_read(fsg); -		break; - -	case READ_10: -		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); -		if ((reply = check_command_size_in_blocks(fsg, 10, -				DATA_DIR_TO_HOST, -				(1<<1) | (0xf<<2) | (3<<7), 1, -				"READ(10)")) == 0) -			reply = do_read(fsg); -		break; - -	case READ_12: -		fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]); -		if ((reply = check_command_size_in_blocks(fsg, 12, -				DATA_DIR_TO_HOST, -				(1<<1) | (0xf<<2) | (0xf<<6), 1, -				"READ(12)")) == 0) -			reply = do_read(fsg); -		break; - -	case READ_CAPACITY: -		fsg->data_size_from_cmnd = 8; -		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, -				(0xf<<2) | (1<<8), 1, -				"READ CAPACITY")) == 0) -			reply = do_read_capacity(fsg, bh); -		break; - -	case READ_HEADER: -		if (!mod_data.cdrom) -			goto unknown_cmnd; -		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); -		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, -				(3<<7) | (0x1f<<1), 1, -				"READ HEADER")) == 0) -			reply = do_read_header(fsg, bh); -		break; - -	case READ_TOC: -		if (!mod_data.cdrom) -			goto unknown_cmnd; -		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); -		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, -				(7<<6) | (1<<1), 1, -				"READ TOC")) == 0) -			reply = do_read_toc(fsg, bh); -		break; - -	case READ_FORMAT_CAPACITIES: -		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); -		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, -				(3<<7), 1, -				"READ FORMAT CAPACITIES")) == 0) -			reply = do_read_format_capacities(fsg, bh); -		break; - -	case REQUEST_SENSE: -		fsg->data_size_from_cmnd = fsg->cmnd[4]; -		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, -				(1<<4), 0, -				"REQUEST SENSE")) == 0) -			reply = do_request_sense(fsg, bh); -		break; - -	case START_STOP: -		fsg->data_size_from_cmnd = 0; -		if ((reply = check_command(fsg, 6, DATA_DIR_NONE, -				(1<<1) | (1<<4), 0, -				"START-STOP UNIT")) == 0) -			reply = do_start_stop(fsg); -		break; - -	case SYNCHRONIZE_CACHE: -		fsg->data_size_from_cmnd = 0; -		if ((reply = check_command(fsg, 10, DATA_DIR_NONE, -				(0xf<<2) | (3<<7), 1, -				"SYNCHRONIZE CACHE")) == 0) -			reply = do_synchronize_cache(fsg); -		break; - -	case TEST_UNIT_READY: -		fsg->data_size_from_cmnd = 0; -		reply = check_command(fsg, 6, DATA_DIR_NONE, -				0, 1, -				"TEST UNIT READY"); -		break; - -	/* Although optional, this command is used by MS-Windows.  We -	 * support a minimal version: BytChk must be 0. */ -	case VERIFY: -		fsg->data_size_from_cmnd = 0; -		if ((reply = check_command(fsg, 10, DATA_DIR_NONE, -				(1<<1) | (0xf<<2) | (3<<7), 1, -				"VERIFY")) == 0) -			reply = do_verify(fsg); -		break; - -	case WRITE_6: -		i = fsg->cmnd[4]; -		fsg->data_size_from_cmnd = (i == 0) ? 256 : i; -		if ((reply = check_command_size_in_blocks(fsg, 6, -				DATA_DIR_FROM_HOST, -				(7<<1) | (1<<4), 1, -				"WRITE(6)")) == 0) -			reply = do_write(fsg); -		break; - -	case WRITE_10: -		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); -		if ((reply = check_command_size_in_blocks(fsg, 10, -				DATA_DIR_FROM_HOST, -				(1<<1) | (0xf<<2) | (3<<7), 1, -				"WRITE(10)")) == 0) -			reply = do_write(fsg); -		break; - -	case WRITE_12: -		fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]); -		if ((reply = check_command_size_in_blocks(fsg, 12, -				DATA_DIR_FROM_HOST, -				(1<<1) | (0xf<<2) | (0xf<<6), 1, -				"WRITE(12)")) == 0) -			reply = do_write(fsg); -		break; - -	/* Some mandatory commands that we recognize but don't implement. -	 * They don't mean much in this setting.  It's left as an exercise -	 * for anyone interested to implement RESERVE and RELEASE in terms -	 * of Posix locks. */ -	case FORMAT_UNIT: -	case RELEASE: -	case RESERVE: -	case SEND_DIAGNOSTIC: -		// Fall through - -	default: - unknown_cmnd: -		fsg->data_size_from_cmnd = 0; -		sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]); -		if ((reply = check_command(fsg, fsg->cmnd_size, -				DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) { -			fsg->curlun->sense_data = SS_INVALID_COMMAND; -			reply = -EINVAL; -		} -		break; -	} -	up_read(&fsg->filesem); - -	if (reply == -EINTR || signal_pending(current)) -		return -EINTR; - -	/* Set up the single reply buffer for finish_reply() */ -	if (reply == -EINVAL) -		reply = 0;		// Error reply length -	if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) { -		reply = min((u32) reply, fsg->data_size_from_cmnd); -		bh->inreq->length = reply; -		bh->state = BUF_STATE_FULL; -		fsg->residue -= reply; -	}				// Otherwise it's already set - -	return 0; -} - - -/*-------------------------------------------------------------------------*/ - -static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) -{ -	struct usb_request		*req = bh->outreq; -	struct bulk_cb_wrap	*cbw = req->buf; - -	/* Was this a real packet?  Should it be ignored? */ -	if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) -		return -EINVAL; - -	/* Is the CBW valid? */ -	if (req->actual != US_BULK_CB_WRAP_LEN || -			cbw->Signature != cpu_to_le32( -				US_BULK_CB_SIGN)) { -		DBG(fsg, "invalid CBW: len %u sig 0x%x\n", -				req->actual, -				le32_to_cpu(cbw->Signature)); - -		/* The Bulk-only spec says we MUST stall the IN endpoint -		 * (6.6.1), so it's unavoidable.  It also says we must -		 * retain this state until the next reset, but there's -		 * no way to tell the controller driver it should ignore -		 * Clear-Feature(HALT) requests. -		 * -		 * We aren't required to halt the OUT endpoint; instead -		 * we can simply accept and discard any data received -		 * until the next reset. */ -		wedge_bulk_in_endpoint(fsg); -		set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); -		return -EINVAL; -	} - -	/* Is the CBW meaningful? */ -	if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN || -			cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { -		DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " -				"cmdlen %u\n", -				cbw->Lun, cbw->Flags, cbw->Length); - -		/* We can do anything we want here, so let's stall the -		 * bulk pipes if we are allowed to. */ -		if (mod_data.can_stall) { -			fsg_set_halt(fsg, fsg->bulk_out); -			halt_bulk_in_endpoint(fsg); -		} -		return -EINVAL; -	} - -	/* Save the command for later */ -	fsg->cmnd_size = cbw->Length; -	memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size); -	if (cbw->Flags & US_BULK_FLAG_IN) -		fsg->data_dir = DATA_DIR_TO_HOST; -	else -		fsg->data_dir = DATA_DIR_FROM_HOST; -	fsg->data_size = le32_to_cpu(cbw->DataTransferLength); -	if (fsg->data_size == 0) -		fsg->data_dir = DATA_DIR_NONE; -	fsg->lun = cbw->Lun; -	fsg->tag = cbw->Tag; -	return 0; -} - - -static int get_next_command(struct fsg_dev *fsg) -{ -	struct fsg_buffhd	*bh; -	int			rc = 0; - -	if (transport_is_bbb()) { - -		/* Wait for the next buffer to become available */ -		bh = fsg->next_buffhd_to_fill; -		while (bh->state != BUF_STATE_EMPTY) { -			rc = sleep_thread(fsg); -			if (rc) -				return rc; -		} - -		/* Queue a request to read a Bulk-only CBW */ -		set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN); -		start_transfer(fsg, fsg->bulk_out, bh->outreq, -				&bh->outreq_busy, &bh->state); - -		/* We will drain the buffer in software, which means we -		 * can reuse it for the next filling.  No need to advance -		 * next_buffhd_to_fill. */ - -		/* Wait for the CBW to arrive */ -		while (bh->state != BUF_STATE_FULL) { -			rc = sleep_thread(fsg); -			if (rc) -				return rc; -		} -		smp_rmb(); -		rc = received_cbw(fsg, bh); -		bh->state = BUF_STATE_EMPTY; - -	} else {		// USB_PR_CB or USB_PR_CBI - -		/* Wait for the next command to arrive */ -		while (fsg->cbbuf_cmnd_size == 0) { -			rc = sleep_thread(fsg); -			if (rc) -				return rc; -		} - -		/* Is the previous status interrupt request still busy? -		 * The host is allowed to skip reading the status, -		 * so we must cancel it. */ -		if (fsg->intreq_busy) -			usb_ep_dequeue(fsg->intr_in, fsg->intreq); - -		/* Copy the command and mark the buffer empty */ -		fsg->data_dir = DATA_DIR_UNKNOWN; -		spin_lock_irq(&fsg->lock); -		fsg->cmnd_size = fsg->cbbuf_cmnd_size; -		memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size); -		fsg->cbbuf_cmnd_size = 0; -		spin_unlock_irq(&fsg->lock); - -		/* Use LUN from the command */ -		fsg->lun = fsg->cmnd[1] >> 5; -	} - -	/* Update current lun */ -	if (fsg->lun >= 0 && fsg->lun < fsg->nluns) -		fsg->curlun = &fsg->luns[fsg->lun]; -	else -		fsg->curlun = NULL; - -	return rc; -} - - -/*-------------------------------------------------------------------------*/ - -static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep, -		const struct usb_endpoint_descriptor *d) -{ -	int	rc; - -	ep->driver_data = fsg; -	ep->desc = d; -	rc = usb_ep_enable(ep); -	if (rc) -		ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc); -	return rc; -} - -static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep, -		struct usb_request **preq) -{ -	*preq = usb_ep_alloc_request(ep, GFP_ATOMIC); -	if (*preq) -		return 0; -	ERROR(fsg, "can't allocate request for %s\n", ep->name); -	return -ENOMEM; -} - -/* - * Reset interface setting and re-init endpoint state (toggle etc). - * Call with altsetting < 0 to disable the interface.  The only other - * available altsetting is 0, which enables the interface. - */ -static int do_set_interface(struct fsg_dev *fsg, int altsetting) -{ -	int	rc = 0; -	int	i; -	const struct usb_endpoint_descriptor	*d; - -	if (fsg->running) -		DBG(fsg, "reset interface\n"); - -reset: -	/* Deallocate the requests */ -	for (i = 0; i < fsg_num_buffers; ++i) { -		struct fsg_buffhd *bh = &fsg->buffhds[i]; - -		if (bh->inreq) { -			usb_ep_free_request(fsg->bulk_in, bh->inreq); -			bh->inreq = NULL; -		} -		if (bh->outreq) { -			usb_ep_free_request(fsg->bulk_out, bh->outreq); -			bh->outreq = NULL; -		} -	} -	if (fsg->intreq) { -		usb_ep_free_request(fsg->intr_in, fsg->intreq); -		fsg->intreq = NULL; -	} - -	/* Disable the endpoints */ -	if (fsg->bulk_in_enabled) { -		usb_ep_disable(fsg->bulk_in); -		fsg->bulk_in_enabled = 0; -	} -	if (fsg->bulk_out_enabled) { -		usb_ep_disable(fsg->bulk_out); -		fsg->bulk_out_enabled = 0; -	} -	if (fsg->intr_in_enabled) { -		usb_ep_disable(fsg->intr_in); -		fsg->intr_in_enabled = 0; -	} - -	fsg->running = 0; -	if (altsetting < 0 || rc != 0) -		return rc; - -	DBG(fsg, "set interface %d\n", altsetting); - -	/* Enable the endpoints */ -	d = fsg_ep_desc(fsg->gadget, -			&fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc, -			&fsg_ss_bulk_in_desc); -	if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0) -		goto reset; -	fsg->bulk_in_enabled = 1; - -	d = fsg_ep_desc(fsg->gadget, -			&fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc, -			&fsg_ss_bulk_out_desc); -	if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0) -		goto reset; -	fsg->bulk_out_enabled = 1; -	fsg->bulk_out_maxpacket = usb_endpoint_maxp(d); -	clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); - -	if (transport_is_cbi()) { -		d = fsg_ep_desc(fsg->gadget, -				&fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc, -				&fsg_ss_intr_in_desc); -		if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0) -			goto reset; -		fsg->intr_in_enabled = 1; -	} - -	/* Allocate the requests */ -	for (i = 0; i < fsg_num_buffers; ++i) { -		struct fsg_buffhd	*bh = &fsg->buffhds[i]; - -		if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0) -			goto reset; -		if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0) -			goto reset; -		bh->inreq->buf = bh->outreq->buf = bh->buf; -		bh->inreq->context = bh->outreq->context = bh; -		bh->inreq->complete = bulk_in_complete; -		bh->outreq->complete = bulk_out_complete; -	} -	if (transport_is_cbi()) { -		if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0) -			goto reset; -		fsg->intreq->complete = intr_in_complete; -	} - -	fsg->running = 1; -	for (i = 0; i < fsg->nluns; ++i) -		fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED; -	return rc; -} - - -/* - * Change our operational configuration.  This code must agree with the code - * that returns config descriptors, and with interface altsetting code. - * - * It's also responsible for power management interactions.  Some - * configurations might not work with our current power sources. - * For now we just assume the gadget is always self-powered. - */ -static int do_set_config(struct fsg_dev *fsg, u8 new_config) -{ -	int	rc = 0; - -	/* Disable the single interface */ -	if (fsg->config != 0) { -		DBG(fsg, "reset config\n"); -		fsg->config = 0; -		rc = do_set_interface(fsg, -1); -	} - -	/* Enable the interface */ -	if (new_config != 0) { -		fsg->config = new_config; -		if ((rc = do_set_interface(fsg, 0)) != 0) -			fsg->config = 0;	// Reset on errors -		else -			INFO(fsg, "%s config #%d\n", -			     usb_speed_string(fsg->gadget->speed), -			     fsg->config); -	} -	return rc; -} - - -/*-------------------------------------------------------------------------*/ - -static void handle_exception(struct fsg_dev *fsg) -{ -	siginfo_t		info; -	int			sig; -	int			i; -	int			num_active; -	struct fsg_buffhd	*bh; -	enum fsg_state		old_state; -	u8			new_config; -	struct fsg_lun		*curlun; -	unsigned int		exception_req_tag; -	int			rc; - -	/* Clear the existing signals.  Anything but SIGUSR1 is converted -	 * into a high-priority EXIT exception. */ -	for (;;) { -		sig = dequeue_signal_lock(current, ¤t->blocked, &info); -		if (!sig) -			break; -		if (sig != SIGUSR1) { -			if (fsg->state < FSG_STATE_EXIT) -				DBG(fsg, "Main thread exiting on signal\n"); -			raise_exception(fsg, FSG_STATE_EXIT); -		} -	} - -	/* Cancel all the pending transfers */ -	if (fsg->intreq_busy) -		usb_ep_dequeue(fsg->intr_in, fsg->intreq); -	for (i = 0; i < fsg_num_buffers; ++i) { -		bh = &fsg->buffhds[i]; -		if (bh->inreq_busy) -			usb_ep_dequeue(fsg->bulk_in, bh->inreq); -		if (bh->outreq_busy) -			usb_ep_dequeue(fsg->bulk_out, bh->outreq); -	} - -	/* Wait until everything is idle */ -	for (;;) { -		num_active = fsg->intreq_busy; -		for (i = 0; i < fsg_num_buffers; ++i) { -			bh = &fsg->buffhds[i]; -			num_active += bh->inreq_busy + bh->outreq_busy; -		} -		if (num_active == 0) -			break; -		if (sleep_thread(fsg)) -			return; -	} - -	/* Clear out the controller's fifos */ -	if (fsg->bulk_in_enabled) -		usb_ep_fifo_flush(fsg->bulk_in); -	if (fsg->bulk_out_enabled) -		usb_ep_fifo_flush(fsg->bulk_out); -	if (fsg->intr_in_enabled) -		usb_ep_fifo_flush(fsg->intr_in); - -	/* Reset the I/O buffer states and pointers, the SCSI -	 * state, and the exception.  Then invoke the handler. */ -	spin_lock_irq(&fsg->lock); - -	for (i = 0; i < fsg_num_buffers; ++i) { -		bh = &fsg->buffhds[i]; -		bh->state = BUF_STATE_EMPTY; -	} -	fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain = -			&fsg->buffhds[0]; - -	exception_req_tag = fsg->exception_req_tag; -	new_config = fsg->new_config; -	old_state = fsg->state; - -	if (old_state == FSG_STATE_ABORT_BULK_OUT) -		fsg->state = FSG_STATE_STATUS_PHASE; -	else { -		for (i = 0; i < fsg->nluns; ++i) { -			curlun = &fsg->luns[i]; -			curlun->prevent_medium_removal = 0; -			curlun->sense_data = curlun->unit_attention_data = -					SS_NO_SENSE; -			curlun->sense_data_info = 0; -			curlun->info_valid = 0; -		} -		fsg->state = FSG_STATE_IDLE; -	} -	spin_unlock_irq(&fsg->lock); - -	/* Carry out any extra actions required for the exception */ -	switch (old_state) { -	default: -		break; - -	case FSG_STATE_ABORT_BULK_OUT: -		send_status(fsg); -		spin_lock_irq(&fsg->lock); -		if (fsg->state == FSG_STATE_STATUS_PHASE) -			fsg->state = FSG_STATE_IDLE; -		spin_unlock_irq(&fsg->lock); -		break; - -	case FSG_STATE_RESET: -		/* In case we were forced against our will to halt a -		 * bulk endpoint, clear the halt now.  (The SuperH UDC -		 * requires this.) */ -		if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) -			usb_ep_clear_halt(fsg->bulk_in); - -		if (transport_is_bbb()) { -			if (fsg->ep0_req_tag == exception_req_tag) -				ep0_queue(fsg);	// Complete the status stage - -		} else if (transport_is_cbi()) -			send_status(fsg);	// Status by interrupt pipe - -		/* Technically this should go here, but it would only be -		 * a waste of time.  Ditto for the INTERFACE_CHANGE and -		 * CONFIG_CHANGE cases. */ -		// for (i = 0; i < fsg->nluns; ++i) -		//	fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED; -		break; - -	case FSG_STATE_INTERFACE_CHANGE: -		rc = do_set_interface(fsg, 0); -		if (fsg->ep0_req_tag != exception_req_tag) -			break; -		if (rc != 0)			// STALL on errors -			fsg_set_halt(fsg, fsg->ep0); -		else				// Complete the status stage -			ep0_queue(fsg); -		break; - -	case FSG_STATE_CONFIG_CHANGE: -		rc = do_set_config(fsg, new_config); -		if (fsg->ep0_req_tag != exception_req_tag) -			break; -		if (rc != 0)			// STALL on errors -			fsg_set_halt(fsg, fsg->ep0); -		else				// Complete the status stage -			ep0_queue(fsg); -		break; - -	case FSG_STATE_DISCONNECT: -		for (i = 0; i < fsg->nluns; ++i) -			fsg_lun_fsync_sub(fsg->luns + i); -		do_set_config(fsg, 0);		// Unconfigured state -		break; - -	case FSG_STATE_EXIT: -	case FSG_STATE_TERMINATED: -		do_set_config(fsg, 0);			// Free resources -		spin_lock_irq(&fsg->lock); -		fsg->state = FSG_STATE_TERMINATED;	// Stop the thread -		spin_unlock_irq(&fsg->lock); -		break; -	} -} - - -/*-------------------------------------------------------------------------*/ - -static int fsg_main_thread(void *fsg_) -{ -	struct fsg_dev		*fsg = fsg_; - -	/* Allow the thread to be killed by a signal, but set the signal mask -	 * to block everything but INT, TERM, KILL, and USR1. */ -	allow_signal(SIGINT); -	allow_signal(SIGTERM); -	allow_signal(SIGKILL); -	allow_signal(SIGUSR1); - -	/* Allow the thread to be frozen */ -	set_freezable(); - -	/* Arrange for userspace references to be interpreted as kernel -	 * pointers.  That way we can pass a kernel pointer to a routine -	 * that expects a __user pointer and it will work okay. */ -	set_fs(get_ds()); - -	/* The main loop */ -	while (fsg->state != FSG_STATE_TERMINATED) { -		if (exception_in_progress(fsg) || signal_pending(current)) { -			handle_exception(fsg); -			continue; -		} - -		if (!fsg->running) { -			sleep_thread(fsg); -			continue; -		} - -		if (get_next_command(fsg)) -			continue; - -		spin_lock_irq(&fsg->lock); -		if (!exception_in_progress(fsg)) -			fsg->state = FSG_STATE_DATA_PHASE; -		spin_unlock_irq(&fsg->lock); - -		if (do_scsi_command(fsg) || finish_reply(fsg)) -			continue; - -		spin_lock_irq(&fsg->lock); -		if (!exception_in_progress(fsg)) -			fsg->state = FSG_STATE_STATUS_PHASE; -		spin_unlock_irq(&fsg->lock); - -		if (send_status(fsg)) -			continue; - -		spin_lock_irq(&fsg->lock); -		if (!exception_in_progress(fsg)) -			fsg->state = FSG_STATE_IDLE; -		spin_unlock_irq(&fsg->lock); -		} - -	spin_lock_irq(&fsg->lock); -	fsg->thread_task = NULL; -	spin_unlock_irq(&fsg->lock); - -	/* If we are exiting because of a signal, unregister the -	 * gadget driver. */ -	if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) -		usb_gadget_unregister_driver(&fsg_driver); - -	/* Let the unbind and cleanup routines know the thread has exited */ -	complete_and_exit(&fsg->thread_notifier, 0); -} - - -/*-------------------------------------------------------------------------*/ - - -/* The write permissions and store_xxx pointers are set in fsg_bind() */ -static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL); -static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL); -static DEVICE_ATTR(file, 0444, fsg_show_file, NULL); - - -/*-------------------------------------------------------------------------*/ - -static void fsg_release(struct kref *ref) -{ -	struct fsg_dev	*fsg = container_of(ref, struct fsg_dev, ref); - -	kfree(fsg->luns); -	kfree(fsg); -} - -static void lun_release(struct device *dev) -{ -	struct rw_semaphore	*filesem = dev_get_drvdata(dev); -	struct fsg_dev		*fsg = -		container_of(filesem, struct fsg_dev, filesem); - -	kref_put(&fsg->ref, fsg_release); -} - -static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) -{ -	struct fsg_dev		*fsg = get_gadget_data(gadget); -	int			i; -	struct fsg_lun		*curlun; -	struct usb_request	*req = fsg->ep0req; - -	DBG(fsg, "unbind\n"); -	clear_bit(REGISTERED, &fsg->atomic_bitflags); - -	/* If the thread isn't already dead, tell it to exit now */ -	if (fsg->state != FSG_STATE_TERMINATED) { -		raise_exception(fsg, FSG_STATE_EXIT); -		wait_for_completion(&fsg->thread_notifier); - -		/* The cleanup routine waits for this completion also */ -		complete(&fsg->thread_notifier); -	} - -	/* Unregister the sysfs attribute files and the LUNs */ -	for (i = 0; i < fsg->nluns; ++i) { -		curlun = &fsg->luns[i]; -		if (curlun->registered) { -			device_remove_file(&curlun->dev, &dev_attr_nofua); -			device_remove_file(&curlun->dev, &dev_attr_ro); -			device_remove_file(&curlun->dev, &dev_attr_file); -			fsg_lun_close(curlun); -			device_unregister(&curlun->dev); -			curlun->registered = 0; -		} -	} - -	/* Free the data buffers */ -	for (i = 0; i < fsg_num_buffers; ++i) -		kfree(fsg->buffhds[i].buf); - -	/* Free the request and buffer for endpoint 0 */ -	if (req) { -		kfree(req->buf); -		usb_ep_free_request(fsg->ep0, req); -	} - -	set_gadget_data(gadget, NULL); -} - - -static int __init check_parameters(struct fsg_dev *fsg) -{ -	int	prot; - -	/* Store the default values */ -	mod_data.transport_type = USB_PR_BULK; -	mod_data.transport_name = "Bulk-only"; -	mod_data.protocol_type = USB_SC_SCSI; -	mod_data.protocol_name = "Transparent SCSI"; - -	/* Some peripheral controllers are known not to be able to -	 * halt bulk endpoints correctly.  If one of them is present, -	 * disable stalls. -	 */ -	if (gadget_is_at91(fsg->gadget)) -		mod_data.can_stall = 0; - -	if (mod_data.release == 0xffff) -		mod_data.release = get_default_bcdDevice(); - -	prot = simple_strtol(mod_data.protocol_parm, NULL, 0); - -#ifdef CONFIG_USB_FILE_STORAGE_TEST -	if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) { -		;		// Use default setting -	} else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) { -		mod_data.transport_type = USB_PR_CB; -		mod_data.transport_name = "Control-Bulk"; -	} else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) { -		mod_data.transport_type = USB_PR_CBI; -		mod_data.transport_name = "Control-Bulk-Interrupt"; -	} else { -		ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm); -		return -EINVAL; -	} - -	if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 || -			prot == USB_SC_SCSI) { -		;		// Use default setting -	} else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 || -			prot == USB_SC_RBC) { -		mod_data.protocol_type = USB_SC_RBC; -		mod_data.protocol_name = "RBC"; -	} else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 || -			strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 || -			prot == USB_SC_8020) { -		mod_data.protocol_type = USB_SC_8020; -		mod_data.protocol_name = "8020i (ATAPI)"; -	} else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 || -			prot == USB_SC_QIC) { -		mod_data.protocol_type = USB_SC_QIC; -		mod_data.protocol_name = "QIC-157"; -	} else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 || -			prot == USB_SC_UFI) { -		mod_data.protocol_type = USB_SC_UFI; -		mod_data.protocol_name = "UFI"; -	} else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 || -			prot == USB_SC_8070) { -		mod_data.protocol_type = USB_SC_8070; -		mod_data.protocol_name = "8070i"; -	} else { -		ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm); -		return -EINVAL; -	} - -	mod_data.buflen &= PAGE_CACHE_MASK; -	if (mod_data.buflen <= 0) { -		ERROR(fsg, "invalid buflen\n"); -		return -ETOOSMALL; -	} - -#endif /* CONFIG_USB_FILE_STORAGE_TEST */ - -	/* Serial string handling. -	 * On a real device, the serial string would be loaded -	 * from permanent storage. */ -	if (mod_data.serial) { -		const char *ch; -		unsigned len = 0; - -		/* Sanity check : -		 * The CB[I] specification limits the serial string to -		 * 12 uppercase hexadecimal characters. -		 * BBB need at least 12 uppercase hexadecimal characters, -		 * with a maximum of 126. */ -		for (ch = mod_data.serial; *ch; ++ch) { -			++len; -			if ((*ch < '0' || *ch > '9') && -			    (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */ -				WARNING(fsg, -					"Invalid serial string character: %c\n", -					*ch); -				goto no_serial; -			} -		} -		if (len > 126 || -		    (mod_data.transport_type == USB_PR_BULK && len < 12) || -		    (mod_data.transport_type != USB_PR_BULK && len > 12)) { -			WARNING(fsg, "Invalid serial string length!\n"); -			goto no_serial; -		} -		fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial; -	} else { -		WARNING(fsg, "No serial-number string provided!\n"); - no_serial: -		device_desc.iSerialNumber = 0; -	} - -	return 0; -} - - -static int __init fsg_bind(struct usb_gadget *gadget, -		struct usb_gadget_driver *driver) -{ -	struct fsg_dev		*fsg = the_fsg; -	int			rc; -	int			i; -	struct fsg_lun		*curlun; -	struct usb_ep		*ep; -	struct usb_request	*req; -	char			*pathbuf, *p; - -	fsg->gadget = gadget; -	set_gadget_data(gadget, fsg); -	fsg->ep0 = gadget->ep0; -	fsg->ep0->driver_data = fsg; - -	if ((rc = check_parameters(fsg)) != 0) -		goto out; - -	if (mod_data.removable) {	// Enable the store_xxx attributes -		dev_attr_file.attr.mode = 0644; -		dev_attr_file.store = fsg_store_file; -		if (!mod_data.cdrom) { -			dev_attr_ro.attr.mode = 0644; -			dev_attr_ro.store = fsg_store_ro; -		} -	} - -	/* Only for removable media? */ -	dev_attr_nofua.attr.mode = 0644; -	dev_attr_nofua.store = fsg_store_nofua; - -	/* Find out how many LUNs there should be */ -	i = mod_data.nluns; -	if (i == 0) -		i = max(mod_data.num_filenames, 1u); -	if (i > FSG_MAX_LUNS) { -		ERROR(fsg, "invalid number of LUNs: %d\n", i); -		rc = -EINVAL; -		goto out; -	} - -	/* Create the LUNs, open their backing files, and register the -	 * LUN devices in sysfs. */ -	fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL); -	if (!fsg->luns) { -		rc = -ENOMEM; -		goto out; -	} -	fsg->nluns = i; - -	for (i = 0; i < fsg->nluns; ++i) { -		curlun = &fsg->luns[i]; -		curlun->cdrom = !!mod_data.cdrom; -		curlun->ro = mod_data.cdrom || mod_data.ro[i]; -		curlun->initially_ro = curlun->ro; -		curlun->removable = mod_data.removable; -		curlun->nofua = mod_data.nofua[i]; -		curlun->dev.release = lun_release; -		curlun->dev.parent = &gadget->dev; -		curlun->dev.driver = &fsg_driver.driver; -		dev_set_drvdata(&curlun->dev, &fsg->filesem); -		dev_set_name(&curlun->dev,"%s-lun%d", -			     dev_name(&gadget->dev), i); - -		kref_get(&fsg->ref); -		rc = device_register(&curlun->dev); -		if (rc) { -			INFO(fsg, "failed to register LUN%d: %d\n", i, rc); -			put_device(&curlun->dev); -			goto out; -		} -		curlun->registered = 1; - -		rc = device_create_file(&curlun->dev, &dev_attr_ro); -		if (rc) -			goto out; -		rc = device_create_file(&curlun->dev, &dev_attr_nofua); -		if (rc) -			goto out; -		rc = device_create_file(&curlun->dev, &dev_attr_file); -		if (rc) -			goto out; - -		if (mod_data.file[i] && *mod_data.file[i]) { -			rc = fsg_lun_open(curlun, mod_data.file[i]); -			if (rc) -				goto out; -		} else if (!mod_data.removable) { -			ERROR(fsg, "no file given for LUN%d\n", i); -			rc = -EINVAL; -			goto out; -		} -	} - -	/* Find all the endpoints we will use */ -	usb_ep_autoconfig_reset(gadget); -	ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc); -	if (!ep) -		goto autoconf_fail; -	ep->driver_data = fsg;		// claim the endpoint -	fsg->bulk_in = ep; - -	ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc); -	if (!ep) -		goto autoconf_fail; -	ep->driver_data = fsg;		// claim the endpoint -	fsg->bulk_out = ep; - -	if (transport_is_cbi()) { -		ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc); -		if (!ep) -			goto autoconf_fail; -		ep->driver_data = fsg;		// claim the endpoint -		fsg->intr_in = ep; -	} - -	/* Fix up the descriptors */ -	device_desc.idVendor = cpu_to_le16(mod_data.vendor); -	device_desc.idProduct = cpu_to_le16(mod_data.product); -	device_desc.bcdDevice = cpu_to_le16(mod_data.release); - -	i = (transport_is_cbi() ? 3 : 2);	// Number of endpoints -	fsg_intf_desc.bNumEndpoints = i; -	fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type; -	fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type; -	fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL; - -	if (gadget_is_dualspeed(gadget)) { -		fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL; - -		/* Assume endpoint addresses are the same for both speeds */ -		fsg_hs_bulk_in_desc.bEndpointAddress = -			fsg_fs_bulk_in_desc.bEndpointAddress; -		fsg_hs_bulk_out_desc.bEndpointAddress = -			fsg_fs_bulk_out_desc.bEndpointAddress; -		fsg_hs_intr_in_desc.bEndpointAddress = -			fsg_fs_intr_in_desc.bEndpointAddress; -	} - -	if (gadget_is_superspeed(gadget)) { -		unsigned		max_burst; - -		fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL; - -		/* Calculate bMaxBurst, we know packet size is 1024 */ -		max_burst = min_t(unsigned, mod_data.buflen / 1024, 15); - -		/* Assume endpoint addresses are the same for both speeds */ -		fsg_ss_bulk_in_desc.bEndpointAddress = -			fsg_fs_bulk_in_desc.bEndpointAddress; -		fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst; - -		fsg_ss_bulk_out_desc.bEndpointAddress = -			fsg_fs_bulk_out_desc.bEndpointAddress; -		fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; -	} - -	if (gadget_is_otg(gadget)) -		fsg_otg_desc.bmAttributes |= USB_OTG_HNP; - -	rc = -ENOMEM; - -	/* Allocate the request and buffer for endpoint 0 */ -	fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL); -	if (!req) -		goto out; -	req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL); -	if (!req->buf) -		goto out; -	req->complete = ep0_complete; - -	/* Allocate the data buffers */ -	for (i = 0; i < fsg_num_buffers; ++i) { -		struct fsg_buffhd	*bh = &fsg->buffhds[i]; - -		/* Allocate for the bulk-in endpoint.  We assume that -		 * the buffer will also work with the bulk-out (and -		 * interrupt-in) endpoint. */ -		bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL); -		if (!bh->buf) -			goto out; -		bh->next = bh + 1; -	} -	fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0]; - -	/* This should reflect the actual gadget power source */ -	usb_gadget_set_selfpowered(gadget); - -	snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer, -			"%s %s with %s", -			init_utsname()->sysname, init_utsname()->release, -			gadget->name); - -	fsg->thread_task = kthread_create(fsg_main_thread, fsg, -			"file-storage-gadget"); -	if (IS_ERR(fsg->thread_task)) { -		rc = PTR_ERR(fsg->thread_task); -		goto out; -	} - -	INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); -	INFO(fsg, "NOTE: This driver is deprecated.  " -			"Consider using g_mass_storage instead.\n"); -	INFO(fsg, "Number of LUNs=%d\n", fsg->nluns); - -	pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); -	for (i = 0; i < fsg->nluns; ++i) { -		curlun = &fsg->luns[i]; -		if (fsg_lun_is_open(curlun)) { -			p = NULL; -			if (pathbuf) { -				p = d_path(&curlun->filp->f_path, -					   pathbuf, PATH_MAX); -				if (IS_ERR(p)) -					p = NULL; -			} -			LINFO(curlun, "ro=%d, nofua=%d, file: %s\n", -			      curlun->ro, curlun->nofua, (p ? p : "(error)")); -		} -	} -	kfree(pathbuf); - -	DBG(fsg, "transport=%s (x%02x)\n", -			mod_data.transport_name, mod_data.transport_type); -	DBG(fsg, "protocol=%s (x%02x)\n", -			mod_data.protocol_name, mod_data.protocol_type); -	DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n", -			mod_data.vendor, mod_data.product, mod_data.release); -	DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n", -			mod_data.removable, mod_data.can_stall, -			mod_data.cdrom, mod_data.buflen); -	DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task)); - -	set_bit(REGISTERED, &fsg->atomic_bitflags); - -	/* Tell the thread to start working */ -	wake_up_process(fsg->thread_task); -	return 0; - -autoconf_fail: -	ERROR(fsg, "unable to autoconfigure all endpoints\n"); -	rc = -ENOTSUPP; - -out: -	fsg->state = FSG_STATE_TERMINATED;	// The thread is dead -	fsg_unbind(gadget); -	complete(&fsg->thread_notifier); -	return rc; -} - - -/*-------------------------------------------------------------------------*/ - -static void fsg_suspend(struct usb_gadget *gadget) -{ -	struct fsg_dev		*fsg = get_gadget_data(gadget); - -	DBG(fsg, "suspend\n"); -	set_bit(SUSPENDED, &fsg->atomic_bitflags); -} - -static void fsg_resume(struct usb_gadget *gadget) -{ -	struct fsg_dev		*fsg = get_gadget_data(gadget); - -	DBG(fsg, "resume\n"); -	clear_bit(SUSPENDED, &fsg->atomic_bitflags); -} - - -/*-------------------------------------------------------------------------*/ - -static __refdata struct usb_gadget_driver		fsg_driver = { -	.max_speed	= USB_SPEED_SUPER, -	.function	= (char *) fsg_string_product, -	.bind		= fsg_bind, -	.unbind		= fsg_unbind, -	.disconnect	= fsg_disconnect, -	.setup		= fsg_setup, -	.suspend	= fsg_suspend, -	.resume		= fsg_resume, - -	.driver		= { -		.name		= DRIVER_NAME, -		.owner		= THIS_MODULE, -		// .release = ... -		// .suspend = ... -		// .resume = ... -	}, -}; - - -static int __init fsg_alloc(void) -{ -	struct fsg_dev		*fsg; - -	fsg = kzalloc(sizeof *fsg + -		      fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL); - -	if (!fsg) -		return -ENOMEM; -	spin_lock_init(&fsg->lock); -	init_rwsem(&fsg->filesem); -	kref_init(&fsg->ref); -	init_completion(&fsg->thread_notifier); - -	the_fsg = fsg; -	return 0; -} - - -static int __init fsg_init(void) -{ -	int		rc; -	struct fsg_dev	*fsg; - -	rc = fsg_num_buffers_validate(); -	if (rc != 0) -		return rc; - -	if ((rc = fsg_alloc()) != 0) -		return rc; -	fsg = the_fsg; -	rc = usb_gadget_probe_driver(&fsg_driver); -	if (rc != 0) -		kref_put(&fsg->ref, fsg_release); -	return rc; -} -module_init(fsg_init); - - -static void __exit fsg_cleanup(void) -{ -	struct fsg_dev	*fsg = the_fsg; - -	/* Unregister the driver iff the thread hasn't already done so */ -	if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) -		usb_gadget_unregister_driver(&fsg_driver); - -	/* Wait for the thread to finish up */ -	wait_for_completion(&fsg->thread_notifier); - -	kref_put(&fsg->ref, fsg_release); -} -module_exit(fsg_cleanup); diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index b09452d6f33..ec50f18c889 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -2347,7 +2347,7 @@ static int fsl_qe_stop(struct usb_gadget *gadget,  }  /* udc structure's alloc and setup, include ep-param alloc */ -static struct qe_udc __devinit *qe_udc_config(struct platform_device *ofdev) +static struct qe_udc *qe_udc_config(struct platform_device *ofdev)  {  	struct qe_udc *udc;  	struct device_node *np = ofdev->dev.of_node; @@ -2402,7 +2402,7 @@ cleanup:  }  /* USB Controller register init */ -static int __devinit qe_udc_reg_init(struct qe_udc *udc) +static int qe_udc_reg_init(struct qe_udc *udc)  {  	struct usb_ctlr __iomem *qe_usbregs;  	qe_usbregs = udc->usb_regs; @@ -2420,7 +2420,7 @@ static int __devinit qe_udc_reg_init(struct qe_udc *udc)  	return 0;  } -static int __devinit qe_ep_config(struct qe_udc *udc, unsigned char pipe_num) +static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)  {  	struct qe_ep *ep = &udc->eps[pipe_num]; @@ -2473,7 +2473,7 @@ static void qe_udc_release(struct device *dev)  /* Driver probe functions */  static const struct of_device_id qe_udc_match[]; -static int __devinit qe_udc_probe(struct platform_device *ofdev) +static int qe_udc_probe(struct platform_device *ofdev)  {  	struct qe_udc *udc;  	const struct of_device_id *match; @@ -2651,7 +2651,7 @@ static int qe_udc_resume(struct platform_device *dev)  }  #endif -static int __devexit qe_udc_remove(struct platform_device *ofdev) +static int qe_udc_remove(struct platform_device *ofdev)  {  	struct qe_udc *udc = dev_get_drvdata(&ofdev->dev);  	struct qe_ep *ep; @@ -2710,7 +2710,7 @@ static int __devexit qe_udc_remove(struct platform_device *ofdev)  }  /*-------------------------------------------------------------------------*/ -static const struct of_device_id qe_udc_match[] __devinitconst = { +static const struct of_device_id qe_udc_match[] = {  	{  		.compatible = "fsl,mpc8323-qe-usb",  		.data = (void *)PORT_QE, @@ -2735,7 +2735,7 @@ static struct platform_driver udc_driver = {  		.of_match_table = qe_udc_match,  	},  	.probe          = qe_udc_probe, -	.remove         = __devexit_p(qe_udc_remove), +	.remove         = qe_udc_remove,  #ifdef CONFIG_PM  	.suspend        = qe_udc_suspend,  	.resume         = qe_udc_resume, diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 6ae70cba0c4..c19f7f13790 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -2126,7 +2126,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,  	tmp_reg = fsl_readl(&dr_regs->usbintr);  	t = scnprintf(next, size, -			"USB Intrrupt Enable Reg:\n" +			"USB Interrupt Enable Reg:\n"  			"Sleep Enable: %d SOF Received Enable: %d "  			"Reset Enable: %d\n"  			"System Error Enable: %d " diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 74130f6c12c..c36260ea8bf 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -203,7 +203,7 @@ static int __init hidg_plat_driver_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit hidg_plat_driver_remove(struct platform_device *pdev) +static int hidg_plat_driver_remove(struct platform_device *pdev)  {  	struct hidg_func_node *e, *n; @@ -229,7 +229,7 @@ static __refdata struct usb_composite_driver hidg_driver = {  };  static struct platform_driver hidg_plat_driver = { -	.remove		= __devexit_p(hidg_plat_driver_remove), +	.remove		= hidg_plat_driver_remove,  	.driver		= {  		.owner	= THIS_MODULE,  		.name	= "hidg", diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 76494cabf4e..8ac840f25ba 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -76,7 +76,6 @@ MODULE_LICENSE ("GPL");  /*----------------------------------------------------------------------*/  #define GADGETFS_MAGIC		0xaee71ee7 -#define DMA_ADDR_INVALID	(~(dma_addr_t)0)  /* /dev/gadget/$CHIP represents ep0 and the whole device */  enum ep0_state { @@ -918,7 +917,6 @@ static void clean_req (struct usb_ep *ep, struct usb_request *req)  	if (req->buf != dev->rbuf) {  		kfree(req->buf);  		req->buf = dev->rbuf; -		req->dma = DMA_ADDR_INVALID;  	}  	req->complete = epio_complete;  	dev->setup_out_ready = 0; @@ -1408,7 +1406,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)  		dev->setup_abort = 1;  	req->buf = dev->rbuf; -	req->dma = DMA_ADDR_INVALID;  	req->context = NULL;  	value = -EOPNOTSUPP;  	switch (ctrl->bRequest) { diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index 21a9861dabf..dd1c9b1fe52 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -2399,7 +2399,7 @@ static void udc_handle_ep0_setup(struct lpc32xx_udc *udc)  		if (i < 0) {  			/* setup processing failed, force stall */ -			dev_err(udc->dev, +			dev_dbg(udc->dev,  				"req %02x.%02x protocol STALL; stat %d\n",  				reqtype, req, i);  			udc->ep0state = WAIT_FOR_SETUP; @@ -3352,7 +3352,7 @@ phy_fail:  	return retval;  } -static int __devexit lpc32xx_udc_remove(struct platform_device *pdev) +static int lpc32xx_udc_remove(struct platform_device *pdev)  {  	struct lpc32xx_udc *udc = platform_get_drvdata(pdev); @@ -3447,7 +3447,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_udc_of_match);  #endif  static struct platform_driver lpc32xx_udc_driver = { -	.remove		= __devexit_p(lpc32xx_udc_remove), +	.remove		= lpc32xx_udc_remove,  	.shutdown	= lpc32xx_udc_shutdown,  	.suspend	= lpc32xx_udc_suspend,  	.resume		= lpc32xx_udc_resume, diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index 8cfd5b028db..b5cea273c95 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -1763,7 +1763,7 @@ static void mv_u3d_gadget_release(struct device *dev)  	dev_dbg(dev, "%s\n", __func__);  } -static __devexit int mv_u3d_remove(struct platform_device *dev) +static int mv_u3d_remove(struct platform_device *dev)  {  	struct mv_u3d *u3d = platform_get_drvdata(dev); diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index ea45224f78c..379aac7b82f 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -2128,7 +2128,7 @@ static void gadget_release(struct device *_dev)  	complete(udc->done);  } -static int __devexit mv_udc_remove(struct platform_device *dev) +static int mv_udc_remove(struct platform_device *dev)  {  	struct mv_udc *udc = the_controller;  	int clk_i; @@ -2188,7 +2188,7 @@ static int __devexit mv_udc_remove(struct platform_device *dev)  	return 0;  } -static int __devinit mv_udc_probe(struct platform_device *dev) +static int mv_udc_probe(struct platform_device *dev)  {  	struct mv_usb_platform_data *pdata = dev->dev.platform_data;  	struct mv_udc *udc; diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index c009263a47e..d226058e3b8 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -2193,7 +2193,7 @@ net2272_gadget_release(struct device *_dev)  /*---------------------------------------------------------------------------*/ -static void __devexit +static void  net2272_remove(struct net2272 *dev)  {  	usb_del_gadget_udc(&dev->gadget); @@ -2215,8 +2215,7 @@ net2272_remove(struct net2272 *dev)  	dev_info(dev->dev, "unbind\n");  } -static struct net2272 * __devinit -net2272_probe_init(struct device *dev, unsigned int irq) +static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq)  {  	struct net2272 *ret; @@ -2246,7 +2245,7 @@ net2272_probe_init(struct device *dev, unsigned int irq)  	return ret;  } -static int __devinit +static int  net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)  {  	int ret; @@ -2306,7 +2305,7 @@ err_add_udc:   * don't respond over USB until a gadget driver binds to us   */ -static int __devinit +static int  net2272_rdk1_probe(struct pci_dev *pdev, struct net2272 *dev)  {  	unsigned long resource, len, tmp; @@ -2389,7 +2388,7 @@ net2272_rdk1_probe(struct pci_dev *pdev, struct net2272 *dev)  	return ret;  } -static int __devinit +static int  net2272_rdk2_probe(struct pci_dev *pdev, struct net2272 *dev)  {  	unsigned long resource, len; @@ -2447,7 +2446,7 @@ net2272_rdk2_probe(struct pci_dev *pdev, struct net2272 *dev)  	return ret;  } -static int __devinit +static int  net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)  {  	struct net2272 *dev; @@ -2489,7 +2488,7 @@ net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)  	return ret;  } -static void __devexit +static void  net2272_rdk1_remove(struct pci_dev *pdev, struct net2272 *dev)  {  	int i; @@ -2511,7 +2510,7 @@ net2272_rdk1_remove(struct pci_dev *pdev, struct net2272 *dev)  	}  } -static void __devexit +static void  net2272_rdk2_remove(struct pci_dev *pdev, struct net2272 *dev)  {  	int i; @@ -2530,7 +2529,7 @@ net2272_rdk2_remove(struct pci_dev *pdev, struct net2272 *dev)  			pci_resource_len(pdev, i));  } -static void __devexit +static void  net2272_pci_remove(struct pci_dev *pdev)  {  	struct net2272 *dev = pci_get_drvdata(pdev); @@ -2549,7 +2548,7 @@ net2272_pci_remove(struct pci_dev *pdev)  }  /* Table of matching PCI IDs */ -static struct pci_device_id __devinitdata pci_ids[] = { +static struct pci_device_id pci_ids[] = {  	{	/* RDK 1 card */  		.class       = ((PCI_CLASS_BRIDGE_OTHER << 8) | 0xfe),  		.class_mask  = 0, @@ -2575,7 +2574,7 @@ static struct pci_driver net2272_pci_driver = {  	.id_table = pci_ids,  	.probe    = net2272_pci_probe, -	.remove   = __devexit_p(net2272_pci_remove), +	.remove   = net2272_pci_remove,  };  static int net2272_pci_register(void) @@ -2595,7 +2594,7 @@ static inline void net2272_pci_unregister(void) { }  /*---------------------------------------------------------------------------*/ -static int __devinit +static int  net2272_plat_probe(struct platform_device *pdev)  {  	struct net2272 *dev; @@ -2661,7 +2660,7 @@ net2272_plat_probe(struct platform_device *pdev)  	return ret;  } -static int __devexit +static int  net2272_plat_remove(struct platform_device *pdev)  {  	struct net2272 *dev = platform_get_drvdata(pdev); @@ -2678,7 +2677,7 @@ net2272_plat_remove(struct platform_device *pdev)  static struct platform_driver net2272_plat_driver = {  	.probe   = net2272_plat_probe, -	.remove  = __devexit_p(net2272_plat_remove), +	.remove  = net2272_plat_remove,  	.driver  = {  		.name  = driver_name,  		.owner = THIS_MODULE, diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index ac335af154b..708c0b55dcc 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -9,7 +9,7 @@   * CODE STATUS HIGHLIGHTS   *   * This driver should work well with most "gadget" drivers, including - * the File Storage, Serial, and Ethernet/RNDIS gadget drivers + * the Mass Storage, Serial, and Ethernet/RNDIS gadget drivers   * as well as Gadget Zero and Gadgetfs.   *   * DMA is enabled by default.  Drivers using transfer queues might use diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 1b8ddc3ddc5..8bfe990caf1 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2508,7 +2508,7 @@ static inline void remove_proc_file(void) {}   * UDC_SYSCON_1.CFG_LOCK is set can now work.  We won't use that   * capability yet though.   */ -static unsigned __devinit +static unsigned  omap_ep_setup(char *name, u8 addr, u8 type,  		unsigned buf, unsigned maxp, int dbuf)  { @@ -2626,7 +2626,7 @@ static void omap_udc_release(struct device *dev)  	udc = NULL;  } -static int __devinit +static int  omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)  {  	unsigned	tmp, buf; @@ -2763,7 +2763,7 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)  	return 0;  } -static int __devinit omap_udc_probe(struct platform_device *pdev) +static int omap_udc_probe(struct platform_device *pdev)  {  	int			status = -ENODEV;  	int			hmc; @@ -2976,7 +2976,7 @@ cleanup0:  	return status;  } -static int __devexit omap_udc_remove(struct platform_device *pdev) +static int omap_udc_remove(struct platform_device *pdev)  {  	DECLARE_COMPLETION_ONSTACK(done); @@ -3062,7 +3062,7 @@ static int omap_udc_resume(struct platform_device *dev)  static struct platform_driver udc_driver = {  	.probe		= omap_udc_probe, -	.remove		= __devexit_p(omap_udc_remove), +	.remove		= omap_udc_remove,  	.suspend	= omap_udc_suspend,  	.resume		= omap_udc_resume,  	.driver		= { diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index e156e3f2672..35bcc83d1e0 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -983,8 +983,10 @@ static int __init printer_func_bind(struct usb_configuration *c,  {  	struct printer_dev *dev = container_of(f, struct printer_dev, function);  	struct usb_composite_dev *cdev = c->cdev; -	struct usb_ep		*in_ep, *out_ep; +	struct usb_ep *in_ep; +	struct usb_ep *out_ep = NULL;  	int id; +	int ret;  	id = usb_interface_id(c, f);  	if (id < 0) @@ -1010,6 +1012,11 @@ autoconf_fail:  	hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;  	hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; +	ret = usb_assign_descriptors(f, fs_printer_function, +			hs_printer_function, NULL); +	if (ret) +		return ret; +  	dev->in_ep = in_ep;  	dev->out_ep = out_ep;  	return 0; @@ -1018,6 +1025,7 @@ autoconf_fail:  static void printer_func_unbind(struct usb_configuration *c,  		struct usb_function *f)  { +	usb_free_all_descriptors(f);  }  static int printer_func_set_alt(struct usb_function *f, @@ -1110,8 +1118,6 @@ static int __init printer_bind_config(struct usb_configuration *c)  	dev = &usb_printer_gadget;  	dev->function.name = shortname; -	dev->function.descriptors = fs_printer_function; -	dev->function.hs_descriptors = hs_printer_function;  	dev->function.bind = printer_func_bind;  	dev->function.setup = printer_func_setup;  	dev->function.unbind = printer_func_unbind; diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 8efbf08c356..d4ca9f1f7f2 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -29,6 +29,7 @@  #include <linux/list.h>  #include <linux/interrupt.h>  #include <linux/mm.h> +#include <linux/platform_data/pxa2xx_udc.h>  #include <linux/platform_device.h>  #include <linux/dma-mapping.h>  #include <linux/irq.h> @@ -59,9 +60,6 @@  #include <mach/lubbock.h>  #endif -#include <asm/mach/udc_pxa2xx.h> - -  /*   * This driver handles the USB Device Controller (UDC) in Intel's PXA 25x   * series processors.  The UDC for the IXP 4xx series is very similar. diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index a1d268c6f2c..79d81a4b234 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -418,7 +418,7 @@ struct udc_stats {   * @irq: udc irq   * @clk: udc clock   * @usb_gadget: udc gadget structure - * @driver: bound gadget (zero, g_ether, g_file_storage, ...) + * @driver: bound gadget (zero, g_ether, g_mass_storage, ...)   * @dev: device   * @mach: machine info, used to activate specific GPIO   * @transceiver: external transceiver to handle vbus sense and D+ pullup diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 6f696ee8b81..141971d9051 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -3072,7 +3072,7 @@ static struct usb_gadget_ops s3c_hsotg_gadget_ops = {   * creation) to give to the gadget driver. Setup the endpoint name, any   * direction information and other state that may be required.   */ -static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg, +static void s3c_hsotg_initep(struct s3c_hsotg *hsotg,  				       struct s3c_hsotg_ep *hs_ep,  				       int epnum)  { @@ -3414,7 +3414,7 @@ static const struct file_operations ep_fops = {   * with the same name as the device itself, in case we end up   * with multiple blocks in future systems.   */ -static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg) +static void s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)  {  	struct dentry *root;  	unsigned epidx; @@ -3460,7 +3460,7 @@ static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg)   *   * Cleanup (remove) the debugfs files for use on module exit.   */ -static void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg) +static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)  {  	unsigned epidx; @@ -3490,7 +3490,7 @@ static void s3c_hsotg_release(struct device *dev)   * @pdev: The platform information for the driver   */ -static int __devinit s3c_hsotg_probe(struct platform_device *pdev) +static int s3c_hsotg_probe(struct platform_device *pdev)  {  	struct s3c_hsotg_plat *plat = pdev->dev.platform_data;  	struct device *dev = &pdev->dev; @@ -3675,7 +3675,7 @@ err_clk:   * s3c_hsotg_remove - remove function for hsotg driver   * @pdev: The platform information for the driver   */ -static int __devexit s3c_hsotg_remove(struct platform_device *pdev) +static int s3c_hsotg_remove(struct platform_device *pdev)  {  	struct s3c_hsotg *hsotg = platform_get_drvdata(pdev); @@ -3708,7 +3708,7 @@ static struct platform_driver s3c_hsotg_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= s3c_hsotg_probe, -	.remove		= __devexit_p(s3c_hsotg_remove), +	.remove		= s3c_hsotg_remove,  	.suspend	= s3c_hsotg_suspend,  	.resume		= s3c_hsotg_resume,  }; diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index d8e785d4ad5..52379b11f08 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -1261,7 +1261,7 @@ static struct usb_gadget_ops s3c_hsudc_gadget_ops = {  	.vbus_draw	= s3c_hsudc_vbus_draw,  }; -static int __devinit s3c_hsudc_probe(struct platform_device *pdev) +static int s3c_hsudc_probe(struct platform_device *pdev)  {  	struct device *dev = &pdev->dev;  	struct resource *res; diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index 8d9bcd8207c..0e3ae43454a 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -11,30 +11,10 @@   * (at your option) any later version.   */ -  /*   * This file requires the following identifiers used in USB strings to   * be defined (each of type pointer to char): - *  - fsg_string_manufacturer -- name of the manufacturer - *  - fsg_string_product      -- name of the product - *  - fsg_string_config       -- name of the configuration   *  - fsg_string_interface    -- name of the interface - * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS - * macro is defined prior to including this file. - */ - -/* - * When FSG_NO_INTR_EP is defined fsg_fs_intr_in_desc and - * fsg_hs_intr_in_desc objects as well as - * FSG_FS_FUNCTION_PRE_EP_ENTRIES and FSG_HS_FUNCTION_PRE_EP_ENTRIES - * macros are not defined. - * - * When FSG_NO_DEVICE_STRINGS is defined FSG_STRING_MANUFACTURER, - * FSG_STRING_PRODUCT, FSG_STRING_SERIAL and FSG_STRING_CONFIG are not - * defined (as well as corresponding entries in string tables are - * missing) and FSG_STRING_INTERFACE has value of zero. - * - * When FSG_NO_OTG is defined fsg_otg_desc won't be defined.   */  /* @@ -78,34 +58,6 @@  #define LWARN(lun, fmt, args...)  dev_warn(&(lun)->dev, fmt, ## args)  #define LINFO(lun, fmt, args...)  dev_info(&(lun)->dev, fmt, ## args) -/* - * Keep those macros in sync with those in - * include/linux/usb/composite.h or else GCC will complain.  If they - * are identical (the same names of arguments, white spaces in the - * same places) GCC will allow redefinition otherwise (even if some - * white space is removed or added) warning will be issued. - * - * Those macros are needed here because File Storage Gadget does not - * include the composite.h header.  For composite gadgets those macros - * are redundant since composite.h is included any way. - * - * One could check whether those macros are already defined (which - * would indicate composite.h had been included) or not (which would - * indicate we were in FSG) but this is not done because a warning is - * desired if definitions here differ from the ones in composite.h. - * - * We want the definitions to match and be the same in File Storage - * Gadget as well as Mass Storage Function (and so composite gadgets - * using MSF).  If someone changes them in composite.h it will produce - * a warning in this file when building MSF. - */ -#define DBG(d, fmt, args...)     dev_dbg(&(d)->gadget->dev , fmt , ## args) -#define VDBG(d, fmt, args...)    dev_vdbg(&(d)->gadget->dev , fmt , ## args) -#define ERROR(d, fmt, args...)   dev_err(&(d)->gadget->dev , fmt , ## args) -#define WARNING(d, fmt, args...) dev_warn(&(d)->gadget->dev , fmt , ## args) -#define INFO(d, fmt, args...)    dev_info(&(d)->gadget->dev , fmt , ## args) - -  #ifdef DUMP_MSGS @@ -203,9 +155,12 @@ struct fsg_lun {  	struct device	dev;  }; -#define fsg_lun_is_open(curlun)	((curlun)->filp != NULL) +static inline bool fsg_lun_is_open(struct fsg_lun *curlun) +{ +	return curlun->filp != NULL; +} -static struct fsg_lun *fsg_lun_from_dev(struct device *dev) +static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev)  {  	return container_of(dev, struct fsg_lun, dev);  } @@ -308,26 +263,10 @@ static inline u32 get_unaligned_be24(u8 *buf)  enum { -#ifndef FSG_NO_DEVICE_STRINGS -	FSG_STRING_MANUFACTURER	= 1, -	FSG_STRING_PRODUCT, -	FSG_STRING_SERIAL, -	FSG_STRING_CONFIG, -#endif  	FSG_STRING_INTERFACE  }; -#ifndef FSG_NO_OTG -static struct usb_otg_descriptor -fsg_otg_desc = { -	.bLength =		sizeof fsg_otg_desc, -	.bDescriptorType =	USB_DT_OTG, - -	.bmAttributes =		USB_OTG_SRP, -}; -#endif -  /* There is only one interface. */  static struct usb_interface_descriptor @@ -367,37 +306,10 @@ fsg_fs_bulk_out_desc = {  	/* wMaxPacketSize set by autoconfiguration */  }; -#ifndef FSG_NO_INTR_EP - -static struct usb_endpoint_descriptor -fsg_fs_intr_in_desc = { -	.bLength =		USB_DT_ENDPOINT_SIZE, -	.bDescriptorType =	USB_DT_ENDPOINT, - -	.bEndpointAddress =	USB_DIR_IN, -	.bmAttributes =		USB_ENDPOINT_XFER_INT, -	.wMaxPacketSize =	cpu_to_le16(2), -	.bInterval =		32,	/* frames -> 32 ms */ -}; - -#ifndef FSG_NO_OTG -#  define FSG_FS_FUNCTION_PRE_EP_ENTRIES	2 -#else -#  define FSG_FS_FUNCTION_PRE_EP_ENTRIES	1 -#endif - -#endif -  static struct usb_descriptor_header *fsg_fs_function[] = { -#ifndef FSG_NO_OTG -	(struct usb_descriptor_header *) &fsg_otg_desc, -#endif  	(struct usb_descriptor_header *) &fsg_intf_desc,  	(struct usb_descriptor_header *) &fsg_fs_bulk_in_desc,  	(struct usb_descriptor_header *) &fsg_fs_bulk_out_desc, -#ifndef FSG_NO_INTR_EP -	(struct usb_descriptor_header *) &fsg_fs_intr_in_desc, -#endif  	NULL,  }; @@ -431,37 +343,11 @@ fsg_hs_bulk_out_desc = {  	.bInterval =		1,	/* NAK every 1 uframe */  }; -#ifndef FSG_NO_INTR_EP - -static struct usb_endpoint_descriptor -fsg_hs_intr_in_desc = { -	.bLength =		USB_DT_ENDPOINT_SIZE, -	.bDescriptorType =	USB_DT_ENDPOINT, - -	/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ -	.bmAttributes =		USB_ENDPOINT_XFER_INT, -	.wMaxPacketSize =	cpu_to_le16(2), -	.bInterval =		9,	/* 2**(9-1) = 256 uframes -> 32 ms */ -}; - -#ifndef FSG_NO_OTG -#  define FSG_HS_FUNCTION_PRE_EP_ENTRIES	2 -#else -#  define FSG_HS_FUNCTION_PRE_EP_ENTRIES	1 -#endif - -#endif  static struct usb_descriptor_header *fsg_hs_function[] = { -#ifndef FSG_NO_OTG -	(struct usb_descriptor_header *) &fsg_otg_desc, -#endif  	(struct usb_descriptor_header *) &fsg_intf_desc,  	(struct usb_descriptor_header *) &fsg_hs_bulk_in_desc,  	(struct usb_descriptor_header *) &fsg_hs_bulk_out_desc, -#ifndef FSG_NO_INTR_EP -	(struct usb_descriptor_header *) &fsg_hs_intr_in_desc, -#endif  	NULL,  }; @@ -499,34 +385,6 @@ static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {  	/*.bMaxBurst =		DYNAMIC, */  }; -#ifndef FSG_NO_INTR_EP - -static struct usb_endpoint_descriptor -fsg_ss_intr_in_desc = { -	.bLength =		USB_DT_ENDPOINT_SIZE, -	.bDescriptorType =	USB_DT_ENDPOINT, - -	/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ -	.bmAttributes =		USB_ENDPOINT_XFER_INT, -	.wMaxPacketSize =	cpu_to_le16(2), -	.bInterval =		9,	/* 2**(9-1) = 256 uframes -> 32 ms */ -}; - -static struct usb_ss_ep_comp_descriptor fsg_ss_intr_in_comp_desc = { -	.bLength =		sizeof(fsg_ss_bulk_in_comp_desc), -	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP, - -	.wBytesPerInterval =	cpu_to_le16(2), -}; - -#ifndef FSG_NO_OTG -#  define FSG_SS_FUNCTION_PRE_EP_ENTRIES	2 -#else -#  define FSG_SS_FUNCTION_PRE_EP_ENTRIES	1 -#endif - -#endif -  static __maybe_unused struct usb_ext_cap_descriptor fsg_ext_cap_desc = {  	.bLength =		USB_DT_USB_EXT_CAP_SIZE,  	.bDescriptorType =	USB_DT_DEVICE_CAPABILITY, @@ -563,18 +421,11 @@ static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = {  };  static struct usb_descriptor_header *fsg_ss_function[] = { -#ifndef FSG_NO_OTG -	(struct usb_descriptor_header *) &fsg_otg_desc, -#endif  	(struct usb_descriptor_header *) &fsg_intf_desc,  	(struct usb_descriptor_header *) &fsg_ss_bulk_in_desc,  	(struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc,  	(struct usb_descriptor_header *) &fsg_ss_bulk_out_desc,  	(struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc, -#ifndef FSG_NO_INTR_EP -	(struct usb_descriptor_header *) &fsg_ss_intr_in_desc, -	(struct usb_descriptor_header *) &fsg_ss_intr_in_comp_desc, -#endif  	NULL,  }; @@ -594,12 +445,6 @@ fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,  /* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */  static struct usb_string		fsg_strings[] = { -#ifndef FSG_NO_DEVICE_STRINGS -	{FSG_STRING_MANUFACTURER,	fsg_string_manufacturer}, -	{FSG_STRING_PRODUCT,		fsg_string_product}, -	{FSG_STRING_SERIAL,		""}, -	{FSG_STRING_CONFIG,		fsg_string_config}, -#endif  	{FSG_STRING_INTERFACE,		fsg_string_interface},  	{}  }; diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 97e68b38cfd..4f7f76f00c7 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -1384,7 +1384,7 @@ static struct se_node_acl *usbg_alloc_fabric_acl(struct se_portal_group *se_tpg)  	nacl = kzalloc(sizeof(struct usbg_nacl), GFP_KERNEL);  	if (!nacl) { -		printk(KERN_ERR "Unable to alocate struct usbg_nacl\n"); +		printk(KERN_ERR "Unable to allocate struct usbg_nacl\n");  		return NULL;  	} @@ -2139,6 +2139,7 @@ static struct usb_descriptor_header *uasp_fs_function_desc[] = {  	(struct usb_descriptor_header *) &uasp_status_pipe_desc,  	(struct usb_descriptor_header *) &uasp_fs_cmd_desc,  	(struct usb_descriptor_header *) &uasp_cmd_pipe_desc, +	NULL,  };  static struct usb_descriptor_header *uasp_hs_function_desc[] = { @@ -2239,6 +2240,7 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)  	struct usb_gadget	*gadget = c->cdev->gadget;  	struct usb_ep		*ep;  	int			iface; +	int			ret;  	iface = usb_interface_id(c, f);  	if (iface < 0) @@ -2289,6 +2291,11 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)  		uasp_ss_status_desc.bEndpointAddress;  	uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress; +	ret = usb_assign_descriptors(f, uasp_fs_function_desc, +			uasp_hs_function_desc, uasp_ss_function_desc); +	if (ret) +		goto ep_fail; +  	return 0;  ep_fail:  	pr_err("Can't claim all required eps\n"); @@ -2304,6 +2311,7 @@ static void usbg_unbind(struct usb_configuration *c, struct usb_function *f)  {  	struct f_uas *fu = to_f_uas(f); +	usb_free_all_descriptors(f);  	kfree(fu);  } @@ -2384,9 +2392,6 @@ static int usbg_cfg_bind(struct usb_configuration *c)  	if (!fu)  		return -ENOMEM;  	fu->function.name = "Target Function"; -	fu->function.descriptors = uasp_fs_function_desc; -	fu->function.hs_descriptors = uasp_hs_function_desc; -	fu->function.ss_descriptors = uasp_ss_function_desc;  	fu->function.bind = usbg_bind;  	fu->function.unbind = usbg_unbind;  	fu->function.set_alt = usbg_set_alt; diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index f1739526820..d0f95482f40 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -1145,8 +1145,10 @@ int gserial_setup(struct usb_gadget *g, unsigned count)  	return status;  fail: -	while (count--) +	while (count--) { +		tty_port_destroy(&ports[count].port->port);  		kfree(ports[count].port); +	}  	put_tty_driver(gs_tty_driver);  	gs_tty_driver = NULL;  	return status; @@ -1200,6 +1202,7 @@ void gserial_cleanup(void)  		WARN_ON(port->port_usb != NULL); +		tty_port_destroy(&port->port);  		kfree(port);  	}  	n_ports = 0; diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index f3cd9690b10..4d90a800063 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -439,16 +439,6 @@ static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL)  static USB_UDC_SPEED_ATTR(current_speed, speed);  static USB_UDC_SPEED_ATTR(maximum_speed, max_speed); -/* TODO: Scheduled for removal in 3.8. */ -static ssize_t usb_udc_is_dualspeed_show(struct device *dev, -		struct device_attribute *attr, char *buf) -{ -	struct usb_udc		*udc = container_of(dev, struct usb_udc, dev); -	return snprintf(buf, PAGE_SIZE, "%d\n", -			gadget_is_dualspeed(udc->gadget)); -} -static DEVICE_ATTR(is_dualspeed, S_IRUSR, usb_udc_is_dualspeed_show, NULL); -  #define USB_UDC_ATTR(name)					\  ssize_t usb_udc_##name##_show(struct device *dev,		\  		struct device_attribute *attr, char *buf)	\ @@ -472,7 +462,6 @@ static struct attribute *usb_udc_attrs[] = {  	&dev_attr_current_speed.attr,  	&dev_attr_maximum_speed.attr, -	&dev_attr_is_dualspeed.attr,  	&dev_attr_is_otg.attr,  	&dev_attr_is_a_peripheral.attr,  	&dev_attr_b_hnp_enable.attr, diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 3f1431d37e1..d6bb128ce21 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -95,6 +95,11 @@ config USB_EHCI_TT_NEWSCHED  	  If unsure, say Y. +config USB_EHCI_PCI +	tristate +	depends on USB_EHCI_HCD && 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 @@ -215,9 +220,13 @@ config USB_W90X900_EHCI  		Enables support for the W90X900 USB controller  config USB_CNS3XXX_EHCI -	bool "Cavium CNS3XXX EHCI Module" +	bool "Cavium CNS3XXX EHCI Module (DEPRECATED)"  	depends on USB_EHCI_HCD && ARCH_CNS3XXX +	select USB_EHCI_HCD_PLATFORM  	---help--- +	  This option is deprecated now and the driver was removed, use +	  USB_EHCI_HCD_PLATFORM instead. +  	  Enable support for the CNS3XXX SOC's on-chip EHCI controller.  	  It is needed for high-speed (480Mbit/sec) USB 2.0 device  	  support. @@ -333,16 +342,6 @@ config USB_OHCI_ATH79  	  Enables support for the built-in OHCI controller present on the  	  Atheros AR71XX/AR7240 SoCs. -config USB_OHCI_HCD_PPC_SOC -	bool "OHCI support for on-chip PPC USB controller" -	depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx) -	default y -	select USB_OHCI_BIG_ENDIAN_DESC -	select USB_OHCI_BIG_ENDIAN_MMIO -	---help--- -	  Enables support for the USB controller on the MPC52xx or -	  STB03xxx processor chip.  If unsure, say Y. -  config USB_OHCI_HCD_PPC_OF_BE  	bool "OHCI support for OF platform bus (big endian)"  	depends on USB_OHCI_HCD && PPC_OF @@ -393,9 +392,13 @@ config USB_OHCI_HCD_SSB  	  If unsure, say N.  config USB_OHCI_SH -	bool "OHCI support for SuperH USB controller" +	bool "OHCI support for SuperH USB controller (DEPRECATED)"  	depends on USB_OHCI_HCD && SUPERH +	select USB_OHCI_HCD_PLATFORM  	---help--- +	  This option is deprecated now and the driver was removed, use +	  USB_OHCI_HCD_PLATFORM instead. +  	  Enables support for the on-chip OHCI controller on the SuperH.  	  If you use the PCI OHCI controller, this option is not necessary. @@ -406,9 +409,13 @@ config USB_OHCI_EXYNOS  	 Enable support for the Samsung Exynos SOC's on-chip OHCI controller.  config USB_CNS3XXX_OHCI -	bool "Cavium CNS3XXX OHCI Module" +	bool "Cavium CNS3XXX OHCI Module (DEPRECATED)"  	depends on USB_OHCI_HCD && ARCH_CNS3XXX +	select USB_OHCI_HCD_PLATFORM  	---help--- +	  This option is deprecated now and the driver was removed, use +	  USB_OHCI_HCD_PLATFORM instead. +  	  Enable support for the CNS3XXX SOC's on-chip OHCI controller.  	  It is needed for low-speed USB 1.0 device support. @@ -423,7 +430,7 @@ config USB_OHCI_HCD_PLATFORM  	  If unsure, say N.  config USB_EHCI_HCD_PLATFORM -	bool "Generic EHCI driver for a platform device" +	tristate "Generic EHCI driver for a platform device"  	depends on USB_EHCI_HCD  	default n  	---help--- diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 9e0a89ced15..1eb4c3006e9 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -24,6 +24,9 @@ obj-$(CONFIG_USB_WHCI_HCD)	+= whci/  obj-$(CONFIG_PCI)		+= pci-quirks.o  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_OXU210HP_HCD)	+= oxu210hp-hcd.o  obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o  obj-$(CONFIG_USB_ISP1362_HCD)	+= isp1362-hcd.o @@ -40,6 +43,5 @@ obj-$(CONFIG_USB_HWA_HCD)	+= hwa-hc.o  obj-$(CONFIG_USB_IMX21_HCD)	+= imx21-hcd.o  obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= fsl-mph-dr-of.o  obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o -obj-$(CONFIG_MIPS_ALCHEMY)	+= alchemy-common.o  obj-$(CONFIG_USB_HCD_BCMA)	+= bcma-hcd.o  obj-$(CONFIG_USB_HCD_SSB)	+= ssb-hcd.o diff --git a/drivers/usb/host/alchemy-common.c b/drivers/usb/host/alchemy-common.c deleted file mode 100644 index 936af8359fb..00000000000 --- a/drivers/usb/host/alchemy-common.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - * USB block power/access management abstraction. - * - * Au1000+: The OHCI block control register is at the far end of the OHCI memory - *	    area. Au1550 has OHCI on different base address. No need to handle - *	    UDC here. - * Au1200:  one register to control access and clocks to O/EHCI, UDC and OTG - *	    as well as the PHY for EHCI and UDC. - * - */ - -#include <linux/init.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/spinlock.h> -#include <linux/syscore_ops.h> -#include <asm/mach-au1x00/au1000.h> - -/* control register offsets */ -#define AU1000_OHCICFG	0x7fffc -#define AU1550_OHCICFG	0x07ffc -#define AU1200_USBCFG	0x04 - -/* Au1000 USB block config bits */ -#define USBHEN_RD	(1 << 4)		/* OHCI reset-done indicator */ -#define USBHEN_CE	(1 << 3)		/* OHCI block clock enable */ -#define USBHEN_E	(1 << 2)		/* OHCI block enable */ -#define USBHEN_C	(1 << 1)		/* OHCI block coherency bit */ -#define USBHEN_BE	(1 << 0)		/* OHCI Big-Endian */ - -/* Au1200 USB config bits */ -#define USBCFG_PFEN	(1 << 31)		/* prefetch enable (undoc) */ -#define USBCFG_RDCOMB	(1 << 30)		/* read combining (undoc) */ -#define USBCFG_UNKNOWN	(5 << 20)		/* unknown, leave this way */ -#define USBCFG_SSD	(1 << 23)		/* serial short detect en */ -#define USBCFG_PPE	(1 << 19)		/* HS PHY PLL */ -#define USBCFG_UCE	(1 << 18)		/* UDC clock enable */ -#define USBCFG_ECE	(1 << 17)		/* EHCI clock enable */ -#define USBCFG_OCE	(1 << 16)		/* OHCI clock enable */ -#define USBCFG_FLA(x)	(((x) & 0x3f) << 8) -#define USBCFG_UCAM	(1 << 7)		/* coherent access (undoc) */ -#define USBCFG_GME	(1 << 6)		/* OTG mem access */ -#define USBCFG_DBE	(1 << 5)		/* UDC busmaster enable */ -#define USBCFG_DME	(1 << 4)		/* UDC mem enable */ -#define USBCFG_EBE	(1 << 3)		/* EHCI busmaster enable */ -#define USBCFG_EME	(1 << 2)		/* EHCI mem enable */ -#define USBCFG_OBE	(1 << 1)		/* OHCI busmaster enable */ -#define USBCFG_OME	(1 << 0)		/* OHCI mem enable */ -#define USBCFG_INIT_AU1200	(USBCFG_PFEN | USBCFG_RDCOMB | USBCFG_UNKNOWN |\ -				 USBCFG_SSD | USBCFG_FLA(0x20) | USBCFG_UCAM | \ -				 USBCFG_GME | USBCFG_DBE | USBCFG_DME |	       \ -				 USBCFG_EBE | USBCFG_EME | USBCFG_OBE |	       \ -				 USBCFG_OME) - -/* Au1300 USB config registers */ -#define USB_DWC_CTRL1		0x00 -#define USB_DWC_CTRL2		0x04 -#define USB_VBUS_TIMER		0x10 -#define USB_SBUS_CTRL		0x14 -#define USB_MSR_ERR		0x18 -#define USB_DWC_CTRL3		0x1C -#define USB_DWC_CTRL4		0x20 -#define USB_OTG_STATUS		0x28 -#define USB_DWC_CTRL5		0x2C -#define USB_DWC_CTRL6		0x30 -#define USB_DWC_CTRL7		0x34 -#define USB_PHY_STATUS		0xC0 -#define USB_INT_STATUS		0xC4 -#define USB_INT_ENABLE		0xC8 - -#define USB_DWC_CTRL1_OTGD	0x04 /* set to DISable OTG */ -#define USB_DWC_CTRL1_HSTRS	0x02 /* set to ENable EHCI */ -#define USB_DWC_CTRL1_DCRS	0x01 /* set to ENable UDC */ - -#define USB_DWC_CTRL2_PHY1RS	0x04 /* set to enable PHY1 */ -#define USB_DWC_CTRL2_PHY0RS	0x02 /* set to enable PHY0 */ -#define USB_DWC_CTRL2_PHYRS	0x01 /* set to enable PHY */ - -#define USB_DWC_CTRL3_OHCI1_CKEN	(1 << 19) -#define USB_DWC_CTRL3_OHCI0_CKEN	(1 << 18) -#define USB_DWC_CTRL3_EHCI0_CKEN	(1 << 17) -#define USB_DWC_CTRL3_OTG0_CKEN		(1 << 16) - -#define USB_SBUS_CTRL_SBCA		0x04 /* coherent access */ - -#define USB_INTEN_FORCE			0x20 -#define USB_INTEN_PHY			0x10 -#define USB_INTEN_UDC			0x08 -#define USB_INTEN_EHCI			0x04 -#define USB_INTEN_OHCI1			0x02 -#define USB_INTEN_OHCI0			0x01 - -static DEFINE_SPINLOCK(alchemy_usb_lock); - -static inline void __au1300_usb_phyctl(void __iomem *base, int enable) -{ -	unsigned long r, s; - -	r = __raw_readl(base + USB_DWC_CTRL2); -	s = __raw_readl(base + USB_DWC_CTRL3); - -	s &= USB_DWC_CTRL3_OHCI1_CKEN | USB_DWC_CTRL3_OHCI0_CKEN | -		USB_DWC_CTRL3_EHCI0_CKEN | USB_DWC_CTRL3_OTG0_CKEN; - -	if (enable) { -		/* simply enable all PHYs */ -		r |= USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS | -		     USB_DWC_CTRL2_PHYRS; -		__raw_writel(r, base + USB_DWC_CTRL2); -		wmb(); -	} else if (!s) { -		/* no USB block active, do disable all PHYs */ -		r &= ~(USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS | -		       USB_DWC_CTRL2_PHYRS); -		__raw_writel(r, base + USB_DWC_CTRL2); -		wmb(); -	} -} - -static inline void __au1300_ohci_control(void __iomem *base, int enable, int id) -{ -	unsigned long r; - -	if (enable) { -		__raw_writel(1, base + USB_DWC_CTRL7);  /* start OHCI clock */ -		wmb(); - -		r = __raw_readl(base + USB_DWC_CTRL3);	/* enable OHCI block */ -		r |= (id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN -			       : USB_DWC_CTRL3_OHCI1_CKEN; -		__raw_writel(r, base + USB_DWC_CTRL3); -		wmb(); - -		__au1300_usb_phyctl(base, enable);	/* power up the PHYs */ - -		r = __raw_readl(base + USB_INT_ENABLE); -		r |= (id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1; -		__raw_writel(r, base + USB_INT_ENABLE); -		wmb(); - -		/* reset the OHCI start clock bit */ -		__raw_writel(0, base + USB_DWC_CTRL7); -		wmb(); -	} else { -		r = __raw_readl(base + USB_INT_ENABLE); -		r &= ~((id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1); -		__raw_writel(r, base + USB_INT_ENABLE); -		wmb(); - -		r = __raw_readl(base + USB_DWC_CTRL3); -		r &= ~((id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN -				 : USB_DWC_CTRL3_OHCI1_CKEN); -		__raw_writel(r, base + USB_DWC_CTRL3); -		wmb(); - -		__au1300_usb_phyctl(base, enable); -	} -} - -static inline void __au1300_ehci_control(void __iomem *base, int enable) -{ -	unsigned long r; - -	if (enable) { -		r = __raw_readl(base + USB_DWC_CTRL3); -		r |= USB_DWC_CTRL3_EHCI0_CKEN; -		__raw_writel(r, base + USB_DWC_CTRL3); -		wmb(); - -		r = __raw_readl(base + USB_DWC_CTRL1); -		r |= USB_DWC_CTRL1_HSTRS; -		__raw_writel(r, base + USB_DWC_CTRL1); -		wmb(); - -		__au1300_usb_phyctl(base, enable); - -		r = __raw_readl(base + USB_INT_ENABLE); -		r |= USB_INTEN_EHCI; -		__raw_writel(r, base + USB_INT_ENABLE); -		wmb(); -	} else { -		r = __raw_readl(base + USB_INT_ENABLE); -		r &= ~USB_INTEN_EHCI; -		__raw_writel(r, base + USB_INT_ENABLE); -		wmb(); - -		r = __raw_readl(base + USB_DWC_CTRL1); -		r &= ~USB_DWC_CTRL1_HSTRS; -		__raw_writel(r, base + USB_DWC_CTRL1); -		wmb(); - -		r = __raw_readl(base + USB_DWC_CTRL3); -		r &= ~USB_DWC_CTRL3_EHCI0_CKEN; -		__raw_writel(r, base + USB_DWC_CTRL3); -		wmb(); - -		__au1300_usb_phyctl(base, enable); -	} -} - -static inline void __au1300_udc_control(void __iomem *base, int enable) -{ -	unsigned long r; - -	if (enable) { -		r = __raw_readl(base + USB_DWC_CTRL1); -		r |= USB_DWC_CTRL1_DCRS; -		__raw_writel(r, base + USB_DWC_CTRL1); -		wmb(); - -		__au1300_usb_phyctl(base, enable); - -		r = __raw_readl(base + USB_INT_ENABLE); -		r |= USB_INTEN_UDC; -		__raw_writel(r, base + USB_INT_ENABLE); -		wmb(); -	} else { -		r = __raw_readl(base + USB_INT_ENABLE); -		r &= ~USB_INTEN_UDC; -		__raw_writel(r, base + USB_INT_ENABLE); -		wmb(); - -		r = __raw_readl(base + USB_DWC_CTRL1); -		r &= ~USB_DWC_CTRL1_DCRS; -		__raw_writel(r, base + USB_DWC_CTRL1); -		wmb(); - -		__au1300_usb_phyctl(base, enable); -	} -} - -static inline void __au1300_otg_control(void __iomem *base, int enable) -{ -	unsigned long r; -	if (enable) { -		r = __raw_readl(base + USB_DWC_CTRL3); -		r |= USB_DWC_CTRL3_OTG0_CKEN; -		__raw_writel(r, base + USB_DWC_CTRL3); -		wmb(); - -		r = __raw_readl(base + USB_DWC_CTRL1); -		r &= ~USB_DWC_CTRL1_OTGD; -		__raw_writel(r, base + USB_DWC_CTRL1); -		wmb(); - -		__au1300_usb_phyctl(base, enable); -	} else { -		r = __raw_readl(base + USB_DWC_CTRL1); -		r |= USB_DWC_CTRL1_OTGD; -		__raw_writel(r, base + USB_DWC_CTRL1); -		wmb(); - -		r = __raw_readl(base + USB_DWC_CTRL3); -		r &= ~USB_DWC_CTRL3_OTG0_CKEN; -		__raw_writel(r, base + USB_DWC_CTRL3); -		wmb(); - -		__au1300_usb_phyctl(base, enable); -	} -} - -static inline int au1300_usb_control(int block, int enable) -{ -	void __iomem *base = -		(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR); -	int ret = 0; - -	switch (block) { -	case ALCHEMY_USB_OHCI0: -		__au1300_ohci_control(base, enable, 0); -		break; -	case ALCHEMY_USB_OHCI1: -		__au1300_ohci_control(base, enable, 1); -		break; -	case ALCHEMY_USB_EHCI0: -		__au1300_ehci_control(base, enable); -		break; -	case ALCHEMY_USB_UDC0: -		__au1300_udc_control(base, enable); -		break; -	case ALCHEMY_USB_OTG0: -		__au1300_otg_control(base, enable); -		break; -	default: -		ret = -ENODEV; -	} -	return ret; -} - -static inline void au1300_usb_init(void) -{ -	void __iomem *base = -		(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR); - -	/* set some sane defaults.  Note: we don't fiddle with DWC_CTRL4 -	 * here at all: Port 2 routing (EHCI or UDC) must be set either -	 * by boot firmware or platform init code; I can't autodetect -	 * a sane setting. -	 */ -	__raw_writel(0, base + USB_INT_ENABLE); /* disable all USB irqs */ -	wmb(); -	__raw_writel(0, base + USB_DWC_CTRL3); /* disable all clocks */ -	wmb(); -	__raw_writel(~0, base + USB_MSR_ERR); /* clear all errors */ -	wmb(); -	__raw_writel(~0, base + USB_INT_STATUS); /* clear int status */ -	wmb(); -	/* set coherent access bit */ -	__raw_writel(USB_SBUS_CTRL_SBCA, base + USB_SBUS_CTRL); -	wmb(); -} - -static inline void __au1200_ohci_control(void __iomem *base, int enable) -{ -	unsigned long r = __raw_readl(base + AU1200_USBCFG); -	if (enable) { -		__raw_writel(r | USBCFG_OCE, base + AU1200_USBCFG); -		wmb(); -		udelay(2000); -	} else { -		__raw_writel(r & ~USBCFG_OCE, base + AU1200_USBCFG); -		wmb(); -		udelay(1000); -	} -} - -static inline void __au1200_ehci_control(void __iomem *base, int enable) -{ -	unsigned long r = __raw_readl(base + AU1200_USBCFG); -	if (enable) { -		__raw_writel(r | USBCFG_ECE | USBCFG_PPE, base + AU1200_USBCFG); -		wmb(); -		udelay(1000); -	} else { -		if (!(r & USBCFG_UCE))		/* UDC also off? */ -			r &= ~USBCFG_PPE;	/* yes: disable HS PHY PLL */ -		__raw_writel(r & ~USBCFG_ECE, base + AU1200_USBCFG); -		wmb(); -		udelay(1000); -	} -} - -static inline void __au1200_udc_control(void __iomem *base, int enable) -{ -	unsigned long r = __raw_readl(base + AU1200_USBCFG); -	if (enable) { -		__raw_writel(r | USBCFG_UCE | USBCFG_PPE, base + AU1200_USBCFG); -		wmb(); -	} else { -		if (!(r & USBCFG_ECE))		/* EHCI also off? */ -			r &= ~USBCFG_PPE;	/* yes: disable HS PHY PLL */ -		__raw_writel(r & ~USBCFG_UCE, base + AU1200_USBCFG); -		wmb(); -	} -} - -static inline int au1200_coherency_bug(void) -{ -#if defined(CONFIG_DMA_COHERENT) -	/* Au1200 AB USB does not support coherent memory */ -	if (!(read_c0_prid() & 0xff)) { -		printk(KERN_INFO "Au1200 USB: this is chip revision AB !!\n"); -		printk(KERN_INFO "Au1200 USB: update your board or re-configure" -				 " the kernel\n"); -		return -ENODEV; -	} -#endif -	return 0; -} - -static inline int au1200_usb_control(int block, int enable) -{ -	void __iomem *base = -			(void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR); -	int ret = 0; - -	switch (block) { -	case ALCHEMY_USB_OHCI0: -		ret = au1200_coherency_bug(); -		if (ret && enable) -			goto out; -		__au1200_ohci_control(base, enable); -		break; -	case ALCHEMY_USB_UDC0: -		__au1200_udc_control(base, enable); -		break; -	case ALCHEMY_USB_EHCI0: -		ret = au1200_coherency_bug(); -		if (ret && enable) -			goto out; -		__au1200_ehci_control(base, enable); -		break; -	default: -		ret = -ENODEV; -	} -out: -	return ret; -} - - -/* initialize USB block(s) to a known working state */ -static inline void au1200_usb_init(void) -{ -	void __iomem *base = -			(void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR); -	__raw_writel(USBCFG_INIT_AU1200, base + AU1200_USBCFG); -	wmb(); -	udelay(1000); -} - -static inline void au1000_usb_init(unsigned long rb, int reg) -{ -	void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg); -	unsigned long r = __raw_readl(base); - -#if defined(__BIG_ENDIAN) -	r |= USBHEN_BE; -#endif -	r |= USBHEN_C; - -	__raw_writel(r, base); -	wmb(); -	udelay(1000); -} - - -static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg) -{ -	void __iomem *base = (void __iomem *)KSEG1ADDR(rb); -	unsigned long r = __raw_readl(base + creg); - -	if (enable) { -		__raw_writel(r | USBHEN_CE, base + creg); -		wmb(); -		udelay(1000); -		__raw_writel(r | USBHEN_CE | USBHEN_E, base + creg); -		wmb(); -		udelay(1000); - -		/* wait for reset complete (read reg twice: au1500 erratum) */ -		while (__raw_readl(base + creg), -			!(__raw_readl(base + creg) & USBHEN_RD)) -			udelay(1000); -	} else { -		__raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg); -		wmb(); -	} -} - -static inline int au1000_usb_control(int block, int enable, unsigned long rb, -				     int creg) -{ -	int ret = 0; - -	switch (block) { -	case ALCHEMY_USB_OHCI0: -		__au1xx0_ohci_control(enable, rb, creg); -		break; -	default: -		ret = -ENODEV; -	} -	return ret; -} - -/* - * alchemy_usb_control - control Alchemy on-chip USB blocks - * @block:	USB block to target - * @enable:	set 1 to enable a block, 0 to disable - */ -int alchemy_usb_control(int block, int enable) -{ -	unsigned long flags; -	int ret; - -	spin_lock_irqsave(&alchemy_usb_lock, flags); -	switch (alchemy_get_cputype()) { -	case ALCHEMY_CPU_AU1000: -	case ALCHEMY_CPU_AU1500: -	case ALCHEMY_CPU_AU1100: -		ret = au1000_usb_control(block, enable, -				AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG); -		break; -	case ALCHEMY_CPU_AU1550: -		ret = au1000_usb_control(block, enable, -				AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG); -		break; -	case ALCHEMY_CPU_AU1200: -		ret = au1200_usb_control(block, enable); -		break; -	case ALCHEMY_CPU_AU1300: -		ret = au1300_usb_control(block, enable); -		break; -	default: -		ret = -ENODEV; -	} -	spin_unlock_irqrestore(&alchemy_usb_lock, flags); -	return ret; -} -EXPORT_SYMBOL_GPL(alchemy_usb_control); - - -static unsigned long alchemy_usb_pmdata[2]; - -static void au1000_usb_pm(unsigned long br, int creg, int susp) -{ -	void __iomem *base = (void __iomem *)KSEG1ADDR(br); - -	if (susp) { -		alchemy_usb_pmdata[0] = __raw_readl(base + creg); -		/* There appears to be some undocumented reset register.... */ -		__raw_writel(0, base + 0x04); -		wmb(); -		__raw_writel(0, base + creg); -		wmb(); -	} else { -		__raw_writel(alchemy_usb_pmdata[0], base + creg); -		wmb(); -	} -} - -static void au1200_usb_pm(int susp) -{ -	void __iomem *base = -			(void __iomem *)KSEG1ADDR(AU1200_USB_OTG_PHYS_ADDR); -	if (susp) { -		/* save OTG_CAP/MUX registers which indicate port routing */ -		/* FIXME: write an OTG driver to do that */ -		alchemy_usb_pmdata[0] = __raw_readl(base + 0x00); -		alchemy_usb_pmdata[1] = __raw_readl(base + 0x04); -	} else { -		/* restore access to all MMIO areas */ -		au1200_usb_init(); - -		/* restore OTG_CAP/MUX registers */ -		__raw_writel(alchemy_usb_pmdata[0], base + 0x00); -		__raw_writel(alchemy_usb_pmdata[1], base + 0x04); -		wmb(); -	} -} - -static void au1300_usb_pm(int susp) -{ -	void __iomem *base = -			(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR); -	/* remember Port2 routing */ -	if (susp) { -		alchemy_usb_pmdata[0] = __raw_readl(base + USB_DWC_CTRL4); -	} else { -		au1300_usb_init(); -		__raw_writel(alchemy_usb_pmdata[0], base + USB_DWC_CTRL4); -		wmb(); -	} -} - -static void alchemy_usb_pm(int susp) -{ -	switch (alchemy_get_cputype()) { -	case ALCHEMY_CPU_AU1000: -	case ALCHEMY_CPU_AU1500: -	case ALCHEMY_CPU_AU1100: -		au1000_usb_pm(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG, susp); -		break; -	case ALCHEMY_CPU_AU1550: -		au1000_usb_pm(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG, susp); -		break; -	case ALCHEMY_CPU_AU1200: -		au1200_usb_pm(susp); -		break; -	case ALCHEMY_CPU_AU1300: -		au1300_usb_pm(susp); -		break; -	} -} - -static int alchemy_usb_suspend(void) -{ -	alchemy_usb_pm(1); -	return 0; -} - -static void alchemy_usb_resume(void) -{ -	alchemy_usb_pm(0); -} - -static struct syscore_ops alchemy_usb_pm_ops = { -	.suspend	= alchemy_usb_suspend, -	.resume		= alchemy_usb_resume, -}; - -static int __init alchemy_usb_init(void) -{ -	switch (alchemy_get_cputype()) { -	case ALCHEMY_CPU_AU1000: -	case ALCHEMY_CPU_AU1500: -	case ALCHEMY_CPU_AU1100: -		au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG); -		break; -	case ALCHEMY_CPU_AU1550: -		au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG); -		break; -	case ALCHEMY_CPU_AU1200: -		au1200_usb_init(); -		break; -	case ALCHEMY_CPU_AU1300: -		au1300_usb_init(); -		break; -	} - -	register_syscore_ops(&alchemy_usb_pm_ops); - -	return 0; -} -arch_initcall(alchemy_usb_init); diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c index 443da21d73c..df13d425e9c 100644 --- a/drivers/usb/host/bcma-hcd.c +++ b/drivers/usb/host/bcma-hcd.c @@ -54,7 +54,7 @@ static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask,  	return -ETIMEDOUT;  } -static void __devinit bcma_hcd_4716wa(struct bcma_device *dev) +static void bcma_hcd_4716wa(struct bcma_device *dev)  {  #ifdef CONFIG_BCMA_DRIVER_MIPS  	/* Work around for 4716 failures. */ @@ -88,7 +88,7 @@ static void __devinit bcma_hcd_4716wa(struct bcma_device *dev)  }  /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ -static void __devinit bcma_hcd_init_chip(struct bcma_device *dev) +static void bcma_hcd_init_chip(struct bcma_device *dev)  {  	u32 tmp; @@ -165,8 +165,7 @@ static const struct usb_ehci_pdata ehci_pdata = {  static const struct usb_ohci_pdata ohci_pdata = {  }; -static struct platform_device * __devinit -bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr) +static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr)  {  	struct platform_device *hci_dev;  	struct resource hci_res[2]; @@ -212,7 +211,7 @@ err_alloc:  	return ERR_PTR(ret);  } -static int __devinit bcma_hcd_probe(struct bcma_device *dev) +static int bcma_hcd_probe(struct bcma_device *dev)  {  	int err;  	u16 chipid_top; @@ -266,7 +265,7 @@ err_free_usb_dev:  	return err;  } -static void __devexit bcma_hcd_remove(struct bcma_device *dev) +static void bcma_hcd_remove(struct bcma_device *dev)  {  	struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);  	struct platform_device *ohci_dev = usb_dev->ohci_dev; @@ -306,7 +305,7 @@ static int bcma_hcd_resume(struct bcma_device *dev)  #define bcma_hcd_resume	NULL  #endif /* CONFIG_PM */ -static const struct bcma_device_id bcma_hcd_table[] __devinitconst = { +static const struct bcma_device_id bcma_hcd_table[] = {  	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),  	BCMA_CORETABLE_END  }; @@ -316,7 +315,7 @@ static struct bcma_driver bcma_hcd_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= bcma_hcd_table,  	.probe		= bcma_hcd_probe, -	.remove		= __devexit_p(bcma_hcd_remove), +	.remove		= bcma_hcd_remove,  	.shutdown	= bcma_hcd_shutdown,  	.suspend	= bcma_hcd_suspend,  	.resume		= bcma_hcd_resume, diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 411bb74152e..27639487f7a 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -53,18 +53,11 @@ 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); -	int retval;  	/* registers start at offset 0x0 */  	ehci->caps = hcd->regs; -	retval = ehci_setup(hcd); -	if (retval) -		return retval; - -	ehci_port_power(ehci, 0); - -	return retval; +	return ehci_setup(hcd);  }  static const struct hc_driver ehci_atmel_hc_driver = { @@ -104,7 +97,7 @@ static const struct hc_driver ehci_atmel_hc_driver = {  static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32); -static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev) +static int ehci_atmel_drv_probe(struct platform_device *pdev)  {  	struct usb_hcd *hcd;  	const struct hc_driver *driver = &ehci_atmel_hc_driver; @@ -189,7 +182,7 @@ fail_create_hcd:  	return retval;  } -static int __devexit ehci_atmel_drv_remove(struct platform_device *pdev) +static int ehci_atmel_drv_remove(struct platform_device *pdev)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev); @@ -214,7 +207,7 @@ MODULE_DEVICE_TABLE(of, atmel_ehci_dt_ids);  static struct platform_driver ehci_atmel_driver = {  	.probe		= ehci_atmel_drv_probe, -	.remove		= __devexit_p(ehci_atmel_drv_remove), +	.remove		= ehci_atmel_drv_remove,  	.shutdown	= usb_hcd_platform_shutdown,  	.driver		= {  		.name	= "atmel-ehci", diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c deleted file mode 100644 index 65c945eb414..00000000000 --- a/drivers/usb/host/ehci-au1xxx.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * EHCI HCD (Host Controller Driver) for USB. - * - * Bus Glue for AMD Alchemy Au1xxx - * - * Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org> - * - * Modified for AMD Alchemy Au1200 EHC - *  by K.Boge <karsten.boge@amd.com> - * - * This file is licenced under the GPL. - */ - -#include <linux/platform_device.h> -#include <asm/mach-au1x00/au1000.h> - - -extern int usb_disabled(void); - -static int au1xxx_ehci_setup(struct usb_hcd *hcd) -{ -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); -	int ret; - -	ehci->caps = hcd->regs; -	ret = ehci_setup(hcd); - -	ehci->need_io_watchdog = 0; -	return ret; -} - -static const struct hc_driver ehci_au1xxx_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "Au1xxx EHCI", -	.hcd_priv_size		= sizeof(struct ehci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq			= ehci_irq, -	.flags			= HCD_MEMORY | HCD_USB2, - -	/* -	 * basic lifecycle operations -	 * -	 * FIXME -- ehci_init() doesn't do enough here. -	 * See ehci-ppc-soc for a complete implementation. -	 */ -	.reset			= au1xxx_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 int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) -{ -	struct usb_hcd *hcd; -	struct resource *res; -	int ret; - -	if (usb_disabled()) -		return -ENODEV; - -	if (pdev->resource[1].flags != IORESOURCE_IRQ) { -		pr_debug("resource[1] is not IORESOURCE_IRQ"); -		return -ENOMEM; -	} -	hcd = usb_create_hcd(&ehci_au1xxx_hc_driver, &pdev->dev, "Au1xxx"); -	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_request_and_ioremap(&pdev->dev, res); -	if (!hcd->regs) { -		pr_debug("devm_request_and_ioremap failed"); -		ret = -ENOMEM; -		goto err1; -	} - -	if (alchemy_usb_control(ALCHEMY_USB_EHCI0, 1)) { -		printk(KERN_INFO "%s: controller init failed!\n", pdev->name); -		ret = -ENODEV; -		goto err1; -	} - -	ret = usb_add_hcd(hcd, pdev->resource[1].start, -			  IRQF_SHARED); -	if (ret == 0) { -		platform_set_drvdata(pdev, hcd); -		return ret; -	} - -	alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); -err1: -	usb_put_hcd(hcd); -	return ret; -} - -static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev) -{ -	struct usb_hcd *hcd = platform_get_drvdata(pdev); - -	usb_remove_hcd(hcd); -	alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); -	usb_put_hcd(hcd); -	platform_set_drvdata(pdev, NULL); - -	return 0; -} - -#ifdef CONFIG_PM -static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) -{ -	struct usb_hcd *hcd = dev_get_drvdata(dev); -	bool do_wakeup = device_may_wakeup(dev); -	int rc; - -	rc = ehci_suspend(hcd, do_wakeup); -	alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); - -	return rc; -} - -static int ehci_hcd_au1xxx_drv_resume(struct device *dev) -{ -	struct usb_hcd *hcd = dev_get_drvdata(dev); - -	alchemy_usb_control(ALCHEMY_USB_EHCI0, 1); -	ehci_resume(hcd, false); - -	return 0; -} - -static const struct dev_pm_ops au1xxx_ehci_pmops = { -	.suspend	= ehci_hcd_au1xxx_drv_suspend, -	.resume		= ehci_hcd_au1xxx_drv_resume, -}; - -#define AU1XXX_EHCI_PMOPS &au1xxx_ehci_pmops - -#else -#define AU1XXX_EHCI_PMOPS NULL -#endif - -static struct platform_driver ehci_hcd_au1xxx_driver = { -	.probe		= ehci_hcd_au1xxx_drv_probe, -	.remove		= ehci_hcd_au1xxx_drv_remove, -	.shutdown	= usb_hcd_platform_shutdown, -	.driver = { -		.name	= "au1xxx-ehci", -		.owner	= THIS_MODULE, -		.pm	= AU1XXX_EHCI_PMOPS, -	} -}; - -MODULE_ALIAS("platform:au1xxx-ehci"); diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c deleted file mode 100644 index d91708d2e72..00000000000 --- a/drivers/usb/host/ehci-cns3xxx.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2008 Cavium Networks - * - * This file 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/platform_device.h> -#include <linux/atomic.h> -#include <mach/cns3xxx.h> -#include <mach/pm.h> - -static int cns3xxx_ehci_init(struct usb_hcd *hcd) -{ -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); -	int retval; - -	/* -	 * EHCI and OHCI share the same clock and power, -	 * resetting twice would cause the 1st controller been reset. -	 * Therefore only do power up  at the first up device, and -	 * power down at the last down device. -	 * -	 * Set USB AHB INCR length to 16 -	 */ -	if (atomic_inc_return(&usb_pwr_ref) == 1) { -		cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB); -		cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST); -		cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST); -		__raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)), -			MISC_CHIP_CONFIG_REG); -	} - -	ehci->caps = hcd->regs; - -	hcd->has_tt = 0; - -	retval = ehci_setup(hcd); -	if (retval) -		return retval; - -	ehci_port_power(ehci, 0); - -	return retval; -} - -static const struct hc_driver cns3xxx_ehci_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "CNS3XXX EHCI Host Controller", -	.hcd_priv_size		= sizeof(struct ehci_hcd), -	.irq			= ehci_irq, -	.flags			= HCD_MEMORY | HCD_USB2, -	.reset			= cns3xxx_ehci_init, -	.start			= ehci_run, -	.stop			= ehci_stop, -	.shutdown		= ehci_shutdown, -	.urb_enqueue		= ehci_urb_enqueue, -	.urb_dequeue		= ehci_urb_dequeue, -	.endpoint_disable	= ehci_endpoint_disable, -	.endpoint_reset		= ehci_endpoint_reset, -	.get_frame_number	= ehci_get_frame, -	.hub_status_data	= ehci_hub_status_data, -	.hub_control		= ehci_hub_control, -#ifdef CONFIG_PM -	.bus_suspend		= ehci_bus_suspend, -	.bus_resume		= ehci_bus_resume, -#endif -	.relinquish_port	= ehci_relinquish_port, -	.port_handed_over	= ehci_port_handed_over, - -	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete, -}; - -static int cns3xxx_ehci_probe(struct platform_device *pdev) -{ -	struct device *dev = &pdev->dev; -	struct usb_hcd *hcd; -	const struct hc_driver *driver = &cns3xxx_ehci_hc_driver; -	struct resource *res; -	int irq; -	int retval; - -	if (usb_disabled()) -		return -ENODEV; - -	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -	if (!res) { -		dev_err(dev, "Found HC with no IRQ.\n"); -		return -ENODEV; -	} -	irq = res->start; - -	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); -	if (!hcd) -		return -ENOMEM; - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(dev, "Found HC with no register addr.\n"); -		retval = -ENODEV; -		goto err1; -	} - -	hcd->rsrc_start = res->start; -	hcd->rsrc_len = resource_size(res); - -	hcd->regs = devm_request_and_ioremap(&pdev->dev, res); -	if (hcd->regs == NULL) { -		dev_dbg(dev, "error mapping memory\n"); -		retval = -EFAULT; -		goto err1; -	} - -	retval = usb_add_hcd(hcd, irq, IRQF_SHARED); -	if (retval == 0) -		return retval; - -err1: -	usb_put_hcd(hcd); - -	return retval; -} - -static int cns3xxx_ehci_remove(struct platform_device *pdev) -{ -	struct usb_hcd *hcd = platform_get_drvdata(pdev); - -	usb_remove_hcd(hcd); - -	/* -	 * EHCI and OHCI share the same clock and power, -	 * resetting twice would cause the 1st controller been reset. -	 * Therefore only do power up  at the first up device, and -	 * power down at the last down device. -	 */ -	if (atomic_dec_return(&usb_pwr_ref) == 0) -		cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST); - -	usb_put_hcd(hcd); - -	platform_set_drvdata(pdev, NULL); - -	return 0; -} - -MODULE_ALIAS("platform:cns3xxx-ehci"); - -static struct platform_driver cns3xxx_ehci_driver = { -	.probe = cns3xxx_ehci_probe, -	.remove = cns3xxx_ehci_remove, -	.driver = { -		.name = "cns3xxx-ehci", -	}, -}; diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 1599806e3d4..70b496dc18a 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -18,21 +18,6 @@  /* this file is part of ehci-hcd.c */ -#define ehci_dbg(ehci, fmt, args...) \ -	dev_dbg (ehci_to_hcd(ehci)->self.controller , fmt , ## args ) -#define ehci_err(ehci, fmt, args...) \ -	dev_err (ehci_to_hcd(ehci)->self.controller , fmt , ## args ) -#define ehci_info(ehci, fmt, args...) \ -	dev_info (ehci_to_hcd(ehci)->self.controller , fmt , ## args ) -#define ehci_warn(ehci, fmt, args...) \ -	dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args ) - -#ifdef VERBOSE_DEBUG -#	define ehci_vdbg ehci_dbg -#else -	static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {} -#endif -  #ifdef	DEBUG  /* check the values in the HCSPARAMS register @@ -352,11 +337,6 @@ static int debug_async_open(struct inode *, struct file *);  static int debug_periodic_open(struct inode *, struct file *);  static int debug_registers_open(struct inode *, struct file *);  static int debug_async_open(struct inode *, struct file *); -static ssize_t debug_lpm_read(struct file *file, char __user *user_buf, -				   size_t count, loff_t *ppos); -static ssize_t debug_lpm_write(struct file *file, const char __user *buffer, -			      size_t count, loff_t *ppos); -static int debug_lpm_close(struct inode *inode, struct file *file);  static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);  static int debug_close(struct inode *, struct file *); @@ -382,14 +362,6 @@ static const struct file_operations debug_registers_fops = {  	.release	= debug_close,  	.llseek		= default_llseek,  }; -static const struct file_operations debug_lpm_fops = { -	.owner		= THIS_MODULE, -	.open		= simple_open, -	.read		= debug_lpm_read, -	.write		= debug_lpm_write, -	.release	= debug_lpm_close, -	.llseek		= noop_llseek, -};  static struct dentry *ehci_debug_root; @@ -971,86 +943,6 @@ static int debug_registers_open(struct inode *inode, struct file *file)  	return file->private_data ? 0 : -ENOMEM;  } -static int debug_lpm_close(struct inode *inode, struct file *file) -{ -	return 0; -} - -static ssize_t debug_lpm_read(struct file *file, char __user *user_buf, -				   size_t count, loff_t *ppos) -{ -	/* TODO: show lpm stats */ -	return 0; -} - -static ssize_t debug_lpm_write(struct file *file, const char __user *user_buf, -			      size_t count, loff_t *ppos) -{ -	struct usb_hcd		*hcd; -	struct ehci_hcd		*ehci; -	char buf[50]; -	size_t len; -	u32 temp; -	unsigned long port; -	u32 __iomem	*portsc ; -	u32 params; - -	hcd = bus_to_hcd(file->private_data); -	ehci = hcd_to_ehci(hcd); - -	len = min(count, sizeof(buf) - 1); -	if (copy_from_user(buf, user_buf, len)) -		return -EFAULT; -	buf[len] = '\0'; -	if (len > 0 && buf[len - 1] == '\n') -		buf[len - 1] = '\0'; - -	if (strncmp(buf, "enable", 5) == 0) { -		if (strict_strtoul(buf + 7, 10, &port)) -			return -EINVAL; -		params = ehci_readl(ehci, &ehci->caps->hcs_params); -		if (port > HCS_N_PORTS(params)) { -			ehci_dbg(ehci, "ERR: LPM on bad port %lu\n", port); -			return -ENODEV; -		} -		portsc = &ehci->regs->port_status[port-1]; -		temp = ehci_readl(ehci, portsc); -		if (!(temp & PORT_DEV_ADDR)) { -			ehci_dbg(ehci, "LPM: no device attached\n"); -			return -ENODEV; -		} -		temp |= PORT_LPM; -		ehci_writel(ehci, temp, portsc); -		printk(KERN_INFO "force enable LPM for port %lu\n", port); -	} else if (strncmp(buf, "hird=", 5) == 0) { -		unsigned long hird; -		if (strict_strtoul(buf + 5, 16, &hird)) -			return -EINVAL; -		printk(KERN_INFO "setting hird %s %lu\n", buf + 6, hird); -		ehci->command = (ehci->command & ~CMD_HIRD) | (hird << 24); -		ehci_writel(ehci, ehci->command, &ehci->regs->command); -	} else if (strncmp(buf, "disable", 7) == 0) { -		if (strict_strtoul(buf + 8, 10, &port)) -			return -EINVAL; -		params = ehci_readl(ehci, &ehci->caps->hcs_params); -		if (port > HCS_N_PORTS(params)) { -			ehci_dbg(ehci, "ERR: LPM off bad port %lu\n", port); -			return -ENODEV; -		} -		portsc = &ehci->regs->port_status[port-1]; -		temp = ehci_readl(ehci, portsc); -		if (!(temp & PORT_DEV_ADDR)) { -			ehci_dbg(ehci, "ERR: no device attached\n"); -			return -ENODEV; -		} -		temp &= ~PORT_LPM; -		ehci_writel(ehci, temp, portsc); -		printk(KERN_INFO "disabled LPM for port %lu\n", port); -	} else -		return -EOPNOTSUPP; -	return count; -} -  static inline void create_debug_files (struct ehci_hcd *ehci)  {  	struct usb_bus *bus = &ehci_to_hcd(ehci)->self; @@ -1071,10 +963,6 @@ static inline void create_debug_files (struct ehci_hcd *ehci)  						    &debug_registers_fops))  		goto file_error; -	if (!debugfs_create_file("lpm", S_IRUGO|S_IWUSR, ehci->debug_dir, bus, -						    &debug_lpm_fops)) -		goto file_error; -  	return;  file_error: diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 0d2f35ca93f..fd9b5424b86 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -349,7 +349,6 @@ static int ehci_fsl_reinit(struct ehci_hcd *ehci)  {  	if (ehci_fsl_usb_setup(ehci))  		return -EINVAL; -	ehci_port_power(ehci, 0);  	return 0;  } diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c index 3180cb3624d..1fc89292f5d 100644 --- a/drivers/usb/host/ehci-grlib.c +++ b/drivers/usb/host/ehci-grlib.c @@ -34,22 +34,6 @@  #define GRUSBHC_HCIVERSION 0x0100 /* Known value of cap. reg. HCIVERSION */ -/* called during probe() after chip reset completes */ -static int ehci_grlib_setup(struct usb_hcd *hcd) -{ -	struct ehci_hcd	*ehci = hcd_to_ehci(hcd); -	int		retval; - -	retval = ehci_setup(hcd); -	if (retval) -		return retval; - -	ehci_port_power(ehci, 1); - -	return retval; -} - -  static const struct hc_driver ehci_grlib_hc_driver = {  	.description		= hcd_name,  	.product_desc		= "GRLIB GRUSBHC EHCI", @@ -64,7 +48,7 @@ static const struct hc_driver ehci_grlib_hc_driver = {  	/*  	 * basic lifecycle operations  	 */ -	.reset			= ehci_grlib_setup, +	.reset			= ehci_setup,  	.start			= ehci_run,  	.stop			= ehci_stop,  	.shutdown		= ehci_shutdown, @@ -98,7 +82,7 @@ static const struct hc_driver ehci_grlib_hc_driver = {  }; -static int __devinit ehci_hcd_grlib_probe(struct platform_device *op) +static int ehci_hcd_grlib_probe(struct platform_device *op)  {  	struct device_node *dn = op->dev.of_node;  	struct usb_hcd *hcd; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 6bf6c42481e..c97503bb0b0 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -39,7 +39,6 @@  #include <linux/dma-mapping.h>  #include <linux/debugfs.h>  #include <linux/slab.h> -#include <linux/uaccess.h>  #include <asm/byteorder.h>  #include <asm/io.h> @@ -108,19 +107,39 @@ static bool ignore_oc = 0;  module_param (ignore_oc, bool, S_IRUGO);  MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); -/* for link power management(LPM) feature */ -static unsigned int hird; -module_param(hird, int, S_IRUGO); -MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us"); -  #define	INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)  /*-------------------------------------------------------------------------*/  #include "ehci.h" -#include "ehci-dbg.c"  #include "pci-quirks.h" +/* + * The MosChip MCS9990 controller updates its microframe counter + * a little before the frame counter, and occasionally we will read + * the invalid intermediate value.  Avoid problems by checking the + * microframe number (the low-order 3 bits); if they are 0 then + * re-read the register to get the correct value. + */ +static unsigned ehci_moschip_read_frame_index(struct ehci_hcd *ehci) +{ +	unsigned uf; + +	uf = ehci_readl(ehci, &ehci->regs->frame_index); +	if (unlikely((uf & 7) == 0)) +		uf = ehci_readl(ehci, &ehci->regs->frame_index); +	return uf; +} + +static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci) +{ +	if (ehci->frame_index_bug) +		return ehci_moschip_read_frame_index(ehci); +	return ehci_readl(ehci, &ehci->regs->frame_index); +} + +#include "ehci-dbg.c" +  /*-------------------------------------------------------------------------*/  /* @@ -293,7 +312,6 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);  #include "ehci-timer.c"  #include "ehci-hub.c" -#include "ehci-lpm.c"  #include "ehci-mem.c"  #include "ehci-q.c"  #include "ehci-sched.c" @@ -353,24 +371,6 @@ static void ehci_shutdown(struct usb_hcd *hcd)  	hrtimer_cancel(&ehci->hrtimer);  } -static void ehci_port_power (struct ehci_hcd *ehci, int is_on) -{ -	unsigned port; - -	if (!HCS_PPC (ehci->hcs_params)) -		return; - -	ehci_dbg (ehci, "...power%s ports...\n", is_on ? "up" : "down"); -	for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) -		(void) ehci_hub_control(ehci_to_hcd(ehci), -				is_on ? SetPortFeature : ClearPortFeature, -				USB_PORT_FEAT_POWER, -				port--, NULL, 0); -	/* Flush those writes */ -	ehci_readl(ehci, &ehci->regs->command); -	msleep(20); -} -  /*-------------------------------------------------------------------------*/  /* @@ -503,7 +503,7 @@ static int ehci_init(struct usb_hcd *hcd)  	/* controllers may cache some of the periodic schedule ... */  	if (HCC_ISOC_CACHE(hcc_params))		// full frame cache -		ehci->i_thresh = 2 + 8; +		ehci->i_thresh = 0;  	else					// N microframes cached  		ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); @@ -555,17 +555,6 @@ static int ehci_init(struct usb_hcd *hcd)  		temp &= ~(3 << 2);  		temp |= (EHCI_TUNE_FLS << 2);  	} -	if (HCC_LPM(hcc_params)) { -		/* support link power management EHCI 1.1 addendum */ -		ehci_dbg(ehci, "support lpm\n"); -		ehci->has_lpm = 1; -		if (hird > 0xf) { -			ehci_dbg(ehci, "hird %d invalid, use default 0", -			hird); -			hird = 0; -		} -		temp |= hird << 24; -	}  	ehci->command = temp;  	/* Accept arbitrarily long scatter-gather lists */ @@ -660,7 +649,7 @@ static int ehci_run (struct usb_hcd *hcd)  	return 0;  } -static int ehci_setup(struct usb_hcd *hcd) +int ehci_setup(struct usb_hcd *hcd)  {  	struct ehci_hcd *ehci = hcd_to_ehci(hcd);  	int retval; @@ -691,6 +680,7 @@ static int ehci_setup(struct usb_hcd *hcd)  	return 0;  } +EXPORT_SYMBOL_GPL(ehci_setup);  /*-------------------------------------------------------------------------*/ @@ -1096,7 +1086,7 @@ static int ehci_get_frame (struct usb_hcd *hcd)  /* These routines handle the generic parts of controller suspend/resume */ -static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup) +int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)  {  	struct ehci_hcd		*ehci = hcd_to_ehci(hcd); @@ -1119,9 +1109,10 @@ static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)  	return 0;  } +EXPORT_SYMBOL_GPL(ehci_suspend);  /* Returns 0 if power was preserved, 1 if power was lost */ -static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated) +int ehci_resume(struct usb_hcd *hcd, bool hibernated)  {  	struct ehci_hcd		*ehci = hcd_to_ehci(hcd); @@ -1177,33 +1168,83 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)  	ehci->rh_state = EHCI_RH_SUSPENDED;  	spin_unlock_irq(&ehci->lock); -	/* here we "know" root ports should always stay powered */ -	ehci_port_power(ehci, 1); -  	return 1;  } +EXPORT_SYMBOL_GPL(ehci_resume);  #endif  /*-------------------------------------------------------------------------*/  /* - * The EHCI in ChipIdea HDRC cannot be a separate module or device, - * because its registers (and irq) are shared between host/gadget/otg - * functions  and in order to facilitate role switching we cannot - * give the ehci driver exclusive access to those. + * Generic structure: This gets copied for platform drivers so that + * individual entries can be overridden as needed.   */ -#ifndef CHIPIDEA_EHCI + +static const struct hc_driver ehci_hc_driver = { +	.description =		hcd_name, +	.product_desc =		"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 =		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, +	.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, +	.bus_suspend =		ehci_bus_suspend, +	.bus_resume =		ehci_bus_resume, +	.relinquish_port =	ehci_relinquish_port, +	.port_handed_over =	ehci_port_handed_over, +}; + +void ehci_init_driver(struct hc_driver *drv, +		const struct ehci_driver_overrides *over) +{ +	/* Copy the generic table to drv and then apply the overrides */ +	*drv = ehci_hc_driver; + +	if (over) { +		drv->hcd_priv_size += over->extra_priv_size; +		if (over->reset) +			drv->reset = over->reset; +	} +} +EXPORT_SYMBOL_GPL(ehci_init_driver); + +/*-------------------------------------------------------------------------*/  MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_AUTHOR (DRIVER_AUTHOR);  MODULE_LICENSE ("GPL"); -#ifdef CONFIG_PCI -#include "ehci-pci.c" -#define	PCI_DRIVER		ehci_pci_driver -#endif -  #ifdef CONFIG_USB_EHCI_FSL  #include "ehci-fsl.c"  #define	PLATFORM_DRIVER		ehci_fsl_driver @@ -1219,11 +1260,6 @@ MODULE_LICENSE ("GPL");  #define PLATFORM_DRIVER		ehci_hcd_sh_driver  #endif -#ifdef CONFIG_MIPS_ALCHEMY -#include "ehci-au1xxx.c" -#define	PLATFORM_DRIVER		ehci_hcd_au1xxx_driver -#endif -  #ifdef CONFIG_USB_EHCI_HCD_OMAP  #include "ehci-omap.c"  #define        PLATFORM_DRIVER         ehci_hcd_omap_driver @@ -1249,11 +1285,6 @@ MODULE_LICENSE ("GPL");  #define	PLATFORM_DRIVER		ehci_orion_driver  #endif -#ifdef CONFIG_ARCH_IXP4XX -#include "ehci-ixp4xx.c" -#define	PLATFORM_DRIVER		ixp4xx_ehci_driver -#endif -  #ifdef CONFIG_USB_W90X900_EHCI  #include "ehci-w90x900.c"  #define	PLATFORM_DRIVER		ehci_hcd_w90x900_driver @@ -1269,11 +1300,6 @@ MODULE_LICENSE ("GPL");  #define PLATFORM_DRIVER		ehci_octeon_driver  #endif -#ifdef CONFIG_USB_CNS3XXX_EHCI -#include "ehci-cns3xxx.c" -#define PLATFORM_DRIVER		cns3xxx_ehci_driver -#endif -  #ifdef CONFIG_ARCH_VT8500  #include "ehci-vt8500.c"  #define	PLATFORM_DRIVER		vt8500_ehci_driver @@ -1314,34 +1340,23 @@ MODULE_LICENSE ("GPL");  #define PLATFORM_DRIVER		ehci_grlib_driver  #endif -#ifdef CONFIG_CPU_XLR -#include "ehci-xls.c" -#define PLATFORM_DRIVER		ehci_xls_driver -#endif -  #ifdef CONFIG_USB_EHCI_MV  #include "ehci-mv.c"  #define        PLATFORM_DRIVER         ehci_mv_driver  #endif -#ifdef CONFIG_MACH_LOONGSON1 -#include "ehci-ls1x.c" -#define PLATFORM_DRIVER		ehci_ls1x_driver -#endif -  #ifdef CONFIG_MIPS_SEAD3  #include "ehci-sead3.c"  #define	PLATFORM_DRIVER		ehci_hcd_sead3_driver  #endif -#ifdef CONFIG_USB_EHCI_HCD_PLATFORM -#include "ehci-platform.c" -#define PLATFORM_DRIVER		ehci_platform_driver -#endif - -#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ -    !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ -    !defined(XILINX_OF_PLATFORM_DRIVER) +#if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \ +	!IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ +	!defined(CONFIG_USB_CHIPIDEA_HOST) && \ +	!defined(PLATFORM_DRIVER) && \ +	!defined(PS3_SYSTEM_BUS_DRIVER) && \ +	!defined(OF_PLATFORM_DRIVER) && \ +	!defined(XILINX_OF_PLATFORM_DRIVER)  #error "missing bus glue for ehci-hcd"  #endif @@ -1378,12 +1393,6 @@ static int __init ehci_hcd_init(void)  		goto clean0;  #endif -#ifdef PCI_DRIVER -	retval = pci_register_driver(&PCI_DRIVER); -	if (retval < 0) -		goto clean1; -#endif -  #ifdef PS3_SYSTEM_BUS_DRIVER  	retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);  	if (retval < 0) @@ -1415,10 +1424,6 @@ clean3:  	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);  clean2:  #endif -#ifdef PCI_DRIVER -	pci_unregister_driver(&PCI_DRIVER); -clean1: -#endif  #ifdef PLATFORM_DRIVER  	platform_driver_unregister(&PLATFORM_DRIVER);  clean0: @@ -1444,9 +1449,6 @@ static void __exit ehci_hcd_cleanup(void)  #ifdef PLATFORM_DRIVER  	platform_driver_unregister(&PLATFORM_DRIVER);  #endif -#ifdef PCI_DRIVER -	pci_unregister_driver(&PCI_DRIVER); -#endif  #ifdef PS3_SYSTEM_BUS_DRIVER  	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);  #endif @@ -1456,5 +1458,3 @@ static void __exit ehci_hcd_cleanup(void)  	clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);  }  module_exit(ehci_hcd_cleanup); - -#endif /* CHIPIDEA_EHCI */ diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 914ce9370e7..4ccb97c0678 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -56,6 +56,19 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)  	if (!ehci->owned_ports)  		return; +	/* Make sure the ports are powered */ +	port = HCS_N_PORTS(ehci->hcs_params); +	while (port--) { +		if (test_bit(port, &ehci->owned_ports)) { +			reg = &ehci->regs->port_status[port]; +			status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; +			if (!(status & PORT_POWER)) { +				status |= PORT_POWER; +				ehci_writel(ehci, status, reg); +			} +		} +	} +  	/* Give the connections some time to appear */  	msleep(20); @@ -384,11 +397,24 @@ static int ehci_bus_resume (struct usb_hcd *hcd)  	ehci_writel(ehci, ehci->command, &ehci->regs->command);  	ehci->rh_state = EHCI_RH_RUNNING; -	/* Some controller/firmware combinations need a delay during which -	 * they set up the port statuses.  See Bugzilla #8190. */ -	spin_unlock_irq(&ehci->lock); -	msleep(8); -	spin_lock_irq(&ehci->lock); +	/* +	 * According to Bugzilla #8190, the port status for some controllers +	 * will be wrong without a delay. At their wrong status, the port +	 * is enabled, but not suspended neither resumed. +	 */ +	i = HCS_N_PORTS(ehci->hcs_params); +	while (i--) { +		temp = ehci_readl(ehci, &ehci->regs->port_status[i]); +		if ((temp & PORT_PE) && +				!(temp & (PORT_SUSPEND | PORT_RESUME))) { +			ehci_dbg(ehci, "Port status(0x%x) is wrong\n", temp); +			spin_unlock_irq(&ehci->lock); +			msleep(8); +			spin_lock_irq(&ehci->lock); +			break; +		} +	} +  	if (ehci->shutdown)  		goto shutdown; @@ -764,11 +790,6 @@ static int ehci_hub_control (  						status_reg);  			break;  		case USB_PORT_FEAT_C_CONNECTION: -			if (ehci->has_lpm) { -				/* clear PORTSC bits on disconnect */ -				temp &= ~PORT_LPM; -				temp &= ~PORT_DEV_ADDR; -			}  			ehci_writel(ehci, temp | PORT_CSC, status_reg);  			break;  		case USB_PORT_FEAT_C_OVER_CURRENT: @@ -1088,8 +1109,7 @@ error_exit:  	return retval;  } -static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd, -		int portnum) +static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)  {  	struct ehci_hcd		*ehci = hcd_to_ehci(hcd); @@ -1098,8 +1118,7 @@ static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,  	set_owner(ehci, --portnum, PORT_OWNER);  } -static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd, -		int portnum) +static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum)  {  	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);  	u32 __iomem		*reg; diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c deleted file mode 100644 index f224c0a48be..00000000000 --- a/drivers/usb/host/ehci-ixp4xx.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * IXP4XX EHCI Host Controller Driver - * - * Author: Vladimir Barinov <vbarinov@embeddedalley.com> - * - * Based on "ehci-fsl.c" by Randy Vinson <rvinson@mvista.com> - * - * 2007 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include <linux/platform_device.h> - -static int ixp4xx_ehci_init(struct usb_hcd *hcd) -{ -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); -	int retval = 0; - -	ehci->big_endian_desc = 1; -	ehci->big_endian_mmio = 1; - -	ehci->caps = hcd->regs + 0x100; - -	hcd->has_tt = 1; - -	retval = ehci_setup(hcd); -	if (retval) -		return retval; - -	ehci_port_power(ehci, 0); - -	return retval; -} - -static const struct hc_driver ixp4xx_ehci_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "IXP4XX EHCI Host Controller", -	.hcd_priv_size		= sizeof(struct ehci_hcd), -	.irq			= ehci_irq, -	.flags			= HCD_MEMORY | HCD_USB2, -	.reset			= ixp4xx_ehci_init, -	.start			= ehci_run, -	.stop			= ehci_stop, -	.shutdown		= ehci_shutdown, -	.urb_enqueue		= ehci_urb_enqueue, -	.urb_dequeue		= ehci_urb_dequeue, -	.endpoint_disable	= ehci_endpoint_disable, -	.endpoint_reset		= ehci_endpoint_reset, -	.get_frame_number	= ehci_get_frame, -	.hub_status_data	= ehci_hub_status_data, -	.hub_control		= ehci_hub_control, -#if defined(CONFIG_PM) -	.bus_suspend		= ehci_bus_suspend, -	.bus_resume		= ehci_bus_resume, -#endif -	.relinquish_port	= ehci_relinquish_port, -	.port_handed_over	= ehci_port_handed_over, - -	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete, -}; - -static int ixp4xx_ehci_probe(struct platform_device *pdev) -{ -	struct usb_hcd *hcd; -	const struct hc_driver *driver = &ixp4xx_ehci_hc_driver; -	struct resource *res; -	int irq; -	int retval; - -	if (usb_disabled()) -		return -ENODEV; - -	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -	if (!res) { -		dev_err(&pdev->dev, -			"Found HC with no IRQ. Check %s setup!\n", -			dev_name(&pdev->dev)); -		return -ENODEV; -	} -	irq = res->start; - -	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); -	if (!hcd) { -		retval = -ENOMEM; -		goto fail_create_hcd; -	} - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(&pdev->dev, -			"Found HC with no register addr. Check %s setup!\n", -			dev_name(&pdev->dev)); -		retval = -ENODEV; -		goto fail_request_resource; -	} -	hcd->rsrc_start = res->start; -	hcd->rsrc_len = resource_size(res); - -	hcd->regs = devm_request_and_ioremap(&pdev->dev, res); -	if (hcd->regs == NULL) { -		dev_dbg(&pdev->dev, "error mapping memory\n"); -		retval = -EFAULT; -		goto fail_request_resource; -	} - -	retval = usb_add_hcd(hcd, irq, IRQF_SHARED); -	if (retval) -		goto fail_request_resource; - -	return retval; - -fail_request_resource: -	usb_put_hcd(hcd); -fail_create_hcd: -	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval); -	return retval; -} - -static int ixp4xx_ehci_remove(struct platform_device *pdev) -{ -	struct usb_hcd *hcd = platform_get_drvdata(pdev); - -	usb_remove_hcd(hcd); -	usb_put_hcd(hcd); - -	return 0; -} - -MODULE_ALIAS("platform:ixp4xx-ehci"); - -static struct platform_driver ixp4xx_ehci_driver = { -	.probe = ixp4xx_ehci_probe, -	.remove = ixp4xx_ehci_remove, -	.driver = { -		.name = "ixp4xx-ehci", -	}, -}; diff --git a/drivers/usb/host/ehci-lpm.c b/drivers/usb/host/ehci-lpm.c deleted file mode 100644 index 2111627a19d..00000000000 --- a/drivers/usb/host/ehci-lpm.c +++ /dev/null @@ -1,84 +0,0 @@ -/* ehci-lpm.c EHCI HCD LPM support code - * Copyright (c) 2008 - 2010,  Intel Corporation. - * Author: Jacob Pan <jacob.jun.pan@intel.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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. -*/ - -/* this file is part of ehci-hcd.c */ -static int __maybe_unused ehci_lpm_set_da(struct ehci_hcd *ehci, -	int dev_addr, int port_num) -{ -	u32 __iomem portsc; - -	ehci_dbg(ehci, "set dev address %d for port %d\n", dev_addr, port_num); -	if (port_num > HCS_N_PORTS(ehci->hcs_params)) { -		ehci_dbg(ehci, "invalid port number %d\n", port_num); -		return -ENODEV; -	} -	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_num-1]); -	portsc &= ~PORT_DEV_ADDR; -	portsc |= dev_addr<<25; -	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_num-1]); -	return 0; -} - -/* - * this function is used to check if the device support LPM - * if yes, mark the PORTSC register with PORT_LPM bit - */ -static int __maybe_unused ehci_lpm_check(struct ehci_hcd *ehci, int port) -{ -	u32 __iomem	*portsc ; -	u32 val32; -	int retval; - -	portsc = &ehci->regs->port_status[port-1]; -	val32 = ehci_readl(ehci, portsc); -	if (!(val32 & PORT_DEV_ADDR)) { -		ehci_dbg(ehci, "LPM: no device attached\n"); -		return -ENODEV; -	} -	val32 |= PORT_LPM; -	ehci_writel(ehci, val32, portsc); -	msleep(5); -	val32 |= PORT_SUSPEND; -	ehci_dbg(ehci, "Sending LPM 0x%08x to port %d\n", val32, port); -	ehci_writel(ehci, val32, portsc); -	/* wait for ACK */ -	msleep(10); -	retval = handshake(ehci, &ehci->regs->port_status[port-1], PORT_SSTS, -			PORTSC_SUSPEND_STS_ACK, 125); -	dbg_port(ehci, "LPM", port, val32); -	if (retval != -ETIMEDOUT) { -		ehci_dbg(ehci, "LPM: device ACK for LPM\n"); -		val32 |= PORT_LPM; -		/* -		 * now device should be in L1 sleep, let's wake up the device -		 * so that we can complete enumeration. -		 */ -		ehci_writel(ehci, val32, portsc); -		msleep(10); -		val32 |= PORT_RESUME; -		ehci_writel(ehci, val32, portsc); -	} else { -		ehci_dbg(ehci, "LPM: device does not ACK, disable LPM %d\n", -			retval); -		val32 &= ~PORT_LPM; -		retval = -ETIMEDOUT; -		ehci_writel(ehci, val32, portsc); -	} - -	return retval; -} diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c deleted file mode 100644 index aa0f328922d..00000000000 --- a/drivers/usb/host/ehci-ls1x.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - *  Bus Glue for Loongson LS1X built-in EHCI controller. - * - *  Copyright (c) 2012 Zhang, Keguang <keguang.zhang@gmail.com> - * - *  This program is free software; you can redistribute it and/or modify it - *  under the terms of the GNU General Public License version 2 as published - *  by the Free Software Foundation. - */ - - -#include <linux/platform_device.h> - -static int ehci_ls1x_reset(struct usb_hcd *hcd) -{ -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); -	int ret; - -	ehci->caps = hcd->regs; - -	ret = ehci_setup(hcd); -	if (ret) -		return ret; - -	ehci_port_power(ehci, 0); - -	return 0; -} - -static const struct hc_driver ehci_ls1x_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "LOONGSON1 EHCI", -	.hcd_priv_size		= sizeof(struct ehci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq			= ehci_irq, -	.flags			= HCD_MEMORY | HCD_USB2, - -	/* -	 * basic lifecycle operations -	 */ -	.reset			= ehci_ls1x_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, - -	/* -	 * 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, - -	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete, -}; - -static int ehci_hcd_ls1x_probe(struct platform_device *pdev) -{ -	struct usb_hcd *hcd; -	struct resource *res; -	int irq; -	int ret; - -	pr_debug("initializing loongson1 ehci USB Controller\n"); - -	if (usb_disabled()) -		return -ENODEV; - -	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -	if (!res) { -		dev_err(&pdev->dev, -			"Found HC with no IRQ. Check %s setup!\n", -			dev_name(&pdev->dev)); -		return -ENODEV; -	} -	irq = res->start; - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(&pdev->dev, -			"Found HC with no register addr. Check %s setup!\n", -			dev_name(&pdev->dev)); -		return -ENODEV; -	} - -	hcd = usb_create_hcd(&ehci_ls1x_hc_driver, &pdev->dev, -				dev_name(&pdev->dev)); -	if (!hcd) -		return -ENOMEM; -	hcd->rsrc_start	= res->start; -	hcd->rsrc_len	= resource_size(res); - -	hcd->regs = devm_request_and_ioremap(&pdev->dev, res); -	if (hcd->regs == NULL) { -		dev_dbg(&pdev->dev, "error mapping memory\n"); -		ret = -EFAULT; -		goto err_put_hcd; -	} - -	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); -	if (ret) -		goto err_put_hcd; - -	return ret; - -err_put_hcd: -	usb_put_hcd(hcd); -	return ret; -} - -static int ehci_hcd_ls1x_remove(struct platform_device *pdev) -{ -	struct usb_hcd *hcd = platform_get_drvdata(pdev); - -	usb_remove_hcd(hcd); -	usb_put_hcd(hcd); - -	return 0; -} - -static struct platform_driver ehci_ls1x_driver = { -	.probe = ehci_hcd_ls1x_probe, -	.remove = ehci_hcd_ls1x_remove, -	.shutdown = usb_hcd_platform_shutdown, -	.driver = { -		.name = "ls1x-ehci", -		.owner	= THIS_MODULE, -	}, -}; - -MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ls1x-ehci"); diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 4af4dc5b618..88a49c87e74 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -53,7 +53,6 @@ static int ehci_msm_reset(struct usb_hcd *hcd)  	/* Disable streaming mode and select host mode */  	writel(0x13, USB_USBMODE); -	ehci_port_power(ehci, 1);  	return 0;  } @@ -174,7 +173,7 @@ put_hcd:  	return ret;  } -static int __devexit ehci_msm_remove(struct platform_device *pdev) +static int ehci_msm_remove(struct platform_device *pdev)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev); @@ -221,7 +220,7 @@ static const struct dev_pm_ops ehci_msm_dev_pm_ops = {  static struct platform_driver ehci_msm_driver = {  	.probe	= ehci_msm_probe, -	.remove	= __devexit_p(ehci_msm_remove), +	.remove	= ehci_msm_remove,  	.driver = {  		   .name = "msm_hsusb_host",  		   .pm = &ehci_msm_dev_pm_ops, diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index 8e58a5fa199..ec7f5d2c90d 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -38,17 +38,9 @@ struct ehci_mxc_priv {  /* called during probe() after chip reset completes */  static int ehci_mxc_setup(struct usb_hcd *hcd)  { -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); -	int retval; -  	hcd->has_tt = 1; -	retval = ehci_setup(hcd); -	if (retval) -		return retval; - -	ehci_port_power(ehci, 0); -	return 0; +	return ehci_setup(hcd);  }  static const struct hc_driver ehci_mxc_hc_driver = { diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c index ba26957abf4..a89750fff4f 100644 --- a/drivers/usb/host/ehci-octeon.c +++ b/drivers/usb/host/ehci-octeon.c @@ -159,9 +159,6 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, hcd); -	/* root ports should always stay powered */ -	ehci_port_power(ehci, 1); -  	return 0;  err3:  	ehci_octeon_stop(); diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 0d5ac36fdf4..ac17a7c3a0c 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -147,9 +147,6 @@ static int omap_ehci_init(struct usb_hcd *hcd)  			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);  	} -	/* root ports should always stay powered */ -	ehci_port_power(ehci, 1); -  	return rc;  } diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index e7e8275028d..a7d1f5b4c4e 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -104,20 +104,6 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd)  	wrl(USB_MODE, 0x13);  } -static int ehci_orion_setup(struct usb_hcd *hcd) -{ -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); -	int retval; - -	retval = ehci_setup(hcd); -	if (retval) -		return retval; - -	ehci_port_power(ehci, 0); - -	return retval; -} -  static const struct hc_driver ehci_orion_hc_driver = {  	.description = hcd_name,  	.product_desc = "Marvell Orion EHCI", @@ -132,7 +118,7 @@ static const struct hc_driver ehci_orion_hc_driver = {  	/*  	 * basic lifecycle operations  	 */ -	.reset = ehci_orion_setup, +	.reset = ehci_setup,  	.start = ehci_run,  	.stop = ehci_stop,  	.shutdown = ehci_shutdown, @@ -163,7 +149,7 @@ static const struct hc_driver ehci_orion_hc_driver = {  	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,  }; -static void __devinit +static void  ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,  			     const struct mbus_dram_target_info *dram)  { @@ -186,7 +172,7 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,  static u64 ehci_orion_dma_mask = DMA_BIT_MASK(32); -static int __devinit ehci_orion_drv_probe(struct platform_device *pdev) +static int ehci_orion_drv_probe(struct platform_device *pdev)  {  	struct orion_ehci_data *pd = pdev->dev.platform_data;  	const struct mbus_dram_target_info *dram; diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 2cb7d370c4e..dabb2049482 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -18,9 +18,18 @@   * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */ -#ifndef CONFIG_PCI -#error "This file is PCI bus glue.  CONFIG_PCI must be defined." -#endif +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> + +#include "ehci.h" +#include "pci-quirks.h" + +#define DRIVER_DESC "EHCI PCI platform driver" + +static const char hcd_name[] = "ehci-pci";  /* defined here to avoid adding to pci_ids.h for single instance use */  #define PCI_DEVICE_ID_INTEL_CE4100_USB	0x2e70 @@ -103,7 +112,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)  		}  		break;  	case PCI_VENDOR_ID_INTEL: -		ehci->fs_i_thresh = 1;  		if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB)  			hcd->has_tt = 1;  		break; @@ -203,11 +211,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)  		break;  	case PCI_VENDOR_ID_INTEL:  		ehci->need_io_watchdog = 0; -		if (pdev->device == 0x0806 || pdev->device == 0x0811 -				|| pdev->device == 0x0829) { -			ehci_info(ehci, "disable lpm for langwell/penwell\n"); -			ehci->has_lpm = 0; -		}  		break;  	case PCI_VENDOR_ID_NVIDIA:  		switch (pdev->device) { @@ -217,8 +220,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)  		 * devices with PPCD enabled.  		 */  		case 0x0d9d: -			ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89"); -			ehci->has_lpm = 0; +			ehci_info(ehci, "disable ppcd for nvidia mcp89\n");  			ehci->has_ppcd = 0;  			ehci->command &= ~CMD_PPCEE;  			break; @@ -304,7 +306,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)  		ehci_warn(ehci, "selective suspend/wakeup unavailable\n");  #endif -	ehci_port_power(ehci, 1);  	retval = ehci_pci_reinit(ehci, pdev);  done:  	return retval; @@ -323,18 +324,14 @@ done:   * Also they depend on separate root hub suspend/resume.   */ -static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) -{ -	return ehci_suspend(hcd, do_wakeup); -} -  static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)  {  	return pdev->class == PCI_CLASS_SERIAL_USB_EHCI &&  		pdev->vendor == PCI_VENDOR_ID_INTEL &&  		(pdev->device == 0x1E26 ||  		 pdev->device == 0x8C2D || -		 pdev->device == 0x8C26); +		 pdev->device == 0x8C26 || +		 pdev->device == 0x9C26);  }  static void ehci_enable_xhci_companion(void) @@ -378,76 +375,17 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)  		(void) ehci_pci_reinit(ehci, pdev);  	return 0;  } -#endif -static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev) -{ -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); -	int rc = 0; - -	if (!udev->parent) /* udev is root hub itself, impossible */ -		rc = -1; -	/* we only support lpm device connected to root hub yet */ -	if (ehci->has_lpm && !udev->parent->parent) { -		rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum); -		if (!rc) -			rc = ehci_lpm_check(ehci, udev->portnum); -	} -	return rc; -} +#else -static const struct hc_driver ehci_pci_hc_driver = { -	.description =		hcd_name, -	.product_desc =		"EHCI Host Controller", -	.hcd_priv_size =	sizeof(struct ehci_hcd), +#define ehci_suspend		NULL +#define ehci_pci_resume		NULL +#endif	/* CONFIG_PM */ -	/* -	 * generic hardware linkage -	 */ -	.irq =			ehci_irq, -	.flags =		HCD_MEMORY | HCD_USB2, +static struct hc_driver __read_mostly ehci_pci_hc_driver; -	/* -	 * basic lifecycle operations -	 */ +static const struct ehci_driver_overrides pci_overrides __initdata = {  	.reset =		ehci_pci_setup, -	.start =		ehci_run, -#ifdef	CONFIG_PM -	.pci_suspend =		ehci_pci_suspend, -	.pci_resume =		ehci_pci_resume, -#endif -	.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, - -	/* -	 * call back when device connected and addressed -	 */ -	.update_device =	ehci_update_device, - -	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,  };  /*-------------------------------------------------------------------------*/ @@ -480,3 +418,31 @@ static struct pci_driver ehci_pci_driver = {  	},  #endif  }; + +static int __init ehci_pci_init(void) +{ +	if (usb_disabled()) +		return -ENODEV; + +	pr_info("%s: " DRIVER_DESC "\n", hcd_name); + +	ehci_init_driver(&ehci_pci_hc_driver, &pci_overrides); + +	/* Entries for the PCI suspend/resume callbacks are special */ +	ehci_pci_hc_driver.pci_suspend = ehci_suspend; +	ehci_pci_hc_driver.pci_resume = ehci_pci_resume; + +	return pci_register_driver(&ehci_pci_driver); +} +module_init(ehci_pci_init); + +static void __exit ehci_pci_cleanup(void) +{ +	pci_unregister_driver(&ehci_pci_driver); +} +module_exit(ehci_pci_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("David Brownell"); +MODULE_AUTHOR("Alan Stern"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index 764e0100b6f..58fa0c90c7c 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -18,9 +18,21 @@   *   * Licensed under the GNU/GPL. See COPYING for details.   */ +#include <linux/kernel.h> +#include <linux/hrtimer.h> +#include <linux/io.h> +#include <linux/module.h>  #include <linux/platform_device.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h>  #include <linux/usb/ehci_pdriver.h> +#include "ehci.h" + +#define DRIVER_DESC "EHCI generic platform driver" + +static const char hcd_name[] = "ehci-platform"; +  static int ehci_platform_reset(struct usb_hcd *hcd)  {  	struct platform_device *pdev = to_platform_device(hcd->self.controller); @@ -38,47 +50,18 @@ static int ehci_platform_reset(struct usb_hcd *hcd)  	if (retval)  		return retval; -	if (pdata->port_power_on) -		ehci_port_power(ehci, 1); -	if (pdata->port_power_off) -		ehci_port_power(ehci, 0); - +	if (pdata->no_io_watchdog) +		ehci->need_io_watchdog = 0;  	return 0;  } -static const struct hc_driver ehci_platform_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "Generic Platform EHCI Controller", -	.hcd_priv_size		= sizeof(struct ehci_hcd), - -	.irq			= ehci_irq, -	.flags			= HCD_MEMORY | HCD_USB2, - -	.reset			= ehci_platform_reset, -	.start			= ehci_run, -	.stop			= ehci_stop, -	.shutdown		= ehci_shutdown, - -	.urb_enqueue		= ehci_urb_enqueue, -	.urb_dequeue		= ehci_urb_dequeue, -	.endpoint_disable	= ehci_endpoint_disable, -	.endpoint_reset		= ehci_endpoint_reset, +static struct hc_driver __read_mostly ehci_platform_hc_driver; -	.get_frame_number	= ehci_get_frame, - -	.hub_status_data	= ehci_hub_status_data, -	.hub_control		= ehci_hub_control, -#if defined(CONFIG_PM) -	.bus_suspend		= ehci_bus_suspend, -	.bus_resume		= ehci_bus_resume, -#endif -	.relinquish_port	= ehci_relinquish_port, -	.port_handed_over	= ehci_port_handed_over, - -	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, +static const struct ehci_driver_overrides platform_overrides __initdata = { +	.reset =	ehci_platform_reset,  }; -static int __devinit ehci_platform_probe(struct platform_device *dev) +static int ehci_platform_probe(struct platform_device *dev)  {  	struct usb_hcd *hcd;  	struct resource *res_mem; @@ -96,12 +79,12 @@ static int __devinit ehci_platform_probe(struct platform_device *dev)  	irq = platform_get_irq(dev, 0);  	if (irq < 0) { -		pr_err("no irq provided"); +		dev_err(&dev->dev, "no irq provided");  		return irq;  	}  	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);  	if (!res_mem) { -		pr_err("no memory recourse provided"); +		dev_err(&dev->dev, "no memory resource provided");  		return -ENXIO;  	} @@ -121,29 +104,19 @@ static int __devinit ehci_platform_probe(struct platform_device *dev)  	hcd->rsrc_start = res_mem->start;  	hcd->rsrc_len = resource_size(res_mem); -	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { -		pr_err("controller already in use"); -		err = -EBUSY; -		goto err_put_hcd; -	} - -	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); +	hcd->regs = devm_request_and_ioremap(&dev->dev, res_mem);  	if (!hcd->regs) {  		err = -ENOMEM; -		goto err_release_region; +		goto err_put_hcd;  	}  	err = usb_add_hcd(hcd, irq, IRQF_SHARED);  	if (err) -		goto err_iounmap; +		goto err_put_hcd;  	platform_set_drvdata(dev, hcd);  	return err; -err_iounmap: -	iounmap(hcd->regs); -err_release_region: -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);  err_put_hcd:  	usb_put_hcd(hcd);  err_power: @@ -153,14 +126,12 @@ err_power:  	return err;  } -static int __devexit ehci_platform_remove(struct platform_device *dev) +static int ehci_platform_remove(struct platform_device *dev)  {  	struct usb_hcd *hcd = platform_get_drvdata(dev);  	struct usb_ehci_pdata *pdata = dev->dev.platform_data;  	usb_remove_hcd(hcd); -	iounmap(hcd->regs); -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);  	usb_put_hcd(hcd);  	platform_set_drvdata(dev, NULL); @@ -225,7 +196,7 @@ static const struct dev_pm_ops ehci_platform_pm_ops = {  static struct platform_driver ehci_platform_driver = {  	.id_table	= ehci_platform_table,  	.probe		= ehci_platform_probe, -	.remove		= __devexit_p(ehci_platform_remove), +	.remove		= ehci_platform_remove,  	.shutdown	= usb_hcd_platform_shutdown,  	.driver		= {  		.owner	= THIS_MODULE, @@ -233,3 +204,26 @@ static struct platform_driver ehci_platform_driver = {  		.pm	= &ehci_platform_pm_ops,  	}  }; + +static int __init ehci_platform_init(void) +{ +	if (usb_disabled()) +		return -ENODEV; + +	pr_info("%s: " DRIVER_DESC "\n", hcd_name); + +	ehci_init_driver(&ehci_platform_hc_driver, &platform_overrides); +	return platform_driver_register(&ehci_platform_driver); +} +module_init(ehci_platform_init); + +static void __exit ehci_platform_cleanup(void) +{ +	platform_driver_unregister(&ehci_platform_driver); +} +module_exit(ehci_platform_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Hauke Mehrtens"); +MODULE_AUTHOR("Alan Stern"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c index 087aee2a904..363890ee41d 100644 --- a/drivers/usb/host/ehci-pmcmsp.c +++ b/drivers/usb/host/ehci-pmcmsp.c @@ -90,7 +90,6 @@ static int ehci_msp_setup(struct usb_hcd *hcd)  		return retval;  	usb_hcd_tdi_set_mode(ehci); -	ehci_port_power(ehci, 0);  	return retval;  } diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index fa937d05a02..45aceefd0c2 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -71,7 +71,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {   * Fix: Enable Break Memory Transfer (BMT) in INSNREG3   */  #define PPC440EPX_EHCI0_INSREG_BMT	(0x1 << 0) -static int __devinit +static int  ppc44x_enable_bmt(struct device_node *dn)  {  	__iomem u32 *insreg_virt; @@ -87,7 +87,7 @@ ppc44x_enable_bmt(struct device_node *dn)  } -static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op) +static int ehci_hcd_ppc_of_probe(struct platform_device *op)  {  	struct device_node *dn = op->dev.of_node;  	struct usb_hcd *hcd; diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 45a356e9f13..df5925a4f0d 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c @@ -93,7 +93,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {  	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,  }; -static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev) +static int ps3_ehci_probe(struct ps3_system_bus_device *dev)  {  	int result;  	struct usb_hcd *hcd; diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 4b66374bdc8..3d989028c83 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -264,15 +264,9 @@ ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status)  __releases(ehci->lock)  __acquires(ehci->lock)  { -	if (likely (urb->hcpriv != NULL)) { -		struct ehci_qh	*qh = (struct ehci_qh *) urb->hcpriv; - -		/* S-mask in a QH means it's an interrupt urb */ -		if ((qh->hw->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) { - -			/* ... update hc-wide periodic stats (for usbfs) */ -			ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; -		} +	if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { +		/* ... update hc-wide periodic stats */ +		ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;  	}  	if (unlikely(urb->unlinked)) { diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index 85b74be202e..319dcfaa873 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -85,7 +85,7 @@ static void s5p_setup_vbus_gpio(struct platform_device *pdev)  static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32); -static int __devinit s5p_ehci_probe(struct platform_device *pdev) +static int s5p_ehci_probe(struct platform_device *pdev)  {  	struct s5p_ehci_platdata *pdata;  	struct s5p_ehci_hcd *s5p_ehci; @@ -136,7 +136,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)  		goto fail_clk;  	} -	err = clk_enable(s5p_ehci->clk); +	err = clk_prepare_enable(s5p_ehci->clk);  	if (err)  		goto fail_clk; @@ -183,13 +183,13 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)  	return 0;  fail_io: -	clk_disable(s5p_ehci->clk); +	clk_disable_unprepare(s5p_ehci->clk);  fail_clk:  	usb_put_hcd(hcd);  	return err;  } -static int __devexit s5p_ehci_remove(struct platform_device *pdev) +static int s5p_ehci_remove(struct platform_device *pdev)  {  	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;  	struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev); @@ -200,7 +200,7 @@ static int __devexit s5p_ehci_remove(struct platform_device *pdev)  	if (pdata && pdata->phy_exit)  		pdata->phy_exit(pdev, S5P_USB_PHY_HOST); -	clk_disable(s5p_ehci->clk); +	clk_disable_unprepare(s5p_ehci->clk);  	usb_put_hcd(hcd); @@ -231,7 +231,7 @@ static int s5p_ehci_suspend(struct device *dev)  	if (pdata && pdata->phy_exit)  		pdata->phy_exit(pdev, S5P_USB_PHY_HOST); -	clk_disable(s5p_ehci->clk); +	clk_disable_unprepare(s5p_ehci->clk);  	return rc;  } @@ -243,7 +243,7 @@ static int s5p_ehci_resume(struct device *dev)  	struct platform_device *pdev = to_platform_device(dev);  	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; -	clk_enable(s5p_ehci->clk); +	clk_prepare_enable(s5p_ehci->clk);  	if (pdata && pdata->phy_init)  		pdata->phy_init(pdev, S5P_USB_PHY_HOST); @@ -274,7 +274,7 @@ MODULE_DEVICE_TABLE(of, exynos_ehci_match);  static struct platform_driver s5p_ehci_driver = {  	.probe		= s5p_ehci_probe, -	.remove		= __devexit_p(s5p_ehci_remove), +	.remove		= s5p_ehci_remove,  	.shutdown	= s5p_ehci_shutdown,  	.driver = {  		.name	= "s5p-ehci", diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 7cf3da7babf..69ebee73c0c 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -36,29 +36,6 @@  static int ehci_get_frame (struct usb_hcd *hcd); -#ifdef CONFIG_PCI - -static unsigned ehci_read_frame_index(struct ehci_hcd *ehci) -{ -	unsigned uf; - -	/* -	 * The MosChip MCS9990 controller updates its microframe counter -	 * a little before the frame counter, and occasionally we will read -	 * the invalid intermediate value.  Avoid problems by checking the -	 * microframe number (the low-order 3 bits); if they are 0 then -	 * re-read the register to get the correct value. -	 */ -	uf = ehci_readl(ehci, &ehci->regs->frame_index); -	if (unlikely(ehci->frame_index_bug && ((uf & 7) == 0))) -		uf = ehci_readl(ehci, &ehci->regs->frame_index); -	return uf; -} - -#endif - -/*-------------------------------------------------------------------------*/ -  /*   * periodic_next_shadow - return "next" pointer on shadow list   * @periodic: host pointer to qh/itd/sitd @@ -1361,7 +1338,7 @@ sitd_slot_ok (   * given EHCI_TUNE_FLS and the slop).  Or, write a smarter scheduler!   */ -#define SCHEDULE_SLOP	80	/* microframes */ +#define SCHEDULING_DELAY	40	/* microframes */  static int  iso_stream_schedule ( @@ -1370,7 +1347,7 @@ iso_stream_schedule (  	struct ehci_iso_stream	*stream  )  { -	u32			now, next, start, period, span; +	u32			now, base, next, start, period, span;  	int			status;  	unsigned		mod = ehci->periodic_size << 3;  	struct ehci_iso_sched	*sched = urb->hcpriv; @@ -1382,62 +1359,72 @@ iso_stream_schedule (  		span <<= 3;  	} -	if (span > mod - SCHEDULE_SLOP) { -		ehci_dbg (ehci, "iso request %p too long\n", urb); -		status = -EFBIG; -		goto fail; -	} -  	now = ehci_read_frame_index(ehci) & (mod - 1);  	/* Typical case: reuse current schedule, stream is still active.  	 * Hopefully there are no gaps from the host falling behind -	 * (irq delays etc), but if there are we'll take the next -	 * slot in the schedule, implicitly assuming URB_ISO_ASAP. +	 * (irq delays etc).  If there are, the behavior depends on +	 * whether URB_ISO_ASAP is set.  	 */  	if (likely (!list_empty (&stream->td_list))) { -		u32	excess; -		/* For high speed devices, allow scheduling within the -		 * isochronous scheduling threshold.  For full speed devices -		 * and Intel PCI-based controllers, don't (work around for -		 * Intel ICH9 bug). -		 */ -		if (!stream->highspeed && ehci->fs_i_thresh) -			next = now + ehci->i_thresh; +		/* Take the isochronous scheduling threshold into account */ +		if (ehci->i_thresh) +			next = now + ehci->i_thresh;	/* uframe cache */  		else -			next = now; +			next = (now + 2 + 7) & ~0x07;	/* full frame cache */ -		/* Fell behind (by up to twice the slop amount)? -		 * We decide based on the time of the last currently-scheduled -		 * slot, not the time of the next available slot. +		/* +		 * Use ehci->last_iso_frame as the base.  There can't be any +		 * TDs scheduled for earlier than that.  		 */ -		excess = (stream->next_uframe - period - next) & (mod - 1); -		if (excess >= mod - 2 * SCHEDULE_SLOP) -			start = next + excess - mod + period * -					DIV_ROUND_UP(mod - excess, period); -		else -			start = next + excess + period; -		if (start - now >= mod) { -			ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n", -					urb, start - now - period, period, -					mod); -			status = -EFBIG; +		base = ehci->last_iso_frame << 3; +		next = (next - base) & (mod - 1); +		start = (stream->next_uframe - base) & (mod - 1); + +		/* Is the schedule already full? */ +		if (unlikely(start < period)) { +			ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n", +					urb, stream->next_uframe, base, +					period, mod); +			status = -ENOSPC;  			goto fail;  		} + +		/* Behind the scheduling threshold? */ +		if (unlikely(start < next)) { + +			/* USB_ISO_ASAP: Round up to the first available slot */ +			if (urb->transfer_flags & URB_ISO_ASAP) +				start += (next - start + period - 1) & -period; + +			/* +			 * Not ASAP: Use the next slot in the stream.  If +			 * the entire URB falls before the threshold, fail. +			 */ +			else if (start + span - period < next) { +				ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n", +						urb, start + base, +						span - period, next + base); +				status = -EXDEV; +				goto fail; +			} +		} + +		start += base;  	}  	/* need to schedule; when's the next (u)frame we could start?  	 * this is bigger than ehci->i_thresh allows; scheduling itself -	 * isn't free, the slop should handle reasonably slow cpus.  it +	 * isn't free, the delay should handle reasonably slow cpus.  it  	 * can also help high bandwidth if the dma and irq loads don't  	 * jump until after the queue is primed.  	 */  	else {  		int done = 0; -		start = SCHEDULE_SLOP + (now & ~0x07); -		/* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */ +		base = now & ~0x07; +		start = base + SCHEDULING_DELAY;  		/* find a uframe slot with enough bandwidth.  		 * Early uframes are more precious because full-speed @@ -1464,19 +1451,16 @@ iso_stream_schedule (  		/* no room in the schedule */  		if (!done) { -			ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n", -				urb, now, now + mod); +			ehci_dbg(ehci, "iso sched full %p", urb);  			status = -ENOSPC;  			goto fail;  		}  	}  	/* Tried to schedule too far into the future? */ -	if (unlikely(start - now + span - period -				>= mod - 2 * SCHEDULE_SLOP)) { -		ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n", -				urb, start - now, span - period, -				mod - 2 * SCHEDULE_SLOP); +	if (unlikely(start - base + span - period >= mod)) { +		ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n", +				urb, start - base, span - period, mod);  		status = -EFBIG;  		goto fail;  	} @@ -1490,7 +1474,7 @@ iso_stream_schedule (  	/* Make sure scan_isoc() sees these */  	if (ehci->isoc_count == 0) -		ehci->next_frame = now >> 3; +		ehci->last_iso_frame = now >> 3;  	return 0;   fail: @@ -1646,7 +1630,7 @@ static void itd_link_urb(  	/* don't need that schedule data any more */  	iso_sched_free (stream, iso_sched); -	urb->hcpriv = NULL; +	urb->hcpriv = stream;  	++ehci->isoc_count;  	enable_periodic(ehci); @@ -1708,7 +1692,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd)  			urb->actual_length += desc->actual_length;  		} else {  			/* URB was too late */ -			desc->status = -EXDEV; +			urb->error_count++;  		}  	} @@ -2045,7 +2029,7 @@ static void sitd_link_urb(  	/* don't need that schedule data any more */  	iso_sched_free (stream, sched); -	urb->hcpriv = NULL; +	urb->hcpriv = stream;  	++ehci->isoc_count;  	enable_periodic(ehci); @@ -2081,7 +2065,7 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)  	t = hc32_to_cpup(ehci, &sitd->hw_results);  	/* report transfer status */ -	if (t & SITD_ERRS) { +	if (unlikely(t & SITD_ERRS)) {  		urb->error_count++;  		if (t & SITD_STS_DBE)  			desc->status = usb_pipein (urb->pipe) @@ -2091,6 +2075,9 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd)  			desc->status = -EOVERFLOW;  		else /* XACT, MMF, etc */  			desc->status = -EPROTO; +	} else if (unlikely(t & SITD_STS_ACTIVE)) { +		/* URB was too late */ +		urb->error_count++;  	} else {  		desc->status = 0;  		desc->actual_length = desc->length - SITD_LENGTH(t); @@ -2220,16 +2207,16 @@ static void scan_isoc(struct ehci_hcd *ehci)  		now_frame = (uf >> 3) & fmask;  		live = true;  	} else  { -		now_frame = (ehci->next_frame - 1) & fmask; +		now_frame = (ehci->last_iso_frame - 1) & fmask;  		live = false;  	}  	ehci->now_frame = now_frame; -	frame = ehci->next_frame;  	for (;;) {  		union ehci_shadow	q, *q_p;  		__hc32			type, *hw_p; +		frame = ehci->last_iso_frame;  restart:  		/* scan each element in frame's queue for completions */  		q_p = &ehci->pshadow [frame]; @@ -2334,7 +2321,6 @@ restart:  		/* Stop when we have reached the current frame */  		if (frame == now_frame)  			break; -		frame = (frame + 1) & fmask; +		ehci->last_iso_frame = (frame + 1) & fmask;  	} -	ehci->next_frame = now_frame;  } diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index 6081e1ed3ac..0c90a24fa98 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -21,17 +21,10 @@ struct ehci_sh_priv {  static int ehci_sh_reset(struct usb_hcd *hcd)  {  	struct ehci_hcd	*ehci = hcd_to_ehci(hcd); -	int ret;  	ehci->caps = hcd->regs; -	ret = ehci_setup(hcd); -	if (unlikely(ret)) -		return ret; - -	ehci_port_power(ehci, 0); - -	return ret; +	return ehci_setup(hcd);  }  static const struct hc_driver ehci_sh_hc_driver = { diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c index c718a065e15..466c1bb5b96 100644 --- a/drivers/usb/host/ehci-spear.c +++ b/drivers/usb/host/ehci-spear.c @@ -37,18 +37,11 @@ static void spear_stop_ehci(struct spear_ehci *ehci)  static int ehci_spear_setup(struct usb_hcd *hcd)  {  	struct ehci_hcd *ehci = hcd_to_ehci(hcd); -	int retval = 0;  	/* registers start at offset 0x0 */  	ehci->caps = hcd->regs; -	retval = ehci_setup(hcd); -	if (retval) -		return retval; - -	ehci_port_power(ehci, 0); - -	return retval; +	return ehci_setup(hcd);  }  static const struct hc_driver ehci_spear_hc_driver = { @@ -116,8 +109,6 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)  	struct clk *usbh_clk;  	const struct hc_driver *driver = &ehci_spear_hc_driver;  	int irq, retval; -	char clk_name[20] = "usbh_clk"; -	static int instance = -1;  	if (usb_disabled())  		return -ENODEV; @@ -125,7 +116,7 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)  	irq = platform_get_irq(pdev, 0);  	if (irq < 0) {  		retval = irq; -		goto fail_irq_get; +		goto fail;  	}  	/* @@ -136,47 +127,38 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)  	if (!pdev->dev.dma_mask)  		pdev->dev.dma_mask = &spear_ehci_dma_mask; -	/* -	 * Increment the device instance, when probing via device-tree -	 */ -	if (pdev->id < 0) -		instance++; -	else -		instance = pdev->id; -	sprintf(clk_name, "usbh.%01d_clk", instance); - -	usbh_clk = clk_get(NULL, clk_name); +	usbh_clk = devm_clk_get(&pdev->dev, NULL);  	if (IS_ERR(usbh_clk)) {  		dev_err(&pdev->dev, "Error getting interface clock\n");  		retval = PTR_ERR(usbh_clk); -		goto fail_get_usbh_clk; +		goto fail;  	}  	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));  	if (!hcd) {  		retval = -ENOMEM; -		goto fail_create_hcd; +		goto fail;  	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) {  		retval = -ENODEV; -		goto fail_request_resource; +		goto err_put_hcd;  	}  	hcd->rsrc_start = res->start;  	hcd->rsrc_len = resource_size(res); -	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, +	if (!devm_request_mem_region(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len,  				driver->description)) {  		retval = -EBUSY; -		goto fail_request_resource; +		goto err_put_hcd;  	} -	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); +	hcd->regs = devm_ioremap(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len);  	if (hcd->regs == NULL) {  		dev_dbg(&pdev->dev, "error mapping memory\n");  		retval = -ENOMEM; -		goto fail_ioremap; +		goto err_put_hcd;  	}  	ehci = (struct spear_ehci *)hcd_to_ehci(hcd); @@ -185,21 +167,15 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)  	spear_start_ehci(ehci);  	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);  	if (retval) -		goto fail_add_hcd; +		goto err_stop_ehci;  	return retval; -fail_add_hcd: +err_stop_ehci:  	spear_stop_ehci(ehci); -	iounmap(hcd->regs); -fail_ioremap: -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -fail_request_resource: +err_put_hcd:  	usb_put_hcd(hcd); -fail_create_hcd: -	clk_put(usbh_clk); -fail_get_usbh_clk: -fail_irq_get: +fail:  	dev_err(&pdev->dev, "init fail, %d\n", retval);  	return retval ; @@ -218,17 +194,12 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)  	if (ehci_p->clk)  		spear_stop_ehci(ehci_p); -	iounmap(hcd->regs); -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);  	usb_put_hcd(hcd); -	if (ehci_p->clk) -		clk_put(ehci_p->clk); -  	return 0;  } -static struct of_device_id spear_ehci_id_table[] __devinitdata = { +static struct of_device_id spear_ehci_id_table[] = {  	{ .compatible = "st,spear600-ehci", },  	{ },  }; diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 2de089001ae..acf17556bd8 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -280,7 +280,6 @@ static void tegra_ehci_shutdown(struct usb_hcd *hcd)  static int tegra_ehci_setup(struct usb_hcd *hcd)  {  	struct ehci_hcd *ehci = hcd_to_ehci(hcd); -	int retval;  	/* EHCI registers start at offset 0x100 */  	ehci->caps = hcd->regs + 0x100; @@ -288,12 +287,7 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)  	/* switch to host mode */  	hcd->has_tt = 1; -	retval = ehci_setup(hcd); -	if (retval) -		return retval; - -	ehci_port_power(ehci, 1); -	return retval; +	return ehci_setup(hcd);  }  struct dma_aligned_buffer { @@ -781,9 +775,6 @@ static int tegra_ehci_remove(struct platform_device *pdev)  	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);  	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); -	if (tegra == NULL || hcd == NULL) -		return -EINVAL; -  	pm_runtime_get_sync(&pdev->dev);  	pm_runtime_disable(&pdev->dev);  	pm_runtime_put_noidle(&pdev->dev); @@ -814,7 +805,7 @@ static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)  		hcd->driver->shutdown(hcd);  } -static struct of_device_id tegra_ehci_of_match[] __devinitdata = { +static struct of_device_id tegra_ehci_of_match[] = {  	{ .compatible = "nvidia,tegra20-ehci", },  	{ },  }; diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c index d3c9a3e397b..11695d5b9d8 100644 --- a/drivers/usb/host/ehci-vt8500.c +++ b/drivers/usb/host/ehci-vt8500.c @@ -19,22 +19,6 @@  #include <linux/of.h>  #include <linux/platform_device.h> -static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev) -{ -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); -	int rc = 0; - -	if (!udev->parent) /* udev is root hub itself, impossible */ -		rc = -1; -	/* we only support lpm device connected to root hub yet */ -	if (ehci->has_lpm && !udev->parent->parent) { -		rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum); -		if (!rc) -			rc = ehci_lpm_check(ehci, udev->portnum); -	} -	return rc; -} -  static const struct hc_driver vt8500_ehci_hc_driver = {  	.description		= hcd_name,  	.product_desc		= "VT8500 EHCI", @@ -77,11 +61,6 @@ static const struct hc_driver vt8500_ehci_hc_driver = {  	.relinquish_port	= ehci_relinquish_port,  	.port_handed_over	= ehci_port_handed_over, -	/* -	 * call back when device connected and addressed -	 */ -	.update_device =	ehci_update_device, -  	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,  }; diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c index ec598082c14..59e0e24c753 100644 --- a/drivers/usb/host/ehci-w90x900.c +++ b/drivers/usb/host/ehci-w90x900.c @@ -13,12 +13,12 @@  #include <linux/platform_device.h> -/*ebable phy0 and phy1 for w90p910*/ +/* enable phy0 and phy1 for w90p910 */  #define	ENPHY		(0x01<<8)  #define PHY0_CTR	(0xA4)  #define PHY1_CTR	(0xA8) -static int __devinit usb_w90x900_probe(const struct hc_driver *driver, +static int usb_w90x900_probe(const struct hc_driver *driver,  		      struct platform_device *pdev)  {  	struct usb_hcd *hcd; @@ -147,7 +147,7 @@ static const struct hc_driver ehci_w90x900_hc_driver = {  	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,  }; -static int __devinit ehci_w90x900_probe(struct platform_device *pdev) +static int ehci_w90x900_probe(struct platform_device *pdev)  {  	if (usb_disabled())  		return -ENODEV; @@ -155,7 +155,7 @@ static int __devinit ehci_w90x900_probe(struct platform_device *pdev)  	return usb_w90x900_probe(&ehci_w90x900_hc_driver, pdev);  } -static int __devexit ehci_w90x900_remove(struct platform_device *pdev) +static int ehci_w90x900_remove(struct platform_device *pdev)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev); @@ -166,7 +166,7 @@ static int __devexit ehci_w90x900_remove(struct platform_device *pdev)  static struct platform_driver ehci_hcd_w90x900_driver = {  	.probe  = ehci_w90x900_probe, -	.remove = __devexit_p(ehci_w90x900_remove), +	.remove = ehci_w90x900_remove,  	.driver = {  		.name = "w90x900-ehci",  		.owner = THIS_MODULE, diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 6a3f921a5d7..4f285e8e404 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -125,7 +125,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = {   * as HS only or HS/FS only, it checks the configuration in the device tree   * entry, and sets an appropriate value for hcd->has_tt.   */ -static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op) +static int ehci_hcd_xilinx_of_probe(struct platform_device *op)  {  	struct device_node *dn = op->dev.of_node;  	struct usb_hcd *hcd; diff --git a/drivers/usb/host/ehci-xls.c b/drivers/usb/host/ehci-xls.c deleted file mode 100644 index 8dc6a22d90b..00000000000 --- a/drivers/usb/host/ehci-xls.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * EHCI HCD for Netlogic XLS processors. - * - * (C) Copyright 2011 Netlogic Microsystems Inc. - * - *  Based on various ehci-*.c drivers - * - * This file is subject to the terms and conditions of the GNU General Public - * License.  See the file COPYING in the main directory of this archive for - * more details. - */ - -#include <linux/platform_device.h> - -static int ehci_xls_setup(struct usb_hcd *hcd) -{ -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); - -	ehci->caps = hcd->regs; - -	return ehci_setup(hcd); -} - -int ehci_xls_probe_internal(const struct hc_driver *driver, -	struct platform_device *pdev) -{ -	struct usb_hcd  *hcd; -	struct resource *res; -	int retval, irq; - -	/* Get our IRQ from an earlier registered Platform Resource */ -	irq = platform_get_irq(pdev, 0); -	if (irq < 0) { -		dev_err(&pdev->dev, "Found HC with no IRQ. Check %s setup!\n", -				dev_name(&pdev->dev)); -		return -ENODEV; -	} - -	/* Get our Memory Handle */ -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(&pdev->dev, "Error: MMIO Handle %s setup!\n", -				dev_name(&pdev->dev)); -		return -ENODEV; -	} -	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); -	if (!hcd) { -		retval = -ENOMEM; -		goto err1; -	} - -	hcd->rsrc_start = res->start; -	hcd->rsrc_len = resource_size(res); - -	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, -				driver->description)) { -		dev_dbg(&pdev->dev, "controller already in use\n"); -		retval = -EBUSY; -		goto err2; -	} -	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); - -	if (hcd->regs == NULL) { -		dev_dbg(&pdev->dev, "error mapping memory\n"); -		retval = -EFAULT; -		goto err3; -	} - -	retval = usb_add_hcd(hcd, irq, IRQF_SHARED); -	if (retval != 0) -		goto err4; -	return retval; - -err4: -	iounmap(hcd->regs); -err3: -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err2: -	usb_put_hcd(hcd); -err1: -	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), -			retval); -	return retval; -} - -static struct hc_driver ehci_xls_hc_driver = { -	.description	= hcd_name, -	.product_desc	= "XLS EHCI Host Controller", -	.hcd_priv_size	= sizeof(struct ehci_hcd), -	.irq		= ehci_irq, -	.flags		= HCD_USB2 | HCD_MEMORY, -	.reset		= ehci_xls_setup, -	.start		= ehci_run, -	.stop		= ehci_stop, -	.shutdown	= ehci_shutdown, - -	.urb_enqueue	= ehci_urb_enqueue, -	.urb_dequeue	= ehci_urb_dequeue, -	.endpoint_disable = ehci_endpoint_disable, -	.endpoint_reset	= ehci_endpoint_reset, - -	.get_frame_number = ehci_get_frame, - -	.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 int ehci_xls_probe(struct platform_device *pdev) -{ -	if (usb_disabled()) -		return -ENODEV; - -	return ehci_xls_probe_internal(&ehci_xls_hc_driver, pdev); -} - -static int ehci_xls_remove(struct platform_device *pdev) -{ -	struct usb_hcd *hcd = platform_get_drvdata(pdev); - -	usb_remove_hcd(hcd); -	iounmap(hcd->regs); -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -	usb_put_hcd(hcd); -	return 0; -} - -MODULE_ALIAS("ehci-xls"); - -static struct platform_driver ehci_xls_driver = { -	.probe		= ehci_xls_probe, -	.remove		= ehci_xls_remove, -	.shutdown	= usb_hcd_platform_shutdown, -	.driver		= { -		.name = "ehci-xls", -	}, -}; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index da07d98f7d1..9dadc7118d6 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -143,7 +143,7 @@ struct ehci_hcd {			/* one per controller */  	struct ehci_qh		*intr_unlink_last;  	unsigned		intr_unlink_cycle;  	unsigned		now_frame;	/* frame from HC hardware */ -	unsigned		next_frame;	/* scan periodic, start here */ +	unsigned		last_iso_frame;	/* last frame scanned for iso */  	unsigned		intr_count;	/* intr activity count */  	unsigned		isoc_count;	/* isoc activity count */  	unsigned		periodic_count;	/* periodic activity count */ @@ -193,7 +193,6 @@ struct ehci_hcd {			/* one per controller */  	unsigned		has_amcc_usb23:1;  	unsigned		need_io_watchdog:1;  	unsigned		amd_pll_fix:1; -	unsigned		fs_i_thresh:1;	/* Intel iso scheduling */  	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) */ @@ -207,7 +206,6 @@ struct ehci_hcd {			/* one per controller */  	#define OHCI_HCCTRL_LEN         0x4  	__hc32			*ohci_hcctrl_reg;  	unsigned		has_hostpc:1; -	unsigned		has_lpm:1;  /* support link power management */  	unsigned		has_ppcd:1; /* support per-port change bits */  	u8			sbrn;		/* packed release number */ @@ -762,26 +760,41 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)  /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_PCI - -/* For working around the MosChip frame-index-register bug */ -static unsigned ehci_read_frame_index(struct ehci_hcd *ehci); - +#define ehci_dbg(ehci, fmt, args...) \ +	dev_dbg(ehci_to_hcd(ehci)->self.controller , fmt , ## args) +#define ehci_err(ehci, fmt, args...) \ +	dev_err(ehci_to_hcd(ehci)->self.controller , fmt , ## args) +#define ehci_info(ehci, fmt, args...) \ +	dev_info(ehci_to_hcd(ehci)->self.controller , fmt , ## args) +#define ehci_warn(ehci, fmt, args...) \ +	dev_warn(ehci_to_hcd(ehci)->self.controller , fmt , ## args) + +#ifdef VERBOSE_DEBUG +#	define ehci_vdbg ehci_dbg  #else - -static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci) -{ -	return ehci_readl(ehci, &ehci->regs->frame_index); -} - +	static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {}  #endif -/*-------------------------------------------------------------------------*/ -  #ifndef DEBUG  #define STUB_DEBUG_FILES  #endif	/* DEBUG */  /*-------------------------------------------------------------------------*/ +/* Declarations of things exported for use by ehci platform drivers */ + +struct ehci_driver_overrides { +	size_t		extra_priv_size; +	int		(*reset)(struct usb_hcd *hcd); +}; + +extern void	ehci_init_driver(struct hc_driver *drv, +				const struct ehci_driver_overrides *over); +extern int	ehci_setup(struct usb_hcd *hcd); + +#ifdef CONFIG_PM +extern int	ehci_suspend(struct usb_hcd *hcd, bool do_wakeup); +extern int	ehci_resume(struct usb_hcd *hcd, bool hibernated); +#endif	/* CONFIG_PM */ +  #endif /* __LINUX_EHCI_HCD_H */ diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index 7da1a26bed2..0b46542591f 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -561,7 +561,7 @@ static const struct hc_driver fhci_driver = {  	.hub_control = fhci_hub_control,  }; -static int __devinit of_fhci_probe(struct platform_device *ofdev) +static int of_fhci_probe(struct platform_device *ofdev)  {  	struct device *dev = &ofdev->dev;  	struct device_node *node = dev->of_node; @@ -780,7 +780,7 @@ err_regs:  	return ret;  } -static int __devexit fhci_remove(struct device *dev) +static int fhci_remove(struct device *dev)  {  	struct usb_hcd *hcd = dev_get_drvdata(dev);  	struct fhci_hcd *fhci = hcd_to_fhci(hcd); @@ -803,7 +803,7 @@ static int __devexit fhci_remove(struct device *dev)  	return 0;  } -static int __devexit of_fhci_remove(struct platform_device *ofdev) +static int of_fhci_remove(struct platform_device *ofdev)  {  	return fhci_remove(&ofdev->dev);  } @@ -821,7 +821,7 @@ static struct platform_driver of_fhci_driver = {  		.of_match_table = of_fhci_match,  	},  	.probe		= of_fhci_probe, -	.remove		= __devexit_p(of_fhci_remove), +	.remove		= of_fhci_remove,  };  module_platform_driver(of_fhci_driver); diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 1e771292383..5105127c1d4 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -24,7 +24,7 @@ struct fsl_usb2_dev_data {  	enum fsl_usb2_operating_modes op_mode;	/* operating mode */  }; -struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = { +struct fsl_usb2_dev_data dr_mode_data[] = {  	{  		.dr_mode = "host",  		.drivers = { "fsl-ehci", NULL, NULL, }, @@ -42,7 +42,7 @@ struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = {  	},  }; -struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np) +struct fsl_usb2_dev_data *get_dr_mode_data(struct device_node *np)  {  	const unsigned char *prop;  	int i; @@ -59,7 +59,7 @@ struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np)  	return &dr_mode_data[0]; /* mode not specified, use host */  } -static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type) +static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)  {  	if (!phy_type)  		return FSL_USB2_PHY_NONE; @@ -75,7 +75,7 @@ static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type)  	return FSL_USB2_PHY_NONE;  } -struct platform_device * __devinit fsl_usb2_device_register( +struct platform_device *fsl_usb2_device_register(  					struct platform_device *ofdev,  					struct fsl_usb2_platform_data *pdata,  					const char *name, int id) @@ -154,7 +154,7 @@ static int usb_get_ver_info(struct device_node *np)  	return ver;  } -static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev) +static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)  {  	struct device_node *np = ofdev->dev.of_node;  	struct platform_device *usb_dev; @@ -224,13 +224,13 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)  	return 0;  } -static int __devexit __unregister_subdev(struct device *dev, void *d) +static int __unregister_subdev(struct device *dev, void *d)  {  	platform_device_unregister(to_platform_device(dev));  	return 0;  } -static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev) +static int fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)  {  	device_for_each_child(&ofdev->dev, NULL, __unregister_subdev);  	return 0; @@ -336,7 +336,7 @@ static struct platform_driver fsl_usb2_mph_dr_driver = {  		.of_match_table = fsl_usb2_mph_dr_of_match,  	},  	.probe	= fsl_usb2_mph_dr_of_probe, -	.remove	= __devexit_p(fsl_usb2_mph_dr_of_remove), +	.remove	= fsl_usb2_mph_dr_of_remove,  };  module_platform_driver(fsl_usb2_mph_dr_driver); diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index f19e2690c23..bd6a7447ccc 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -1680,7 +1680,7 @@ static int imx21_hc_reset(struct usb_hcd *hcd)  	return 0;  } -static int __devinit imx21_hc_start(struct usb_hcd *hcd) +static int imx21_hc_start(struct usb_hcd *hcd)  {  	struct imx21 *imx21 = hcd_to_imx21(hcd);  	unsigned long flags; diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 9e65e3091c8..b64e661618b 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1557,7 +1557,7 @@ static int isp116x_remove(struct platform_device *pdev)  	return 0;  } -static int __devinit isp116x_probe(struct platform_device *pdev) +static int isp116x_probe(struct platform_device *pdev)  {  	struct usb_hcd *hcd;  	struct isp116x *isp116x; diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 256326322cf..974480c516f 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2645,7 +2645,7 @@ static struct hc_driver isp1362_hc_driver = {  /*-------------------------------------------------------------------------*/ -static int __devexit isp1362_remove(struct platform_device *pdev) +static int isp1362_remove(struct platform_device *pdev)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev);  	struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); @@ -2680,7 +2680,7 @@ static int __devexit isp1362_remove(struct platform_device *pdev)  	return 0;  } -static int __devinit isp1362_probe(struct platform_device *pdev) +static int isp1362_probe(struct platform_device *pdev)  {  	struct usb_hcd *hcd;  	struct isp1362_hcd *isp1362_hcd; @@ -2856,7 +2856,7 @@ static int isp1362_resume(struct platform_device *pdev)  static struct platform_driver isp1362_driver = {  	.probe = isp1362_probe, -	.remove = __devexit_p(isp1362_remove), +	.remove = isp1362_remove,  	.suspend = isp1362_suspend,  	.resume = isp1362_resume, diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index fff114fd546..bbb791bd761 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -43,7 +43,6 @@ static int of_isp1760_probe(struct platform_device *dev)  	struct device_node *dp = dev->dev.of_node;  	struct resource *res;  	struct resource memory; -	struct of_irq oirq;  	int virq;  	resource_size_t res_len;  	int ret; @@ -69,14 +68,12 @@ static int of_isp1760_probe(struct platform_device *dev)  		goto free_data;  	} -	if (of_irq_map_one(dp, 0, &oirq)) { +	virq = irq_of_parse_and_map(dp, 0); +	if (!virq) {  		ret = -ENODEV;  		goto release_reg;  	} -	virq = irq_create_of_mapping(oirq.controller, oirq.specifier, -			oirq.size); -  	if (of_device_is_compatible(dp, "nxp,usb-isp1761"))  		devflags |= ISP1760_FLAG_ISP1761; @@ -175,7 +172,7 @@ static struct platform_driver isp1760_of_driver = {  #endif  #ifdef CONFIG_PCI -static int __devinit isp1761_pci_probe(struct pci_dev *dev, +static int isp1761_pci_probe(struct pci_dev *dev,  		const struct pci_device_id *id)  {  	u8 latency, limit; @@ -349,7 +346,7 @@ static struct pci_driver isp1761_pci_driver = {  };  #endif -static int __devinit isp1760_plat_probe(struct platform_device *pdev) +static int isp1760_plat_probe(struct platform_device *pdev)  {  	int ret = 0;  	struct usb_hcd *hcd; @@ -416,7 +413,7 @@ out:  	return ret;  } -static int __devexit isp1760_plat_remove(struct platform_device *pdev) +static int isp1760_plat_remove(struct platform_device *pdev)  {  	struct resource *mem_res;  	resource_size_t mem_size; @@ -435,7 +432,7 @@ static int __devexit isp1760_plat_remove(struct platform_device *pdev)  static struct platform_driver isp1760_plat_driver = {  	.probe	= isp1760_plat_probe, -	.remove	= __devexit_p(isp1760_plat_remove), +	.remove	= isp1760_plat_remove,  	.driver	= {  		.name	= "isp1760",  	}, diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 0bf72f943b0..a0cb44f0e72 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -16,11 +16,11 @@  #include <linux/platform_device.h>  #include <linux/of_platform.h>  #include <linux/of_gpio.h> +#include <linux/platform_data/atmel.h>  #include <mach/hardware.h>  #include <asm/gpio.h> -#include <mach/board.h>  #include <mach/cpu.h>  #ifndef CONFIG_ARCH_AT91 @@ -94,7 +94,7 @@ static void at91_stop_hc(struct platform_device *pdev)  /*-------------------------------------------------------------------------*/ -static void __devexit usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); +static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);  /* configure so an HC device and id are always provided */  /* always called with process context; sleeping is OK */ @@ -108,7 +108,7 @@ static void __devexit usb_hcd_at91_remove (struct usb_hcd *, struct platform_dev   * then invokes the start() method for the HCD associated with it   * through the hotplug entry's driver_data.   */ -static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver, +static int usb_hcd_at91_probe(const struct hc_driver *driver,  			struct platform_device *pdev)  {  	int retval; @@ -203,7 +203,7 @@ static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver,   * context, "rmmod" or something similar.   *   */ -static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd, +static void usb_hcd_at91_remove(struct usb_hcd *hcd,  				struct platform_device *pdev)  {  	usb_remove_hcd(hcd); @@ -222,7 +222,7 @@ static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd,  /*-------------------------------------------------------------------------*/ -static int __devinit +static int  ohci_at91_reset (struct usb_hcd *hcd)  {  	struct at91_usbh_data	*board = hcd->self.controller->platform_data; @@ -236,7 +236,7 @@ ohci_at91_reset (struct usb_hcd *hcd)  	return 0;  } -static int __devinit +static int  ohci_at91_start (struct usb_hcd *hcd)  {  	struct ohci_hcd		*ohci = hcd_to_ohci (hcd); @@ -506,7 +506,7 @@ MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids);  static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32); -static int __devinit ohci_at91_of_init(struct platform_device *pdev) +static int ohci_at91_of_init(struct platform_device *pdev)  {  	struct device_node *np = pdev->dev.of_node;  	int i, gpio; @@ -548,7 +548,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)  	return 0;  }  #else -static int __devinit ohci_at91_of_init(struct platform_device *pdev) +static int ohci_at91_of_init(struct platform_device *pdev)  {  	return 0;  } @@ -556,7 +556,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)  /*-------------------------------------------------------------------------*/ -static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev) +static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)  {  	struct at91_usbh_data	*pdata;  	int			i; @@ -641,7 +641,7 @@ static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev)  	return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);  } -static int __devexit ohci_hcd_at91_drv_remove(struct platform_device *pdev) +static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)  {  	struct at91_usbh_data	*pdata = pdev->dev.platform_data;  	int			i; @@ -705,7 +705,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)  	if (!clocked)  		at91_start_clock(); -	ohci_finish_controller_resume(hcd); +	ohci_resume(hcd, false);  	return 0;  }  #else @@ -717,7 +717,7 @@ MODULE_ALIAS("platform:at91_ohci");  static struct platform_driver ohci_hcd_at91_driver = {  	.probe		= ohci_hcd_at91_drv_probe, -	.remove		= __devexit_p(ohci_hcd_at91_drv_remove), +	.remove		= ohci_hcd_at91_drv_remove,  	.shutdown	= usb_hcd_platform_shutdown,  	.suspend	= ohci_hcd_at91_drv_suspend,  	.resume		= ohci_hcd_at91_drv_resume, diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c deleted file mode 100644 index c611699b4aa..00000000000 --- a/drivers/usb/host/ohci-au1xxx.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> - * (C) Copyright 2002 Hewlett-Packard Company - * - * Bus Glue for AMD Alchemy Au1xxx - * - * Written by Christopher Hoover <ch@hpl.hp.com> - * Based on fragments of previous driver by Russell King et al. - * - * Modified for LH7A404 from ohci-sa1111.c - *  by Durgesh Pattamatta <pattamattad@sharpsec.com> - * Modified for AMD Alchemy Au1xxx - *  by Matt Porter <mporter@kernel.crashing.org> - * - * This file is licenced under the GPL. - */ - -#include <linux/platform_device.h> -#include <linux/signal.h> - -#include <asm/mach-au1x00/au1000.h> - - -extern int usb_disabled(void); - -static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd) -{ -	struct ohci_hcd	*ohci = hcd_to_ohci(hcd); -	int ret; - -	ohci_dbg(ohci, "ohci_au1xxx_start, ohci:%p", ohci); - -	if ((ret = ohci_init(ohci)) < 0) -		return ret; - -	if ((ret = ohci_run(ohci)) < 0) { -		dev_err(hcd->self.controller, "can't start %s", -			hcd->self.bus_name); -		ohci_stop(hcd); -		return ret; -	} - -	return 0; -} - -static const struct hc_driver ohci_au1xxx_hc_driver = { -	.description =		hcd_name, -	.product_desc =		"Au1xxx OHCI", -	.hcd_priv_size =	sizeof(struct ohci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq =			ohci_irq, -	.flags =		HCD_USB11 | HCD_MEMORY, - -	/* -	 * basic lifecycle operations -	 */ -	.start =		ohci_au1xxx_start, -	.stop =			ohci_stop, -	.shutdown =		ohci_shutdown, - -	/* -	 * managing i/o requests and associated device resources -	 */ -	.urb_enqueue =		ohci_urb_enqueue, -	.urb_dequeue =		ohci_urb_dequeue, -	.endpoint_disable =	ohci_endpoint_disable, - -	/* -	 * scheduling support -	 */ -	.get_frame_number =	ohci_get_frame, - -	/* -	 * root hub support -	 */ -	.hub_status_data =	ohci_hub_status_data, -	.hub_control =		ohci_hub_control, -#ifdef	CONFIG_PM -	.bus_suspend =		ohci_bus_suspend, -	.bus_resume =		ohci_bus_resume, -#endif -	.start_port_reset =	ohci_start_port_reset, -}; - -static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev) -{ -	int ret, unit; -	struct usb_hcd *hcd; - -	if (usb_disabled()) -		return -ENODEV; - -	if (pdev->resource[1].flags != IORESOURCE_IRQ) { -		pr_debug("resource[1] is not IORESOURCE_IRQ\n"); -		return -ENOMEM; -	} - -	hcd = usb_create_hcd(&ohci_au1xxx_hc_driver, &pdev->dev, "au1xxx"); -	if (!hcd) -		return -ENOMEM; - -	hcd->rsrc_start = pdev->resource[0].start; -	hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; - -	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { -		pr_debug("request_mem_region failed\n"); -		ret = -EBUSY; -		goto err1; -	} - -	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); -	if (!hcd->regs) { -		pr_debug("ioremap failed\n"); -		ret = -ENOMEM; -		goto err2; -	} - -	unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ? -			ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0; -	if (alchemy_usb_control(unit, 1)) { -		printk(KERN_INFO "%s: controller init failed!\n", pdev->name); -		ret = -ENODEV; -		goto err3; -	} - -	ohci_hcd_init(hcd_to_ohci(hcd)); - -	ret = usb_add_hcd(hcd, pdev->resource[1].start, -			  IRQF_SHARED); -	if (ret == 0) { -		platform_set_drvdata(pdev, hcd); -		return ret; -	} - -	alchemy_usb_control(unit, 0); -err3: -	iounmap(hcd->regs); -err2: -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err1: -	usb_put_hcd(hcd); -	return ret; -} - -static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev) -{ -	struct usb_hcd *hcd = platform_get_drvdata(pdev); -	int unit; - -	unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ? -			ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0; -	usb_remove_hcd(hcd); -	alchemy_usb_control(unit, 0); -	iounmap(hcd->regs); -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -	usb_put_hcd(hcd); -	platform_set_drvdata(pdev, NULL); - -	return 0; -} - -#ifdef CONFIG_PM -static int ohci_hcd_au1xxx_drv_suspend(struct device *dev) -{ -	struct usb_hcd *hcd = dev_get_drvdata(dev); -	struct ohci_hcd	*ohci = hcd_to_ohci(hcd); -	unsigned long flags; -	int rc; - -	rc = 0; - -	/* Root hub was already suspended. Disable irq emission and -	 * mark HW unaccessible, bail out if RH has been resumed. Use -	 * the spinlock to properly synchronize with possible pending -	 * RH suspend or resume activity. -	 */ -	spin_lock_irqsave(&ohci->lock, flags); -	if (ohci->rh_state != OHCI_RH_SUSPENDED) { -		rc = -EINVAL; -		goto bail; -	} -	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); -	(void)ohci_readl(ohci, &ohci->regs->intrdisable); - -	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - -	alchemy_usb_control(ALCHEMY_USB_OHCI0, 0); -bail: -	spin_unlock_irqrestore(&ohci->lock, flags); - -	return rc; -} - -static int ohci_hcd_au1xxx_drv_resume(struct device *dev) -{ -	struct usb_hcd *hcd = dev_get_drvdata(dev); - -	alchemy_usb_control(ALCHEMY_USB_OHCI0, 1); - -	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); -	ohci_finish_controller_resume(hcd); - -	return 0; -} - -static const struct dev_pm_ops au1xxx_ohci_pmops = { -	.suspend	= ohci_hcd_au1xxx_drv_suspend, -	.resume		= ohci_hcd_au1xxx_drv_resume, -}; - -#define AU1XXX_OHCI_PMOPS &au1xxx_ohci_pmops - -#else -#define AU1XXX_OHCI_PMOPS NULL -#endif - -static struct platform_driver ohci_hcd_au1xxx_driver = { -	.probe		= ohci_hcd_au1xxx_drv_probe, -	.remove		= ohci_hcd_au1xxx_drv_remove, -	.shutdown	= usb_hcd_platform_shutdown, -	.driver		= { -		.name	= "au1xxx-ohci", -		.owner	= THIS_MODULE, -		.pm	= AU1XXX_OHCI_PMOPS, -	}, -}; - -MODULE_ALIAS("platform:au1xxx-ohci"); diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c deleted file mode 100644 index 2c9f233047b..00000000000 --- a/drivers/usb/host/ohci-cns3xxx.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2008 Cavium Networks - * - * This file 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/platform_device.h> -#include <linux/atomic.h> -#include <mach/cns3xxx.h> -#include <mach/pm.h> - -static int __devinit -cns3xxx_ohci_start(struct usb_hcd *hcd) -{ -	struct ohci_hcd	*ohci = hcd_to_ohci(hcd); -	int ret; - -	/* -	 * EHCI and OHCI share the same clock and power, -	 * resetting twice would cause the 1st controller been reset. -	 * Therefore only do power up  at the first up device, and -	 * power down at the last down device. -	 * -	 * Set USB AHB INCR length to 16 -	 */ -	if (atomic_inc_return(&usb_pwr_ref) == 1) { -		cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB); -		cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST); -		cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST); -		__raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)), -			MISC_CHIP_CONFIG_REG); -	} - -	ret = ohci_init(ohci); -	if (ret < 0) -		return ret; - -	ohci->num_ports = 1; - -	ret = ohci_run(ohci); -	if (ret < 0) { -		dev_err(hcd->self.controller, "can't start %s\n", -			hcd->self.bus_name); -		ohci_stop(hcd); -		return ret; -	} -	return 0; -} - -static const struct hc_driver cns3xxx_ohci_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "CNS3XXX OHCI Host controller", -	.hcd_priv_size		= sizeof(struct ohci_hcd), -	.irq			= ohci_irq, -	.flags			= HCD_USB11 | HCD_MEMORY, -	.start			= cns3xxx_ohci_start, -	.stop			= ohci_stop, -	.shutdown		= ohci_shutdown, -	.urb_enqueue		= ohci_urb_enqueue, -	.urb_dequeue		= ohci_urb_dequeue, -	.endpoint_disable	= ohci_endpoint_disable, -	.get_frame_number	= ohci_get_frame, -	.hub_status_data	= ohci_hub_status_data, -	.hub_control		= ohci_hub_control, -#ifdef CONFIG_PM -	.bus_suspend		= ohci_bus_suspend, -	.bus_resume		= ohci_bus_resume, -#endif -	.start_port_reset	= ohci_start_port_reset, -}; - -static int cns3xxx_ohci_probe(struct platform_device *pdev) -{ -	struct device *dev = &pdev->dev; -	struct usb_hcd *hcd; -	const struct hc_driver *driver = &cns3xxx_ohci_hc_driver; -	struct resource *res; -	int irq; -	int retval; - -	if (usb_disabled()) -		return -ENODEV; - -	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -	if (!res) { -		dev_err(dev, "Found HC with no IRQ.\n"); -		return -ENODEV; -	} -	irq = res->start; - -	hcd = usb_create_hcd(driver, dev, dev_name(dev)); -	if (!hcd) -		return -ENOMEM; - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(dev, "Found HC with no register addr.\n"); -		retval = -ENODEV; -		goto err1; -	} -	hcd->rsrc_start = res->start; -	hcd->rsrc_len = resource_size(res); - -	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, -			driver->description)) { -		dev_dbg(dev, "controller already in use\n"); -		retval = -EBUSY; -		goto err1; -	} - -	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); -	if (!hcd->regs) { -		dev_dbg(dev, "error mapping memory\n"); -		retval = -EFAULT; -		goto err2; -	} - -	ohci_hcd_init(hcd_to_ohci(hcd)); - -	retval = usb_add_hcd(hcd, irq, IRQF_SHARED); -	if (retval == 0) -		return retval; - -	iounmap(hcd->regs); -err2: -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err1: -	usb_put_hcd(hcd); -	return retval; -} - -static int cns3xxx_ohci_remove(struct platform_device *pdev) -{ -	struct usb_hcd *hcd = platform_get_drvdata(pdev); - -	usb_remove_hcd(hcd); -	iounmap(hcd->regs); -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - -	/* -	 * EHCI and OHCI share the same clock and power, -	 * resetting twice would cause the 1st controller been reset. -	 * Therefore only do power up  at the first up device, and -	 * power down at the last down device. -	 */ -	if (atomic_dec_return(&usb_pwr_ref) == 0) -		cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST); - -	usb_put_hcd(hcd); - -	platform_set_drvdata(pdev, NULL); - -	return 0; -} - -MODULE_ALIAS("platform:cns3xxx-ohci"); - -static struct platform_driver ohci_hcd_cns3xxx_driver = { -	.probe = cns3xxx_ohci_probe, -	.remove = cns3xxx_ohci_remove, -	.driver = { -		.name = "cns3xxx-ohci", -	}, -}; diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index dbfbd1dfd2e..8704e9fa5a8 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -107,7 +107,7 @@ static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd,  	usb_put_hcd(hcd);  } -static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd) +static int ohci_ep93xx_start(struct usb_hcd *hcd)  {  	struct ohci_hcd *ohci = hcd_to_ohci(hcd);  	int ret; @@ -194,7 +194,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)  	ep93xx_start_hc(&pdev->dev); -	ohci_finish_controller_resume(hcd); +	ohci_resume(hcd, false);  	return 0;  }  #endif diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index 20a50081f92..aa3b8844bb9 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -23,6 +23,11 @@ struct exynos_ohci_hcd {  	struct clk *clk;  }; +static int ohci_exynos_reset(struct usb_hcd *hcd) +{ +	return ohci_init(hcd_to_ohci(hcd)); +} +  static int ohci_exynos_start(struct usb_hcd *hcd)  {  	struct ohci_hcd *ohci = hcd_to_ohci(hcd); @@ -30,10 +35,6 @@ static int ohci_exynos_start(struct usb_hcd *hcd)  	ohci_dbg(ohci, "ohci_exynos_start, ohci:%p", ohci); -	ret = ohci_init(ohci); -	if (ret < 0) -		return ret; -  	ret = ohci_run(ohci);  	if (ret < 0) {  		dev_err(hcd->self.controller, "can't start %s\n", @@ -53,6 +54,7 @@ static const struct hc_driver exynos_ohci_hc_driver = {  	.irq			= ohci_irq,  	.flags			= HCD_MEMORY|HCD_USB11, +	.reset			= ohci_exynos_reset,  	.start			= ohci_exynos_start,  	.stop			= ohci_stop,  	.shutdown		= ohci_shutdown, @@ -74,7 +76,7 @@ static const struct hc_driver exynos_ohci_hc_driver = {  static u64 ohci_exynos_dma_mask = DMA_BIT_MASK(32); -static int __devinit exynos_ohci_probe(struct platform_device *pdev) +static int exynos_ohci_probe(struct platform_device *pdev)  {  	struct exynos4_ohci_platdata *pdata;  	struct exynos_ohci_hcd *exynos_ohci; @@ -115,7 +117,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)  	}  	exynos_ohci->hcd = hcd; -	exynos_ohci->clk = clk_get(&pdev->dev, "usbhost"); +	exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");  	if (IS_ERR(exynos_ohci->clk)) {  		dev_err(&pdev->dev, "Failed to get usbhost clock\n"); @@ -123,9 +125,9 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)  		goto fail_clk;  	} -	err = clk_enable(exynos_ohci->clk); +	err = clk_prepare_enable(exynos_ohci->clk);  	if (err) -		goto fail_clken; +		goto fail_clk;  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) { @@ -167,15 +169,13 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev)  	return 0;  fail_io: -	clk_disable(exynos_ohci->clk); -fail_clken: -	clk_put(exynos_ohci->clk); +	clk_disable_unprepare(exynos_ohci->clk);  fail_clk:  	usb_put_hcd(hcd);  	return err;  } -static int __devexit exynos_ohci_remove(struct platform_device *pdev) +static int exynos_ohci_remove(struct platform_device *pdev)  {  	struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;  	struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev); @@ -186,8 +186,7 @@ static int __devexit exynos_ohci_remove(struct platform_device *pdev)  	if (pdata && pdata->phy_exit)  		pdata->phy_exit(pdev, S5P_USB_PHY_HOST); -	clk_disable(exynos_ohci->clk); -	clk_put(exynos_ohci->clk); +	clk_disable_unprepare(exynos_ohci->clk);  	usb_put_hcd(hcd); @@ -232,7 +231,7 @@ static int exynos_ohci_suspend(struct device *dev)  	if (pdata && pdata->phy_exit)  		pdata->phy_exit(pdev, S5P_USB_PHY_HOST); -	clk_disable(exynos_ohci->clk); +	clk_disable_unprepare(exynos_ohci->clk);  fail:  	spin_unlock_irqrestore(&ohci->lock, flags); @@ -247,15 +246,12 @@ static int exynos_ohci_resume(struct device *dev)  	struct platform_device *pdev = to_platform_device(dev);  	struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; -	clk_enable(exynos_ohci->clk); +	clk_prepare_enable(exynos_ohci->clk);  	if (pdata && pdata->phy_init)  		pdata->phy_init(pdev, S5P_USB_PHY_HOST); -	/* Mark hardware accessible again as we are out of D3 state by now */ -	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - -	ohci_finish_controller_resume(hcd); +	ohci_resume(hcd, false);  	return 0;  } @@ -279,7 +275,7 @@ MODULE_DEVICE_TABLE(of, exynos_ohci_match);  static struct platform_driver exynos_ohci_driver = {  	.probe		= exynos_ohci_probe, -	.remove		= __devexit_p(exynos_ohci_remove), +	.remove		= exynos_ohci_remove,  	.shutdown	= exynos_ohci_shutdown,  	.driver = {  		.name	= "exynos-ohci", diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 4a1d64d9233..180a2b01db5 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -231,13 +231,41 @@ static int ohci_urb_enqueue (  			frame &= ~(ed->interval - 1);  			frame |= ed->branch;  			urb->start_frame = frame; +		} +	} else if (ed->type == PIPE_ISOCHRONOUS) { +		u16	next = ohci_frame_no(ohci) + 2; +		u16	frame = ed->last_iso + ed->interval; + +		/* Behind the scheduling threshold? */ +		if (unlikely(tick_before(frame, next))) { -			/* yes, only URB_ISO_ASAP is supported, and -			 * urb->start_frame is never used as input. +			/* USB_ISO_ASAP: Round up to the first available slot */ +			if (urb->transfer_flags & URB_ISO_ASAP) +				frame += (next - frame + ed->interval - 1) & +						-ed->interval; + +			/* +			 * Not ASAP: Use the next slot in the stream.  If +			 * the entire URB falls before the threshold, fail.  			 */ +			else if (tick_before(frame + ed->interval * +					(urb->number_of_packets - 1), next)) { +				retval = -EXDEV; +				usb_hcd_unlink_urb_from_ep(hcd, urb); +				goto fail; +			} + +			/* +			 * Some OHCI hardware doesn't handle late TDs +			 * correctly.  After retiring them it proceeds to +			 * the next ED instead of the next TD.  Therefore +			 * we have to omit the late TDs entirely. +			 */ +			urb_priv->td_cnt = DIV_ROUND_UP(next - frame, +					ed->interval);  		} -	} else if (ed->type == PIPE_ISOCHRONOUS) -		urb->start_frame = ed->last_iso + ed->interval; +		urb->start_frame = frame; +	}  	/* fill the TDs and link them to the ed; and  	 * enable that part of the schedule, if needed @@ -983,6 +1011,79 @@ static int ohci_restart (struct ohci_hcd *ohci)  #endif +#ifdef CONFIG_PM + +static int __maybe_unused ohci_suspend(struct usb_hcd *hcd, bool do_wakeup) +{ +	struct ohci_hcd	*ohci = hcd_to_ohci (hcd); +	unsigned long	flags; + +	/* Disable irq emission and mark HW unaccessible. Use +	 * the spinlock to properly synchronize with possible pending +	 * RH suspend or resume activity. +	 */ +	spin_lock_irqsave (&ohci->lock, flags); +	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); +	(void)ohci_readl(ohci, &ohci->regs->intrdisable); + +	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); +	spin_unlock_irqrestore (&ohci->lock, flags); + +	return 0; +} + + +static int __maybe_unused ohci_resume(struct usb_hcd *hcd, bool hibernated) +{ +	struct ohci_hcd		*ohci = hcd_to_ohci(hcd); +	int			port; +	bool			need_reinit = false; + +	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + +	/* Make sure resume from hibernation re-enumerates everything */ +	if (hibernated) +		ohci_usb_reset(ohci); + +	/* See if the controller is already running or has been reset */ +	ohci->hc_control = ohci_readl(ohci, &ohci->regs->control); +	if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { +		need_reinit = true; +	} else { +		switch (ohci->hc_control & OHCI_CTRL_HCFS) { +		case OHCI_USB_OPER: +		case OHCI_USB_RESET: +			need_reinit = true; +		} +	} + +	/* If needed, reinitialize and suspend the root hub */ +	if (need_reinit) { +		spin_lock_irq(&ohci->lock); +		ohci_rh_resume(ohci); +		ohci_rh_suspend(ohci, 0); +		spin_unlock_irq(&ohci->lock); +	} + +	/* Normally just turn on port power and enable interrupts */ +	else { +		ohci_dbg(ohci, "powerup ports\n"); +		for (port = 0; port < ohci->num_ports; port++) +			ohci_writel(ohci, RH_PS_PPS, +					&ohci->regs->roothub.portstatus[port]); + +		ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable); +		ohci_readl(ohci, &ohci->regs->intrenable); +		msleep(20); +	} + +	usb_hcd_resume_root_hub(hcd); + +	return 0; +} + +#endif +  /*-------------------------------------------------------------------------*/  MODULE_AUTHOR (DRIVER_AUTHOR); @@ -1029,21 +1130,6 @@ MODULE_LICENSE ("GPL");  #define PLATFORM_DRIVER		ohci_hcd_ep93xx_driver  #endif -#ifdef CONFIG_MIPS_ALCHEMY -#include "ohci-au1xxx.c" -#define PLATFORM_DRIVER		ohci_hcd_au1xxx_driver -#endif - -#ifdef CONFIG_PNX8550 -#include "ohci-pnx8550.c" -#define PLATFORM_DRIVER		ohci_hcd_pnx8550_driver -#endif - -#ifdef CONFIG_USB_OHCI_HCD_PPC_SOC -#include "ohci-ppc-soc.c" -#define PLATFORM_DRIVER		ohci_hcd_ppc_soc_driver -#endif -  #ifdef CONFIG_ARCH_AT91  #include "ohci-at91.c"  #define PLATFORM_DRIVER		ohci_hcd_at91_driver @@ -1059,11 +1145,6 @@ MODULE_LICENSE ("GPL");  #define PLATFORM_DRIVER		ohci_hcd_da8xx_driver  #endif -#ifdef CONFIG_USB_OHCI_SH -#include "ohci-sh.c" -#define PLATFORM_DRIVER		ohci_hcd_sh_driver -#endif -  #ifdef CONFIG_USB_OHCI_HCD_PPC_OF  #include "ohci-ppc-of.c" @@ -1105,16 +1186,6 @@ MODULE_LICENSE ("GPL");  #define PLATFORM_DRIVER		ohci_hcd_tilegx_driver  #endif -#ifdef CONFIG_USB_CNS3XXX_OHCI -#include "ohci-cns3xxx.c" -#define PLATFORM_DRIVER		ohci_hcd_cns3xxx_driver -#endif - -#ifdef CONFIG_CPU_XLR -#include "ohci-xls.c" -#define PLATFORM_DRIVER		ohci_xls_driver -#endif -  #ifdef CONFIG_USB_OHCI_HCD_PLATFORM  #include "ohci-platform.c"  #define PLATFORM_DRIVER		ohci_platform_driver diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 2f3619eefef..db09dae7b55 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -316,48 +316,6 @@ static int ohci_bus_resume (struct usb_hcd *hcd)  	return rc;  } -/* Carry out the final steps of resuming the controller device */ -static void __maybe_unused ohci_finish_controller_resume(struct usb_hcd *hcd) -{ -	struct ohci_hcd		*ohci = hcd_to_ohci(hcd); -	int			port; -	bool			need_reinit = false; - -	/* See if the controller is already running or has been reset */ -	ohci->hc_control = ohci_readl(ohci, &ohci->regs->control); -	if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { -		need_reinit = true; -	} else { -		switch (ohci->hc_control & OHCI_CTRL_HCFS) { -		case OHCI_USB_OPER: -		case OHCI_USB_RESET: -			need_reinit = true; -		} -	} - -	/* If needed, reinitialize and suspend the root hub */ -	if (need_reinit) { -		spin_lock_irq(&ohci->lock); -		ohci_rh_resume(ohci); -		ohci_rh_suspend(ohci, 0); -		spin_unlock_irq(&ohci->lock); -	} - -	/* Normally just turn on port power and enable interrupts */ -	else { -		ohci_dbg(ohci, "powerup ports\n"); -		for (port = 0; port < ohci->num_ports; port++) -			ohci_writel(ohci, RH_PS_PPS, -					&ohci->regs->roothub.portstatus[port]); - -		ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable); -		ohci_readl(ohci, &ohci->regs->intrenable); -		msleep(20); -	} - -	usb_hcd_resume_root_hub(hcd); -} -  /* Carry out polling-, autostop-, and autoresume-related state changes */  static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,  		int any_connected, int rhsc_status) diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c index 931d588c3fb..8062bb9dea1 100644 --- a/drivers/usb/host/ohci-jz4740.c +++ b/drivers/usb/host/ohci-jz4740.c @@ -145,7 +145,7 @@ static const struct hc_driver ohci_jz4740_hc_driver = {  }; -static __devinit int jz4740_ohci_probe(struct platform_device *pdev) +static int jz4740_ohci_probe(struct platform_device *pdev)  {  	int ret;  	struct usb_hcd *hcd; @@ -239,7 +239,7 @@ err_free:  	return ret;  } -static __devexit int jz4740_ohci_remove(struct platform_device *pdev) +static int jz4740_ohci_remove(struct platform_device *pdev)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev);  	struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd); @@ -266,7 +266,7 @@ static __devexit int jz4740_ohci_remove(struct platform_device *pdev)  static struct platform_driver ohci_hcd_jz4740_driver = {  	.probe = jz4740_ohci_probe, -	.remove = __devexit_p(jz4740_ohci_remove), +	.remove = jz4740_ohci_remove,  	.driver = {  		.name = "jz4740-ohci",  		.owner = THIS_MODULE, diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c index e068f034cb9..2344040c16d 100644 --- a/drivers/usb/host/ohci-nxp.c +++ b/drivers/usb/host/ohci-nxp.c @@ -147,7 +147,7 @@ static void nxp_stop_hc(void)  	__raw_writel(tmp, USB_OTG_STAT_CONTROL);  } -static int __devinit ohci_nxp_start(struct usb_hcd *hcd) +static int ohci_nxp_start(struct usb_hcd *hcd)  {  	struct ohci_hcd *ohci = hcd_to_ohci(hcd);  	int ret; @@ -205,7 +205,7 @@ static const struct hc_driver ohci_nxp_hc_driver = {  	.start_port_reset = ohci_start_port_reset,  }; -static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) +static int usb_hcd_nxp_probe(struct platform_device *pdev)  {  	struct usb_hcd *hcd = 0;  	struct ohci_hcd *ohci; diff --git a/drivers/usb/host/ohci-octeon.c b/drivers/usb/host/ohci-octeon.c index d469bf9b9e5..d44430d009f 100644 --- a/drivers/usb/host/ohci-octeon.c +++ b/drivers/usb/host/ohci-octeon.c @@ -42,7 +42,7 @@ static void ohci_octeon_hw_stop(void)  	octeon2_usb_clocks_stop();  } -static int __devinit ohci_octeon_start(struct usb_hcd *hcd) +static int ohci_octeon_start(struct usb_hcd *hcd)  {  	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);  	int ret; diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 439e6e4f2d6..b1d32fb4a7a 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -529,7 +529,7 @@ static int ohci_omap_resume(struct platform_device *dev)  	ohci->next_statechange = jiffies;  	omap_ohci_clock_power(1); -	ohci_finish_controller_resume(hcd); +	ohci_resume(hcd, false);  	return 0;  } diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c index bd7803dce9b..eb35d963023 100644 --- a/drivers/usb/host/ohci-omap3.c +++ b/drivers/usb/host/ohci-omap3.c @@ -124,7 +124,7 @@ static const struct hc_driver ohci_omap3_hc_driver = {   * then invokes the start() method for the HCD associated with it   * through the hotplug entry's driver_data.   */ -static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev) +static int ohci_hcd_omap3_probe(struct platform_device *pdev)  {  	struct device		*dev = &pdev->dev;  	struct usb_hcd		*hcd = NULL; @@ -208,7 +208,7 @@ err_io:   * the HCD's stop() method.  It is always called from a thread   * context, normally "rmmod", "apmd", or something similar.   */ -static int __devexit ohci_hcd_omap3_remove(struct platform_device *pdev) +static int ohci_hcd_omap3_remove(struct platform_device *pdev)  {  	struct device *dev	= &pdev->dev;  	struct usb_hcd *hcd	= dev_get_drvdata(dev); @@ -231,7 +231,7 @@ static void ohci_hcd_omap3_shutdown(struct platform_device *pdev)  static struct platform_driver ohci_hcd_omap3_driver = {  	.probe		= ohci_hcd_omap3_probe, -	.remove		= __devexit_p(ohci_hcd_omap3_remove), +	.remove		= ohci_hcd_omap3_remove,  	.shutdown	= ohci_hcd_omap3_shutdown,  	.driver		= {  		.name	= "ohci-omap3", diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 1843bb68ac7..951514ef446 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -270,7 +270,7 @@ static int ohci_pci_reset (struct usb_hcd *hcd)  } -static int __devinit ohci_pci_start (struct usb_hcd *hcd) +static int ohci_pci_start (struct usb_hcd *hcd)  {  	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);  	int		ret; @@ -296,49 +296,6 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)  	return ret;  } -#ifdef	CONFIG_PM - -static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) -{ -	struct ohci_hcd	*ohci = hcd_to_ohci (hcd); -	unsigned long	flags; -	int		rc = 0; - -	/* Root hub was already suspended. Disable irq emission and -	 * mark HW unaccessible, bail out if RH has been resumed. Use -	 * the spinlock to properly synchronize with possible pending -	 * RH suspend or resume activity. -	 */ -	spin_lock_irqsave (&ohci->lock, flags); -	if (ohci->rh_state != OHCI_RH_SUSPENDED) { -		rc = -EINVAL; -		goto bail; -	} -	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); -	(void)ohci_readl(ohci, &ohci->regs->intrdisable); - -	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - bail: -	spin_unlock_irqrestore (&ohci->lock, flags); - -	return rc; -} - - -static int ohci_pci_resume(struct usb_hcd *hcd, bool hibernated) -{ -	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - -	/* Make sure resume from hibernation re-enumerates everything */ -	if (hibernated) -		ohci_usb_reset(hcd_to_ohci(hcd)); - -	ohci_finish_controller_resume(hcd); -	return 0; -} - -#endif	/* CONFIG_PM */ -  /*-------------------------------------------------------------------------*/ @@ -362,8 +319,8 @@ static const struct hc_driver ohci_pci_hc_driver = {  	.shutdown =		ohci_shutdown,  #ifdef	CONFIG_PM -	.pci_suspend =		ohci_pci_suspend, -	.pci_resume =		ohci_pci_resume, +	.pci_suspend =		ohci_suspend, +	.pci_resume =		ohci_resume,  #endif  	/* diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index e24ec9f7916..084503b03fc 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -31,6 +31,10 @@ static int ohci_platform_reset(struct usb_hcd *hcd)  		ohci->flags |= OHCI_QUIRK_FRAME_NO;  	ohci_hcd_init(ohci); + +	if (pdata->num_ports) +		ohci->num_ports = pdata->num_ports; +  	err = ohci_init(ohci);  	return err; @@ -79,7 +83,7 @@ static const struct hc_driver ohci_platform_hc_driver = {  	.start_port_reset	= ohci_start_port_reset,  }; -static int __devinit ohci_platform_probe(struct platform_device *dev) +static int ohci_platform_probe(struct platform_device *dev)  {  	struct usb_hcd *hcd;  	struct resource *res_mem; @@ -97,13 +101,13 @@ static int __devinit ohci_platform_probe(struct platform_device *dev)  	irq = platform_get_irq(dev, 0);  	if (irq < 0) { -		pr_err("no irq provided"); +		dev_err(&dev->dev, "no irq provided");  		return irq;  	}  	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);  	if (!res_mem) { -		pr_err("no memory recourse provided"); +		dev_err(&dev->dev, "no memory resource provided");  		return -ENXIO;  	} @@ -123,29 +127,19 @@ static int __devinit ohci_platform_probe(struct platform_device *dev)  	hcd->rsrc_start = res_mem->start;  	hcd->rsrc_len = resource_size(res_mem); -	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { -		pr_err("controller already in use"); -		err = -EBUSY; -		goto err_put_hcd; -	} - -	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); +	hcd->regs = devm_request_and_ioremap(&dev->dev, res_mem);  	if (!hcd->regs) {  		err = -ENOMEM; -		goto err_release_region; +		goto err_put_hcd;  	}  	err = usb_add_hcd(hcd, irq, IRQF_SHARED);  	if (err) -		goto err_iounmap; +		goto err_put_hcd;  	platform_set_drvdata(dev, hcd);  	return err; -err_iounmap: -	iounmap(hcd->regs); -err_release_region: -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);  err_put_hcd:  	usb_put_hcd(hcd);  err_power: @@ -155,14 +149,12 @@ err_power:  	return err;  } -static int __devexit ohci_platform_remove(struct platform_device *dev) +static int ohci_platform_remove(struct platform_device *dev)  {  	struct usb_hcd *hcd = platform_get_drvdata(dev);  	struct usb_ohci_pdata *pdata = dev->dev.platform_data;  	usb_remove_hcd(hcd); -	iounmap(hcd->regs); -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);  	usb_put_hcd(hcd);  	platform_set_drvdata(dev, NULL); @@ -199,7 +191,7 @@ static int ohci_platform_resume(struct device *dev)  			return err;  	} -	ohci_finish_controller_resume(hcd); +	ohci_resume(hcd, false);  	return 0;  } @@ -222,7 +214,7 @@ static const struct dev_pm_ops ohci_platform_pm_ops = {  static struct platform_driver ohci_platform_driver = {  	.id_table	= ohci_platform_table,  	.probe		= ohci_platform_probe, -	.remove		= __devexit_p(ohci_platform_remove), +	.remove		= ohci_platform_remove,  	.shutdown	= usb_hcd_platform_shutdown,  	.driver		= {  		.owner	= THIS_MODULE, diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c deleted file mode 100644 index 148d27d6a67..00000000000 --- a/drivers/usb/host/ohci-pnx8550.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> - * (C) Copyright 2002 Hewlett-Packard Company - * (C) Copyright 2005 Embedded Alley Solutions, Inc. - * - * Bus Glue for PNX8550 - * - * Written by Christopher Hoover <ch@hpl.hp.com> - * Based on fragments of previous driver by Russell King et al. - * - * Modified for LH7A404 from ohci-sa1111.c - *  by Durgesh Pattamatta <pattamattad@sharpsec.com> - * - * Modified for PNX8550 from ohci-sa1111.c and sa-omap.c - *  by Vitaly Wool <vitalywool@gmail.com> - * - * This file is licenced under the GPL. - */ - -#include <linux/device.h> -#include <linux/platform_device.h> -#include <asm/mach-pnx8550/usb.h> -#include <asm/mach-pnx8550/int.h> -#include <asm/mach-pnx8550/pci.h> - -#ifndef CONFIG_PNX8550 -#error "This file is PNX8550 bus glue.  CONFIG_PNX8550 must be defined." -#endif - -extern int usb_disabled(void); - -/*-------------------------------------------------------------------------*/ - -static void pnx8550_start_hc(struct platform_device *dev) -{ -	/* -	 * Set register CLK48CTL to enable and 48MHz -	 */ -	outl(0x00000003, PCI_BASE | 0x0004770c); - -	/* -	 * Set register CLK12CTL to enable and 48MHz -	 */ -	outl(0x00000003, PCI_BASE | 0x00047710); - -	udelay(100); -} - -static void pnx8550_stop_hc(struct platform_device *dev) -{ -	udelay(10); -} - - -/*-------------------------------------------------------------------------*/ - -/* configure so an HC device and id are always provided */ -/* always called with process context; sleeping is OK */ - - -/** - * usb_hcd_pnx8550_probe - initialize pnx8550-based HCDs - * Context: !in_interrupt() - * - * Allocates basic resources for this USB host controller, and - * then invokes the start() method for the HCD associated with it - * through the hotplug entry's driver_data. - * - */ -int usb_hcd_pnx8550_probe (const struct hc_driver *driver, -			  struct platform_device *dev) -{ -	int retval; -	struct usb_hcd *hcd; - -	if (dev->resource[0].flags != IORESOURCE_MEM || -			dev->resource[1].flags != IORESOURCE_IRQ) { -		dev_err (&dev->dev,"invalid resource type\n"); -		return -ENOMEM; -	} - -	hcd = usb_create_hcd (driver, &dev->dev, "pnx8550"); -	if (!hcd) -		return -ENOMEM; -	hcd->rsrc_start = dev->resource[0].start; -	hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; - -	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { -		dev_err(&dev->dev, "request_mem_region [0x%08llx, 0x%08llx] " -				"failed\n", hcd->rsrc_start, hcd->rsrc_len); -		retval = -EBUSY; -		goto err1; -	} - -	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); -	if (!hcd->regs) { -		dev_err(&dev->dev, "ioremap [[0x%08llx, 0x%08llx] failed\n", -				hcd->rsrc_start, hcd->rsrc_len); -		retval = -ENOMEM; -		goto err2; -	} - -	pnx8550_start_hc(dev); - -	ohci_hcd_init(hcd_to_ohci(hcd)); - -	retval = usb_add_hcd(hcd, dev->resource[1].start, 0); -	if (retval == 0) -		return retval; - -	pnx8550_stop_hc(dev); -	iounmap(hcd->regs); - err2: -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - err1: -	usb_put_hcd(hcd); -	return retval; -} - - -/* may be called without controller electrically present */ -/* may be called with controller, bus, and devices active */ - -/** - * usb_hcd_pnx8550_remove - shutdown processing for pnx8550-based HCDs - * @dev: USB Host Controller being removed - * Context: !in_interrupt() - * - * Reverses the effect of usb_hcd_pnx8550_probe(), first invoking - * the HCD's stop() method.  It is always called from a thread - * context, normally "rmmod", "apmd", or something similar. - * - */ -void usb_hcd_pnx8550_remove (struct usb_hcd *hcd, struct platform_device *dev) -{ -	usb_remove_hcd(hcd); -	pnx8550_stop_hc(dev); -	iounmap(hcd->regs); -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -	usb_put_hcd(hcd); -} - -/*-------------------------------------------------------------------------*/ - -static int __devinit -ohci_pnx8550_start (struct usb_hcd *hcd) -{ -	struct ohci_hcd	*ohci = hcd_to_ohci (hcd); -	int		ret; - -	ohci_dbg (ohci, "ohci_pnx8550_start, ohci:%p", ohci); - -	if ((ret = ohci_init(ohci)) < 0) -		return ret; - -	if ((ret = ohci_run (ohci)) < 0) { -		dev_err(hcd->self.controller, "can't start %s", -			hcd->self.bus_name); -		ohci_stop (hcd); -		return ret; -	} - -	return 0; -} - -/*-------------------------------------------------------------------------*/ - -static const struct hc_driver ohci_pnx8550_hc_driver = { -	.description =		hcd_name, -	.product_desc =		"PNX8550 OHCI", -	.hcd_priv_size =	sizeof(struct ohci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq =			ohci_irq, -	.flags =		HCD_USB11 | HCD_MEMORY, - -	/* -	 * basic lifecycle operations -	 */ -	.start =		ohci_pnx8550_start, -	.stop =			ohci_stop, - -	/* -	 * managing i/o requests and associated device resources -	 */ -	.urb_enqueue =		ohci_urb_enqueue, -	.urb_dequeue =		ohci_urb_dequeue, -	.endpoint_disable =	ohci_endpoint_disable, - -	/* -	 * scheduling support -	 */ -	.get_frame_number =	ohci_get_frame, - -	/* -	 * root hub support -	 */ -	.hub_status_data =	ohci_hub_status_data, -	.hub_control =		ohci_hub_control, -#ifdef	CONFIG_PM -	.bus_suspend =		ohci_bus_suspend, -	.bus_resume =		ohci_bus_resume, -#endif -	.start_port_reset =	ohci_start_port_reset, -}; - -/*-------------------------------------------------------------------------*/ - -static int ohci_hcd_pnx8550_drv_probe(struct platform_device *pdev) -{ -	int ret; - -	if (usb_disabled()) -		return -ENODEV; - -	ret = usb_hcd_pnx8550_probe(&ohci_pnx8550_hc_driver, pdev); -	return ret; -} - -static int ohci_hcd_pnx8550_drv_remove(struct platform_device *pdev) -{ -	struct usb_hcd *hcd = platform_get_drvdata(pdev); - -	usb_hcd_pnx8550_remove(hcd, pdev); -	return 0; -} - -MODULE_ALIAS("platform:pnx8550-ohci"); - -static struct platform_driver ohci_hcd_pnx8550_driver = { -	.driver = { -		.name	= "pnx8550-ohci", -		.owner	= THIS_MODULE, -	}, -	.probe		= ohci_hcd_pnx8550_drv_probe, -	.remove		= ohci_hcd_pnx8550_drv_remove, -}; - diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index e27d5ae2b9e..64c2ed9ff95 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -19,7 +19,7 @@  #include <asm/prom.h> -static int __devinit +static int  ohci_ppc_of_start(struct usb_hcd *hcd)  {  	struct ohci_hcd	*ohci = hcd_to_ohci(hcd); @@ -81,7 +81,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = {  }; -static int __devinit ohci_hcd_ppc_of_probe(struct platform_device *op) +static int ohci_hcd_ppc_of_probe(struct platform_device *op)  {  	struct device_node *dn = op->dev.of_node;  	struct usb_hcd *hcd; diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c deleted file mode 100644 index 185c39ed81b..00000000000 --- a/drivers/usb/host/ohci-ppc-soc.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> - * (C) Copyright 2002 Hewlett-Packard Company - * (C) Copyright 2003-2005 MontaVista Software Inc. - * - * Bus Glue for PPC On-Chip OHCI driver - * Tested on Freescale MPC5200 and IBM STB04xxx - * - * Modified by Dale Farnsworth <dale@farnsworth.org> from ohci-sa1111.c - * - * This file is licenced under the GPL. - */ - -#include <linux/platform_device.h> -#include <linux/signal.h> - -/* configure so an HC device and id are always provided */ -/* always called with process context; sleeping is OK */ - -/** - * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs - * Context: !in_interrupt() - * - * Allocates basic resources for this USB host controller. - * - * Store this function in the HCD's struct pci_driver as probe(). - */ -static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver, -			  struct platform_device *pdev) -{ -	int retval; -	struct usb_hcd *hcd; -	struct ohci_hcd	*ohci; -	struct resource *res; -	int irq; - -	pr_debug("initializing PPC-SOC USB Controller\n"); - -	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -	if (!res) { -		pr_debug("%s: no irq\n", __FILE__); -		return -ENODEV; -	} -	irq = res->start; - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		pr_debug("%s: no reg addr\n", __FILE__); -		return -ENODEV; -	} - -	hcd = usb_create_hcd(driver, &pdev->dev, "PPC-SOC USB"); -	if (!hcd) -		return -ENOMEM; -	hcd->rsrc_start = res->start; -	hcd->rsrc_len = resource_size(res); - -	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { -		pr_debug("%s: request_mem_region failed\n", __FILE__); -		retval = -EBUSY; -		goto err1; -	} - -	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); -	if (!hcd->regs) { -		pr_debug("%s: ioremap failed\n", __FILE__); -		retval = -ENOMEM; -		goto err2; -	} - -	ohci = hcd_to_ohci(hcd); -	ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; - -#ifdef CONFIG_PPC_MPC52xx -	/* MPC52xx doesn't need frame_no shift */ -	ohci->flags |= OHCI_QUIRK_FRAME_NO; -#endif -	ohci_hcd_init(ohci); - -	retval = usb_add_hcd(hcd, irq, 0); -	if (retval == 0) -		return retval; - -	pr_debug("Removing PPC-SOC USB Controller\n"); - -	iounmap(hcd->regs); - err2: -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - err1: -	usb_put_hcd(hcd); -	return retval; -} - - -/* may be called without controller electrically present */ -/* may be called with controller, bus, and devices active */ - -/** - * usb_hcd_ppc_soc_remove - shutdown processing for On-Chip HCDs - * @pdev: USB Host Controller being removed - * Context: !in_interrupt() - * - * Reverses the effect of usb_hcd_ppc_soc_probe(). - * It is always called from a thread - * context, normally "rmmod", "apmd", or something similar. - * - */ -static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd, -		struct platform_device *pdev) -{ -	usb_remove_hcd(hcd); - -	pr_debug("stopping PPC-SOC USB Controller\n"); - -	iounmap(hcd->regs); -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -	usb_put_hcd(hcd); -} - -static int __devinit -ohci_ppc_soc_start(struct usb_hcd *hcd) -{ -	struct ohci_hcd	*ohci = hcd_to_ohci(hcd); -	int		ret; - -	if ((ret = ohci_init(ohci)) < 0) -		return ret; - -	if ((ret = ohci_run(ohci)) < 0) { -		dev_err(hcd->self.controller, "can't start %s\n", -			hcd->self.bus_name); -		ohci_stop(hcd); -		return ret; -	} - -	return 0; -} - -static const struct hc_driver ohci_ppc_soc_hc_driver = { -	.description =		hcd_name, -	.hcd_priv_size =	sizeof(struct ohci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq =			ohci_irq, -	.flags =		HCD_USB11 | HCD_MEMORY, - -	/* -	 * basic lifecycle operations -	 */ -	.start =		ohci_ppc_soc_start, -	.stop =			ohci_stop, -	.shutdown =		ohci_shutdown, - -	/* -	 * managing i/o requests and associated device resources -	 */ -	.urb_enqueue =		ohci_urb_enqueue, -	.urb_dequeue =		ohci_urb_dequeue, -	.endpoint_disable =	ohci_endpoint_disable, - -	/* -	 * scheduling support -	 */ -	.get_frame_number =	ohci_get_frame, - -	/* -	 * root hub support -	 */ -	.hub_status_data =	ohci_hub_status_data, -	.hub_control =		ohci_hub_control, -#ifdef	CONFIG_PM -	.bus_suspend =		ohci_bus_suspend, -	.bus_resume =		ohci_bus_resume, -#endif -	.start_port_reset =	ohci_start_port_reset, -}; - -static int ohci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) -{ -	int ret; - -	if (usb_disabled()) -		return -ENODEV; - -	ret = usb_hcd_ppc_soc_probe(&ohci_ppc_soc_hc_driver, pdev); -	return ret; -} - -static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev) -{ -	struct usb_hcd *hcd = platform_get_drvdata(pdev); - -	usb_hcd_ppc_soc_remove(hcd, pdev); -	return 0; -} - -static struct platform_driver ohci_hcd_ppc_soc_driver = { -	.probe		= ohci_hcd_ppc_soc_drv_probe, -	.remove		= ohci_hcd_ppc_soc_drv_remove, -	.shutdown	= usb_hcd_platform_shutdown, -#ifdef	CONFIG_PM -	/*.suspend	= ohci_hcd_ppc_soc_drv_suspend,*/ -	/*.resume	= ohci_hcd_ppc_soc_drv_resume,*/ -#endif -	.driver		= { -		.name	= "ppc-soc-ohci", -		.owner	= THIS_MODULE, -	}, -}; - -MODULE_ALIAS("platform:ppc-soc-ohci"); diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c index 2ee1d8d713d..7d35cd9e286 100644 --- a/drivers/usb/host/ohci-ps3.c +++ b/drivers/usb/host/ohci-ps3.c @@ -30,7 +30,7 @@ static int ps3_ohci_hc_reset(struct usb_hcd *hcd)  	return ohci_init(ohci);  } -static int __devinit ps3_ohci_hc_start(struct usb_hcd *hcd) +static int ps3_ohci_hc_start(struct usb_hcd *hcd)  {  	int result;  	struct ohci_hcd *ohci = hcd_to_ohci(hcd); @@ -76,7 +76,7 @@ static const struct hc_driver ps3_ohci_hc_driver = {  #endif  }; -static int __devinit ps3_ohci_probe(struct ps3_system_bus_device *dev) +static int ps3_ohci_probe(struct ps3_system_bus_device *dev)  {  	int result;  	struct usb_hcd *hcd; diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 2bf11440b01..efe71f3ca47 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -284,7 +284,7 @@ MODULE_DEVICE_TABLE(of, pxa_ohci_dt_ids);  static u64 pxa_ohci_dma_mask = DMA_BIT_MASK(32); -static int __devinit ohci_pxa_of_init(struct platform_device *pdev) +static int ohci_pxa_of_init(struct platform_device *pdev)  {  	struct device_node *np = pdev->dev.of_node;  	struct pxaohci_platform_data *pdata; @@ -330,7 +330,7 @@ static int __devinit ohci_pxa_of_init(struct platform_device *pdev)  	return 0;  }  #else -static int __devinit ohci_pxa_of_init(struct platform_device *pdev) +static int ohci_pxa_of_init(struct platform_device *pdev)  {  	return 0;  } @@ -471,7 +471,7 @@ void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)  /*-------------------------------------------------------------------------*/ -static int __devinit +static int  ohci_pxa27x_start (struct usb_hcd *hcd)  {  	struct ohci_hcd	*ohci = hcd_to_ohci (hcd); @@ -591,7 +591,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct device *dev)  	/* Select Power Management Mode */  	pxa27x_ohci_select_pmm(ohci, inf->port_mode); -	ohci_finish_controller_resume(hcd); +	ohci_resume(hcd, false);  	return 0;  } diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index c5a1ea9145f..7482cfbe8c5 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -596,7 +596,6 @@ static void td_submit_urb (  		urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C);  	} -	urb_priv->td_cnt = 0;  	list_add (&urb_priv->pending, &ohci->pending);  	if (data_len) @@ -672,7 +671,8 @@ static void td_submit_urb (  	 * we could often reduce the number of TDs here.  	 */  	case PIPE_ISOCHRONOUS: -		for (cnt = 0; cnt < urb->number_of_packets; cnt++) { +		for (cnt = urb_priv->td_cnt; cnt < urb->number_of_packets; +				cnt++) {  			int	frame = urb->start_frame;  			// FIXME scheduling should handle frame counter @@ -1128,6 +1128,25 @@ dl_done_list (struct ohci_hcd *ohci)  	while (td) {  		struct td	*td_next = td->next_dl_td; +		struct ed	*ed = td->ed; + +		/* +		 * Some OHCI controllers (NVIDIA for sure, maybe others) +		 * occasionally forget to add TDs to the done queue.  Since +		 * TDs for a given endpoint are always processed in order, +		 * if we find a TD on the donelist then all of its +		 * predecessors must be finished as well. +		 */ +		for (;;) { +			struct td	*td2; + +			td2 = list_first_entry(&ed->td_list, struct td, +					td_list); +			if (td2 == td) +				break; +			takeback_td(ohci, td2); +		} +  		takeback_td(ohci, td);  		td = td_next;  	} diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 0d2309ca471..ad0f5526960 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -323,8 +323,6 @@ usb_hcd_s3c2410_remove(struct usb_hcd *hcd, struct platform_device *dev)  {  	usb_remove_hcd(hcd);  	s3c2410_stop_hc(dev); -	iounmap(hcd->regs); -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);  	usb_put_hcd(hcd);  } @@ -353,35 +351,29 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,  	hcd->rsrc_start = dev->resource[0].start;  	hcd->rsrc_len	= resource_size(&dev->resource[0]); -	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { -		dev_err(&dev->dev, "request_mem_region failed\n"); -		retval = -EBUSY; +	hcd->regs = devm_request_and_ioremap(&dev->dev, &dev->resource[0]); +	if (!hcd->regs) { +		dev_err(&dev->dev, "devm_request_and_ioremap failed\n"); +		retval = -ENOMEM;  		goto err_put;  	} -	clk = clk_get(&dev->dev, "usb-host"); +	clk = devm_clk_get(&dev->dev, "usb-host");  	if (IS_ERR(clk)) {  		dev_err(&dev->dev, "cannot get usb-host clock\n");  		retval = PTR_ERR(clk); -		goto err_mem; +		goto err_put;  	} -	usb_clk = clk_get(&dev->dev, "usb-bus-host"); +	usb_clk = devm_clk_get(&dev->dev, "usb-bus-host");  	if (IS_ERR(usb_clk)) {  		dev_err(&dev->dev, "cannot get usb-bus-host clock\n");  		retval = PTR_ERR(usb_clk); -		goto err_clk; +		goto err_put;  	}  	s3c2410_start_hc(dev, hcd); -	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); -	if (!hcd->regs) { -		dev_err(&dev->dev, "ioremap failed\n"); -		retval = -ENOMEM; -		goto err_ioremap; -	} -  	ohci_hcd_init(hcd_to_ohci(hcd));  	retval = usb_add_hcd(hcd, dev->resource[1].start, 0); @@ -392,14 +384,6 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,   err_ioremap:  	s3c2410_stop_hc(dev); -	iounmap(hcd->regs); -	clk_put(usb_clk); - - err_clk: -	clk_put(clk); - - err_mem: -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);   err_put:  	usb_put_hcd(hcd); @@ -474,12 +458,12 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {  /* device driver */ -static int __devinit ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev) +static int ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev)  {  	return usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev);  } -static int __devexit ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev) +static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev); @@ -524,8 +508,7 @@ static int ohci_hcd_s3c2410_drv_resume(struct device *dev)  	s3c2410_start_hc(pdev, hcd); -	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); -	ohci_finish_controller_resume(hcd); +	ohci_resume(hcd, false);  	return 0;  } @@ -541,7 +524,7 @@ static const struct dev_pm_ops ohci_hcd_s3c2410_pm_ops = {  static struct platform_driver ohci_hcd_s3c2410_driver = {  	.probe		= ohci_hcd_s3c2410_drv_probe, -	.remove		= __devexit_p(ohci_hcd_s3c2410_drv_remove), +	.remove		= ohci_hcd_s3c2410_drv_remove,  	.shutdown	= usb_hcd_platform_shutdown,  	.driver		= {  		.owner	= THIS_MODULE, diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index b6cc9252092..17b2a7dad77 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c @@ -63,7 +63,7 @@ static int ohci_sa1111_reset(struct usb_hcd *hcd)  	return ohci_init(ohci);  } -static int __devinit ohci_sa1111_start(struct usb_hcd *hcd) +static int ohci_sa1111_start(struct usb_hcd *hcd)  {  	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);  	int ret; diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c deleted file mode 100644 index 76a20c27836..00000000000 --- a/drivers/usb/host/ohci-sh.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * Copyright (C) 2008 Renesas Solutions Corp. - * - * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA - * - */ - -#include <linux/platform_device.h> - -static int ohci_sh_start(struct usb_hcd *hcd) -{ -	struct ohci_hcd	*ohci = hcd_to_ohci(hcd); - -	ohci_hcd_init(ohci); -	ohci_init(ohci); -	ohci_run(ohci); -	return 0; -} - -static const struct hc_driver ohci_sh_hc_driver = { -	.description =		hcd_name, -	.product_desc =		"SuperH OHCI", -	.hcd_priv_size =	sizeof(struct ohci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq =			ohci_irq, -	.flags =		HCD_USB11 | HCD_MEMORY, - -	/* -	 * basic lifecycle operations -	 */ -	.start =		ohci_sh_start, -	.stop =			ohci_stop, -	.shutdown =		ohci_shutdown, - -	/* -	 * managing i/o requests and associated device resources -	 */ -	.urb_enqueue =		ohci_urb_enqueue, -	.urb_dequeue =		ohci_urb_dequeue, -	.endpoint_disable =	ohci_endpoint_disable, - -	/* -	 * scheduling support -	 */ -	.get_frame_number =	ohci_get_frame, - -	/* -	 * root hub support -	 */ -	.hub_status_data =	ohci_hub_status_data, -	.hub_control =		ohci_hub_control, -#ifdef	CONFIG_PM -	.bus_suspend =		ohci_bus_suspend, -	.bus_resume =		ohci_bus_resume, -#endif -	.start_port_reset =	ohci_start_port_reset, -}; - -/*-------------------------------------------------------------------------*/ - -static int ohci_hcd_sh_probe(struct platform_device *pdev) -{ -	struct resource *res = NULL; -	struct usb_hcd *hcd = NULL; -	int irq = -1; -	int ret; - -	if (usb_disabled()) -		return -ENODEV; - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(&pdev->dev, "platform_get_resource error.\n"); -		return -ENODEV; -	} - -	irq = platform_get_irq(pdev, 0); -	if (irq < 0) { -		dev_err(&pdev->dev, "platform_get_irq error.\n"); -		return -ENODEV; -	} - -	/* initialize hcd */ -	hcd = usb_create_hcd(&ohci_sh_hc_driver, &pdev->dev, (char *)hcd_name); -	if (!hcd) { -		dev_err(&pdev->dev, "Failed to create hcd\n"); -		return -ENOMEM; -	} - -	hcd->regs = (void __iomem *)res->start; -	hcd->rsrc_start = res->start; -	hcd->rsrc_len = resource_size(res); -	ret = usb_add_hcd(hcd, irq, IRQF_SHARED); -	if (ret != 0) { -		dev_err(&pdev->dev, "Failed to add hcd\n"); -		usb_put_hcd(hcd); -		return ret; -	} - -	return ret; -} - -static int ohci_hcd_sh_remove(struct platform_device *pdev) -{ -	struct usb_hcd *hcd = platform_get_drvdata(pdev); - -	usb_remove_hcd(hcd); -	usb_put_hcd(hcd); - -	return 0; -} - -static struct platform_driver ohci_hcd_sh_driver = { -	.probe		= ohci_hcd_sh_probe, -	.remove		= ohci_hcd_sh_remove, -	.shutdown	= usb_hcd_platform_shutdown, -	.driver		= { -		.name	= "sh_ohci", -		.owner	= THIS_MODULE, -	}, -}; - -MODULE_ALIAS("platform:sh_ohci"); diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index 5596ac2ba1c..3b5b908fd47 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -238,7 +238,7 @@ static int ohci_sm501_resume(struct platform_device *pdev)  	ohci->next_statechange = jiffies;  	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1); -	ohci_finish_controller_resume(hcd); +	ohci_resume(hcd, false);  	return 0;  }  #else diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c index fc7305ee3c9..9020bf0e2ec 100644 --- a/drivers/usb/host/ohci-spear.c +++ b/drivers/usb/host/ohci-spear.c @@ -33,7 +33,7 @@ static void spear_stop_ohci(struct spear_ohci *ohci)  	clk_disable_unprepare(ohci->clk);  } -static int __devinit ohci_spear_start(struct usb_hcd *hcd) +static int ohci_spear_start(struct usb_hcd *hcd)  {  	struct ohci_hcd *ohci = hcd_to_ohci(hcd);  	int ret; @@ -101,13 +101,11 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)  	struct spear_ohci *ohci_p;  	struct resource *res;  	int retval, irq; -	char clk_name[20] = "usbh_clk"; -	static int instance = -1;  	irq = platform_get_irq(pdev, 0);  	if (irq < 0) {  		retval = irq; -		goto fail_irq_get; +		goto fail;  	}  	/* @@ -118,47 +116,39 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)  	if (!pdev->dev.dma_mask)  		pdev->dev.dma_mask = &spear_ohci_dma_mask; -	/* -	 * Increment the device instance, when probing via device-tree -	 */ -	if (pdev->id < 0) -		instance++; -	else -		instance = pdev->id; -	sprintf(clk_name, "usbh.%01d_clk", instance); - -	usbh_clk = clk_get(NULL, clk_name); +	usbh_clk = devm_clk_get(&pdev->dev, NULL);  	if (IS_ERR(usbh_clk)) {  		dev_err(&pdev->dev, "Error getting interface clock\n");  		retval = PTR_ERR(usbh_clk); -		goto fail_get_usbh_clk; +		goto fail;  	}  	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));  	if (!hcd) {  		retval = -ENOMEM; -		goto fail_create_hcd; +		goto fail;  	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) {  		retval = -ENODEV; -		goto fail_request_resource; +		goto err_put_hcd;  	}  	hcd->rsrc_start = pdev->resource[0].start;  	hcd->rsrc_len = resource_size(res); -	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { +	if (!devm_request_mem_region(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len, +				hcd_name)) {  		dev_dbg(&pdev->dev, "request_mem_region failed\n");  		retval = -EBUSY; -		goto fail_request_resource; +		goto err_put_hcd;  	} -	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); +	hcd->regs = devm_ioremap(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len);  	if (!hcd->regs) {  		dev_dbg(&pdev->dev, "ioremap failed\n");  		retval = -ENOMEM; -		goto fail_ioremap; +		goto err_put_hcd;  	}  	ohci_p = (struct spear_ohci *)hcd_to_ohci(hcd); @@ -171,15 +161,9 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)  		return retval;  	spear_stop_ohci(ohci_p); -	iounmap(hcd->regs); -fail_ioremap: -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -fail_request_resource: +err_put_hcd:  	usb_put_hcd(hcd); -fail_create_hcd: -	clk_put(usbh_clk); -fail_get_usbh_clk: -fail_irq_get: +fail:  	dev_err(&pdev->dev, "init fail, %d\n", retval);  	return retval; @@ -194,12 +178,8 @@ static int spear_ohci_hcd_drv_remove(struct platform_device *pdev)  	if (ohci_p->clk)  		spear_stop_ohci(ohci_p); -	iounmap(hcd->regs); -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);  	usb_put_hcd(hcd); -	if (ohci_p->clk) -		clk_put(ohci_p->clk);  	platform_set_drvdata(pdev, NULL);  	return 0;  } @@ -231,12 +211,12 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev)  	ohci->next_statechange = jiffies;  	spear_start_ohci(ohci_p); -	ohci_finish_controller_resume(hcd); +	ohci_resume(hcd, false);  	return 0;  }  #endif -static struct of_device_id spear_ohci_id_table[] __devinitdata = { +static struct of_device_id spear_ohci_id_table[] = {  	{ .compatible = "st,spear600-ohci", },  	{ },  }; diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index 60c2b0722f2..d370245a4ee 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c @@ -184,7 +184,7 @@ static const struct hc_driver ohci_tmio_hc_driver = {  /*-------------------------------------------------------------------------*/  static struct platform_driver ohci_hcd_tmio_driver; -static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev) +static int ohci_hcd_tmio_drv_probe(struct platform_device *dev)  {  	const struct mfd_cell *cell = mfd_get_cell(dev);  	struct resource *regs = platform_get_resource(dev, IORESOURCE_MEM, 0); @@ -271,7 +271,7 @@ err_usb_create_hcd:  	return ret;  } -static int __devexit ohci_hcd_tmio_drv_remove(struct platform_device *dev) +static int ohci_hcd_tmio_drv_remove(struct platform_device *dev)  {  	struct usb_hcd *hcd = platform_get_drvdata(dev);  	struct tmio_hcd *tmio = hcd_to_tmio(hcd); @@ -352,7 +352,7 @@ static int ohci_hcd_tmio_drv_resume(struct platform_device *dev)  	spin_unlock_irqrestore(&tmio->lock, flags); -	ohci_finish_controller_resume(hcd); +	ohci_resume(hcd, false);  	return 0;  } @@ -363,7 +363,7 @@ static int ohci_hcd_tmio_drv_resume(struct platform_device *dev)  static struct platform_driver ohci_hcd_tmio_driver = {  	.probe		= ohci_hcd_tmio_drv_probe, -	.remove		= __devexit_p(ohci_hcd_tmio_drv_remove), +	.remove		= ohci_hcd_tmio_drv_remove,  	.shutdown	= usb_hcd_platform_shutdown,  	.suspend	= ohci_hcd_tmio_drv_suspend,  	.resume		= ohci_hcd_tmio_drv_resume, diff --git a/drivers/usb/host/ohci-xls.c b/drivers/usb/host/ohci-xls.c deleted file mode 100644 index 41e378f17c6..00000000000 --- a/drivers/usb/host/ohci-xls.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * OHCI HCD for Netlogic XLS processors. - * - * (C) Copyright 2011 Netlogic Microsystems Inc. - * - *  Based on ohci-au1xxx.c, and other Linux OHCI drivers. - * - * This file is subject to the terms and conditions of the GNU General Public - * License.  See the file COPYING in the main directory of this archive for - * more details. - */ - -#include <linux/platform_device.h> -#include <linux/signal.h> - -static int ohci_xls_probe_internal(const struct hc_driver *driver, -			struct platform_device *dev) -{ -	struct resource *res; -	struct usb_hcd *hcd; -	int retval, irq; - -	/* Get our IRQ from an earlier registered Platform Resource */ -	irq = platform_get_irq(dev, 0); -	if (irq < 0) { -		dev_err(&dev->dev, "Found HC with no IRQ\n"); -		return -ENODEV; -	} - -	/* Get our Memory Handle */ -	res = platform_get_resource(dev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(&dev->dev, "MMIO Handle incorrect!\n"); -		return -ENODEV; -	} - -	hcd = usb_create_hcd(driver, &dev->dev, "XLS"); -	if (!hcd) { -		retval = -ENOMEM; -		goto err1; -	} -	hcd->rsrc_start = res->start; -	hcd->rsrc_len = resource_size(res); - -	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, -			driver->description)) { -		dev_dbg(&dev->dev, "Controller already in use\n"); -		retval = -EBUSY; -		goto err2; -	} - -	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); -	if (hcd->regs == NULL) { -		dev_dbg(&dev->dev, "error mapping memory\n"); -		retval = -EFAULT; -		goto err3; -	} - -	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); -	if (retval != 0) -		goto err4; -	return retval; - -err4: -	iounmap(hcd->regs); -err3: -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err2: -	usb_put_hcd(hcd); -err1: -	dev_err(&dev->dev, "init fail, %d\n", retval); -	return retval; -} - -static int ohci_xls_reset(struct usb_hcd *hcd) -{ -	struct ohci_hcd *ohci = hcd_to_ohci(hcd); - -	ohci_hcd_init(ohci); -	return ohci_init(ohci); -} - -static int __devinit ohci_xls_start(struct usb_hcd *hcd) -{ -	struct ohci_hcd *ohci; -	int ret; - -	ohci = hcd_to_ohci(hcd); -	ret = ohci_run(ohci); -	if (ret < 0) { -		dev_err(hcd->self.controller, "can't start %s\n", -			hcd->self.bus_name); -		ohci_stop(hcd); -		return ret; -	} -	return 0; -} - -static struct hc_driver ohci_xls_hc_driver = { -	.description	= hcd_name, -	.product_desc	= "XLS OHCI Host Controller", -	.hcd_priv_size	= sizeof(struct ohci_hcd), -	.irq		= ohci_irq, -	.flags		= HCD_MEMORY | HCD_USB11, -	.reset		= ohci_xls_reset, -	.start		= ohci_xls_start, -	.stop		= ohci_stop, -	.shutdown	= ohci_shutdown, -	.urb_enqueue	= ohci_urb_enqueue, -	.urb_dequeue	= ohci_urb_dequeue, -	.endpoint_disable = ohci_endpoint_disable, -	.get_frame_number = ohci_get_frame, -	.hub_status_data = ohci_hub_status_data, -	.hub_control	= ohci_hub_control, -#ifdef CONFIG_PM -	.bus_suspend	= ohci_bus_suspend, -	.bus_resume	= ohci_bus_resume, -#endif -	.start_port_reset = ohci_start_port_reset, -}; - -static int ohci_xls_probe(struct platform_device *dev) -{ -	int ret; - -	pr_debug("In ohci_xls_probe"); -	if (usb_disabled()) -		return -ENODEV; -	ret = ohci_xls_probe_internal(&ohci_xls_hc_driver, dev); -	return ret; -} - -static int ohci_xls_remove(struct platform_device *dev) -{ -	struct usb_hcd *hcd = platform_get_drvdata(dev); - -	usb_remove_hcd(hcd); -	iounmap(hcd->regs); -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -	usb_put_hcd(hcd); -	return 0; -} - -static struct platform_driver ohci_xls_driver = { -	.probe		= ohci_xls_probe, -	.remove		= ohci_xls_remove, -	.shutdown	= usb_hcd_platform_shutdown, -	.driver		= { -		.name	= "ohci-xls-0", -		.owner	= THIS_MODULE, -	}, -}; diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 39f9e4a9a2d..a3b6d7104ae 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -443,7 +443,7 @@ static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)  #define pio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_IO)  #define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY) -static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev) +static void quirk_usb_handoff_uhci(struct pci_dev *pdev)  {  	unsigned long base = 0;  	int i; @@ -461,12 +461,12 @@ static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev)  		uhci_check_and_reset_hc(pdev, base);  } -static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx) +static int mmio_resource_enabled(struct pci_dev *pdev, int idx)  {  	return pci_resource_start(pdev, idx) && mmio_enabled(pdev);  } -static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) +static void quirk_usb_handoff_ohci(struct pci_dev *pdev)  {  	void __iomem *base;  	u32 control; @@ -533,7 +533,7 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)  	iounmap(base);  } -static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = { +static const struct dmi_system_id ehci_dmi_nohandoff_table[] = {  	{  		/*  Pegatron Lucid (ExoPC) */  		.matches = { @@ -558,7 +558,7 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {  	{ }  }; -static void __devinit ehci_bios_handoff(struct pci_dev *pdev, +static void ehci_bios_handoff(struct pci_dev *pdev,  					void __iomem *op_reg_base,  					u32 cap, u8 offset)  { @@ -626,7 +626,7 @@ static void __devinit ehci_bios_handoff(struct pci_dev *pdev,  		writel(0, op_reg_base + EHCI_CONFIGFLAG);  } -static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) +static void quirk_usb_disable_ehci(struct pci_dev *pdev)  {  	void __iomem *base, *op_reg_base;  	u32	hcc_params, cap, val; @@ -723,6 +723,7 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done,  }  #define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI	0x8C31 +#define PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI	0x9C31  bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev)  { @@ -736,7 +737,8 @@ bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev)  {  	return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&  		pdev->vendor == PCI_VENDOR_ID_INTEL && -		pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI; +		(pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI || +		 pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI);  }  bool usb_is_intel_switchable_xhci(struct pci_dev *pdev) @@ -841,7 +843,7 @@ EXPORT_SYMBOL_GPL(usb_disable_xhci_ports);   * and then waits 5 seconds for the BIOS to hand over control.   * If we timeout, assume the BIOS is broken and take control anyway.   */ -static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) +static void quirk_usb_handoff_xhci(struct pci_dev *pdev)  {  	void __iomem *base;  	int ext_cap_offset; @@ -941,7 +943,7 @@ hc_init:  	iounmap(base);  } -static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) +static void quirk_usb_early_handoff(struct pci_dev *pdev)  {  	/* Skip Netlogic mips SoC's internal PCI USB controller.  	 * This device does not need/support EHCI/OHCI handoff diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index fcc09e5ec0a..a6fd8f5371d 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2036,10 +2036,8 @@ static void collect_usb_address_map(struct usb_device *udev, unsigned long *map)  	    udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB)  		map[udev->devnum/32] |= (1 << (udev->devnum % 32)); -	usb_hub_for_each_child(udev, chix, childdev) { -		if (childdev) -			collect_usb_address_map(childdev, map); -	} +	usb_hub_for_each_child(udev, chix, childdev) +		collect_usb_address_map(childdev, map);  }  /* this function must be called with interrupt disabled */ @@ -2393,7 +2391,7 @@ static const struct dev_pm_ops r8a66597_dev_pm_ops = {  #define R8A66597_DEV_PM_OPS	NULL  #endif -static int __devexit r8a66597_remove(struct platform_device *pdev) +static int r8a66597_remove(struct platform_device *pdev)  {  	struct r8a66597		*r8a66597 = dev_get_drvdata(&pdev->dev);  	struct usb_hcd		*hcd = r8a66597_to_hcd(r8a66597); @@ -2407,7 +2405,7 @@ static int __devexit r8a66597_remove(struct platform_device *pdev)  	return 0;  } -static int __devinit r8a66597_probe(struct platform_device *pdev) +static int r8a66597_probe(struct platform_device *pdev)  {  	char clk_name[8];  	struct resource *res = NULL, *ires; @@ -2534,7 +2532,7 @@ clean_up:  static struct platform_driver r8a66597_driver = {  	.probe =	r8a66597_probe, -	.remove =	__devexit_p(r8a66597_remove), +	.remove =	r8a66597_remove,  	.driver		= {  		.name = (char *) hcd_name,  		.owner	= THIS_MODULE, diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 619b05f42d4..d62f0404baa 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -1595,7 +1595,7 @@ static struct hc_driver sl811h_hc_driver = {  /*-------------------------------------------------------------------------*/ -static int __devexit +static int  sl811h_remove(struct platform_device *dev)  {  	struct usb_hcd		*hcd = platform_get_drvdata(dev); @@ -1618,7 +1618,7 @@ sl811h_remove(struct platform_device *dev)  	return 0;  } -static int __devinit +static int  sl811h_probe(struct platform_device *dev)  {  	struct usb_hcd		*hcd; @@ -1808,7 +1808,7 @@ sl811h_resume(struct platform_device *dev)  /* this driver is exported so sl811_cs can depend on it */  struct platform_driver sl811h_driver = {  	.probe =	sl811h_probe, -	.remove =	__devexit_p(sl811h_remove), +	.remove =	sl811h_remove,  	.suspend =	sl811h_suspend,  	.resume =	sl811h_resume, diff --git a/drivers/usb/host/ssb-hcd.c b/drivers/usb/host/ssb-hcd.c index c2a29faba07..74af2c6287d 100644 --- a/drivers/usb/host/ssb-hcd.c +++ b/drivers/usb/host/ssb-hcd.c @@ -39,7 +39,7 @@ struct ssb_hcd_device {  	u32 enable_flags;  }; -static void __devinit ssb_hcd_5354wa(struct ssb_device *dev) +static void ssb_hcd_5354wa(struct ssb_device *dev)  {  #ifdef CONFIG_SSB_DRIVER_MIPS  	/* Work around for 5354 failures */ @@ -53,7 +53,7 @@ static void __devinit ssb_hcd_5354wa(struct ssb_device *dev)  #endif  } -static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev) +static void ssb_hcd_usb20wa(struct ssb_device *dev)  {  	if (dev->id.coreid == SSB_DEV_USB20_HOST) {  		/* @@ -80,7 +80,7 @@ static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev)  }  /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ -static u32 __devinit ssb_hcd_init_chip(struct ssb_device *dev) +static u32 ssb_hcd_init_chip(struct ssb_device *dev)  {  	u32 flags = 0; @@ -101,8 +101,7 @@ static const struct usb_ehci_pdata ehci_pdata = {  static const struct usb_ohci_pdata ohci_pdata = {  }; -static struct platform_device * __devinit -ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len) +static struct platform_device *ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len)  {  	struct platform_device *hci_dev;  	struct resource hci_res[2]; @@ -148,7 +147,7 @@ err_alloc:  	return ERR_PTR(ret);  } -static int __devinit ssb_hcd_probe(struct ssb_device *dev, +static int ssb_hcd_probe(struct ssb_device *dev,  				   const struct ssb_device_id *id)  {  	int err, tmp; @@ -207,7 +206,7 @@ err_free_usb_dev:  	return err;  } -static void __devexit ssb_hcd_remove(struct ssb_device *dev) +static void ssb_hcd_remove(struct ssb_device *dev)  {  	struct ssb_hcd_device *usb_dev = ssb_get_drvdata(dev);  	struct platform_device *ohci_dev = usb_dev->ohci_dev; @@ -221,7 +220,7 @@ static void __devexit ssb_hcd_remove(struct ssb_device *dev)  	ssb_device_disable(dev, 0);  } -static void __devexit ssb_hcd_shutdown(struct ssb_device *dev) +static void ssb_hcd_shutdown(struct ssb_device *dev)  {  	ssb_device_disable(dev, 0);  } @@ -249,7 +248,7 @@ static int ssb_hcd_resume(struct ssb_device *dev)  #define ssb_hcd_resume	NULL  #endif /* CONFIG_PM */ -static const struct ssb_device_id ssb_hcd_table[] __devinitconst = { +static const struct ssb_device_id ssb_hcd_table[] = {  	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),  	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),  	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), @@ -261,7 +260,7 @@ static struct ssb_driver ssb_hcd_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= ssb_hcd_table,  	.probe		= ssb_hcd_probe, -	.remove		= __devexit_p(ssb_hcd_remove), +	.remove		= ssb_hcd_remove,  	.shutdown	= ssb_hcd_shutdown,  	.suspend	= ssb_hcd_suspend,  	.resume		= ssb_hcd_resume, diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index dbbd1ba2522..5efdffe3236 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -2990,7 +2990,7 @@ static struct hc_driver u132_hc_driver = {  * synchronously - but instead should immediately stop activity to the  * device and asynchronously call usb_remove_hcd()  */ -static int __devexit u132_remove(struct platform_device *pdev) +static int u132_remove(struct platform_device *pdev)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev);  	if (hcd) { @@ -3084,7 +3084,7 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev)  	mutex_unlock(&u132->sw_lock);  } -static int __devinit u132_probe(struct platform_device *pdev) +static int u132_probe(struct platform_device *pdev)  {  	struct usb_hcd *hcd;  	int retval; @@ -3212,7 +3212,7 @@ static int u132_resume(struct platform_device *pdev)  */  static struct platform_driver u132_platform_driver = {  	.probe = u132_probe, -	.remove = __devexit_p(u132_remove), +	.remove = u132_remove,  	.suspend = u132_suspend,  	.resume = u132_resume,  	.driver = { diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c index f7a62138e3e..511bfc46dd7 100644 --- a/drivers/usb/host/uhci-grlib.c +++ b/drivers/usb/host/uhci-grlib.c @@ -85,7 +85,7 @@ static const struct hc_driver uhci_grlib_hc_driver = {  }; -static int __devinit uhci_hcd_grlib_probe(struct platform_device *op) +static int uhci_hcd_grlib_probe(struct platform_device *op)  {  	struct device_node *dn = op->dev.of_node;  	struct usb_hcd *hcd; diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c index 68ebf20e151..8c4dace4b14 100644 --- a/drivers/usb/host/uhci-platform.c +++ b/drivers/usb/host/uhci-platform.c @@ -62,7 +62,7 @@ static const struct hc_driver uhci_platform_hc_driver = {  static u64 platform_uhci_dma_mask = DMA_BIT_MASK(32); -static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev) +static int uhci_hcd_platform_probe(struct platform_device *pdev)  {  	struct usb_hcd *hcd;  	struct uhci_hcd	*uhci; diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index d2c6f5ac462..15921fd5504 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -1256,7 +1256,8 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,  		struct uhci_qh *qh)  {  	struct uhci_td *td = NULL;	/* Since urb->number_of_packets > 0 */ -	int i, frame; +	int i; +	unsigned frame, next;  	unsigned long destination, status;  	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; @@ -1265,37 +1266,29 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,  			urb->number_of_packets >= UHCI_NUMFRAMES)  		return -EFBIG; +	uhci_get_current_frame_number(uhci); +  	/* Check the period and figure out the starting frame number */  	if (!qh->bandwidth_reserved) {  		qh->period = urb->interval; -		if (urb->transfer_flags & URB_ISO_ASAP) { -			qh->phase = -1;		/* Find the best phase */ -			i = uhci_check_bandwidth(uhci, qh); -			if (i) -				return i; - -			/* Allow a little time to allocate the TDs */ -			uhci_get_current_frame_number(uhci); -			frame = uhci->frame_number + 10; - -			/* Move forward to the first frame having the -			 * correct phase */ -			urb->start_frame = frame + ((qh->phase - frame) & -					(qh->period - 1)); -		} else { -			i = urb->start_frame - uhci->last_iso_frame; -			if (i <= 0 || i >= UHCI_NUMFRAMES) -				return -EINVAL; -			qh->phase = urb->start_frame & (qh->period - 1); -			i = uhci_check_bandwidth(uhci, qh); -			if (i) -				return i; -		} +		qh->phase = -1;		/* Find the best phase */ +		i = uhci_check_bandwidth(uhci, qh); +		if (i) +			return i; + +		/* Allow a little time to allocate the TDs */ +		next = uhci->frame_number + 10; +		frame = qh->phase; + +		/* Round up to the first available slot */ +		frame += (next - frame + qh->period - 1) & -qh->period;  	} else if (qh->period != urb->interval) {  		return -EINVAL;		/* Can't change the period */  	} else { +		next = uhci->frame_number + 2; +  		/* Find the next unused frame */  		if (list_empty(&qh->queue)) {  			frame = qh->iso_frame; @@ -1308,25 +1301,31 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,  					lurb->number_of_packets *  					lurb->interval;  		} -		if (urb->transfer_flags & URB_ISO_ASAP) { -			/* Skip some frames if necessary to insure -			 * the start frame is in the future. + +		/* Fell behind? */ +		if (uhci_frame_before_eq(frame, next)) { + +			/* USB_ISO_ASAP: Round up to the first available slot */ +			if (urb->transfer_flags & URB_ISO_ASAP) +				frame += (next - frame + qh->period - 1) & +						-qh->period; + +			/* +			 * Not ASAP: Use the next slot in the stream.  If +			 * the entire URB falls before the threshold, fail.  			 */ -			uhci_get_current_frame_number(uhci); -			if (uhci_frame_before_eq(frame, uhci->frame_number)) { -				frame = uhci->frame_number + 1; -				frame += ((qh->phase - frame) & -					(qh->period - 1)); -			} -		}	/* Otherwise pick up where the last URB leaves off */ -		urb->start_frame = frame; +			else if (!uhci_frame_before_eq(next, +					frame + (urb->number_of_packets - 1) * +						qh->period)) +				return -EXDEV; +		}  	}  	/* Make sure we won't have to go too far into the future */  	if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES, -			urb->start_frame + urb->number_of_packets * -				urb->interval)) +			frame + urb->number_of_packets * urb->interval))  		return -EFBIG; +	urb->start_frame = frame;  	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;  	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 487bc083dea..fb51c7085ad 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -205,7 +205,12 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,  		next = xhci_segment_alloc(xhci, cycle_state, flags);  		if (!next) { -			xhci_free_segments_for_ring(xhci, *first); +			prev = *first; +			while (prev) { +				next = prev->next; +				xhci_segment_free(xhci, prev); +				prev = next; +			}  			return -ENOMEM;  		}  		xhci_link_segments(xhci, prev, next, type); @@ -258,7 +263,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,  	return ring;  fail: -	xhci_ring_free(xhci, ring); +	kfree(ring);  	return NULL;  } diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 8345d7c2306..af259e0ec17 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -29,6 +29,7 @@  /* Device for a quirk */  #define PCI_VENDOR_ID_FRESCO_LOGIC	0x1b73  #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK	0x1000 +#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400	0x1400  #define PCI_VENDOR_ID_ETRON		0x1b6f  #define PCI_DEVICE_ID_ASROCK_P67	0x7023 @@ -58,8 +59,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)  	/* Look for vendor-specific quirks */  	if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && -			pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK) { -		if (pdev->revision == 0x0) { +			(pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK || +			 pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1400)) { +		if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK && +				pdev->revision == 0x0) {  			xhci->quirks |= XHCI_RESET_EP_QUIRK;  			xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"  					" endpoint cmd after reset endpoint\n"); @@ -218,15 +221,8 @@ static void xhci_pci_remove(struct pci_dev *dev)  static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)  {  	struct xhci_hcd	*xhci = hcd_to_xhci(hcd); -	int	retval = 0; -	if (hcd->state != HC_STATE_SUSPENDED || -			xhci->shared_hcd->state != HC_STATE_SUSPENDED) -		return -EINVAL; - -	retval = xhci_suspend(xhci); - -	return retval; +	return xhci_suspend(xhci);  }  static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 4e1a8946b8d..cbb44b7b9d6 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -318,7 +318,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)  	 * seconds), then it should assume that the there are  	 * larger problems with the xHC and assert HCRST.  	 */ -	ret = handshake(xhci, &xhci->op_regs->cmd_ring, +	ret = xhci_handshake(xhci, &xhci->op_regs->cmd_ring,  			CMD_RING_RUNNING, 0, 5 * 1000 * 1000);  	if (ret < 0) {  		xhci_err(xhci, "Stopped the command ring failed, " @@ -3071,11 +3071,11 @@ static u32 xhci_td_remainder(unsigned int remainder)  }  /* - * For xHCI 1.0 host controllers, TD size is the number of packets remaining in - * the TD (*not* including this TRB). + * For xHCI 1.0 host controllers, TD size is the number of max packet sized + * packets remaining in the TD (*not* including this TRB).   *   * Total TD packet count = total_packet_count = - *     roundup(TD size in bytes / wMaxPacketSize) + *     DIV_ROUND_UP(TD size in bytes / wMaxPacketSize)   *   * Packets transferred up to and including this TRB = packets_transferred =   *     rounddown(total bytes transferred including this TRB / wMaxPacketSize) @@ -3083,15 +3083,16 @@ static u32 xhci_td_remainder(unsigned int remainder)   * TD size = total_packet_count - packets_transferred   *   * It must fit in bits 21:17, so it can't be bigger than 31. + * The last TRB in a TD must have the TD size set to zero.   */ -  static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len, -		unsigned int total_packet_count, struct urb *urb) +		unsigned int total_packet_count, struct urb *urb, +		unsigned int num_trbs_left)  {  	int packets_transferred;  	/* One TRB with a zero-length data packet. */ -	if (running_total == 0 && trb_buff_len == 0) +	if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0))  		return 0;  	/* All the TRB queueing functions don't count the current TRB in @@ -3100,7 +3101,9 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,  	packets_transferred = (running_total + trb_buff_len) /  		usb_endpoint_maxp(&urb->ep->desc); -	return xhci_td_remainder(total_packet_count - packets_transferred); +	if ((total_packet_count - packets_transferred) > 31) +		return 31 << 17; +	return (total_packet_count - packets_transferred) << 17;  }  static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, @@ -3127,7 +3130,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  	num_trbs = count_sg_trbs_needed(xhci, urb);  	num_sgs = urb->num_mapped_sgs; -	total_packet_count = roundup(urb->transfer_buffer_length, +	total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,  			usb_endpoint_maxp(&urb->ep->desc));  	trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id], @@ -3210,7 +3213,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  					running_total);  		} else {  			remainder = xhci_v1_0_td_remainder(running_total, -					trb_buff_len, total_packet_count, urb); +					trb_buff_len, total_packet_count, urb, +					num_trbs - 1);  		}  		length_field = TRB_LEN(trb_buff_len) |  			remainder | @@ -3318,7 +3322,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  	start_cycle = ep_ring->cycle_state;  	running_total = 0; -	total_packet_count = roundup(urb->transfer_buffer_length, +	total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,  			usb_endpoint_maxp(&urb->ep->desc));  	/* How much data is in the first TRB? */  	addr = (u64) urb->transfer_dma; @@ -3364,7 +3368,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  					running_total);  		} else {  			remainder = xhci_v1_0_td_remainder(running_total, -					trb_buff_len, total_packet_count, urb); +					trb_buff_len, total_packet_count, urb, +					num_trbs - 1);  		}  		length_field = TRB_LEN(trb_buff_len) |  			remainder | @@ -3627,7 +3632,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  		addr = start_addr + urb->iso_frame_desc[i].offset;  		td_len = urb->iso_frame_desc[i].length;  		td_remain_len = td_len; -		total_packet_count = roundup(td_len, +		total_packet_count = DIV_ROUND_UP(td_len,  				usb_endpoint_maxp(&urb->ep->desc));  		/* A zero-length transfer still involves at least one packet. */  		if (total_packet_count == 0) @@ -3706,7 +3711,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  			} else {  				remainder = xhci_v1_0_td_remainder(  						running_total, trb_buff_len, -						total_packet_count, urb); +						total_packet_count, urb, +						(trbs_per_td - j - 1));  			}  			length_field = TRB_LEN(trb_buff_len) |  				remainder | diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index c9e419f29b7..5c72c431bab 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -40,7 +40,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");  /* TODO: copied from ehci-hcd.c - can this be refactored? */  /* - * handshake - spin reading hc until handshake completes or fails + * xhci_handshake - spin reading hc until handshake completes or fails   * @ptr: address of hc register to be read   * @mask: bits to look at in result of read   * @done: value of those bits when handshake succeeds @@ -52,7 +52,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");   * handshake done).  There are two failure modes:  "usec" have passed (major   * hardware flakeout), or the register reads as all-ones (hardware removed).   */ -int handshake(struct xhci_hcd *xhci, void __iomem *ptr, +int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr,  		      u32 mask, u32 done, int usec)  {  	u32	result; @@ -103,7 +103,7 @@ int xhci_halt(struct xhci_hcd *xhci)  	xhci_dbg(xhci, "// Halt the HC\n");  	xhci_quiesce(xhci); -	ret = handshake(xhci, &xhci->op_regs->status, +	ret = xhci_handshake(xhci, &xhci->op_regs->status,  			STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);  	if (!ret) {  		xhci->xhc_state |= XHCI_STATE_HALTED; @@ -132,7 +132,7 @@ static int xhci_start(struct xhci_hcd *xhci)  	 * Wait for the HCHalted Status bit to be 0 to indicate the host is  	 * running.  	 */ -	ret = handshake(xhci, &xhci->op_regs->status, +	ret = xhci_handshake(xhci, &xhci->op_regs->status,  			STS_HALT, 0, XHCI_MAX_HALT_USEC);  	if (ret == -ETIMEDOUT)  		xhci_err(xhci, "Host took too long to start, " @@ -167,7 +167,7 @@ int xhci_reset(struct xhci_hcd *xhci)  	command |= CMD_RESET;  	xhci_writel(xhci, command, &xhci->op_regs->command); -	ret = handshake(xhci, &xhci->op_regs->command, +	ret = xhci_handshake(xhci, &xhci->op_regs->command,  			CMD_RESET, 0, 10 * 1000 * 1000);  	if (ret)  		return ret; @@ -177,7 +177,7 @@ int xhci_reset(struct xhci_hcd *xhci)  	 * xHCI cannot write to any doorbells or operational registers other  	 * than status until the "Controller Not Ready" flag is cleared.  	 */ -	ret = handshake(xhci, &xhci->op_regs->status, +	ret = xhci_handshake(xhci, &xhci->op_regs->status,  			STS_CNR, 0, 10 * 1000 * 1000);  	for (i = 0; i < 2; ++i) { @@ -480,7 +480,7 @@ static bool compliance_mode_recovery_timer_quirk_check(void)  	if (strstr(dmi_product_name, "Z420") ||  			strstr(dmi_product_name, "Z620") ||  			strstr(dmi_product_name, "Z820") || -			strstr(dmi_product_name, "Z1")) +			strstr(dmi_product_name, "Z1 Workstation"))  		return true;  	return false; @@ -880,6 +880,10 @@ int xhci_suspend(struct xhci_hcd *xhci)  	struct usb_hcd		*hcd = xhci_to_hcd(xhci);  	u32			command; +	if (hcd->state != HC_STATE_SUSPENDED || +			xhci->shared_hcd->state != HC_STATE_SUSPENDED) +		return -EINVAL; +  	spin_lock_irq(&xhci->lock);  	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);  	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); @@ -890,7 +894,7 @@ int xhci_suspend(struct xhci_hcd *xhci)  	command = xhci_readl(xhci, &xhci->op_regs->command);  	command &= ~CMD_RUN;  	xhci_writel(xhci, command, &xhci->op_regs->command); -	if (handshake(xhci, &xhci->op_regs->status, +	if (xhci_handshake(xhci, &xhci->op_regs->status,  		      STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) {  		xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");  		spin_unlock_irq(&xhci->lock); @@ -905,7 +909,8 @@ int xhci_suspend(struct xhci_hcd *xhci)  	command = xhci_readl(xhci, &xhci->op_regs->command);  	command |= CMD_CSS;  	xhci_writel(xhci, command, &xhci->op_regs->command); -	if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) { +	if (xhci_handshake(xhci, &xhci->op_regs->status, +				STS_SAVE, 0, 10 * 1000)) {  		xhci_warn(xhci, "WARN: xHC save state timeout\n");  		spin_unlock_irq(&xhci->lock);  		return -ETIMEDOUT; @@ -967,7 +972,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)  		command = xhci_readl(xhci, &xhci->op_regs->command);  		command |= CMD_CRS;  		xhci_writel(xhci, command, &xhci->op_regs->command); -		if (handshake(xhci, &xhci->op_regs->status, +		if (xhci_handshake(xhci, &xhci->op_regs->status,  			      STS_RESTORE, 0, 10 * 1000)) {  			xhci_warn(xhci, "WARN: xHC restore state timeout\n");  			spin_unlock_irq(&xhci->lock); @@ -1035,7 +1040,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)  	command = xhci_readl(xhci, &xhci->op_regs->command);  	command |= CMD_RUN;  	xhci_writel(xhci, command, &xhci->op_regs->command); -	handshake(xhci, &xhci->op_regs->status, STS_HALT, +	xhci_handshake(xhci, &xhci->op_regs->status, STS_HALT,  		  0, 250 * 1000);  	/* step 5: walk topology and initialize portsc, @@ -2254,7 +2259,7 @@ static bool xhci_is_async_ep(unsigned int ep_type)  static bool xhci_is_sync_in_ep(unsigned int ep_type)  { -	return (ep_type == ISOC_IN_EP || ep_type != INT_IN_EP); +	return (ep_type == ISOC_IN_EP || ep_type == INT_IN_EP);  }  static unsigned int xhci_get_ss_bw_consumed(struct xhci_bw_info *ep_bw) @@ -3874,7 +3879,8 @@ static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd,  	spin_lock_irqsave(&xhci->lock, flags);  	/* Check L1 Status */ -	ret = handshake(xhci, pm_addr, PORT_L1S_MASK, PORT_L1S_SUCCESS, 125); +	ret = xhci_handshake(xhci, pm_addr, +			PORT_L1S_MASK, PORT_L1S_SUCCESS, 125);  	if (ret != -ETIMEDOUT) {  		/* enter L1 successfully */  		temp = xhci_readl(xhci, addr); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 53df4e70ca0..f791bd0aee6 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1720,7 +1720,7 @@ static inline void xhci_unregister_plat(void)  /* xHCI host controller glue */  typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); -int handshake(struct xhci_hcd *xhci, void __iomem *ptr, +int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr,  		u32 mask, u32 done, int usec);  void xhci_quiesce(struct xhci_hcd *xhci);  int xhci_halt(struct xhci_hcd *xhci); diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index a8f05239350..fecde69bfa7 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -246,6 +246,7 @@ 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/ezusb.c b/drivers/usb/misc/ezusb.c index 6589268a651..e712afed947 100644 --- a/drivers/usb/misc/ezusb.c +++ b/drivers/usb/misc/ezusb.c @@ -15,6 +15,7 @@  #include <linux/usb.h>  #include <linux/firmware.h>  #include <linux/ihex.h> +#include <linux/usb/ezusb.h>  struct ezusb_fx_type {  	/* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */ @@ -22,21 +23,16 @@ struct ezusb_fx_type {  	unsigned short max_internal_adress;  }; -struct ezusb_fx_type ezusb_fx1 = { +static struct ezusb_fx_type ezusb_fx1 = {  	.cpucs_reg = 0x7F92,  	.max_internal_adress = 0x1B3F,  }; -struct ezusb_fx_type ezusb_fx2 = { -	.cpucs_reg = 0xE600, -	.max_internal_adress = 0x3FFF, -}; -  /* Commands for writing to memory */  #define WRITE_INT_RAM 0xA0  #define WRITE_EXT_RAM 0xA3 -int ezusb_writememory(struct usb_device *dev, int address, +static int ezusb_writememory(struct usb_device *dev, int address,  				unsigned char *data, int length, __u8 request)  {  	int result; @@ -58,10 +54,9 @@ int ezusb_writememory(struct usb_device *dev, int address,  	kfree(transfer_buffer);  	return result;  } -EXPORT_SYMBOL_GPL(ezusb_writememory); -int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg, -			 unsigned char reset_bit) +static int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg, +			   unsigned char reset_bit)  {  	int response = ezusb_writememory(dev, cpucs_reg, &reset_bit, 1, WRITE_INT_RAM);  	if (response < 0) @@ -76,12 +71,6 @@ int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit)  }  EXPORT_SYMBOL_GPL(ezusb_fx1_set_reset); -int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit) -{ -	return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit); -} -EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset); -  static int ezusb_ihex_firmware_download(struct usb_device *dev,  					struct ezusb_fx_type fx,  					const char *firmware_path) @@ -151,11 +140,28 @@ int ezusb_fx1_ihex_firmware_download(struct usb_device *dev,  }  EXPORT_SYMBOL_GPL(ezusb_fx1_ihex_firmware_download); +#if 0 +/* + * Once someone one needs these fx2 functions, uncomment them + * and add them to ezusb.h and all should be good. + */ +static struct ezusb_fx_type ezusb_fx2 = { +	.cpucs_reg = 0xE600, +	.max_internal_adress = 0x3FFF, +}; + +int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit) +{ +	return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit); +} +EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset); +  int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,  				     const char *firmware_path)  {  	return ezusb_ihex_firmware_download(dev, ezusb_fx2, firmware_path);  }  EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download); +#endif  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 055b84adeda..7667b12f2ff 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -423,6 +423,9 @@ alloc_sglist(int nents, int max, int vary)  	unsigned		i;  	unsigned		size = max; +	if (max == 0) +		return NULL; +  	sg = kmalloc_array(nents, sizeof *sg, GFP_KERNEL);  	if (!sg)  		return NULL; @@ -2386,6 +2389,7 @@ static struct usbtest_info gz_info = {  	.name		= "Linux gadget zero",  	.autoconf	= 1,  	.ctrl_out	= 1, +	.iso		= 1,  	.alt		= 0,  }; diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index a87cdd2387c..c107d7cdfa6 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -454,7 +454,7 @@ static const struct musb_platform_ops am35x_ops = {  static u64 am35x_dmamask = DMA_BIT_MASK(32); -static int __devinit am35x_probe(struct platform_device *pdev) +static int am35x_probe(struct platform_device *pdev)  {  	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;  	struct platform_device		*musb; @@ -464,7 +464,6 @@ static int __devinit am35x_probe(struct platform_device *pdev)  	struct clk			*clk;  	int				ret = -ENOMEM; -	int				musbid;  	glue = kzalloc(sizeof(*glue), GFP_KERNEL);  	if (!glue) { @@ -472,18 +471,10 @@ static int __devinit am35x_probe(struct platform_device *pdev)  		goto err0;  	} -	/* get the musb id */ -	musbid = musb_get_id(&pdev->dev, GFP_KERNEL); -	if (musbid < 0) { -		dev_err(&pdev->dev, "failed to allocate musb id\n"); -		ret = -ENOMEM; -		goto err1; -	} - -	musb = platform_device_alloc("musb-hdrc", musbid); +	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);  	if (!musb) {  		dev_err(&pdev->dev, "failed to allocate musb device\n"); -		goto err2; +		goto err1;  	}  	phy_clk = clk_get(&pdev->dev, "fck"); @@ -512,7 +503,6 @@ static int __devinit am35x_probe(struct platform_device *pdev)  		goto err6;  	} -	musb->id			= musbid;  	musb->dev.parent		= &pdev->dev;  	musb->dev.dma_mask		= &am35x_dmamask;  	musb->dev.coherent_dma_mask	= am35x_dmamask; @@ -562,9 +552,6 @@ err4:  err3:  	platform_device_put(musb); -err2: -	musb_put_id(&pdev->dev, musbid); -  err1:  	kfree(glue); @@ -572,13 +559,11 @@ err0:  	return ret;  } -static int __devexit am35x_remove(struct platform_device *pdev) +static int am35x_remove(struct platform_device *pdev)  {  	struct am35x_glue	*glue = platform_get_drvdata(pdev); -	musb_put_id(&pdev->dev, glue->musb->id); -	platform_device_del(glue->musb); -	platform_device_put(glue->musb); +	platform_device_unregister(glue->musb);  	clk_disable(glue->clk);  	clk_disable(glue->phy_clk);  	clk_put(glue->clk); @@ -643,7 +628,7 @@ static struct dev_pm_ops am35x_pm_ops = {  static struct platform_driver am35x_driver = {  	.probe		= am35x_probe, -	.remove		= __devexit_p(am35x_remove), +	.remove		= am35x_remove,  	.driver		= {  		.name	= "musb-am35x",  		.pm	= DEV_PM_OPS, @@ -653,15 +638,4 @@ static struct platform_driver am35x_driver = {  MODULE_DESCRIPTION("AM35x MUSB Glue Layer");  MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");  MODULE_LICENSE("GPL v2"); - -static int __init am35x_init(void) -{ -	return platform_driver_register(&am35x_driver); -} -module_init(am35x_init); - -static void __exit am35x_exit(void) -{ -	platform_driver_unregister(&am35x_driver); -} -module_exit(am35x_exit); +module_platform_driver(am35x_driver); diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index e8cff9bb9d2..14dab9f9b3d 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -448,14 +448,13 @@ static const struct musb_platform_ops bfin_ops = {  static u64 bfin_dmamask = DMA_BIT_MASK(32); -static int __devinit bfin_probe(struct platform_device *pdev) +static int bfin_probe(struct platform_device *pdev)  {  	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;  	struct platform_device		*musb;  	struct bfin_glue		*glue;  	int				ret = -ENOMEM; -	int				musbid;  	glue = kzalloc(sizeof(*glue), GFP_KERNEL);  	if (!glue) { @@ -463,21 +462,12 @@ static int __devinit bfin_probe(struct platform_device *pdev)  		goto err0;  	} -	/* get the musb id */ -	musbid = musb_get_id(&pdev->dev, GFP_KERNEL); -	if (musbid < 0) { -		dev_err(&pdev->dev, "failed to allocate musb id\n"); -		ret = -ENOMEM; -		goto err1; -	} - -	musb = platform_device_alloc("musb-hdrc", musbid); +	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);  	if (!musb) {  		dev_err(&pdev->dev, "failed to allocate musb device\n"); -		goto err2; +		goto err1;  	} -	musb->id			= musbid;  	musb->dev.parent		= &pdev->dev;  	musb->dev.dma_mask		= &bfin_dmamask;  	musb->dev.coherent_dma_mask	= bfin_dmamask; @@ -513,9 +503,6 @@ static int __devinit bfin_probe(struct platform_device *pdev)  err3:  	platform_device_put(musb); -err2: -	musb_put_id(&pdev->dev, musbid); -  err1:  	kfree(glue); @@ -523,13 +510,11 @@ err0:  	return ret;  } -static int __devexit bfin_remove(struct platform_device *pdev) +static int bfin_remove(struct platform_device *pdev)  {  	struct bfin_glue		*glue = platform_get_drvdata(pdev); -	musb_put_id(&pdev->dev, glue->musb->id); -	platform_device_del(glue->musb); -	platform_device_put(glue->musb); +	platform_device_unregister(glue->musb);  	kfree(glue);  	return 0; @@ -585,15 +570,4 @@ static struct platform_driver bfin_driver = {  MODULE_DESCRIPTION("Blackfin MUSB Glue Layer");  MODULE_AUTHOR("Bryan Wy <cooloney@kernel.org>");  MODULE_LICENSE("GPL v2"); - -static int __init bfin_init(void) -{ -	return platform_driver_register(&bfin_driver); -} -module_init(bfin_init); - -static void __exit bfin_exit(void) -{ -	platform_driver_unregister(&bfin_driver); -} -module_exit(bfin_exit); +module_platform_driver(bfin_driver); diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index e19da82b478..0968dd7a859 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -1314,10 +1314,10 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)  	return IRQ_HANDLED;  } +EXPORT_SYMBOL_GPL(cppi_interrupt);  /* Instantiate a software object representing a DMA controller. */ -struct dma_controller *__devinit -dma_controller_create(struct musb *musb, void __iomem *mregs) +struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *mregs)  {  	struct cppi		*controller;  	struct device		*dev = musb->controller; diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 8bc44b76eec..97996af2646 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -471,7 +471,7 @@ static const struct musb_platform_ops da8xx_ops = {  static u64 da8xx_dmamask = DMA_BIT_MASK(32); -static int __devinit da8xx_probe(struct platform_device *pdev) +static int da8xx_probe(struct platform_device *pdev)  {  	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;  	struct platform_device		*musb; @@ -480,7 +480,6 @@ static int __devinit da8xx_probe(struct platform_device *pdev)  	struct clk			*clk;  	int				ret = -ENOMEM; -	int				musbid;  	glue = kzalloc(sizeof(*glue), GFP_KERNEL);  	if (!glue) { @@ -488,18 +487,10 @@ static int __devinit da8xx_probe(struct platform_device *pdev)  		goto err0;  	} -	/* get the musb id */ -	musbid = musb_get_id(&pdev->dev, GFP_KERNEL); -	if (musbid < 0) { -		dev_err(&pdev->dev, "failed to allocate musb id\n"); -		ret = -ENOMEM; -		goto err1; -	} - -	musb = platform_device_alloc("musb-hdrc", musbid); +	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);  	if (!musb) {  		dev_err(&pdev->dev, "failed to allocate musb device\n"); -		goto err2; +		goto err1;  	}  	clk = clk_get(&pdev->dev, "usb20"); @@ -515,7 +506,6 @@ static int __devinit da8xx_probe(struct platform_device *pdev)  		goto err4;  	} -	musb->id			= musbid;  	musb->dev.parent		= &pdev->dev;  	musb->dev.dma_mask		= &da8xx_dmamask;  	musb->dev.coherent_dma_mask	= da8xx_dmamask; @@ -558,9 +548,6 @@ err4:  err3:  	platform_device_put(musb); -err2: -	musb_put_id(&pdev->dev, musbid); -  err1:  	kfree(glue); @@ -568,13 +555,11 @@ err0:  	return ret;  } -static int __devexit da8xx_remove(struct platform_device *pdev) +static int da8xx_remove(struct platform_device *pdev)  {  	struct da8xx_glue		*glue = platform_get_drvdata(pdev); -	musb_put_id(&pdev->dev, glue->musb->id); -	platform_device_del(glue->musb); -	platform_device_put(glue->musb); +	platform_device_unregister(glue->musb);  	clk_disable(glue->clk);  	clk_put(glue->clk);  	kfree(glue); @@ -584,7 +569,7 @@ static int __devexit da8xx_remove(struct platform_device *pdev)  static struct platform_driver da8xx_driver = {  	.probe		= da8xx_probe, -	.remove		= __devexit_p(da8xx_remove), +	.remove		= da8xx_remove,  	.driver		= {  		.name	= "musb-da8xx",  	}, @@ -593,15 +578,4 @@ static struct platform_driver da8xx_driver = {  MODULE_DESCRIPTION("DA8xx/OMAP-L1x MUSB Glue Layer");  MODULE_AUTHOR("Sergei Shtylyov <sshtylyov@ru.mvista.com>");  MODULE_LICENSE("GPL v2"); - -static int __init da8xx_init(void) -{ -	return platform_driver_register(&da8xx_driver); -} -module_init(da8xx_init); - -static void __exit da8xx_exit(void) -{ -	platform_driver_unregister(&da8xx_driver); -} -module_exit(da8xx_exit); +module_platform_driver(da8xx_driver); diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 606bfd00cde..b1c01cad28b 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -504,7 +504,7 @@ static const struct musb_platform_ops davinci_ops = {  static u64 davinci_dmamask = DMA_BIT_MASK(32); -static int __devinit davinci_probe(struct platform_device *pdev) +static int davinci_probe(struct platform_device *pdev)  {  	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;  	struct platform_device		*musb; @@ -512,7 +512,6 @@ static int __devinit davinci_probe(struct platform_device *pdev)  	struct clk			*clk;  	int				ret = -ENOMEM; -	int				musbid;  	glue = kzalloc(sizeof(*glue), GFP_KERNEL);  	if (!glue) { @@ -520,18 +519,10 @@ static int __devinit davinci_probe(struct platform_device *pdev)  		goto err0;  	} -	/* get the musb id */ -	musbid = musb_get_id(&pdev->dev, GFP_KERNEL); -	if (musbid < 0) { -		dev_err(&pdev->dev, "failed to allocate musb id\n"); -		ret = -ENOMEM; -		goto err1; -	} - -	musb = platform_device_alloc("musb-hdrc", musbid); +	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);  	if (!musb) {  		dev_err(&pdev->dev, "failed to allocate musb device\n"); -		goto err2; +		goto err1;  	}  	clk = clk_get(&pdev->dev, "usb"); @@ -547,7 +538,6 @@ static int __devinit davinci_probe(struct platform_device *pdev)  		goto err4;  	} -	musb->id			= musbid;  	musb->dev.parent		= &pdev->dev;  	musb->dev.dma_mask		= &davinci_dmamask;  	musb->dev.coherent_dma_mask	= davinci_dmamask; @@ -590,9 +580,6 @@ err4:  err3:  	platform_device_put(musb); -err2: -	musb_put_id(&pdev->dev, musbid); -  err1:  	kfree(glue); @@ -600,13 +587,11 @@ err0:  	return ret;  } -static int __devexit davinci_remove(struct platform_device *pdev) +static int davinci_remove(struct platform_device *pdev)  {  	struct davinci_glue		*glue = platform_get_drvdata(pdev); -	musb_put_id(&pdev->dev, glue->musb->id); -	platform_device_del(glue->musb); -	platform_device_put(glue->musb); +	platform_device_unregister(glue->musb);  	clk_disable(glue->clk);  	clk_put(glue->clk);  	kfree(glue); @@ -616,7 +601,7 @@ static int __devexit davinci_remove(struct platform_device *pdev)  static struct platform_driver davinci_driver = {  	.probe		= davinci_probe, -	.remove		= __devexit_p(davinci_remove), +	.remove		= davinci_remove,  	.driver		= {  		.name	= "musb-davinci",  	}, @@ -625,15 +610,4 @@ static struct platform_driver davinci_driver = {  MODULE_DESCRIPTION("DaVinci MUSB Glue Layer");  MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");  MODULE_LICENSE("GPL v2"); - -static int __init davinci_init(void) -{ -	return platform_driver_register(&davinci_driver); -} -module_init(davinci_init); - -static void __exit davinci_exit(void) -{ -	platform_driver_unregister(&davinci_driver); -} -module_exit(davinci_exit); +module_platform_driver(davinci_driver); diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index bb56a0e8b23..57cc9c6eaa9 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -116,7 +116,6 @@  #define MUSB_DRIVER_NAME "musb-hdrc"  const char musb_driver_name[] = MUSB_DRIVER_NAME; -static DEFINE_IDA(musb_ida);  MODULE_DESCRIPTION(DRIVER_INFO);  MODULE_AUTHOR(DRIVER_AUTHOR); @@ -133,35 +132,6 @@ static inline struct musb *dev_to_musb(struct device *dev)  /*-------------------------------------------------------------------------*/ -int musb_get_id(struct device *dev, gfp_t gfp_mask) -{ -	int ret; -	int id; - -	ret = ida_pre_get(&musb_ida, gfp_mask); -	if (!ret) { -		dev_err(dev, "failed to reserve resource for id\n"); -		return -ENOMEM; -	} - -	ret = ida_get_new(&musb_ida, &id); -	if (ret < 0) { -		dev_err(dev, "failed to allocate a new id\n"); -		return ret; -	} - -	return id; -} -EXPORT_SYMBOL_GPL(musb_get_id); - -void musb_put_id(struct device *dev, int id) -{ - -	dev_dbg(dev, "removing id %d\n", id); -	ida_remove(&musb_ida, id); -} -EXPORT_SYMBOL_GPL(musb_put_id); -  #ifndef CONFIG_BLACKFIN  static int musb_ulpi_read(struct usb_phy *phy, u32 offset)  { @@ -467,12 +437,12 @@ void musb_hnp_stop(struct musb *musb)   */  static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, -				u8 devctl, u8 power) +				u8 devctl)  {  	struct usb_otg *otg = musb->xceiv->otg;  	irqreturn_t handled = IRQ_NONE; -	dev_dbg(musb->controller, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl, +	dev_dbg(musb->controller, "<== DevCtl=%02x, int_usb=0x%x\n", devctl,  		int_usb);  	/* in host mode, the peripheral may issue remote wakeup. @@ -485,6 +455,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  		if (devctl & MUSB_DEVCTL_HM) {  			void __iomem *mbase = musb->mregs; +			u8 power;  			switch (musb->xceiv->state) {  			case OTG_STATE_A_SUSPEND: @@ -492,6 +463,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  				 * will stop RESUME signaling  				 */ +				power = musb_readb(musb->mregs, MUSB_POWER);  				if (power & MUSB_POWER_SUSPENDM) {  					/* spurious */  					musb->int_usb &= ~MUSB_INTR_SUSPEND; @@ -655,8 +627,8 @@ 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 power %02x\n", -			otg_state_string(musb->xceiv->state), devctl, power); +		dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n", +			otg_state_string(musb->xceiv->state), devctl);  		handled = IRQ_HANDLED;  		switch (musb->xceiv->state) { @@ -722,8 +694,10 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,  		if (is_peripheral_active(musb)) {  			/* REVISIT HNP; just force disconnect */  		} -		musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask); -		musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe); +		musb->intrtxe = musb->epmask; +		musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe); +		musb->intrrxe = musb->epmask & 0xfffe; +		musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe);  		musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7);  		musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED  					|USB_PORT_STAT_HIGH_SPEED @@ -944,8 +918,10 @@ void musb_start(struct musb *musb)  	dev_dbg(musb->controller, "<== devctl %02x\n", devctl);  	/*  Set INT enable registers, enable interrupts */ -	musb_writew(regs, MUSB_INTRTXE, musb->epmask); -	musb_writew(regs, MUSB_INTRRXE, musb->epmask & 0xfffe); +	musb->intrtxe = musb->epmask; +	musb_writew(regs, MUSB_INTRTXE, musb->intrtxe); +	musb->intrrxe = musb->epmask & 0xfffe; +	musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);  	musb_writeb(regs, MUSB_INTRUSBE, 0xf7);  	musb_writeb(regs, MUSB_TESTMODE, 0); @@ -983,7 +959,9 @@ static void musb_generic_disable(struct musb *musb)  	/* disable interrupts */  	musb_writeb(mbase, MUSB_INTRUSBE, 0); +	musb->intrtxe = 0;  	musb_writew(mbase, MUSB_INTRTXE, 0); +	musb->intrrxe = 0;  	musb_writew(mbase, MUSB_INTRRXE, 0);  	/* off */ @@ -1062,12 +1040,12 @@ static void musb_shutdown(struct platform_device *pdev)  	|| defined(CONFIG_USB_MUSB_AM35X_MODULE)	\  	|| defined(CONFIG_USB_MUSB_DSPS)		\  	|| defined(CONFIG_USB_MUSB_DSPS_MODULE) -static ushort __devinitdata fifo_mode = 4; +static ushort fifo_mode = 4;  #elif defined(CONFIG_USB_MUSB_UX500)			\  	|| defined(CONFIG_USB_MUSB_UX500_MODULE) -static ushort __devinitdata fifo_mode = 5; +static ushort fifo_mode = 5;  #else -static ushort __devinitdata fifo_mode = 2; +static ushort fifo_mode = 2;  #endif  /* "modprobe ... fifo_mode=1" etc */ @@ -1080,7 +1058,7 @@ MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration");   */  /* mode 0 - fits in 2KB */ -static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = { +static struct musb_fifo_cfg mode_0_cfg[] = {  { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, },  { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, },  { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, }, @@ -1089,7 +1067,7 @@ static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = {  };  /* mode 1 - fits in 4KB */ -static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = { +static struct musb_fifo_cfg mode_1_cfg[] = {  { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },  { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },  { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, }, @@ -1098,7 +1076,7 @@ static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = {  };  /* mode 2 - fits in 4KB */ -static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = { +static struct musb_fifo_cfg mode_2_cfg[] = {  { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, },  { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, },  { .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, }, @@ -1108,7 +1086,7 @@ static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = {  };  /* mode 3 - fits in 4KB */ -static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = { +static struct musb_fifo_cfg mode_3_cfg[] = {  { .hw_ep_num = 1, .style = FIFO_TX,   .maxpacket = 512, .mode = BUF_DOUBLE, },  { .hw_ep_num = 1, .style = FIFO_RX,   .maxpacket = 512, .mode = BUF_DOUBLE, },  { .hw_ep_num = 2, .style = FIFO_TX,   .maxpacket = 512, }, @@ -1118,7 +1096,7 @@ static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = {  };  /* mode 4 - fits in 16KB */ -static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = { +static struct musb_fifo_cfg mode_4_cfg[] = {  { .hw_ep_num =  1, .style = FIFO_TX,   .maxpacket = 512, },  { .hw_ep_num =  1, .style = FIFO_RX,   .maxpacket = 512, },  { .hw_ep_num =  2, .style = FIFO_TX,   .maxpacket = 512, }, @@ -1149,7 +1127,7 @@ static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = {  };  /* mode 5 - fits in 8KB */ -static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = { +static struct musb_fifo_cfg mode_5_cfg[] = {  { .hw_ep_num =  1, .style = FIFO_TX,   .maxpacket = 512, },  { .hw_ep_num =  1, .style = FIFO_RX,   .maxpacket = 512, },  { .hw_ep_num =  2, .style = FIFO_TX,   .maxpacket = 512, }, @@ -1185,7 +1163,7 @@ static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = {   *   * returns negative errno or offset for next fifo.   */ -static int __devinit +static int  fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,  		const struct musb_fifo_cfg *cfg, u16 offset)  { @@ -1256,11 +1234,11 @@ fifo_setup(struct musb *musb, struct musb_hw_ep  *hw_ep,  	return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0));  } -static struct musb_fifo_cfg __devinitdata ep0_cfg = { +static struct musb_fifo_cfg ep0_cfg = {  	.style = FIFO_RXTX, .maxpacket = 64,  }; -static int __devinit ep_config_from_table(struct musb *musb) +static int ep_config_from_table(struct musb *musb)  {  	const struct musb_fifo_cfg	*cfg;  	unsigned		i, n; @@ -1351,7 +1329,7 @@ done:   * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false   * @param musb the controller   */ -static int __devinit ep_config_from_hw(struct musb *musb) +static int ep_config_from_hw(struct musb *musb)  {  	u8 epnum = 0;  	struct musb_hw_ep *hw_ep; @@ -1398,7 +1376,7 @@ enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, };  /* Initialize MUSB (M)HDRC part of the USB hardware subsystem;   * configure endpoints, or take their config from silicon   */ -static int __devinit musb_core_init(u16 musb_type, struct musb *musb) +static int musb_core_init(u16 musb_type, struct musb *musb)  {  	u8 reg;  	char *type; @@ -1523,33 +1501,6 @@ static int __devinit musb_core_init(u16 musb_type, struct musb *musb)  /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \ -	defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500) - -static irqreturn_t generic_interrupt(int irq, void *__hci) -{ -	unsigned long	flags; -	irqreturn_t	retval = IRQ_NONE; -	struct musb	*musb = __hci; - -	spin_lock_irqsave(&musb->lock, flags); - -	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); -	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); -	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); - -	if (musb->int_usb || musb->int_tx || musb->int_rx) -		retval = musb_interrupt(musb); - -	spin_unlock_irqrestore(&musb->lock, flags); - -	return retval; -} - -#else -#define generic_interrupt	NULL -#endif -  /*   * handle all the irqs defined by the HDRC core. for now we expect:  other   * irq sources (phy, dma, etc) will be handled first, musb->int_* values @@ -1560,12 +1511,11 @@ static irqreturn_t generic_interrupt(int irq, void *__hci)  irqreturn_t musb_interrupt(struct musb *musb)  {  	irqreturn_t	retval = IRQ_NONE; -	u8		devctl, power; +	u8		devctl;  	int		ep_num;  	u32		reg;  	devctl = musb_readb(musb->mregs, MUSB_DEVCTL); -	power = musb_readb(musb->mregs, MUSB_POWER);  	dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n",  		(devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral", @@ -1576,7 +1526,7 @@ irqreturn_t musb_interrupt(struct musb *musb)  	 */  	if (musb->int_usb)  		retval |= musb_stage0_irq(musb, musb->int_usb, -				devctl, power); +				devctl);  	/* "stage 1" is handling endpoint irqs */ @@ -1628,7 +1578,7 @@ irqreturn_t musb_interrupt(struct musb *musb)  EXPORT_SYMBOL_GPL(musb_interrupt);  #ifndef CONFIG_MUSB_PIO_ONLY -static bool __devinitdata use_dma = 1; +static bool use_dma = 1;  /* "modprobe ... use_dma=0" etc */  module_param(use_dma, bool, 0); @@ -1809,8 +1759,7 @@ static void musb_irq_work(struct work_struct *data)   * Init support   */ -static struct musb *__devinit -allocate_instance(struct device *dev, +static struct musb *allocate_instance(struct device *dev,  		struct musb_hdrc_config *config, void __iomem *mbase)  {  	struct musb		*musb; @@ -1885,7 +1834,7 @@ static void musb_free(struct musb *musb)   * @ctrl: virtual address of controller registers,   *	not yet corrected for platform-specific offsets   */ -static int __devinit +static int  musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)  {  	int			status; @@ -1919,7 +1868,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)  	musb->ops = plat->platform_ops;  	/* The musb_platform_init() call: -	 *   - adjusts musb->mregs and musb->isr if needed, +	 *   - adjusts musb->mregs +	 *   - sets the musb->isr  	 *   - may initialize an integrated tranceiver  	 *   - initializes musb->xceiv, usually by otg_get_phy()  	 *   - stops powering VBUS @@ -1929,7 +1879,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)  	 * external/discrete ones in various flavors (twl4030 family,  	 * isp1504, non-OTG, etc) mostly hooking up through ULPI.  	 */ -	musb->isr = generic_interrupt;  	status = musb_platform_init(musb);  	if (status < 0)  		goto fail1; @@ -2060,7 +2009,7 @@ fail0:  /* all implementations (PCI bridge to FPGA, VLYNQ, etc) should just   * bridge to a platform device; this driver then suffices.   */ -static int __devinit musb_probe(struct platform_device *pdev) +static int musb_probe(struct platform_device *pdev)  {  	struct device	*dev = &pdev->dev;  	int		irq = platform_get_irq_byname(pdev, "mc"); @@ -2085,7 +2034,7 @@ static int __devinit musb_probe(struct platform_device *pdev)  	return status;  } -static int __devexit musb_remove(struct platform_device *pdev) +static int musb_remove(struct platform_device *pdev)  {  	struct device	*dev = &pdev->dev;  	struct musb	*musb = dev_to_musb(dev); @@ -2120,8 +2069,6 @@ static void musb_save_context(struct musb *musb)  	musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE);  	musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs);  	musb->context.power = musb_readb(musb_base, MUSB_POWER); -	musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE); -	musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE);  	musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE);  	musb->context.index = musb_readb(musb_base, MUSB_INDEX);  	musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL); @@ -2194,8 +2141,8 @@ static void musb_restore_context(struct musb *musb)  	musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);  	musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);  	musb_writeb(musb_base, MUSB_POWER, musb->context.power); -	musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe); -	musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe); +	musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe); +	musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe);  	musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);  	musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl); @@ -2340,7 +2287,7 @@ static struct platform_driver musb_driver = {  		.pm		= MUSB_DEV_PM_OPS,  	},  	.probe		= musb_probe, -	.remove		= __devexit_p(musb_remove), +	.remove		= musb_remove,  	.shutdown	= musb_shutdown,  }; diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index c158aacd6de..7fb4819a6f1 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -288,7 +288,6 @@ struct musb_csr_regs {  struct musb_context_registers {  	u8 power; -	u16 intrtxe, intrrxe;  	u8 intrusbe;  	u16 frame;  	u8 index, testmode; @@ -313,6 +312,8 @@ struct musb {  	struct work_struct	irq_work;  	u16			hwvers; +	u16			intrrxe; +	u16			intrtxe;  /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */  #define MUSB_PORT_STAT_RESUME	(1 << 31) @@ -521,8 +522,6 @@ extern const char musb_driver_name[];  extern void musb_start(struct musb *musb);  extern void musb_stop(struct musb *musb); -extern int musb_get_id(struct device *dev, gfp_t gfp_mask); -extern void musb_put_id(struct device *dev, int id);  extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src);  extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst); diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index 1d6e8af94c0..4c216790e86 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c @@ -233,7 +233,7 @@ static const struct file_operations musb_test_mode_fops = {  	.release		= single_release,  }; -int __devinit musb_init_debugfs(struct musb *musb) +int musb_init_debugfs(struct musb *musb)  {  	struct dentry		*root;  	struct dentry		*file; diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h index 24d39210d4a..1b6b827b769 100644 --- a/drivers/usb/musb/musb_dma.h +++ b/drivers/usb/musb/musb_dma.h @@ -178,8 +178,7 @@ struct dma_controller {  extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit); -extern struct dma_controller *__devinit -dma_controller_create(struct musb *, void __iomem *); +extern struct dma_controller *dma_controller_create(struct musb *, void __iomem *);  extern void dma_controller_destroy(struct dma_controller *); diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index aa34f22181c..e6f2ae8368b 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -123,8 +123,44 @@ struct dsps_glue {  	const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */  	struct timer_list timer[2];	/* otg_workaround timer */  	unsigned long last_timer[2];    /* last timer data for each instance */ +	u32 __iomem *usb_ctrl[2];  }; +#define	DSPS_AM33XX_CONTROL_MODULE_PHYS_0	0x44e10620 +#define	DSPS_AM33XX_CONTROL_MODULE_PHYS_1	0x44e10628 + +static const resource_size_t dsps_control_module_phys[] = { +	DSPS_AM33XX_CONTROL_MODULE_PHYS_0, +	DSPS_AM33XX_CONTROL_MODULE_PHYS_1, +}; + +/** + * musb_dsps_phy_control - phy on/off + * @glue: struct dsps_glue * + * @id: musb instance + * @on: flag for phy to be switched on or off + * + * This is to enable the PHY using usb_ctrl register in system control + * module space. + * + * XXX: This function will be removed once we have a seperate driver for + * control module + */ +static void musb_dsps_phy_control(struct dsps_glue *glue, u8 id, u8 on) +{ +	u32 usbphycfg; + +	usbphycfg = readl(glue->usb_ctrl[id]); + +	if (on) { +		usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN); +		usbphycfg |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN; +	} else { +		usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN; +	} + +	writel(usbphycfg, glue->usb_ctrl[id]); +}  /**   * dsps_musb_enable - enable interrupts   */ @@ -295,7 +331,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)  	 * Also, DRVVBUS pulses for SRP (but not at 5V) ...  	 */  	if (usbintr & MUSB_INTR_BABBLE) -		pr_info("CAUTION: musb: Babble Interrupt Occured\n"); +		pr_info("CAUTION: musb: Babble Interrupt Occurred\n");  	if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {  		int drvvbus = dsps_readl(reg_base, wrp->status); @@ -364,11 +400,9 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)  static int dsps_musb_init(struct musb *musb)  {  	struct device *dev = musb->controller; -	struct musb_hdrc_platform_data *plat = dev->platform_data;  	struct platform_device *pdev = to_platform_device(dev);  	struct dsps_glue *glue = dev_get_drvdata(dev->parent);  	const struct dsps_musb_wrapper *wrp = glue->wrp; -	struct omap_musb_board_data *data = plat->board_data;  	void __iomem *reg_base = musb->ctrl_base;  	u32 rev, val;  	int status; @@ -376,7 +410,8 @@ static int dsps_musb_init(struct musb *musb)  	/* mentor core register starts at offset of 0x400 from musb base */  	musb->mregs += wrp->musb_core_offset; -	/* Get the NOP PHY */ +	/* NOP driver needs change if supporting dual instance */ +	usb_nop_xceiv_register();  	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);  	if (IS_ERR_OR_NULL(musb->xceiv))  		return -ENODEV; @@ -394,8 +429,7 @@ static int dsps_musb_init(struct musb *musb)  	dsps_writel(reg_base, wrp->control, (1 << wrp->reset));  	/* Start the on-chip PHY and its PLL. */ -	if (data->set_phy_power) -		data->set_phy_power(1); +	musb_dsps_phy_control(glue, pdev->id, 1);  	musb->isr = dsps_interrupt; @@ -417,16 +451,13 @@ err0:  static int dsps_musb_exit(struct musb *musb)  {  	struct device *dev = musb->controller; -	struct musb_hdrc_platform_data *plat = dev->platform_data; -	struct omap_musb_board_data *data = plat->board_data;  	struct platform_device *pdev = to_platform_device(dev);  	struct dsps_glue *glue = dev_get_drvdata(dev->parent);  	del_timer_sync(&glue->timer[pdev->id]);  	/* Shutdown the on-chip PHY and its PLL. */ -	if (data->set_phy_power) -		data->set_phy_power(0); +	musb_dsps_phy_control(glue, pdev->id, 0);  	/* NOP driver needs change if supporting dual instance */  	usb_put_phy(musb->xceiv); @@ -447,7 +478,7 @@ static struct musb_platform_ops dsps_ops = {  static u64 musb_dmamask = DMA_BIT_MASK(32); -static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) +static int dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)  {  	struct device *dev = glue->dev;  	struct platform_device *pdev = to_platform_device(dev); @@ -458,24 +489,33 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)  	struct resource *res;  	struct resource	resources[2];  	char res_name[11]; -	int ret, musbid; +	int ret; -	/* get memory resource */ -	snprintf(res_name, sizeof(res_name), "musb%d", id); -	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name); +	resources[0].start = dsps_control_module_phys[id]; +	resources[0].end = resources[0].start + SZ_4 - 1; +	resources[0].flags = IORESOURCE_MEM; + +	glue->usb_ctrl[id] = devm_request_and_ioremap(&pdev->dev, resources); +	if (glue->usb_ctrl[id] == NULL) { +		dev_err(dev, "Failed to obtain usb_ctrl%d memory\n", id); +		ret = -ENODEV; +		goto err0; +	} + +	/* first resource is for usbss, so start index from 1 */ +	res = platform_get_resource(pdev, IORESOURCE_MEM, id + 1);  	if (!res) { -		dev_err(dev, "%s get mem resource failed\n", res_name); +		dev_err(dev, "failed to get memory for instance %d\n", id);  		ret = -ENODEV;  		goto err0;  	}  	res->parent = NULL;  	resources[0] = *res; -	/* get irq resource */ -	snprintf(res_name, sizeof(res_name), "musb%d-irq", id); -	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name); +	/* first resource is for usbss, so start index from 1 */ +	res = platform_get_resource(pdev, IORESOURCE_IRQ, id + 1);  	if (!res) { -		dev_err(dev, "%s get irq resource failed\n", res_name); +		dev_err(dev, "failed to get irq for instance %d\n", id);  		ret = -ENODEV;  		goto err0;  	} @@ -483,22 +523,14 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)  	resources[1] = *res;  	resources[1].name = "mc"; -	/* get the musb id */ -	musbid = musb_get_id(dev, GFP_KERNEL); -	if (musbid < 0) { -		dev_err(dev, "failed to allocate musb id\n"); -		ret = -ENOMEM; -		goto err0; -	}  	/* allocate the child platform device */ -	musb = platform_device_alloc("musb-hdrc", musbid); +	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);  	if (!musb) {  		dev_err(dev, "failed to allocate musb device\n");  		ret = -ENOMEM; -		goto err1; +		goto err0;  	} -	musb->id			= musbid;  	musb->dev.parent		= dev;  	musb->dev.dma_mask		= &musb_dmamask;  	musb->dev.coherent_dma_mask	= musb_dmamask; @@ -555,20 +587,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)  err2:  	platform_device_put(musb); -err1: -	musb_put_id(dev, musbid);  err0:  	return ret;  } -static void dsps_delete_musb_pdev(struct dsps_glue *glue, u8 id) -{ -	musb_put_id(glue->dev, glue->musb[id]->id); -	platform_device_del(glue->musb[id]); -	platform_device_put(glue->musb[id]); -} - -static int __devinit dsps_probe(struct platform_device *pdev) +static int dsps_probe(struct platform_device *pdev)  {  	struct device_node *np = pdev->dev.of_node;  	const struct of_device_id *match; @@ -627,7 +650,7 @@ static int __devinit dsps_probe(struct platform_device *pdev)  			dev_err(&pdev->dev, "failed to create child pdev\n");  			/* release resources of previously created instances */  			for (i--; i >= 0 ; i--) -				dsps_delete_musb_pdev(glue, i); +				platform_device_unregister(glue->musb[i]);  			goto err3;  		}  	} @@ -644,7 +667,7 @@ err1:  err0:  	return ret;  } -static int __devexit dsps_remove(struct platform_device *pdev) +static int dsps_remove(struct platform_device *pdev)  {  	struct dsps_glue *glue = platform_get_drvdata(pdev);  	const struct dsps_musb_wrapper *wrp = glue->wrp; @@ -652,7 +675,7 @@ static int __devexit dsps_remove(struct platform_device *pdev)  	/* delete the child platform device */  	for (i = 0; i < wrp->instances ; i++) -		dsps_delete_musb_pdev(glue, i); +		platform_device_unregister(glue->musb[i]);  	/* disable usbss clocks */  	pm_runtime_put(&pdev->dev); @@ -665,24 +688,26 @@ static int __devexit dsps_remove(struct platform_device *pdev)  #ifdef CONFIG_PM_SLEEP  static int dsps_suspend(struct device *dev)  { -	struct musb_hdrc_platform_data *plat = dev->platform_data; -	struct omap_musb_board_data *data = plat->board_data; +	struct platform_device *pdev = to_platform_device(dev->parent); +	struct dsps_glue *glue = platform_get_drvdata(pdev); +	const struct dsps_musb_wrapper *wrp = glue->wrp; +	int i; -	/* Shutdown the on-chip PHY and its PLL. */ -	if (data->set_phy_power) -		data->set_phy_power(0); +	for (i = 0; i < wrp->instances; i++) +		musb_dsps_phy_control(glue, i, 0);  	return 0;  }  static int dsps_resume(struct device *dev)  { -	struct musb_hdrc_platform_data *plat = dev->platform_data; -	struct omap_musb_board_data *data = plat->board_data; +	struct platform_device *pdev = to_platform_device(dev->parent); +	struct dsps_glue *glue = platform_get_drvdata(pdev); +	const struct dsps_musb_wrapper *wrp = glue->wrp; +	int i; -	/* Start the on-chip PHY and its PLL. */ -	if (data->set_phy_power) -		data->set_phy_power(1); +	for (i = 0; i < wrp->instances; i++) +		musb_dsps_phy_control(glue, i, 1);  	return 0;  } @@ -690,7 +715,7 @@ static int dsps_resume(struct device *dev)  static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume); -static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = { +static const struct dsps_musb_wrapper ti81xx_driver_data = {  	.revision		= 0x00,  	.control		= 0x14,  	.status			= 0x18, @@ -718,10 +743,10 @@ static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = {  	.rxep_bitmap		= (0xfffe << 16),  	.musb_core_offset	= 0x400,  	.poll_seconds		= 2, -	.instances		= 2, +	.instances		= 1,  }; -static const struct platform_device_id musb_dsps_id_table[] __devinitconst = { +static const struct platform_device_id musb_dsps_id_table[] = {  	{  		.name	= "musb-ti81xx",  		.driver_data	= (kernel_ulong_t) &ti81xx_driver_data, @@ -731,7 +756,7 @@ static const struct platform_device_id musb_dsps_id_table[] __devinitconst = {  MODULE_DEVICE_TABLE(platform, musb_dsps_id_table);  #ifdef CONFIG_OF -static const struct of_device_id musb_dsps_of_match[] __devinitconst = { +static const struct of_device_id musb_dsps_of_match[] = {  	{ .compatible = "ti,musb-am33xx",  		.data = (void *) &ti81xx_driver_data, },  	{  }, @@ -741,7 +766,7 @@ MODULE_DEVICE_TABLE(of, musb_dsps_of_match);  static struct platform_driver dsps_usbss_driver = {  	.probe		= dsps_probe, -	.remove         = __devexit_p(dsps_remove), +	.remove         = dsps_remove,  	.driver         = {  		.name   = "musb-dsps",  		.pm	= &dsps_pm_ops, diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index b6b84dacc79..876787438c2 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1090,7 +1090,6 @@ static int musb_gadget_enable(struct usb_ep *ep,  	 */  	musb_ep_select(mbase, epnum);  	if (usb_endpoint_dir_in(desc)) { -		u16 int_txe = musb_readw(mbase, MUSB_INTRTXE);  		if (hw_ep->is_shared_fifo)  			musb_ep->is_in = 1; @@ -1102,8 +1101,8 @@ static int musb_gadget_enable(struct usb_ep *ep,  			goto fail;  		} -		int_txe |= (1 << epnum); -		musb_writew(mbase, MUSB_INTRTXE, int_txe); +		musb->intrtxe |= (1 << epnum); +		musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe);  		/* REVISIT if can_bulk_split(), use by updating "tmp";  		 * likewise high bandwidth periodic tx @@ -1130,7 +1129,6 @@ static int musb_gadget_enable(struct usb_ep *ep,  		musb_writew(regs, MUSB_TXCSR, csr);  	} else { -		u16 int_rxe = musb_readw(mbase, MUSB_INTRRXE);  		if (hw_ep->is_shared_fifo)  			musb_ep->is_in = 0; @@ -1142,8 +1140,8 @@ static int musb_gadget_enable(struct usb_ep *ep,  			goto fail;  		} -		int_rxe |= (1 << epnum); -		musb_writew(mbase, MUSB_INTRRXE, int_rxe); +		musb->intrrxe |= (1 << epnum); +		musb_writew(mbase, MUSB_INTRRXE, musb->intrrxe);  		/* REVISIT if can_bulk_combine() use by updating "tmp"  		 * likewise high bandwidth periodic rx @@ -1231,14 +1229,12 @@ static int musb_gadget_disable(struct usb_ep *ep)  	/* zero the endpoint sizes */  	if (musb_ep->is_in) { -		u16 int_txe = musb_readw(musb->mregs, MUSB_INTRTXE); -		int_txe &= ~(1 << epnum); -		musb_writew(musb->mregs, MUSB_INTRTXE, int_txe); +		musb->intrtxe &= ~(1 << epnum); +		musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe);  		musb_writew(epio, MUSB_TXMAXP, 0);  	} else { -		u16 int_rxe = musb_readw(musb->mregs, MUSB_INTRRXE); -		int_rxe &= ~(1 << epnum); -		musb_writew(musb->mregs, MUSB_INTRRXE, int_rxe); +		musb->intrrxe &= ~(1 << epnum); +		musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe);  		musb_writew(epio, MUSB_RXMAXP, 0);  	} @@ -1554,7 +1550,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)  	void __iomem	*epio = musb->endpoints[epnum].regs;  	void __iomem	*mbase;  	unsigned long	flags; -	u16		csr, int_txe; +	u16		csr;  	mbase = musb->mregs; @@ -1562,8 +1558,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)  	musb_ep_select(mbase, (u8) epnum);  	/* disable interrupts */ -	int_txe = musb_readw(mbase, MUSB_INTRTXE); -	musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum)); +	musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe & ~(1 << epnum));  	if (musb_ep->is_in) {  		csr = musb_readw(epio, MUSB_TXCSR); @@ -1587,7 +1582,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)  	}  	/* re-enable interrupt */ -	musb_writew(mbase, MUSB_INTRTXE, int_txe); +	musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe);  	spin_unlock_irqrestore(&musb->lock, flags);  } @@ -1792,7 +1787,7 @@ static void musb_gadget_release(struct device *dev)  } -static void __devinit +static void  init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)  {  	struct musb_hw_ep	*hw_ep = musb->endpoints + epnum; @@ -1829,7 +1824,7 @@ init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)   * Initialize the endpoints exposed to peripheral drivers, with backlinks   * to the rest of the driver state.   */ -static inline void __devinit musb_g_init_endpoints(struct musb *musb) +static inline void musb_g_init_endpoints(struct musb *musb)  {  	u8			epnum;  	struct musb_hw_ep	*hw_ep; @@ -1862,7 +1857,7 @@ static inline void __devinit musb_g_init_endpoints(struct musb *musb)  /* called once during driver setup to initialize and link into   * the driver model; memory is zeroed.   */ -int __devinit musb_gadget_setup(struct musb *musb) +int musb_gadget_setup(struct musb *musb)  {  	int status; @@ -2176,10 +2171,9 @@ __acquires(musb->lock)  	u8		devctl = musb_readb(mbase, MUSB_DEVCTL);  	u8		power; -	dev_dbg(musb->controller, "<== %s addr=%x driver '%s'\n", +	dev_dbg(musb->controller, "<== %s driver '%s'\n",  			(devctl & MUSB_DEVCTL_BDEVICE)  				? "B-Device" : "A-Device", -			musb_readb(mbase, MUSB_FADDR),  			musb->gadget_driver  				? musb->gadget_driver->driver.name  				: NULL diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index e40d7647caf..c9c1ac4e075 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -673,10 +673,8 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)  	csr = musb_readw(regs, MUSB_CSR0);  	len = musb_readb(regs, MUSB_COUNT0); -	dev_dbg(musb->controller, "csr %04x, count %d, myaddr %d, ep0stage %s\n", -			csr, len, -			musb_readb(mbase, MUSB_FADDR), -			decode_ep0stage(musb->ep0_state)); +	dev_dbg(musb->controller, "csr %04x, count %d, ep0stage %s\n", +			csr, len, decode_ep0stage(musb->ep0_state));  	if (csr & MUSB_CSR0_P_DATAEND) {  		/* diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 3df6a76b851..e9f0fd9ddd2 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -740,7 +740,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,  		csr = musb_readw(epio, MUSB_TXCSR);  		/* disable interrupt in case we flush */ -		int_txe = musb_readw(mbase, MUSB_INTRTXE); +		int_txe = musb->intrtxe;  		musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));  		/* general endpoint setup */ diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 0fc6ca6bc60..3d1fd52a15a 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -380,8 +380,7 @@ void dma_controller_destroy(struct dma_controller *c)  	kfree(controller);  } -struct dma_controller *__devinit -dma_controller_create(struct musb *musb, void __iomem *base) +struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *base)  {  	struct musb_dma_controller *controller;  	struct device *dev = musb->controller; diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h index 320fd4afb93..f7b13fd2525 100644 --- a/drivers/usb/musb/musbhsdma.h +++ b/drivers/usb/musb/musbhsdma.h @@ -31,10 +31,6 @@   *   */ -#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) -#include "omap2430.h" -#endif -  #ifndef CONFIG_BLACKFIN  #define MUSB_HSDMA_BASE		0x200 diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index a538fe17a96..da00af46079 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -333,6 +333,26 @@ static void omap_musb_mailbox_work(struct work_struct *mailbox_work)  	omap_musb_set_mailbox(glue);  } +static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci) +{ +	unsigned long   flags; +	irqreturn_t     retval = IRQ_NONE; +	struct musb     *musb = __hci; + +	spin_lock_irqsave(&musb->lock, flags); + +	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); +	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); +	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); + +	if (musb->int_usb || musb->int_tx || musb->int_rx) +		retval = musb_interrupt(musb); + +	spin_unlock_irqrestore(&musb->lock, flags); + +	return retval; +} +  static int omap2430_musb_init(struct musb *musb)  {  	u32 l; @@ -352,6 +372,8 @@ static int omap2430_musb_init(struct musb *musb)  		return -ENODEV;  	} +	musb->isr = omap2430_musb_interrupt; +  	status = pm_runtime_get_sync(dev);  	if (status < 0) {  		dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status); @@ -468,7 +490,7 @@ static const struct musb_platform_ops omap2430_ops = {  static u64 omap2430_dmamask = DMA_BIT_MASK(32); -static int __devinit omap2430_probe(struct platform_device *pdev) +static int omap2430_probe(struct platform_device *pdev)  {  	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;  	struct omap_musb_board_data	*data; @@ -478,7 +500,6 @@ static int __devinit omap2430_probe(struct platform_device *pdev)  	struct musb_hdrc_config		*config;  	struct resource			*res;  	int				ret = -ENOMEM; -	int				musbid;  	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);  	if (!glue) { @@ -486,21 +507,12 @@ static int __devinit omap2430_probe(struct platform_device *pdev)  		goto err0;  	} -	/* get the musb id */ -	musbid = musb_get_id(&pdev->dev, GFP_KERNEL); -	if (musbid < 0) { -		dev_err(&pdev->dev, "failed to allocate musb id\n"); -		ret = -ENOMEM; -		goto err0; -	} - -	musb = platform_device_alloc("musb-hdrc", musbid); +	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);  	if (!musb) {  		dev_err(&pdev->dev, "failed to allocate musb device\n"); -		goto err1; +		goto err0;  	} -	musb->id			= musbid;  	musb->dev.parent		= &pdev->dev;  	musb->dev.dma_mask		= &omap2430_dmamask;  	musb->dev.coherent_dma_mask	= omap2430_dmamask; @@ -521,7 +533,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev)  			dev_err(&pdev->dev,  				"failed to allocate musb platfrom data\n");  			ret = -ENOMEM; -			goto err1; +			goto err2;  		}  		data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); @@ -529,14 +541,14 @@ static int __devinit omap2430_probe(struct platform_device *pdev)  			dev_err(&pdev->dev,  					"failed to allocate musb board data\n");  			ret = -ENOMEM; -			goto err1; +			goto err2;  		}  		config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);  		if (!data) {  			dev_err(&pdev->dev,  				"failed to allocate musb hdrc config\n"); -			goto err1; +			goto err2;  		}  		of_property_read_u32(np, "mode", (u32 *)&pdata->mode); @@ -589,19 +601,15 @@ static int __devinit omap2430_probe(struct platform_device *pdev)  err2:  	platform_device_put(musb); -err1: -	musb_put_id(&pdev->dev, musbid); -  err0:  	return ret;  } -static int __devexit omap2430_remove(struct platform_device *pdev) +static int omap2430_remove(struct platform_device *pdev)  {  	struct omap2430_glue		*glue = platform_get_drvdata(pdev);  	cancel_work_sync(&glue->omap_musb_mailbox_work); -	musb_put_id(&pdev->dev, glue->musb->id);  	platform_device_unregister(glue->musb);  	return 0; @@ -666,7 +674,7 @@ MODULE_DEVICE_TABLE(of, omap2430_id_table);  static struct platform_driver omap2430_driver = {  	.probe		= omap2430_probe, -	.remove		= __devexit_p(omap2430_remove), +	.remove		= omap2430_remove,  	.driver		= {  		.name	= "musb-omap2430",  		.pm	= DEV_PM_OPS, diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index dc4d75ea13a..8bde6fc5eb7 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -1153,14 +1153,13 @@ static const struct musb_platform_ops tusb_ops = {  static u64 tusb_dmamask = DMA_BIT_MASK(32); -static int __devinit tusb_probe(struct platform_device *pdev) +static int tusb_probe(struct platform_device *pdev)  {  	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;  	struct platform_device		*musb;  	struct tusb6010_glue		*glue;  	int				ret = -ENOMEM; -	int				musbid;  	glue = kzalloc(sizeof(*glue), GFP_KERNEL);  	if (!glue) { @@ -1168,21 +1167,12 @@ static int __devinit tusb_probe(struct platform_device *pdev)  		goto err0;  	} -	/* get the musb id */ -	musbid = musb_get_id(&pdev->dev, GFP_KERNEL); -	if (musbid < 0) { -		dev_err(&pdev->dev, "failed to allocate musb id\n"); -		ret = -ENOMEM; -		goto err1; -	} - -	musb = platform_device_alloc("musb-hdrc", musbid); +	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);  	if (!musb) {  		dev_err(&pdev->dev, "failed to allocate musb device\n"); -		goto err2; +		goto err1;  	} -	musb->id			= musbid;  	musb->dev.parent		= &pdev->dev;  	musb->dev.dma_mask		= &tusb_dmamask;  	musb->dev.coherent_dma_mask	= tusb_dmamask; @@ -1218,9 +1208,6 @@ static int __devinit tusb_probe(struct platform_device *pdev)  err3:  	platform_device_put(musb); -err2: -	musb_put_id(&pdev->dev, musbid); -  err1:  	kfree(glue); @@ -1228,13 +1215,11 @@ err0:  	return ret;  } -static int __devexit tusb_remove(struct platform_device *pdev) +static int tusb_remove(struct platform_device *pdev)  {  	struct tusb6010_glue		*glue = platform_get_drvdata(pdev); -	musb_put_id(&pdev->dev, glue->musb->id); -	platform_device_del(glue->musb); -	platform_device_put(glue->musb); +	platform_device_unregister(glue->musb);  	kfree(glue);  	return 0; @@ -1242,7 +1227,7 @@ static int __devexit tusb_remove(struct platform_device *pdev)  static struct platform_driver tusb_driver = {  	.probe		= tusb_probe, -	.remove		= __devexit_p(tusb_remove), +	.remove		= tusb_remove,  	.driver		= {  		.name	= "musb-tusb",  	}, @@ -1251,15 +1236,4 @@ static struct platform_driver tusb_driver = {  MODULE_DESCRIPTION("TUSB6010 MUSB Glue Layer");  MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");  MODULE_LICENSE("GPL v2"); - -static int __init tusb_init(void) -{ -	return platform_driver_register(&tusb_driver); -} -module_init(tusb_init); - -static void __exit tusb_exit(void) -{ -	platform_driver_unregister(&tusb_driver); -} -module_exit(tusb_exit); +module_platform_driver(tusb_driver); diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c index 82310b6bc97..98df17c984a 100644 --- a/drivers/usb/musb/tusb6010_omap.c +++ b/drivers/usb/musb/tusb6010_omap.c @@ -668,8 +668,7 @@ void dma_controller_destroy(struct dma_controller *c)  	kfree(tusb_dma);  } -struct dma_controller *__devinit -dma_controller_create(struct musb *musb, void __iomem *base) +struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *base)  {  	void __iomem		*tbase = musb->ctrl_base;  	struct tusb_omap_dma	*tusb_dma; diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index 0e62f504410..a27ca1a9c99 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -36,6 +36,26 @@ struct ux500_glue {  };  #define glue_to_musb(g)	platform_get_drvdata(g->musb) +static irqreturn_t ux500_musb_interrupt(int irq, void *__hci) +{ +	unsigned long   flags; +	irqreturn_t     retval = IRQ_NONE; +	struct musb     *musb = __hci; + +	spin_lock_irqsave(&musb->lock, flags); + +	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); +	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); +	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); + +	if (musb->int_usb || musb->int_tx || musb->int_rx) +		retval = musb_interrupt(musb); + +	spin_unlock_irqrestore(&musb->lock, flags); + +	return retval; +} +  static int ux500_musb_init(struct musb *musb)  {  	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); @@ -44,6 +64,8 @@ static int ux500_musb_init(struct musb *musb)  		return -ENODEV;  	} +	musb->isr = ux500_musb_interrupt; +  	return 0;  } @@ -59,13 +81,12 @@ static const struct musb_platform_ops ux500_ops = {  	.exit		= ux500_musb_exit,  }; -static int __devinit ux500_probe(struct platform_device *pdev) +static int ux500_probe(struct platform_device *pdev)  {  	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;  	struct platform_device		*musb;  	struct ux500_glue		*glue;  	struct clk			*clk; -	int				musbid;  	int				ret = -ENOMEM;  	glue = kzalloc(sizeof(*glue), GFP_KERNEL); @@ -74,18 +95,10 @@ static int __devinit ux500_probe(struct platform_device *pdev)  		goto err0;  	} -	/* get the musb id */ -	musbid = musb_get_id(&pdev->dev, GFP_KERNEL); -	if (musbid < 0) { -		dev_err(&pdev->dev, "failed to allocate musb id\n"); -		ret = -ENOMEM; -		goto err1; -	} - -	musb = platform_device_alloc("musb-hdrc", musbid); +	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);  	if (!musb) {  		dev_err(&pdev->dev, "failed to allocate musb device\n"); -		goto err2; +		goto err1;  	}  	clk = clk_get(&pdev->dev, "usb"); @@ -101,7 +114,6 @@ static int __devinit ux500_probe(struct platform_device *pdev)  		goto err4;  	} -	musb->id			= musbid;  	musb->dev.parent		= &pdev->dev;  	musb->dev.dma_mask		= pdev->dev.dma_mask;  	musb->dev.coherent_dma_mask	= pdev->dev.coherent_dma_mask; @@ -144,9 +156,6 @@ err4:  err3:  	platform_device_put(musb); -err2: -	musb_put_id(&pdev->dev, musbid); -  err1:  	kfree(glue); @@ -154,13 +163,11 @@ err0:  	return ret;  } -static int __devexit ux500_remove(struct platform_device *pdev) +static int ux500_remove(struct platform_device *pdev)  {  	struct ux500_glue	*glue = platform_get_drvdata(pdev); -	musb_put_id(&pdev->dev, glue->musb->id); -	platform_device_del(glue->musb); -	platform_device_put(glue->musb); +	platform_device_unregister(glue->musb);  	clk_disable(glue->clk);  	clk_put(glue->clk);  	kfree(glue); @@ -209,7 +216,7 @@ static const struct dev_pm_ops ux500_pm_ops = {  static struct platform_driver ux500_driver = {  	.probe		= ux500_probe, -	.remove		= __devexit_p(ux500_remove), +	.remove		= ux500_remove,  	.driver		= {  		.name	= "musb-ux500",  		.pm	= DEV_PM_OPS, @@ -219,15 +226,4 @@ static struct platform_driver ux500_driver = {  MODULE_DESCRIPTION("UX500 MUSB Glue Layer");  MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>");  MODULE_LICENSE("GPL v2"); - -static int __init ux500_init(void) -{ -	return platform_driver_register(&ux500_driver); -} -module_init(ux500_init); - -static void __exit ux500_exit(void) -{ -	platform_driver_unregister(&ux500_driver); -} -module_exit(ux500_exit); +module_platform_driver(ux500_driver); diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index f1059e725ea..039e567dd3b 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -364,8 +364,7 @@ void dma_controller_destroy(struct dma_controller *c)  	kfree(controller);  } -struct dma_controller *__devinit -dma_controller_create(struct musb *musb, void __iomem *base) +struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *base)  {  	struct ux500_dma_controller *controller;  	struct platform_device *pdev = to_platform_device(musb->controller); diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c index ae8ad561f08..2d86f26a018 100644 --- a/drivers/usb/otg/ab8500-usb.c +++ b/drivers/usb/otg/ab8500-usb.c @@ -468,7 +468,7 @@ static int ab8500_usb_v2_res_setup(struct platform_device *pdev,  	return 0;  } -static int __devinit ab8500_usb_probe(struct platform_device *pdev) +static int ab8500_usb_probe(struct platform_device *pdev)  {  	struct ab8500_usb	*ab;  	struct usb_otg		*otg; @@ -546,7 +546,7 @@ fail0:  	return err;  } -static int __devexit ab8500_usb_remove(struct platform_device *pdev) +static int ab8500_usb_remove(struct platform_device *pdev)  {  	struct ab8500_usb *ab = platform_get_drvdata(pdev); @@ -571,7 +571,7 @@ static int __devexit ab8500_usb_remove(struct platform_device *pdev)  static struct platform_driver ab8500_usb_driver = {  	.probe		= ab8500_usb_probe, -	.remove		= __devexit_p(ab8500_usb_remove), +	.remove		= ab8500_usb_remove,  	.driver		= {  		.name	= "ab8500-usb",  		.owner	= THIS_MODULE, diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c index c19d1d7173a..d16adb41eb2 100644 --- a/drivers/usb/otg/fsl_otg.c +++ b/drivers/usb/otg/fsl_otg.c @@ -1110,7 +1110,7 @@ static const struct file_operations otg_fops = {  	.release = fsl_otg_release,  }; -static int __devinit fsl_otg_probe(struct platform_device *pdev) +static int fsl_otg_probe(struct platform_device *pdev)  {  	int ret; @@ -1144,7 +1144,7 @@ static int __devinit fsl_otg_probe(struct platform_device *pdev)  	return ret;  } -static int __devexit fsl_otg_remove(struct platform_device *pdev) +static int fsl_otg_remove(struct platform_device *pdev)  {  	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; @@ -1169,7 +1169,7 @@ static int __devexit fsl_otg_remove(struct platform_device *pdev)  struct platform_driver fsl_otg_driver = {  	.probe = fsl_otg_probe, -	.remove = __devexit_p(fsl_otg_remove), +	.remove = fsl_otg_remove,  	.driver = {  		.name = driver_name,  		.owner = THIS_MODULE, diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c index ceee2119bff..af9cb11626b 100644 --- a/drivers/usb/otg/isp1301_omap.c +++ b/drivers/usb/otg/isp1301_omap.c @@ -1493,7 +1493,7 @@ isp1301_start_hnp(struct usb_otg *otg)  /*-------------------------------------------------------------------------*/ -static int __devinit +static int  isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)  {  	int			status; diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c index 9f5fc906041..3b9f0d95113 100644 --- a/drivers/usb/otg/msm_otg.c +++ b/drivers/usb/otg/msm_otg.c @@ -1606,7 +1606,7 @@ free_motg:  	return ret;  } -static int __devexit msm_otg_remove(struct platform_device *pdev) +static int msm_otg_remove(struct platform_device *pdev)  {  	struct msm_otg *motg = platform_get_drvdata(pdev);  	struct usb_phy *phy = &motg->phy; @@ -1746,7 +1746,7 @@ static const struct dev_pm_ops msm_otg_dev_pm_ops = {  #endif  static struct platform_driver msm_otg_driver = { -	.remove = __devexit_p(msm_otg_remove), +	.remove = msm_otg_remove,  	.driver = {  		.name = DRIVER_NAME,  		.owner = THIS_MODULE, diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c index 3f124e8f579..1dd57504186 100644 --- a/drivers/usb/otg/mv_otg.c +++ b/drivers/usb/otg/mv_otg.c @@ -958,16 +958,4 @@ static struct platform_driver mv_otg_driver = {  	.resume = mv_otg_resume,  #endif  }; - -static int __init mv_otg_init(void) -{ -	return platform_driver_register(&mv_otg_driver); -} - -static void __exit mv_otg_exit(void) -{ -	platform_driver_unregister(&mv_otg_driver); -} - -module_init(mv_otg_init); -module_exit(mv_otg_exit); +module_platform_driver(mv_otg_driver); diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c index 88db976647c..76302720055 100644 --- a/drivers/usb/otg/mxs-phy.c +++ b/drivers/usb/otg/mxs-phy.c @@ -20,7 +20,6 @@  #include <linux/delay.h>  #include <linux/err.h>  #include <linux/io.h> -#include <linux/workqueue.h>  #define DRIVER_NAME "mxs_phy" @@ -35,16 +34,9 @@  #define BM_USBPHY_CTRL_ENUTMILEVEL2		BIT(14)  #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT	BIT(1) -/* - * Amount of delay in miliseconds to safely enable ENHOSTDISCONDETECT bit - * so that connection and reset processing can be completed for the root hub. - */ -#define MXY_PHY_ENHOSTDISCONDETECT_DELAY	250 -  struct mxs_phy {  	struct usb_phy phy;  	struct clk *clk; -	struct delayed_work enhostdiscondetect_work;  };  #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy) @@ -70,7 +62,6 @@ static int mxs_phy_init(struct usb_phy *phy)  	clk_prepare_enable(mxs_phy->clk);  	mxs_phy_hw_init(mxs_phy); -	INIT_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work, NULL);  	return 0;  } @@ -85,46 +76,28 @@ static void mxs_phy_shutdown(struct usb_phy *phy)  	clk_disable_unprepare(mxs_phy->clk);  } -static void mxs_phy_enhostdiscondetect_delay(struct work_struct *ws) +static int mxs_phy_on_connect(struct usb_phy *phy, +		enum usb_device_speed speed)  { -	struct mxs_phy *mxs_phy = container_of(ws, struct mxs_phy, -						enhostdiscondetect_work.work); - -	/* Enable HOSTDISCONDETECT after delay. */ -	dev_dbg(mxs_phy->phy.dev, "Setting ENHOSTDISCONDETECT\n"); -	writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, -				mxs_phy->phy.io_priv + HW_USBPHY_CTRL_SET); -} - -static int mxs_phy_on_connect(struct usb_phy *phy, int port) -{ -	struct mxs_phy *mxs_phy = to_mxs_phy(phy); - -	dev_dbg(phy->dev, "Connect on port %d\n", port); - -	mxs_phy_hw_init(mxs_phy); +	dev_dbg(phy->dev, "%s speed device has connected\n", +		(speed == USB_SPEED_HIGH) ? "high" : "non-high"); -	/* -	 * Delay enabling ENHOSTDISCONDETECT so that connection and -	 * reset processing can be completed for the root hub. -	 */ -	dev_dbg(phy->dev, "Delaying setting ENHOSTDISCONDETECT\n"); -	PREPARE_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work, -			mxs_phy_enhostdiscondetect_delay); -	schedule_delayed_work(&mxs_phy->enhostdiscondetect_work, -			msecs_to_jiffies(MXY_PHY_ENHOSTDISCONDETECT_DELAY)); +	if (speed == USB_SPEED_HIGH) +		writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, +				phy->io_priv + HW_USBPHY_CTRL_SET);  	return 0;  } -static int mxs_phy_on_disconnect(struct usb_phy *phy, int port) +static int mxs_phy_on_disconnect(struct usb_phy *phy, +		enum usb_device_speed speed)  { -	dev_dbg(phy->dev, "Disconnect on port %d\n", port); +	dev_dbg(phy->dev, "%s speed device has disconnected\n", +		(speed == USB_SPEED_HIGH) ? "high" : "non-high"); -	/* No need to delay before clearing ENHOSTDISCONDETECT. */ -	dev_dbg(phy->dev, "Clearing ENHOSTDISCONDETECT\n"); -	writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, -			phy->io_priv + HW_USBPHY_CTRL_CLR); +	if (speed == USB_SPEED_HIGH) +		writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, +				phy->io_priv + HW_USBPHY_CTRL_CLR);  	return 0;  } @@ -176,7 +149,7 @@ static int mxs_phy_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit mxs_phy_remove(struct platform_device *pdev) +static int mxs_phy_remove(struct platform_device *pdev)  {  	platform_set_drvdata(pdev, NULL); @@ -191,7 +164,7 @@ MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);  static struct platform_driver mxs_phy_driver = {  	.probe = mxs_phy_probe, -	.remove = __devexit_p(mxs_phy_remove), +	.remove = mxs_phy_remove,  	.driver = {  		.name = DRIVER_NAME,  		.owner	= THIS_MODULE, diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index e52e35e7ada..a3ce24b94a7 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -93,7 +93,7 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)  	return 0;  } -static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) +static int nop_usb_xceiv_probe(struct platform_device *pdev)  {  	struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data;  	struct nop_usb_xceiv	*nop; @@ -141,7 +141,7 @@ exit:  	return err;  } -static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev) +static int nop_usb_xceiv_remove(struct platform_device *pdev)  {  	struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); @@ -156,7 +156,7 @@ static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)  static struct platform_driver nop_usb_xceiv_driver = {  	.probe		= nop_usb_xceiv_probe, -	.remove		= __devexit_p(nop_usb_xceiv_remove), +	.remove		= nop_usb_xceiv_remove,  	.driver		= {  		.name	= "nop_usb_xceiv",  		.owner	= THIS_MODULE, diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index f0d2e7530cf..0a701938ab5 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -123,10 +123,10 @@  #define PHY_CLK_CTRL_STS		0xFF  #define PHY_DPLL_CLK			(1 << 0) -/* In module TWL4030_MODULE_PM_MASTER */ +/* In module TWL_MODULE_PM_MASTER */  #define STS_HW_CONDITIONS		0x0F -/* In module TWL4030_MODULE_PM_RECEIVER */ +/* In module TWL_MODULE_PM_RECEIVER */  #define VUSB_DEDICATED1			0x7D  #define VUSB_DEDICATED2			0x7E  #define VUSB1V5_DEV_GRP			0x71 @@ -195,14 +195,14 @@ static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,  }  #define twl4030_usb_write_verify(twl, address, data)	\ -	twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_USB, (data), (address)) +	twl4030_i2c_write_u8_verify(twl, TWL_MODULE_USB, (data), (address))  static inline int twl4030_usb_write(struct twl4030_usb *twl,  		u8 address, u8 data)  {  	int ret = 0; -	ret = twl_i2c_write_u8(TWL4030_MODULE_USB, data, address); +	ret = twl_i2c_write_u8(TWL_MODULE_USB, data, address);  	if (ret < 0)  		dev_dbg(twl->dev,  			"TWL4030:USB:Write[0x%x] Error %d\n", address, ret); @@ -227,7 +227,7 @@ static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address)  static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address)  { -	return twl4030_readb(twl, TWL4030_MODULE_USB, address); +	return twl4030_readb(twl, TWL_MODULE_USB, address);  }  /*-------------------------------------------------------------------------*/ @@ -264,8 +264,7 @@ static enum omap_musb_vbus_id_status  	 * signal is active, the OTG module is activated, and  	 * its interrupt may be raised (may wake the system).  	 */ -	status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER, -			STS_HW_CONDITIONS); +	status = twl4030_readb(twl, TWL_MODULE_PM_MASTER, STS_HW_CONDITIONS);  	if (status < 0)  		dev_err(twl->dev, "USB link status err %d\n", status);  	else if (status & (BIT(7) | BIT(2))) { @@ -372,8 +371,7 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)  		 * SLEEP. We work around this by clearing the bit after usv3v1  		 * is re-activated. This ensures that VUSB3V1 is really active.  		 */ -		twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, -							VUSB_DEDICATED2); +		twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);  		regulator_enable(twl->usb1v5);  		__twl4030_phy_power(twl, 1);  		twl4030_usb_write(twl, PHY_CLK_CTRL, @@ -419,50 +417,48 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)  static int twl4030_usb_ldo_init(struct twl4030_usb *twl)  {  	/* Enable writing to power configuration registers */ -	twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, -			TWL4030_PM_MASTER_KEY_CFG1, -			TWL4030_PM_MASTER_PROTECT_KEY); +	twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1, +			 TWL4030_PM_MASTER_PROTECT_KEY); -	twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, -			TWL4030_PM_MASTER_KEY_CFG2, -			TWL4030_PM_MASTER_PROTECT_KEY); +	twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2, +			 TWL4030_PM_MASTER_PROTECT_KEY);  	/* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/ -	/*twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/ +	/*twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/  	/* input to VUSB3V1 LDO is from VBAT, not VBUS */ -	twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); +	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);  	/* Initialize 3.1V regulator */ -	twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); +	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);  	twl->usb3v1 = regulator_get(twl->dev, "usb3v1");  	if (IS_ERR(twl->usb3v1))  		return -ENODEV; -	twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); +	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);  	/* Initialize 1.5V regulator */ -	twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); +	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);  	twl->usb1v5 = regulator_get(twl->dev, "usb1v5");  	if (IS_ERR(twl->usb1v5))  		goto fail1; -	twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); +	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);  	/* Initialize 1.8V regulator */ -	twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); +	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);  	twl->usb1v8 = regulator_get(twl->dev, "usb1v8");  	if (IS_ERR(twl->usb1v8))  		goto fail2; -	twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); +	twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);  	/* disable access to power configuration registers */ -	twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, -			TWL4030_PM_MASTER_PROTECT_KEY); +	twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0, +			 TWL4030_PM_MASTER_PROTECT_KEY);  	return 0; @@ -579,7 +575,7 @@ static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host)  	return 0;  } -static int __devinit twl4030_usb_probe(struct platform_device *pdev) +static int twl4030_usb_probe(struct platform_device *pdev)  {  	struct twl4030_usb_data *pdata = pdev->dev.platform_data;  	struct twl4030_usb	*twl; diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index fcadef7864f..8cd6cf49bdb 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c @@ -310,7 +310,7 @@ static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)  	return 0;  } -static int __devinit twl6030_usb_probe(struct platform_device *pdev) +static int twl6030_usb_probe(struct platform_device *pdev)  {  	u32 ret;  	struct twl6030_usb	*twl; diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 63c339b3e67..7eb73c561bd 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -32,3 +32,15 @@ config MV_U3D_PHY  	help  	  Enable this to support Marvell USB 3.0 phy controller for Marvell  	  SoC. + +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. +	  This driver supports: R8A7779 + +	  To compile this driver as a module, choose M here: the +	  module will be called rcar-phy. diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index b069f29f122..1a579a860a0 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_OMAP_USB2)			+= omap-usb2.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 diff --git a/drivers/usb/phy/mv_u3d_phy.c b/drivers/usb/phy/mv_u3d_phy.c index 9f1c5d3c60e..eaddbe3d430 100644 --- a/drivers/usb/phy/mv_u3d_phy.c +++ b/drivers/usb/phy/mv_u3d_phy.c @@ -262,7 +262,7 @@ calstart:  	return 0;  } -static int __devinit mv_u3d_phy_probe(struct platform_device *pdev) +static int mv_u3d_phy_probe(struct platform_device *pdev)  {  	struct mv_u3d_phy *mv_u3d_phy;  	struct mv_usb_platform_data *pdata; @@ -331,7 +331,7 @@ static int __exit mv_u3d_phy_remove(struct platform_device *pdev)  static struct platform_driver mv_u3d_phy_driver = {  	.probe		= mv_u3d_phy_probe, -	.remove		= __devexit_p(mv_u3d_phy_remove), +	.remove		= mv_u3d_phy_remove,  	.driver		= {  		.name	= "mv-u3d-phy",  		.owner	= THIS_MODULE, diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/omap-usb2.c index 15ab3d6f2e8..26ae8f49225 100644 --- a/drivers/usb/phy/omap-usb2.c +++ b/drivers/usb/phy/omap-usb2.c @@ -141,7 +141,7 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)  	return 0;  } -static int __devinit omap_usb2_probe(struct platform_device *pdev) +static int omap_usb2_probe(struct platform_device *pdev)  {  	struct omap_usb			*phy;  	struct usb_otg			*otg; @@ -199,7 +199,7 @@ static int __devinit omap_usb2_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit omap_usb2_remove(struct platform_device *pdev) +static int omap_usb2_remove(struct platform_device *pdev)  {  	struct omap_usb	*phy = platform_get_drvdata(pdev); @@ -254,7 +254,7 @@ MODULE_DEVICE_TABLE(of, omap_usb2_id_table);  static struct platform_driver omap_usb2_driver = {  	.probe		= omap_usb2_probe, -	.remove		= __devexit_p(omap_usb2_remove), +	.remove		= omap_usb2_remove,  	.driver		= {  		.name	= "omap-usb2",  		.owner	= THIS_MODULE, diff --git a/drivers/usb/phy/rcar-phy.c b/drivers/usb/phy/rcar-phy.c new file mode 100644 index 00000000000..a35681b0c50 --- /dev/null +++ b/drivers/usb/phy/rcar-phy.c @@ -0,0 +1,220 @@ +/* + * Renesas R-Car USB phy driver + * + * Copyright (C) 2012 Renesas Solutions Corp. + * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/usb/otg.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> +#include <linux/module.h> + +/* USBH common register */ +#define USBPCTRL0	0x0800 +#define USBPCTRL1	0x0804 +#define USBST		0x0808 +#define USBEH0		0x080C +#define USBOH0		0x081C +#define USBCTL0		0x0858 +#define EIIBC1		0x0094 +#define EIIBC2		0x009C + +/* USBPCTRL1 */ +#define PHY_RST		(1 << 2) +#define PLL_ENB		(1 << 1) +#define PHY_ENB		(1 << 0) + +/* USBST */ +#define ST_ACT		(1 << 31) +#define ST_PLL		(1 << 30) + +struct rcar_usb_phy_priv { +	struct usb_phy phy; +	spinlock_t lock; + +	void __iomem *reg0; +	void __iomem *reg1; +	int counter; +}; + +#define usb_phy_to_priv(p) container_of(p, struct rcar_usb_phy_priv, phy) + + +/* + * USB initial/install operation. + * + * This function setup USB phy. + * The used value and setting order came from + * [USB :: Initial setting] on datasheet. + */ +static int rcar_usb_phy_init(struct usb_phy *phy) +{ +	struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy); +	struct device *dev = phy->dev; +	void __iomem *reg0 = priv->reg0; +	void __iomem *reg1 = priv->reg1; +	int i; +	u32 val; +	unsigned long flags; + +	spin_lock_irqsave(&priv->lock, flags); +	if (priv->counter++ == 0) { + +		/* +		 * USB phy start-up +		 */ + +		/* (1) USB-PHY standby release */ +		iowrite32(PHY_ENB, (reg0 + USBPCTRL1)); + +		/* (2) start USB-PHY internal PLL */ +		iowrite32(PHY_ENB | PLL_ENB, (reg0 + USBPCTRL1)); + +		/* (3) USB module status check */ +		for (i = 0; i < 1024; i++) { +			udelay(10); +			val = ioread32(reg0 + USBST); +			if (val == (ST_ACT | ST_PLL)) +				break; +		} + +		if (val != (ST_ACT | ST_PLL)) { +			dev_err(dev, "USB phy not ready\n"); +			goto phy_init_end; +		} + +		/* (4) USB-PHY reset clear */ +		iowrite32(PHY_ENB | PLL_ENB | PHY_RST, (reg0 + USBPCTRL1)); + +		/* set platform specific port settings */ +		iowrite32(0x00000000, (reg0 + USBPCTRL0)); + +		/* +		 * EHCI IP internal buffer setting +		 * EHCI IP internal buffer enable +		 * +		 * These are recommended value of a datasheet +		 * see [USB :: EHCI internal buffer setting] +		 */ +		iowrite32(0x00ff0040, (reg0 + EIIBC1)); +		iowrite32(0x00ff0040, (reg1 + EIIBC1)); + +		iowrite32(0x00000001, (reg0 + EIIBC2)); +		iowrite32(0x00000001, (reg1 + EIIBC2)); + +		/* +		 * Bus alignment settings +		 */ + +		/* (1) EHCI bus alignment (little endian) */ +		iowrite32(0x00000000, (reg0 + USBEH0)); + +		/* (1) OHCI bus alignment (little endian) */ +		iowrite32(0x00000000, (reg0 + USBOH0)); +	} + +phy_init_end: +	spin_unlock_irqrestore(&priv->lock, flags); + +	return 0; +} + +static void rcar_usb_phy_shutdown(struct usb_phy *phy) +{ +	struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy); +	void __iomem *reg0 = priv->reg0; +	unsigned long flags; + +	spin_lock_irqsave(&priv->lock, flags); + +	if (priv->counter-- == 1) { /* last user */ +		iowrite32(0x00000000, (reg0 + USBPCTRL0)); +		iowrite32(0x00000000, (reg0 + USBPCTRL1)); +	} + +	spin_unlock_irqrestore(&priv->lock, flags); +} + +static int rcar_usb_phy_probe(struct platform_device *pdev) +{ +	struct rcar_usb_phy_priv *priv; +	struct resource *res0, *res1; +	struct device *dev = &pdev->dev; +	void __iomem *reg0, *reg1; +	int ret; + +	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); +	if (!res0 || !res1) { +		dev_err(dev, "Not enough platform resources\n"); +		return -EINVAL; +	} + +	/* +	 * CAUTION +	 * +	 * Because this phy address is also mapped under OHCI/EHCI address area, +	 * this driver can't use devm_request_and_ioremap(dev, res) here +	 */ +	reg0 = devm_ioremap_nocache(dev, res0->start, resource_size(res0)); +	reg1 = devm_ioremap_nocache(dev, res1->start, resource_size(res1)); +	if (!reg0 || !reg1) { +		dev_err(dev, "ioremap error\n"); +		return -ENOMEM; +	} + +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +	if (!priv) { +		dev_err(dev, "priv data allocation error\n"); +		return -ENOMEM; +	} + +	priv->reg0		= reg0; +	priv->reg1		= reg1; +	priv->counter		= 0; +	priv->phy.dev		= dev; +	priv->phy.label		= dev_name(dev); +	priv->phy.init		= rcar_usb_phy_init; +	priv->phy.shutdown	= rcar_usb_phy_shutdown; +	spin_lock_init(&priv->lock); + +	ret = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2); +	if (ret < 0) { +		dev_err(dev, "usb phy addition error\n"); +		return ret; +	} + +	platform_set_drvdata(pdev, priv); + +	return ret; +} + +static int rcar_usb_phy_remove(struct platform_device *pdev) +{ +	struct rcar_usb_phy_priv *priv = platform_get_drvdata(pdev); + +	usb_remove_phy(&priv->phy); + +	return 0; +} + +static struct platform_driver rcar_usb_phy_driver = { +	.driver		= { +		.name	= "rcar_usb_phy", +	}, +	.probe		= rcar_usb_phy_probe, +	.remove		= rcar_usb_phy_remove, +}; + +module_platform_driver(rcar_usb_phy_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Renesas R-Car USB phy"); +MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index 072edc1cc55..38bce046f4d 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -132,6 +132,11 @@ void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable)  	usbhs_bset(priv, SYSCFG, mask, enable ? val : 0);  } +void usbhs_sys_function_pullup(struct usbhs_priv *priv, int enable) +{ +	usbhs_bset(priv, SYSCFG, DPRPU, enable ? DPRPU : 0); +} +  void usbhs_sys_set_test_mode(struct usbhs_priv *priv, u16 mode)  {  	usbhs_write(priv, TESTMODE, mode); @@ -551,7 +556,7 @@ probe_end_pipe_exit:  	return ret;  } -static int __devexit usbhs_remove(struct platform_device *pdev) +static int usbhs_remove(struct platform_device *pdev)  {  	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);  	struct renesas_usbhs_platform_info *info = pdev->dev.platform_data; @@ -631,7 +636,7 @@ static struct platform_driver renesas_usbhs_driver = {  		.pm	= &usbhsc_pm_ops,  	},  	.probe		= usbhs_probe, -	.remove		= __devexit_p(usbhs_remove), +	.remove		= usbhs_remove,  };  module_platform_driver(renesas_usbhs_driver); diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h index dddf40a59de..c69dd2fba36 100644 --- a/drivers/usb/renesas_usbhs/common.h +++ b/drivers/usb/renesas_usbhs/common.h @@ -285,6 +285,7 @@ void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data);   */  void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable);  void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable); +void usbhs_sys_function_pullup(struct usbhs_priv *priv, int enable);  void usbhs_sys_set_test_mode(struct usbhs_priv *priv, u16 mode);  /* diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index c021b202c0f..9538f0feafe 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -163,7 +163,7 @@ static int usbhsf_pkt_handler(struct usbhs_pipe *pipe, int type)  		func = pkt->handler->dma_done;  		break;  	default: -		dev_err(dev, "unknown pkt hander\n"); +		dev_err(dev, "unknown pkt handler\n");  		goto __usbhs_pkt_handler_end;  	} @@ -192,8 +192,8 @@ void usbhs_pkt_start(struct usbhs_pipe *pipe)  /*   *		irq enable/disable function   */ -#define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e) -#define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e) +#define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, irq_bempsts, e) +#define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, irq_brdysts, e)  #define usbhsf_irq_callback_ctrl(pipe, status, enable)			\  	({								\  		struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);	\ @@ -202,9 +202,9 @@ void usbhs_pkt_start(struct usbhs_pipe *pipe)  		if (!mod)						\  			return;						\  		if (enable)						\ -			mod->irq_##status |= status;			\ +			mod->status |= status;				\  		else							\ -			mod->irq_##status &= ~status;			\ +			mod->status &= ~status;				\  		usbhs_irq_callback_update(priv, mod);			\  	}) @@ -488,6 +488,8 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)  	usbhs_pipe_data_sequence(pipe, pkt->sequence);  	pkt->sequence = -1; /* -1 sequence will be ignored */ +	usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length); +  	ret = usbhsf_fifo_select(pipe, fifo, 1);  	if (ret < 0)  		return 0; @@ -594,6 +596,7 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)  	usbhs_pipe_data_sequence(pipe, pkt->sequence);  	pkt->sequence = -1; /* -1 sequence will be ignored */ +	usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length);  	usbhs_pipe_enable(pipe);  	usbhsf_rx_irq_ctrl(pipe, 1); @@ -795,6 +798,7 @@ static void xfer_work(struct work_struct *work)  	dev_dbg(dev, "  %s %d (%d/ %d)\n",  		fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); +	usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);  	usbhs_pipe_enable(pipe);  	usbhsf_dma_start(pipe, fifo);  	dma_async_issue_pending(chan); diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 61933a90e5b..6a030b931a3 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c @@ -151,7 +151,7 @@ int usbhs_mod_probe(struct usbhs_priv *priv)  		goto mod_init_host_err;  	/* irq settings */ -	ret = request_irq(priv->irq, usbhs_interrupt, +	ret = devm_request_irq(dev, priv->irq, usbhs_interrupt,  			  priv->irqflags, dev_name(dev), priv);  	if (ret) {  		dev_err(dev, "irq request err\n"); @@ -172,7 +172,6 @@ void usbhs_mod_remove(struct usbhs_priv *priv)  {  	usbhs_mod_host_remove(priv);  	usbhs_mod_gadget_remove(priv); -	free_irq(priv->irq, priv);  }  /* diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 28478ce26c3..dd41f61893e 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -883,6 +883,16 @@ static int usbhsg_get_frame(struct usb_gadget *gadget)  	return usbhs_frame_get_num(priv);  } +static int usbhsg_pullup(struct usb_gadget *gadget, int is_on) +{ +	struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); +	struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); + +	usbhs_sys_function_pullup(priv, is_on); + +	return 0; +} +  static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self)  {  	struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); @@ -900,6 +910,7 @@ static struct usb_gadget_ops usbhsg_gadget_ops = {  	.set_selfpowered	= usbhsg_set_selfpowered,  	.udc_start		= usbhsg_gadget_start,  	.udc_stop		= usbhsg_gadget_stop, +	.pullup			= usbhsg_pullup,  };  static int usbhsg_start(struct usbhs_priv *priv) diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 069cd765400..3d3cd6ca268 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -85,6 +85,7 @@ struct usbhsh_ep {  	struct usbhsh_device	*udev;   /* attached udev */  	struct usb_host_endpoint *ep;  	struct list_head	ep_list; /* list to usbhsh_device */ +	unsigned int		counter; /* pipe attach counter */  };  #define USBHSH_DEVICE_MAX	10 /* see DEVADDn / DCPMAXP / PIPEMAXP */ @@ -271,8 +272,12 @@ static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv,  	/********************  spin lock ********************/  	usbhs_lock(priv, flags); -	if (unlikely(usbhsh_uep_to_pipe(uep))) { -		dev_err(dev, "uep already has pipe\n"); +	/* +	 * if uep has been attached to pipe, +	 * reuse it +	 */ +	if (usbhsh_uep_to_pipe(uep)) { +		ret = 0;  		goto usbhsh_pipe_attach_done;  	} @@ -320,6 +325,9 @@ static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv,  	}  usbhsh_pipe_attach_done: +	if (0 == ret) +		uep->counter++; +  	usbhs_unlock(priv, flags);  	/********************  spin unlock ******************/ @@ -346,7 +354,7 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,  	if (unlikely(!pipe)) {  		dev_err(dev, "uep doens't have pipe\n"); -	} else { +	} else if (1 == uep->counter--) { /* last user */  		struct usb_host_endpoint *ep = usbhsh_uep_to_ep(uep);  		struct usbhsh_device *udev = usbhsh_uep_to_udev(uep); @@ -391,6 +399,7 @@ static int usbhsh_endpoint_attach(struct usbhsh_hpriv *hpriv,  	/*  	 * init endpoint  	 */ +	uep->counter = 0;  	INIT_LIST_HEAD(&uep->ep_list);  	list_add_tail(&uep->ep_list, &udev->ep_list_head); @@ -686,9 +695,9 @@ static int usbhsh_queue_push(struct usb_hcd *hcd,  	}  	if (usb_pipein(urb->pipe)) -		pipe->handler = &usbhs_fifo_pio_pop_handler; +		pipe->handler = &usbhs_fifo_dma_pop_handler;  	else -		pipe->handler = &usbhs_fifo_pio_push_handler; +		pipe->handler = &usbhs_fifo_dma_push_handler;  	buf = (void *)(urb->transfer_buffer + urb->actual_length);  	len = urb->transfer_buffer_length - urb->actual_length; @@ -921,6 +930,19 @@ static int usbhsh_dcp_queue_push(struct usb_hcd *hcd,   */  static int usbhsh_dma_map_ctrl(struct usbhs_pkt *pkt, int map)  { +	if (map) { +		struct usbhsh_request *ureq = usbhsh_pkt_to_ureq(pkt); +		struct urb *urb = ureq->urb; + +		/* it can not use scatter/gather */ +		if (urb->num_sgs) +			return -EINVAL; + +		pkt->dma = urb->transfer_dma; +		if (!pkt->dma) +			return -EINVAL; +	} +  	return 0;  } @@ -946,7 +968,6 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,  	struct usb_host_endpoint *ep = urb->ep;  	struct usbhsh_device *new_udev = NULL;  	int is_dir_in = usb_pipein(urb->pipe); -	int i;  	int ret;  	dev_dbg(dev, "%s (%s)\n", __func__, is_dir_in ? "in" : "out"); @@ -992,13 +1013,7 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,  	 * attach pipe to endpoint  	 * see [image of mod_host]  	 */ -	for (i = 0; i < 1024; i++) { -		ret = usbhsh_pipe_attach(hpriv, urb); -		if (ret < 0) -			msleep(100); -		else -			break; -	} +	ret = usbhsh_pipe_attach(hpriv, urb);  	if (ret < 0) {  		dev_err(dev, "pipe attach failed\n");  		goto usbhsh_urb_enqueue_error_free_endpoint; @@ -1072,8 +1087,6 @@ static void usbhsh_endpoint_disable(struct usb_hcd *hcd,  static int usbhsh_hub_status_data(struct usb_hcd *hcd, char *buf)  {  	struct usbhsh_hpriv *hpriv = usbhsh_hcd_to_hpriv(hcd); -	struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); -	struct device *dev = usbhs_priv_to_dev(priv);  	int roothub_id = 1; /* only 1 root hub */  	/* @@ -1085,8 +1098,6 @@ static int usbhsh_hub_status_data(struct usb_hcd *hcd, char *buf)  	else  		*buf = 0; -	dev_dbg(dev, "%s (%02x)\n", __func__, *buf); -  	return !!(*buf);  } diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index 122526cfd32..7926e1c700f 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -93,6 +93,82 @@ static void usbhsp_pipe_cfg_set(struct usbhs_pipe *pipe, u16 mask, u16 val)  }  /* + *		PIPEnTRN/PIPEnTRE functions + */ +static void usbhsp_pipe_trn_set(struct usbhs_pipe *pipe, u16 mask, u16 val) +{ +	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); +	struct device *dev = usbhs_priv_to_dev(priv); +	int num = usbhs_pipe_number(pipe); +	u16 reg; + +	/* +	 * It is impossible to calculate address, +	 * since PIPEnTRN addresses were mapped randomly. +	 */ +#define CASE_PIPExTRN(a)		\ +	case 0x ## a:			\ +		reg = PIPE ## a ## TRN;	\ +		break; + +	switch (num) { +	CASE_PIPExTRN(1); +	CASE_PIPExTRN(2); +	CASE_PIPExTRN(3); +	CASE_PIPExTRN(4); +	CASE_PIPExTRN(5); +	CASE_PIPExTRN(B); +	CASE_PIPExTRN(C); +	CASE_PIPExTRN(D); +	CASE_PIPExTRN(E); +	CASE_PIPExTRN(F); +	CASE_PIPExTRN(9); +	CASE_PIPExTRN(A); +	default: +		dev_err(dev, "unknown pipe (%d)\n", num); +		return; +	} +	__usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val); +} + +static void usbhsp_pipe_tre_set(struct usbhs_pipe *pipe, u16 mask, u16 val) +{ +	struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); +	struct device *dev = usbhs_priv_to_dev(priv); +	int num = usbhs_pipe_number(pipe); +	u16 reg; + +	/* +	 * It is impossible to calculate address, +	 * since PIPEnTRE addresses were mapped randomly. +	 */ +#define CASE_PIPExTRE(a)			\ +	case 0x ## a:				\ +		reg = PIPE ## a ## TRE;		\ +		break; + +	switch (num) { +	CASE_PIPExTRE(1); +	CASE_PIPExTRE(2); +	CASE_PIPExTRE(3); +	CASE_PIPExTRE(4); +	CASE_PIPExTRE(5); +	CASE_PIPExTRE(B); +	CASE_PIPExTRE(C); +	CASE_PIPExTRE(D); +	CASE_PIPExTRE(E); +	CASE_PIPExTRE(F); +	CASE_PIPExTRE(9); +	CASE_PIPExTRE(A); +	default: +		dev_err(dev, "unknown pipe (%d)\n", num); +		return; +	} + +	__usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val); +} + +/*   *		PIPEBUF   */  static void usbhsp_pipe_buf_set(struct usbhs_pipe *pipe, u16 mask, u16 val) @@ -264,6 +340,31 @@ int usbhs_pipe_is_stall(struct usbhs_pipe *pipe)  	return (int)(pid == PID_STALL10 || pid == PID_STALL11);  } +void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len) +{ +	if (!usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK)) +		return; + +	/* +	 * clear and disable transfer counter for IN/OUT pipe +	 */ +	usbhsp_pipe_tre_set(pipe, TRCLR | TRENB, TRCLR); + +	/* +	 * Only IN direction bulk pipe can use transfer count. +	 * Without using this function, +	 * received data will break if it was large data size. +	 * see PIPEnTRN/PIPEnTRE for detail +	 */ +	if (usbhs_pipe_is_dir_in(pipe)) { +		int maxp = usbhs_pipe_get_maxpacket(pipe); + +		usbhsp_pipe_trn_set(pipe, 0xffff, DIV_ROUND_UP(len, maxp)); +		usbhsp_pipe_tre_set(pipe, TRENB, TRENB); /* enable */ +	} +} + +  /*   *		pipe setup   */ diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 3d80c7b1fd1..b476fde955b 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -88,6 +88,7 @@ void usbhs_pipe_enable(struct usbhs_pipe *pipe);  void usbhs_pipe_disable(struct usbhs_pipe *pipe);  void usbhs_pipe_stall(struct usbhs_pipe *pipe);  int usbhs_pipe_is_stall(struct usbhs_pipe *pipe); +void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len);  void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo);  void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel,  			      u16 epnum, u16 maxp); diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index 54e1bb6372e..6d110a3bc7e 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -68,10 +68,6 @@  #define THROTTLED		0x01  #define ACTUALLY_THROTTLED	0x02 -/* - * Version Information - */ -#define DRIVER_VERSION "v2.0"  #define DRIVER_AUTHOR "Naranjo, Manuel Francisco <naranjo.manuel@gmail.com>, Johan Hovold <jhovold@gmail.com>"  #define DRIVER_DESC "AIRcable USB Driver" @@ -192,5 +188,4 @@ module_usb_serial_driver(serial_drivers, id_table);  MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION);  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index bd50a8a41a0..a88882c0e23 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -37,11 +37,6 @@  #include <linux/mutex.h>  #include <linux/spinlock.h> -/* - * Version information - */ - -#define DRIVER_VERSION "v0.7"  #define DRIVER_AUTHOR "Bart Hartgers <bart.hartgers+ark3116@gmail.com>"  #define DRIVER_DESC "USB ARK3116 serial/IrDA driver"  #define DRIVER_DEV_DESC "ARK3116 RS232/IrDA" diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index ea29556f0d7..b72a4c16670 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -37,10 +37,6 @@  #include <linux/usb/serial.h>  #include "belkin_sa.h" -/* - * Version Information - */ -#define DRIVER_VERSION "v1.3"  #define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>"  #define DRIVER_DESC "USB Belkin Serial converter driver" @@ -509,5 +505,4 @@ module_usb_serial_driver(serial_drivers, id_table);  MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION);  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index c15f2e7cefc..37decb13d7e 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -121,7 +121,6 @@ static int usb_serial_device_remove(struct device *dev)  	return retval;  } -#ifdef CONFIG_HOTPLUG  static ssize_t store_new_id(struct device_driver *driver,  			    const char *buf, size_t count)  { @@ -159,15 +158,6 @@ static void free_dynids(struct usb_serial_driver *drv)  	spin_unlock(&drv->dynids.lock);  } -#else -static struct driver_attribute drv_attrs[] = { -	__ATTR_NULL, -}; -static inline void free_dynids(struct usb_serial_driver *drv) -{ -} -#endif -  struct bus_type usb_serial_bus_type = {  	.name =		"usb-serial",  	.match =	usb_serial_device_match, diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index eb033fc92a1..f14736f647f 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -24,10 +24,6 @@  #include <linux/uaccess.h>  #include <linux/usb/serial.h> -/* - * Version Information - */ -#define DRIVER_VERSION "v0.09"  #define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver"  /* @@ -35,8 +31,7 @@   */  static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *);  static void cp210x_close(struct usb_serial_port *); -static void cp210x_get_termios(struct tty_struct *, -	struct usb_serial_port *port); +static void cp210x_get_termios(struct tty_struct *, struct usb_serial_port *);  static void cp210x_get_termios_port(struct usb_serial_port *port,  	unsigned int *cflagp, unsigned int *baudp);  static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *, @@ -118,6 +113,7 @@ static const struct usb_device_id id_table[] = {  	{ USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */  	{ USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */  	{ USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */ +	{ USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */  	{ USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */  	{ USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */  	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ @@ -169,7 +165,7 @@ struct cp210x_serial_private {  static struct usb_serial_driver cp210x_device = {  	.driver = {  		.owner =	THIS_MODULE, -		.name = 	"cp210x", +		.name =		"cp210x",  	},  	.id_table		= id_table,  	.num_ports		= 1, @@ -179,7 +175,7 @@ static struct usb_serial_driver cp210x_device = {  	.close			= cp210x_close,  	.break_ctl		= cp210x_break_ctl,  	.set_termios		= cp210x_set_termios, -	.tiocmget 		= cp210x_tiocmget, +	.tiocmget		= cp210x_tiocmget,  	.tiocmset		= cp210x_tiocmset,  	.attach			= cp210x_startup,  	.release		= cp210x_release, @@ -281,7 +277,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,  	int result, i, length;  	/* Number of integers required to contain the array */ -	length = (((size - 1) | 3) + 1)/4; +	length = (((size - 1) | 3) + 1) / 4;  	buf = kcalloc(length, sizeof(__le32), GFP_KERNEL);  	if (!buf) { @@ -328,12 +324,11 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,  	int result, i, length;  	/* Number of integers required to contain the array */ -	length = (((size - 1) | 3) + 1)/4; +	length = (((size - 1) | 3) + 1) / 4;  	buf = kmalloc(length * sizeof(__le32), GFP_KERNEL);  	if (!buf) { -		dev_err(&port->dev, "%s - out of memory.\n", -				__func__); +		dev_err(&port->dev, "%s - out of memory.\n", __func__);  		return -ENOMEM;  	} @@ -384,7 +379,8 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port,   * cp210x_quantise_baudrate   * Quantises the baud rate as per AN205 Table 1   */ -static unsigned int cp210x_quantise_baudrate(unsigned int baud) { +static unsigned int cp210x_quantise_baudrate(unsigned int baud) +{  	if (baud <= 300)  		baud = 300;  	else if (baud <= 600)      baud = 600; @@ -467,9 +463,7 @@ static void cp210x_get_termios(struct tty_struct *tty,  		cp210x_get_termios_port(tty->driver_data,  			&tty->termios.c_cflag, &baud);  		tty_encode_baud_rate(tty, baud, baud); -	} - -	else { +	} else {  		unsigned int cflag;  		cflag = 0;  		cp210x_get_termios_port(port, &cflag, &baud); @@ -693,8 +687,8 @@ static void cp210x_set_termios(struct tty_struct *tty,  			break;*/  		default:  			dev_dbg(dev, "cp210x driver does not support the number of bits requested, using 8 bit mode\n"); -				bits |= BITS_DATA_8; -				break; +			bits |= BITS_DATA_8; +			break;  		}  		if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))  			dev_dbg(dev, "Number of data bits requested not supported by device\n"); @@ -767,7 +761,7 @@ static void cp210x_set_termios(struct tty_struct *tty,  } -static int cp210x_tiocmset (struct tty_struct *tty, +static int cp210x_tiocmset(struct tty_struct *tty,  		unsigned int set, unsigned int clear)  {  	struct usb_serial_port *port = tty->driver_data; @@ -809,7 +803,7 @@ static void cp210x_dtr_rts(struct usb_serial_port *p, int on)  		cp210x_tiocmset_port(p, 0, TIOCM_DTR|TIOCM_RTS);  } -static int cp210x_tiocmget (struct tty_struct *tty) +static int cp210x_tiocmget(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data;  	unsigned int control; @@ -829,7 +823,7 @@ static int cp210x_tiocmget (struct tty_struct *tty)  	return result;  } -static void cp210x_break_ctl (struct tty_struct *tty, int break_state) +static void cp210x_break_ctl(struct tty_struct *tty, int break_state)  {  	struct usb_serial_port *port = tty->driver_data;  	unsigned int state; @@ -874,5 +868,4 @@ static void cp210x_release(struct usb_serial *serial)  module_usb_serial_driver(serial_drivers, id_table);  MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION);  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 4ee77dcbe69..69a4fa1cee2 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -43,10 +43,6 @@  #define CYBERJACK_LOCAL_BUF_SIZE 32 -/* - * Version Information - */ -#define DRIVER_VERSION "v1.01"  #define DRIVER_AUTHOR "Matthias Bruestle"  #define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver" @@ -441,5 +437,4 @@ module_usb_serial_driver(serial_drivers, id_table);  MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION);  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index f0da1279c11..fd8c35fd452 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -50,10 +50,6 @@ static bool stats;  static int interval;  static bool unstable_bauds; -/* - * Version Information - */ -#define DRIVER_VERSION "v1.10"  #define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>"  #define DRIVER_DESC "Cypress USB to Serial Driver" @@ -1303,7 +1299,6 @@ module_usb_serial_driver(serial_drivers, id_table_combined);  MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION);  MODULE_LICENSE("GPL");  module_param(stats, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index b50fa1c6d88..45d4af62967 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -32,10 +32,6 @@  /* Defines */ -/* - * Version Information - */ -#define DRIVER_VERSION "v1.80.1.2"  #define DRIVER_AUTHOR "Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>"  #define DRIVER_DESC "Digi AccelePort USB-2/USB-4 Serial Converter driver" diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 43ede4a1e12..0f658618db1 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -28,10 +28,6 @@  #include <linux/usb.h>  #include <linux/usb/serial.h> -/* - * Version Information - */ -#define DRIVER_VERSION "v1.3"  #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Gary Brubaker <xavyer@ix.netcom.com>"  #define DRIVER_DESC "USB Empeg Mark I/II Driver" diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index be845873e23..0a373b3ae96 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -73,7 +73,6 @@ struct ftdi_private {  	char prev_status;        /* Used for TIOCMIWAIT */  	bool dev_gone;        /* Used to abort TIOCMIWAIT */  	char transmit_empty;	/* If transmitter is empty or not */ -	struct usb_serial_port *port;  	__u16 interface;	/* FT2232C, FT2232H or FT4232H port interface  				   (0 for FT232/245) */ @@ -192,6 +191,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(NEWPORT_VID, NEWPORT_AGILIS_PID) },  	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },  	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, @@ -923,6 +923,9 @@ static int ftdi_get_icount(struct tty_struct *tty,  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); +static int ftdi_chars_in_buffer(struct tty_struct *tty); +static int ftdi_get_modem_status(struct tty_struct *tty, +						unsigned char status[2]);  static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);  static unsigned short int ftdi_232am_baud_to_divisor(int baud); @@ -957,6 +960,7 @@ static struct usb_serial_driver ftdi_sio_device = {  	.ioctl =		ftdi_ioctl,  	.set_termios =		ftdi_set_termios,  	.break_ctl =		ftdi_break_ctl, +	.chars_in_buffer =      ftdi_chars_in_buffer,  };  static struct usb_serial_driver * const serial_drivers[] = { @@ -1090,6 +1094,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set,  			__func__,  			(set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged",  			(set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged"); +		rv = usb_translate_errors(rv);  	} else {  		dev_dbg(dev, "%s - DTR %s, RTS %s\n", __func__,  			(set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged", @@ -1682,7 +1687,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)  	kref_init(&priv->kref);  	mutex_init(&priv->cfg_lock); -	memset(&priv->icount, 0x00, sizeof(priv->icount));  	init_waitqueue_head(&priv->delta_msr_wait);  	priv->flags = ASYNC_LOW_LATENCY; @@ -1691,7 +1695,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)  	if (quirk && quirk->port_probe)  		quirk->port_probe(priv); -	priv->port = port;  	usb_set_serial_port_data(port, priv);  	ftdi_determine_type(port); @@ -1781,7 +1784,7 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)  	struct usb_device *udev = serial->dev;  	if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) || -	    (udev->product && !strcmp(udev->product, "BeagleBone/XDS100"))) +	    (udev->product && !strcmp(udev->product, "BeagleBone/XDS100V2")))  		return ftdi_jtag_probe(serial);  	return 0; @@ -2089,6 +2092,29 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state)  } +static int ftdi_chars_in_buffer(struct tty_struct *tty) +{ +	struct usb_serial_port *port = tty->driver_data; +	int chars; +	unsigned char buf[2]; +	int ret; + +	chars = usb_serial_generic_chars_in_buffer(tty); +	if (chars) +		goto out; + +	/* Check if hardware buffer is empty. */ +	ret = ftdi_get_modem_status(tty, buf); +	if (ret == 2) { +		if (!(buf[1] & FTDI_RS_TEMT)) +			chars = 1; +	} +out: +	dev_dbg(&port->dev, "%s - %d\n", __func__, chars); + +	return chars; +} +  /* old_termios contains the original termios settings and tty->termios contains   * the new setting to be used   * WARNING: set_termios calls this with old_termios in kernel space @@ -2272,7 +2298,14 @@ no_c_cflag_changes:  	}  } -static int ftdi_tiocmget(struct tty_struct *tty) +/* + * Get modem-control status. + * + * Returns the number of status bytes retrieved (device dependant), or + * negative error code. + */ +static int ftdi_get_modem_status(struct tty_struct *tty, +						unsigned char status[2])  {  	struct usb_serial_port *port = tty->driver_data;  	struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -2312,16 +2345,43 @@ static int ftdi_tiocmget(struct tty_struct *tty)  			FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,  			0, priv->interface,  			buf, len, WDR_TIMEOUT); -	if (ret < 0) +	if (ret < 0) { +		dev_err(&port->dev, "failed to get modem status: %d\n", ret); +		ret = usb_translate_errors(ret);  		goto out; +	} -	ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | -		(buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | -		(buf[0]  & FTDI_SIO_RI_MASK  ? TIOCM_RI  : 0) | -		(buf[0]  & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0) | -		priv->last_dtr_rts; +	status[0] = buf[0]; +	if (ret > 1) +		status[1] = buf[1]; +	else +		status[1] = 0; + +	dev_dbg(&port->dev, "%s - 0x%02x%02x\n", __func__, status[0], +								status[1]);  out:  	kfree(buf); + +	return ret; +} + +static int ftdi_tiocmget(struct tty_struct *tty) +{ +	struct usb_serial_port *port = tty->driver_data; +	struct ftdi_private *priv = usb_get_serial_port_data(port); +	unsigned char buf[2]; +	int ret; + +	ret = ftdi_get_modem_status(tty, buf); +	if (ret < 0) +		return ret; + +	ret =	(buf[0] & FTDI_SIO_DSR_MASK  ? TIOCM_DSR : 0) | +		(buf[0] & FTDI_SIO_CTS_MASK  ? TIOCM_CTS : 0) | +		(buf[0] & FTDI_SIO_RI_MASK   ? TIOCM_RI  : 0) | +		(buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0) | +		priv->last_dtr_rts; +  	return ret;  } diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 57c12ef6625..049b6e715fa 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -752,6 +752,12 @@  #define TTI_VID			0x103E	/* Vendor Id */  #define TTI_QL355P_PID		0x03E8	/* TTi QL355P power supply */ +/* + * Newport Cooperation (www.newport.com) + */ +#define NEWPORT_VID			0x104D +#define NEWPORT_AGILIS_PID		0x3000 +  /* Interbiometrics USB I/O Board */  /* Developed for Interbiometrics by Rudolf Gugler */  #define INTERBIOMETRICS_VID              0x1209 diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 296612153ea..2ea70a63199 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -262,6 +262,7 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)  	dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);  	return chars;  } +EXPORT_SYMBOL_GPL(usb_serial_generic_chars_in_buffer);  static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,  						int index, gfp_t mem_flags) diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c index 0bbaf21a9d1..2cba60d90c7 100644 --- a/drivers/usb/serial/hp4x.c +++ b/drivers/usb/serial/hp4x.c @@ -20,10 +20,6 @@  #include <linux/usb.h>  #include <linux/usb/serial.h> -/* - * Version Information - */ -#define DRIVER_VERSION "v1.00"  #define DRIVER_DESC "HP4x (48/49) Generic Serial driver"  #define HP_VENDOR_ID 0x03f0 @@ -52,5 +48,4 @@ static struct usb_serial_driver * const serial_drivers[] = {  module_usb_serial_driver(serial_drivers, id_table);  MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION);  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 5acc0d13864..7b770c7f8b1 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -51,10 +51,6 @@  #include "io_ionsp.h"		/* info for the iosp messages */  #include "io_16654.h"		/* 16654 UART defines */ -/* - * Version Information - */ -#define DRIVER_VERSION "v2.7"  #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"  #define DRIVER_DESC "Edgeport USB Serial Driver" diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 60023c2d2a3..58184f3de68 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -40,10 +40,6 @@  #include "io_usbvend.h"  #include "io_ti.h" -/* - * Version Information - */ -#define DRIVER_VERSION "v0.7mode043006"  #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"  #define DRIVER_DESC "Edgeport USB Serial Driver" diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 1068bf22e27..76c9a847da5 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -25,11 +25,6 @@  #define KP_RETRIES	100 -/* - * Version Information - */ - -#define DRIVER_VERSION "v1.0"  #define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>"  #define DRIVER_DESC "USB PocketPC PDA driver" diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 4264821a3b3..155eab14b30 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -49,10 +49,6 @@  #include <linux/uaccess.h>  #include "usb-wwan.h" -/* - * Version Information - */ -#define DRIVER_VERSION	"v0.4"  #define DRIVER_AUTHOR	"Roelf Diedericks"  #define DRIVER_DESC	"IPWireless tty driver" diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index cd5533e81de..1e1fbed65ef 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -32,10 +32,6 @@  #include "iuu_phoenix.h"  #include <linux/random.h> -/* - * Version Information - */ -#define DRIVER_VERSION "v0.12"  #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"  static const struct usb_device_id id_table[] = { @@ -1164,7 +1160,7 @@ static ssize_t store_vcc_mode(struct device *dev,  	struct iuu_private *priv = usb_get_serial_port_data(port);  	unsigned long v; -	if (strict_strtoul(buf, 10, &v)) { +	if (kstrtoul(buf, 10, &v)) {  		dev_err(dev, "%s - vcc_mode: %s is not a unsigned long\n",  				__func__, buf);  		goto fail_store_vcc_mode; @@ -1232,8 +1228,6 @@ MODULE_AUTHOR("Alain Degreffe eczema@ecze.com");  MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_LICENSE("GPL"); -MODULE_VERSION(DRIVER_VERSION); -  module_param(xmas, bool, S_IRUGO | S_IWUSR);  MODULE_PARM_DESC(xmas, "Xmas colors enabled or not"); diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index cff8dd5b462..97bc49f68ef 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -44,10 +44,6 @@  #include <linux/usb/ezusb.h>  #include "keyspan.h" -/* - * Version Information - */ -#define DRIVER_VERSION "v1.1.5"  #define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"  #define DRIVER_DESC "Keyspan USB to Serial Converter Driver" diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index bb87e29c4ac..41b01092af0 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -42,10 +42,6 @@  	#undef XIRCOM  #endif -/* - * Version Information - */ -#define DRIVER_VERSION "v1.1"  #define DRIVER_AUTHOR "Brian Warner <warner@lothar.com>"  #define DRIVER_DESC "USB Keyspan PDA Converter driver" diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 1f4517864cd..fc9e14a1e9b 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -49,10 +49,6 @@  #include <linux/usb/serial.h>  #include "kl5kusb105.h" -/* - * Version Information - */ -#define DRIVER_VERSION "v0.4"  #define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>, Johan Hovold <jhovold@gmail.com>"  #define DRIVER_DESC "KLSI KL5KUSB105 chipset USB->Serial Converter driver" diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index c9ca7a5b12e..b747ba615d0 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -38,8 +38,6 @@  #include <linux/ioctl.h>  #include "kobil_sct.h" -/* Version Information */ -#define DRIVER_VERSION "21/05/2004"  #define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com"  #define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)" diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 8a208100410..b6911757c85 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -38,10 +38,6 @@  #include <linux/ioctl.h>  #include "mct_u232.h" -/* - * Version Information - */ -#define DRIVER_VERSION "z2.1"		/* Linux in-kernel version */  #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"  #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver" diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 6f29c74eb76..3d258448c29 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -20,8 +20,6 @@  #include <linux/uaccess.h>  #include <linux/usb/serial.h> -/* Version Information */ -#define DRIVER_VERSION "v1.2.0.0"  #define DRIVER_DESC "Metrologic Instruments Inc. - USB-POS driver"  /* Product information. */ diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 75267421aad..f57a6b1fe78 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -36,10 +36,6 @@  #include <linux/uaccess.h>  #include <linux/parport.h> -/* - * Version Information - */ -#define DRIVER_VERSION "2.1"  #define DRIVER_AUTHOR "Aspire Communications pvt Ltd."  #define DRIVER_DESC "Moschip USB Serial Driver" diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 1cf3375ec1a..66d9e088d9d 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -35,10 +35,6 @@  #include <linux/usb/serial.h>  #include <linux/uaccess.h> -/* - * Version Information - */ -#define DRIVER_VERSION "1.3.2"  #define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver"  /* diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 9ab73d29577..7818af931a4 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -23,10 +23,6 @@  #include <linux/usb.h>  #include <linux/usb/serial.h> -/* - * Version Information - */ -#define DRIVER_VERSION "v1.1"  #define DRIVER_AUTHOR "Alessandro Zummo"  #define DRIVER_DESC "USB ZyXEL omni.net LCD PLUS Driver" diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 6aba731d486..c6bfb83efb1 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -1,6 +1,7 @@  /*   * Opticon USB barcode to serial driver   * + * Copyright (C) 2011 - 2012 Johan Hovold <jhovold@gmail.com>   * Copyright (C) 2011 Martin Jansen <martin.jansen@opticon.com>   * Copyright (C) 2008 - 2009 Greg Kroah-Hartman <gregkh@suse.de>   * Copyright (C) 2008 - 2009 Novell Inc. @@ -40,114 +41,70 @@ MODULE_DEVICE_TABLE(usb, id_table);  /* This structure holds all of the individual device information */  struct opticon_private { -	struct usb_device *udev; -	struct usb_serial *serial; -	struct usb_serial_port *port; -	unsigned char *bulk_in_buffer; -	struct urb *bulk_read_urb; -	int buffer_size; -	u8 bulk_address;  	spinlock_t lock;	/* protects the following flags */ -	bool throttled; -	bool actually_throttled;  	bool rts;  	bool cts;  	int outstanding_urbs;  }; - -static void opticon_read_bulk_callback(struct urb *urb) +static void opticon_process_data_packet(struct usb_serial_port *port, +					const unsigned char *buf, size_t len)  { -	struct opticon_private *priv = urb->context; -	unsigned char *data = urb->transfer_buffer; -	struct usb_serial_port *port = priv->port; -	int status = urb->status;  	struct tty_struct *tty; -	int result; -	int data_length; + +	tty = tty_port_tty_get(&port->port); +	if (!tty) +		return; + +	tty_insert_flip_string(tty, buf, len); +	tty_flip_buffer_push(tty); +	tty_kref_put(tty); +} + +static void opticon_process_status_packet(struct usb_serial_port *port, +					const unsigned char *buf, size_t len) +{ +	struct opticon_private *priv = usb_get_serial_port_data(port);  	unsigned long flags; -	switch (status) { -	case 0: -		/* success */ -		break; -	case -ECONNRESET: -	case -ENOENT: -	case -ESHUTDOWN: -		/* this urb is terminated, clean up */ -		dev_dbg(&priv->udev->dev, "%s - urb shutting down with status: %d\n", -			__func__, status); +	spin_lock_irqsave(&priv->lock, flags); +	if (buf[0] == 0x00) +		priv->cts = false; +	else +		priv->cts = true; +	spin_unlock_irqrestore(&priv->lock, flags); +} + +static void opticon_process_read_urb(struct urb *urb) +{ +	struct usb_serial_port *port = urb->context; +	const unsigned char *hdr = urb->transfer_buffer; +	const unsigned char *data = hdr + 2; +	size_t data_len = urb->actual_length - 2; + +	if (urb->actual_length <= 2) { +		dev_dbg(&port->dev, "malformed packet received: %d bytes\n", +							urb->actual_length);  		return; -	default: -		dev_dbg(&priv->udev->dev, "%s - nonzero urb status received: %d\n", -			__func__, status); -		goto exit;  	} - -	usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); - -	if (urb->actual_length > 2) { -		data_length = urb->actual_length - 2; - -		/* -		 * Data from the device comes with a 2 byte header: -		 * -		 * <0x00><0x00>data... -		 *	This is real data to be sent to the tty layer -		 * <0x00><0x01)level -		 *	This is a CTS level change, the third byte is the CTS -		 *	value (0 for low, 1 for high). -		 */ -		if ((data[0] == 0x00) && (data[1] == 0x00)) { -			/* real data, send it to the tty layer */ -			tty = tty_port_tty_get(&port->port); -			if (tty) { -				tty_insert_flip_string(tty, data + 2, -						       data_length); -				tty_flip_buffer_push(tty); -				tty_kref_put(tty); -			} -		} else { -			if ((data[0] == 0x00) && (data[1] == 0x01)) { -				spin_lock_irqsave(&priv->lock, flags); -				/* CTS status information package */ -				if (data[2] == 0x00) -					priv->cts = false; -				else -					priv->cts = true; -				spin_unlock_irqrestore(&priv->lock, flags); -			} else { -				dev_dbg(&priv->udev->dev, -					"Unknown data packet received from the device:" -					" %2x %2x\n", -					data[0], data[1]); -			} -		} +	/* +	 * Data from the device comes with a 2 byte header: +	 * +	 * <0x00><0x00>data... +	 *      This is real data to be sent to the tty layer +	 * <0x00><0x01>level +	 *      This is a CTS level change, the third byte is the CTS +	 *      value (0 for low, 1 for high). +	 */ +	if ((hdr[0] == 0x00) && (hdr[1] == 0x00)) { +		opticon_process_data_packet(port, data, data_len); +	} else if ((hdr[0] == 0x00) && (hdr[1] == 0x01)) { +		opticon_process_status_packet(port, data, data_len);  	} else { -		dev_dbg(&priv->udev->dev, -			"Improper amount of data received from the device, " -			"%d bytes", urb->actual_length); +		dev_dbg(&port->dev, "unknown packet received: %02x %02x\n", +							hdr[0], hdr[1]);  	} - -exit: -	spin_lock(&priv->lock); - -	/* Continue trying to always read if we should */ -	if (!priv->throttled) { -		usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev, -				  usb_rcvbulkpipe(priv->udev, -						  priv->bulk_address), -				  priv->bulk_in_buffer, priv->buffer_size, -				  opticon_read_bulk_callback, priv); -		result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC); -		if (result) -			dev_err(&port->dev, -			    "%s - failed resubmitting read urb, error %d\n", -							__func__, result); -	} else -		priv->actually_throttled = true; -	spin_unlock(&priv->lock);  }  static int send_control_msg(struct usb_serial_port *port, u8 requesttype, @@ -175,52 +132,35 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,  static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port)  { -	struct opticon_private *priv = usb_get_serial_data(port->serial); +	struct opticon_private *priv = usb_get_serial_port_data(port);  	unsigned long flags; -	int result = 0; +	int res;  	spin_lock_irqsave(&priv->lock, flags); -	priv->throttled = false; -	priv->actually_throttled = false; -	priv->port = port;  	priv->rts = false;  	spin_unlock_irqrestore(&priv->lock, flags);  	/* Clear RTS line */  	send_control_msg(port, CONTROL_RTS, 0); -	/* Setup the read URB and start reading from the device */ -	usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev, -			  usb_rcvbulkpipe(priv->udev, -					  priv->bulk_address), -			  priv->bulk_in_buffer, priv->buffer_size, -			  opticon_read_bulk_callback, priv); -  	/* clear the halt status of the enpoint */ -	usb_clear_halt(priv->udev, priv->bulk_read_urb->pipe); +	usb_clear_halt(port->serial->dev, port->read_urb->pipe); + +	res = usb_serial_generic_open(tty, port); +	if (!res) +		return res; -	result = usb_submit_urb(priv->bulk_read_urb, GFP_KERNEL); -	if (result) -		dev_err(&port->dev, -			"%s - failed resubmitting read urb, error %d\n", -			__func__, result);  	/* Request CTS line state, sometimes during opening the current  	 * CTS state can be missed. */  	send_control_msg(port, RESEND_CTS_STATE, 1); -	return result; -} - -static void opticon_close(struct usb_serial_port *port) -{ -	struct opticon_private *priv = usb_get_serial_data(port->serial); -	/* shutdown our urbs */ -	usb_kill_urb(priv->bulk_read_urb); +	return res;  }  static void opticon_write_control_callback(struct urb *urb)  { -	struct opticon_private *priv = urb->context; +	struct usb_serial_port *port = urb->context; +	struct opticon_private *priv = usb_get_serial_port_data(port);  	int status = urb->status;  	unsigned long flags; @@ -231,20 +171,21 @@ static void opticon_write_control_callback(struct urb *urb)  	kfree(urb->setup_packet);  	if (status) -		dev_dbg(&priv->udev->dev, "%s - nonzero write bulk status received: %d\n", +		dev_dbg(&port->dev, +			"%s - non-zero urb status received: %d\n",  			__func__, status);  	spin_lock_irqsave(&priv->lock, flags);  	--priv->outstanding_urbs;  	spin_unlock_irqrestore(&priv->lock, flags); -	usb_serial_port_softint(priv->port); +	usb_serial_port_softint(port);  }  static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,  			 const unsigned char *buf, int count)  { -	struct opticon_private *priv = usb_get_serial_data(port->serial); +	struct opticon_private *priv = usb_get_serial_port_data(port);  	struct usb_serial *serial = port->serial;  	struct urb *urb;  	unsigned char *buffer; @@ -298,7 +239,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,  	usb_fill_control_urb(urb, serial->dev,  		usb_sndctrlpipe(serial->dev, 0),  		(unsigned char *)dr, buffer, count, -		opticon_write_control_callback, priv); +		opticon_write_control_callback, port);  	/* send it down the pipe */  	status = usb_submit_urb(urb, GFP_ATOMIC); @@ -331,7 +272,7 @@ error_no_buffer:  static int opticon_write_room(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; -	struct opticon_private *priv = usb_get_serial_data(port->serial); +	struct opticon_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	/* @@ -350,44 +291,10 @@ static int opticon_write_room(struct tty_struct *tty)  	return 2048;  } -static void opticon_throttle(struct tty_struct *tty) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct opticon_private *priv = usb_get_serial_data(port->serial); -	unsigned long flags; - -	spin_lock_irqsave(&priv->lock, flags); -	priv->throttled = true; -	spin_unlock_irqrestore(&priv->lock, flags); -} - - -static void opticon_unthrottle(struct tty_struct *tty) -{ -	struct usb_serial_port *port = tty->driver_data; -	struct opticon_private *priv = usb_get_serial_data(port->serial); -	unsigned long flags; -	int result, was_throttled; - -	spin_lock_irqsave(&priv->lock, flags); -	priv->throttled = false; -	was_throttled = priv->actually_throttled; -	priv->actually_throttled = false; -	spin_unlock_irqrestore(&priv->lock, flags); - -	if (was_throttled) { -		result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC); -		if (result) -			dev_err(&port->dev, -				"%s - failed submitting read urb, error %d\n", -							__func__, result); -	} -} -  static int opticon_tiocmget(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; -	struct opticon_private *priv = usb_get_serial_data(port->serial); +	struct opticon_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	int result = 0; @@ -407,7 +314,7 @@ static int opticon_tiocmset(struct tty_struct *tty,  {  	struct usb_serial_port *port = tty->driver_data;  	struct usb_serial *serial = port->serial; -	struct opticon_private *priv = usb_get_serial_data(port->serial); +	struct opticon_private *priv = usb_get_serial_port_data(port);  	unsigned long flags;  	bool rts;  	bool changed = false; @@ -438,7 +345,7 @@ static int opticon_tiocmset(struct tty_struct *tty,  	return ret;  } -static int get_serial_info(struct opticon_private *priv, +static int get_serial_info(struct usb_serial_port *port,  			   struct serial_struct __user *serial)  {  	struct serial_struct tmp; @@ -450,7 +357,7 @@ static int get_serial_info(struct opticon_private *priv,  	/* fake emulate a 16550 uart to make userspace code happy */  	tmp.type		= PORT_16550A; -	tmp.line		= priv->serial->minor; +	tmp.line		= port->serial->minor;  	tmp.port		= 0;  	tmp.irq			= 0;  	tmp.flags		= ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; @@ -468,13 +375,12 @@ static int opticon_ioctl(struct tty_struct *tty,  			 unsigned int cmd, unsigned long arg)  {  	struct usb_serial_port *port = tty->driver_data; -	struct opticon_private *priv = usb_get_serial_data(port->serial);  	dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd);  	switch (cmd) {  	case TIOCGSERIAL: -		return get_serial_info(priv, +		return get_serial_info(port,  				       (struct serial_struct __user *)arg);  	} @@ -483,106 +389,36 @@ static int opticon_ioctl(struct tty_struct *tty,  static int opticon_startup(struct usb_serial *serial)  { -	struct opticon_private *priv; -	struct usb_host_interface *intf; -	int i; -	int retval = -ENOMEM; -	bool bulk_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; -	} -	spin_lock_init(&priv->lock); -	priv->serial = serial; -	priv->port = serial->port[0]; -	priv->udev = serial->dev; -	priv->outstanding_urbs = 0;	/* Init the outstanding urbs */ - -	/* find our bulk 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_bulk_in(endpoint)) -			continue; - -		priv->bulk_read_urb = usb_alloc_urb(0, GFP_KERNEL); -		if (!priv->bulk_read_urb) { -			dev_err(&priv->udev->dev, "out of memory\n"); -			goto error; -		} - -		priv->buffer_size = usb_endpoint_maxp(endpoint) * 2; -		priv->bulk_in_buffer = kmalloc(priv->buffer_size, GFP_KERNEL); -		if (!priv->bulk_in_buffer) { -			dev_err(&priv->udev->dev, "out of memory\n"); -			goto error; -		} - -		priv->bulk_address = endpoint->bEndpointAddress; - -		bulk_in_found = true; -		break; -		} - -	if (!bulk_in_found) { -		dev_err(&priv->udev->dev, -			"Error - the proper endpoints were not found!\n"); -		goto error; +	if (!serial->num_bulk_in) { +		dev_err(&serial->dev->dev, "no bulk in endpoint\n"); +		return -ENODEV;  	} -	usb_set_serial_data(serial, priv);  	return 0; - -error: -	usb_free_urb(priv->bulk_read_urb); -	kfree(priv->bulk_in_buffer); -	kfree(priv); -	return retval;  } -static void opticon_disconnect(struct usb_serial *serial) +static int opticon_port_probe(struct usb_serial_port *port)  { -	struct opticon_private *priv = usb_get_serial_data(serial); - -	usb_kill_urb(priv->bulk_read_urb); -	usb_free_urb(priv->bulk_read_urb); -} +	struct opticon_private *priv; -static void opticon_release(struct usb_serial *serial) -{ -	struct opticon_private *priv = usb_get_serial_data(serial); +	priv = kzalloc(sizeof(*priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; -	kfree(priv->bulk_in_buffer); -	kfree(priv); -} +	spin_lock_init(&priv->lock); -static int opticon_suspend(struct usb_serial *serial, pm_message_t message) -{ -	struct opticon_private *priv = usb_get_serial_data(serial); +	usb_set_serial_port_data(port, priv); -	usb_kill_urb(priv->bulk_read_urb);  	return 0;  } -static int opticon_resume(struct usb_serial *serial) +static int opticon_port_remove(struct usb_serial_port *port)  { -	struct opticon_private *priv = usb_get_serial_data(serial); -	struct usb_serial_port *port = serial->port[0]; -	int result; - -	mutex_lock(&port->port.mutex); -	/* This is protected by the port mutex against close/open */ -	if (test_bit(ASYNCB_INITIALIZED, &port->port.flags)) -		result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO); -	else -		result = 0; -	mutex_unlock(&port->port.mutex); -	return result; +	struct opticon_private *priv = usb_get_serial_port_data(port); + +	kfree(priv); + +	return 0;  }  static struct usb_serial_driver opticon_device = { @@ -592,20 +428,19 @@ static struct usb_serial_driver opticon_device = {  	},  	.id_table =		id_table,  	.num_ports =		1, +	.bulk_in_size =		256,  	.attach =		opticon_startup, +	.port_probe =		opticon_port_probe, +	.port_remove =		opticon_port_remove,  	.open =			opticon_open, -	.close =		opticon_close,  	.write =		opticon_write,  	.write_room = 		opticon_write_room, -	.disconnect =		opticon_disconnect, -	.release =		opticon_release, -	.throttle = 		opticon_throttle, -	.unthrottle =		opticon_unthrottle, +	.throttle =		usb_serial_generic_throttle, +	.unthrottle =		usb_serial_generic_unthrottle,  	.ioctl =		opticon_ioctl,  	.tiocmget =		opticon_tiocmget,  	.tiocmset =		opticon_tiocmset, -	.suspend = 		opticon_suspend, -	.resume =		opticon_resume, +	.process_read_urb =	opticon_process_read_urb,  };  static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index edc64bb6f45..e6f87b76c71 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -28,7 +28,6 @@    device features.  */ -#define DRIVER_VERSION "v0.7.2"  #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"  #define DRIVER_DESC "USB Driver for GSM modems" @@ -81,6 +80,7 @@ static void option_instat_callback(struct urb *urb);  #define OPTION_PRODUCT_GTM380_MODEM		0x7201  #define HUAWEI_VENDOR_ID			0x12D1 +#define HUAWEI_PRODUCT_E173			0x140C  #define HUAWEI_PRODUCT_K4505			0x1464  #define HUAWEI_PRODUCT_K3765			0x1465  #define HUAWEI_PRODUCT_K4605			0x14C6 @@ -553,6 +553,8 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) },  	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) },  	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff), +		.driver_info = (kernel_ulong_t) &net_intf1_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff),  		.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff), @@ -741,23 +743,23 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },  	{ USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },  	{ USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011) }, -	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012, 0xff) },  	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },  	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },  	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */ @@ -884,6 +886,10 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff),  		.driver_info = (kernel_ulong_t)&net_intf5_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0135, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0136, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0137, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0139, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) }, @@ -904,20 +910,34 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),  	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0189, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */  	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0196, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0197, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */  	  .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0200, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0201, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */  	  .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff),  	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0330, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0395, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0414, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0417, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff),  	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),  	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff),  	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff),  	  .driver_info = (kernel_ulong_t)&net_intf2_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, @@ -1097,6 +1117,10 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1301, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1302, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1303, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1333, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff),  		.driver_info = (kernel_ulong_t)&net_intf2_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff), @@ -1174,22 +1198,22 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },  	{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },  	/* Pirelli  */ -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1)}, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2)}, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004)}, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005)}, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006)}, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007)}, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008)}, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009)}, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A)}, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B) }, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C) }, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D) }, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E) }, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) }, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)}, -	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)}, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011, 0xff) }, +	{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012, 0xff) },  	/* Cinterion */  	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },  	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) }, @@ -1350,20 +1374,10 @@ static int option_probe(struct usb_serial *serial,  				&serial->interface->cur_altsetting->desc;  	struct usb_device_descriptor *dev_desc = &serial->dev->descriptor; -	/* -	 * D-Link DWM 652 still exposes CD-Rom emulation interface in modem -	 * mode. -	 */ -	if (dev_desc->idVendor == DLINK_VENDOR_ID && -		dev_desc->idProduct == DLINK_PRODUCT_DWM_652 && -		iface_desc->bInterfaceClass == 0x08) +	/* Never bind to the CD-Rom emulation interface	*/ +	if (iface_desc->bInterfaceClass == 0x08)  		return -ENODEV; -	/* Bandrich modem and AT command interface is 0xff */ -	if ((dev_desc->idVendor == BANDRICH_VENDOR_ID || -		dev_desc->idVendor == PIRELLI_VENDOR_ID) && -		iface_desc->bInterfaceClass != 0xff) -		return -ENODEV;  	/*  	 * Don't bind reserved interfaces (like network ones) which often have  	 * the same class/subclass/protocol as the serial interfaces.  Look at @@ -1378,9 +1392,9 @@ static int option_probe(struct usb_serial *serial,  	 * Don't bind network interface on Samsung GT-B3730, it is handled by  	 * a separate module.  	 */ -	if (dev_desc->idVendor == SAMSUNG_VENDOR_ID && -		dev_desc->idProduct == SAMSUNG_PRODUCT_GT_B3730 && -		iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA) +	if (dev_desc->idVendor == cpu_to_le16(SAMSUNG_VENDOR_ID) && +	    dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) && +	    iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)  		return -ENODEV;  	/* Store device id so we can use it during attach. */ @@ -1518,5 +1532,4 @@ static int option_send_setup(struct usb_serial_port *port)  MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION);  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index cee9a52ca89..d217fd6ee43 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -57,7 +57,6 @@  #define OTI6858_DESCRIPTION \  	"Ours Technology Inc. OTi-6858 USB to serial adapter driver"  #define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>" -#define OTI6858_VERSION "0.2"  static const struct usb_device_id id_table[] = {  	{ USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) }, @@ -899,5 +898,4 @@ module_usb_serial_driver(serial_drivers, id_table);  MODULE_DESCRIPTION(OTI6858_DESCRIPTION);  MODULE_AUTHOR(OTI6858_AUTHOR); -MODULE_VERSION(OTI6858_VERSION);  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index ffcfc962ab1..d152be97d04 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -65,8 +65,6 @@  #define QT2_WRITE_BUFFER_SIZE   512  /* size of write buffer */  #define QT2_WRITE_CONTROL_SIZE  5    /* control bytes used for a write */ -/* Version Information */ -#define DRIVER_VERSION "v0.1"  #define DRIVER_DESC "Quatech 2nd gen USB to Serial Driver"  #define	USB_VENDOR_ID_QUATECH	0x061d diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c index e4a1787cdba..a76b1ae54a2 100644 --- a/drivers/usb/serial/siemens_mpi.c +++ b/drivers/usb/serial/siemens_mpi.c @@ -16,8 +16,6 @@  #include <linux/usb.h>  #include <linux/usb/serial.h> -/* Version Information */ -#define DRIVER_VERSION "Version 0.1 09/26/2005"  #define DRIVER_AUTHOR "Thomas Hergenhahn@web.de http://libnodave.sf.net"  #define DRIVER_DESC "Driver for Siemens USB/MPI adapter" diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 270860f6bb2..af06f2f5f38 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -18,7 +18,7 @@  */  /* Uncomment to log function calls */  /* #define DEBUG */ -#define DRIVER_VERSION "v.1.7.16" +  #define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer"  #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" @@ -1078,7 +1078,6 @@ module_usb_serial_driver(serial_drivers, id_table);  MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION);  MODULE_LICENSE("GPL");  module_param(nmea, bool, S_IRUGO | S_IWUSR); diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 769c137f897..a42536af125 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -28,9 +28,6 @@  #include <linux/usb.h>  #include <linux/usb/serial.h> - -/* Version Information */ -#define DRIVER_VERSION	"v0.10"  #define DRIVER_DESC 	"SPCP8x5 USB to serial adaptor driver"  #define SPCP8x5_007_VID		0x04FC @@ -651,5 +648,4 @@ static struct usb_serial_driver * const serial_drivers[] = {  module_usb_serial_driver(serial_drivers, id_table);  MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION);  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 868d1e6852e..4543ea35022 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -46,8 +46,6 @@  #define FULLPWRBIT          0x00000080  #define NEXT_BOARD_POWER_BIT        0x00000004 -/* Version Information */ -#define DRIVER_VERSION "v0.1"  #define DRIVER_DESC "Quatech SSU-100 USB to Serial Driver"  #define	USB_VENDOR_ID_QUATECH	0x061d	/* Quatech VID */ diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 73b8e056916..64bda135ba7 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -597,6 +597,7 @@ static void port_release(struct device *dev)  	kfifo_free(&port->write_fifo);  	kfree(port->interrupt_in_buffer);  	kfree(port->interrupt_out_buffer); +	tty_port_destroy(&port->port);  	kfree(port);  } diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index a3e9c095f0d..01c94aada56 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -19,7 +19,6 @@    - controlling the baud rate doesn't make sense  */ -#define DRIVER_VERSION "v0.7.2"  #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"  #define DRIVER_DESC "USB Driver for GSM modems" @@ -710,5 +709,4 @@ EXPORT_SYMBOL(usb_wwan_resume);  MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION);  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/vivopay-serial.c b/drivers/usb/serial/vivopay-serial.c index 0c0aa876c20..6299526ff8c 100644 --- a/drivers/usb/serial/vivopay-serial.c +++ b/drivers/usb/serial/vivopay-serial.c @@ -10,8 +10,6 @@  #include <linux/usb.h>  #include <linux/usb/serial.h> - -#define DRIVER_VERSION "v1.0"  #define DRIVER_DESC "ViVOpay USB Serial Driver"  #define VIVOPAY_VENDOR_ID 0x1d5f @@ -42,5 +40,4 @@ module_usb_serial_driver(serial_drivers, id_table);  MODULE_AUTHOR("Forest Bond <forest.bond@outpostembedded.com>");  MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION);  MODULE_LICENSE("GPL"); diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 0ae7bb64b5e..eab04a6b5fb 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -203,7 +203,7 @@ config USB_STORAGE_ENE_UB6250  config USB_UAS  	tristate "USB Attached SCSI" -	depends on USB && SCSI +	depends on USB && 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/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index d36446dd7ae..ea5f2586fbd 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -455,7 +455,7 @@ static int rts51x_check_status(struct us_data *us, u8 lun)  	u8 buf[16];  	retval = rts51x_read_status(us, lun, buf, 16, &(chip->status_len)); -	if (retval < 0) +	if (retval != STATUS_SUCCESS)  		return -EIO;  	US_DEBUGP("chip->status_len = %d\n", chip->status_len); diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 12aa72630ae..31b3e1a61bb 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -925,7 +925,6 @@ int usb_stor_probe1(struct us_data **pus,  	host->max_cmd_len = 16;  	host->sg_tablesize = usb_stor_sg_tablesize(intf);  	*pus = us = host_to_us(host); -	memset(us, 0, sizeof(struct us_data));  	mutex_init(&(us->dev_mutex));  	us_set_lock_class(&us->dev_mutex, intf);  	init_completion(&us->cmnd_ready); diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 0616f235bd6..ce310170829 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -105,20 +105,15 @@ static int skel_open(struct inode *inode, struct file *file)  		goto exit;  	} -	/* increment our usage count for the device */ -	kref_get(&dev->kref); - -	/* lock the device to allow correctly handling errors -	 * in resumption */ -	mutex_lock(&dev->io_mutex); -  	retval = usb_autopm_get_interface(interface);  	if (retval) -		goto out_err; +		goto exit; + +	/* increment our usage count for the device */ +	kref_get(&dev->kref);  	/* save our object in the file's private structure */  	file->private_data = dev; -	mutex_unlock(&dev->io_mutex);  exit:  	return retval; diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index 231009af65a..1d365316960 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c @@ -847,19 +847,6 @@ static void wusb_dev_bos_rm(struct wusb_dev *wusb_dev)  	wusb_dev->wusb_cap_descr = NULL;  }; -static struct usb_wireless_cap_descriptor wusb_cap_descr_default = { -	.bLength = sizeof(wusb_cap_descr_default), -	.bDescriptorType = USB_DT_DEVICE_CAPABILITY, -	.bDevCapabilityType = USB_CAP_TYPE_WIRELESS_USB, - -	.bmAttributes = USB_WIRELESS_BEACON_NONE, -	.wPHYRates = cpu_to_le16(USB_WIRELESS_PHY_53), -	.bmTFITXPowerInfo = 0, -	.bmFFITXPowerInfo = 0, -	.bmBandGroup = cpu_to_le16(0x0001),	/* WUSB1.0[7.4.1] bottom */ -	.bReserved = 0 -}; -  /*   * USB stack's device addition Notifier Callback   *  | 
