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

📄 cpqfctsworker.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      if( !cpqfcHBAdata->PortDiscDone) // cleared by LDn      {        printk("Discard Q'd ELS login frame\n");        break;        }      ulStatus = cpqfcTSBuildExchange(          cpqfcHBAdata,          fcLQ->Qitem[QconsumerNdx].Type, // e.g. PLOGI          (TachFCHDR_GCMND*)            fcLQ->Qitem[QconsumerNdx].ulBuff, // incoming fchs          NULL,         // no data (no scatter/gather list)          &ExchangeID );// fcController->fcExchanges index, -1 if failed      if( !ulStatus ) // Exchange setup?      {        ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID );        if( !ulStatus )        {          // submitted to Tach's Outbound Que (ERQ PI incremented)          // waited for completion for ELS type (Login frames issued          // synchronously)        }        else          // check reason for Exchange not being started - we might          // want to Queue and start later, or fail with error        {        }      }      else   // Xchange setup failed...        printk(" cpqfcTSBuildExchange failed: %Xh\n", ulStatus );      break;    case SCSI_REPORT_LUNS:      // pass the incoming frame (actually, it's a PRLI frame)      // so we can send REPORT_LUNS, in order to determine VSA/PDU      // FCP-SCSI Lun address mode      IssueReportLunsCommand( cpqfcHBAdata, (TachFCHDR_GCMND*)            fcLQ->Qitem[QconsumerNdx].ulBuff);       break;          case BLS_ABTS:       // need to ABORT one or more exchanges    {      LONG x_ID = fcLQ->Qitem[QconsumerNdx].ulBuff[0];      BOOLEAN FrozeTach = FALSE;              if( x_ID > TACH_SEST_LEN )  // (in)sanity check      {//	printk( " cpqfcTS ERROR! BOGUS x_ID %Xh", x_ID);	break;      }      if( Exchanges->fcExchange[ x_ID].Cmnd == NULL ) // should be RARE      {//	printk(" ABTS %Xh Scsi Cmnd null! ", x_ID);	       break;  // nothing to abort!      }//#define ABTS_DBG#ifdef ABTS_DBG      printk("INV SEST[%X] ", x_ID);       if( Exchanges->fcExchange[x_ID].status & FC2_TIMEOUT)      {        printk("FC2TO");      }      if( Exchanges->fcExchange[x_ID].status & INITIATOR_ABORT)      {        printk("IA");      }      if( Exchanges->fcExchange[x_ID].status & PORTID_CHANGED)      {        printk("PORTID");      }      if( Exchanges->fcExchange[x_ID].status & DEVICE_REMOVED)      {        printk("DEVRM");      }      if( Exchanges->fcExchange[x_ID].status & LINKFAIL_TX)      {        printk("LKF");      }      if( Exchanges->fcExchange[x_ID].status & FRAME_TO)      {        printk("FRMTO");      }      if( Exchanges->fcExchange[x_ID].status & ABORTSEQ_NOTIFY)      {        printk("ABSQ");      }      if( Exchanges->fcExchange[x_ID].status & SFQ_FRAME)      {        printk("SFQFR");      }      if( Exchanges->fcExchange[ x_ID].type == 0x2000)        printk(" WR");      else if( Exchanges->fcExchange[ x_ID].type == 0x3000)        printk(" RD");      else if( Exchanges->fcExchange[ x_ID].type == 0x10)        printk(" ABTS");      else        printk(" %Xh", Exchanges->fcExchange[ x_ID].type);       if( !(Exchanges->fcExchange[x_ID].status & INITIATOR_ABORT))      {	printk(" Cmd %p, ",           Exchanges->fcExchange[ x_ID].Cmnd);        printk(" brd/chn/trg/lun %d/%d/%d/%d port_id %06X\n",           cpqfcHBAdata->HBAnum,          Exchanges->fcExchange[ x_ID].Cmnd->channel,          Exchanges->fcExchange[ x_ID].Cmnd->target,          Exchanges->fcExchange[ x_ID].Cmnd->lun,          Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF);      }      else  // assume that Cmnd ptr is invalid on _abort()      {	printk(" Cmd ptr invalid\n");      }     #endif                  // Steps to ABORT a SEST exchange:      // 1. Freeze TL SCSI assists & ERQ (everything)      // 2. Receive FROZEN inbound CM (must succeed!)      // 3. Invalidate x_ID SEST entry       // 4. Resume TL SCSI assists & ERQ (everything)      // 5. Build/start on exchange - change "type" to BLS_ABTS,      //    timeout to X sec (RA_TOV from PLDA is actually 0)      // 6. Set Exchange Q'd status if ABTS cannot be started,      //    or simply complete Exchange in "Terminate" condition  PCI_TRACEO( x_ID, 0xB4)            // 1 & 2 . Freeze Tach & get confirmation of freeze      FrozeTach = FreezeTach( cpqfcHBAdata);      // 3. OK, Tachyon is frozen, so we can invalidate SEST exchange.      // FC2_TIMEOUT means we are originating the abort, while      // TARGET_ABORT means we are ACCepting an abort.      // LINKFAIL_TX, ABORTSEQ_NOFITY, INV_ENTRY or FRAME_TO are       // all from Tachyon:      // Exchange was corrupted by LDn or other FC physical failure      // INITIATOR_ABORT means the upper layer driver/application      // requested the abort.	        // clear bit 31 (VALid), to invalidate & take control from TL      fcChip->SEST->u[ x_ID].IWE.Hdr_Len &= 0x7FFFFFFF;      // examine and Tach's "Linked List" for IWEs that       // received (nearly) simultaneous transfer ready (XRDY)       // repair linked list if necessary (TBD!)      // (If we ignore the "Linked List", we will time out      // WRITE commands where we received the FCP-SCSI XFRDY      // frame (because Tachyon didn't processes it).  Linked List      // management should be done as an optimization.//       readl( fcChip->Registers.ReMapMemBase+TL_MEM_SEST_LINKED_LIST ));            // 4. Resume all Tachlite functions (for other open Exchanges)      // as quickly as possible to allow other exchanges to other ports      // to resume.  Freezing Tachyon may cause cascading errors, because      // any received SEST frame cannot be processed by the SEST.      // Don't "unfreeze" unless Link is operational      if( FrozeTach )  // did we just freeze it (above)?        fcChip->UnFreezeTachyon( fcChip, 2);  // both ERQ and FCP assists        PCI_TRACEO( x_ID, 0xB4)      // Note there is no confirmation that the chip is "unfrozen".  Also,      // if the Link is down when unfreeze is called, it has no effect.      // Chip will unfreeze when the Link is back up.      // 5. Now send out Abort commands if possible      // Some Aborts can't be "sent" (Port_id changed or gone);      // if the device is gone, there is no port_id to send the ABTS to.      if( !(Exchanges->fcExchange[ x_ID].status & PORTID_CHANGED)			  &&          !(Exchanges->fcExchange[ x_ID].status & DEVICE_REMOVED) )      {        Exchanges->fcExchange[ x_ID].type = BLS_ABTS;        fchs.s_id = Exchanges->fcExchange[ x_ID].fchs.d_id;        ulStatus = cpqfcTSBuildExchange(          cpqfcHBAdata,          BLS_ABTS,          &fchs,        // (uses only s_id)          NULL,         // (no scatter/gather list for ABTS)          &x_ID );// ABTS on this Exchange ID        if( !ulStatus ) // Exchange setup build OK?        {            // ABTS may be needed because an Exchange was corrupted            // by a Link disruption.  If the Link is UP, we can	    // presume that this ABTS can start immediately; otherwise,	    // set Que'd status so the Login functions            // can restart it when the FC physical Link is restored          if( ((fcChip->Registers.FMstatus.value &0xF0) &0x80)) // loop init?          {			    //                printk(" *set Q status x_ID %Xh on LDn* ", x_ID);                Exchanges->fcExchange[ x_ID].status |= EXCHANGE_QUEUED;          }          else  // what FC device (port_id) does the Cmd belong to?          {            PFC_LOGGEDIN_PORT pLoggedInPort =               Exchanges->fcExchange[ x_ID].pLoggedInPort;                        // if Port is logged in, we might start the abort.	            if( (pLoggedInPort != NULL) 			      &&                (pLoggedInPort->prli == TRUE) )             {              // it's possible that an Exchange has already been Queued              // to start after Login completes.  Check and don't	      // start it (again) here if Q'd status set//	    printk(" ABTS xchg %Xh ", x_ID);             	      if( Exchanges->fcExchange[x_ID].status & EXCHANGE_QUEUED)	      {//		    printk("already Q'd ");	      }	      else	      {//	            printk("starting ");		                fcChip->fcStats.FC2aborted++;                 ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, x_ID );                if( !ulStatus )                {                    // OK                    // submitted to Tach's Outbound Que (ERQ PI incremented)                }                else                {/*                   printk("ABTS exchange start failed -status %Xh, x_ID %Xh ",                        ulStatus, x_ID);*/                } 	      }	    }	    else	    {/*         	  printk(" ABTS NOT starting xchg %Xh, %p ",			       x_ID, pLoggedInPort);	          if( pLoggedInPort )	            printk("prli %d ", pLoggedInPort->prli);*/	    }		 	  }        }        else  // what the #@!        {  // how do we fail to build an Exchange for ABTS??              printk("ABTS exchange build failed -status %Xh, x_ID %Xh\n",                ulStatus, x_ID);        }      }      else   // abort without ABTS -- just complete exchange/Cmnd to Linux      {//            printk(" *Terminating x_ID %Xh on %Xh* ", //		    x_ID, Exchanges->fcExchange[x_ID].status);        cpqfcTSCompleteExchange( fcChip, x_ID);      }    } // end of ABTS case      break;    case BLS_ABTS_ACC:   // need to ACCept one ABTS                         // (NOTE! this code not updated for Linux yet..)            printk(" *ABTS_ACC* ");      // 1. Freeze TL      fcChip->FreezeTachyon( fcChip, 2);  // both ERQ and FCP assists      memcpy(  // copy the incoming ABTS frame        &fchs,        fcLQ->Qitem[QconsumerNdx].ulBuff, // incoming fchs        sizeof( fchs));      // 3. OK, Tachyon is frozen so we can invalidate SEST entry       // (if necessary)      // Status FC2_TIMEOUT means we are originating the abort, while      // TARGET_ABORT means we are ACCepting an abort            ExchangeID = fchs.ox_rx_id & 0x7FFF; // RX_ID for exchange//      printk("ABTS ACC for Target ExchangeID %Xh\n", ExchangeID);      // sanity check on received ExchangeID      if( Exchanges->fcExchange[ ExchangeID].status == TARGET_ABORT )      {          // clear bit 31 (VALid), to invalidate & take control from TL//          printk("Invalidating SEST exchange %Xh\n", ExchangeID);          fcChip->SEST->u[ ExchangeID].IWE.Hdr_Len &= 0x7FFFFFFF;      }      // 4. Resume all Tachlite functions (for other open Exchanges)      // as quickly as possible to allow other exchanges to other ports      // to resume.  Freezing Tachyon for too long may royally screw      // up everything!      fcChip->UnFreezeTachyon( fcChip, 2);  // both ERQ and FCP assists            // Note there is no confirmation that the chip is "unfrozen".  Also,      // if the Link is down when unfreeze is called, it has no effect.      // Chip will unfreeze when the Link is back up.      // 5. Now send out Abort ACC reply for this exchange      Exchanges->fcExchange[ ExchangeID].type = BLS_ABTS_ACC;            fchs.s_id = Exchanges->fcExchange[ ExchangeID].fchs.d_id;      ulStatus = cpqfcTSBuildExchange(            cpqfcHBAdata,            BLS_ABTS_ACC,            &fchs,            NULL,         // no data (no scatter/gather list)            &ExchangeID );// fcController->fcExchanges index, -1 if failed      if( !ulStatus ) // Exchange setup?      {        ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID );        if( !ulStatus )        {          // submitted to Tach's Outbound Que (ERQ PI incremented)          // waited for completion for ELS type (Login frames issued          // synchronously)        }        else          // check reason for Exchange not being started - we might          // want to Queue and start later, or fail with error        {        }       }      break;    case BLS_ABTS_RJT:   // need to ReJecT one ABTS; reject implies the                         // exchange doesn't exist in the TARGET context.                         // ExchangeID has to come from LinkService space.      printk(" *ABTS_RJT* ");      ulStatus = cpqfcTSBuildExchange(            cpqfcHBAdata,            BLS_ABTS_RJT,            (TachFCHDR_GCMND*)              fcLQ->Qitem[QconsumerNdx].ulBuff, // incoming fchs            NULL,         // no data (no scatter/gather list)            &ExchangeID );// fcController->fcExchanges index, -1 if failed      if( !ulStatus ) // Exchange setup OK?      {        ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID );        // If it fails, we aren't required to retry.      }      if( ulStatus )      {        printk("Failed to send BLS_RJT for ABTS, X_ID %Xh\n", ExchangeID);      }      else      {        printk("Sent BLS_RJT for ABTS, X_ID %Xh\n", ExchangeID);            }      break;    default:      break;  }                   // end switch//doNothing:    // done with this item - now set the NEXT index  if( QconsumerNdx+1 >= FC_LINKQ_DEPTH ) // rollover test  {    fcLQ->consumer = 0;  }  else  {     fcLQ->consumer++;  }  PCI_TRACEO( fcLQ->Qitem[QconsumerNdx].Type, 0x94)  LEAVE("WorkTask");  return;}// When Tachyon reports link down, bad al_pa, or Link Service (e.g. Login)// commands come in, post to the LinkQ so that action can be taken outside the// interrupt handler.  // This circular Q works like Tachyon's que - the producer points to the next// (unused) entry.  Called by Interrupt handler, WorkerThread, Timer// sputlinkqvoid cpqfcTSPutLinkQue( CPQFCHBA *cpqfcHBAdata,  int Type,   void *QueContent){

⌨️ 快捷键说明

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