⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpqfctscontrol.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	    // bad alpa is reported before FRAME_TO, examine the status	    // flags to see if the device is removed.  If so, DON'T	    // post an ABTS, since it will be terminated by the bad alpa	    // message.	    if( dwStatus & FRAME_TO ) // check for device removed...	    {	      if( !(Exchanges->fcExchange[x_ID].status & DEVICE_REMOVED) )	      { 		// presumes device is still there: send ABTS.                  cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &x_ID);	      }	    }	    else  // Abort all other errors	    {              cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &x_ID);	    }            // if the HPE bit is set, we have to CLose the LOOP            // (see TL/TS UG, pg. 239)            if( dwStatus &= HOSTPROG_ERR )            // set CL bit (see TL/TS UG, pg. 172)              writel( 4, fcChip->Registers.FMcontrol.address);          }        }          // NOTE: we don't necessarily care about ALL completion messages...                                      // SCSI resp. complete OR        if( ((x_ID < TACH_SEST_LEN) && RPCset)||              (x_ID >= TACH_SEST_LEN) )  // non-SCSI command        {              // exchange done; complete to upper levels with status              // (if necessary) and free the exchange slot                      if( x_ID >= TACH_SEST_LEN ) // Link Service Outbound frame?                                    // A Request or Reply has been sent          {                         // signal waiting WorkerThread            up( cpqfcHBAdata->TYOBcomplete);   // frame is OUT of Tach                                    // WorkerThread will complete Xchng          }          else  // X_ID is for FCP assist (SEST)          {              // TBD (target mode)//            fcCompleteExchange( fcChip, x_ID); // TRE completed          }        }      }      else  // ERROR CONDITION!  bogus x_ID in completion message      {        printk(" ProcessIMQ (OBCM) x_id out of range %Xh\n", x_ID);      }          // Load the Frame Manager's error counters.  We check them here          // because presumably the link is up and healthy enough for the          // counters to be meaningful (i.e., don't check them while loop          // is initializing).      fcChip->Registers.FMLinkStatus1.value =    // get TL's counter        readl(fcChip->Registers.FMLinkStatus1.address);                        fcChip->Registers.FMLinkStatus2.value =    // get TL's counter        readl(fcChip->Registers.FMLinkStatus2.address);                  fcParseLinkStatusCounters( fcChip); // load into 6 s/w accumulators    break;    case ERROR_IDLE_COMPLETION:  // TachLite Error Idle...        // We usually get this when the link goes down during heavy traffic.    // For now, presume that if SEST Exchanges are open, we will    // get this as our cue to INVALIDATE all SEST entries    // (and we OWN all the SEST entries).    // See TL/TS UG, pg. 53          for( x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++)      {        // Does this VALid SEST entry need to be invalidated for Abort?        fcChip->SEST->u[ x_ID].IWE.Hdr_Len &= 0x7FFFFFFF;       }            CpqTsUnFreezeTachlite( fcChip, 2); // unfreeze Tachyon, if Link OK    break;    case INBOUND_SFS_COMPLETION:  //0x04          // NOTE! we must process this SFQ message to avoid SFQ filling          // up and stopping TachLite.  Incoming commands are placed here,          // as well as 'unknown' frames (e.g. LIP loop position data)          // write this CM's producer index to global...          // TL/TS UG, pg 234:          // Type: 0 - reserved          //       1 - Unassisted FCP          //       2 - BAD FCP          //       3 - Unkown Frame          //       4-F reserved      fcChip->SFQ->producerIndex = (USHORT)        (fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[0] & 0x0fffL);      ucInboundMessageType = 0;  // default to useless frame        // we can only process two Types: 1, Unassisted FCP, and 3, Unknown        // Also, we aren't interested in processing frame fragments        // so don't Que anything with 'LKF' bit set      if( !(fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2]         & 0x40000000) )  // 'LKF' link failure bit clear?      {        ucInboundMessageType = (UCHAR)  // ICM DWord3, "Type"        (fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2] & 0x0fL);      }      else      {	fcChip->fcStats.linkFailRX++;//        printk("LKF (link failure) bit set on inbound message\n");      }          // clears SFQ entry from Tachyon buffer; copies to contiguous ulBuff      CpqTsGetSFQEntry(        fcChip,                  // i.e. this Device Object        (USHORT)fcChip->SFQ->producerIndex,  // SFQ producer ndx                 ulFibreFrame, TRUE);    // contiguous destination buffer, update chip                             // analyze the incoming frame outside the INT handler...        // (i.e., Worker)      if( ucInboundMessageType == 1 )      {        fchs = (TachFCHDR_GCMND*)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        {	  // someone sent us a SCSI command	  //          fcPutScsiQue( cpqfcHBAdata, //                        SFQ_UNASSISTED_FCP, ulFibreFrame); 	}	else if( ((fchs->d_id & 0xFF000000) == 0x07000000) || // RSP (status)            (fchs->d_id & 0xFF000000) == 0x05000000 )  // XRDY  	{	  ULONG x_ID;	  // Unfortunately, ABTS requires a Freeze on the chip so	  // we can modify the shared memory SEST.  When frozen,	  // any received Exchange frames cannot be processed by	  // Tachyon, so they will be dumped in here.  It is too	  // complex to attempt the reconstruct these frames in	  // the correct Exchange context, so we simply seek to	  // find status or transfer ready frames, and cause the	  // exchange to complete with errors before the timeout	  // expires.  We use a Linux Scsi Cmnd result code that	  // causes immediate retry.	  	  // Do we have an open exchange that matches this s_id	  // and ox_id?	  for( x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++)	  {            if( (fchs->s_id & 0xFFFFFF) ==                  (Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF) 		       &&                (fchs->ox_rx_id & 0xFFFF0000) ==                  (Exchanges->fcExchange[x_ID].fchs.ox_rx_id & 0xFFFF0000) )	    {    //          printk(" #R/X frame x_ID %08X# ", fchs->ox_rx_id );              // simulate the anticipated error - since the	      // SEST was frozen, frames were lost...              Exchanges->fcExchange[ x_ID ].status |= SFQ_FRAME;              	      // presumes device is still there: send ABTS.              cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &x_ID);	      break;  // done	    }	  }	}	        }                else if( ucInboundMessageType == 3)      {        // FC Link Service frames (e.g. PLOGI, ACC) come in here.          cpqfcTSPutLinkQue( cpqfcHBAdata, SFQ_UNKNOWN, ulFibreFrame);                                 }      else if( ucInboundMessageType == 2 ) // "bad FCP"?      {#ifdef IMQ_DEBUG        printk("Bad FCP incoming frame discarded\n");#endif      }      else // don't know this type      {#ifdef IMQ_DEBUG         printk("Incoming frame discarded, type: %Xh\n", ucInboundMessageType);#endif      }                // Check the Frame Manager's error counters.  We check them here        // because presumably the link is up and healthy enough for the        // counters to be meaningful (i.e., don't check them while loop        // is initializing).      fcChip->Registers.FMLinkStatus1.value =    // get TL's counter        readl(fcChip->Registers.FMLinkStatus1.address);                        fcChip->Registers.FMLinkStatus2.value =    // get TL's counter        readl(fcChip->Registers.FMLinkStatus2.address);                      break;                    // We get this CM because we issued a freeze                    // command to stop outbound frames.  We issue the                    // freeze command at Link Up time; when this message                    // is received, the ERQ base can be switched and PDISC                    // frames can be sent.          case ERQ_FROZEN_COMPLETION:  // note: expect ERQ followed immediately                                 // by FCP when freezing TL      fcChip->Registers.TYstatus.value =         // read what's frozen        readl(fcChip->Registers.TYstatus.address);      // (do nothing; wait for FCP frozen message)      break;    case FCP_FROZEN_COMPLETION:            fcChip->Registers.TYstatus.value =         // read what's frozen        readl(fcChip->Registers.TYstatus.address);            // Signal the kernel thread to proceed with SEST modification      up( cpqfcHBAdata->TachFrozen);      break;    case INBOUND_C1_TIMEOUT:    case MFS_BUF_WARN:    case IMQ_BUF_WARN:    break;        // In older Tachyons, we 'clear' the internal 'core' interrupt state        // by reading the FMstatus register.  In newer TachLite (Tachyon),        // we must WRITE the register        // to clear the condition (TL/TS UG, pg 179)    case FRAME_MGR_INTERRUPT:    {      PFC_LOGGEDIN_PORT pLoggedInPort;       fcChip->Registers.FMstatus.value =         readl( fcChip->Registers.FMstatus.address );                      // PROBLEM: It is possible, especially with "dumb" hubs that      // don't automatically LIP on by-pass of ports that are going      // away, for the hub by-pass process to destroy critical       // ordered sets of a frame.  The result of this is a hung LPSM      // (Loop Port State Machine), which on Tachyon results in a      // (default 2 sec) Loop State Timeout (LST) FM message.  We       // want to avoid this relatively huge timeout by detecting      // likely scenarios which will result in LST.      // To do this, we could examine FMstatus for Loss of Synchronization      // and/or Elastic Store (ES) errors.  Of these, Elastic Store is better      // because we get this indication more quickly than the LOS.      // Not all ES errors are harmfull, so we don't want to LIP on every      // ES.  Instead, on every ES, detect whether our LPSM in in one      // of the LST states: ARBITRATING, OPEN, OPENED, XMITTED CLOSE,      // or RECEIVED CLOSE.  (See TL/TS UG, pg. 181)      // If any of these LPSM states are detected      // in combination with the LIP while LDn is not set,       // send an FM init (LIP F7,F7 for loops)!      // It is critical to the physical link stability NOT to reset (LIP)      // more than absolutely necessary; this is a basic premise of the      // SANMark level 1 spec.      {	ULONG Lpsm = (fcChip->Registers.FMstatus.value & 0xF0) >>4;		if( (fcChip->Registers.FMstatus.value & 0x400)  // ElasticStore?                      &&            !(fcChip->Registers.FMstatus.value & 0x100) // NOT LDn	              &&            !(fcChip->Registers.FMstatus.value & 0x1000)) // NOT LF	{	  if( (Lpsm != 0) || // not MONITORING? or	      !(Lpsm & 0x8) )// not already offline?	  {	  // now check the particular LST states...            if( (Lpsm == ARBITRATING) || (Lpsm == OPEN) ||	      (Lpsm == OPENED)      || (Lpsm == XMITTD_CLOSE) ||	      (Lpsm == RCVD_CLOSE) )	    {	      // re-init the loop before it hangs itself!              printk(" #req FMinit on E-S: LPSM %Xh# ",Lpsm);	      fcChip->fcStats.FMinits++;              writel( 6, fcChip->Registers.FMcontrol.address); // LIP	    }	  }	}	else if( fcChip->Registers.FMstatus.value & 0x40000 ) // LST?	{          printk(" #req FMinit on LST, LPSM %Xh# ",Lpsm);	           fcChip->fcStats.FMinits++;          writel( 6, fcChip->Registers.FMcontrol.address);  // LIP	}        }      // clear only the 'interrupting' type bits for this REG read      writel( (fcChip->Registers.FMstatus.value & 0xff3fff00L),        fcChip->Registers.FMstatus.address);                                         // copy frame manager status to unused ULONG slot      fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[0] =          fcChip->Registers.FMstatus.value; // (for debugging)          // Load the Frame Manager's error counters.  We check them here          // because presumably the link is up and healthy enough for the          // counters to be meaningful (i.e., don't check them while loop          // is initializing).      fcChip->Registers.FMLinkStatus1.value =   // get TL's counter        readl(fcChip->Registers.FMLinkStatus1.address);                  fcChip->Registers.FMLinkStatus2.value =   // get TL's counter        readl(fcChip->Registers.FMLinkStatus2.address);                    // Get FM BB_Credit Zero Reg - does not clear on READ      fcChip->Registers.FMBB_CreditZero.value =   // get TL's counter        readl(fcChip->Registers.FMBB_CreditZero.address);                  fcParseLinkStatusCounters( fcChip); // load into 6 s/w accumulators               // LINK DOWN      if( fcChip->Registers.FMstatus.value & 0x100L ) // Link DOWN bit      {                                 	#ifdef IMQ_DEBUG        printk("LinkDn\n");#endif        printk(" #LDn# ");                fcChip->fcStats.linkDown++;        	SetTachTOV( cpqfcHBAdata);  // must set according to SANMark	// Check the ERQ - force it to be "empty" to prevent Tach	// from sending out frames before we do logins.  	if( fcChip->ERQ->producerIndex != fcChip->ERQ->consumerIndex)	{//	  printk("#ERQ PI != CI#");          CpqTsFreezeTachlite( fcChip, 1); // freeze ERQ only	  	  fcChip->ERQ->producerIndex = fcChip->ERQ->consumerIndex = 0; 	  writel( fcChip->ERQ->base, 	    (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_BASE));          // re-writing base forces ERQ PI to equal CI  	}			// link down transition occurred -- port_ids can change        // on next LinkUp, so we must invalidate current logins        // (and any I/O in progress) until PDISC or PLOGI/PRLI

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -