Re: Kernel 2.6.5 - Compaq Fibre Channel 64-bit/66Mhz HBA [PATCH]

From: Rolf Eike Beer
Date: Thu Aug 11 2005 - 12:58:12 EST


Bolke de Bruin wrote:

>So the basic question is. Does this controller work on kernel 2.6.5?

Don't think about it. This thing is a mess. I tried to remove the #errors
(which was rather simple) and replace them by kmalloc(). Of course then
someone should care about ENOMEM case. One function had no problem at all, the
huge buffer can be avoided at all. The other one is called from an interrupt
handler. This thing tries to handle the complete packet transfer in the
interrupt. Don't use it. It will blow up.

If someone has some spare time this interrupt handler has to be split up. Here
is a diff of what I've done so far. To apply this one you will have to use my
two patches sent in the last days first, the subject lines are

[PATCH 2.6.13-rc5] reduce whitespace bloat in drivers/scsi/cpqfcTScontrol.c
[PATCH 2.6.13-rc5] rewrite drivers/scsi/cpqfcTScontrol.c::CpqTsGetSFQEntry

This patch also kills cpqfcTS_reset() function which is never referenced to.
It causes a compile error by using SCSI_RESET_ERROR, which is undefined (now?).

Eike

--- a/drivers/scsi/cpqfcTScontrol.c 2005-08-11 19:04:26.000000000 +0200
+++ b/drivers/scsi/cpqfcTScontrol.c 2005-08-11 19:28:05.000000000 +0200
@@ -556,27 +556,21 @@ static int PeekIMQEntry( PTACHYON fcChip
// first, we need to find an Inbound Completion message,
// If we find it, check the incoming frame payload (1st word)
// for LILP frame
- if( (fcChip->IMQ->QEntry[CI].type & 0x1FF) == 0x104 )
- {
- TachFCHDR_GCMND* fchs;
-#error This is too much stack
- ULONG ulFibreFrame[2048/4]; // max DWORDS in incoming FC Frame
- ULONG SFQpi = fcChip->IMQ->QEntry[CI].word[0] & 0x0fffL;
-
- CpqTsGetSFQEntry( fcChip,
- SFQpi, // SFQ producer ndx
- ulFibreFrame, 0); // DON'T update chip--this is a "lookahead"
+ if( (fcChip->IMQ->QEntry[CI].type & 0x1FF) == 0x104 ) {
+ TachFCHDR_GCMND *fchs;

- fchs = (TachFCHDR_GCMND*)&ulFibreFrame;
- if( fchs->pl[0] == ELS_LILP_FRAME)
- {
- return 1; // found the LILP frame!
- }
- else
- {
- // keep looking...
- }
- }
+ /* Reference to the first chunk of this struct in QEntry
+ * buffer. We can only rely on the first 64 bytes of
+ * data because consumerIndex may have a wraparound.
+ * This is no problem, we only want to see the first
+ * double word of payload, which is within this range.
+ */
+ fchs = (TachFCHDR_GCMND*) &fcChip->SFQ->QEntry[fcChip->SFQ->consumerIndex];
+
+ if(fchs->pl[0] == ELS_LILP_FRAME) {
+ return 1;
+ }
+ }
}
break;

@@ -665,8 +659,7 @@ int CpqTsProcessIMQEntry(void *host)
ULONG x_ID;
ULONG ulBuff, dwStatus;
TachFCHDR_GCMND* fchs;
-#error This is too much stack
- ULONG ulFibreFrame[2048/4]; // max number of DWORDS in incoming Fibre Frame
+ void *ulFibreFrame = kmalloc(2048, GFP_KERNEL); /* max number of DWORDS in incoming Fibre Frame */
UCHAR ucInboundMessageType; // Inbound CM, dword 3 "type" field

ENTER("ProcessIMQEntry");
@@ -675,6 +668,9 @@ int CpqTsProcessIMQEntry(void *host)
// is a new message waiting for us?
// equal indexes means empty que

+ if (!ulFibreFrame)
+ return -ENOMEM;
+
if( fcChip->IMQ->producerIndex != fcChip->IMQ->consumerIndex )
{ // need to process message

@@ -881,7 +877,7 @@ int CpqTsProcessIMQEntry(void *host)

if( ucInboundMessageType == 1 )
{
- fchs = (TachFCHDR_GCMND*)ulFibreFrame; // cast to examine IB frame
+ fchs = ulFibreFrame; // cast to examine IB frame
// don't fill up our Q with garbage - only accept FCP-CMND
// or XRDY frames
if( (fchs->d_id & 0xFF000000) == 0x06000000 ) // CMND
@@ -1432,7 +1428,7 @@ int CpqTsProcessIMQEntry(void *host)
// to analyze data transfer (successful?), then send a response
// frame for this exchange

- ulFibreFrame[0] = x_ID; // copy for later reference
+ *((ULONG*) ulFibreFrame) = x_ID; // copy for later reference

// if this was a TWE, we have to send satus response
if( Exchanges->fcExchange[ x_ID].type == SCSI_TWE )
@@ -1500,6 +1496,7 @@ int CpqTsProcessIMQEntry(void *host)

LEAVE("ProcessIMQEntry");

+ kfree(ulFibreFrame);
return iStatus;
}

--- a/drivers/scsi/cpqfcTSstructs.h 2005-08-11 19:30:55.000000000 +0200
+++ b/drivers/scsi/cpqfcTSstructs.h 2005-08-11 19:31:31.000000000 +0200
@@ -813,7 +813,6 @@ typedef struct
void (*UnFreezeTachyon)(void*, int );
int (*InitializeTachyon)(void*, int, int );
int (*InitializeFrameManager)(void*, int );
- int (*ProcessIMQEntry)(void*);
int (*ReadWriteWWN)(void*, int ReadWrite);
int (*ReadWriteNVRAM)(void*, void*, int ReadWrite);

--- a/drivers/scsi/cpqfcTSinit.c 2005-08-11 19:29:22.000000000 +0200
+++ b/drivers/scsi/cpqfcTSinit.c 2005-08-11 19:46:07.000000000 +0200
@@ -215,7 +215,6 @@ static void Cpqfc_initHBAdata(CPQFCHBA *
cpqfcHBAdata->fcChip.DestroyTachyonQues = CpqTsDestroyTachLiteQues;
cpqfcHBAdata->fcChip.InitializeTachyon = CpqTsInitializeTachLite;
cpqfcHBAdata->fcChip.LaserControl = CpqTsLaserControl;
- cpqfcHBAdata->fcChip.ProcessIMQEntry = CpqTsProcessIMQEntry;
cpqfcHBAdata->fcChip.InitializeFrameManager = CpqTsInitializeFrameManager;
cpqfcHBAdata->fcChip.ReadWriteWWN = CpqTsReadWriteWWN;
cpqfcHBAdata->fcChip.ReadWriteNVRAM = CpqTsReadWriteNVRAM;
@@ -1693,16 +1692,6 @@ int cpqfcTS_eh_device_reset(Scsi_Cmnd *C
return retval;
}

-
-int cpqfcTS_reset(Scsi_Cmnd *Cmnd, unsigned int reset_flags)
-{
-
- ENTER("cpqfcTS_reset");
-
- LEAVE("cpqfcTS_reset");
- return SCSI_RESET_ERROR; /* Bus Reset Not supported */
-}
-
/* This function determines the bios parameters for a given
harddisk. These tend to be numbers that are made up by the
host adapter. Parameters:
@@ -1763,6 +1752,7 @@ irqreturn_t cpqfcTS_intr_handler( int ir
{
while( (++InfLoopBrk < INFINITE_IMQ_BREAK) && (MoreMessages ==1) )
{
+#error handle CpqTsProcessIMQEntry returning -ENOMEM
MoreMessages = CpqTsProcessIMQEntry( HostAdapter); // ret 0 when done
}
if( InfLoopBrk >= INFINITE_IMQ_BREAK )
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/