summaryrefslogtreecommitdiff
path: root/drivers/usb/usbip
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/usbip')
-rw-r--r--drivers/usb/usbip/stub_dev.c9
-rw-r--r--drivers/usb/usbip/stub_main.c8
-rw-r--r--drivers/usb/usbip/stub_rx.c79
-rw-r--r--drivers/usb/usbip/stub_tx.c11
-rw-r--r--drivers/usb/usbip/usbip_common.h6
-rw-r--r--drivers/usb/usbip/vhci_hcd.c222
-rw-r--r--drivers/usb/usbip/vhci_rx.c6
-rw-r--r--drivers/usb/usbip/vhci_sysfs.c3
-rw-r--r--drivers/usb/usbip/vudc.h2
-rw-r--r--drivers/usb/usbip/vudc_dev.c8
-rw-r--r--drivers/usb/usbip/vudc_sysfs.c6
-rw-r--r--drivers/usb/usbip/vudc_transfer.c2
-rw-r--r--drivers/usb/usbip/vudc_tx.c2
13 files changed, 196 insertions, 168 deletions
diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c
index 9c6954aad6c8..ce625b1ce9a5 100644
--- a/drivers/usb/usbip/stub_dev.c
+++ b/drivers/usb/usbip/stub_dev.c
@@ -464,8 +464,13 @@ static void stub_disconnect(struct usb_device *udev)
/* release port */
rc = usb_hub_release_port(udev->parent, udev->portnum,
(struct usb_dev_state *) udev);
- if (rc) {
- dev_dbg(&udev->dev, "unable to release port\n");
+ /*
+ * NOTE: If a HUB disconnect triggered disconnect of the down stream
+ * device usb_hub_release_port will return -ENODEV so we can safely ignore
+ * that error here.
+ */
+ if (rc && (rc != -ENODEV)) {
+ dev_dbg(&udev->dev, "unable to release port (%i)\n", rc);
return;
}
diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c
index 0a6624d37929..79110a69d697 100644
--- a/drivers/usb/usbip/stub_main.c
+++ b/drivers/usb/usbip/stub_main.c
@@ -377,14 +377,14 @@ static int __init usbip_host_init(void)
goto err_usb_register;
}
- ret = driver_create_file(&stub_driver.drvwrap.driver,
+ ret = driver_create_file(&stub_driver.driver,
&driver_attr_match_busid);
if (ret) {
pr_err("driver_create_file failed\n");
goto err_create_file;
}
- ret = driver_create_file(&stub_driver.drvwrap.driver,
+ ret = driver_create_file(&stub_driver.driver,
&driver_attr_rebind);
if (ret) {
pr_err("driver_create_file failed\n");
@@ -402,10 +402,10 @@ err_usb_register:
static void __exit usbip_host_exit(void)
{
- driver_remove_file(&stub_driver.drvwrap.driver,
+ driver_remove_file(&stub_driver.driver,
&driver_attr_match_busid);
- driver_remove_file(&stub_driver.drvwrap.driver,
+ driver_remove_file(&stub_driver.driver,
&driver_attr_rebind);
/*
diff --git a/drivers/usb/usbip/stub_rx.c b/drivers/usb/usbip/stub_rx.c
index fc01b31bbb87..9aa30ef76f3b 100644
--- a/drivers/usb/usbip/stub_rx.c
+++ b/drivers/usb/usbip/stub_rx.c
@@ -144,53 +144,62 @@ static int tweak_set_configuration_cmd(struct urb *urb)
if (err && err != -ENODEV)
dev_err(&sdev->udev->dev, "can't set config #%d, error %d\n",
config, err);
- return 0;
+ return err;
}
static int tweak_reset_device_cmd(struct urb *urb)
{
struct stub_priv *priv = (struct stub_priv *) urb->context;
struct stub_device *sdev = priv->sdev;
+ int err;
dev_info(&urb->dev->dev, "usb_queue_reset_device\n");
- if (usb_lock_device_for_reset(sdev->udev, NULL) < 0) {
+ err = usb_lock_device_for_reset(sdev->udev, NULL);
+ if (err < 0) {
dev_err(&urb->dev->dev, "could not obtain lock to reset device\n");
- return 0;
+ return err;
}
- usb_reset_device(sdev->udev);
+ err = usb_reset_device(sdev->udev);
usb_unlock_device(sdev->udev);
- return 0;
+ return err;
}
/*
* clear_halt, set_interface, and set_configuration require special tricks.
+ * Returns 1 if request was tweaked, 0 otherwise.
*/
-static void tweak_special_requests(struct urb *urb)
+static int tweak_special_requests(struct urb *urb)
{
+ int err;
+
if (!urb || !urb->setup_packet)
- return;
+ return 0;
if (usb_pipetype(urb->pipe) != PIPE_CONTROL)
- return;
+ return 0;
if (is_clear_halt_cmd(urb))
/* tweak clear_halt */
- tweak_clear_halt_cmd(urb);
+ err = tweak_clear_halt_cmd(urb);
else if (is_set_interface_cmd(urb))
/* tweak set_interface */
- tweak_set_interface_cmd(urb);
+ err = tweak_set_interface_cmd(urb);
else if (is_set_configuration_cmd(urb))
/* tweak set_configuration */
- tweak_set_configuration_cmd(urb);
+ err = tweak_set_configuration_cmd(urb);
else if (is_reset_device_cmd(urb))
- tweak_reset_device_cmd(urb);
- else
+ err = tweak_reset_device_cmd(urb);
+ else {
usbip_dbg_stub_rx("no need to tweak\n");
+ return 0;
+ }
+
+ return !err;
}
/*
@@ -260,7 +269,7 @@ static int stub_recv_cmd_unlink(struct stub_device *sdev,
return 0;
}
- usbip_dbg_stub_rx("seqnum %d is not pending\n",
+ usbip_dbg_stub_rx("seqnum %u is not pending\n",
pdu->u.cmd_unlink.seqnum);
/*
@@ -468,6 +477,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
int support_sg = 1;
int np = 0;
int ret, i;
+ int is_tweaked;
if (pipe == -1)
return;
@@ -580,8 +590,11 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
priv->urbs[i]->pipe = pipe;
priv->urbs[i]->complete = stub_complete;
- /* no need to submit an intercepted request, but harmless? */
- tweak_special_requests(priv->urbs[i]);
+ /*
+ * all URBs belong to a single PDU, so a global is_tweaked flag is
+ * enough
+ */
+ is_tweaked = tweak_special_requests(priv->urbs[i]);
masking_bogus_flags(priv->urbs[i]);
}
@@ -594,22 +607,32 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
/* urb is now ready to submit */
for (i = 0; i < priv->num_urbs; i++) {
- ret = usb_submit_urb(priv->urbs[i], GFP_KERNEL);
+ if (!is_tweaked) {
+ ret = usb_submit_urb(priv->urbs[i], GFP_KERNEL);
- if (ret == 0)
- usbip_dbg_stub_rx("submit urb ok, seqnum %u\n",
- pdu->base.seqnum);
- else {
- dev_err(&udev->dev, "submit_urb error, %d\n", ret);
- usbip_dump_header(pdu);
- usbip_dump_urb(priv->urbs[i]);
+ if (ret == 0)
+ usbip_dbg_stub_rx("submit urb ok, seqnum %u\n",
+ pdu->base.seqnum);
+ else {
+ dev_err(&udev->dev, "submit_urb error, %d\n", ret);
+ usbip_dump_header(pdu);
+ usbip_dump_urb(priv->urbs[i]);
+ /*
+ * Pessimistic.
+ * This connection will be discarded.
+ */
+ usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT);
+ break;
+ }
+ } else {
/*
- * Pessimistic.
- * This connection will be discarded.
+ * An identical URB was already submitted in
+ * tweak_special_requests(). Skip submitting this URB to not
+ * duplicate the request.
*/
- usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT);
- break;
+ priv->urbs[i]->status = 0;
+ stub_complete(priv->urbs[i]);
}
}
diff --git a/drivers/usb/usbip/stub_tx.c b/drivers/usb/usbip/stub_tx.c
index b1c2f6781cb3..55919c3762ba 100644
--- a/drivers/usb/usbip/stub_tx.c
+++ b/drivers/usb/usbip/stub_tx.c
@@ -4,6 +4,7 @@
*/
#include <linux/kthread.h>
+#include <linux/minmax.h>
#include <linux/socket.h>
#include <linux/scatterlist.h>
@@ -201,7 +202,7 @@ static int stub_send_ret_submit(struct stub_device *sdev)
/* 1. setup usbip_header */
setup_ret_submit_pdu(&pdu_header, urb);
- usbip_dbg_stub_tx("setup txdata seqnum: %d\n",
+ usbip_dbg_stub_tx("setup txdata seqnum: %u\n",
pdu_header.base.seqnum);
if (priv->sgl) {
@@ -239,17 +240,13 @@ static int stub_send_ret_submit(struct stub_device *sdev)
urb->actual_length > 0) {
if (urb->num_sgs) {
unsigned int copy = urb->actual_length;
- int size;
+ unsigned int size;
for_each_sg(urb->sg, sg, urb->num_sgs, i) {
if (copy == 0)
break;
- if (copy < sg->length)
- size = copy;
- else
- size = sg->length;
-
+ size = min(copy, sg->length);
iov[iovnum].iov_base = sg_virt(sg);
iov[iovnum].iov_len = size;
diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_common.h
index d8cbd2dfc2c2..282efca64a01 100644
--- a/drivers/usb/usbip/usbip_common.h
+++ b/drivers/usb/usbip/usbip_common.h
@@ -298,12 +298,6 @@ struct usbip_device {
__k; \
})
-#define kthread_stop_put(k) \
- do { \
- kthread_stop(k); \
- put_task_struct(k); \
- } while (0)
-
/* usbip_common.c */
void usbip_dump_urb(struct urb *purb);
void usbip_dump_header(struct usbip_header *pdu);
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
index 37d1fc34e8a5..e55690da19e5 100644
--- a/drivers/usb/usbip/vhci_hcd.c
+++ b/drivers/usb/usbip/vhci_hcd.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/string_choices.h>
#include "usbip_common.h"
#include "vhci.h"
@@ -345,9 +346,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
if (wIndex < 1 || wIndex > VHCI_HC_PORTS) {
invalid_rhport = true;
if (wIndex > VHCI_HC_PORTS)
- pr_err("invalid port number %d\n", wIndex);
- } else
+ dev_err(hcd_dev(hcd), "invalid port number %d\n", wIndex);
+ } else {
rhport = wIndex - 1;
+ }
vhci_hcd = hcd_to_vhci_hcd(hcd);
vhci = vhci_hcd->vhci;
@@ -367,14 +369,14 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
break;
case ClearPortFeature:
if (invalid_rhport) {
- pr_err("invalid port number %d\n", wIndex);
+ dev_err(hcd_dev(hcd), "invalid port number %d\n", wIndex);
goto error;
}
switch (wValue) {
case USB_PORT_FEAT_SUSPEND:
- if (hcd->speed == HCD_USB3) {
- pr_err(" ClearPortFeature: USB_PORT_FEAT_SUSPEND req not "
- "supported for USB 3.0 roothub\n");
+ if (hcd->speed >= HCD_USB3) {
+ dev_err(hcd_dev(hcd),
+ "ClearPortFeature: USB_PORT_FEAT_SUSPEND req not supported for USB 3.0 roothub\n");
goto error;
}
usbip_dbg_vhci_rh(
@@ -388,7 +390,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case USB_PORT_FEAT_POWER:
usbip_dbg_vhci_rh(
" ClearPortFeature: USB_PORT_FEAT_POWER\n");
- if (hcd->speed == HCD_USB3)
+ if (hcd->speed >= HCD_USB3)
vhci_hcd->port_status[rhport] &= ~USB_SS_PORT_STAT_POWER;
else
vhci_hcd->port_status[rhport] &= ~USB_PORT_STAT_POWER;
@@ -404,19 +406,20 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
break;
case GetHubDescriptor:
usbip_dbg_vhci_rh(" GetHubDescriptor\n");
- if (hcd->speed == HCD_USB3 &&
+ if (hcd->speed >= HCD_USB3 &&
(wLength < USB_DT_SS_HUB_SIZE ||
wValue != (USB_DT_SS_HUB << 8))) {
- pr_err("Wrong hub descriptor type for USB 3.0 roothub.\n");
+ dev_err(hcd_dev(hcd),
+ "Wrong hub descriptor type for USB 3.0 roothub.\n");
goto error;
}
- if (hcd->speed == HCD_USB3)
+ if (hcd->speed >= HCD_USB3)
ss_hub_descriptor((struct usb_hub_descriptor *) buf);
else
hub_descriptor((struct usb_hub_descriptor *) buf);
break;
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
- if (hcd->speed != HCD_USB3)
+ if (hcd->speed < HCD_USB3)
goto error;
if ((wValue >> 8) != USB_DT_BOS)
@@ -432,7 +435,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case GetPortStatus:
usbip_dbg_vhci_rh(" GetPortStatus port %x\n", wIndex);
if (invalid_rhport) {
- pr_err("invalid port number %d\n", wIndex);
+ dev_err(hcd_dev(hcd), "invalid port number %d\n", wIndex);
retval = -EPIPE;
goto error;
}
@@ -482,7 +485,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
USB_PORT_STAT_LOW_SPEED;
break;
default:
- pr_err("vhci_device speed not set\n");
+ dev_err(hcd_dev(hcd), "vhci_device speed not set\n");
break;
}
}
@@ -503,9 +506,9 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case USB_PORT_FEAT_LINK_STATE:
usbip_dbg_vhci_rh(
" SetPortFeature: USB_PORT_FEAT_LINK_STATE\n");
- if (hcd->speed != HCD_USB3) {
- pr_err("USB_PORT_FEAT_LINK_STATE req not "
- "supported for USB 2.0 roothub\n");
+ if (hcd->speed < HCD_USB3) {
+ dev_err(hcd_dev(hcd),
+ "USB_PORT_FEAT_LINK_STATE req not supported for USB 2.0 roothub\n");
goto error;
}
/*
@@ -521,9 +524,9 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
usbip_dbg_vhci_rh(
" SetPortFeature: USB_PORT_FEAT_U2_TIMEOUT\n");
/* TODO: add suspend/resume support! */
- if (hcd->speed != HCD_USB3) {
- pr_err("USB_PORT_FEAT_U1/2_TIMEOUT req not "
- "supported for USB 2.0 roothub\n");
+ if (hcd->speed < HCD_USB3) {
+ dev_err(hcd_dev(hcd),
+ "USB_PORT_FEAT_U1/2_TIMEOUT req not supported for USB 2.0 roothub\n");
goto error;
}
break;
@@ -531,14 +534,14 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
usbip_dbg_vhci_rh(
" SetPortFeature: USB_PORT_FEAT_SUSPEND\n");
/* Applicable only for USB2.0 hub */
- if (hcd->speed == HCD_USB3) {
- pr_err("USB_PORT_FEAT_SUSPEND req not "
- "supported for USB 3.0 roothub\n");
+ if (hcd->speed >= HCD_USB3) {
+ dev_err(hcd_dev(hcd),
+ "USB_PORT_FEAT_SUSPEND req not supported for USB 3.0 roothub\n");
goto error;
}
if (invalid_rhport) {
- pr_err("invalid port number %d\n", wIndex);
+ dev_err(hcd_dev(hcd), "invalid port number %d\n", wIndex);
goto error;
}
@@ -548,10 +551,10 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
usbip_dbg_vhci_rh(
" SetPortFeature: USB_PORT_FEAT_POWER\n");
if (invalid_rhport) {
- pr_err("invalid port number %d\n", wIndex);
+ dev_err(hcd_dev(hcd), "invalid port number %d\n", wIndex);
goto error;
}
- if (hcd->speed == HCD_USB3)
+ if (hcd->speed >= HCD_USB3)
vhci_hcd->port_status[rhport] |= USB_SS_PORT_STAT_POWER;
else
vhci_hcd->port_status[rhport] |= USB_PORT_STAT_POWER;
@@ -560,13 +563,13 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
usbip_dbg_vhci_rh(
" SetPortFeature: USB_PORT_FEAT_BH_PORT_RESET\n");
if (invalid_rhport) {
- pr_err("invalid port number %d\n", wIndex);
+ dev_err(hcd_dev(hcd), "invalid port number %d\n", wIndex);
goto error;
}
/* Applicable only for USB3.0 hub */
- if (hcd->speed != HCD_USB3) {
- pr_err("USB_PORT_FEAT_BH_PORT_RESET req not "
- "supported for USB 2.0 roothub\n");
+ if (hcd->speed < HCD_USB3) {
+ dev_err(hcd_dev(hcd),
+ "USB_PORT_FEAT_BH_PORT_RESET req not supported for USB 2.0 roothub\n");
goto error;
}
fallthrough;
@@ -574,11 +577,11 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
usbip_dbg_vhci_rh(
" SetPortFeature: USB_PORT_FEAT_RESET\n");
if (invalid_rhport) {
- pr_err("invalid port number %d\n", wIndex);
+ dev_err(hcd_dev(hcd), "invalid port number %d\n", wIndex);
goto error;
}
/* if it's already enabled, disable */
- if (hcd->speed == HCD_USB3) {
+ if (hcd->speed >= HCD_USB3) {
vhci_hcd->port_status[rhport] = 0;
vhci_hcd->port_status[rhport] =
(USB_SS_PORT_STAT_POWER |
@@ -597,12 +600,12 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
usbip_dbg_vhci_rh(" SetPortFeature: default %d\n",
wValue);
if (invalid_rhport) {
- pr_err("invalid port number %d\n", wIndex);
+ dev_err(hcd_dev(hcd), "invalid port number %d\n", wIndex);
goto error;
}
if (wValue >= 32)
goto error;
- if (hcd->speed == HCD_USB3) {
+ if (hcd->speed >= HCD_USB3) {
if ((vhci_hcd->port_status[rhport] &
USB_SS_PORT_STAT_POWER) != 0) {
vhci_hcd->port_status[rhport] |= (1 << wValue);
@@ -616,9 +619,9 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
break;
case GetPortErrorCount:
usbip_dbg_vhci_rh(" GetPortErrorCount\n");
- if (hcd->speed != HCD_USB3) {
- pr_err("GetPortErrorCount req not "
- "supported for USB 2.0 roothub\n");
+ if (hcd->speed < HCD_USB3) {
+ dev_err(hcd_dev(hcd),
+ "GetPortErrorCount req not supported for USB 2.0 roothub\n");
goto error;
}
/* We'll always return 0 since this is a dummy hub */
@@ -626,14 +629,15 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
break;
case SetHubDepth:
usbip_dbg_vhci_rh(" SetHubDepth\n");
- if (hcd->speed != HCD_USB3) {
- pr_err("SetHubDepth req not supported for "
- "USB 2.0 roothub\n");
+ if (hcd->speed < HCD_USB3) {
+ dev_err(hcd_dev(hcd),
+ "SetHubDepth req not supported for USB 2.0 roothub\n");
goto error;
}
break;
default:
- pr_err("default hub control req: %04x v%04x i%04x l%d\n",
+ dev_err(hcd_dev(hcd),
+ "default hub control req: %04x v%04x i%04x l%d\n",
typeReq, wValue, wIndex, wLength);
error:
/* "protocol stall" on error */
@@ -641,12 +645,12 @@ error:
}
if (usbip_dbg_flag_vhci_rh) {
- pr_debug("port %d\n", rhport);
+ dev_dbg(hcd_dev(hcd), "%s port %d\n", __func__, rhport);
/* Only dump valid port status */
if (!invalid_rhport) {
dump_port_status_diff(prev_port_status[rhport],
vhci_hcd->port_status[rhport],
- hcd->speed == HCD_USB3);
+ hcd->speed >= HCD_USB3);
}
}
usbip_dbg_vhci_rh(" bye\n");
@@ -675,7 +679,7 @@ static void vhci_tx_urb(struct urb *urb, struct vhci_device *vdev)
spin_lock_irqsave(&vdev->priv_lock, flags);
- priv->seqnum = atomic_inc_return(&vhci_hcd->seqnum);
+ priv->seqnum = (u32)atomic_inc_return(&vhci_hcd->seqnum);
if (priv->seqnum == 0xffff)
dev_info(&urb->dev->dev, "seqnum max\n");
@@ -701,7 +705,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
unsigned long flags;
if (portnum > VHCI_HC_PORTS) {
- pr_err("invalid port number %d\n", portnum);
+ dev_err(hcd_dev(hcd), "invalid port number %d\n", portnum);
return -ENODEV;
}
vdev = &vhci_hcd->vdev[portnum-1];
@@ -745,6 +749,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
*
*/
if (usb_pipedevice(urb->pipe) == 0) {
+ struct usb_device *old;
__u8 type = usb_pipetype(urb->pipe);
struct usb_ctrlrequest *ctrlreq =
(struct usb_ctrlrequest *) urb->setup_packet;
@@ -755,14 +760,26 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
goto no_need_xmit;
}
+ old = vdev->udev;
switch (ctrlreq->bRequest) {
case USB_REQ_SET_ADDRESS:
/* set_address may come when a device is reset */
dev_info(dev, "SetAddress Request (%d) to port %d\n",
ctrlreq->wValue, vdev->rhport);
- usb_put_dev(vdev->udev);
vdev->udev = usb_get_dev(urb->dev);
+ /*
+ * NOTE: A similar operation has been done via
+ * USB_REQ_GET_DESCRIPTOR handler below, which is
+ * supposed to always precede USB_REQ_SET_ADDRESS.
+ *
+ * It's not entirely clear if operating on a different
+ * usb_device instance here is a real possibility,
+ * otherwise this call and vdev->udev assignment above
+ * should be dropped.
+ */
+ dev_pm_syscore_device(&vdev->udev->dev, true);
+ usb_put_dev(old);
spin_lock(&vdev->ud.lock);
vdev->ud.status = VDEV_ST_USED;
@@ -781,8 +798,19 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
usbip_dbg_vhci_hc(
"Not yet?:Get_Descriptor to device 0 (get max pipe size)\n");
- usb_put_dev(vdev->udev);
vdev->udev = usb_get_dev(urb->dev);
+ /*
+ * Set syscore PM flag for the virtually attached
+ * devices to ensure they will not enter suspend on
+ * the client side.
+ *
+ * Note this doesn't have any impact on the physical
+ * devices attached to the host system on the server
+ * side, hence there is no need to undo the operation
+ * on disconnect.
+ */
+ dev_pm_syscore_device(&vdev->udev->dev, true);
+ usb_put_dev(old);
goto out;
default:
@@ -806,15 +834,15 @@ out:
no_need_xmit:
usb_hcd_unlink_urb_from_ep(hcd, urb);
no_need_unlink:
- spin_unlock_irqrestore(&vhci->lock, flags);
if (!ret) {
/* usb_hcd_giveback_urb() should be called with
* irqs disabled
*/
- local_irq_disable();
+ spin_unlock(&vhci->lock);
usb_hcd_giveback_urb(hcd, urb, urb->status);
- local_irq_enable();
+ spin_lock(&vhci->lock);
}
+ spin_unlock_irqrestore(&vhci->lock, flags);
return ret;
}
@@ -933,7 +961,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
unlink->seqnum = atomic_inc_return(&vhci_hcd->seqnum);
if (unlink->seqnum == 0xffff)
- pr_info("seqnum max\n");
+ dev_info(hcd_dev(hcd), "seqnum max\n");
unlink->unlink_seqnum = priv->seqnum;
@@ -1011,10 +1039,11 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
static void vhci_shutdown_connection(struct usbip_device *ud)
{
struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
+ struct usb_hcd *hcd = vhci_hcd_to_hcd(vdev_to_vhci_hcd(vdev));
/* need this? see stub_dev.c */
if (ud->tcp_socket) {
- pr_debug("shutdown tcp_socket %d\n", ud->sockfd);
+ dev_dbg(hcd_dev(hcd), "shutdown tcp_socket %d\n", ud->sockfd);
kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
}
@@ -1027,7 +1056,7 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
kthread_stop_put(vdev->ud.tcp_tx);
vdev->ud.tcp_tx = NULL;
}
- pr_info("stop threads\n");
+ dev_info(hcd_dev(hcd), "stop threads\n");
/* active connection is closed */
if (vdev->ud.tcp_socket) {
@@ -1035,7 +1064,7 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
vdev->ud.tcp_socket = NULL;
vdev->ud.sockfd = -1;
}
- pr_info("release socket\n");
+ dev_info(hcd_dev(hcd), "release socket\n");
vhci_device_unlink_cleanup(vdev);
@@ -1061,12 +1090,13 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
*/
rh_port_disconnect(vdev);
- pr_info("disconnect device\n");
+ dev_info(hcd_dev(hcd), "disconnect device\n");
}
static void vhci_device_reset(struct usbip_device *ud)
{
struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
+ struct usb_device *old = vdev->udev;
unsigned long flags;
spin_lock_irqsave(&ud->lock, flags);
@@ -1074,8 +1104,8 @@ static void vhci_device_reset(struct usbip_device *ud)
vdev->speed = 0;
vdev->devid = 0;
- usb_put_dev(vdev->udev);
vdev->udev = NULL;
+ usb_put_dev(old);
if (ud->tcp_socket) {
sockfd_put(ud->tcp_socket);
@@ -1140,6 +1170,7 @@ static int hcd_name_to_id(const char *name)
static int vhci_setup(struct usb_hcd *hcd)
{
struct vhci *vhci = *((void **)dev_get_platdata(hcd->self.controller));
+
if (usb_hcd_is_primary_hcd(hcd)) {
vhci->vhci_hcd_hs = hcd_to_vhci_hcd(hcd);
vhci->vhci_hcd_hs->vhci = vhci;
@@ -1153,16 +1184,12 @@ static int vhci_setup(struct usb_hcd *hcd)
} else {
vhci->vhci_hcd_ss = hcd_to_vhci_hcd(hcd);
vhci->vhci_hcd_ss->vhci = vhci;
- hcd->speed = HCD_USB3;
- hcd->self.root_hub->speed = USB_SPEED_SUPER;
+ hcd->speed = HCD_USB31;
+ hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS;
}
- /*
- * Support SG.
- * sg_tablesize is an arbitrary value to alleviate memory pressure
- * on the host.
- */
- hcd->self.sg_tablesize = 32;
+ /* accept arbitrarily long scatter-gather lists */
+ hcd->self.sg_tablesize = ~0;
hcd->self.no_sg_constraint = 1;
return 0;
@@ -1199,7 +1226,7 @@ static int vhci_start(struct usb_hcd *hcd)
id = hcd_name_to_id(hcd_name(hcd));
if (id < 0) {
- pr_err("invalid vhci name %s\n", hcd_name(hcd));
+ dev_err(hcd_dev(hcd), "invalid vhci name %s\n", hcd_name(hcd));
return -EINVAL;
}
@@ -1216,7 +1243,7 @@ static int vhci_start(struct usb_hcd *hcd)
vhci_finish_attr_group();
return err;
}
- pr_info("created sysfs %s\n", hcd_name(hcd));
+ dev_info(hcd_dev(hcd), "created sysfs %s\n", hcd_name(hcd));
}
return 0;
@@ -1315,7 +1342,7 @@ static const struct hc_driver vhci_hc_driver = {
.product_desc = driver_desc,
.hcd_priv_size = sizeof(struct vhci_hcd),
- .flags = HCD_USB3 | HCD_SHARED,
+ .flags = HCD_USB31 | HCD_SHARED,
.reset = vhci_setup,
.start = vhci_start,
@@ -1349,10 +1376,9 @@ static int vhci_hcd_probe(struct platform_device *pdev)
* Our private data is also allocated automatically.
*/
hcd_hs = usb_create_hcd(&vhci_hc_driver, &pdev->dev, dev_name(&pdev->dev));
- if (!hcd_hs) {
- pr_err("create primary hcd failed\n");
- return -ENOMEM;
- }
+ if (!hcd_hs)
+ return dev_err_probe(&pdev->dev, -ENOMEM, "create primary hcd failed\n");
+
hcd_hs->has_tt = 1;
/*
@@ -1360,22 +1386,21 @@ static int vhci_hcd_probe(struct platform_device *pdev)
* Call the driver's reset() and start() routines.
*/
ret = usb_add_hcd(hcd_hs, 0, 0);
- if (ret != 0) {
- pr_err("usb_add_hcd hs failed %d\n", ret);
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret, "usb_add_hcd hs failed\n");
goto put_usb2_hcd;
}
hcd_ss = usb_create_shared_hcd(&vhci_hc_driver, &pdev->dev,
dev_name(&pdev->dev), hcd_hs);
if (!hcd_ss) {
- ret = -ENOMEM;
- pr_err("create shared hcd failed\n");
+ ret = dev_err_probe(&pdev->dev, -ENOMEM, "create shared hcd failed\n");
goto remove_usb2_hcd;
}
ret = usb_add_hcd(hcd_ss, 0, 0);
if (ret) {
- pr_err("usb_add_hcd ss failed %d\n", ret);
+ dev_err_probe(&pdev->dev, ret, "usb_add_hcd ss failed\n");
goto put_usb3_hcd;
}
@@ -1449,7 +1474,7 @@ static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state)
if (connected > 0) {
dev_info(&pdev->dev,
"We have %d active connection%s. Do not suspend.\n",
- connected, (connected == 1 ? "" : "s"));
+ connected, str_plural(connected));
ret = -EBUSY;
} else {
dev_info(&pdev->dev, "suspend vhci_hcd");
@@ -1483,7 +1508,7 @@ static int vhci_hcd_resume(struct platform_device *pdev)
static struct platform_driver vhci_driver = {
.probe = vhci_hcd_probe,
- .remove_new = vhci_hcd_remove,
+ .remove = vhci_hcd_remove,
.suspend = vhci_hcd_suspend,
.resume = vhci_hcd_resume,
.driver = {
@@ -1493,13 +1518,10 @@ static struct platform_driver vhci_driver = {
static void del_platform_devices(void)
{
- struct platform_device *pdev;
int i;
for (i = 0; i < vhci_num_controllers; i++) {
- pdev = vhcis[i].pdev;
- if (pdev != NULL)
- platform_device_unregister(pdev);
+ platform_device_unregister(vhcis[i].pdev);
vhcis[i].pdev = NULL;
}
sysfs_remove_link(&platform_bus.kobj, driver_name);
@@ -1519,45 +1541,33 @@ static int __init vhci_hcd_init(void)
if (vhcis == NULL)
return -ENOMEM;
- for (i = 0; i < vhci_num_controllers; i++) {
- vhcis[i].pdev = platform_device_alloc(driver_name, i);
- if (!vhcis[i].pdev) {
- i--;
- while (i >= 0)
- platform_device_put(vhcis[i--].pdev);
- ret = -ENOMEM;
- goto err_device_alloc;
- }
- }
- for (i = 0; i < vhci_num_controllers; i++) {
- void *vhci = &vhcis[i];
- ret = platform_device_add_data(vhcis[i].pdev, &vhci, sizeof(void *));
- if (ret)
- goto err_driver_register;
- }
-
ret = platform_driver_register(&vhci_driver);
if (ret)
goto err_driver_register;
for (i = 0; i < vhci_num_controllers; i++) {
- ret = platform_device_add(vhcis[i].pdev);
+ void *vhci = &vhcis[i];
+ struct platform_device_info pdevinfo = {
+ .name = driver_name,
+ .id = i,
+ .data = &vhci,
+ .size_data = sizeof(void *),
+ };
+
+ vhcis[i].pdev = platform_device_register_full(&pdevinfo);
+ ret = PTR_ERR_OR_ZERO(vhcis[i].pdev);
if (ret < 0) {
- i--;
- while (i >= 0)
- platform_device_del(vhcis[i--].pdev);
+ while (i--)
+ platform_device_unregister(vhcis[i].pdev);
goto err_add_hcd;
}
}
- return ret;
+ return 0;
err_add_hcd:
platform_driver_unregister(&vhci_driver);
err_driver_register:
- for (i = 0; i < vhci_num_controllers; i++)
- platform_device_put(vhcis[i].pdev);
-err_device_alloc:
kfree(vhcis);
return ret;
}
diff --git a/drivers/usb/usbip/vhci_rx.c b/drivers/usb/usbip/vhci_rx.c
index 7f2d1c241559..a75f4a898a41 100644
--- a/drivers/usb/usbip/vhci_rx.c
+++ b/drivers/usb/usbip/vhci_rx.c
@@ -66,7 +66,7 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,
spin_unlock_irqrestore(&vdev->priv_lock, flags);
if (!urb) {
- pr_err("cannot find a urb of seqnum %u max seqnum %d\n",
+ pr_err("cannot find a urb of seqnum %u max seqnum %u\n",
pdu->base.seqnum,
atomic_read(&vhci_hcd->seqnum));
usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
@@ -162,10 +162,10 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
* already received the result of its submit result and gave
* back the URB.
*/
- pr_info("the urb (seqnum %d) was already given back\n",
+ pr_info("the urb (seqnum %u) was already given back\n",
pdu->base.seqnum);
} else {
- usbip_dbg_vhci_rx("now giveback urb %d\n", pdu->base.seqnum);
+ usbip_dbg_vhci_rx("now giveback urb %u\n", pdu->base.seqnum);
/* If unlink is successful, status is -ECONNRESET */
urb->status = pdu->u.ret_unlink.status;
diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c
index e2847cd3e6e3..d5865460e82d 100644
--- a/drivers/usb/usbip/vhci_sysfs.c
+++ b/drivers/usb/usbip/vhci_sysfs.c
@@ -283,6 +283,7 @@ static int valid_args(__u32 *pdev_nr, __u32 *rhport,
case USB_SPEED_HIGH:
case USB_SPEED_WIRELESS:
case USB_SPEED_SUPER:
+ case USB_SPEED_SUPER_PLUS:
break;
default:
pr_err("Failed attach request for unsupported USB speed: %s\n",
@@ -349,7 +350,7 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
vhci_hcd = hcd_to_vhci_hcd(hcd);
vhci = vhci_hcd->vhci;
- if (speed == USB_SPEED_SUPER)
+ if (speed >= USB_SPEED_SUPER)
vdev = &vhci->vhci_hcd_ss->vdev[rhport];
else
vdev = &vhci->vhci_hcd_hs->vdev[rhport];
diff --git a/drivers/usb/usbip/vudc.h b/drivers/usb/usbip/vudc.h
index 1bd4bc005829..faf61c9c6a98 100644
--- a/drivers/usb/usbip/vudc.h
+++ b/drivers/usb/usbip/vudc.h
@@ -173,6 +173,6 @@ struct vudc_device *alloc_vudc_device(int devid);
void put_vudc_device(struct vudc_device *udc_dev);
int vudc_probe(struct platform_device *pdev);
-int vudc_remove(struct platform_device *pdev);
+void vudc_remove(struct platform_device *pdev);
#endif /* __USBIP_VUDC_H */
diff --git a/drivers/usb/usbip/vudc_dev.c b/drivers/usb/usbip/vudc_dev.c
index 2bc428f2e261..f11535020e35 100644
--- a/drivers/usb/usbip/vudc_dev.c
+++ b/drivers/usb/usbip/vudc_dev.c
@@ -489,11 +489,11 @@ static void vudc_device_unusable(struct usbip_device *ud)
struct vudc_device *alloc_vudc_device(int devid)
{
- struct vudc_device *udc_dev = NULL;
+ struct vudc_device *udc_dev;
udc_dev = kzalloc(sizeof(*udc_dev), GFP_KERNEL);
if (!udc_dev)
- goto out;
+ return NULL;
INIT_LIST_HEAD(&udc_dev->dev_entry);
@@ -503,7 +503,6 @@ struct vudc_device *alloc_vudc_device(int devid)
udc_dev = NULL;
}
-out:
return udc_dev;
}
@@ -629,12 +628,11 @@ out:
return ret;
}
-int vudc_remove(struct platform_device *pdev)
+void vudc_remove(struct platform_device *pdev)
{
struct vudc *udc = platform_get_drvdata(pdev);
usb_del_gadget_udc(&udc->gadget);
cleanup_vudc_hw(udc);
kfree(udc);
- return 0;
}
diff --git a/drivers/usb/usbip/vudc_sysfs.c b/drivers/usb/usbip/vudc_sysfs.c
index 907a43a00896..47f3a7d51736 100644
--- a/drivers/usb/usbip/vudc_sysfs.c
+++ b/drivers/usb/usbip/vudc_sysfs.c
@@ -67,7 +67,7 @@ out:
* Exposes device descriptor from the gadget driver.
*/
static ssize_t dev_desc_read(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *out,
+ const struct bin_attribute *attr, char *out,
loff_t off, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
@@ -88,7 +88,7 @@ unlock:
spin_unlock_irqrestore(&udc->lock, flags);
return ret;
}
-static BIN_ATTR_RO(dev_desc, sizeof(struct usb_device_descriptor));
+static const BIN_ATTR_RO(dev_desc, sizeof(struct usb_device_descriptor));
static ssize_t usbip_sockfd_store(struct device *dev,
struct device_attribute *attr,
@@ -252,7 +252,7 @@ static struct attribute *dev_attrs[] = {
NULL,
};
-static struct bin_attribute *dev_bin_attrs[] = {
+static const struct bin_attribute *const dev_bin_attrs[] = {
&bin_attr_dev_desc,
NULL,
};
diff --git a/drivers/usb/usbip/vudc_transfer.c b/drivers/usb/usbip/vudc_transfer.c
index 7e801fee33bf..a4f02ea3e3ef 100644
--- a/drivers/usb/usbip/vudc_transfer.c
+++ b/drivers/usb/usbip/vudc_transfer.c
@@ -301,7 +301,7 @@ top:
static void v_timer(struct timer_list *t)
{
- struct vudc *udc = from_timer(udc, t, tr_timer.timer);
+ struct vudc *udc = timer_container_of(udc, t, tr_timer.timer);
struct transfer_timer *timer = &udc->tr_timer;
struct urbp *urb_p, *tmp;
unsigned long flags;
diff --git a/drivers/usb/usbip/vudc_tx.c b/drivers/usb/usbip/vudc_tx.c
index 3ccb17c3e840..30c11bf9f4e7 100644
--- a/drivers/usb/usbip/vudc_tx.c
+++ b/drivers/usb/usbip/vudc_tx.c
@@ -107,7 +107,7 @@ static int v_send_ret_submit(struct vudc *udc, struct urbp *urb_p)
/* 1. setup usbip_header */
setup_ret_submit_pdu(&pdu_header, urb_p);
- usbip_dbg_stub_tx("setup txdata seqnum: %d\n",
+ usbip_dbg_stub_tx("setup txdata seqnum: %u\n",
pdu_header.base.seqnum);
usbip_header_correct_endian(&pdu_header, 1);