Skip to content

Commit

Permalink
staging: usbip: replace the interrupt safe spinlocks with common ones.
Browse files Browse the repository at this point in the history
On the client side, we have a virtual hcd driver, there actually no
hardware interrupts, so we do not need worry about race conditions
caused by irq with spinlock held. Turning off irq is not good for system
performance after all. Just replace them with a non interrupt safe
version.

Signed-off-by: Harvey Yang <harvey.huawei.yang@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Harvey Yang authored and Greg Kroah-Hartman committed Jan 22, 2013
1 parent dcf1477 commit 50b66b5
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 58 deletions.
76 changes: 32 additions & 44 deletions drivers/staging/usbip/vhci_hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,9 @@ static void dump_port_status_diff(u32 prev_status, u32 new_status)

void rh_port_connect(int rhport, enum usb_device_speed speed)
{
unsigned long flags;

usbip_dbg_vhci_rh("rh_port_connect %d\n", rhport);

spin_lock_irqsave(&the_controller->lock, flags);
spin_lock(&the_controller->lock);

the_controller->port_status[rhport] |= USB_PORT_STAT_CONNECTION
| (1 << USB_PORT_FEAT_C_CONNECTION);
Expand All @@ -141,24 +139,22 @@ void rh_port_connect(int rhport, enum usb_device_speed speed)
break;
}

spin_unlock_irqrestore(&the_controller->lock, flags);
spin_unlock(&the_controller->lock);

usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
}

static void rh_port_disconnect(int rhport)
{
unsigned long flags;

usbip_dbg_vhci_rh("rh_port_disconnect %d\n", rhport);

spin_lock_irqsave(&the_controller->lock, flags);
spin_lock(&the_controller->lock);

the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION;
the_controller->port_status[rhport] |=
(1 << USB_PORT_FEAT_C_CONNECTION);

spin_unlock_irqrestore(&the_controller->lock, flags);
spin_unlock(&the_controller->lock);
usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
}

Expand All @@ -183,7 +179,6 @@ static void rh_port_disconnect(int rhport)
static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
{
struct vhci_hcd *vhci;
unsigned long flags;
int retval;
int rhport;
int changed = 0;
Expand All @@ -193,7 +188,7 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf)

vhci = hcd_to_vhci(hcd);

spin_lock_irqsave(&vhci->lock, flags);
spin_lock(&vhci->lock);
if (!HCD_HW_ACCESSIBLE(hcd)) {
usbip_dbg_vhci_rh("hw accessible flag not on?\n");
goto done;
Expand All @@ -216,7 +211,7 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
usb_hcd_resume_root_hub(hcd);

done:
spin_unlock_irqrestore(&vhci->lock, flags);
spin_unlock(&vhci->lock);
return changed ? retval : 0;
}

Expand All @@ -237,7 +232,6 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
{
struct vhci_hcd *dum;
int retval = 0;
unsigned long flags;
int rhport;

u32 prev_port_status[VHCI_NPORTS];
Expand All @@ -257,7 +251,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,

dum = hcd_to_vhci(hcd);

spin_lock_irqsave(&dum->lock, flags);
spin_lock(&dum->lock);

/* store old status and compare now and old later */
if (usbip_dbg_flag_vhci_rh) {
Expand Down Expand Up @@ -410,7 +404,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
}
usbip_dbg_vhci_rh(" bye\n");

spin_unlock_irqrestore(&dum->lock, flags);
spin_unlock(&dum->lock);

return retval;
}
Expand All @@ -433,7 +427,6 @@ static void vhci_tx_urb(struct urb *urb)
{
struct vhci_device *vdev = get_vdev(urb->dev);
struct vhci_priv *priv;
unsigned long flag;

if (!vdev) {
pr_err("could not get virtual device");
Expand All @@ -442,11 +435,11 @@ static void vhci_tx_urb(struct urb *urb)

priv = kzalloc(sizeof(struct vhci_priv), GFP_ATOMIC);

spin_lock_irqsave(&vdev->priv_lock, flag);
spin_lock(&vdev->priv_lock);

if (!priv) {
dev_err(&urb->dev->dev, "malloc vhci_priv\n");
spin_unlock_irqrestore(&vdev->priv_lock, flag);
spin_unlock(&vdev->priv_lock);
usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC);
return;
}
Expand All @@ -463,15 +456,14 @@ static void vhci_tx_urb(struct urb *urb)
list_add_tail(&priv->list, &vdev->priv_tx);

wake_up(&vdev->waitq_tx);
spin_unlock_irqrestore(&vdev->priv_lock, flag);
spin_unlock(&vdev->priv_lock);
}

static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
gfp_t mem_flags)
{
struct device *dev = &urb->dev->dev;
int ret = 0;
unsigned long flags;
struct vhci_device *vdev;

usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n",
Expand All @@ -480,11 +472,11 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
/* patch to usb_sg_init() is in 2.5.60 */
BUG_ON(!urb->transfer_buffer && urb->transfer_buffer_length);

spin_lock_irqsave(&the_controller->lock, flags);
spin_lock(&the_controller->lock);

if (urb->status != -EINPROGRESS) {
dev_err(dev, "URB already unlinked!, status %d\n", urb->status);
spin_unlock_irqrestore(&the_controller->lock, flags);
spin_unlock(&the_controller->lock);
return urb->status;
}

Expand All @@ -496,7 +488,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
vdev->ud.status == VDEV_ST_ERROR) {
dev_err(dev, "enqueue for inactive port %d\n", vdev->rhport);
spin_unlock(&vdev->ud.lock);
spin_unlock_irqrestore(&the_controller->lock, flags);
spin_unlock(&the_controller->lock);
return -ENODEV;
}
spin_unlock(&vdev->ud.lock);
Expand Down Expand Up @@ -571,14 +563,14 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,

out:
vhci_tx_urb(urb);
spin_unlock_irqrestore(&the_controller->lock, flags);
spin_unlock(&the_controller->lock);

return 0;

no_need_xmit:
usb_hcd_unlink_urb_from_ep(hcd, urb);
no_need_unlink:
spin_unlock_irqrestore(&the_controller->lock, flags);
spin_unlock(&the_controller->lock);
usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
return ret;
}
Expand Down Expand Up @@ -631,27 +623,26 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
*/
static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
{
unsigned long flags;
struct vhci_priv *priv;
struct vhci_device *vdev;

pr_info("dequeue a urb %p\n", urb);

spin_lock_irqsave(&the_controller->lock, flags);
spin_lock(&the_controller->lock);

priv = urb->hcpriv;
if (!priv) {
/* URB was never linked! or will be soon given back by
* vhci_rx. */
spin_unlock_irqrestore(&the_controller->lock, flags);
spin_unlock(&the_controller->lock);
return 0;
}

{
int ret = 0;
ret = usb_hcd_check_unlink_urb(hcd, urb, status);
if (ret) {
spin_unlock_irqrestore(&the_controller->lock, flags);
spin_unlock(&the_controller->lock);
return ret;
}
}
Expand All @@ -661,16 +652,14 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)

if (!vdev->ud.tcp_socket) {
/* tcp connection is closed */
unsigned long flags2;

spin_lock_irqsave(&vdev->priv_lock, flags2);
spin_lock(&vdev->priv_lock);

pr_info("device %p seems to be disconnected\n", vdev);
list_del(&priv->list);
kfree(priv);
urb->hcpriv = NULL;

spin_unlock_irqrestore(&vdev->priv_lock, flags2);
spin_unlock(&vdev->priv_lock);

/*
* If tcp connection is alive, we have sent CMD_UNLINK.
Expand All @@ -681,24 +670,23 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)

usb_hcd_unlink_urb_from_ep(hcd, urb);

spin_unlock_irqrestore(&the_controller->lock, flags);
spin_unlock(&the_controller->lock);
usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
urb->status);
spin_lock_irqsave(&the_controller->lock, flags);
spin_lock(&the_controller->lock);

} else {
/* tcp connection is alive */
unsigned long flags2;
struct vhci_unlink *unlink;

spin_lock_irqsave(&vdev->priv_lock, flags2);
spin_lock(&vdev->priv_lock);

/* setup CMD_UNLINK pdu */
unlink = kzalloc(sizeof(struct vhci_unlink), GFP_ATOMIC);
if (!unlink) {
pr_err("malloc vhci_unlink\n");
spin_unlock_irqrestore(&vdev->priv_lock, flags2);
spin_unlock_irqrestore(&the_controller->lock, flags);
spin_unlock(&vdev->priv_lock);
spin_unlock(&the_controller->lock);
usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC);
return -ENOMEM;
}
Expand All @@ -716,10 +704,10 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
list_add_tail(&unlink->list, &vdev->unlink_tx);
wake_up(&vdev->waitq_tx);

spin_unlock_irqrestore(&vdev->priv_lock, flags2);
spin_unlock(&vdev->priv_lock);
}

spin_unlock_irqrestore(&the_controller->lock, flags);
spin_unlock(&the_controller->lock);

usbip_dbg_vhci_hc("leave\n");
return 0;
Expand Down Expand Up @@ -957,9 +945,9 @@ static int vhci_bus_suspend(struct usb_hcd *hcd)

dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);

spin_lock_irq(&vhci->lock);
spin_lock(&vhci->lock);
hcd->state = HC_STATE_SUSPENDED;
spin_unlock_irq(&vhci->lock);
spin_unlock(&vhci->lock);

return 0;
}
Expand All @@ -971,13 +959,13 @@ static int vhci_bus_resume(struct usb_hcd *hcd)

dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);

spin_lock_irq(&vhci->lock);
spin_lock(&vhci->lock);
if (!HCD_HW_ACCESSIBLE(hcd)) {
rc = -ESHUTDOWN;
} else {
hcd->state = HC_STATE_RUNNING;
}
spin_unlock_irq(&vhci->lock);
spin_unlock(&vhci->lock);

return rc;
}
Expand Down
10 changes: 4 additions & 6 deletions drivers/staging/usbip/vhci_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,
{
struct usbip_device *ud = &vdev->ud;
struct urb *urb;
unsigned long flags;

spin_lock(&vdev->priv_lock);
urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum);
Expand Down Expand Up @@ -101,9 +100,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,

usbip_dbg_vhci_rx("now giveback urb %p\n", urb);

spin_lock_irqsave(&the_controller->lock, flags);
spin_lock(&the_controller->lock);
usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
spin_unlock_irqrestore(&the_controller->lock, flags);
spin_unlock(&the_controller->lock);

usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);

Expand Down Expand Up @@ -141,7 +140,6 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
{
struct vhci_unlink *unlink;
struct urb *urb;
unsigned long flags;

usbip_dump_header(pdu);

Expand Down Expand Up @@ -171,9 +169,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
urb->status = pdu->u.ret_unlink.status;
pr_info("urb->status %d\n", urb->status);

spin_lock_irqsave(&the_controller->lock, flags);
spin_lock(&the_controller->lock);
usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
spin_unlock_irqrestore(&the_controller->lock, flags);
spin_unlock(&the_controller->lock);

usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
urb->status);
Expand Down
14 changes: 6 additions & 8 deletions drivers/staging/usbip/vhci_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,17 @@ static void setup_cmd_submit_pdu(struct usbip_header *pdup, struct urb *urb)

static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev)
{
unsigned long flags;
struct vhci_priv *priv, *tmp;

spin_lock_irqsave(&vdev->priv_lock, flags);
spin_lock(&vdev->priv_lock);

list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) {
list_move_tail(&priv->list, &vdev->priv_rx);
spin_unlock_irqrestore(&vdev->priv_lock, flags);
spin_unlock(&vdev->priv_lock);
return priv;
}

spin_unlock_irqrestore(&vdev->priv_lock, flags);
spin_unlock(&vdev->priv_lock);

return NULL;
}
Expand Down Expand Up @@ -136,18 +135,17 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev)

static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev)
{
unsigned long flags;
struct vhci_unlink *unlink, *tmp;

spin_lock_irqsave(&vdev->priv_lock, flags);
spin_lock(&vdev->priv_lock);

list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
list_move_tail(&unlink->list, &vdev->unlink_rx);
spin_unlock_irqrestore(&vdev->priv_lock, flags);
spin_unlock(&vdev->priv_lock);
return unlink;
}

spin_unlock_irqrestore(&vdev->priv_lock, flags);
spin_unlock(&vdev->priv_lock);

return NULL;
}
Expand Down

0 comments on commit 50b66b5

Please sign in to comment.