📄 nsmos.c
字号:
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 + -