Re: [PATCH v8 2/2] usbip: vhci extension: dynamic extension

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 12/26/2016 12:18 AM, Nobuo Iwata wrote:
> Modification for dynamic device registration and unregistration.

Why is this necessary? Could make your change logs concise with
important details on why a change is needed and the functionality
it adds. This change log is way too long and doesn't summarize the
changes. Please note that the information in the cover-letter doesn't
go into this commit.

It helps to have a clear change log so it is easier for me to review
the patch.

thanks,
-- Shuah

> 
> 1. kernel config
> 
> Following parameters are added.
> 
> USBIP_VHCI_HC_PORTS: Number of ports per USB/IP virtual host 
> controller. The default is 8 - same as current VHCI_NPORTS.
> USBIP_VHCI_MAX_HCS: Muximum number of USB/IP virtual host controllers. 
> The default is 1.
> USBIP_VHCI_INIT_HCS: Initial number of USB/IP virtual host controllers. 
> The default is 1.
> Static number of devices: USBIP_VHCI_NR_HCS is removed with this patch.
> 
> 2. view from sysfs
> 
> Sysfs structure is changed as following.
> 
> BEFORE this patchset:
>     /sys/devices/platform
>         +-- vhci
>             +-- status
>             +-- attach
>             +-- detach
>             +-- usbip_debug
> 
> AFTER: example for CONFIG_USBIP_INIT_HCS=2 CONFIG_USBIP_MAX_HCS=4
> At the beginning
>     /sys/devices/platform
>         +-- vhci
>         |   +-- nports
>         |   +-- status
>         |   +-- status.1
>         |   +-- status.2
>         |   +-- status.3
>         |   +-- attach
>         |   +-- detach
>         |   +-- usbip_debug
>         +-- vhci.1
> 
> The status files are shown to the maximum number of devices. Port 
> status in status.2 and status.3 represents as free but corresponding 
> devices are not yes registered.
> When all ports in status and status.1 are used, userspace tool requests 
> 'attach' to a port in status.2 then vhci.2 will be registred. The limit 
> is defined with USBIP_VHCI_MAX_NCS.
> 
> By preparing muximum number of status files, there's no need to 
> introduce additional operations for userspace tool.
> 
> When number of free ports becomes more than USBIP_VHCI_HC_PORTS * 
> VHCI_FREE_HCS(2), a free controller other than the first one will be 
> unregistered. It will be invoked by 'detach' operation and other error 
> situations which ports are released.
> 
> Signed-off-by: Nobuo Iwata <nobuo.iwata@xxxxxxxxxxxxxxx>
> ---
>  drivers/usb/usbip/Kconfig      |  17 ++-
>  drivers/usb/usbip/vhci.h       |  36 ++++-
>  drivers/usb/usbip/vhci_hcd.c   | 250 ++++++++++++++++++++++++++++-----
>  drivers/usb/usbip/vhci_rx.c    |  10 +-
>  drivers/usb/usbip/vhci_sysfs.c |  46 +++---
>  drivers/usb/usbip/vhci_tx.c    |   6 +-
>  6 files changed, 291 insertions(+), 74 deletions(-)
> 
> diff --git a/drivers/usb/usbip/Kconfig b/drivers/usb/usbip/Kconfig
> index eeefa29..42d8979 100644
> --- a/drivers/usb/usbip/Kconfig
> +++ b/drivers/usb/usbip/Kconfig
> @@ -35,8 +35,8 @@ config USBIP_VHCI_HC_PORTS
>  	  host controller driver, this defines number of ports per
>  	  USB/IP virtual host controller.
>  
> -config USBIP_VHCI_NR_HCS
> -	int "Number of USB/IP virtual host controllers"
> +config USBIP_VHCI_MAX_HCS
> +	int "Maximum number of USB/IP virtual host controllers"
>  	range 1 128
>  	default 1
>  	depends on USBIP_VHCI_HCD
> @@ -44,7 +44,18 @@ config USBIP_VHCI_NR_HCS
>  	  To increase number of ports available for USB/IP virtual
>  	  host controller driver, this defines number of USB/IP
>  	  virtual host controllers as if adding physical host
> -	  controllers.
> +	  controllers. This defines the maximum number.
> +
> +config USBIP_VHCI_INIT_HCS
> +	int "Initial number of USB/IP virtual host controllers"
> +	range 1 USBIP_VHCI_MAX_HCS
> +	default 1
> +	depends on USBIP_VHCI_MAX_HCS
> +	---help---
> +	  To increase number of ports available for USB/IP virtual
> +	  host controller driver, this defines number of USB/IP
> +	  virtual host controllers as if adding physical host
> +	  controllers. This defines the number at initializing.
>  
>  config USBIP_HOST
>  	tristate "Host driver"
> diff --git a/drivers/usb/usbip/vhci.h b/drivers/usb/usbip/vhci.h
> index 88b71c4..ba893a7 100644
> --- a/drivers/usb/usbip/vhci.h
> +++ b/drivers/usb/usbip/vhci.h
> @@ -51,6 +51,9 @@ struct vhci_device {
>  
>  	/* vhci_tx thread sleeps for this queue */
>  	wait_queue_head_t waitq_tx;
> +
> +	/* denotes port is in-use */
> +	atomic_t using_port;
>  };
>  
>  /* urb->hcpriv, use container_of() */
> @@ -79,12 +82,21 @@ struct vhci_unlink {
>  #define VHCI_HC_PORTS 8
>  #endif
>  
> -#ifdef CONFIG_USBIP_VHCI_NR_HCS
> -#define VHCI_NR_HCS CONFIG_USBIP_VHCI_NR_HCS
> +#ifdef CONFIG_USBIP_VHCI_MAX_HCS
> +#define VHCI_MAX_HCS CONFIG_USBIP_VHCI_MAX_HCS
> +#else
> +#define VHCI_MAX_HCS 1
> +#endif
> +
> +#ifdef CONFIG_USBIP_VHCI_INIT_HCS
> +#define VHCI_INIT_HCS CONFIG_USBIP_VHCI_INIT_HCS
>  #else
> -#define VHCI_NR_HCS 1
> +#define VHCI_INIT_HCS 1
>  #endif
>  
> +/* VHCI_FREE_HCS * VHCI_HC_PORTS: ports to keep free at unregister */
> +#define VHCI_FREE_HCS 2
> +
>  #define MAX_STATUS_NAME 16
>  
>  /* for usb_bus.hcpriv */
> @@ -98,6 +110,8 @@ struct vhci_hcd {
>  
>  	atomic_t seqnum;
>  
> +	unsigned int using_ports;
> +
>  	/*
>  	 * NOTE:
>  	 * wIndex shows the port number and begins from 1.
> @@ -106,12 +120,18 @@ struct vhci_hcd {
>  	struct vhci_device vdev[VHCI_HC_PORTS];
>  };
>  
> +extern int vhci_max_controllers;
> +extern int vhci_init_controllers;
>  extern int vhci_num_controllers;
>  extern struct platform_device **vhci_pdevs;
>  extern struct attribute_group vhci_attr_group;
>  
>  /* vhci_hcd.c */
>  void rh_port_connect(struct vhci_device *vdev, enum usb_device_speed speed);
> +int vhci_get_device(__u32 pdev_nr, __u32 rhport,
> +		    struct vhci_hcd **vhci, struct vhci_device **vdev);
> +void vhci_put_device(struct vhci_device *vdev);
> +void vhci_event_add(struct usbip_device *ud, unsigned long event);
>  
>  /* vhci_sysfs.c */
>  int vhci_init_attr_group(void);
> @@ -160,4 +180,14 @@ static inline struct vhci_hcd *vdev_to_vhci(struct vhci_device *vdev)
>  			(void *)(vdev - vdev->rhport), struct vhci_hcd, vdev);
>  }
>  
> +static inline int pdev_id2nr(int id)
> +{
> +	return (id < 0) ? 0 : id;
> +}
> +
> +static inline int pdev_nr2id(int nr)
> +{
> +	return (nr == 0) ? -1 : nr;
> +}
> +
>  #endif /* __USBIP_VHCI_H */
> diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
> index c4724fb..4a0f1ae 100644
> --- a/drivers/usb/usbip/vhci_hcd.c
> +++ b/drivers/usb/usbip/vhci_hcd.c
> @@ -57,10 +57,22 @@ static int vhci_get_frame_number(struct usb_hcd *hcd);
>  static const char driver_name[] = "vhci_hcd";
>  static const char driver_desc[] = "USB/IP Virtual Host Controller";
>  
> -int vhci_num_controllers = VHCI_NR_HCS;
> +int vhci_max_controllers = VHCI_MAX_HCS;
> +int vhci_init_controllers = VHCI_INIT_HCS;
> +int vhci_num_controllers;
>  
> +static spinlock_t pdevs_lock;
>  struct platform_device **vhci_pdevs;
>  
> +static spinlock_t using_ports_lock;
> +static unsigned int vhci_using_ports;
> +
> +static int pdevs_init_completed;
> +static atomic_t pdevs_init_count;
> +
> +static wait_queue_head_t pdevs_waitq;
> +static int pdev_nr_started;
> +
>  static const char * const bit_desc[] = {
>  	"CONNECTION",		/*0*/
>  	"ENABLE",		/*1*/
> @@ -439,7 +451,7 @@ static struct vhci_device *get_vdev(struct usb_device *udev)
>  	if (!udev)
>  		return NULL;
>  
> -	for (pdev_nr = 0; pdev_nr < vhci_num_controllers; pdev_nr++) {
> +	for (pdev_nr = 0; pdev_nr < vhci_max_controllers; pdev_nr++) {
>  		pdev = *(vhci_pdevs + pdev_nr);
>  		if (pdev == NULL)
>  			continue;
> @@ -471,7 +483,7 @@ static void vhci_tx_urb(struct urb *urb)
>  
>  	priv = kzalloc(sizeof(struct vhci_priv), GFP_ATOMIC);
>  	if (!priv) {
> -		usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC);
> +		vhci_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC);
>  		return;
>  	}
>  
> @@ -727,7 +739,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
>  		if (!unlink) {
>  			spin_unlock(&vdev->priv_lock);
>  			spin_unlock_irqrestore(&vhci->lock, flags);
> -			usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC);
> +			vhci_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC);
>  			return -ENOMEM;
>  		}
>  
> @@ -868,7 +880,6 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
>  	pr_info("disconnect device\n");
>  }
>  
> -
>  static void vhci_device_reset(struct usbip_device *ud)
>  {
>  	struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
> @@ -889,15 +900,20 @@ static void vhci_device_reset(struct usbip_device *ud)
>  	ud->status = VDEV_ST_NULL;
>  
>  	spin_unlock_irqrestore(&ud->lock, flags);
> +
> +	vhci_put_device(vdev);
>  }
>  
>  static void vhci_device_unusable(struct usbip_device *ud)
>  {
> +	struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
>  	unsigned long flags;
>  
>  	spin_lock_irqsave(&ud->lock, flags);
>  	ud->status = VDEV_ST_ERROR;
>  	spin_unlock_irqrestore(&ud->lock, flags);
> +
> +	vhci_put_device(vdev);
>  }
>  
>  static void vhci_device_init(struct vhci_device *vdev)
> @@ -907,6 +923,7 @@ static void vhci_device_init(struct vhci_device *vdev)
>  	vdev->ud.side   = USBIP_VHCI;
>  	vdev->ud.status = VDEV_ST_NULL;
>  	spin_lock_init(&vdev->ud.lock);
> +	atomic_set(&vdev->using_port, 0);
>  
>  	INIT_LIST_HEAD(&vdev->priv_rx);
>  	INIT_LIST_HEAD(&vdev->priv_tx);
> @@ -923,7 +940,7 @@ static void vhci_device_init(struct vhci_device *vdev)
>  	usbip_start_eh(&vdev->ud);
>  }
>  
> -static int hcd_name_to_id(const char *name)
> +static int hcd_name_to_pdev_nr(const char *name)
>  {
>  	char *c;
>  	long val;
> @@ -943,7 +960,7 @@ static int hcd_name_to_id(const char *name)
>  static int vhci_start(struct usb_hcd *hcd)
>  {
>  	struct vhci_hcd *vhci = hcd_to_vhci(hcd);
> -	int id, rhport;
> +	int pdev_nr, rhport;
>  	int err = 0;
>  
>  	usbip_dbg_vhci_hc("enter vhci_start\n");
> @@ -959,18 +976,19 @@ static int vhci_start(struct usb_hcd *hcd)
>  
>  	atomic_set(&vhci->seqnum, 0);
>  	spin_lock_init(&vhci->lock);
> +	vhci->using_ports = 0;
>  
>  	hcd->power_budget = 0; /* no limit */
>  	hcd->uses_new_polling = 1;
>  
> -	id = hcd_name_to_id(hcd_name(hcd));
> -	if (id < 0) {
> +	pdev_nr = hcd_name_to_pdev_nr(hcd_name(hcd));
> +	if (pdev_nr < 0) {
>  		pr_err("invalid vhci name %s\n", hcd_name(hcd));
>  		return -EINVAL;
>  	}
>  
>  	/* vhci_hcd is now ready to be controlled through sysfs */
> -	if (id == 0) {
> +	if (pdev_nr == 0) {
>  		err = vhci_init_attr_group();
>  		if (err) {
>  			pr_err("init attr group\n");
> @@ -985,19 +1003,26 @@ static int vhci_start(struct usb_hcd *hcd)
>  		pr_info("created sysfs %s\n", hcd_name(hcd));
>  	}
>  
> +	if (atomic_dec_and_test(&pdevs_init_count))
> +		pdevs_init_completed = 1;
> +	if (pdevs_init_completed)
> +		atomic_set(&pdevs_init_count, -1);
> +	pdev_nr_started = pdev_nr;
> +	wake_up(&pdevs_waitq);
> +
>  	return 0;
>  }
>  
>  static void vhci_stop(struct usb_hcd *hcd)
>  {
>  	struct vhci_hcd *vhci = hcd_to_vhci(hcd);
> -	int id, rhport;
> +	int pdev_nr, rhport;
>  
>  	usbip_dbg_vhci_hc("stop VHCI controller\n");
>  
>  	/* 1. remove the userland interface of vhci_hcd */
> -	id = hcd_name_to_id(hcd_name(hcd));
> -	if (id == 0) {
> +	pdev_nr = hcd_name_to_pdev_nr(hcd_name(hcd));
> +	if (pdev_nr == 0) {
>  		sysfs_remove_group(&hcd_dev(hcd)->kobj, &vhci_attr_group);
>  		vhci_finish_attr_group();
>  	}
> @@ -1006,7 +1031,7 @@ static void vhci_stop(struct usb_hcd *hcd)
>  	for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) {
>  		struct vhci_device *vdev = &vhci->vdev[rhport];
>  
> -		usbip_event_add(&vdev->ud, VDEV_EVENT_REMOVED);
> +		vhci_event_add(&vdev->ud, VDEV_EVENT_REMOVED);
>  		usbip_stop_eh(&vdev->ud);
>  	}
>  }
> @@ -1201,49 +1226,198 @@ static struct platform_driver vhci_driver = {
>  	},
>  };
>  
> -static int add_platform_device(int id)
> +static int __add_platform_device(int pdev_nr)
>  {
>  	struct platform_device *pdev;
> -	int dev_nr;
> -
> -	if (id == 0)
> -		dev_nr = -1;
> -	else
> -		dev_nr = id;
> +	int id = pdev_nr2id(pdev_nr);
>  
> -	pdev = platform_device_register_simple(driver_name, dev_nr, NULL, 0);
> -	if (IS_ERR(pdev))
> +	pdev = platform_device_register_simple(driver_name, id, NULL, 0);
> +	if (IS_ERR(pdev)) {
> +		pr_err("failed to register pdev\n");
>  		return PTR_ERR(pdev);
> +	}
>  
> -	*(vhci_pdevs + id) = pdev;
> +	*(vhci_pdevs + pdev_nr) = pdev;
> +	++vhci_num_controllers;
>  	return 0;
>  }
>  
> +static void __del_platform_device(int pdev_nr)
> +{
> +	struct platform_device *pdev = *(vhci_pdevs + pdev_nr);
> +
> +	if (!pdev)
> +		return;
> +
> +	usbip_dbg_vhci_rh("deleting pdev %d\n", pdev_nr);
> +	*(vhci_pdevs + pdev_nr) = NULL;
> +	vhci_num_controllers--;
> +	platform_device_unregister(pdev);
> +}
> +
> +static void __del_platform_devices(void)
> +{
> +	int i;
> +
> +	for (i = 0; i < vhci_max_controllers; i++)
> +		__del_platform_device(i);
> +	sysfs_remove_link(&platform_bus.kobj, driver_name);
> +}
> +
>  static void del_platform_devices(void)
>  {
> +	spin_lock(&pdevs_lock);
> +	__del_platform_devices();
> +	spin_unlock(&pdevs_lock);
> +}
> +
> +static void __vhci_get_device(struct platform_device *pdev, __u32 rhport,
> +			      struct vhci_hcd **vhci, struct vhci_device **vdev)
> +{
> +	struct usb_hcd *hcd;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&using_ports_lock, flags);
> +	hcd = platform_get_drvdata(pdev);
> +	*vhci = hcd_to_vhci(hcd);
> +	*vdev = &((*vhci)->vdev[rhport]);
> +	vhci_using_ports++;
> +	((*vhci)->using_ports)++;
> +	atomic_set(&((*vdev)->using_port), 1);
> +	spin_unlock_irqrestore(&using_ports_lock, flags);
> +}
> +
> +int vhci_get_device(__u32 pdev_nr, __u32 rhport,
> +		    struct vhci_hcd **vhci, struct vhci_device **vdev)
> +{
>  	struct platform_device *pdev;
> -	int i;
> +	unsigned long flags;
> +	int ret;
> +
> +	if (wait_event_interruptible(pdevs_waitq, pdevs_init_completed))
> +		return -ERESTARTSYS;
>  
> -	for (i = 0; i < vhci_num_controllers; i++) {
> -		pdev = *(vhci_pdevs + i);
> -		if (pdev != NULL)
> -			platform_device_unregister(pdev);
> -		*(vhci_pdevs + i) = NULL;
> +	spin_lock_irqsave(&pdevs_lock, flags);
> +
> +	pdev = *(vhci_pdevs + pdev_nr);
> +	if (pdev) {
> +		__vhci_get_device(pdev, rhport, vhci, vdev);
> +		spin_unlock_irqrestore(&pdevs_lock, flags);
> +		return 0;
>  	}
> -	sysfs_remove_link(&platform_bus.kobj, driver_name);
> +
> +	pdev_nr_started = -1;
> +
> +	ret = __add_platform_device(pdev_nr);
> +	if (ret) {
> +		spin_unlock_irqrestore(&pdevs_lock, flags);
> +		return ret;
> +	}
> +
> +	usbip_dbg_vhci_rh("waiting pdev started %d\n", pdev_nr);
> +	if (wait_event_interruptible(pdevs_waitq,
> +				     pdev_nr_started == pdev_nr)) {
> +		spin_unlock_irqrestore(&pdevs_lock, flags);
> +		return -ERESTARTSYS;
> +	}
> +	usbip_dbg_vhci_rh("end of waiting pdev started %d\n", pdev_nr);
> +
> +	pdev = *(vhci_pdevs + pdev_nr);
> +	__vhci_get_device(pdev, rhport, vhci, vdev);
> +
> +	spin_unlock_irqrestore(&pdevs_lock, flags);
> +
> +	return 0;
> +}
> +
> +void vhci_put_device(struct vhci_device *vdev)
> +{
> +	struct vhci_hcd *vhci;
> +	unsigned long flags;
> +
> +	if (!atomic_dec_and_test(&vdev->using_port))
> +		return;
> +
> +	spin_lock_irqsave(&using_ports_lock, flags);
> +	vhci = vdev_to_vhci(vdev);
> +	(vhci->using_ports)--;
> +	vhci_using_ports--;
> +	spin_unlock_irqrestore(&using_ports_lock, flags);
> +}
> +
> +static int __try_del_platform_device(void)
> +{
> +	int pdev_nr;
> +	struct platform_device *pdev;
> +	struct vhci_hcd *vhci;
> +
> +	for (pdev_nr = (vhci_max_controllers - 1); pdev_nr > 0; pdev_nr--) {
> +		pdev = *(vhci_pdevs + pdev_nr);
> +		if (!pdev)
> +			continue;
> +		vhci = hcd_to_vhci(platform_get_drvdata(pdev));
> +		if (!vhci->using_ports) {
> +			__del_platform_device(pdev_nr);
> +			return 1;
> +		}
> +	}
> +	return 0;
> +}
> +
> +static void try_del_platform_device(void)
> +{
> +	unsigned long flags;
> +	unsigned int free_ports;
> +
> +	if (!spin_trylock_irqsave(&pdevs_lock, flags)) {
> +		usbip_dbg_vhci_rh("recursive call or exitting\n");
> +		return;
> +	}
> +	usbip_dbg_vhci_rh("trying del pdev\n");
> +
> +	if (vhci_num_controllers > vhci_init_controllers) {
> +		free_ports = (vhci_num_controllers * VHCI_HC_PORTS)
> +				- vhci_using_ports;
> +		usbip_dbg_vhci_rh("%d free ports in %d hcs\n",
> +				  free_ports, vhci_num_controllers);
> +		/* free_pots will be decremented with this event */
> +		if (free_ports >=  (VHCI_HC_PORTS * VHCI_FREE_HCS))
> +			__try_del_platform_device();
> +	}
> +
> +	spin_unlock_irqrestore(&pdevs_lock, flags);
> +}
> +
> +void vhci_event_add(struct usbip_device *ud, unsigned long event)
> +{
> +	usbip_dbg_vhci_rh("adding event %lu\n", event);
> +
> +	if (event != VDEV_EVENT_REMOVED && !usbip_in_eh(current))
> +		try_del_platform_device();
> +
> +	usbip_event_add(ud, event);
>  }
>  
>  static int __init vhci_hcd_init(void)
>  {
> -	int i, ret;
> +	int pdev_nr, ret;
>  
>  	if (usb_disabled())
>  		return -ENODEV;
>  
> -	if (vhci_num_controllers < 1)
> -		vhci_num_controllers = 1;
> +	if (vhci_max_controllers < 1)
> +		vhci_max_controllers = 1;
> +	if (vhci_init_controllers < 1)
> +		vhci_init_controllers = 1;
> +	if (vhci_init_controllers > vhci_max_controllers)
> +		vhci_init_controllers = vhci_max_controllers;
>  
> -	vhci_pdevs = kcalloc(vhci_num_controllers, sizeof(void *), GFP_KERNEL);
> +	spin_lock_init(&pdevs_lock);
> +	spin_lock_init(&using_ports_lock);
> +	init_waitqueue_head(&pdevs_waitq);
> +	atomic_set(&pdevs_init_count, vhci_init_controllers);
> +
> +	vhci_pdevs = kcalloc(vhci_max_controllers, sizeof(void *), GFP_KERNEL);
>  	if (vhci_pdevs == NULL)
>  		return -ENOMEM;
>  
> @@ -1251,8 +1425,8 @@ static int __init vhci_hcd_init(void)
>  	if (ret)
>  		goto err_driver_register;
>  
> -	for (i = 0; i < vhci_num_controllers; i++) {
> -		ret = add_platform_device(i);
> +	for (pdev_nr = 0; pdev_nr < vhci_init_controllers; pdev_nr++) {
> +		ret = __add_platform_device(pdev_nr);
>  		if (ret)
>  			goto err_platform_device_register;
>  	}
> @@ -1261,7 +1435,7 @@ static int __init vhci_hcd_init(void)
>  	return ret;
>  
>  err_platform_device_register:
> -	del_platform_devices();
> +	__del_platform_devices();
>  	platform_driver_unregister(&vhci_driver);
>  err_driver_register:
>  	kfree(vhci_pdevs);
> diff --git a/drivers/usb/usbip/vhci_rx.c b/drivers/usb/usbip/vhci_rx.c
> index fc2d319..bea43f7 100644
> --- a/drivers/usb/usbip/vhci_rx.c
> +++ b/drivers/usb/usbip/vhci_rx.c
> @@ -83,7 +83,7 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,
>  		pr_err("cannot find a urb of seqnum %u\n", pdu->base.seqnum);
>  		pr_info("max seqnum %d\n",
>  			atomic_read(&vhci->seqnum));
> -		usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
> +		vhci_event_add(ud, VDEV_EVENT_ERROR_TCP);
>  		return;
>  	}
>  
> @@ -222,18 +222,18 @@ static void vhci_rx_pdu(struct usbip_device *ud)
>  		} else if (ret != -ERESTARTSYS)
>  			pr_info("xmit failed %d\n", ret);
>  
> -		usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
> +		vhci_event_add(ud, VDEV_EVENT_ERROR_TCP);
>  		return;
>  	}
>  	if (ret == 0) {
>  		pr_info("connection closed");
> -		usbip_event_add(ud, VDEV_EVENT_DOWN);
> +		vhci_event_add(ud, VDEV_EVENT_DOWN);
>  		return;
>  	}
>  	if (ret != sizeof(pdu)) {
>  		pr_err("received pdu size is %d, should be %d\n", ret,
>  		       (unsigned int)sizeof(pdu));
> -		usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
> +		vhci_event_add(ud, VDEV_EVENT_ERROR_TCP);
>  		return;
>  	}
>  
> @@ -253,7 +253,7 @@ static void vhci_rx_pdu(struct usbip_device *ud)
>  		/* NOT REACHED */
>  		pr_err("unknown pdu %u\n", pdu.base.command);
>  		usbip_dump_header(&pdu);
> -		usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
> +		vhci_event_add(ud, VDEV_EVENT_ERROR_TCP);
>  		break;
>  	}
>  }
> diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c
> index 5d4be4b..589bcc8 100644
> --- a/drivers/usb/usbip/vhci_sysfs.c
> +++ b/drivers/usb/usbip/vhci_sysfs.c
> @@ -30,15 +30,15 @@
>  /* TODO: refine locking ?*/
>  
>  /* Sysfs entry to show port status */
> -static ssize_t status_show_vhci(int pdev_nr, char *out)
> +static ssize_t status_show_vhci(int pdev_nr, struct platform_device *pdev,
> +				char *out)
>  {
> -	struct platform_device *pdev = *(vhci_pdevs + pdev_nr);
>  	struct vhci_hcd *vhci;
>  	char *s = out;
>  	int i = 0;
>  	unsigned long flags;
>  
> -	if (!pdev || !out) {
> +	if (!out) {
>  		usbip_dbg_vhci_sysfs("show status error\n");
>  		return 0;
>  	}
> @@ -86,7 +86,7 @@ static ssize_t status_show_vhci(int pdev_nr, char *out)
>  	return out - s;
>  }
>  
> -static ssize_t status_show_not_ready(int pdev_nr, char *out)
> +static ssize_t status_show_idle(int pdev_nr, char *out)
>  {
>  	char *s = out;
>  	int i = 0;
> @@ -94,7 +94,7 @@ static ssize_t status_show_not_ready(int pdev_nr, char *out)
>  	for (i = 0; i < VHCI_HC_PORTS; i++) {
>  		out += sprintf(out, "%04u %03u ",
>  				    (pdev_nr * VHCI_HC_PORTS) + i,
> -				    VDEV_ST_NOTASSIGNED);
> +				    VDEV_ST_NULL);
>  		out += sprintf(out, "000 00000000 0000000000000000 0-0");
>  		out += sprintf(out, "\n");
>  	}
> @@ -123,15 +123,20 @@ static ssize_t status_show(struct device *dev,
>  {
>  	char *s = out;
>  	int pdev_nr;
> +	struct platform_device *pdev = NULL;
>  
>  	out += sprintf(out,
>  		       "port sta spd dev      socket           local_busid\n");
>  
>  	pdev_nr = status_name_to_id(attr->attr.name);
>  	if (pdev_nr < 0)
> -		out += status_show_not_ready(pdev_nr, out);
> +		return 0;
> +
> +	pdev = *(vhci_pdevs + pdev_nr);
> +	if (pdev)
> +		out += status_show_vhci(pdev_nr, pdev, out);
>  	else
> -		out += status_show_vhci(pdev_nr, out);
> +		out += status_show_idle(pdev_nr, out);
>  
>  	return out - s;
>  }
> @@ -141,7 +146,7 @@ static ssize_t nports_show(struct device *dev, struct device_attribute *attr,
>  {
>  	char *s = out;
>  
> -	out += sprintf(out, "%d\n", VHCI_HC_PORTS * vhci_num_controllers);
> +	out += sprintf(out, "%d\n", VHCI_HC_PORTS * vhci_max_controllers);
>  	return out - s;
>  }
>  static DEVICE_ATTR_RO(nports);
> @@ -172,14 +177,14 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci, __u32 rhport)
>  	spin_unlock(&vdev->ud.lock);
>  	spin_unlock_irqrestore(&vhci->lock, flags);
>  
> -	usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN);
> +	vhci_event_add(&vdev->ud, VDEV_EVENT_DOWN);
>  
>  	return 0;
>  }
>  
>  static int valid_port(__u32 pdev_nr, __u32 rhport)
>  {
> -	if (pdev_nr >= vhci_num_controllers) {
> +	if (pdev_nr >= vhci_max_controllers) {
>  		pr_err("pdev %u\n", pdev_nr);
>  		return 0;
>  	}
> @@ -261,7 +266,6 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
>  	struct socket *socket;
>  	int sockfd = 0;
>  	__u32 port = 0, pdev_nr = 0, rhport = 0, devid = 0, speed = 0;
> -	struct usb_hcd *hcd;
>  	struct vhci_hcd *vhci;
>  	struct vhci_device *vdev;
>  	int err;
> @@ -287,18 +291,15 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
>  	if (!valid_args(pdev_nr, rhport, speed))
>  		return -EINVAL;
>  
> -	hcd = platform_get_drvdata(*(vhci_pdevs + pdev_nr));
> -	if (hcd == NULL) {
> -		dev_err(dev, "port %d is not ready\n", port);
> +	if (vhci_get_device(pdev_nr, rhport, &vhci, &vdev))
>  		return -EAGAIN;
> -	}
> -	vhci = hcd_to_vhci(hcd);
> -	vdev = &vhci->vdev[rhport];
>  
>  	/* Extract socket from fd. */
>  	socket = sockfd_lookup(sockfd, &err);
> -	if (!socket)
> +	if (!socket) {
> +		vhci_put_device(vdev);
>  		return -EINVAL;
> +	}
>  
>  	/* now need lock until setting vdev status as used */
>  
> @@ -312,6 +313,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
>  		spin_unlock_irqrestore(&vhci->lock, flags);
>  
>  		sockfd_put(socket);
> +		vhci_put_device(vdev);
>  
>  		dev_err(dev, "port %d already used\n", rhport);
>  		/*
> @@ -372,12 +374,12 @@ static int init_status_attrs(void)
>  {
>  	int id;
>  
> -	status_attrs = kcalloc(vhci_num_controllers, sizeof(struct status_attr),
> +	status_attrs = kcalloc(vhci_max_controllers, sizeof(struct status_attr),
>  			       GFP_KERNEL);
>  	if (status_attrs == NULL)
>  		return -ENOMEM;
>  
> -	for (id = 0; id < vhci_num_controllers; id++)
> +	for (id = 0; id < vhci_max_controllers; id++)
>  		set_status_attr(id);
>  
>  	return 0;
> @@ -397,7 +399,7 @@ int vhci_init_attr_group(void)
>  	struct attribute **attrs;
>  	int ret, i;
>  
> -	attrs = kcalloc((vhci_num_controllers + 5), sizeof(struct attribute *),
> +	attrs = kcalloc((vhci_max_controllers + 5), sizeof(struct attribute *),
>  			GFP_KERNEL);
>  	if (attrs == NULL)
>  		return -ENOMEM;
> @@ -411,7 +413,7 @@ int vhci_init_attr_group(void)
>  	*(attrs + 1) = &dev_attr_detach.attr;
>  	*(attrs + 2) = &dev_attr_attach.attr;
>  	*(attrs + 3) = &dev_attr_usbip_debug.attr;
> -	for (i = 0; i < vhci_num_controllers; i++)
> +	for (i = 0; i < vhci_max_controllers; i++)
>  		*(attrs + i + 4) = &((status_attrs + i)->attr.attr);
>  	vhci_attr_group.attrs = attrs;
>  	return 0;
> diff --git a/drivers/usb/usbip/vhci_tx.c b/drivers/usb/usbip/vhci_tx.c
> index 3e7878f..94f9c0a 100644
> --- a/drivers/usb/usbip/vhci_tx.c
> +++ b/drivers/usb/usbip/vhci_tx.c
> @@ -106,7 +106,7 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev)
>  
>  			iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len);
>  			if (!iso_buffer) {
> -				usbip_event_add(&vdev->ud,
> +				vhci_event_add(&vdev->ud,
>  						SDEV_EVENT_ERROR_MALLOC);
>  				return -1;
>  			}
> @@ -121,7 +121,7 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev)
>  			pr_err("sendmsg failed!, ret=%d for %zd\n", ret,
>  			       txsize);
>  			kfree(iso_buffer);
> -			usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP);
> +			vhci_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP);
>  			return -1;
>  		}
>  
> @@ -190,7 +190,7 @@ static int vhci_send_cmd_unlink(struct vhci_device *vdev)
>  		if (ret != txsize) {
>  			pr_err("sendmsg failed!, ret=%d for %zd\n", ret,
>  			       txsize);
> -			usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP);
> +			vhci_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP);
>  			return -1;
>  		}
>  
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux