Staging: sxg: SXG SGL related cleanup in data structures and code
authorMithlesh Thukral <mithlesh@linsyssoft.com>
Mon, 19 Jan 2009 14:53:22 +0000 (20:23 +0530)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 3 Apr 2009 21:53:10 +0000 (14:53 -0700)
* Cleanup in allocation of SXG_SGLs.
* Locking issues related to SglQLock.
* XmtCmd and XmtZeroLock consistency fixes.

Signed-off-by: LinSysSoft Sahara Team <saharaproj@linsyssoft.com>
Signed-off-by: Christopher Harrer <charrer@alacritech.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/sxg/sxg.c
drivers/staging/sxg/sxg.h
drivers/staging/sxg/sxg_ethtool.c
drivers/staging/sxg/sxghif.h

index 80e84768da125fbed629313f02c26955b5236374..b8e0e2b7360a43cf9c8eabf9cc1f56903cd73f09 100644 (file)
@@ -95,13 +95,13 @@ static int sxg_entry_halt(struct net_device *dev);
 static int sxg_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int sxg_send_packets(struct sk_buff *skb, struct net_device *dev);
 static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb);
-static void sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
+static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
                                struct sxg_scatter_gather *SxgSgl);
 
 static void sxg_handle_interrupt(struct adapter_t *adapter);
 static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId);
 static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId);
-static void sxg_complete_slow_send(struct adapter_t *adapter);
+static void sxg_complete_slow_send(struct adapter_t *adapter, int irq_context);
 static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter,
                                        struct sxg_event *Event);
 static void sxg_process_rcv_error(struct adapter_t *adapter, u32 ErrorStatus);
@@ -112,8 +112,12 @@ static bool sxg_mac_filter(struct adapter_t *adapter,
 static struct net_device_stats *sxg_get_stats(struct net_device *dev);
 #endif
 
-void SxgFreeResources(struct adapter_t *adapter);
-void SxgFreeRcvBlocks(struct adapter_t *adapter);
+void sxg_free_resources(struct adapter_t *adapter);
+void sxg_free_rcvblocks(struct adapter_t *adapter);
+void sxg_free_sgl_buffers(struct adapter_t *adapter);
+void sxg_unmap_resources(struct adapter_t *adapter);
+void sxg_free_mcast_addrs(struct adapter_t *adapter);
+void sxg_collect_statistics(struct adapter_t *adapter);
 
 #define XXXTODO 0
 
@@ -505,6 +509,12 @@ static int sxg_allocate_resources(struct adapter_t *adapter)
                        goto per_tcb_allocation_failed;
                }
                memset(adapter->RcvRings, 0, sizeof(struct sxg_rcv_ring) * 1);
+               adapter->ucode_stats = kzalloc(sizeof(struct sxg_ucode_stats), GFP_ATOMIC);
+               adapter->pucode_stats = pci_map_single(adapter->pcidev,
+                                               adapter->ucode_stats,
+                                               sizeof(struct sxg_ucode_stats),
+                                               PCI_DMA_FROMDEVICE);
+//             memset(adapter->ucode_stats, 0, sizeof(struct sxg_ucode_stats));
                break;
 
              per_tcb_allocation_failed:
@@ -524,6 +534,13 @@ static int sxg_allocate_resources(struct adapter_t *adapter)
                        adapter->RcvRings = NULL;
                }
                /* Loop around and try again.... */
+               if (adapter->ucode_stats) {
+                       pci_unmap_single(adapter->pcidev,
+                                       sizeof(struct sxg_ucode_stats),
+                                       adapter->pucode_stats, PCI_DMA_FROMDEVICE);
+                       adapter->ucode_stats = NULL;
+               }
+
        }
 
        DBG_ERROR("%s Initialize RCV ZERO and XMT ZERO rings\n", __func__);
@@ -1213,7 +1230,7 @@ static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId)
        }
        /* Slowpath send completions */
        if (Isr & SXG_ISR_SPSEND) {
-               sxg_complete_slow_send(adapter);
+               sxg_complete_slow_send(adapter, 1);
        }
        /* Dump */
        if (Isr & SXG_ISR_UPC) {
@@ -1400,27 +1417,37 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId)
  *
  * Arguments -
  *     adapter         - A pointer to our adapter structure
-
+ *     irq_context     - An integer to denote if we are in interrupt context
  * Return
  *     None
  */
-static void sxg_complete_slow_send(struct adapter_t *adapter)
+static void sxg_complete_slow_send(struct adapter_t *adapter, int irq_context)
 {
        struct sxg_xmt_ring *XmtRing = &adapter->XmtRings[0];
        struct sxg_ring_info *XmtRingInfo = &adapter->XmtRingZeroInfo;
        u32 *ContextType;
        struct sxg_cmd *XmtCmd;
+       unsigned long flags;
+       unsigned long sgl_flags;
+       unsigned int processed_count = 0;
 
        /*
         * NOTE - This lock is dropped and regrabbed in this loop.
         * This means two different processors can both be running/
         * through this loop. Be *very* careful.
         */
-       spin_lock(&adapter->XmtZeroLock);
+       if(irq_context) {
+               if(!spin_trylock(&adapter->XmtZeroLock))
+                       goto lock_busy;
+       }
+       else
+               spin_lock_irqsave(&adapter->XmtZeroLock, flags);
+
        SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpSnds",
                  adapter, XmtRingInfo->Head, XmtRingInfo->Tail, 0);
 
-       while (XmtRingInfo->Tail != *adapter->XmtRingZeroIndex) {
+       while ((XmtRingInfo->Tail != *adapter->XmtRingZeroIndex)
+               && processed_count++ < SXG_COMPLETE_SLOW_SEND_LIMIT)  {
                /*
                 * Locate the current Cmd (ring descriptor entry), and
                 * associated SGL, and advance the tail
@@ -1438,10 +1465,14 @@ static void sxg_complete_slow_send(struct adapter_t *adapter)
                                struct sk_buff *skb;
                                struct sxg_scatter_gather *SxgSgl =
                                        (struct sxg_scatter_gather *)ContextType;
+                               dma64_addr_t FirstSgeAddress;
+                               u32 FirstSgeLength;
 
                                /* Dumb-nic send.  Command context is the dumb-nic SGL */
                                skb = (struct sk_buff *)ContextType;
                                skb = SxgSgl->DumbPacket;
+                               FirstSgeAddress = XmtCmd->Buffer.FirstSgeAddress;
+                               FirstSgeLength = XmtCmd->Buffer.FirstSgeLength;
                                /* Complete the send */
                                SXG_TRACE(TRACE_SXG, SxgTraceBuffer,
                                          TRACE_IMPORTANT, "DmSndCmp", skb, 0,
@@ -1456,17 +1487,36 @@ static void sxg_complete_slow_send(struct adapter_t *adapter)
                                 * chimney send, which results in a double trip
                                 * in SxgTcpOuput
                                 */
-                               spin_unlock(&adapter->XmtZeroLock);
-                               SXG_COMPLETE_DUMB_SEND(adapter, skb);
+                               if(irq_context)
+                                       spin_unlock(&adapter->XmtZeroLock);
+                               else
+                                       spin_unlock_irqrestore(
+                                               &adapter->XmtZeroLock, flags);
+
+                               SxgSgl->DumbPacket = NULL;
+                               SXG_COMPLETE_DUMB_SEND(adapter, skb,
+                                                       FirstSgeAddress,
+                                                       FirstSgeLength);
+                               SXG_FREE_SGL_BUFFER(adapter, SxgSgl, NULL,
+                                               irq_context);
                                /* and reacquire.. */
-                               spin_lock(&adapter->XmtZeroLock);
+                               if(irq_context) {
+                                       if(!spin_trylock(&adapter->XmtZeroLock))
+                                               goto lock_busy;
+                               }
+                               else
+                                       spin_lock_irqsave(&adapter->XmtZeroLock, flags);
                        }
                        break;
                default:
                        ASSERT(0);
                }
        }
-       spin_unlock(&adapter->XmtZeroLock);
+       if(irq_context)
+               spin_unlock(&adapter->XmtZeroLock);
+       else
+               spin_unlock_irqrestore(&adapter->XmtZeroLock, flags);
+lock_busy:
        SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpSnd",
                  adapter, XmtRingInfo->Head, XmtRingInfo->Tail, 0);
 }
@@ -1486,8 +1536,14 @@ static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter,
        u32 BufferSize = adapter->ReceiveBufferSize;
        struct sxg_rcv_data_buffer_hdr *RcvDataBufferHdr;
        struct sk_buff *Packet;
+       static int read_counter = 0;
 
        RcvDataBufferHdr = (struct sxg_rcv_data_buffer_hdr *) Event->HostHandle;
+       if(read_counter++ & 0x100)
+       {
+               sxg_collect_statistics(adapter);
+               read_counter = 0;
+       }
        ASSERT(RcvDataBufferHdr);
        ASSERT(RcvDataBufferHdr->State == SXG_BUFFER_ONCARD);
        SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "SlowRcv", Event,
@@ -1560,12 +1616,13 @@ static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter,
                  RcvDataBufferHdr, Packet, Event->Length, 0);
        /* Lastly adjust the receive packet length. */
        RcvDataBufferHdr->SxgDumbRcvPacket = NULL;
+       RcvDataBufferHdr->PhysicalAddress = NULL;
        SXG_ALLOCATE_RCV_PACKET(adapter, RcvDataBufferHdr, BufferSize);
        if (RcvDataBufferHdr->skb)
        {
                spin_lock(&adapter->RcvQLock);
                SXG_FREE_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr);
-               adapter->RcvBuffersOnCard ++;
+               // adapter->RcvBuffersOnCard ++;
                spin_unlock(&adapter->RcvQLock);
        }
        return (Packet);
@@ -1911,20 +1968,17 @@ static void __devexit sxg_entry_remove(struct pci_dev *pcidev)
        u32 mmio_start = 0;
        unsigned int mmio_len = 0;
        struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev);
-
+/*
        set_bit(ADAPT_DOWN, &adapter->state);
-       flush_scheduled_work();
+*/     flush_scheduled_work();
 
        /* Deallocate Resources */
-
-       SxgFreeResources(adapter);
+       unregister_netdev(dev);
+       sxg_free_resources(adapter);
 
        ASSERT(adapter);
        DBG_ERROR("sxg: %s ENTER dev[%p] adapter[%p]\n", __func__, dev,
                  adapter);
-       sxg_deregister_interrupt(adapter);
-       sxg_unmap_mmio_space(adapter);
-       DBG_ERROR("sxg: %s unregister_netdev\n", __func__);
 
        mmio_start = pci_resource_start(pcidev, 0);
        mmio_len = pci_resource_len(pcidev, 0);
@@ -1933,11 +1987,6 @@ static void __devexit sxg_entry_remove(struct pci_dev *pcidev)
                  mmio_start, mmio_len);
        release_mem_region(mmio_start, mmio_len);
 
-/*
-       DBG_ERROR("sxg: %s iounmap dev->base_addr[%x]\n", __func__,
-                 (unsigned int)dev->base_addr);
-       iounmap((char *)dev->base_addr);
-*/
         mmio_start = pci_resource_start(pcidev, 2);
         mmio_len = pci_resource_len(pcidev, 2);
 
@@ -1945,10 +1994,6 @@ static void __devexit sxg_entry_remove(struct pci_dev *pcidev)
                   mmio_start, mmio_len);
         release_mem_region(mmio_start, mmio_len);
 
-       iounmap((char *)dev->base_addr);
-       unregister_netdev(dev);
-       //pci_release_regions(pcidev);
-       //free_netdev(dev);
        pci_disable_device(pcidev);
 
        DBG_ERROR("sxg: %s deallocate device\n", __func__);
@@ -1978,6 +2023,7 @@ static int sxg_entry_halt(struct net_device *dev)
 
        spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags);
 
+       sxg_deregister_interrupt(adapter);
        return (STATUS_SUCCESS);
 }
 
@@ -2076,13 +2122,14 @@ static int sxg_send_packets(struct sk_buff *skb, struct net_device *dev)
 #else
                SXG_DROP_DUMB_SEND(adapter, skb);
                adapter->stats.tx_dropped++;
+               return NETDEV_TX_BUSY;
 #endif
        }
        DBG_ERROR("sxg: %s EXIT sxg_send_packets status[%x]\n", __func__,
                  status);
 
       xmit_done:
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 /*
@@ -2100,6 +2147,7 @@ static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb)
 {
        struct sxg_x64_sgl         *pSgl;
        struct sxg_scatter_gather  *SxgSgl;
+       unsigned long sgl_flags;
        /* void *SglBuffer; */
        /* u32 SglBufferLength; */
 
@@ -2111,7 +2159,7 @@ static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb)
                  adapter, skb, 0, 0);
 
        /* Allocate a SGL buffer */
-       SXG_GET_SGL_BUFFER(adapter, SxgSgl);
+       SXG_GET_SGL_BUFFER(adapter, SxgSgl, 0);
        if (!SxgSgl) {
                adapter->Stats.NoSglBuf++;
                adapter->Stats.XmtErrors++;
@@ -2129,9 +2177,7 @@ static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb)
        pSgl = NULL;
 
        /* Call the common sxg_dumb_sgl routine to complete the send. */
-       sxg_dumb_sgl(pSgl, SxgSgl);
-       /* Return success sxg_dumb_sgl (or something later) will complete it.*/
-       return (STATUS_SUCCESS);
+       return (sxg_dumb_sgl(pSgl, SxgSgl));
 }
 
 /*
@@ -2142,9 +2188,9 @@ static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb)
  *             SxgSgl   - struct sxg_scatter_gather
  *
  * Return Value:
- *     None.
+ *     Status of send operation.
  */
-static void sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
+static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
                                struct sxg_scatter_gather *SxgSgl)
 {
        struct adapter_t *adapter = SxgSgl->adapter;
@@ -2158,6 +2204,7 @@ static void sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
        /* unsigned int BufLen; */
        /* u32 SglOffset; */
        u64 phys_addr;
+       unsigned long flags;
 
        SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSgl",
                  pSgl, SxgSgl, 0, 0);
@@ -2179,16 +2226,17 @@ static void sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
        SxgSgl->Sgl.NumberOfElements = 1;
 
        /* Grab the spinlock and acquire a command */
-       spin_lock(&adapter->XmtZeroLock);
+       spin_lock_irqsave(&adapter->XmtZeroLock, flags);
        SXG_GET_CMD(XmtRing, XmtRingInfo, XmtCmd, SxgSgl);
        if (XmtCmd == NULL) {
                /*
                 * Call sxg_complete_slow_send to see if we can
                 * free up any XmtRingZero entries and then try again
                 */
-               spin_unlock(&adapter->XmtZeroLock);
-               sxg_complete_slow_send(adapter);
-               spin_lock(&adapter->XmtZeroLock);
+
+               spin_unlock_irqrestore(&adapter->XmtZeroLock, flags);
+               sxg_complete_slow_send(adapter, 0);
+               spin_lock_irqsave(&adapter->XmtZeroLock, flags);
                SXG_GET_CMD(XmtRing, XmtRingInfo, XmtCmd, SxgSgl);
                if (XmtCmd == NULL) {
                        adapter->Stats.XmtZeroFull++;
@@ -2235,10 +2283,10 @@ static void sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
         */
        WRITE_REG(adapter->UcodeRegs[0].XmtCmd, 1, TRUE);
        adapter->Stats.XmtQLen++;       /* Stats within lock */
-       spin_unlock(&adapter->XmtZeroLock);
+       spin_unlock_irqrestore(&adapter->XmtZeroLock, flags);
        SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDumSgl2",
                  XmtCmd, pSgl, SxgSgl, 0);
-       return;
+       return  STATUS_SUCCESS;
 
       abortcmd:
        /*
@@ -2249,7 +2297,8 @@ static void sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
        if (XmtCmd) {
                SXG_ABORT_CMD(XmtRingInfo);
        }
-       spin_unlock(&adapter->XmtZeroLock);
+       spin_unlock_irqrestore(&adapter->XmtZeroLock, flags);
+       return STATUS_FAILURE;
 
 /*
  * failsgl:
@@ -2260,7 +2309,7 @@ static void sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
        SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "DumSGFal",
                  pSgl, SxgSgl, XmtRingInfo->Head, XmtRingInfo->Tail);
        /* SxgSgl->DumbPacket is the skb */
-       SXG_COMPLETE_DUMB_SEND(adapter, SxgSgl->DumbPacket);
+       // SXG_COMPLETE_DUMB_SEND(adapter, SxgSgl->DumbPacket);
 }
 
 /*
@@ -3065,58 +3114,85 @@ static void sxg_unmap_mmio_space(struct adapter_t *adapter)
  */
 #endif
 }
-/*
-void SxgFreeRcvBlocks(struct adapter_t *adapter)
+
+void sxg_free_sgl_buffers(struct adapter_t *adapter)
 {
-        u32                             i;
         struct list_entry               *ple;
-        struct sxg_rcv_block_hdr        *Hdr;
-        struct sxg_rcv_data_buffer_hdr *RcvDataBufferHdr;
-        u32    FreeBuffers = 0, FreeBlocks = 0;
+        struct sxg_scatter_gather       *Sgl;
 
-        SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "FrRcvBlk",
-                           adapter, 0, 0, 0);
+        while(!(IsListEmpty(&adapter->AllSglBuffers))) {
+                 ple = RemoveHeadList(&adapter->AllSglBuffers);
+                 Sgl = container_of(ple, struct sxg_scatter_gather, AllList);
+                kfree(Sgl);
+                adapter->AllSglBufferCount--;
+        }
+}
+
+void sxg_free_rcvblocks(struct adapter_t *adapter)
+{
+       u32                             i;
+               void                            *temp_RcvBlock;
+               struct list_entry               *ple;
+               struct sxg_rcv_block_hdr        *RcvBlockHdr;
+       struct sxg_rcv_data_buffer_hdr  *RcvDataBufferHdr;
+        ASSERT((adapter->state == SXG_STATE_INITIALIZING) ||
+                    (adapter->state == SXG_STATE_HALTING));
+        while(!(IsListEmpty(&adapter->AllRcvBlocks))) {
+
+                 ple = RemoveHeadList(&adapter->AllRcvBlocks);
+                 RcvBlockHdr = container_of(ple, struct sxg_rcv_block_hdr, AllList);
+
+                if(RcvBlockHdr->VirtualAddress) {
+                        temp_RcvBlock = RcvBlockHdr->VirtualAddress;
+
+                        for(i=0; i< SXG_RCV_DESCRIPTORS_PER_BLOCK;
+                             i++, temp_RcvBlock += SXG_RCV_DATA_HDR_SIZE) {
+                                RcvDataBufferHdr =
+                                        (struct sxg_rcv_data_buffer_hdr *)temp_RcvBlock;
+                                SXG_FREE_RCV_PACKET(RcvDataBufferHdr);
+                        }
+                }
 
-       ASSERT((adapter->State == SXG_STATE_INITIALIZING) ||
-                   (pAdapt->State == SXG_STATE_HALTING));
+                pci_free_consistent(adapter->pcidev,
+                                         SXG_RCV_BLOCK_SIZE(SXG_RCV_DATA_HDR_SIZE),
+                                         RcvBlockHdr->VirtualAddress,
+                                         RcvBlockHdr->PhysicalAddress);
+                adapter->AllRcvBlockCount--;
+       }
+       ASSERT(adapter->AllRcvBlockCount == 0);
+       SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XFrRBlk",
+                       adapter, 0, 0, 0);
+}
+void sxg_free_mcast_addrs(struct adapter_t *adapter)
+{
+       struct sxg_multicast_address    *address;
+        while(adapter->MulticastAddrs) {
+                address = adapter->MulticastAddrs;
+                adapter->MulticastAddrs = address->Next;
+               kfree(address);
+         }
+
+        adapter->MulticastMask= 0;
+}
 
-        for(i = 0; i < SXG_MAX_CPU; i++) {
-                FreeBuffers += pAdapt->PerCpuResources[i].FreeReceiveBuffers.Count;
-                FreeBlocks += pAdapt->PerCpuResources[i].FreeReceiveBlocks.Count;
-                pAdapt->PerCpuResources[i].FreeReceiveBuffers.Count = 0;
-                pAdapt->PerCpuResources[i].FreeReceiveBuffers.FreeList = NULL;
-                pAdapt->PerCpuResources[i].FreeReceiveBlocks.Count = 0;
-                pAdapt->PerCpuResources[i].FreeReceiveBlocks.FreeList = NULL;
-        }
-        FreeBuffers += pAdapt->GlobalResources.FreeReceiveBuffers.Count;
-        FreeBlocks += pAdapt->GlobalResources.FreeReceiveBlocks.Count;
-        pAdapt->GlobalResources.FreeReceiveBuffers.Count = 0;
-        pAdapt->GlobalResources.FreeReceiveBuffers.FreeList = NULL;
-        pAdapt->GlobalResources.FreeReceiveBlocks.Count = 0;
-        pAdapt->GlobalResources.FreeReceiveBlocks.FreeList = NULL;
-        ASSERT(FreeBlocks == pAdapt->AllRcvBlockCount); // See SXG_RCV_BLOCK
-        ASSERT(FreeBuffers ==
-                   (pAdapt->AllRcvBlockCount * SXG_RCV_DESCRIPTORS_PER_BLOCK)); // See SXG_RCV_BLOCK
-
-        while(!(IsListEmpty(&pAdapt->AllRcvBlocks))) {
-                ple = RemoveHeadList(&pAdapt->AllRcvBlocks);
-                Hdr = CONTAINING_RECORD(ple, SXG_RCV_BLOCK_HDR, AllList);
-                NdisMFreeSharedMemory(pAdapt->MiniportHandle,
-                                                          SXG_RCV_BLOCK_SIZE(pAdapt->ReceiveBufferSize),
-                                                          TRUE,
-                                                          Hdr->VirtualAddress,
-                                                          Hdr->PhysicalAddress);
-                pAdapt->AllRcvBlockCount--;
+void sxg_unmap_resources(struct adapter_t *adapter)
+{
+       if(adapter->HwRegs) {
+               iounmap((void *)adapter->HwRegs);
+         }
+        if(adapter->UcodeRegs) {
+               iounmap((void *)adapter->UcodeRegs);
         }
-        ASSERT(pAdapt->AllRcvBlockCount == 0);
-        SLIC_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XFrRBlk",
-                           pAdapt, 0, 0, 0);
+
+        ASSERT(adapter->AllRcvBlockCount == 0);
+        SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XFrRBlk",
+                           adapter, 0, 0, 0);
 }
-*/
-//#if XXXTODO
+
+
 
 /*
- * SxgFreeResources - Free everything allocated in SxgAllocateResources
+ * sxg_free_resources - Free everything allocated in SxgAllocateResources
  *
  * Arguments -
  *     adapter         - A pointer to our adapter structure
@@ -3124,14 +3200,10 @@ void SxgFreeRcvBlocks(struct adapter_t *adapter)
  * Return
  *     none
  */
-void SxgFreeResources(struct adapter_t *adapter)
+void sxg_free_resources(struct adapter_t *adapter)
 {
        u32 RssIds, IsrCount;
        u32 i;
-/*
-       SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "FreeRes",
-                 adapter, adapter->MaxTcbs, 0, 0);
-*/
        RssIds = SXG_RSS_CPU_COUNT(adapter);
        IsrCount = adapter->MsiEnabled ? RssIds : 1;
 
@@ -3142,14 +3214,13 @@ void SxgFreeResources(struct adapter_t *adapter)
                 */
                return;
        }
-/*
+
        if (!(IsListEmpty(&adapter->AllRcvBlocks))) {
-               SxgFreeRcvBlocks(adapter);
+               sxg_free_rcvblocks(adapter);
        }
        if (!(IsListEmpty(&adapter->AllSglBuffers))) {
-               SxgFreeSglBuffers(adapter);
+               sxg_free_sgl_buffers(adapter);
        }
-*/
 
        if (adapter->XmtRingZeroIndex) {
                pci_free_consistent(adapter->pcidev,
@@ -3157,82 +3228,49 @@ void SxgFreeResources(struct adapter_t *adapter)
                                    adapter->XmtRingZeroIndex,
                                    adapter->PXmtRingZeroIndex);
        }
-        printk("VSS Free Isr\n");
         if (adapter->Isr) {
                 pci_free_consistent(adapter->pcidev,
                                     sizeof(u32) * IsrCount,
                                     adapter->Isr, adapter->PIsr);
         }
 
-       printk("VSS Free EventRings\n");
         if (adapter->EventRings) {
                 pci_free_consistent(adapter->pcidev,
                                     sizeof(struct sxg_event_ring) * RssIds,
                                     adapter->EventRings, adapter->PEventRings);
         }
-/*
-       printk("VSS Free RcvRings\n");
         if (adapter->RcvRings) {
                 pci_free_consistent(adapter->pcidev,
-                                   sizeof(struct sxg_rcv_ring) * 4096,
+                                   sizeof(struct sxg_rcv_ring) * 1,
                                    adapter->RcvRings,
                                    adapter->PRcvRings);
                 adapter->RcvRings = NULL;
         }
 
-        printk("VSS Free XmtRings\n");
         if(adapter->XmtRings) {
                 pci_free_consistent(adapter->pcidev,
-                                            sizeof(struct sxg_xmt_ring) * 4096,
+                                            sizeof(struct sxg_xmt_ring) * 1,
                                             adapter->XmtRings,
                                             adapter->PXmtRings);
                         adapter->XmtRings = NULL;
         }
 
-*/
+       if (adapter->ucode_stats) {
+               pci_unmap_single(adapter->pcidev,
+                               sizeof(struct sxg_ucode_stats),
+                                adapter->pucode_stats, PCI_DMA_FROMDEVICE);
+               adapter->ucode_stats = NULL;
+       }
 
-/*
 
-       SXG_FREE_PACKET_POOL(adapter->PacketPoolHandle);
-       SXG_FREE_BUFFER_POOL(adapter->BufferPoolHandle);
-*/
        /* Unmap register spaces */
-       // SxgUnmapResources(adapter);
-
-       /* Deregister DMA */
-/*     if (adapter->DmaHandle) {
-               SXG_DEREGISTER_DMA(adapter->DmaHandle);
-       }
-*/     /* Deregister interrupt */
-       // SxgDeregisterInterrupt(adapter);
-
-       /* Possibly free system info (5.2 only) */
-       // SXG_RELEASE_SYSTEM_INFO(adapter);
+       sxg_unmap_resources(adapter);
 
-       //SxgDiagFreeResources(adapter);
+       sxg_free_mcast_addrs(adapter);
 
-       // SxgFreeMCastAddrs(adapter);
-/*
-       if (SXG_TIMER_ALLOCATED(adapter->ResetTimer)) {
-               SXG_CANCEL_TIMER(adapter->ResetTimer, TimerCancelled);
-               SXG_FREE_TIMER(adapter->ResetTimer);
-       }
-       if (SXG_TIMER_ALLOCATED(adapter->RssTimer)) {
-               SXG_CANCEL_TIMER(adapter->RssTimer, TimerCancelled);
-               SXG_FREE_TIMER(adapter->RssTimer);
-       }
-       if (SXG_TIMER_ALLOCATED(adapter->OffloadTimer)) {
-               SXG_CANCEL_TIMER(adapter->OffloadTimer, TimerCancelled);
-               SXG_FREE_TIMER(adapter->OffloadTimer);
-       }
-*/
        adapter->BasicAllocations = FALSE;
 
-/*     SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XFreeRes",
-                 adapter, adapter->MaxTcbs, 0, 0);
-*/
 }
-// #endif
 
 /*
  * sxg_allocate_complete -
@@ -3311,8 +3349,12 @@ static int sxg_allocate_buffer_memory(struct adapter_t *adapter,
        ++adapter->AllocationsPending;
        spin_unlock(&adapter->AdapterLock);
 
-       /* At initialization time allocate resources synchronously. */
-       Buffer = pci_alloc_consistent(adapter->pcidev, Size, &pBuffer);
+       if(BufferType != SXG_BUFFER_TYPE_SGL)
+               Buffer = pci_alloc_consistent(adapter->pcidev, Size, &pBuffer);
+       else {
+               Buffer = kzalloc(Size, GFP_ATOMIC);
+               pBuffer = NULL;
+       }
        if (Buffer == NULL) {
                spin_lock(&adapter->AdapterLock);
                /*
@@ -3468,19 +3510,25 @@ static void sxg_allocate_sgl_buffer_complete(struct adapter_t *adapter,
                                             dma_addr_t PhysicalAddress,
                                             u32 Length)
 {
+       unsigned long sgl_flags;
        SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AlSglCmp",
                  adapter, SxgSgl, Length, 0);
-       spin_lock(&adapter->SglQLock);
+       if(!in_irq())
+               spin_unlock_irqrestore(&adapter->SglQLock, sgl_flags);
+       else
+               spin_unlock(&adapter->SglQLock);
        adapter->AllSglBufferCount++;
-       memset(SxgSgl, 0, sizeof(struct sxg_scatter_gather));
-       /* *PhysicalAddress; */
+       /* PhysicalAddress; */
        SxgSgl->PhysicalAddress = PhysicalAddress;
        /* Initialize backpointer once */
        SxgSgl->adapter = adapter;
        InsertTailList(&adapter->AllSglBuffers, &SxgSgl->AllList);
-       spin_unlock(&adapter->SglQLock);
+       if(!in_irq())
+               spin_unlock_irqrestore(&adapter->SglQLock, sgl_flags);
+       else
+               spin_unlock(&adapter->SglQLock);
        SxgSgl->State = SXG_BUFFER_BUSY;
-       SXG_FREE_SGL_BUFFER(adapter, SxgSgl, NULL);
+       SXG_FREE_SGL_BUFFER(adapter, SxgSgl, NULL, in_irq());
        SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlSgl",
                  adapter, SxgSgl, Length, 0);
 }
@@ -3702,6 +3750,15 @@ static int sxg_fill_descriptor_block(struct adapter_t *adapter,
                SXG_GET_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr);
                ASSERT(RcvDataBufferHdr);
                ASSERT(RcvDataBufferHdr->SxgDumbRcvPacket);
+               if (!RcvDataBufferHdr->SxgDumbRcvPacket) {
+                       SXG_ALLOCATE_RCV_PACKET(adapter, RcvDataBufferHdr,
+                                               adapter->ReceiveBufferSize);
+                       if(RcvDataBufferHdr->skb)
+                               RcvDataBufferHdr->SxgDumbRcvPacket =
+                                               RcvDataBufferHdr->skb;
+                       else
+                               goto no_memory;
+               }
                SXG_REINIATIALIZE_PACKET(RcvDataBufferHdr->SxgDumbRcvPacket);
                RcvDataBufferHdr->State = SXG_BUFFER_ONCARD;
                RcvDescriptorBlock->Descriptors[i].VirtualAddress =
@@ -3730,6 +3787,8 @@ static int sxg_fill_descriptor_block(struct adapter_t *adapter,
                  adapter, adapter->RcvBuffersOnCard,
                  adapter->FreeRcvBufferCount, adapter->AllRcvBlockCount);
        return (STATUS_SUCCESS);
+no_memory:
+       return (-ENOMEM);
 }
 
 /*
@@ -3823,7 +3882,8 @@ static void sxg_complete_descriptor_blocks(struct adapter_t *adapter,
        /* Now grab the RcvQLock lock and proceed */
        spin_lock(&adapter->RcvQLock);
        ASSERT(Index != RcvRingInfo->Tail);
-       while (RcvRingInfo->Tail != Index) {
+       while (sxg_ring_get_forward_diff(RcvRingInfo, Index,
+                                       RcvRingInfo->Tail) > 3) {
                /*
                 * Locate the current Cmd (ring descriptor entry), and
                 * associated receive descriptor block, and advance
@@ -3854,6 +3914,15 @@ static void sxg_complete_descriptor_blocks(struct adapter_t *adapter,
                  adapter, Index, RcvRingInfo->Head, RcvRingInfo->Tail);
 }
 
+/*
+ * Read the statistics which the card has been maintaining.
+ */
+void sxg_collect_statistics(struct adapter_t *adapter)
+{
+       if(adapter->ucode_stats)
+               WRITE_REG64(adapter, adapter->UcodeRegs[0].GetUcodeStats, adapter->pucode_stats, 0);
+}
+
 static struct pci_driver sxg_driver = {
        .name = sxg_driver_name,
        .id_table = sxg_pci_tbl,
index a00c2dc97a1ef7d0c699dec9572f0898c00202ca..2d0ad1977ccc682ce3a32daeff98f72b30ef8cc2 100644 (file)
@@ -121,9 +121,10 @@ struct sxg_stats {
 
 /* DUMB-NIC Send path definitions */
 
-#define SXG_COMPLETE_DUMB_SEND(_pAdapt, _skb) {                        \
-       ASSERT(_skb);                                                   \
-    dev_kfree_skb_irq(_skb);                                            \
+#define SXG_COMPLETE_DUMB_SEND(_pAdapt, _skb, _phys_addr, _size) {             \
+       ASSERT(_skb);                                                           \
+       pci_unmap_single(_pAdapt->pcidev, _size, _phys_addr, PCI_DMA_TODEVICE); \
+       dev_kfree_skb_irq(_skb);                                                \
 }
 
 #define SXG_DROP_DUMB_SEND(_pAdapt, _skb) {                                    \
@@ -262,14 +263,20 @@ struct sxg_stats {
 }
 
 /* SGL macros */
-#define SXG_FREE_SGL_BUFFER(_pAdapt, _Sgl, _NB) {                              \
-       spin_lock(&(_pAdapt)->SglQLock);                                        \
+#define SXG_FREE_SGL_BUFFER(_pAdapt, _Sgl, _NB, _irq) {                                \
+       if(!_irq)                                                               \
+               spin_lock_irqsave(&(_pAdapt)->SglQLock, sgl_flags);             \
+       else                                                                    \
+               spin_lock(&(_pAdapt)->SglQLock);                                \
        (_pAdapt)->FreeSglBufferCount++;                                        \
        ASSERT((_pAdapt)->AllSglBufferCount >= (_pAdapt)->FreeSglBufferCount);  \
        ASSERT(!((_Sgl)->State & SXG_BUFFER_FREE));                             \
        (_Sgl)->State = SXG_BUFFER_FREE;                                        \
        InsertTailList(&(_pAdapt)->FreeSglBuffers, &(_Sgl)->FreeList);          \
-       spin_unlock(&(_pAdapt)->SglQLock);                                      \
+       if(!_irq)                                                               \
+               spin_unlock_irqrestore(&(_pAdapt)->SglQLock, sgl_flags);        \
+       else                                                                    \
+               spin_unlock(&(_pAdapt)->SglQLock);                              \
 }
 
 /*
@@ -279,7 +286,7 @@ struct sxg_stats {
  * until after that.  We're dealing with round numbers here, so we don't need to,
  * and not grabbing it avoids a possible double-trip.
  */
-#define SXG_GET_SGL_BUFFER(_pAdapt, _Sgl) {                            \
+#define SXG_GET_SGL_BUFFER(_pAdapt, _Sgl, _irq) {                      \
        struct list_entry *_ple;                                        \
        if ((_pAdapt->FreeSglBufferCount < SXG_MIN_SGL_BUFFERS) &&      \
           (_pAdapt->AllSglBufferCount < SXG_MAX_SGL_BUFFERS) &&        \
@@ -289,7 +296,10 @@ struct sxg_stats {
                        SXG_BUFFER_TYPE_SGL);                           \
        }                                                               \
        _Sgl = NULL;                                                    \
-       spin_lock(&(_pAdapt)->SglQLock);                                \
+       if(!_irq)                                                       \
+               spin_lock_irqsave(&(_pAdapt)->SglQLock, sgl_flags);     \
+       else                                                            \
+               spin_lock(&(_pAdapt)->SglQLock);                        \
        if((_pAdapt)->FreeSglBufferCount) {                             \
                ASSERT(!(IsListEmpty(&(_pAdapt)->FreeSglBuffers)));     \
                _ple = RemoveHeadList(&(_pAdapt)->FreeSglBuffers);      \
@@ -300,7 +310,10 @@ struct sxg_stats {
                (_Sgl)->State = SXG_BUFFER_BUSY;                        \
                (_Sgl)->pSgl = NULL;                                    \
        }                                                               \
-       spin_unlock(&(_pAdapt)->SglQLock);                              \
+       if(!_irq)                                                       \
+               spin_unlock_irqrestore(&(_pAdapt)->SglQLock, sgl_flags);\
+       else                                                            \
+               spin_unlock(&(_pAdapt)->SglQLock);                      \
 }
 
 /*
@@ -416,6 +429,7 @@ struct sxg_driver {
 #undef STATUS_SUCCESS
 #endif
 
+/* TODO: We need to try and use NETDEV_TX_* before posting this out */
 #define STATUS_SUCCESS              0
 #define STATUS_PENDING              0
 #define STATUS_FAILURE             -1
@@ -631,6 +645,10 @@ struct adapter_t {
 
        struct sxg_rcv_ring     *RcvRings;      /* Receive rings */
        dma_addr_t      PRcvRings;              /* Receive rings - physical address */
+       struct sxg_ucode_stats  *ucode_stats;           /* Ucode Stats  */
+       /* Ucode Stats - physical address */
+       dma_addr_t              pucode_stats;
+
        struct sxg_ring_info    RcvRingZeroInfo;        /* Receive ring 0 info */
 
        u32 *           Isr;            /* Interrupt status register */
@@ -765,4 +783,5 @@ struct slic_crash_info {
 #define SIOCSLICTRACEDUMP        (SIOCDEVPRIVATE+11)
 
 extern struct ethtool_ops sxg_nic_ethtool_ops;
+#define SXG_COMPLETE_SLOW_SEND_LIMIT   128
 #endif /*  __SXG_DRIVER_H__ */
index c15c250e9ec5b98922403f51827c00ea27ddd9db..151f7f075b524cb63a0cd09c65f93fba5558f225 100644 (file)
@@ -137,7 +137,7 @@ sxg_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
        struct adapter_t *adapter = netdev_priv(dev);
        strncpy(drvinfo->driver, sxg_driver_name, 32);
        strncpy(drvinfo->version, SXG_DRV_VERSION, 32);
-       strncpy(drvinfo->fw_version, SAHARA_UCODE_VERS_STRING, 32);
+//     strncpy(drvinfo->fw_version, SAHARA_UCODE_VERS_STRING, 32);
        strncpy(drvinfo->bus_info, pci_name(adapter->pcidev), 32);
        /* TODO : Read the major and minor number of firmware. Is this
         * from the FLASH/EEPROM or download file ?
index 5a9e2712c89a8e5829556bd4bc61ba6580fe51b8..faba61529dd34ffd577f1eabf8f4d409ec9a52b5 100644 (file)
@@ -486,6 +486,20 @@ struct sxg_ring_info {
        SXG_RING_ADVANCE_TAIL(_ringinfo);                               \
 }
 
+/*
+ * For a given ring find out how much the first pointer is ahead of
+ * the second pointer. "ahead" recognises the fact that the ring can wrap
+ */
+static inline int sxg_ring_get_forward_diff (struct sxg_ring_info *ringinfo,
+                                               int a, int b) {
+       if ((a < 0 || a > ringinfo->Size ) || (b < 0 || b > ringinfo->Size))
+               return -1;
+       if (a > b)      /* _a is lagging _b and _b has not wrapped around */
+               return (a - b);
+       else
+               return ((ringinfo->Size - (b - a)));
+}
+
 /***************************************************************
  * Host Command Buffer - commands to INIC via the Cmd Rings
  *