isdn: mISDN: use irqsave() in USB's complete callback
The USB completion callback does not disable interrupts while acquiring the ->lock. We want to remove the local_irq_disable() invocation from __usb_hcd_giveback_urb() and therefore it is required for the callback handler to disable the interrupts while acquiring the lock. The callback may be invoked either in IRQ or BH context depending on the USB host controller. Use the _irqsave() variant of the locking primitives. Cc: Karsten Keil <isdn@linux-pingi.de> Cc: netdev@vger.kernel.org Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
e112ce4356
Коммит
16630f54fe
|
@ -819,6 +819,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
|
|||
int fifon = fifo->fifonum;
|
||||
int i;
|
||||
int hdlc = 0;
|
||||
unsigned long flags;
|
||||
|
||||
if (debug & DBG_HFC_CALL_TRACE)
|
||||
printk(KERN_DEBUG "%s: %s: fifo(%i) len(%i) "
|
||||
|
@ -835,7 +836,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
|
|||
return;
|
||||
}
|
||||
|
||||
spin_lock(&hw->lock);
|
||||
spin_lock_irqsave(&hw->lock, flags);
|
||||
if (fifo->dch) {
|
||||
rx_skb = fifo->dch->rx_skb;
|
||||
maxlen = fifo->dch->maxlen;
|
||||
|
@ -844,7 +845,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
|
|||
if (fifo->bch) {
|
||||
if (test_bit(FLG_RX_OFF, &fifo->bch->Flags)) {
|
||||
fifo->bch->dropcnt += len;
|
||||
spin_unlock(&hw->lock);
|
||||
spin_unlock_irqrestore(&hw->lock, flags);
|
||||
return;
|
||||
}
|
||||
maxlen = bchannel_get_rxbuf(fifo->bch, len);
|
||||
|
@ -854,7 +855,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
|
|||
skb_trim(rx_skb, 0);
|
||||
pr_warning("%s.B%d: No bufferspace for %d bytes\n",
|
||||
hw->name, fifo->bch->nr, len);
|
||||
spin_unlock(&hw->lock);
|
||||
spin_unlock_irqrestore(&hw->lock, flags);
|
||||
return;
|
||||
}
|
||||
maxlen = fifo->bch->maxlen;
|
||||
|
@ -878,7 +879,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
|
|||
} else {
|
||||
printk(KERN_DEBUG "%s: %s: No mem for rx_skb\n",
|
||||
hw->name, __func__);
|
||||
spin_unlock(&hw->lock);
|
||||
spin_unlock_irqrestore(&hw->lock, flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -888,7 +889,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
|
|||
"for fifo(%d) HFCUSB_D_RX\n",
|
||||
hw->name, __func__, fifon);
|
||||
skb_trim(rx_skb, 0);
|
||||
spin_unlock(&hw->lock);
|
||||
spin_unlock_irqrestore(&hw->lock, flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -942,7 +943,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
|
|||
/* deliver transparent data to layer2 */
|
||||
recv_Bchannel(fifo->bch, MISDN_ID_ANY, false);
|
||||
}
|
||||
spin_unlock(&hw->lock);
|
||||
spin_unlock_irqrestore(&hw->lock, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -979,18 +980,19 @@ rx_iso_complete(struct urb *urb)
|
|||
__u8 *buf;
|
||||
static __u8 eof[8];
|
||||
__u8 s0_state;
|
||||
unsigned long flags;
|
||||
|
||||
fifon = fifo->fifonum;
|
||||
status = urb->status;
|
||||
|
||||
spin_lock(&hw->lock);
|
||||
spin_lock_irqsave(&hw->lock, flags);
|
||||
if (fifo->stop_gracefull) {
|
||||
fifo->stop_gracefull = 0;
|
||||
fifo->active = 0;
|
||||
spin_unlock(&hw->lock);
|
||||
spin_unlock_irqrestore(&hw->lock, flags);
|
||||
return;
|
||||
}
|
||||
spin_unlock(&hw->lock);
|
||||
spin_unlock_irqrestore(&hw->lock, flags);
|
||||
|
||||
/*
|
||||
* ISO transfer only partially completed,
|
||||
|
@ -1096,15 +1098,16 @@ rx_int_complete(struct urb *urb)
|
|||
struct usb_fifo *fifo = (struct usb_fifo *) urb->context;
|
||||
struct hfcsusb *hw = fifo->hw;
|
||||
static __u8 eof[8];
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&hw->lock);
|
||||
spin_lock_irqsave(&hw->lock, flags);
|
||||
if (fifo->stop_gracefull) {
|
||||
fifo->stop_gracefull = 0;
|
||||
fifo->active = 0;
|
||||
spin_unlock(&hw->lock);
|
||||
spin_unlock_irqrestore(&hw->lock, flags);
|
||||
return;
|
||||
}
|
||||
spin_unlock(&hw->lock);
|
||||
spin_unlock_irqrestore(&hw->lock, flags);
|
||||
|
||||
fifon = fifo->fifonum;
|
||||
if ((!fifo->active) || (urb->status)) {
|
||||
|
@ -1172,12 +1175,13 @@ tx_iso_complete(struct urb *urb)
|
|||
int *tx_idx;
|
||||
int frame_complete, fifon, status, fillempty = 0;
|
||||
__u8 threshbit, *p;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&hw->lock);
|
||||
spin_lock_irqsave(&hw->lock, flags);
|
||||
if (fifo->stop_gracefull) {
|
||||
fifo->stop_gracefull = 0;
|
||||
fifo->active = 0;
|
||||
spin_unlock(&hw->lock);
|
||||
spin_unlock_irqrestore(&hw->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1195,7 +1199,7 @@ tx_iso_complete(struct urb *urb)
|
|||
} else {
|
||||
printk(KERN_DEBUG "%s: %s: neither BCH nor DCH\n",
|
||||
hw->name, __func__);
|
||||
spin_unlock(&hw->lock);
|
||||
spin_unlock_irqrestore(&hw->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1375,7 +1379,7 @@ tx_iso_complete(struct urb *urb)
|
|||
hw->name, __func__,
|
||||
symbolic(urb_errlist, status), status, fifon);
|
||||
}
|
||||
spin_unlock(&hw->lock);
|
||||
spin_unlock_irqrestore(&hw->lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче