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

📄 nsmos.c

📁 NATIONAL公司DP83816芯片Linux下驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
   txCfg.priorityQueueCnt = adapter->txQCnt;
   for (i = 0x0; i < adapter->txQCnt; i++)
   {
      txCfg.descCnt[i]   = adapter->txdCnt; //FM: Multiple Qs, diff txds?
   }

   // Maximum indications on Tx completions
   txCfg.maxIndications  = NSM_DEFAULT_TX_MAX_INDY;

   if (adapter->opMode == MPL_MODE_NORMAL)
   {
      // Transmit Engine - Not End User configurable Value (atleast initially)
      txCfg.fillThreshold   = NSM_DEFAULT_TX_FILL_THOLD;
      txCfg.drainThreshold  = NSM_DEFAULT_TX_DRAIN_THOLD;
      txCfg.maxDmaBurst     = NSM_DEFAULT_TX_MAX_DMA;

      txCfg.cfgFlags = MPL_TRANSMIT_CFG_FIFO |
                         MPL_TRANSMIT_CFG_QUEUES |
                           MPL_TRANSMIT_CFG_AUTO_PAD;
   }
   else
   {
      // In diag mode only set the Txd ring - No FIFO setup
      txCfg.cfgFlags = MPL_TRANSMIT_CFG_QUEUES;
   }

   // Let MPL do the setup
   status = MplTransmitCfg(adapter->mplContext, &txCfg);

   if (status != NS_STATUS_SUCCESS)
   {
      NSM_DBG(DBG_ERR,("Tx Config Failed \n"));
      NO(configMac);
      return NS_FALSE;
   }

   // Receive Engine - End User (driver load or UI) configurable
   rxCfg.priorityQueueCnt = adapter->rxQCnt;
   for (i = 0x0; i < adapter->rxQCnt; i++)
   {
      rxCfg.descCnt[i]   = adapter->rxdCnt; //FM: Multiple Qs, diff txds?
   }

   // Maximum indications on Rx completions
   rxCfg.maxIndications  = NSM_DEFAULT_RX_MAX_INDY;

   if (adapter->opMode == MPL_MODE_NORMAL)
   {
      // Receive Engine - Not End User configurable Value (atleast initially)
      rxCfg.drainThreshold  = NSM_DEFAULT_RX_DRAIN_THOLD;
      rxCfg.maxDmaBurst     = NSM_DEFAULT_RX_MAX_DMA;

      rxCfg.cfgFlags        = MPL_RECEIVE_CFG_FIFO |
                               MPL_RECEIVE_CFG_QUEUES;
   }
   else
   {
      rxCfg.cfgFlags        = MPL_RECEIVE_CFG_QUEUES;
   }

   // Let MPL do the setup
   status = MplReceiveCfg(adapter->mplContext, &rxCfg);
   if (status != NS_STATUS_SUCCESS)
   {
      NSM_DBG(DBG_ERR,("Rx Config Failed \n"));
      NO(configMac);
      return NS_FALSE;
   }

   // Configure Max MTU
   status = MplCfgMTU (adapter->mplContext, adapter->mtu);
   if (status != NS_STATUS_SUCCESS)
   {
      NSM_DBG(DBG_ERR,("MTU Config Failed \n"));
      NO(configMac);
      return NS_FALSE;
   }

   // Interrupt
   MplInterruptCfg(adapter->mplContext, 
                    adapter->timerHold, adapter->txHold, adapter->rxHold);

   NO(configMac);
   return NS_TRUE;
}

static NS_BOOLEAN
configLink(NSM_CONTEXT *adapter)
{
   MPL_STATUS status;
   MPL_LINK_CFG linkCfg;
   NS_BOOLEAN ret = NS_TRUE;

   NI(configLink);

   memset((void *)&linkCfg, 0x0, sizeof(linkCfg));

   // MPL Link APIs are non-reentrant
   spin_lock_irq(&adapter->linkLock);

   // Report Net stack that the link is down - since it is being set
   netif_carrier_off(adapter->netdev);

   // Link
   linkCfg.mode   = adapter->linkMode;
   linkCfg.speed  = adapter->linkSpeed;
   linkCfg.duplex = adapter->linkDuplex;

   // Pause configuration
   linkCfg.pauseType = adapter->linkPause;
   if (linkCfg.pauseType & MPL_LINK_PAUSE_TRANSMIT)
   {
      // For pause transmits specify the threshold
      linkCfg.pauseCtr    = NSM_DEFAULT_LINK_PAUSE_COUNTER;
      linkCfg.pauseRxDALO = NSM_DEFAULT_LINK_PAUSE_DALO; // Data FIFO Hi
      linkCfg.pauseRxDAHI = NSM_DEFAULT_LINK_PAUSE_DAHI; // Data FIFO Hi
      linkCfg.pauseRxSTLO = NSM_DEFAULT_LINK_PAUSE_STHI; // Status FIFO Hi
      linkCfg.pauseRxSTHI = NSM_DEFAULT_LINK_PAUSE_STHI; // Status FIFO Hi
   }

   // Tell MPL to configure the link
   status = MplLinkCfg(adapter->mplContext, &linkCfg);
   if (status == NS_STATUS_SUCCESS)
   {
       // The existing link matches our needs - Complete the Setup
       if (MplLinkUpComplete(adapter->mplContext) == NS_STATUS_SUCCESS)
       {
          NSM_DBG(DBG_TMP,("Link is UP \n"));

          adapter->linkStatus = MPL_LINK_STATUS_UP;

          // Indicate Upper layers to start Tx and Rx for this adapter
          // If previously reported a Link down - Report AOK now
          //  This is only in normal mode
          if (adapter->opMode == MPL_MODE_NORMAL)
          {
             if (!netif_carrier_ok(adapter->netdev))
             {
                netif_carrier_on(adapter->netdev);
                netif_start_queue(adapter->netdev);
             }    
          }
       }
       else
       {
           NSM_DBG(DBG_ERR,("Link Config Failed \n"));

           adapter->linkStatus = MPL_LINK_STATUS_DOWN;
           ret = NS_FALSE;
       }
   }
   else if (status == NS_STATUS_ASYNCH_COMPLETION)
        {
           NSM_DBG(DBG_TMP,("Link is being Pursued \n"));
           adapter->linkStatus = MPL_LINK_STATUS_ACTIVE;
        }
        else 
        {
           adapter->linkStatus = MPL_LINK_STATUS_DOWN;
           NSM_DBG(DBG_ERR,("Link Config Failed \n"));
           ret = NS_FALSE;
        }

   spin_unlock_irq(&adapter->linkLock);
   NO(configLink);
   return ret;
}

NS_BOOLEAN
setupRxFrags(NSM_CONTEXT *adapter)
{
   NS_UINT allocSize, i, nodes;
   MPL_PKT_FRAG *pFrag = NULL;
   NS_VOID *allocMem;

   NI(setupRxFrags);

   // Allocate memory for the frags
   // The one additional fragment will ensure no race condition
   //  between the consumer (Replenish Task) and Producer (RxDone)
   nodes = adapter->rxdCnt + 1;

#ifdef NSM_DIAG_MODE
   // Additional nodes to handle rx completion queuing
   nodes += adapter->diagStsQueueSize;
#endif //NSM_DIAG_MODE

   allocSize = sizeof(MPL_PKT_FRAG) * nodes;
   allocMem  = kmalloc(allocSize, GFP_KERNEL);

   if (allocMem == NULL)
   {
      NSM_DBG(DBG_ERR,("Failed to Alloc mem to rx frags \n"));
      NO(setupRxFrags);
      return NS_FALSE;
   }
   else
   {
      // Zero up the memory
      memset((void *)(allocMem), 0x0, allocSize);

      pFrag = (MPL_PKT_FRAG *) allocMem;

      // Create linked list
      for (i = 0x0; i < (nodes - 1); i++)
      {
         // Set link
         pFrag->pNextFrag = (pFrag + 1);
         pFrag++;
      }
 
      // Last node has next NULL
      pFrag->pNextFrag = NULL;
 
      // Note Head and Tail of this frag list
      adapter->rxFrags     = allocMem; 
      adapter->rxFragsHead = (MPL_PKT_FRAG *)allocMem; 
      adapter->rxFragsTail = pFrag;
   }

   NO(setupRxFrags);
   return NS_TRUE;
}

NS_VOID
freeRxFrags(NSM_CONTEXT *adapter)
{
   struct pci_dev *pdev = adapter->pdev;
   MPL_PKT_FRAG *pFrag = NULL;
   struct sk_buff* skb;

   NI(freeRxFrags);

   // Free attached buffers
   pFrag = adapter->rxFragsHead;
   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->rxBufferLen, 
                          PCI_DMA_FROMDEVICE);
         dev_kfree_skb(skb);
         pFrag->pNsmPrivate = NULL;
      }

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

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

   NO(freeRxFrags);
   return;
}

NS_VOID
replenishTask(unsigned long data)
{
   NSM_CONTEXT *adapter = (NSM_CONTEXT *)data;
   MPL_PKT_FRAG *pFrag = NULL, *pFragsToMpl = NULL;
   struct sk_buff* skb;
   NS_UINT i, rxdsEmpty, bufCnt = 0x0;

   // Note: This function needs to be called from Intr context
   //       This function is non-reenterant
   NI(replenishTask);

   MplReceiveGetEmptyDesc(adapter->mplContext, adapter->rxQCnt , &rxdsEmpty);

   if (rxdsEmpty == 0x0)
   {
      NO(replenishTask);
      return;
   }

#ifdef NSM_DIAG_MODE
   // While in diag mode, there is a chance that we might run out of
   //  fragments in the free list, while waiting for the app to come
   //  get the packets from us - If we enter this situation then force
   //  a packet from the Rx done list to free some frags
   if (adapter->rxFragsHead == adapter->rxFragsTail)
   {
      NsmDiagProcessDoneList(adapter, 0x1, NS_TRUE, 
                              &adapter->diagRxDoneList, &adapter->rxFragsTail);
   }
#endif //NSM_DIAG_MODE

   // Allocate the required number of buffers
   pFrag = adapter->rxFragsHead;
   for (i = 0x0; i < rxdsEmpty; i++)
   {
#ifdef NSM_DIAG_MODE
      if ( pFrag == adapter->rxFragsTail)
      {
         // Better luck next time
         break;
      }
#endif //NSM_DIAG_MODE

      // Check if this frag need a new SKB
      if (pFrag->pNsmPrivate == NULL)
      {
         // Allocate Skb
         skb = dev_alloc_skb(adapter->rxBufferLen);
         if (skb == NULL)
         {
            NSM_DBG(DBG_ERR,("SKB alloc in Repl Failed! \n"));

            // Better luck next time
            break;
         }
         else
         { 
            // Mark as being used by this device.
            skb->dev = adapter->netdev;
         }

         // Map the Skb buffer
         pFrag->physAddr  = pci_map_single(adapter->pdev, 
                                skb->tail, adapter->rxBufferLen, 
                                PCI_DMA_FROMDEVICE);

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

      // Set the size of the buffer
      pFrag->fragSize = adapter->rxBufferLen;

      // Get the next frag
      pFrag = pFrag->pNextFrag;

      bufCnt++;
   }

   // Check if we managed to allocate new buffers
   if (bufCnt != 0x0)
   {
      pFragsToMpl = adapter->rxFragsHead;

      // Report new buffers to MPL
      MplReceiveReplenish(adapter->mplContext, bufCnt, &pFragsToMpl);

      // Check if MPL returned back some buffers
      if (pFragsToMpl != adapter->rxFragsHead)
      {
         // Move Head to the returned list
         adapter->rxFragsHead = pFragsToMpl;
      }
      else
      {
         // Move Head to the next frag on the cache
         adapter->rxFragsHead = pFrag;
      }
   }

   NO(replenishTask);
   return;
}

static NS_VOID
linkTask(unsigned long data)
{
   NSM_CONTEXT *adapter = (NSM_CONTEXT *)data;
   MPL_LINK_STATUS linkStatus;

   NI(linkTask);

   // MPL Link APIs are non-reentrant
   spin_lock_irq(&adapter->linkLock);

   // Get the current Link State
   linkStatus = MplLinkProcessChange(adapter->mplContext);

   switch (linkStatus) 
   {
      case MPL_LINK_STATUS_UP:

          // Let MPL finish up the Linking process
          if (MplLinkUpComplete(adapter->mplContext) == NS_STATUS_SUCCESS)
          {
             NSM_DBG(DBG_TMP,("Link is UP \n"));
             adapter->linkStatus = MPL_LINK_STATUS_UP;

             // If previously reported a Link down - Report AOK now
             //  This is only in normal mode
             if (adapter->opMode == MPL_MODE_NORMAL)
             {
                if (!netif_carrier_ok(adapter->netdev))
                {
                   netif_carrier_on(adapter->netdev);
                   netif_start_queue(adapter->netdev);
                }    
             }
          }

          break;

      case MPL_LINK_STATUS_ACTIVE:

          NSM_DBG(DBG_TMP,("Link is Actively Pursued \n"));
          adapter->linkStatus = MPL_LINK_STATUS_ACTIVE;

          // Reschedule this task after a brief delay
          mdelay(5); //FM: Eval
          tasklet_schedule(&adapter->linkMonTask);
          break;

      case MPL_LINK_STATUS_DOWN:

          NSM_DBG(DBG_TMP,("Link is Down \n"));
          adapter->linkStatus = MPL_LINK_STATUS_DOWN;

          // If previously reported a Link Up- Report down now
          if (netif_carrier_ok(adapter->netdev))
          {
             netif_carrier_off(adapter->netdev);
             netif_stop_queue(adapter->netdev);
          } 
          break;

    default:
          break;
    }

   spin_unlock_irq(&adapter->linkLock);

   NO(linkTask);
   return;
}

⌨️ 快捷键说明

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