Commit 21619792 authored by Andrew Goodbody's avatar Andrew Goodbody Committed by Greg Kroah-Hartman

usb: usbip: Fix possible deadlocks reported by lockdep

Change spin_lock calls to spin_lock_irqsave to prevent
attmpted recursive lock taking in interrupt context.

This patch fixes Bug 109351
  https://bugzilla.kernel.org/show_bug.cgi?id=109351Signed-off-by: default avatarAndrew Goodbody <andrew.goodbody@cambrionix.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 46e3cafb
...@@ -117,11 +117,12 @@ EXPORT_SYMBOL_GPL(usbip_event_add); ...@@ -117,11 +117,12 @@ EXPORT_SYMBOL_GPL(usbip_event_add);
int usbip_event_happened(struct usbip_device *ud) int usbip_event_happened(struct usbip_device *ud)
{ {
int happened = 0; int happened = 0;
unsigned long flags;
spin_lock(&ud->lock); spin_lock_irqsave(&ud->lock, flags);
if (ud->event != 0) if (ud->event != 0)
happened = 1; happened = 1;
spin_unlock(&ud->lock); spin_unlock_irqrestore(&ud->lock, flags);
return happened; return happened;
} }
......
...@@ -121,9 +121,11 @@ static void dump_port_status_diff(u32 prev_status, u32 new_status) ...@@ -121,9 +121,11 @@ static void dump_port_status_diff(u32 prev_status, u32 new_status)
void rh_port_connect(int rhport, enum usb_device_speed speed) void rh_port_connect(int rhport, enum usb_device_speed speed)
{ {
unsigned long flags;
usbip_dbg_vhci_rh("rh_port_connect %d\n", rhport); usbip_dbg_vhci_rh("rh_port_connect %d\n", rhport);
spin_lock(&the_controller->lock); spin_lock_irqsave(&the_controller->lock, flags);
the_controller->port_status[rhport] |= USB_PORT_STAT_CONNECTION the_controller->port_status[rhport] |= USB_PORT_STAT_CONNECTION
| (1 << USB_PORT_FEAT_C_CONNECTION); | (1 << USB_PORT_FEAT_C_CONNECTION);
...@@ -139,22 +141,24 @@ void rh_port_connect(int rhport, enum usb_device_speed speed) ...@@ -139,22 +141,24 @@ void rh_port_connect(int rhport, enum usb_device_speed speed)
break; break;
} }
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
usb_hcd_poll_rh_status(vhci_to_hcd(the_controller)); usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
} }
static void rh_port_disconnect(int rhport) static void rh_port_disconnect(int rhport)
{ {
unsigned long flags;
usbip_dbg_vhci_rh("rh_port_disconnect %d\n", rhport); usbip_dbg_vhci_rh("rh_port_disconnect %d\n", rhport);
spin_lock(&the_controller->lock); spin_lock_irqsave(&the_controller->lock, flags);
the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION; the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION;
the_controller->port_status[rhport] |= the_controller->port_status[rhport] |=
(1 << USB_PORT_FEAT_C_CONNECTION); (1 << USB_PORT_FEAT_C_CONNECTION);
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
usb_hcd_poll_rh_status(vhci_to_hcd(the_controller)); usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
} }
...@@ -182,13 +186,14 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) ...@@ -182,13 +186,14 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
int retval; int retval;
int rhport; int rhport;
int changed = 0; int changed = 0;
unsigned long flags;
retval = DIV_ROUND_UP(VHCI_NPORTS + 1, 8); retval = DIV_ROUND_UP(VHCI_NPORTS + 1, 8);
memset(buf, 0, retval); memset(buf, 0, retval);
vhci = hcd_to_vhci(hcd); vhci = hcd_to_vhci(hcd);
spin_lock(&vhci->lock); 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");
goto done; goto done;
...@@ -209,7 +214,7 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) ...@@ -209,7 +214,7 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
usb_hcd_resume_root_hub(hcd); usb_hcd_resume_root_hub(hcd);
done: done:
spin_unlock(&vhci->lock); spin_unlock_irqrestore(&vhci->lock, flags);
return changed ? retval : 0; return changed ? retval : 0;
} }
...@@ -231,6 +236,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -231,6 +236,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
struct vhci_hcd *dum; struct vhci_hcd *dum;
int retval = 0; int retval = 0;
int rhport; int rhport;
unsigned long flags;
u32 prev_port_status[VHCI_NPORTS]; u32 prev_port_status[VHCI_NPORTS];
...@@ -249,7 +255,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -249,7 +255,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
dum = hcd_to_vhci(hcd); dum = hcd_to_vhci(hcd);
spin_lock(&dum->lock); spin_lock_irqsave(&dum->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) {
...@@ -403,7 +409,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -403,7 +409,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
} }
usbip_dbg_vhci_rh(" bye\n"); usbip_dbg_vhci_rh(" bye\n");
spin_unlock(&dum->lock); spin_unlock_irqrestore(&dum->lock, flags);
return retval; return retval;
} }
...@@ -426,6 +432,7 @@ static void vhci_tx_urb(struct urb *urb) ...@@ -426,6 +432,7 @@ static void vhci_tx_urb(struct urb *urb)
{ {
struct vhci_device *vdev = get_vdev(urb->dev); struct vhci_device *vdev = get_vdev(urb->dev);
struct vhci_priv *priv; struct vhci_priv *priv;
unsigned long flags;
if (!vdev) { if (!vdev) {
pr_err("could not get virtual device"); pr_err("could not get virtual device");
...@@ -438,7 +445,7 @@ static void vhci_tx_urb(struct urb *urb) ...@@ -438,7 +445,7 @@ static void vhci_tx_urb(struct urb *urb)
return; return;
} }
spin_lock(&vdev->priv_lock); spin_lock_irqsave(&vdev->priv_lock, flags);
priv->seqnum = atomic_inc_return(&the_controller->seqnum); priv->seqnum = atomic_inc_return(&the_controller->seqnum);
if (priv->seqnum == 0xffff) if (priv->seqnum == 0xffff)
...@@ -452,7 +459,7 @@ static void vhci_tx_urb(struct urb *urb) ...@@ -452,7 +459,7 @@ static void vhci_tx_urb(struct urb *urb)
list_add_tail(&priv->list, &vdev->priv_tx); list_add_tail(&priv->list, &vdev->priv_tx);
wake_up(&vdev->waitq_tx); wake_up(&vdev->waitq_tx);
spin_unlock(&vdev->priv_lock); spin_unlock_irqrestore(&vdev->priv_lock, flags);
} }
static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
...@@ -461,6 +468,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, ...@@ -461,6 +468,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
struct device *dev = &urb->dev->dev; struct device *dev = &urb->dev->dev;
int ret = 0; int ret = 0;
struct vhci_device *vdev; struct vhci_device *vdev;
unsigned long flags;
usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n", usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n",
hcd, urb, mem_flags); hcd, urb, mem_flags);
...@@ -468,11 +476,11 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, ...@@ -468,11 +476,11 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
/* 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);
spin_lock(&the_controller->lock); spin_lock_irqsave(&the_controller->lock, flags);
if (urb->status != -EINPROGRESS) { if (urb->status != -EINPROGRESS) {
dev_err(dev, "URB already unlinked!, status %d\n", urb->status); dev_err(dev, "URB already unlinked!, status %d\n", urb->status);
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
return urb->status; return urb->status;
} }
...@@ -484,7 +492,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, ...@@ -484,7 +492,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
vdev->ud.status == VDEV_ST_ERROR) { vdev->ud.status == VDEV_ST_ERROR) {
dev_err(dev, "enqueue for inactive port %d\n", vdev->rhport); dev_err(dev, "enqueue for inactive port %d\n", vdev->rhport);
spin_unlock(&vdev->ud.lock); spin_unlock(&vdev->ud.lock);
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
return -ENODEV; return -ENODEV;
} }
spin_unlock(&vdev->ud.lock); spin_unlock(&vdev->ud.lock);
...@@ -557,14 +565,14 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, ...@@ -557,14 +565,14 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
out: out:
vhci_tx_urb(urb); vhci_tx_urb(urb);
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
return 0; return 0;
no_need_xmit: no_need_xmit:
usb_hcd_unlink_urb_from_ep(hcd, urb); usb_hcd_unlink_urb_from_ep(hcd, urb);
no_need_unlink: no_need_unlink:
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
if (!ret) if (!ret)
usb_hcd_giveback_urb(vhci_to_hcd(the_controller), usb_hcd_giveback_urb(vhci_to_hcd(the_controller),
urb, urb->status); urb, urb->status);
...@@ -621,16 +629,17 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -621,16 +629,17 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
{ {
struct vhci_priv *priv; struct vhci_priv *priv;
struct vhci_device *vdev; struct vhci_device *vdev;
unsigned long flags;
pr_info("dequeue a urb %p\n", urb); pr_info("dequeue a urb %p\n", urb);
spin_lock(&the_controller->lock); spin_lock_irqsave(&the_controller->lock, flags);
priv = urb->hcpriv; priv = urb->hcpriv;
if (!priv) { if (!priv) {
/* URB was never linked! or will be soon given back by /* URB was never linked! or will be soon given back by
* vhci_rx. */ * vhci_rx. */
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
return -EIDRM; return -EIDRM;
} }
...@@ -639,7 +648,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -639,7 +648,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
ret = usb_hcd_check_unlink_urb(hcd, urb, status); ret = usb_hcd_check_unlink_urb(hcd, urb, status);
if (ret) { if (ret) {
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
return ret; return ret;
} }
} }
...@@ -667,10 +676,10 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -667,10 +676,10 @@ 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(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
urb->status); urb->status);
spin_lock(&the_controller->lock); spin_lock_irqsave(&the_controller->lock, flags);
} else { } else {
/* tcp connection is alive */ /* tcp connection is alive */
...@@ -682,7 +691,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -682,7 +691,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
unlink = kzalloc(sizeof(struct vhci_unlink), GFP_ATOMIC); unlink = kzalloc(sizeof(struct vhci_unlink), GFP_ATOMIC);
if (!unlink) { if (!unlink) {
spin_unlock(&vdev->priv_lock); spin_unlock(&vdev->priv_lock);
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC); usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC);
return -ENOMEM; return -ENOMEM;
} }
...@@ -703,7 +712,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -703,7 +712,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
spin_unlock(&vdev->priv_lock); spin_unlock(&vdev->priv_lock);
} }
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
usbip_dbg_vhci_hc("leave\n"); usbip_dbg_vhci_hc("leave\n");
return 0; return 0;
...@@ -712,8 +721,9 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -712,8 +721,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_unlink *unlink, *tmp; struct vhci_unlink *unlink, *tmp;
unsigned long flags;
spin_lock(&the_controller->lock); spin_lock_irqsave(&the_controller->lock, flags);
spin_lock(&vdev->priv_lock); spin_lock(&vdev->priv_lock);
list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
...@@ -747,19 +757,19 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev) ...@@ -747,19 +757,19 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
list_del(&unlink->list); list_del(&unlink->list);
spin_unlock(&vdev->priv_lock); spin_unlock(&vdev->priv_lock);
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
urb->status); urb->status);
spin_lock(&the_controller->lock); spin_lock_irqsave(&the_controller->lock, flags);
spin_lock(&vdev->priv_lock); spin_lock(&vdev->priv_lock);
kfree(unlink); kfree(unlink);
} }
spin_unlock(&vdev->priv_lock); spin_unlock(&vdev->priv_lock);
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
} }
/* /*
...@@ -826,8 +836,9 @@ static void vhci_shutdown_connection(struct usbip_device *ud) ...@@ -826,8 +836,9 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
static void vhci_device_reset(struct usbip_device *ud) static void vhci_device_reset(struct usbip_device *ud)
{ {
struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
unsigned long flags;
spin_lock(&ud->lock); spin_lock_irqsave(&ud->lock, flags);
vdev->speed = 0; vdev->speed = 0;
vdev->devid = 0; vdev->devid = 0;
...@@ -841,14 +852,16 @@ static void vhci_device_reset(struct usbip_device *ud) ...@@ -841,14 +852,16 @@ static void vhci_device_reset(struct usbip_device *ud)
} }
ud->status = VDEV_ST_NULL; ud->status = VDEV_ST_NULL;
spin_unlock(&ud->lock); spin_unlock_irqrestore(&ud->lock, flags);
} }
static void vhci_device_unusable(struct usbip_device *ud) static void vhci_device_unusable(struct usbip_device *ud)
{ {
spin_lock(&ud->lock); unsigned long flags;
spin_lock_irqsave(&ud->lock, flags);
ud->status = VDEV_ST_ERROR; ud->status = VDEV_ST_ERROR;
spin_unlock(&ud->lock); spin_unlock_irqrestore(&ud->lock, flags);
} }
static void vhci_device_init(struct vhci_device *vdev) static void vhci_device_init(struct vhci_device *vdev)
...@@ -938,12 +951,13 @@ static int vhci_get_frame_number(struct usb_hcd *hcd) ...@@ -938,12 +951,13 @@ static int vhci_get_frame_number(struct usb_hcd *hcd)
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); struct vhci_hcd *vhci = hcd_to_vhci(hcd);
unsigned long flags;
dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__); dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
spin_lock(&vhci->lock); spin_lock_irqsave(&vhci->lock, flags);
hcd->state = HC_STATE_SUSPENDED; hcd->state = HC_STATE_SUSPENDED;
spin_unlock(&vhci->lock); spin_unlock_irqrestore(&vhci->lock, flags);
return 0; return 0;
} }
...@@ -952,15 +966,16 @@ static int vhci_bus_resume(struct usb_hcd *hcd) ...@@ -952,15 +966,16 @@ static int vhci_bus_resume(struct usb_hcd *hcd)
{ {
struct vhci_hcd *vhci = hcd_to_vhci(hcd); struct vhci_hcd *vhci = hcd_to_vhci(hcd);
int rc = 0; int rc = 0;
unsigned long flags;
dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__); dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
spin_lock(&vhci->lock); spin_lock_irqsave(&vhci->lock, flags);
if (!HCD_HW_ACCESSIBLE(hcd)) if (!HCD_HW_ACCESSIBLE(hcd))
rc = -ESHUTDOWN; rc = -ESHUTDOWN;
else else
hcd->state = HC_STATE_RUNNING; hcd->state = HC_STATE_RUNNING;
spin_unlock(&vhci->lock); spin_unlock_irqrestore(&vhci->lock, flags);
return rc; return rc;
} }
...@@ -1058,17 +1073,18 @@ static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state) ...@@ -1058,17 +1073,18 @@ static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state)
int rhport = 0; int rhport = 0;
int connected = 0; int connected = 0;
int ret = 0; int ret = 0;
unsigned long flags;
hcd = platform_get_drvdata(pdev); hcd = platform_get_drvdata(pdev);
spin_lock(&the_controller->lock); spin_lock_irqsave(&the_controller->lock, flags);
for (rhport = 0; rhport < VHCI_NPORTS; rhport++) for (rhport = 0; rhport < VHCI_NPORTS; rhport++)
if (the_controller->port_status[rhport] & if (the_controller->port_status[rhport] &
USB_PORT_STAT_CONNECTION) USB_PORT_STAT_CONNECTION)
connected += 1; connected += 1;
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
if (connected > 0) { if (connected > 0) {
dev_info(&pdev->dev, dev_info(&pdev->dev,
......
...@@ -72,10 +72,11 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, ...@@ -72,10 +72,11 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,
{ {
struct usbip_device *ud = &vdev->ud; struct usbip_device *ud = &vdev->ud;
struct urb *urb; struct urb *urb;
unsigned long flags;
spin_lock(&vdev->priv_lock); spin_lock_irqsave(&vdev->priv_lock, flags);
urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum);
spin_unlock(&vdev->priv_lock); spin_unlock_irqrestore(&vdev->priv_lock, flags);
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);
...@@ -104,9 +105,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, ...@@ -104,9 +105,9 @@ 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(&the_controller->lock); spin_lock_irqsave(&the_controller->lock, flags);
usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
...@@ -117,8 +118,9 @@ static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev, ...@@ -117,8 +118,9 @@ static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev,
struct usbip_header *pdu) struct usbip_header *pdu)
{ {
struct vhci_unlink *unlink, *tmp; struct vhci_unlink *unlink, *tmp;
unsigned long flags;
spin_lock(&vdev->priv_lock); spin_lock_irqsave(&vdev->priv_lock, flags);
list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) {
pr_info("unlink->seqnum %lu\n", unlink->seqnum); pr_info("unlink->seqnum %lu\n", unlink->seqnum);
...@@ -127,12 +129,12 @@ static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev, ...@@ -127,12 +129,12 @@ static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev,
unlink->seqnum); unlink->seqnum);
list_del(&unlink->list); list_del(&unlink->list);
spin_unlock(&vdev->priv_lock); spin_unlock_irqrestore(&vdev->priv_lock, flags);
return unlink; return unlink;
} }
} }
spin_unlock(&vdev->priv_lock); spin_unlock_irqrestore(&vdev->priv_lock, flags);
return NULL; return NULL;
} }
...@@ -142,6 +144,7 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, ...@@ -142,6 +144,7 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
{ {
struct vhci_unlink *unlink; struct vhci_unlink *unlink;
struct urb *urb; struct urb *urb;
unsigned long flags;
usbip_dump_header(pdu); usbip_dump_header(pdu);
...@@ -152,9 +155,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, ...@@ -152,9 +155,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
return; return;
} }
spin_lock(&vdev->priv_lock); spin_lock_irqsave(&vdev->priv_lock, flags);
urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum);
spin_unlock(&vdev->priv_lock); spin_unlock_irqrestore(&vdev->priv_lock, flags);
if (!urb) { if (!urb) {
/* /*
...@@ -171,9 +174,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, ...@@ -171,9 +174,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
urb->status = pdu->u.ret_unlink.status; urb->status = pdu->u.ret_unlink.status;
pr_info("urb->status %d\n", urb->status); pr_info("urb->status %d\n", urb->status);
spin_lock(&the_controller->lock); spin_lock_irqsave(&the_controller->lock, flags);
usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
urb->status); urb->status);
...@@ -185,10 +188,11 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, ...@@ -185,10 +188,11 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev,
static int vhci_priv_tx_empty(struct vhci_device *vdev) static int vhci_priv_tx_empty(struct vhci_device *vdev)
{ {
int empty = 0; int empty = 0;
unsigned long flags;
spin_lock(&vdev->priv_lock); spin_lock_irqsave(&vdev->priv_lock, flags);
empty = list_empty(&vdev->priv_rx); empty = list_empty(&vdev->priv_rx);
spin_unlock(&vdev->priv_lock); spin_unlock_irqrestore(&vdev->priv_lock, flags);
return empty; return empty;
} }
......
...@@ -32,10 +32,11 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, ...@@ -32,10 +32,11 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr,
{ {
char *s = out; char *s = out;
int i = 0; int i = 0;
unsigned long flags;
BUG_ON(!the_controller || !out); BUG_ON(!the_controller || !out);
spin_lock(&the_controller->lock); spin_lock_irqsave(&the_controller->lock, flags);
/* /*
* output example: * output example:
...@@ -70,7 +71,7 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, ...@@ -70,7 +71,7 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr,
spin_unlock(&vdev->ud.lock); spin_unlock(&vdev->ud.lock);
} }
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
return out - s; return out - s;
} }
...@@ -80,11 +81,12 @@ static DEVICE_ATTR_RO(status); ...@@ -80,11 +81,12 @@ static DEVICE_ATTR_RO(status);
static int vhci_port_disconnect(__u32 rhport) static int vhci_port_disconnect(__u32 rhport)
{ {
struct vhci_device *vdev; struct vhci_device *vdev;
unsigned long flags;
usbip_dbg_vhci_sysfs("enter\n"); usbip_dbg_vhci_sysfs("enter\n");
/* lock */ /* lock */
spin_lock(&the_controller->lock); spin_lock_irqsave(&the_controller->lock, flags);
vdev = port_to_vdev(rhport); vdev = port_to_vdev(rhport);
...@@ -94,14 +96,14 @@ static int vhci_port_disconnect(__u32 rhport) ...@@ -94,14 +96,14 @@ static int vhci_port_disconnect(__u32 rhport)
/* unlock */ /* unlock */
spin_unlock(&vdev->ud.lock); spin_unlock(&vdev->ud.lock);
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
return -EINVAL; return -EINVAL;
} }
/* unlock */ /* unlock */
spin_unlock(&vdev->ud.lock); spin_unlock(&vdev->ud.lock);
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN); usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN);
...@@ -177,6 +179,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, ...@@ -177,6 +179,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
int sockfd = 0; int sockfd = 0;
__u32 rhport = 0, devid = 0, speed = 0; __u32 rhport = 0, devid = 0, speed = 0;
int err; int err;
unsigned long flags;
/* /*
* @rhport: port number of vhci_hcd * @rhport: port number of vhci_hcd
...@@ -202,14 +205,14 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, ...@@ -202,14 +205,14 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
/* now need lock until setting vdev status as used */ /* now need lock until setting vdev status as used */
/* begin a lock */ /* begin a lock */
spin_lock(&the_controller->lock); spin_lock_irqsave(&the_controller->lock, flags);
vdev = port_to_vdev(rhport); vdev = port_to_vdev(rhport);
spin_lock(&vdev->ud.lock); spin_lock(&vdev->ud.lock);
if (vdev->ud.status != VDEV_ST_NULL) { if (vdev->ud.status != VDEV_ST_NULL) {
/* end of the lock */ /* end of the lock */
spin_unlock(&vdev->ud.lock); spin_unlock(&vdev->ud.lock);
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
sockfd_put(socket); sockfd_put(socket);
...@@ -227,7 +230,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, ...@@ -227,7 +230,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
vdev->ud.status = VDEV_ST_NOTASSIGNED; vdev->ud.status = VDEV_ST_NOTASSIGNED;
spin_unlock(&vdev->ud.lock); spin_unlock(&vdev->ud.lock);
spin_unlock(&the_controller->lock); spin_unlock_irqrestore(&the_controller->lock, flags);
/* end the lock */ /* end the lock */
vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx"); vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx");
......
...@@ -47,16 +47,17 @@ static void setup_cmd_submit_pdu(struct usbip_header *pdup, struct urb *urb) ...@@ -47,16 +47,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) static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev)
{ {
struct vhci_priv *priv, *tmp; struct vhci_priv *priv, *tmp;
unsigned long flags;
spin_lock(&vdev->priv_lock); spin_lock_irqsave(&vdev->priv_lock, flags);
list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) { list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) {
list_move_tail(&priv->list, &vdev->priv_rx); list_move_tail(&priv->list, &vdev->priv_rx);
spin_unlock(&vdev->priv_lock); spin_unlock_irqrestore(&vdev->priv_lock, flags);
return priv; return priv;
} }
spin_unlock(&vdev->priv_lock); spin_unlock_irqrestore(&vdev->priv_lock, flags);
return NULL; return NULL;
} }
...@@ -136,16 +137,17 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev) ...@@ -136,16 +137,17 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev)
static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev) static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev)
{ {
struct vhci_unlink *unlink, *tmp; struct vhci_unlink *unlink, *tmp;
unsigned long flags;
spin_lock(&vdev->priv_lock); spin_lock_irqsave(&vdev->priv_lock, flags);
list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
list_move_tail(&unlink->list, &vdev->unlink_rx); list_move_tail(&unlink->list, &vdev->unlink_rx);
spin_unlock(&vdev->priv_lock); spin_unlock_irqrestore(&vdev->priv_lock, flags);
return unlink; return unlink;
} }
spin_unlock(&vdev->priv_lock); spin_unlock_irqrestore(&vdev->priv_lock, flags);
return NULL; return NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment