usbip: vhci-hcd: Set the vhci structure up to work

This patch enables the new vhci structure. Its lock protects
both the USB2 hub and the shared USB3 hub.

Signed-off-by: Yuyang Du <yuyang.du@intel.com>
Acked-by: Shuah Khan <shuahkh@osg.samsung.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Yuyang Du 2017-06-08 13:04:09 +08:00 коммит произвёл Greg Kroah-Hartman
Родитель dff3565b8e
Коммит 03cd00d538
4 изменённых файлов: 145 добавлений и 105 удалений

Просмотреть файл

@ -100,8 +100,6 @@ struct vhci {
struct vhci_hcd { struct vhci_hcd {
struct vhci *vhci; struct vhci *vhci;
spinlock_t lock;
u32 port_status[VHCI_HC_PORTS]; u32 port_status[VHCI_HC_PORTS];
unsigned resuming:1; unsigned resuming:1;

Просмотреть файл

@ -123,7 +123,8 @@ static void dump_port_status_diff(u32 prev_status, u32 new_status)
void rh_port_connect(struct vhci_device *vdev, enum usb_device_speed speed) void rh_port_connect(struct vhci_device *vdev, enum usb_device_speed speed)
{ {
struct vhci_hcd *vhci = vdev_to_vhci_hcd(vdev); struct vhci_hcd *vhci_hcd = vdev_to_vhci_hcd(vdev);
struct vhci *vhci = vhci_hcd->vhci;
int rhport = vdev->rhport; int rhport = vdev->rhport;
u32 status; u32 status;
unsigned long flags; unsigned long flags;
@ -132,7 +133,7 @@ void rh_port_connect(struct vhci_device *vdev, enum usb_device_speed speed)
spin_lock_irqsave(&vhci->lock, flags); spin_lock_irqsave(&vhci->lock, flags);
status = vhci->port_status[rhport]; status = vhci_hcd->port_status[rhport];
status |= USB_PORT_STAT_CONNECTION | (1 << USB_PORT_FEAT_C_CONNECTION); status |= USB_PORT_STAT_CONNECTION | (1 << USB_PORT_FEAT_C_CONNECTION);
@ -147,16 +148,17 @@ void rh_port_connect(struct vhci_device *vdev, enum usb_device_speed speed)
break; break;
} }
vhci->port_status[rhport] = status; vhci_hcd->port_status[rhport] = status;
spin_unlock_irqrestore(&vhci->lock, flags); spin_unlock_irqrestore(&vhci->lock, flags);
usb_hcd_poll_rh_status(vhci_hcd_to_hcd(vhci)); usb_hcd_poll_rh_status(vhci_hcd_to_hcd(vhci_hcd));
} }
static void rh_port_disconnect(struct vhci_device *vdev) static void rh_port_disconnect(struct vhci_device *vdev)
{ {
struct vhci_hcd *vhci = vdev_to_vhci_hcd(vdev); struct vhci_hcd *vhci_hcd = vdev_to_vhci_hcd(vdev);
struct vhci *vhci = vhci_hcd->vhci;
int rhport = vdev->rhport; int rhport = vdev->rhport;
u32 status; u32 status;
unsigned long flags; unsigned long flags;
@ -165,15 +167,15 @@ static void rh_port_disconnect(struct vhci_device *vdev)
spin_lock_irqsave(&vhci->lock, flags); spin_lock_irqsave(&vhci->lock, flags);
status = vhci->port_status[rhport]; status = vhci_hcd->port_status[rhport];
status &= ~USB_PORT_STAT_CONNECTION; status &= ~USB_PORT_STAT_CONNECTION;
status |= (1 << USB_PORT_FEAT_C_CONNECTION); status |= (1 << USB_PORT_FEAT_C_CONNECTION);
vhci->port_status[rhport] = status; vhci_hcd->port_status[rhport] = status;
spin_unlock_irqrestore(&vhci->lock, flags); spin_unlock_irqrestore(&vhci->lock, flags);
usb_hcd_poll_rh_status(vhci_hcd_to_hcd(vhci)); usb_hcd_poll_rh_status(vhci_hcd_to_hcd(vhci_hcd));
} }
#define PORT_C_MASK \ #define PORT_C_MASK \
@ -196,17 +198,15 @@ static void rh_port_disconnect(struct vhci_device *vdev)
*/ */
static int vhci_hub_status(struct usb_hcd *hcd, char *buf) static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
{ {
struct vhci_hcd *vhci; struct vhci_hcd *vhci_hcd = hcd_to_vhci_hcd(hcd);
int retval; struct vhci *vhci = vhci_hcd->vhci;
int retval = DIV_ROUND_UP(VHCI_HC_PORTS + 1, 8);
int rhport; int rhport;
int changed = 0; int changed = 0;
unsigned long flags; unsigned long flags;
retval = DIV_ROUND_UP(VHCI_HC_PORTS + 1, 8);
memset(buf, 0, retval); memset(buf, 0, retval);
vhci = hcd_to_vhci_hcd(hcd);
spin_lock_irqsave(&vhci->lock, flags); spin_lock_irqsave(&vhci->lock, flags);
if (!HCD_HW_ACCESSIBLE(hcd)) { if (!HCD_HW_ACCESSIBLE(hcd)) {
usbip_dbg_vhci_rh("hw accessible flag not on?\n"); usbip_dbg_vhci_rh("hw accessible flag not on?\n");
@ -215,7 +215,7 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
/* check pseudo status register for each port */ /* check pseudo status register for each port */
for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) { for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) {
if ((vhci->port_status[rhport] & PORT_C_MASK)) { if ((vhci_hcd->port_status[rhport] & PORT_C_MASK)) {
/* The status of a port has been changed, */ /* The status of a port has been changed, */
usbip_dbg_vhci_rh("port %d status changed\n", rhport); usbip_dbg_vhci_rh("port %d status changed\n", rhport);
@ -252,7 +252,8 @@ static inline void hub_descriptor(struct usb_hub_descriptor *desc)
static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
u16 wIndex, char *buf, u16 wLength) u16 wIndex, char *buf, u16 wLength)
{ {
struct vhci_hcd *dum; struct vhci_hcd *vhci_hcd;
struct vhci *vhci;
int retval = 0; int retval = 0;
int rhport; int rhport;
unsigned long flags; unsigned long flags;
@ -272,13 +273,14 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
pr_err("invalid port number %d\n", wIndex); pr_err("invalid port number %d\n", wIndex);
rhport = ((__u8)(wIndex & 0x00ff)) - 1; rhport = ((__u8)(wIndex & 0x00ff)) - 1;
dum = hcd_to_vhci_hcd(hcd); vhci_hcd = hcd_to_vhci_hcd(hcd);
vhci = vhci_hcd->vhci;
spin_lock_irqsave(&dum->lock, flags); spin_lock_irqsave(&vhci->lock, flags);
/* store old status and compare now and old later */ /* store old status and compare now and old later */
if (usbip_dbg_flag_vhci_rh) { if (usbip_dbg_flag_vhci_rh) {
memcpy(prev_port_status, dum->port_status, memcpy(prev_port_status, vhci_hcd->port_status,
sizeof(prev_port_status)); sizeof(prev_port_status));
} }
@ -289,29 +291,29 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case ClearPortFeature: case ClearPortFeature:
switch (wValue) { switch (wValue) {
case USB_PORT_FEAT_SUSPEND: case USB_PORT_FEAT_SUSPEND:
if (dum->port_status[rhport] & USB_PORT_STAT_SUSPEND) { if (vhci_hcd->port_status[rhport] & USB_PORT_STAT_SUSPEND) {
/* 20msec signaling */ /* 20msec signaling */
dum->resuming = 1; vhci_hcd->resuming = 1;
dum->re_timeout = vhci_hcd->re_timeout =
jiffies + msecs_to_jiffies(20); jiffies + msecs_to_jiffies(20);
} }
break; break;
case USB_PORT_FEAT_POWER: case USB_PORT_FEAT_POWER:
usbip_dbg_vhci_rh( usbip_dbg_vhci_rh(
" ClearPortFeature: USB_PORT_FEAT_POWER\n"); " ClearPortFeature: USB_PORT_FEAT_POWER\n");
dum->port_status[rhport] = 0; vhci_hcd->port_status[rhport] = 0;
dum->resuming = 0; vhci_hcd->resuming = 0;
break; break;
case USB_PORT_FEAT_C_RESET: case USB_PORT_FEAT_C_RESET:
usbip_dbg_vhci_rh( usbip_dbg_vhci_rh(
" ClearPortFeature: USB_PORT_FEAT_C_RESET\n"); " ClearPortFeature: USB_PORT_FEAT_C_RESET\n");
switch (dum->vdev[rhport].speed) { switch (vhci_hcd->vdev[rhport].speed) {
case USB_SPEED_HIGH: case USB_SPEED_HIGH:
dum->port_status[rhport] |= vhci_hcd->port_status[rhport] |=
USB_PORT_STAT_HIGH_SPEED; USB_PORT_STAT_HIGH_SPEED;
break; break;
case USB_SPEED_LOW: case USB_SPEED_LOW:
dum->port_status[rhport] |= vhci_hcd->port_status[rhport] |=
USB_PORT_STAT_LOW_SPEED; USB_PORT_STAT_LOW_SPEED;
break; break;
default: default:
@ -321,7 +323,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
default: default:
usbip_dbg_vhci_rh(" ClearPortFeature: default %x\n", usbip_dbg_vhci_rh(" ClearPortFeature: default %x\n",
wValue); wValue);
dum->port_status[rhport] &= ~(1 << wValue); vhci_hcd->port_status[rhport] &= ~(1 << wValue);
break; break;
} }
break; break;
@ -345,36 +347,36 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
/* whoever resets or resumes must GetPortStatus to /* whoever resets or resumes must GetPortStatus to
* complete it!! * complete it!!
*/ */
if (dum->resuming && time_after(jiffies, dum->re_timeout)) { if (vhci_hcd->resuming && time_after(jiffies, vhci_hcd->re_timeout)) {
dum->port_status[rhport] |= vhci_hcd->port_status[rhport] |=
(1 << USB_PORT_FEAT_C_SUSPEND); (1 << USB_PORT_FEAT_C_SUSPEND);
dum->port_status[rhport] &= vhci_hcd->port_status[rhport] &=
~(1 << USB_PORT_FEAT_SUSPEND); ~(1 << USB_PORT_FEAT_SUSPEND);
dum->resuming = 0; vhci_hcd->resuming = 0;
dum->re_timeout = 0; vhci_hcd->re_timeout = 0;
} }
if ((dum->port_status[rhport] & (1 << USB_PORT_FEAT_RESET)) != if ((vhci_hcd->port_status[rhport] & (1 << USB_PORT_FEAT_RESET)) !=
0 && time_after(jiffies, dum->re_timeout)) { 0 && time_after(jiffies, vhci_hcd->re_timeout)) {
dum->port_status[rhport] |= vhci_hcd->port_status[rhport] |=
(1 << USB_PORT_FEAT_C_RESET); (1 << USB_PORT_FEAT_C_RESET);
dum->port_status[rhport] &= vhci_hcd->port_status[rhport] &=
~(1 << USB_PORT_FEAT_RESET); ~(1 << USB_PORT_FEAT_RESET);
dum->re_timeout = 0; vhci_hcd->re_timeout = 0;
if (dum->vdev[rhport].ud.status == if (vhci_hcd->vdev[rhport].ud.status ==
VDEV_ST_NOTASSIGNED) { VDEV_ST_NOTASSIGNED) {
usbip_dbg_vhci_rh( usbip_dbg_vhci_rh(
" enable rhport %d (status %u)\n", " enable rhport %d (status %u)\n",
rhport, rhport,
dum->vdev[rhport].ud.status); vhci_hcd->vdev[rhport].ud.status);
dum->port_status[rhport] |= vhci_hcd->port_status[rhport] |=
USB_PORT_STAT_ENABLE; USB_PORT_STAT_ENABLE;
} }
} }
((__le16 *) buf)[0] = cpu_to_le16(dum->port_status[rhport]); ((__le16 *) buf)[0] = cpu_to_le16(vhci_hcd->port_status[rhport]);
((__le16 *) buf)[1] = ((__le16 *) buf)[1] =
cpu_to_le16(dum->port_status[rhport] >> 16); cpu_to_le16(vhci_hcd->port_status[rhport] >> 16);
usbip_dbg_vhci_rh(" GetPortStatus bye %x %x\n", ((u16 *)buf)[0], usbip_dbg_vhci_rh(" GetPortStatus bye %x %x\n", ((u16 *)buf)[0],
((u16 *)buf)[1]); ((u16 *)buf)[1]);
@ -393,21 +395,21 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
usbip_dbg_vhci_rh( usbip_dbg_vhci_rh(
" SetPortFeature: USB_PORT_FEAT_RESET\n"); " SetPortFeature: USB_PORT_FEAT_RESET\n");
/* if it's already running, disconnect first */ /* if it's already running, disconnect first */
if (dum->port_status[rhport] & USB_PORT_STAT_ENABLE) { if (vhci_hcd->port_status[rhport] & USB_PORT_STAT_ENABLE) {
dum->port_status[rhport] &= vhci_hcd->port_status[rhport] &=
~(USB_PORT_STAT_ENABLE | ~(USB_PORT_STAT_ENABLE |
USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_LOW_SPEED |
USB_PORT_STAT_HIGH_SPEED); USB_PORT_STAT_HIGH_SPEED);
/* FIXME test that code path! */ /* FIXME test that code path! */
} }
/* 50msec reset signaling */ /* 50msec reset signaling */
dum->re_timeout = jiffies + msecs_to_jiffies(50); vhci_hcd->re_timeout = jiffies + msecs_to_jiffies(50);
/* FALLTHROUGH */ /* FALLTHROUGH */
default: default:
usbip_dbg_vhci_rh(" SetPortFeature: default %d\n", usbip_dbg_vhci_rh(" SetPortFeature: default %d\n",
wValue); wValue);
dum->port_status[rhport] |= (1 << wValue); vhci_hcd->port_status[rhport] |= (1 << wValue);
break; break;
} }
break; break;
@ -424,12 +426,12 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
/* Only dump valid port status */ /* Only dump valid port status */
if (rhport >= 0) { if (rhport >= 0) {
dump_port_status_diff(prev_port_status[rhport], dump_port_status_diff(prev_port_status[rhport],
dum->port_status[rhport]); vhci_hcd->port_status[rhport]);
} }
} }
usbip_dbg_vhci_rh(" bye\n"); usbip_dbg_vhci_rh(" bye\n");
spin_unlock_irqrestore(&dum->lock, flags); spin_unlock_irqrestore(&vhci->lock, flags);
return retval; return retval;
} }
@ -437,14 +439,14 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
static void vhci_tx_urb(struct urb *urb, struct vhci_device *vdev) static void vhci_tx_urb(struct urb *urb, struct vhci_device *vdev)
{ {
struct vhci_priv *priv; struct vhci_priv *priv;
struct vhci_hcd *vhci; struct vhci_hcd *vhci_hcd;
unsigned long flags; unsigned long flags;
if (!vdev) { if (!vdev) {
pr_err("could not get virtual device"); pr_err("could not get virtual device");
return; return;
} }
vhci = vdev_to_vhci_hcd(vdev); vhci_hcd = vdev_to_vhci_hcd(vdev);
priv = kzalloc(sizeof(struct vhci_priv), GFP_ATOMIC); priv = kzalloc(sizeof(struct vhci_priv), GFP_ATOMIC);
if (!priv) { if (!priv) {
@ -454,7 +456,7 @@ static void vhci_tx_urb(struct urb *urb, struct vhci_device *vdev)
spin_lock_irqsave(&vdev->priv_lock, flags); spin_lock_irqsave(&vdev->priv_lock, flags);
priv->seqnum = atomic_inc_return(&vhci->seqnum); priv->seqnum = atomic_inc_return(&vhci_hcd->seqnum);
if (priv->seqnum == 0xffff) if (priv->seqnum == 0xffff)
dev_info(&urb->dev->dev, "seqnum max\n"); dev_info(&urb->dev->dev, "seqnum max\n");
@ -472,7 +474,8 @@ static void vhci_tx_urb(struct urb *urb, struct vhci_device *vdev)
static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
gfp_t mem_flags) gfp_t mem_flags)
{ {
struct vhci_hcd *vhci = hcd_to_vhci_hcd(hcd); struct vhci_hcd *vhci_hcd = hcd_to_vhci_hcd(hcd);
struct vhci *vhci = vhci_hcd->vhci;
struct device *dev = &urb->dev->dev; struct device *dev = &urb->dev->dev;
u8 portnum = urb->dev->portnum; u8 portnum = urb->dev->portnum;
int ret = 0; int ret = 0;
@ -486,7 +489,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
pr_err("invalid port number %d\n", portnum); pr_err("invalid port number %d\n", portnum);
return -ENODEV; return -ENODEV;
} }
vdev = &vhci->vdev[portnum-1]; vdev = &vhci_hcd->vdev[portnum-1];
/* patch to usb_sg_init() is in 2.5.60 */ /* patch to usb_sg_init() is in 2.5.60 */
BUG_ON(!urb->transfer_buffer && urb->transfer_buffer_length); BUG_ON(!urb->transfer_buffer && urb->transfer_buffer_length);
@ -639,7 +642,8 @@ no_need_unlink:
*/ */
static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
{ {
struct vhci_hcd *vhci = hcd_to_vhci_hcd(hcd); struct vhci_hcd *vhci_hcd = hcd_to_vhci_hcd(hcd);
struct vhci *vhci = vhci_hcd->vhci;
struct vhci_priv *priv; struct vhci_priv *priv;
struct vhci_device *vdev; struct vhci_device *vdev;
unsigned long flags; unsigned long flags;
@ -690,7 +694,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
usb_hcd_unlink_urb_from_ep(hcd, urb); usb_hcd_unlink_urb_from_ep(hcd, urb);
spin_unlock_irqrestore(&vhci->lock, flags); spin_unlock_irqrestore(&vhci->lock, flags);
usb_hcd_giveback_urb(vhci_hcd_to_hcd(vhci), urb, urb->status); usb_hcd_giveback_urb(hcd, urb, urb->status);
spin_lock_irqsave(&vhci->lock, flags); spin_lock_irqsave(&vhci->lock, flags);
} else { } else {
@ -708,7 +712,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
return -ENOMEM; return -ENOMEM;
} }
unlink->seqnum = atomic_inc_return(&vhci->seqnum); unlink->seqnum = atomic_inc_return(&vhci_hcd->seqnum);
if (unlink->seqnum == 0xffff) if (unlink->seqnum == 0xffff)
pr_info("seqnum max\n"); pr_info("seqnum max\n");
@ -732,8 +736,9 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
static void vhci_device_unlink_cleanup(struct vhci_device *vdev) static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
{ {
struct vhci_hcd *vhci = vdev_to_vhci_hcd(vdev); struct vhci_hcd *vhci_hcd = vdev_to_vhci_hcd(vdev);
struct usb_hcd *hcd = vhci_hcd_to_hcd(vhci); struct usb_hcd *hcd = vhci_hcd_to_hcd(vhci_hcd);
struct vhci *vhci = vhci_hcd->vhci;
struct vhci_unlink *unlink, *tmp; struct vhci_unlink *unlink, *tmp;
unsigned long flags; unsigned long flags;
@ -917,29 +922,47 @@ static int hcd_name_to_id(const char *name)
return val; return val;
} }
static int vhci_setup(struct usb_hcd *hcd)
{
struct vhci *vhci = *((void **)dev_get_platdata(hcd->self.controller));
hcd->self.sg_tablesize = ~0;
vhci->vhci_hcd_hs = hcd_to_vhci_hcd(hcd);
vhci->vhci_hcd_hs->vhci = vhci;
hcd->speed = HCD_USB2;
hcd->self.root_hub->speed = USB_SPEED_HIGH;
return 0;
}
static int vhci_start(struct usb_hcd *hcd) static int vhci_start(struct usb_hcd *hcd)
{ {
struct vhci_hcd *vhci = hcd_to_vhci_hcd(hcd); struct vhci_hcd *vhci_hcd = hcd_to_vhci_hcd(hcd);
int id, rhport; int id, rhport;
int err = 0; int err;
usbip_dbg_vhci_hc("enter vhci_start\n"); usbip_dbg_vhci_hc("enter vhci_start\n");
spin_lock_init(&vhci_hcd->vhci->lock);
/* initialize private data of usb_hcd */ /* initialize private data of usb_hcd */
for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) { for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) {
struct vhci_device *vdev = &vhci->vdev[rhport]; struct vhci_device *vdev = &vhci_hcd->vdev[rhport];
vhci_device_init(vdev); vhci_device_init(vdev);
vdev->rhport = rhport; vdev->rhport = rhport;
} }
atomic_set(&vhci->seqnum, 0); atomic_set(&vhci_hcd->seqnum, 0);
spin_lock_init(&vhci->lock);
hcd->power_budget = 0; /* no limit */ hcd->power_budget = 0; /* no limit */
hcd->uses_new_polling = 1; hcd->uses_new_polling = 1;
#ifdef CONFIG_USB_OTG
hcd->self.otg_port = 1;
#endif
id = hcd_name_to_id(hcd_name(hcd)); id = hcd_name_to_id(hcd_name(hcd));
if (id < 0) { if (id < 0) {
pr_err("invalid vhci name %s\n", hcd_name(hcd)); pr_err("invalid vhci name %s\n", hcd_name(hcd));
@ -967,7 +990,7 @@ static int vhci_start(struct usb_hcd *hcd)
static void vhci_stop(struct usb_hcd *hcd) static void vhci_stop(struct usb_hcd *hcd)
{ {
struct vhci_hcd *vhci = hcd_to_vhci_hcd(hcd); struct vhci_hcd *vhci_hcd = hcd_to_vhci_hcd(hcd);
int id, rhport; int id, rhport;
usbip_dbg_vhci_hc("stop VHCI controller\n"); usbip_dbg_vhci_hc("stop VHCI controller\n");
@ -981,7 +1004,7 @@ static void vhci_stop(struct usb_hcd *hcd)
/* 2. shutdown all the ports of vhci_hcd */ /* 2. shutdown all the ports of vhci_hcd */
for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) { for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) {
struct vhci_device *vdev = &vhci->vdev[rhport]; struct vhci_device *vdev = &vhci_hcd->vdev[rhport];
usbip_event_add(&vdev->ud, VDEV_EVENT_REMOVED); usbip_event_add(&vdev->ud, VDEV_EVENT_REMOVED);
usbip_stop_eh(&vdev->ud); usbip_stop_eh(&vdev->ud);
@ -999,7 +1022,7 @@ static int vhci_get_frame_number(struct usb_hcd *hcd)
/* FIXME: suspend/resume */ /* FIXME: suspend/resume */
static int vhci_bus_suspend(struct usb_hcd *hcd) static int vhci_bus_suspend(struct usb_hcd *hcd)
{ {
struct vhci_hcd *vhci = hcd_to_vhci_hcd(hcd); struct vhci *vhci = *((void **)dev_get_platdata(hcd->self.controller));
unsigned long flags; unsigned long flags;
dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__); dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
@ -1013,7 +1036,7 @@ static int vhci_bus_suspend(struct usb_hcd *hcd)
static int vhci_bus_resume(struct usb_hcd *hcd) static int vhci_bus_resume(struct usb_hcd *hcd)
{ {
struct vhci_hcd *vhci = hcd_to_vhci_hcd(hcd); struct vhci *vhci = *((void **)dev_get_platdata(hcd->self.controller));
int rc = 0; int rc = 0;
unsigned long flags; unsigned long flags;
@ -1042,6 +1065,7 @@ static struct hc_driver vhci_hc_driver = {
.flags = HCD_USB2, .flags = HCD_USB2,
.reset = vhci_setup,
.start = vhci_start, .start = vhci_start,
.stop = vhci_stop, .stop = vhci_stop,
@ -1058,7 +1082,8 @@ static struct hc_driver vhci_hc_driver = {
static int vhci_hcd_probe(struct platform_device *pdev) static int vhci_hcd_probe(struct platform_device *pdev)
{ {
struct usb_hcd *hcd; struct vhci *vhci;
struct usb_hcd *hcd_hs;
int ret; int ret;
usbip_dbg_vhci_hc("name %s id %d\n", pdev->name, pdev->id); usbip_dbg_vhci_hc("name %s id %d\n", pdev->name, pdev->id);
@ -1067,43 +1092,45 @@ static int vhci_hcd_probe(struct platform_device *pdev)
* Allocate and initialize hcd. * Allocate and initialize hcd.
* Our private data is also allocated automatically. * Our private data is also allocated automatically.
*/ */
hcd = usb_create_hcd(&vhci_hc_driver, &pdev->dev, dev_name(&pdev->dev)); hcd_hs = usb_create_hcd(&vhci_hc_driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) { if (!hcd_hs) {
pr_err("create hcd failed\n"); pr_err("create hcd failed\n");
return -ENOMEM; return -ENOMEM;
} }
hcd->has_tt = 1; hcd_hs->has_tt = 1;
/* /*
* Finish generic HCD structure initialization and register. * Finish generic HCD structure initialization and register.
* Call the driver's reset() and start() routines. * Call the driver's reset() and start() routines.
*/ */
ret = usb_add_hcd(hcd, 0, 0); ret = usb_add_hcd(hcd_hs, 0, 0);
if (ret != 0) { if (ret != 0) {
pr_err("usb_add_hcd failed %d\n", ret); pr_err("usb_add_hcd hs failed %d\n", ret);
usb_put_hcd(hcd); goto put_usb2_hcd;
return ret;
} }
usbip_dbg_vhci_hc("bye\n"); usbip_dbg_vhci_hc("bye\n");
return 0; return 0;
put_usb2_hcd:
usb_put_hcd(hcd_hs);
vhci->vhci_hcd_hs = NULL;
return ret;
} }
static int vhci_hcd_remove(struct platform_device *pdev) static int vhci_hcd_remove(struct platform_device *pdev)
{ {
struct usb_hcd *hcd; struct vhci *vhci = *((void **)dev_get_platdata(&pdev->dev));
hcd = platform_get_drvdata(pdev);
if (!hcd)
return 0;
/* /*
* Disconnects the root hub, * Disconnects the root hub,
* then reverses the effects of usb_add_hcd(), * then reverses the effects of usb_add_hcd(),
* invoking the HCD's stop() methods. * invoking the HCD's stop() methods.
*/ */
usb_remove_hcd(hcd); usb_remove_hcd(vhci_hcd_to_hcd(vhci->vhci_hcd_hs));
usb_put_hcd(hcd); usb_put_hcd(vhci_hcd_to_hcd(vhci->vhci_hcd_hs));
vhci->vhci_hcd_hs = NULL;
return 0; return 0;
} }
@ -1114,22 +1141,27 @@ static int vhci_hcd_remove(struct platform_device *pdev)
static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state) static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state)
{ {
struct usb_hcd *hcd; struct usb_hcd *hcd;
struct vhci_hcd *vhci; struct vhci *vhci;
int rhport; int rhport = 0;
int connected = 0; int connected = 0;
int ret = 0; int ret = 0;
unsigned long flags; unsigned long flags;
dev_dbg(&pdev->dev, "%s\n", __func__);
hcd = platform_get_drvdata(pdev); hcd = platform_get_drvdata(pdev);
if (!hcd) if (!hcd)
return 0; return 0;
vhci = hcd_to_vhci_hcd(hcd);
vhci = *((void **)dev_get_platdata(hcd->self.controller));
spin_lock_irqsave(&vhci->lock, flags); spin_lock_irqsave(&vhci->lock, flags);
for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) {
if (vhci->port_status[rhport] & USB_PORT_STAT_CONNECTION) if (vhci->vhci_hcd_hs->port_status[rhport] &
USB_PORT_STAT_CONNECTION)
connected += 1; connected += 1;
}
spin_unlock_irqrestore(&vhci->lock, flags); spin_unlock_irqrestore(&vhci->lock, flags);

Просмотреть файл

@ -70,7 +70,8 @@ struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum)
static void vhci_recv_ret_submit(struct vhci_device *vdev, static void vhci_recv_ret_submit(struct vhci_device *vdev,
struct usbip_header *pdu) struct usbip_header *pdu)
{ {
struct vhci_hcd *vhci = vdev_to_vhci_hcd(vdev); struct vhci_hcd *vhci_hcd = vdev_to_vhci_hcd(vdev);
struct vhci *vhci = vhci_hcd->vhci;
struct usbip_device *ud = &vdev->ud; struct usbip_device *ud = &vdev->ud;
struct urb *urb; struct urb *urb;
unsigned long flags; unsigned long flags;
@ -82,7 +83,7 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,
if (!urb) { if (!urb) {
pr_err("cannot find a urb of seqnum %u\n", pdu->base.seqnum); pr_err("cannot find a urb of seqnum %u\n", pdu->base.seqnum);
pr_info("max seqnum %d\n", pr_info("max seqnum %d\n",
atomic_read(&vhci->seqnum)); atomic_read(&vhci_hcd->seqnum));
usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
return; return;
} }
@ -107,10 +108,10 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,
usbip_dbg_vhci_rx("now giveback urb %p\n", urb); usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
spin_lock_irqsave(&vhci->lock, flags); spin_lock_irqsave(&vhci->lock, flags);
usb_hcd_unlink_urb_from_ep(vhci_hcd_to_hcd(vhci), urb); usb_hcd_unlink_urb_from_ep(vhci_hcd_to_hcd(vhci_hcd), urb);
spin_unlock_irqrestore(&vhci->lock, flags); spin_unlock_irqrestore(&vhci->lock, flags);
usb_hcd_giveback_urb(vhci_hcd_to_hcd(vhci), urb, urb->status); usb_hcd_giveback_urb(vhci_hcd_to_hcd(vhci_hcd), urb, urb->status);
usbip_dbg_vhci_rx("Leave\n"); usbip_dbg_vhci_rx("Leave\n");
} }
@ -143,7 +144,8 @@ static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev,
static void vhci_recv_ret_unlink(struct vhci_device *vdev, static void vhci_recv_ret_unlink(struct vhci_device *vdev,
struct usbip_header *pdu) struct usbip_header *pdu)
{ {
struct vhci_hcd *vhci = vdev_to_vhci_hcd(vdev); struct vhci_hcd *vhci_hcd = vdev_to_vhci_hcd(vdev);
struct vhci *vhci = vhci_hcd->vhci;
struct vhci_unlink *unlink; struct vhci_unlink *unlink;
struct urb *urb; struct urb *urb;
unsigned long flags; unsigned long flags;
@ -177,10 +179,10 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
pr_info("urb->status %d\n", urb->status); pr_info("urb->status %d\n", urb->status);
spin_lock_irqsave(&vhci->lock, flags); spin_lock_irqsave(&vhci->lock, flags);
usb_hcd_unlink_urb_from_ep(vhci_hcd_to_hcd(vhci), urb); usb_hcd_unlink_urb_from_ep(vhci_hcd_to_hcd(vhci_hcd), urb);
spin_unlock_irqrestore(&vhci->lock, flags); spin_unlock_irqrestore(&vhci->lock, flags);
usb_hcd_giveback_urb(vhci_hcd_to_hcd(vhci), urb, urb->status); usb_hcd_giveback_urb(vhci_hcd_to_hcd(vhci_hcd), urb, urb->status);
} }
kfree(unlink); kfree(unlink);

Просмотреть файл

@ -33,9 +33,11 @@
static ssize_t status_show_vhci(int pdev_nr, char *out) static ssize_t status_show_vhci(int pdev_nr, char *out)
{ {
struct platform_device *pdev = vhcis[pdev_nr].pdev; struct platform_device *pdev = vhcis[pdev_nr].pdev;
struct vhci_hcd *vhci; struct vhci *vhci;
struct usb_hcd *hcd;
struct vhci_hcd *vhci_hcd;
char *s = out; char *s = out;
int i = 0; int i;
unsigned long flags; unsigned long flags;
if (!pdev || !out) { if (!pdev || !out) {
@ -43,7 +45,9 @@ static ssize_t status_show_vhci(int pdev_nr, char *out)
return 0; return 0;
} }
vhci = hcd_to_vhci_hcd(platform_get_drvdata(pdev)); hcd = platform_get_drvdata(pdev);
vhci_hcd = hcd_to_vhci_hcd(hcd);
vhci = vhci_hcd->vhci;
spin_lock_irqsave(&vhci->lock, flags); spin_lock_irqsave(&vhci->lock, flags);
@ -58,7 +62,7 @@ static ssize_t status_show_vhci(int pdev_nr, char *out)
* port number and its peer IP address. * port number and its peer IP address.
*/ */
for (i = 0; i < VHCI_HC_PORTS; i++) { for (i = 0; i < VHCI_HC_PORTS; i++) {
struct vhci_device *vdev = &vhci->vdev[i]; struct vhci_device *vdev = &vhci_hcd->vdev[i];
spin_lock(&vdev->ud.lock); spin_lock(&vdev->ud.lock);
out += sprintf(out, "%04u %03u ", out += sprintf(out, "%04u %03u ",
@ -147,9 +151,10 @@ static ssize_t nports_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR_RO(nports); static DEVICE_ATTR_RO(nports);
/* Sysfs entry to shutdown a virtual connection */ /* Sysfs entry to shutdown a virtual connection */
static int vhci_port_disconnect(struct vhci_hcd *vhci, __u32 rhport) static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport)
{ {
struct vhci_device *vdev = &vhci->vdev[rhport]; struct vhci_device *vdev = &vhci_hcd->vdev[rhport];
struct vhci *vhci = vhci_hcd->vhci;
unsigned long flags; unsigned long flags;
usbip_dbg_vhci_sysfs("enter\n"); usbip_dbg_vhci_sysfs("enter\n");
@ -262,8 +267,9 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
int sockfd = 0; int sockfd = 0;
__u32 port = 0, pdev_nr = 0, rhport = 0, devid = 0, speed = 0; __u32 port = 0, pdev_nr = 0, rhport = 0, devid = 0, speed = 0;
struct usb_hcd *hcd; struct usb_hcd *hcd;
struct vhci_hcd *vhci; struct vhci_hcd *vhci_hcd;
struct vhci_device *vdev; struct vhci_device *vdev;
struct vhci *vhci;
int err; int err;
unsigned long flags; unsigned long flags;
@ -292,8 +298,10 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
dev_err(dev, "port %d is not ready\n", port); dev_err(dev, "port %d is not ready\n", port);
return -EAGAIN; return -EAGAIN;
} }
vhci = hcd_to_vhci_hcd(hcd);
vdev = &vhci->vdev[rhport]; vhci_hcd = hcd_to_vhci_hcd(hcd);
vhci = vhci_hcd->vhci;
vdev = &vhci_hcd->vdev[rhport];
/* Extract socket from fd. */ /* Extract socket from fd. */
socket = sockfd_lookup(sockfd, &err); socket = sockfd_lookup(sockfd, &err);