[parisc-linux-cvs] linux grundler

Grant Grundler grundler@dsl2.external.hp.com
Mon, 19 Aug 2002 23:55:21 -0600


Grant Grundler wrote:
> Log message:
> 2.4.19-pa4 cpqfc fixes
> loads as module now on parisc, still doesn't see NVRAM or GBIC.

Still needs more work. Does fix bugs like missing pci_enable_device().
I think the "NVRAM Read Failed" is the next problem that needs to be solved.
Likely a posted PCI write issue.  Console output is before the diff below.

I'm committing this intermediate version for the usual reasons:
o the system no longer crashes (HPMC) when loading the module
o remaining problems are most likely posted PCI write problems
o enabled someone else can work on them.

Anyone interested in working on the a500 + Agilent XL2 should
contact me off list. I'll poke at this off/on again but
not as much as I'd like.

grant


a500:/usr/src/linux# modprobe cpqfc
 scsi_register allocating 6656 bytes for FC HBA
  HBA found!
  HostAdapter->PciDev->irq = 256
  PciDev->baseaddress[0]= 0
  PciDev->baseaddress[1]= 20000
  PciDev->baseaddress[2]= 20100
  PciDev->baseaddress[3]= fffffffffa040000
  cpqfcHBAdata->fcChip.Registers. :
    IOBaseL = 20000
    IOBaseU = 20100
 ioremap'd Membase: fffffffffa040000
    SFQconsumerIndex.address = fffffffffa040058
    ERQproducerIndex.address = fffffffffa040008
    TYconfig.address = fffffffffa040184
    FMconfig.address = fffffffffa0401c0
    FMcontrol.address = fffffffffa0401c4
  Requesting 255 I/O addresses @ 20000
  Requesting 255 I/O addresses @ 20100
  starting TimerTask
  InitializeTachyon
 ResetTachyon
  HBA Tachyon RevId 2.2
Allocating 129024 for 576 Exchanges @ 0000000058fc0000
Allocating 112904 for LinkQ @ 0000000075160000 (576 elements)
Allocating 106504 for TachSEST for 512 Exchanges
  cpqfcTS: writing IMQ BASE E960000h    PI E964000h
  cpqfcTS: SEST 00000000595a0000(virt): Wrote base E980000h @ fffffffffa040140
cpqfcTS: NVRAM read failed
 WARNING! HBA NVRAM WWN read failed - make alias
  WWN 57681D3D44556677
  Waiting for broken Brocade switch...
scsi4 : Agilent FC HBA, Tachyon XL2 HPFC-5200B/2.2: WWN 57681D3D44556677
 on PCI bus 32 device 0x1029 irq 256 IObaseL 0x20000, MEMBASE 0xfa040000
PCI bus width 64 bits, bus speed 66 MHz
FCP-SCSI Driver v2.1.1
GBIC detected: NONE!  LPSM 0h Monitor
a500:/usr/src/linux# 


Index: drivers/scsi/cpqfcTScontrol.c
===================================================================
RCS file: /var/cvs/linux/drivers/scsi/cpqfcTScontrol.c,v
retrieving revision 1.4
diff -u -p -r1.4 cpqfcTScontrol.c
--- drivers/scsi/cpqfcTScontrol.c	9 Nov 2001 23:36:21 -0000	1.4
+++ drivers/scsi/cpqfcTScontrol.c	20 Aug 2002 05:22:32 -0000
@@ -383,14 +383,11 @@ int CpqTsResetTachLite(void *pHBA, int t
       {
         PFC_LOGGEDIN_PORT pLoggedInPort = fcChip->fcPorts.pNextPort;
         PFC_LOGGEDIN_PORT ptr;
-//        printk("checking for allocated LoggedInPorts...\n");
-			
+
         while( pLoggedInPort )
         {
           ptr = pLoggedInPort;
           pLoggedInPort = ptr->pNextPort;
-//	  printk("kfree(%p) on FC LoggedInPort port_id 0x%06lX\n",
-//			  ptr, ptr->port_id);
           kfree( ptr );
         }
       }
@@ -406,7 +403,9 @@ int CpqTsResetTachLite(void *pHBA, int t
                               // However, CPQ 64-bit HBAs have a "health
                               // circuit" which keeps laser ON for a brief
                               // period after it is turned off ( < 1s)
-      
+
+      readb( fcChip->Registers.ReMapMemBase + IINTEN); /* flush posted write */
+
       fcChip->LaserControl( fcChip->Registers.ReMapMemBase, 0);
   
 
@@ -424,9 +423,10 @@ int CpqTsResetTachLite(void *pHBA, int t
         ulBuff = readl( fcChip->Registers.ReMapMemBase + TL_MEM_SOFTRST);
 
         // clear the soft reset
-      for( i=0; i<8; i++)
+      for( i=0; i<8; i++) {
   	writel( 0, (fcChip->Registers.ReMapMemBase + TL_MEM_SOFTRST));
-
+        (void) readl( fcChip->Registers.ReMapMemBase + TL_MEM_SOFTRST);
+	}
                
 
 			       // clear out our copy of Tach regs,
@@ -457,22 +457,19 @@ int CpqTsResetTachLite(void *pHBA, int t
 
 
 
-
-
-
-// 'addrBase' is IOBaseU for both TachLite and (older) Tachyon
 int CpqTsLaserControl( void* addrBase, int opcode )
 {
-  ULONG dwBuff;
+	u32 dwBuff;
 
-  dwBuff = readl((addrBase + TL_MEM_TACH_CONTROL) ); // read TL Control reg
-                                                    // (change only bit 4)
-  if( opcode == 1)
-    dwBuff |= ~0xffffffefL; // set - ON
-  else
-    dwBuff &= 0xffffffefL;  // clear - OFF
-  writel( dwBuff, (addrBase + TL_MEM_TACH_CONTROL)); // write TL Control reg
-  return 0;
+	dwBuff = readl(addrBase + TL_MEM_TACH_CONTROL);
+
+	dwBuff &= ~0x10;	/* assume Laser OFF - clear */
+	if( opcode == 1)
+		dwBuff |= 0x10; /* nope - really want it ON - set */
+
+	writel( dwBuff, (addrBase + TL_MEM_TACH_CONTROL));
+	readl((addrBase + TL_MEM_TACH_CONTROL) ); /* flush posted PCI write */
+	return 0;
 }
 
 
@@ -1669,17 +1666,12 @@ int CpqTsInitializeTachLite( void *pHBA,
   {
     case 1:       // restore hardware to power-on (hard) restart
 
+	DEBUG_PCI(printk(" ResetTachyon\n"));
 
       iStatus = fcChip->ResetTachyon( 
 		  cpqfcHBAdata, opcode2); // laser off, reset hardware
 				      // de-allocate aligned buffers
 
-
-/* TBD      // reset FC link Q (producer and consumer = 0)
-      fcLinkQReset(cpqfcHBAdata); 
-
-*/
-
       if( iStatus )
         break;
 
@@ -1690,17 +1682,11 @@ int CpqTsInitializeTachLite( void *pHBA,
 
       ulBuff = 0x80000000;  // TachLite Configuration Register
 
-      writel( ulBuff, fcChip->Registers.TYconfig.address);
-//      ulBuff = 0x0147L;  // CpqTs PCI CFGCMD register
-//      WritePCIConfiguration( fcChip->Backplane.bus,
-//                           fcChip->Backplane.slot, TLCFGCMD, ulBuff, 4);
-//      ulBuff = 0x0L;  // test!
-//      ReadPCIConfiguration( fcChip->Backplane.bus,
-//                           fcChip->Backplane.slot, TLCFGCMD, &ulBuff, 4);
-
-      // read back for reference...
-      fcChip->Registers.TYconfig.value = 
-         readl( fcChip->Registers.TYconfig.address );
+	writel( ulBuff, fcChip->Registers.TYconfig.address);
+
+	// read back for reference...
+	fcChip->Registers.TYconfig.value =
+		readl( fcChip->Registers.TYconfig.address );
 
       // what is the PCI bus width?
       pci_read_config_byte( cpqfcHBAdata->PciDev,
@@ -1735,7 +1721,11 @@ int CpqTsInitializeTachLite( void *pHBA,
 	}
 	else if( (Major == 2) && (Minor == 1) )
         {
-	  sprintf( cpqfcHBAdata->fcChip.Name, SAGILENT_XL2_21);
+	  sprintf( cpqfcHBAdata->fcChip.Name, SAGILENT_XL2 "/2.1");
+	}
+	else if( (Major == 2) && (Minor == 2) )
+        {
+	  sprintf( cpqfcHBAdata->fcChip.Name, SAGILENT_XL2 "/2.2");
 	}
 	else
 	  sprintf( cpqfcHBAdata->fcChip.Name, STACHLITE_UNKNOWN);
Index: drivers/scsi/cpqfcTSi2c.c
===================================================================
RCS file: /var/cvs/linux/drivers/scsi/cpqfcTSi2c.c,v
retrieving revision 1.1
diff -u -p -r1.1 cpqfcTSi2c.c
--- drivers/scsi/cpqfcTSi2c.c	9 Nov 2000 18:56:48 -0000	1.1
+++ drivers/scsi/cpqfcTSi2c.c	20 Aug 2002 05:22:32 -0000
@@ -136,6 +136,7 @@ static void tl_write_i2c_reg( void* gpio
 
 	// Now or in the new data and send it back out
   writel( temp | value, gpioregOUT);
+  readl( gpioregOUT );	/* flush posted PCI write */
 }
 //-----------------------------------------------------------------------------
 //
@@ -327,6 +328,7 @@ static void tl_set_clock(void* gpioreg)
   ret_val = readl( gpioreg );
   ret_val &= 0xffffffFBL;  // clear GPIO2 (SCL)
   writel( ret_val, gpioreg);
+  readl(gpioreg);	/* flush posted PCI write */
 }
 
 static void tl_clr_clock(void* gpioreg)
@@ -336,6 +338,7 @@ static void tl_clr_clock(void* gpioreg)
   ret_val = readl( gpioreg );
   ret_val |= SET_CLOCK_LO;
   writel( ret_val, gpioreg);
+  readl( gpioreg ); /* flush posted PCI write */
 }
 
 //*****************************************************************
@@ -366,6 +369,7 @@ static void tl_i2c_clock_pulse( UCHAR va
   ret_val |= value;           // the data
   ret_val |= SET_CLOCK_LO;    // the clock
   writel( ret_val, GPIOout );
+  readl( GPIOout );	/* flush posted PCI write */
 
   i2c_delay(0);
 
@@ -463,30 +467,19 @@ int cpqfcTS_GetNVRAM_data( UCHAR *wwnbuf
 
 
 
-// define a short 5 micro sec delay, and longer (ms) delay
 
-static void i2c_delay(ULONG mstime)
-{
-  ULONG i;
-  
-// NOTE: we only expect to use these delays when reading
+// We only expect to use these delays when reading
 // our adapter's NVRAM, which happens only during adapter reset.
 // Delay technique from "Linux Device Drivers", A. Rubini 
 // (1st Ed.) pg 137.
 
+static void i2c_delay(ULONG mstime)
+{
 //  printk(" delay %lx  ", mstime);
-  if( mstime ) // ms delay?
-  {
-    // delay technique
-    for( i=0; i < mstime; i++)
-      udelay(1000); // 1ms per loop
-	
-  }
-  else  // 5 micro sec delay
-  
-    udelay( 5 ); // micro secs
-  
-//  printk("done\n");
+	if( mstime ) {
+		mdelay(mstime);
+	} else
+		udelay(5);
 }
 
 
Index: drivers/scsi/cpqfcTSinit.c
===================================================================
RCS file: /var/cvs/linux/drivers/scsi/cpqfcTSinit.c,v
retrieving revision 1.7
diff -u -p -r1.7 cpqfcTSinit.c
--- drivers/scsi/cpqfcTSinit.c	9 Nov 2001 23:36:21 -0000	1.7
+++ drivers/scsi/cpqfcTSinit.c	20 Aug 2002 05:22:32 -0000
@@ -137,7 +137,7 @@ static void Cpqfc_initHBAdata( CPQFCHBA 
   
   cpqfcHBAdata->fcChip.Registers.SROMBase =  // NULL for HP TS adapter
     PciDev->resource[5].start;
-  
+
   // now the Tachlite chip registers
   // the REGISTER struct holds both the physical address & last
   // written value (some TL registers are WRITE ONLY)
@@ -395,41 +395,37 @@ int cpqfcTS_detect(Scsi_Host_Template *S
 	continue;
       }	
       
-      // OK, we should be able to grab everything we need now.
-      request_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff, DEV_NAME);
-      request_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff, DEV_NAME);
-      DEBUG_PCI(printk("  Requesting 255 I/O addresses @ %x\n",
-        cpqfcHBAdata->fcChip.Registers.IOBaseL ));
-      DEBUG_PCI(printk("  Requesting 255 I/O addresses @ %x\n",
-        cpqfcHBAdata->fcChip.Registers.IOBaseU ));
-
-      
-      // start our kernel worker thread
-
-      launch_FCworker_thread(HostAdapter);
-
-
-      // start our TimerTask...
-
-      cpqfcTStimer = &cpqfcHBAdata->cpqfcTStimer;
-
-      init_timer( cpqfcTStimer); // Linux clears next/prev values
-      cpqfcTStimer->expires = jiffies + HZ; // one second
-      cpqfcTStimer->data = (unsigned long)cpqfcHBAdata; // this adapter
-      cpqfcTStimer->function = cpqfcTSheartbeat; // handles timeouts, housekeeping
-
-      add_timer( cpqfcTStimer);  // give it to Linux
-
-
-      // now initialize our hardware...
-      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.
-      }
+	// OK, we should be able to grab everything we need now.
+	DEBUG_PCI(printk("  Requesting 255 I/O addresses @ %x\n",
+				cpqfcHBAdata->fcChip.Registers.IOBaseL ));
+	request_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff, DEV_NAME);
+
+	DEBUG_PCI(printk("  Requesting 255 I/O addresses @ %x\n",
+				cpqfcHBAdata->fcChip.Registers.IOBaseU ));
+	request_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff, DEV_NAME);
+	pci_enable_device(PciDev);
+
+	launch_FCworker_thread(HostAdapter);
+
+	cpqfcTStimer = &cpqfcHBAdata->cpqfcTStimer;
+
+	init_timer( cpqfcTStimer);	/* Linux clears next/prev values */
+	cpqfcTStimer->expires = jiffies + HZ;	/* one second */
+	cpqfcTStimer->data = (unsigned long)cpqfcHBAdata;
+	cpqfcTStimer->function = cpqfcTSheartbeat;
+
+	add_timer( cpqfcTStimer);	/* start timer */
+
+	/* now initialize our hardware... */
+	if (cpqfcHBAdata->fcChip.InitializeTachyon( cpqfcHBAdata, 1,1)) {
+		printk(KERN_WARNING "cpqfc: initialization of HBA hardware failed.\n");
+		BUG();
+	}
 
       cpqfcHBAdata->fcStatsTime = jiffies;  // (for FC Statistics delta)
       
       // give our HBA time to initialize and login current devices...
+	DEBUG_PCI(printk("  Waiting for broken Brocade switch...\n"));
       {
 	// The Brocade switch (e.g. 2400, 2010, etc.) as of March 2000,
 	// has the following algorithm for FL_Port startup:
@@ -1126,24 +1122,23 @@ Original code from M. McGowen, Compaq
 void cpqfcTS_print_scsi_cmd(Scsi_Cmnd * cmd)
 {
 
-printk("cpqfcTS: (%s) chnl 0x%02x, trgt = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n", 
-    ScsiToAscii( cmd->cmnd[0]), cmd->channel, cmd->target, cmd->lun, cmd->cmd_len);
-
-if( cmd->cmnd[0] == 0)   // Test Unit Ready?
-{
-  int i;
-
-  printk("Cmnd->request_bufflen = 0x%X, ->use_sg = %d, ->bufflen = %d\n",
-    cmd->request_bufflen, cmd->use_sg, cmd->bufflen);
-  printk("Cmnd->request_buffer = %p, ->sglist_len = %d, ->buffer = %p\n",
-    cmd->request_buffer, cmd->sglist_len, cmd->buffer);
-  for (i = 0; i < cmd->cmd_len; i++)
-    printk("0x%02x ", cmd->cmnd[i]);
-  printk("\n");
-}
-
+	printk("cpqfcTS: (%s) chnl 0x%02x, trgt = 0x%02x,"
+			" lun = 0x%02x, cmd_len = 0x%02x\n", 
+			ScsiToAscii( cmd->cmnd[0]), cmd->channel,
+			cmd->target, cmd->lun, cmd->cmd_len);
+
+	if( cmd->cmnd[0] == TEST_UNIT_READY) {
+		int i;
+
+		printk("Cmnd request_bufflen 0x%X, use_sg %d, bufflen %d\n",
+			cmd->request_bufflen, cmd->use_sg, cmd->bufflen);
+		printk("Cmnd->request_buffer 0x%p, sglist_len %d, buffer %p\n",
+			cmd->request_buffer, cmd->sglist_len, cmd->buffer);
+		for (i = 0; i < cmd->cmd_len; i++)
+			printk("0x%02x ", cmd->cmnd[i]);
+		printk("\n");
+	}
 }
-
 #endif				/* DEBUG_CMND */
 
 
Index: drivers/scsi/cpqfcTSstructs.h
===================================================================
RCS file: /var/cvs/linux/drivers/scsi/cpqfcTSstructs.h,v
retrieving revision 1.5
diff -u -p -r1.5 cpqfcTSstructs.h
--- drivers/scsi/cpqfcTSstructs.h	4 Aug 2002 22:58:50 -0000	1.5
+++ drivers/scsi/cpqfcTSstructs.h	20 Aug 2002 05:22:32 -0000
@@ -63,7 +63,7 @@
 #define DEBUG(x)
 #endif				/* DEBUG_CPQFCTS */
 
-//#define DEBUG_CPQFCTS_PCI 1
+#define DEBUG_CPQFCTS_PCI 1
 //#undef DEBUG_CPQFCTS_PCI
 #if DEBUG_CPQFCTS_PCI
 #define DEBUG_PCI(x)	x
@@ -74,7 +74,7 @@
 #define STACHLITE66_TS12  "Compaq FibreChannel HBA Tachyon TS HPFC-5166A/1.2"
 #define STACHLITE66_TS13  "Compaq FibreChannel HBA Tachyon TS HPFC-5166A/1.3"
 #define STACHLITE_UNKNOWN "Compaq FibreChannel HBA Tachyon Chip/Board Ver??"
-#define SAGILENT_XL2_21   "Agilent FC HBA, Tachyon XL2 HPFC-5200B/2.1"
+#define SAGILENT_XL2      "Agilent FC HBA, Tachyon XL2 HPFC-5200B"
 
 // PDA is Peripheral Device Address, VSA is Volume Set Addressing
 // Linux SCSI parameters
@@ -416,7 +416,7 @@ typedef struct           // TachLite pla
 } TachLiteERQ;
 
 // for now, just 32 bit DMA, eventually 40something, with code changes
-#define CPQFCTS_DMA_MASK ((unsigned long) (0x00000000FFFFFFFF))
+#define CPQFCTS_DMA_MASK 0xFFFFFFFFUL
 
 #define TL_MAX_SG_ELEM_LEN 0x7ffff  // Max buffer length a single S/G entry
 				// may represent (a hardware limitation).  The
Index: drivers/scsi/cpqfcTSworker.c
===================================================================
RCS file: /var/cvs/linux/drivers/scsi/cpqfcTSworker.c,v
retrieving revision 1.5
diff -u -p -r1.5 cpqfcTSworker.c
--- drivers/scsi/cpqfcTSworker.c	9 Nov 2001 23:36:21 -0000	1.5
+++ drivers/scsi/cpqfcTSworker.c	20 Aug 2002 05:22:32 -0000
@@ -5111,13 +5111,6 @@ cpqfc_pci_map_sg_page(
 				*maplen, PCI_DMA_TODEVICE);
 	*hw_paddr = (ULONG) *umap_paddr;
 
-#       if BITS_PER_LONG > 32
-       		if( *umap_paddr >>32 ) {
-       	  		printk("cqpfcTS:Tach SG DMA addr %p>32 bits\n", 
-	  			(void*)umap_paddr);
-       			return 0;
-       		}
-#       endif
 	return *umap_paddr;
 }