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

📄 nsmdiag.c

📁 NATIONAL公司DP83816芯片Linux下驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
         {
            NSM_DBG(DBG_ERR,("SKB alloc in fragSetupTx Failed! \n"));
            break;
         }

         // Mark as being used by this device.
         skb->dev = adapter->netdev;

         // Set the Fragment
         pFrag->pAddr = skb->data;
         pFrag->pNsmPrivate = skb;

         // Set link
         if (prevFrag)
         {
            prevFrag->pNextFrag = pFrag;
         }
         prevFrag = pFrag;

         pFrag++;
      }
 
      // Note Head and Tail of this frag list
      // Note: If the skb allocation fails above then the Tail will point to
      //       the last fragment with successful allocation
      adapter->txFrags     = allocMem; 
      adapter->txFragsHead = (MPL_PKT_FRAG *)allocMem; 
      adapter->txFragsTail = prevFrag;

      if (prevFrag)
      {
         // Managed to allocate some buffers
         prevFrag->pNextFrag = NULL;
         ret = NS_TRUE;
      }
   }

   NO(setupTxFrags);
   return ret;
}


//*****************************************************************************
//   freeTxFrags
//     Free the MPL frags for Tx
//
//   Parameters
//      adapter
//         NSM Context
//   Return Value
//      None
//*****************************************************************************
static NS_VOID
freeTxFrags(
      NSM_CONTEXT *adapter)
{
   struct pci_dev *pdev = adapter->pdev;
   MPL_PKT_FRAG *pFrag = NULL;
   struct sk_buff* skb;

   NI(freeTxFrags);

   // Free attached buffers
   pFrag = adapter->txFragsHead;
   while (pFrag)
   {
      skb = (struct sk_buff *)pFrag->pNsmPrivate;
      if (skb != NULL)
      {
         // UnMap and Free the sk buffs
         pci_unmap_single(pdev, (dma_addr_t)pFrag->physAddr,
                          adapter->txBufferLen, 
                          PCI_DMA_TODEVICE);
         dev_kfree_skb(skb);
         pFrag->pNsmPrivate = NULL;
      }

      // Move to the next fragment
      pFrag = pFrag->pNextFrag;
   }

   // Free Frag memory
   if (adapter->txFrags)
   {
      kfree(adapter->txFrags);
      adapter->txFrags = NULL;
      adapter->txFragsHead = NULL;
   }

   NO(freeTxFrags);
   return;
}

//*****************************************************************************
//   pktSetup
//     Setup the Diag Pkts Status Queue for Tx and Rx completion handling
//
//   Parameters
//      adapter
//         NSM Context
//   Return Value
//      NS_TRUE : Setup was successful
//      NS_FALSE : Setup failed
//*****************************************************************************
static NS_BOOLEAN
pktSetup(
      NSM_CONTEXT *adapter)
{
   NS_UINT allocSize, i, nodes;
   NS_VOID *allocMem;
   NS_BOOLEAN ret = NS_FALSE;
   DIAG_PKT *pPkt;

   NI(pktSetup);

   // Allocate memory for the pkts = both for tx and rx
   nodes = adapter->diagStsQueueSize * 2;
            
   allocSize = sizeof(DIAG_PKT) * nodes;
   allocMem  = kmalloc(allocSize, GFP_KERNEL);
   if (allocMem == NULL)
   {
      NSM_DBG(DBG_ERR,("Failed to Alloc mem to diag pkts \n"));
      NO(pktSetup);
      return ret;
   }
   else
   {
      // Note mem
      adapter->diagPkts = allocMem; 

      // Zero up the memory
      memset((void *)(allocMem), 0x0, allocSize);
      pPkt = (DIAG_PKT *) allocMem;

      // Initialize Diag packet free list 
      MplListInit(&adapter->diagFreeList, NS_FALSE);

      // Add nodes to the list
      for (i = 0x0; i < nodes; i++)
      {
         MplListAddTail(&adapter->diagFreeList, &pPkt->link);
         pPkt++; //Get the next packet
      }
      
      // Initialize Diag packet done list (for Tx) - Starts with no nodes
      MplListInit(&adapter->diagTxDoneList, NS_FALSE);

      // Initialize Diag packet done list (for Rx) - Starts with no nodes
      MplListInit(&adapter->diagRxDoneList, NS_FALSE);

      ret = NS_TRUE;
   }

   NO(pktSetup);
   return ret;
}


//*****************************************************************************
//   pktFree
//     Free the diag packets in status queue
//
//   Parameters
//      adapter
//         NSM Context
//   Return Value
//      None
//*****************************************************************************
static NS_VOID
pktFree(
      NSM_CONTEXT *adapter)
{
   NI(pktFree);

   // Clear Tx done list
   NsmDiagProcessDoneList(adapter, 0x0, NS_FALSE,
                     &adapter->diagTxDoneList, &adapter->txFragsTail);

   // Clear Rx done list
   NsmDiagProcessDoneList(adapter, 0x0, NS_FALSE, 
                     &adapter->diagRxDoneList, &adapter->rxFragsTail);

   // UnInitialize Diag packet done list (for Tx)
   MplListDeInit(&adapter->diagTxDoneList);

   // UnInitialize Diag packet done list (for Rx)
   MplListDeInit(&adapter->diagRxDoneList);

   // UnInitialize Diag packet free list
   MplListDeInit(&adapter->diagFreeList);

   // Free Pkt memory
   if (adapter->diagPkts)
   {
      kfree(adapter->diagPkts);
      adapter->diagPkts = NULL;
   }

   NO(pktFree);
   return;
}


//*****************************************************************************
//   txPkt
//     Diag module tx 
//
//   Parameters
//      adapter
//         NSM Context
//     txCmd
//         Command block describing the Tx
//     txData
//         Data block for this Tx
//
//   Return Value
//      NS_STATUS_SUCCESS
//         The initialization was successfully done
//      NS_STATUS_RESOURCES
//         Failed to allocate required resources
//      NS_STATUS_FAILURE
//         Failed to transmit
//*****************************************************************************
static NS_UINT
   txPkt(
      NSM_CONTEXT     *adapter,
      NS_APP_XFER_CMD *txCmd,
      NS_UINT8        *txData)
{
   MPL_PKT_FRAG *pFrag, *headFrag, *prevFrag, *qFrag;
   MPL_PKT mplPkt;
   NS_UINT status, fragsReq, bytesToGo, src, fragCnt, i;

   NI(txPkt);

   // Test if the link is up and the diag tx engine is initialized
   if ((adapter->linkStatus != MPL_LINK_STATUS_UP) ||
         (adapter->txFragsHead == NULL))
   {
      NO(txPkt);
      return NS_STATUS_FAILURE;
   }

   if (txCmd->packetSize == 0x0)
   {
      // What?
      NO(txPkt);
      return NS_STATUS_INVALID_PARM;
   }

   // Compute the number of frags needed
   fragsReq = (txCmd->packetSize + adapter->txBufferLen - 1) /
                                      adapter->txBufferLen;

   // Make sure we have enough frags to sent this pkt
   //  if not force some from the done list
   spin_lock_irq(&adapter->txLock);
   while(checkAvailTxFrag(adapter, fragsReq) != NS_TRUE)
   {
      // Force some frags from the Done list
      NsmDiagProcessDoneList(adapter, 0x1, NS_TRUE,
                          &adapter->diagTxDoneList, &adapter->txFragsTail);
   }
   spin_unlock_irq(&adapter->txLock);

   // Setup the frags
   headFrag = pFrag = adapter->txFragsHead;
   headFrag->pPacketHndl = (NS_VOID *)txCmd->pktHandle;

   // Initialize byte counters
   bytesToGo = txCmd->packetSize;
   src  = 0x0;
   prevFrag = NULL;
      
   while (bytesToGo)
   {
      if (adapter->txBufferLen >= bytesToGo)
      {
         // Final MPL Frag 
         pFrag->fragSize = bytesToGo;
      }
      else
      {
         // More data to go.. Map as much data as allowed and move on
         pFrag->fragSize  = adapter->txBufferLen;
      }
       
      // Set the frag, copy data to frag
      if (copy_from_user(pFrag->pAddr, &txData[src], pFrag->fragSize))
      {
         return NS_STATUS_FAILURE;
      }
      pFrag->physAddr  = pci_map_single(adapter->pdev, pFrag->pAddr, 
                                             pFrag->fragSize, PCI_DMA_TODEVICE);

      // Reduce bytes to go by the size copied
      bytesToGo -= pFrag->fragSize;

      // Note the current frag
      prevFrag = pFrag;

      // Update data offset
      src += pFrag->fragSize;

      // Get a new frag
      pFrag = pFrag->pNextFrag;
   }

   // Prep the MPL pkt
   mplPkt.pNextPacket = NULL;
   mplPkt.fragCount = fragsReq;

   // Set priority after validating
   if ((txCmd->pQueue < 0x1) || 
          (txCmd->pQueue > adapter->mplCaps.txCaps.priorityQCnt))
   {
      // Default to queue 1 - This is returned back to App
      txCmd->pQueue = 0x1;
   }

   mplPkt.txOOB.pQueue = txCmd->pQueue;
   mplPkt.pFragHead = headFrag;
   mplPkt.packetSize  = txCmd->packetSize;
   mplPkt.pNsmPrivate = headFrag; // Head frag as handle

   // Send Packet
   spin_lock_irq(&adapter->txLock);
   status = MplTransmit(adapter->mplContext, 0x01, &mplPkt);

   // Check status
   if (status == NS_STATUS_SUCCESS)
   {
      // Prep for returning status of this packet
      // Partial status is also returned back to the App to handle
      //  cases where the Tx never completes

      txCmd->numDesc = mplPkt.fragCount;

      // Copy physical address used for this transfer
      qFrag = headFrag;
      fragCnt  = (mplPkt.fragCount < NS_APP_MAX_FRAG_INFO) ?
                        mplPkt.fragCount : NS_APP_MAX_FRAG_INFO;
      for (i = 0x0; i < fragCnt; i++)
      {
         txCmd->descPhyAddr[i] = (NS_ADDR)qFrag->pMplPrivate;
         txCmd->bufPhyAddr[i]  = qFrag->physAddr;
         qFrag = qFrag->pNextFrag;
      }

      // Move the headFrag pointer - this update happens only on Tx success
      adapter->txFragsHead = pFrag;
      prevFrag->pNextFrag = NULL; // Detach frags for current pkt
   }

   // Release lock
   spin_unlock_irq(&adapter->txLock);

   NO(txPkt);
   return status;
}

//*****************************************************************************
//   checkAvailTxFrag
//     Check is the required Tx Frags are available for transmiting this pkt
//
//   Parameters
//      adapter
//         NSM Context
//      reqFrags
//         Number of frags required
//
//   Return Value
//      NS_TRUE
//         Available
//      NS_FALSE
//         Not Available
//*****************************************************************************
static NS_BOOLEAN
   checkAvailTxFrag(
      NSM_CONTEXT     *adapter,
      NS_UINT          reqFrags)
{
   NS_UINT cnt = 0x0;
   MPL_PKT_FRAG *pFrag;

   NI(checkAvailTxFrag);   

   pFrag = adapter->txFragsHead;
   while (cnt < reqFrags)
   { 
      if (pFrag == adapter->txFragsTail)
      {
         NO(checkAvailTxFrag);   
         return NS_FALSE;
      }
      pFrag = pFrag->pNextFrag;
      cnt++;
   }

   NO(checkAvailTxFrag);   
   return NS_TRUE;
}

//*****************************************************************************
//   pktStatus
//     Checks the status of previous Tx pkt
//
//   Parameters
//     adapter
//         NSM Context
//     pList
//         List to process from
//     ppTailFrag
//         Pointer to a frag pointer at which to append the freed frags
//     pLock
//         Pointer to the lock controlling access to parent list
//     pCmd
//         Command block describing the pkt
//     pData
//         Destination location to copy data

⌨️ 快捷键说明

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