]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/tg3.c
tg3: Update version to 3.104
[net-next-2.6.git] / drivers / net / tg3.c
index 05fd42f8f4ed526ee6249c1dc3aedbef2e56f6cd..6e6db955b4a97271c1ef6a6dc277202b1e2df54b 100644 (file)
@@ -68,8 +68,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.103"
-#define DRV_MODULE_RELDATE     "November 2, 2009"
+#define DRV_MODULE_VERSION     "3.104"
+#define DRV_MODULE_RELDATE     "November 13, 2009"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -241,6 +241,9 @@ static struct pci_device_id tg3_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57760)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5724)},
        {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
        {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
        {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
@@ -4558,7 +4561,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
        u32 sw_idx = tnapi->rx_rcb_ptr;
        u16 hw_idx;
        int received;
-       struct tg3_rx_prodring_set *tpr = &tp->prodring[0];
+       struct tg3_rx_prodring_set *tpr = tnapi->prodring;
 
        hw_idx = *(tnapi->rx_rcb_prod_idx);
        /*
@@ -4581,13 +4584,13 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
                desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
                opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
                if (opaque_key == RXD_OPAQUE_RING_STD) {
-                       ri = &tpr->rx_std_buffers[desc_idx];
+                       ri = &tp->prodring[0].rx_std_buffers[desc_idx];
                        dma_addr = pci_unmap_addr(ri, mapping);
                        skb = ri->skb;
                        post_ptr = &std_prod_idx;
                        rx_std_posted++;
                } else if (opaque_key == RXD_OPAQUE_RING_JUMBO) {
-                       ri = &tpr->rx_jmb_buffers[desc_idx];
+                       ri = &tp->prodring[0].rx_jmb_buffers[desc_idx];
                        dma_addr = pci_unmap_addr(ri, mapping);
                        skb = ri->skb;
                        post_ptr = &jmb_prod_idx;
@@ -4704,15 +4707,30 @@ next_pkt_nopost:
        tw32_rx_mbox(tnapi->consmbox, sw_idx);
 
        /* Refill RX ring(s). */
-       if (work_mask & RXD_OPAQUE_RING_STD) {
+       if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) || tnapi == &tp->napi[1]) {
+               if (work_mask & RXD_OPAQUE_RING_STD) {
+                       tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
+                       tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG,
+                                    tpr->rx_std_prod_idx);
+               }
+               if (work_mask & RXD_OPAQUE_RING_JUMBO) {
+                       tpr->rx_jmb_prod_idx = jmb_prod_idx %
+                                              TG3_RX_JUMBO_RING_SIZE;
+                       tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG,
+                                    tpr->rx_jmb_prod_idx);
+               }
+               mmiowb();
+       } else if (work_mask) {
+               /* rx_std_buffers[] and rx_jmb_buffers[] entries must be
+                * updated before the producer indices can be updated.
+                */
+               smp_wmb();
+
                tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
-               tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, tpr->rx_std_prod_idx);
-       }
-       if (work_mask & RXD_OPAQUE_RING_JUMBO) {
                tpr->rx_jmb_prod_idx = jmb_prod_idx % TG3_RX_JUMBO_RING_SIZE;
-               tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, tpr->rx_jmb_prod_idx);
+
+               napi_schedule(&tp->napi[1].napi);
        }
-       mmiowb();
 
        return received;
 }
@@ -4743,6 +4761,93 @@ static void tg3_poll_link(struct tg3 *tp)
        }
 }
 
+static void tg3_rx_prodring_xfer(struct tg3 *tp,
+                                struct tg3_rx_prodring_set *dpr,
+                                struct tg3_rx_prodring_set *spr)
+{
+       u32 si, di, cpycnt, src_prod_idx;
+       int i;
+
+       while (1) {
+               src_prod_idx = spr->rx_std_prod_idx;
+
+               /* Make sure updates to the rx_std_buffers[] entries and the
+                * standard producer index are seen in the correct order.
+                */
+               smp_rmb();
+
+               if (spr->rx_std_cons_idx == src_prod_idx)
+                       break;
+
+               if (spr->rx_std_cons_idx < src_prod_idx)
+                       cpycnt = src_prod_idx - spr->rx_std_cons_idx;
+               else
+                       cpycnt = TG3_RX_RING_SIZE - spr->rx_std_cons_idx;
+
+               cpycnt = min(cpycnt, TG3_RX_RING_SIZE - dpr->rx_std_prod_idx);
+
+               si = spr->rx_std_cons_idx;
+               di = dpr->rx_std_prod_idx;
+
+               memcpy(&dpr->rx_std_buffers[di],
+                      &spr->rx_std_buffers[si],
+                      cpycnt * sizeof(struct ring_info));
+
+               for (i = 0; i < cpycnt; i++, di++, si++) {
+                       struct tg3_rx_buffer_desc *sbd, *dbd;
+                       sbd = &spr->rx_std[si];
+                       dbd = &dpr->rx_std[di];
+                       dbd->addr_hi = sbd->addr_hi;
+                       dbd->addr_lo = sbd->addr_lo;
+               }
+
+               spr->rx_std_cons_idx = (spr->rx_std_cons_idx + cpycnt) %
+                                      TG3_RX_RING_SIZE;
+               dpr->rx_std_prod_idx = (dpr->rx_std_prod_idx + cpycnt) %
+                                      TG3_RX_RING_SIZE;
+       }
+
+       while (1) {
+               src_prod_idx = spr->rx_jmb_prod_idx;
+
+               /* Make sure updates to the rx_jmb_buffers[] entries and
+                * the jumbo producer index are seen in the correct order.
+                */
+               smp_rmb();
+
+               if (spr->rx_jmb_cons_idx == src_prod_idx)
+                       break;
+
+               if (spr->rx_jmb_cons_idx < src_prod_idx)
+                       cpycnt = src_prod_idx - spr->rx_jmb_cons_idx;
+               else
+                       cpycnt = TG3_RX_JUMBO_RING_SIZE - spr->rx_jmb_cons_idx;
+
+               cpycnt = min(cpycnt,
+                            TG3_RX_JUMBO_RING_SIZE - dpr->rx_jmb_prod_idx);
+
+               si = spr->rx_jmb_cons_idx;
+               di = dpr->rx_jmb_prod_idx;
+
+               memcpy(&dpr->rx_jmb_buffers[di],
+                      &spr->rx_jmb_buffers[si],
+                      cpycnt * sizeof(struct ring_info));
+
+               for (i = 0; i < cpycnt; i++, di++, si++) {
+                       struct tg3_rx_buffer_desc *sbd, *dbd;
+                       sbd = &spr->rx_jmb[si].std;
+                       dbd = &dpr->rx_jmb[di].std;
+                       dbd->addr_hi = sbd->addr_hi;
+                       dbd->addr_lo = sbd->addr_lo;
+               }
+
+               spr->rx_jmb_cons_idx = (spr->rx_jmb_cons_idx + cpycnt) %
+                                      TG3_RX_JUMBO_RING_SIZE;
+               dpr->rx_jmb_prod_idx = (dpr->rx_jmb_prod_idx + cpycnt) %
+                                      TG3_RX_JUMBO_RING_SIZE;
+       }
+}
+
 static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
 {
        struct tg3 *tp = tnapi->tp;
@@ -4761,6 +4866,30 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
        if (*(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr)
                work_done += tg3_rx(tnapi, budget - work_done);
 
+       if ((tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) && tnapi == &tp->napi[1]) {
+               int i;
+               u32 std_prod_idx = tp->prodring[0].rx_std_prod_idx;
+               u32 jmb_prod_idx = tp->prodring[0].rx_jmb_prod_idx;
+
+               for (i = 2; i < tp->irq_cnt; i++)
+                       tg3_rx_prodring_xfer(tp, tnapi->prodring,
+                                            tp->napi[i].prodring);
+
+               wmb();
+
+               if (std_prod_idx != tp->prodring[0].rx_std_prod_idx) {
+                       u32 mbox = TG3_RX_STD_PROD_IDX_REG;
+                       tw32_rx_mbox(mbox, tp->prodring[0].rx_std_prod_idx);
+               }
+
+               if (jmb_prod_idx != tp->prodring[0].rx_jmb_prod_idx) {
+                       u32 mbox = TG3_RX_JMB_PROD_IDX_REG;
+                       tw32_rx_mbox(mbox, tp->prodring[0].rx_jmb_prod_idx);
+               }
+
+               mmiowb();
+       }
+
        return work_done;
 }
 
@@ -5715,8 +5844,23 @@ static void tg3_rx_prodring_free(struct tg3 *tp,
 {
        int i;
 
-       if (tpr != &tp->prodring[0])
+       if (tpr != &tp->prodring[0]) {
+               for (i = tpr->rx_std_cons_idx; i != tpr->rx_std_prod_idx;
+                    i = (i + 1) % TG3_RX_RING_SIZE)
+                       tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i],
+                                       tp->rx_pkt_map_sz);
+
+               if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
+                       for (i = tpr->rx_jmb_cons_idx;
+                            i != tpr->rx_jmb_prod_idx;
+                            i = (i + 1) % TG3_RX_JUMBO_RING_SIZE) {
+                               tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i],
+                                               TG3_RX_JMB_MAP_SZ);
+                       }
+               }
+
                return;
+       }
 
        for (i = 0; i < TG3_RX_RING_SIZE; i++)
                tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i],
@@ -5741,6 +5885,11 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
 {
        u32 i, rx_pkt_dma_sz;
 
+       tpr->rx_std_cons_idx = 0;
+       tpr->rx_std_prod_idx = 0;
+       tpr->rx_jmb_cons_idx = 0;
+       tpr->rx_jmb_prod_idx = 0;
+
        if (tpr != &tp->prodring[0]) {
                memset(&tpr->rx_std_buffers[0], 0, TG3_RX_STD_BUFF_RING_SIZE);
                if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE)
@@ -6062,6 +6211,11 @@ static int tg3_alloc_consistent(struct tg3 *tp)
                        break;
                }
 
+               if (tp->irq_cnt == 1)
+                       tnapi->prodring = &tp->prodring[0];
+               else if (i)
+                       tnapi->prodring = &tp->prodring[i - 1];
+
                /*
                 * If multivector RSS is enabled, vector 0 does not handle
                 * rx or tx interrupts.  Don't allocate any resources for it.
@@ -12551,10 +12705,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) {
                u32 prod_id_asic_rev;
 
-               if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717C ||
-                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717S ||
-                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718C ||
-                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718S)
+               if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
+                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5724)
                        pci_read_config_dword(tp->pdev,
                                              TG3PCI_GEN2_PRODID_ASICREV,
                                              &prod_id_asic_rev);