patch-2.4.14 linux/drivers/scsi/cpqfcTSinit.c

Next file: linux/drivers/scsi/cpqfcTSioctl.h
Previous file: linux/drivers/scsi/cpqfcTScontrol.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.13/linux/drivers/scsi/cpqfcTSinit.c linux/drivers/scsi/cpqfcTSinit.c
@@ -67,7 +67,7 @@
 
 /* Embedded module documentation macros - see module.h */
 MODULE_AUTHOR("Compaq Computer Corporation");
-MODULE_DESCRIPTION("Driver for Compaq 64-bit/66Mhz PCI Fibre Channel HBA");
+MODULE_DESCRIPTION("Driver for Compaq 64-bit/66Mhz PCI Fibre Channel HBA v. 2.1.1");
 MODULE_LICENSE("GPL");
   
 int cpqfcTS_TargetDeviceReset( Scsi_Device *ScsiDev, unsigned int reset_flags);
@@ -304,6 +304,13 @@
     while( (PciDev =
       pci_find_device( PCIids[i].vendor_id, PCIids[i].device_id, PciDev) ))
     {
+
+      if (pci_set_dma_mask(PciDev, CPQFCTS_DMA_MASK) != 0) {
+	printk(KERN_WARNING 
+		"cpqfc: HBA cannot support required DMA mask, skipping.\n");
+	continue;
+      }
+
       // NOTE: (kernel 2.2.12-32) limits allocation to 128k bytes...
       printk(" scsi_register allocating %d bytes for FC HBA\n",
 		      (ULONG)sizeof(CPQFCHBA));
@@ -415,8 +422,10 @@
 
 
       // now initialize our hardware...
-
-      cpqfcHBAdata->fcChip.InitializeTachyon( cpqfcHBAdata, 1,1);
+      if (cpqfcHBAdata->fcChip.InitializeTachyon( cpqfcHBAdata, 1,1)) {
+	printk(KERN_WARNING "cpqfc: initialization of HBA hardware failed.\n");
+	// FIXME: might want to do something better than nothing here.
+      }
 
       cpqfcHBAdata->fcStatsTime = jiffies;  // (for FC Statistics delta)
       
@@ -660,7 +669,7 @@
 
 
 
-      case SCSI_IOCTL_FC_TARGET_ADDRESS:
+      case CPQFC_IOCTL_FC_TARGET_ADDRESS:
       result = 
         verify_area(VERIFY_WRITE, arg, sizeof(Scsi_FCTargAddress));
       if (result) 
@@ -678,7 +687,7 @@
         break;
 
 
-      case SCSI_IOCTL_FC_TDR:
+      case CPQFC_IOCTL_FC_TDR:
           
         result = cpqfcTS_TargetDeviceReset( ScsiDev, 0);
 
@@ -880,7 +889,6 @@
   cpqfcTSDecodeGBICtype( &cpqfcHBA->fcChip, &buf[0]);
   cpqfcTSGetLPSM( &cpqfcHBA->fcChip, &buf[ strlen(buf)]);
   copy_info(&info, "%s\n", buf); 
-		  
 
 #define DISPLAY_WWN_INFO
 #ifdef DISPLAY_WWN_INFO
@@ -905,6 +913,9 @@
     }
   }
 #endif
+
+
+
   
   
 // Unfortunately, the proc_info buffer isn't big enough
@@ -1191,6 +1202,9 @@
 
 // The file "hosts.h" says not to call scsi_done from
 // inside _queuecommand, so we'll do it from the heartbeat timer
+// (clarification: Turns out it's ok to call scsi_done from queuecommand 
+// for cases that don't go to the hardware like scsi cmds destined
+// for LUNs we know don't exist, so this code might be simplified...)
 
 static void QueBadTargetCmnd( CPQFCHBA *cpqfcHBAdata, Scsi_Cmnd *Cmnd)
 {
@@ -1675,8 +1689,15 @@
   	printk(" cpqfcTS adapter PCI master address crossed 45-bit boundary\n");
       if( IntPending & 0x2 )
 	printk(" cpqfcTS adapter DMA error detected\n");
-      if( IntPending & 0x1 )
+      if( IntPending & 0x1 ) {
+  	UCHAR IntStat;
   	printk(" cpqfcTS adapter PCI error detected\n");
+  	IntStat = readb( cpqfcHBA->fcChip.Registers.INTSTAT.address);
+	if (IntStat & 0x4) printk("(INT)\n");
+	if (IntStat & 0x8) 
+		printk("CRS: PCI master address crossed 46 bit bouandary\n");
+	if (IntStat & 0x10) printk("MRE: external memory parity error.\n");
+      }
     }      
   }
   spin_unlock_irqrestore( &io_request_lock, flags);
@@ -1859,8 +1880,9 @@
 // we need about 8 allocations per HBA.  Figuring at most 10 HBAs per server
 // size the dynamic_mem array at 80.
 
-void* fcMemManager( ALIGNED_MEM *dynamic_mem, ULONG n_alloc, ULONG ab,
-                   ULONG u32_AlignedAddress)
+void* fcMemManager( struct pci_dev *pdev, ALIGNED_MEM *dynamic_mem, 
+		   ULONG n_alloc, ULONG ab, ULONG u32_AlignedAddress,
+			dma_addr_t *dma_handle)
 {
   USHORT allocBoundary=1;   // compiler specific - worst case 1
                                   // best case - replace malloc() call
@@ -1882,38 +1904,51 @@
       if( dynamic_mem[i].AlignedAddress == u32_AlignedAddress )
       {
         alloc_address = dynamic_mem[i].BaseAllocated; // 'success' status
-        kfree( dynamic_mem[i].BaseAllocated);  // return pages to kernel
+	pci_free_consistent(pdev,dynamic_mem[i].size, 
+				alloc_address, 
+				dynamic_mem[i].dma_handle);
         dynamic_mem[i].BaseAllocated = 0;   // clear for next use
         dynamic_mem[i].AlignedAddress = 0;
+        dynamic_mem[i].size = 0;
         break;                        // quit for loop; done
       }
     }
   }
   else if( n_alloc )                   // want new memory?
   {
+    dma_addr_t handle;
     t_alloc = n_alloc + (ab - allocBoundary); // pad bytes for alignment
-//    printk("kmalloc() for Tach alignment: %ld bytes\n", t_alloc);
+//    printk("pci_alloc_consistent() for Tach alignment: %ld bytes\n", t_alloc);
 
+// (would like to) allow thread block to free pages 
     alloc_address =                  // total bytes (NumberOfBytes)
-      kmalloc( t_alloc, GFP_KERNEL); // allow thread block to free pages 
-
+      pci_alloc_consistent(pdev, t_alloc, &handle); 
 
                                   // now mask off least sig. bits of address
     if( alloc_address )           // (only if non-NULL)
     {
                                   // find place to store ptr, so we
                                   // can free it later...
+
+      mask = (LONG)(ab - 1);            // mask all low-order bits
+      mask = ~mask;                            // invert bits
       for( i=0; i<DYNAMIC_ALLOCATIONS; i++) // look for free slot
       {
         if( dynamic_mem[i].BaseAllocated == 0) // take 1st available
         {
           dynamic_mem[i].BaseAllocated = alloc_address;// address from O/S
+          dynamic_mem[i].dma_handle = handle;
+	  if (dma_handle != NULL) 
+	  {
+//             printk("handle = %p, ab=%d, boundary = %d, mask=0x%08x\n", 
+//			handle, ab, allocBoundary, mask);
+	    *dma_handle = (dma_addr_t) 
+		((((ULONG)handle) + (ab - allocBoundary)) & mask);
+	  }
+          dynamic_mem[i].size = t_alloc;
           break;
         }
       }
-      mask = (LONG)(ab - 1);            // mask all low-order bits
-      mask = ~mask;                            // invert bits
-
       ulAddress = (unsigned long)alloc_address;
       
       ulAddress += (ab - allocBoundary);    // add the alignment bytes-

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)