patch-2.4.14 linux/drivers/scsi/cpqfcTScontrol.c
Next file: linux/drivers/scsi/cpqfcTSinit.c
Previous file: linux/drivers/scsi/cpqfc.Readme
Back to the patch index
Back to the overall index
- Lines: 365
- Date:
Thu Oct 25 13:53:50 2001
- Orig file:
v2.4.13/linux/drivers/scsi/cpqfcTScontrol.c
- Orig date:
Sun Aug 12 13:28:00 2001
diff -u --recursive --new-file v2.4.13/linux/drivers/scsi/cpqfcTScontrol.c linux/drivers/scsi/cpqfcTScontrol.c
@@ -55,6 +55,21 @@
static void CpqTsGetSFQEntry(TACHYON * fcChip,
USHORT pi, ULONG * buffr, BOOLEAN UpdateChip);
+static void
+cpqfc_free_dma_consistent(CPQFCHBA *cpqfcHBAdata)
+{
+ // free up the primary EXCHANGES struct and Link Q
+ PTACHYON fcChip = &cpqfcHBAdata->fcChip;
+
+ if (fcChip->Exchanges != NULL)
+ pci_free_consistent(cpqfcHBAdata->PciDev, sizeof(FC_EXCHANGES),
+ fcChip->Exchanges, fcChip->exch_dma_handle);
+ fcChip->Exchanges = NULL;
+ if (cpqfcHBAdata->fcLQ != NULL)
+ pci_free_consistent(cpqfcHBAdata->PciDev, sizeof(FC_LINK_QUE),
+ cpqfcHBAdata->fcLQ, cpqfcHBAdata->fcLQ_dma_handle);
+ cpqfcHBAdata->fcLQ = NULL;
+}
// Note special requirements for Q alignment! (TL/TS UG pg. 190)
// We place critical index pointers at end of QUE elements to assist
@@ -68,7 +83,8 @@
int iStatus=0;
unsigned long ulAddr;
-
+ dma_addr_t ERQdma, IMQdma, SPQdma, SESTdma;
+ int i;
// NOTE! fcMemManager() will return system virtual addresses.
// System (kernel) virtual addresses, though non-paged, still
@@ -78,15 +94,18 @@
// Allocate primary EXCHANGES array...
+ fcChip->Exchanges = NULL;
+ cpqfcHBAdata->fcLQ = NULL;
printk("Allocating %u for %u Exchanges ",
(ULONG)sizeof(FC_EXCHANGES), TACH_MAX_XID);
- fcChip->Exchanges = kmalloc( sizeof( FC_EXCHANGES), GFP_KERNEL );
+ fcChip->Exchanges = pci_alloc_consistent(cpqfcHBAdata->PciDev,
+ sizeof(FC_EXCHANGES), &fcChip->exch_dma_handle);
printk("@ %p\n", fcChip->Exchanges);
if( fcChip->Exchanges == NULL ) // fatal error!!
{
- printk("kmalloc failure on Exchanges: fatal error\n");
+ printk("pci_alloc_consistent failure on Exchanges: fatal error\n");
return -1;
}
// zero out the entire EXCHANGE space
@@ -94,25 +113,24 @@
printk("Allocating %u for LinkQ ", (ULONG)sizeof(FC_LINK_QUE));
- cpqfcHBAdata->fcLQ = kmalloc( sizeof( FC_LINK_QUE), GFP_KERNEL );
+ cpqfcHBAdata->fcLQ = pci_alloc_consistent(cpqfcHBAdata->PciDev,
+ sizeof( FC_LINK_QUE), &cpqfcHBAdata->fcLQ_dma_handle);
printk("@ %p (%u elements)\n", cpqfcHBAdata->fcLQ, FC_LINKQ_DEPTH);
memset( cpqfcHBAdata->fcLQ, 0, sizeof( FC_LINK_QUE));
if( cpqfcHBAdata->fcLQ == NULL ) // fatal error!!
{
- printk("kmalloc failure on fc Link Que: fatal error\n");
+ cpqfc_free_dma_consistent(cpqfcHBAdata);
+ printk("pci_alloc_consistent() failure on fc Link Que: fatal error\n");
return -1;
}
// zero out the entire EXCHANGE space
memset( cpqfcHBAdata->fcLQ, 0, sizeof( FC_LINK_QUE));
-
-
-
// Verify that basic Tach I/O registers are not NULL
-
if( !fcChip->Registers.ReMapMemBase )
{
+ cpqfc_free_dma_consistent(cpqfcHBAdata);
printk("HBA base address NULL: fatal error\n");
return -1;
}
@@ -125,18 +143,21 @@
// Allocate Tach's Exchange Request Queue (each ERQ entry 32 bytes)
- fcChip->ERQ = fcMemManager( &cpqfcHBAdata->dynamic_mem[0],
- sizeof( TachLiteERQ ), 32*(ERQ_LEN), 0L );
+ fcChip->ERQ = fcMemManager( cpqfcHBAdata->PciDev,
+ &cpqfcHBAdata->dynamic_mem[0],
+ sizeof( TachLiteERQ ), 32*(ERQ_LEN), 0L, &ERQdma);
if( !fcChip->ERQ )
{
- printk("kmalloc/alignment failure on ERQ: fatal error\n");
+ cpqfc_free_dma_consistent(cpqfcHBAdata);
+ printk("pci_alloc_consistent/alignment failure on ERQ: fatal error\n");
return -1;
}
fcChip->ERQ->length = ERQ_LEN-1;
- ulAddr = virt_to_bus( fcChip->ERQ);
+ ulAddr = (ULONG) ERQdma;
#if BITS_PER_LONG > 32
if( (ulAddr >> 32) )
{
+ cpqfc_free_dma_consistent(cpqfcHBAdata);
printk(" FATAL! ERQ ptr %p exceeds Tachyon's 32-bit register size\n",
(void*)ulAddr);
return -1; // failed
@@ -147,19 +168,22 @@
// Allocate Tach's Inbound Message Queue (32 bytes per entry)
- fcChip->IMQ = fcMemManager( &cpqfcHBAdata->dynamic_mem[0],
- sizeof( TachyonIMQ ), 32*(IMQ_LEN), 0L );
+ fcChip->IMQ = fcMemManager( cpqfcHBAdata->PciDev,
+ &cpqfcHBAdata->dynamic_mem[0],
+ sizeof( TachyonIMQ ), 32*(IMQ_LEN), 0L, &IMQdma );
if( !fcChip->IMQ )
{
- printk("kmalloc/alignment failure on IMQ: fatal error\n");
+ cpqfc_free_dma_consistent(cpqfcHBAdata);
+ printk("pci_alloc_consistent/alignment failure on IMQ: fatal error\n");
return -1;
}
fcChip->IMQ->length = IMQ_LEN-1;
- ulAddr = virt_to_bus( fcChip->IMQ);
+ ulAddr = IMQdma;
#if BITS_PER_LONG > 32
if( (ulAddr >> 32) )
{
+ cpqfc_free_dma_consistent(cpqfcHBAdata);
printk(" FATAL! IMQ ptr %p exceeds Tachyon's 32-bit register size\n",
(void*)ulAddr);
return -1; // failed
@@ -169,20 +193,23 @@
// Allocate Tach's Single Frame Queue (64 bytes per entry)
- fcChip->SFQ = fcMemManager( &cpqfcHBAdata->dynamic_mem[0],
- sizeof( TachLiteSFQ ), 64*(SFQ_LEN),0L );
+ fcChip->SFQ = fcMemManager( cpqfcHBAdata->PciDev,
+ &cpqfcHBAdata->dynamic_mem[0],
+ sizeof( TachLiteSFQ ), 64*(SFQ_LEN),0L, &SPQdma );
if( !fcChip->SFQ )
{
- printk("kmalloc/alignment failure on SFQ: fatal error\n");
+ cpqfc_free_dma_consistent(cpqfcHBAdata);
+ printk("pci_alloc_consistent/alignment failure on SFQ: fatal error\n");
return -1;
}
fcChip->SFQ->length = SFQ_LEN-1; // i.e. Que length [# entries -
// min. 32; max. 4096 (0xffff)]
- ulAddr = virt_to_bus( fcChip->SFQ);
+ ulAddr = SPQdma;
#if BITS_PER_LONG > 32
if( (ulAddr >> 32) )
{
+ cpqfc_free_dma_consistent(cpqfcHBAdata);
printk(" FATAL! SFQ ptr %p exceeds Tachyon's 32-bit register size\n",
(void*)ulAddr);
return -1; // failed
@@ -197,22 +224,28 @@
// be on physical page (e.g. 4k) boundary.
printk("Allocating %u for TachSEST for %u Exchanges\n",
(ULONG)sizeof(TachSEST), TACH_SEST_LEN);
- fcChip->SEST = fcMemManager( &cpqfcHBAdata->dynamic_mem[0],
- sizeof(TachSEST), 4, 0L );
+ fcChip->SEST = fcMemManager( cpqfcHBAdata->PciDev,
+ &cpqfcHBAdata->dynamic_mem[0],
+ sizeof(TachSEST), 4, 0L, &SESTdma );
// sizeof(TachSEST), 64*TACH_SEST_LEN, 0L );
if( !fcChip->SEST )
{
- printk("kmalloc/alignment failure on SEST: fatal error\n");
+ cpqfc_free_dma_consistent(cpqfcHBAdata);
+ printk("pci_alloc_consistent/alignment failure on SEST: fatal error\n");
return -1;
}
+ for( i=0; i < TACH_SEST_LEN; i++) // for each exchange
+ fcChip->SEST->sgPages[i] = NULL;
+
fcChip->SEST->length = TACH_SEST_LEN; // e.g. DON'T subtract one
// (TL/TS UG, pg 153)
- ulAddr = virt_to_bus( fcChip->SEST);
+ ulAddr = SESTdma;
#if BITS_PER_LONG > 32
if( (ulAddr >> 32) )
{
+ cpqfc_free_dma_consistent(cpqfcHBAdata);
printk(" FATAL! SFQ ptr %p exceeds Tachyon's 32-bit register size\n",
(void*)ulAddr);
return -1; // failed
@@ -241,7 +274,8 @@
// NOTE! write consumer index last, since the write
// causes Tachyon to process the other registers
- ulAddr = virt_to_bus( &fcChip->ERQ->consumerIndex);
+ ulAddr = ((unsigned long)&fcChip->ERQ->consumerIndex -
+ (unsigned long)fcChip->ERQ) + (unsigned long) ERQdma;
// NOTE! Tachyon DMAs to the ERQ consumer Index host
// address; must be correctly aligned
@@ -269,10 +303,13 @@
// NOTE: TachLite DMAs to the producerIndex host address
// must be correctly aligned with address bits 1-0 cleared
// Writing the BASE register clears the PI register, so write it last
- ulAddr = virt_to_bus( &fcChip->IMQ->producerIndex);
+ ulAddr = ((unsigned long)&fcChip->IMQ->producerIndex -
+ (unsigned long)fcChip->IMQ) + (unsigned long) IMQdma;
+
#if BITS_PER_LONG > 32
if( (ulAddr >> 32) )
{
+ cpqfc_free_dma_consistent(cpqfcHBAdata);
printk(" FATAL! IMQ ptr %p exceeds Tachyon's 32-bit register size\n",
(void*)ulAddr);
return -1; // failed
@@ -1225,7 +1262,7 @@
#endif
Exchanges->fcExchange[i].status |= INITIATOR_ABORT;
- cpqfcTSCompleteExchange( fcChip, i); // abort on LDn
+ cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, i); // abort on LDn
}
}
@@ -1505,7 +1542,7 @@
if( RPCset ) // SEST transaction Response frame rec'd
{
// complete the command in our driver...
- cpqfcTSCompleteExchange( fcChip, x_ID);
+ cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev,fcChip, x_ID);
} // end "RPCset"
@@ -1709,16 +1746,15 @@
case 3: // allocate mem, set Tachyon Que registers
iStatus = CpqTsCreateTachLiteQues( cpqfcHBAdata, opcode2);
+ if( iStatus )
+ break;
+
// now that the Queues exist, Tach can DMA to them, so
// we can begin processing INTs
// INTEN register - enable INT (TachLite interrupt)
writeb( 0x1F, fcChip->Registers.ReMapMemBase + IINTEN);
-
- if( iStatus )
- break;
-
-
+ // Fall through
case 4: // Config Fame Manager, Init Loop Command, laser on
// L_PORT or loopback
@@ -1750,9 +1786,11 @@
{
CPQFCHBA *cpqfcHBAdata = (CPQFCHBA*)pHBA;
PTACHYON fcChip = &cpqfcHBAdata->fcChip;
- USHORT i, j, iStatus=0;
+ USHORT i, iStatus=0;
void* vPtr; // mem Align manager sets this to the freed address on success
unsigned long ulPtr; // for 64-bit pointer cast (e.g. Alpa machine)
+ FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+ PSGPAGES j, next;
ENTER("DestroyTachLiteQues");
@@ -1760,19 +1798,25 @@
{
// search out and free Pool for Extended S/G list pages
- for( i=0, j=0; i < TACH_SEST_LEN; i++, j=0) // for each exchange
+ for( i=0; i < TACH_SEST_LEN; i++) // for each exchange
{
- // It's possible that extended S/G pages were allocated and
+ // It's possible that extended S/G pages were allocated, mapped, and
// not cleared due to error conditions or O/S driver termination.
// Make sure they're all gone.
- while( fcChip->SEST->sgPages[i].PoolPage[j] &&
- (j < TL_MAX_SGPAGES))
- kfree( fcChip->SEST->sgPages[i].PoolPage[j++]);
-
+ if (Exchanges->fcExchange[i].Cmnd != NULL)
+ cpqfc_pci_unmap(cpqfcHBAdata->PciDev, Exchanges->fcExchange[i].Cmnd,
+ fcChip, i); // undo DMA mappings.
+
+ for (j=fcChip->SEST->sgPages[i] ; j != NULL ; j = next) {
+ next = j->next;
+ kfree(j);
+ }
+ fcChip->SEST->sgPages[i] = NULL;
}
ulPtr = (unsigned long)fcChip->SEST;
- vPtr = fcMemManager( &cpqfcHBAdata->dynamic_mem[0],
- 0,0, (ULONG)ulPtr ); // 'free' mem
+ vPtr = fcMemManager( cpqfcHBAdata->PciDev,
+ &cpqfcHBAdata->dynamic_mem[0],
+ 0,0, (ULONG)ulPtr, NULL ); // 'free' mem
fcChip->SEST = 0L; // null invalid ptr
if( !vPtr )
{
@@ -1785,8 +1829,9 @@
{
ulPtr = (unsigned long)fcChip->SFQ;
- vPtr = fcMemManager( &cpqfcHBAdata->dynamic_mem[0],
- 0,0, (ULONG)ulPtr ); // 'free' mem
+ vPtr = fcMemManager( cpqfcHBAdata->PciDev,
+ &cpqfcHBAdata->dynamic_mem[0],
+ 0,0, (ULONG)ulPtr, NULL ); // 'free' mem
fcChip->SFQ = 0L; // null invalid ptr
if( !vPtr )
{
@@ -1803,8 +1848,8 @@
fcChip->IMQ->consumerIndex = 0;
ulPtr = (unsigned long)fcChip->IMQ;
- vPtr = fcMemManager( &cpqfcHBAdata->dynamic_mem[0],
- 0,0, (ULONG)ulPtr ); // 'free' mem
+ vPtr = fcMemManager( cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0],
+ 0,0, (ULONG)ulPtr, NULL ); // 'free' mem
fcChip->IMQ = 0L; // null invalid ptr
if( !vPtr )
{
@@ -1816,8 +1861,8 @@
if( fcChip->ERQ ) // release memory blocks used by the queues
{
ulPtr = (unsigned long)fcChip->ERQ;
- vPtr = fcMemManager( &cpqfcHBAdata->dynamic_mem[0],
- 0,0, (ULONG)ulPtr ); // 'free' mem
+ vPtr = fcMemManager( cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0],
+ 0,0, (ULONG)ulPtr, NULL ); // 'free' mem
fcChip->ERQ = 0L; // null invalid ptr
if( !vPtr )
{
@@ -1826,19 +1871,8 @@
}
}
- // free up the primary EXCHANGES struct
- if( fcChip->Exchanges != NULL)
- {
-// printk("kfree() on Exchanges @%p\n", fcChip->Exchanges);
- kfree( fcChip->Exchanges);
- }
-
- // free up Link Q
- if( cpqfcHBAdata->fcLQ != NULL )
- {
-// printk("kfree() on LinkQ @%p\n", fcChip->fcLQ);
- kfree( cpqfcHBAdata->fcLQ);
- }
+ // free up the primary EXCHANGES struct and Link Q
+ cpqfc_free_dma_consistent(cpqfcHBAdata);
LEAVE("DestroyTachLiteQues");
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)