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