* [PATCH] tmscsim: host_lock use in LLD
@ 2004-06-18 21:28 Guennadi Liakhovetski
2004-06-20 13:49 ` James Bottomley
0 siblings, 1 reply; 4+ messages in thread
From: Guennadi Liakhovetski @ 2004-06-18 21:28 UTC (permalink / raw)
To: linux-scsi; +Cc: Kurt Garloff
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1307 bytes --]
Hi
While reviewing tmscsim, I noticed something, I didn't quite like /
understand. The driver takes the host_lock (with irqsave) at the entry to
the ISR, and releases it at the exit. And inside the ISR there are
potentially long busy-waits... Like
int ctr = 6000000; /* only try for about a second */
while( --ctr && !((dstate = DC390_read8 (DMA_Status)) &
DMA_XFER_DONE) && pSRB->SGToBeXferLen );
The attached patch is attempting to fix those places. Not sure if this is
a proper fix though. In my understanding, after looking through the code,
the host_lock is used to protect host-specific data and host-registers.
The ->queuecommand is already called with it help, so, one just,
basically, have to protect other contexts - interrupt, timer,... So, looks
mostly right.
BTW, I noticed, that other drivers have this bug (?) too, e.g.:
in *NCR5380.c::NCR5380_information_transfer() (called with lock held, irqs
disabled)
while (NCR5380_read(STATUS_REG) & SR_REQ);
But just now, looking at dc395x.c I see at places, symmetric to those
from tmscsim, that I am trying to fix with this patch, a comment from
Kurt:
/* KG: This should not be needed any more! */
and those loops are commented out. Kurt (or anybody else), please,
explain?
Thanks
Guennadi
---
Guennadi Liakhovetski
[-- Attachment #2: Type: TEXT/PLAIN, Size: 6611 bytes --]
diff -ur --exclude=CVS vanilla/linux-2.6.6/drivers/scsi/scsiiom.c linux-2.6.6-bk6-tmscsim/drivers/scsi/scsiiom.c
--- vanilla/linux-2.6.6/drivers/scsi/scsiiom.c Thu Jun 17 23:47:03 2004
+++ linux-2.6.6-bk6-tmscsim/drivers/scsi/scsiiom.c Fri Jun 18 23:03:38 2004
@@ -227,7 +227,6 @@
#if DMA_INT
UCHAR dstatus;
#endif
- DC390_IFLAGS;
pACB = (PACB)dev_id;
for (pACB2 = dc390_pACB_start; (pACB2 && pACB2 != pACB); pACB2 = pACB2->pNextACB);
@@ -244,9 +243,9 @@
DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus));
#if DMA_INT
- DC390_LOCK_IO(pACB->pScsiHost);
+ spin_lock_irq(pACB->pScsiHost->host_lock);
dstatus = dc390_dma_intr (pACB);
- DC390_UNLOCK_IO(pACB->pScsiHost);
+ spin_unlock_irq(pACB->pScsiHost->host_lock);
DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus));
if (! (dstatus & SCSI_INTERRUPT))
@@ -260,7 +259,7 @@
//DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
#endif
- DC390_LOCK_IO(pACB->pScsiHost);
+ spin_lock_irq(pACB->pScsiHost->host_lock);
istate = DC390_read8 (Intern_State);
istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */
@@ -328,11 +327,10 @@
DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus));
stateV = (void *) dc390_phase1[phase];
( *stateV )( pACB, pSRB, &sstatus );
- goto unlock;
}
unlock:
- DC390_UNLOCK_IO(pACB->pScsiHost);
+ spin_unlock_irq(pACB->pScsiHost->host_lock);
return IRQ_HANDLED;
}
@@ -363,10 +361,20 @@
if( sstatus & COUNT_2_ZERO )
{
- int ctr = 6000000; /* only try for about a second */
- while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen );
- if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
- dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
+ unsigned long timeout = jiffies + HZ;
+
+ /* Function called from the ISR with the host_lock held and interrupts disabled */
+ if (pSRB->SGToBeXferLen)
+ while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
+ spin_unlock_irq(pACB->pScsiHost->host_lock);
+ udelay(50);
+ spin_lock_irq(pACB->pScsiHost->host_lock);
+ }
+ if (!time_before(jiffies, timeout))
+ printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n",
+ DC390_read32 (DMA_Wk_ByteCntr));
+ dc390_laststatus &= ~0xff000000;
+ dc390_laststatus |= dstate << 24;
pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
pSRB->SGIndex++;
if( pSRB->SGIndex < pSRB->SGcount )
@@ -418,12 +426,23 @@
if( sstatus & COUNT_2_ZERO )
{
- int ctr = 6000000; /* only try for about a second */
int dstate = 0;
- while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen );
- if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
- if (!ctr) printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate);
- dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
+ unsigned long timeout = jiffies + HZ;
+
+ /* Function called from the ISR with the host_lock held and interrupts disabled */
+ if (pSRB->SGToBeXferLen)
+ while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
+ spin_unlock_irq(pACB->pScsiHost->host_lock);
+ udelay(50);
+ spin_lock_irq(pACB->pScsiHost->host_lock);
+ }
+ if (!time_before(jiffies, timeout)) {
+ printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n",
+ DC390_read32 (DMA_Wk_ByteCntr));
+ printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate);
+ }
+ dc390_laststatus &= ~0xff000000;
+ dc390_laststatus |= dstate << 24;
DEBUG1(ResidCnt = ((ULONG) DC390_read8 (CtcReg_High) << 16) \
+ ((ULONG) DC390_read8 (CtcReg_Mid) << 8) \
+ ((ULONG) DC390_read8 (CtcReg_Low)));
@@ -1111,10 +1130,9 @@
pDCB = pACB->pActiveDCB;
if (!pDCB)
{
- int j = 400;
DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\
pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel));
- while (--j) udelay (1000);
+ mdelay(400);
DC390_read8 (INT_Status); /* Reset Pending INT */
DC390_write8 (ScsiCmd, EN_SEL_RESEL);
return;
diff -ur --exclude=CVS vanilla/linux-2.6.6/drivers/scsi/tmscsim.c linux-2.6.6-bk6-tmscsim/drivers/scsi/tmscsim.c
--- vanilla/linux-2.6.6/drivers/scsi/tmscsim.c Thu Jun 17 23:47:03 2004
+++ linux-2.6.6-bk6-tmscsim/drivers/scsi/tmscsim.c Fri Jun 18 23:02:20 2004
@@ -283,12 +283,6 @@
};
MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl);
-#define USE_SPINLOCKS 1
-
-#define DC390_IFLAGS unsigned long iflags
-#define DC390_LOCK_IO(dev) spin_lock_irqsave (((struct Scsi_Host *)dev)->host_lock, iflags)
-#define DC390_UNLOCK_IO(dev) spin_unlock_irqrestore (((struct Scsi_Host *)dev)->host_lock, iflags)
-
/* These macros are used for uniform access to 2.0.x and 2.1.x PCI config space*/
#define PDEV pdev
@@ -863,11 +857,11 @@
static void DC390_waiting_timed_out (unsigned long ptr)
{
PACB pACB = (PACB)ptr;
- DC390_IFLAGS;
+ unsigned long iflags;
DEBUG0(printk ("DC390: Debug: Waiting queue woken up by timer!\n"));
- DC390_LOCK_IO(pACB->pScsiHost);
+ spin_lock_irqsave(pACB->pScsiHost->host_lock, iflags);
dc390_Waiting_process (pACB);
- DC390_UNLOCK_IO(pACB->pScsiHost);
+ spin_unlock_irqrestore(pACB->pScsiHost->host_lock, iflags);
}
/***********************************************************************
@@ -2026,12 +2020,12 @@
static void __devexit dc390_remove_one(struct pci_dev *dev)
{
struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
- DC390_IFLAGS;
+ unsigned long iflags;
PACB pACB = (PACB) scsi_host->hostdata;
scsi_remove_host(scsi_host);
- DC390_LOCK_IO(scsi_host);
+ spin_lock_irqsave(scsi_host->host_lock, iflags);
/* TO DO: We should check for outstanding commands first. */
dc390_shutdown(scsi_host);
@@ -2043,7 +2037,7 @@
release_region(scsi_host->io_port, scsi_host->n_io_port);
dc390_freeDCBs(scsi_host);
- DC390_UNLOCK_IO(scsi_host);
+ spin_unlock_irqrestore(scsi_host->host_lock, iflags);
pci_disable_device(dev);
scsi_host_put(scsi_host);
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] tmscsim: host_lock use in LLD
2004-06-18 21:28 [PATCH] tmscsim: host_lock use in LLD Guennadi Liakhovetski
@ 2004-06-20 13:49 ` James Bottomley
2004-06-20 20:25 ` Guennadi Liakhovetski
2004-06-21 21:29 ` Guennadi Liakhovetski
0 siblings, 2 replies; 4+ messages in thread
From: James Bottomley @ 2004-06-20 13:49 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: SCSI Mailing List, Kurt Garloff
On Fri, 2004-06-18 at 16:28, Guennadi Liakhovetski wrote:
> While reviewing tmscsim, I noticed something, I didn't quite like /
> understand. The driver takes the host_lock (with irqsave) at the entry to
> the ISR, and releases it at the exit. And inside the ISR there are
> potentially long busy-waits... Like
>
> int ctr = 6000000; /* only try for about a second */
> while( --ctr && !((dstate = DC390_read8 (DMA_Status)) &
> DMA_XFER_DONE) && pSRB->SGToBeXferLen );
>
> The attached patch is attempting to fix those places. Not sure if this is
> a proper fix though. In my understanding, after looking through the code,
> the host_lock is used to protect host-specific data and host-registers.
> The ->queuecommand is already called with it help, so, one just,
> basically, have to protect other contexts - interrupt, timer,... So, looks
> mostly right.
This patch is rejecting in this part:
static void __devexit dc390_remove_one(struct pci_dev *dev)
{
struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
- DC390_IFLAGS;
+ unsigned long iflags;
PACB pACB = (PACB) scsi_host->hostdata;
scsi_remove_host(scsi_host);
- DC390_LOCK_IO(scsi_host);
+ spin_lock_irqsave(scsi_host->host_lock, iflags);
As best as I can tell, DC390_IFLAGS has never been part of the tmscsim.c
file ... I think this must be against some modification of the driver
you have in your tree.
James
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] tmscsim: host_lock use in LLD
2004-06-20 13:49 ` James Bottomley
@ 2004-06-20 20:25 ` Guennadi Liakhovetski
2004-06-21 21:29 ` Guennadi Liakhovetski
1 sibling, 0 replies; 4+ messages in thread
From: Guennadi Liakhovetski @ 2004-06-20 20:25 UTC (permalink / raw)
To: James Bottomley; +Cc: SCSI Mailing List, Kurt Garloff, Christoph Hellwig
On Sun, 20 Jun 2004, James Bottomley wrote:
> On Fri, 2004-06-18 at 16:28, Guennadi Liakhovetski wrote:
>> While reviewing tmscsim, I noticed something, I didn't quite like /
>> understand. The driver takes the host_lock (with irqsave) at the entry to
>> the ISR, and releases it at the exit. And inside the ISR there are
>> potentially long busy-waits... Like
>>
>> int ctr = 6000000; /* only try for about a second */
>> while( --ctr && !((dstate = DC390_read8 (DMA_Status)) &
>> DMA_XFER_DONE) && pSRB->SGToBeXferLen );
>>
>> The attached patch is attempting to fix those places. Not sure if this is
>> a proper fix though. In my understanding, after looking through the code,
>> the host_lock is used to protect host-specific data and host-registers.
>> The ->queuecommand is already called with it help, so, one just,
>> basically, have to protect other contexts - interrupt, timer,... So, looks
>> mostly right.
>
> This patch is rejecting in this part:
>
> static void __devexit dc390_remove_one(struct pci_dev *dev)
> {
> struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
> - DC390_IFLAGS;
> + unsigned long iflags;
> PACB pACB = (PACB) scsi_host->hostdata;
>
> scsi_remove_host(scsi_host);
>
> - DC390_LOCK_IO(scsi_host);
> + spin_lock_irqsave(scsi_host->host_lock, iflags);
>
>
> As best as I can tell, DC390_IFLAGS has never been part of the tmscsim.c
> file ... I think this must be against some modification of the driver
> you have in your tree.
Sorry, James. It's been a pretty long Sunday, and I do have a bit of a
headache, so, what I see might quite well differ from what everybody else
sees, but it does look like DC390_IFLAGS is still a part of tmscsim.c as
of 2.6.7... And rejects are due to my another patch, sent to the list,
cc'ed to you, Christoph and Kurt on the 31st May, and I did receive it
back from the list. So, it could have happen that you didn't receive it
personally, but it did come through to the list. Tell me if I should
re-send it. Actually, according to my calculations, there are 3 more
(apart from these 2) outstanding patches for tmscsim.
BTW, what is your preferred way of receiving patches, which depend on each
other? Should I (in the future) wait until the previous patch appears
(where?) in a global tree, or collect several patches and send them
together, or is what I am doing ATM ok (just send patches in as they
appear, "on the queue")?
Sorry for the inconvenience.
Thanks
Guennadi
---
Guennadi Liakhovetski
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] tmscsim: host_lock use in LLD
2004-06-20 13:49 ` James Bottomley
2004-06-20 20:25 ` Guennadi Liakhovetski
@ 2004-06-21 21:29 ` Guennadi Liakhovetski
1 sibling, 0 replies; 4+ messages in thread
From: Guennadi Liakhovetski @ 2004-06-21 21:29 UTC (permalink / raw)
To: James Bottomley; +Cc: SCSI Mailing List
James
For your convenience, outstanding (submitted but not yet applied) patches
are at http://home.arcor.de/g.liakhovetski/scsi/outstanding/
Thanks
Guennadi
---
Guennadi Liakhovetski
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2004-06-21 21:29 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-06-18 21:28 [PATCH] tmscsim: host_lock use in LLD Guennadi Liakhovetski
2004-06-20 13:49 ` James Bottomley
2004-06-20 20:25 ` Guennadi Liakhovetski
2004-06-21 21:29 ` Guennadi Liakhovetski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox