@@ -265,6 +265,7 @@ static void ced_writechar_callback(struct urb *pUrb)
{
DEVICE_EXTENSION *pdx = pUrb->context;
int nGot = pUrb->actual_length; /* what we transferred */
+ unsigned long flags;
if (pUrb->status) { /* sync/async unlink faults aren't errors */
if (!
@@ -275,24 +276,24 @@ static void ced_writechar_callback(struct urb *pUrb)
__func__, pUrb->status);
}
- spin_lock(&pdx->err_lock);
+ spin_lock_irqsave(&pdx->err_lock, flags);
pdx->errors = pUrb->status;
- spin_unlock(&pdx->err_lock);
+ spin_unlock_irqrestore(&pdx->err_lock, flags);
nGot = 0; /* and tidy up again if so */
- spin_lock(&pdx->charOutLock); /* already at irq level */
+ spin_lock_irqsave(&pdx->charOutLock, flags); /* already at irq level */
pdx->dwOutBuffGet = 0; /* Reset the output buffer */
pdx->dwOutBuffPut = 0;
pdx->dwNumOutput = 0; /* Clear the char count */
pdx->bPipeError[0] = 1; /* Flag an error for later */
pdx->bSendCharsPending = false; /* Allow other threads again */
- spin_unlock(&pdx->charOutLock); /* already at irq level */
+ spin_unlock_irqrestore(&pdx->charOutLock, flags); /* already at irq level */
dev_dbg(&pdx->interface->dev,
"%s - char out done, 0 chars sent", __func__);
} else {
dev_dbg(&pdx->interface->dev,
"%s - char out done, %d chars sent", __func__, nGot);
- spin_lock(&pdx->charOutLock); /* already at irq level */
+ spin_lock_irqsave(&pdx->charOutLock, flags); /* already at irq level */
pdx->dwNumOutput -= nGot; /* Now adjust the char send buffer */
pdx->dwOutBuffGet += nGot; /* to match what we did */
if (pdx->dwOutBuffGet >= OUTBUF_SZ) /* Can't do this any earlier as data could be overwritten */
@@ -305,7 +306,7 @@ static void ced_writechar_callback(struct urb *pUrb)
unsigned int dwCount = pdx->dwNumOutput; /* maximum to send */
if ((pdx->dwOutBuffGet + dwCount) > OUTBUF_SZ) /* does it cross buffer end? */
dwCount = OUTBUF_SZ - pdx->dwOutBuffGet;
- spin_unlock(&pdx->charOutLock); /* we are done with stuff that changes */
+ spin_unlock_irqrestore(&pdx->charOutLock, flags); /* we are done with stuff that changes */
memcpy(pdx->pCoherCharOut, pDat, dwCount); /* copy output data to the buffer */
usb_fill_bulk_urb(pdx->pUrbCharOut, pdx->udev,
usb_sndbulkpipe(pdx->udev,
@@ -318,7 +319,7 @@ static void ced_writechar_callback(struct urb *pUrb)
iReturn = usb_submit_urb(pdx->pUrbCharOut, GFP_ATOMIC);
dev_dbg(&pdx->interface->dev, "%s n=%d>%s<", __func__,
dwCount, pDat);
- spin_lock(&pdx->charOutLock); /* grab lock for errors */
+ spin_lock_irqsave(&pdx->charOutLock, flags); /* grab lock for errors */
if (iReturn) {
pdx->bPipeError[nPipe] = 1; /* Flag an error to be handled later */
pdx->bSendCharsPending = false; /* Allow other threads again */
@@ -329,7 +330,7 @@ static void ced_writechar_callback(struct urb *pUrb)
}
} else
pdx->bSendCharsPending = false; /* Allow other threads again */
- spin_unlock(&pdx->charOutLock); /* already at irq level */
+ spin_unlock_irqrestore(&pdx->charOutLock, flags); /* already at irq level */
}
}
@@ -505,8 +506,9 @@ static void staged_callback(struct urb *pUrb)
unsigned int nGot = pUrb->actual_length; /* what we transferred */
bool bCancel = false;
bool bRestartCharInput; /* used at the end */
+ unsigned long flags;
- spin_lock(&pdx->stagedLock); /* stop ReadWriteMem() action while this routine is running */
+ spin_lock_irqsave(&pdx->stagedLock, flags); /* stop ReadWriteMem() action while this routine is running */
pdx->bStagedUrbPending = false; /* clear the flag for staged IRP pending */
if (pUrb->status) { /* sync/async unlink faults aren't errors */
@@ -679,7 +681,7 @@ static void staged_callback(struct urb *pUrb)
bRestartCharInput = !bCancel && (pdx->dwDMAFlag == MODE_CHAR)
&& !pdx->bXFerWaiting;
- spin_unlock(&pdx->stagedLock); /* Finally release the lock again */
+ spin_unlock_irqrestore(&pdx->stagedLock, flags); /* Finally release the lock again */
/* This is not correct as dwDMAFlag is protected by the staged lock, but it is treated */
/* in Allowi as if it were protected by the char lock. In any case, most systems will */
@@ -1093,6 +1095,7 @@ static void ced_readchar_callback(struct urb *pUrb)
{
DEVICE_EXTENSION *pdx = pUrb->context;
int nGot = pUrb->actual_length; /* what we transferred */
+ unsigned long flags;
if (pUrb->status) { /* Do we have a problem to handle? */
int nPipe = pdx->nPipes == 4 ? 1 : 0; /* The pipe number to use for error */
@@ -1108,19 +1111,19 @@ static void ced_readchar_callback(struct urb *pUrb)
"%s - 0 chars pUrb->status=%d (shutdown?)",
__func__, pUrb->status);
- spin_lock(&pdx->err_lock);
+ spin_lock_irqsave(&pdx->err_lock, flags);
pdx->errors = pUrb->status;
- spin_unlock(&pdx->err_lock);
+ spin_unlock_irqrestore(&pdx->err_lock, flags);
nGot = 0; /* and tidy up again if so */
- spin_lock(&pdx->charInLock); /* already at irq level */
+ spin_lock_irqsave(&pdx->charInLock, flags); /* already at irq level */
pdx->bPipeError[nPipe] = 1; /* Flag an error for later */
} else {
if ((nGot > 1) && ((pdx->pCoherCharIn[0] & 0x7f) == 0x1b)) { /* Esc sequence? */
Handle1401Esc(pdx, &pdx->pCoherCharIn[1], nGot - 1); /* handle it */
- spin_lock(&pdx->charInLock); /* already at irq level */
+ spin_lock_irqsave(&pdx->charInLock, flags); /* already at irq level */
} else {
- spin_lock(&pdx->charInLock); /* already at irq level */
+ spin_lock_irqsave(&pdx->charInLock, flags); /* already at irq level */
if (nGot > 0) {
unsigned int i;
if (nGot < INBUF_SZ) {
@@ -1147,7 +1150,7 @@ static void ced_readchar_callback(struct urb *pUrb)
}
pdx->bReadCharsPending = false; /* No longer have a pending read */
- spin_unlock(&pdx->charInLock); /* already at irq level */
+ spin_unlock_irqrestore(&pdx->charInLock, flags); /* already at irq level */
Allowi(pdx); /* see if we can do the next one */
}
Complete() will be run with interrupt enabled, so change to spin_lock_irqsave(). Cc: devel@driverdev.osuosl.org Signed-off-by: Ming Lei <ming.lei@canonical.com> --- drivers/staging/ced1401/usb1401.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-)