Merge branch 'for-upstream' of git://openrisc.net/jonas/linux
[pandora-kernel.git] / drivers / net / bnx2x / bnx2x_ethtool.c
index 1a3ed41..2218630 100644 (file)
@@ -500,78 +500,179 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 #define IS_E1_ONLINE(info)     (((info) & RI_E1_ONLINE) == RI_E1_ONLINE)
 #define IS_E1H_ONLINE(info)    (((info) & RI_E1H_ONLINE) == RI_E1H_ONLINE)
 #define IS_E2_ONLINE(info)     (((info) & RI_E2_ONLINE) == RI_E2_ONLINE)
+#define IS_E3_ONLINE(info)     (((info) & RI_E3_ONLINE) == RI_E3_ONLINE)
+#define IS_E3B0_ONLINE(info)   (((info) & RI_E3B0_ONLINE) == RI_E3B0_ONLINE)
+
+static inline bool bnx2x_is_reg_online(struct bnx2x *bp,
+                                      const struct reg_addr *reg_info)
+{
+       if (CHIP_IS_E1(bp))
+               return IS_E1_ONLINE(reg_info->info);
+       else if (CHIP_IS_E1H(bp))
+               return IS_E1H_ONLINE(reg_info->info);
+       else if (CHIP_IS_E2(bp))
+               return IS_E2_ONLINE(reg_info->info);
+       else if (CHIP_IS_E3A0(bp))
+               return IS_E3_ONLINE(reg_info->info);
+       else if (CHIP_IS_E3B0(bp))
+               return IS_E3B0_ONLINE(reg_info->info);
+       else
+               return false;
+}
+
+/******* Paged registers info selectors ********/
+static inline const u32 *__bnx2x_get_page_addr_ar(struct bnx2x *bp)
+{
+       if (CHIP_IS_E2(bp))
+               return page_vals_e2;
+       else if (CHIP_IS_E3(bp))
+               return page_vals_e3;
+       else
+               return NULL;
+}
+
+static inline u32 __bnx2x_get_page_reg_num(struct bnx2x *bp)
+{
+       if (CHIP_IS_E2(bp))
+               return PAGE_MODE_VALUES_E2;
+       else if (CHIP_IS_E3(bp))
+               return PAGE_MODE_VALUES_E3;
+       else
+               return 0;
+}
+
+static inline const u32 *__bnx2x_get_page_write_ar(struct bnx2x *bp)
+{
+       if (CHIP_IS_E2(bp))
+               return page_write_regs_e2;
+       else if (CHIP_IS_E3(bp))
+               return page_write_regs_e3;
+       else
+               return NULL;
+}
+
+static inline u32 __bnx2x_get_page_write_num(struct bnx2x *bp)
+{
+       if (CHIP_IS_E2(bp))
+               return PAGE_WRITE_REGS_E2;
+       else if (CHIP_IS_E3(bp))
+               return PAGE_WRITE_REGS_E3;
+       else
+               return 0;
+}
+
+static inline const struct reg_addr *__bnx2x_get_page_read_ar(struct bnx2x *bp)
+{
+       if (CHIP_IS_E2(bp))
+               return page_read_regs_e2;
+       else if (CHIP_IS_E3(bp))
+               return page_read_regs_e3;
+       else
+               return NULL;
+}
+
+static inline u32 __bnx2x_get_page_read_num(struct bnx2x *bp)
+{
+       if (CHIP_IS_E2(bp))
+               return PAGE_READ_REGS_E2;
+       else if (CHIP_IS_E3(bp))
+               return PAGE_READ_REGS_E3;
+       else
+               return 0;
+}
+
+static inline int __bnx2x_get_regs_len(struct bnx2x *bp)
+{
+       int num_pages = __bnx2x_get_page_reg_num(bp);
+       int page_write_num = __bnx2x_get_page_write_num(bp);
+       const struct reg_addr *page_read_addr = __bnx2x_get_page_read_ar(bp);
+       int page_read_num = __bnx2x_get_page_read_num(bp);
+       int regdump_len = 0;
+       int i, j, k;
+
+       for (i = 0; i < REGS_COUNT; i++)
+               if (bnx2x_is_reg_online(bp, &reg_addrs[i]))
+                       regdump_len += reg_addrs[i].size;
+
+       for (i = 0; i < num_pages; i++)
+               for (j = 0; j < page_write_num; j++)
+                       for (k = 0; k < page_read_num; k++)
+                               if (bnx2x_is_reg_online(bp, &page_read_addr[k]))
+                                       regdump_len += page_read_addr[k].size;
+
+       return regdump_len;
+}
 
 static int bnx2x_get_regs_len(struct net_device *dev)
 {
        struct bnx2x *bp = netdev_priv(dev);
        int regdump_len = 0;
-       int i, j, k;
 
-       if (CHIP_IS_E1(bp)) {
-               for (i = 0; i < REGS_COUNT; i++)
-                       if (IS_E1_ONLINE(reg_addrs[i].info))
-                               regdump_len += reg_addrs[i].size;
-
-               for (i = 0; i < WREGS_COUNT_E1; i++)
-                       if (IS_E1_ONLINE(wreg_addrs_e1[i].info))
-                               regdump_len += wreg_addrs_e1[i].size *
-                                       (1 + wreg_addrs_e1[i].read_regs_count);
-
-       } else if (CHIP_IS_E1H(bp)) {
-               for (i = 0; i < REGS_COUNT; i++)
-                       if (IS_E1H_ONLINE(reg_addrs[i].info))
-                               regdump_len += reg_addrs[i].size;
-
-               for (i = 0; i < WREGS_COUNT_E1H; i++)
-                       if (IS_E1H_ONLINE(wreg_addrs_e1h[i].info))
-                               regdump_len += wreg_addrs_e1h[i].size *
-                                       (1 + wreg_addrs_e1h[i].read_regs_count);
-       } else if (!CHIP_IS_E1x(bp)) {
-               for (i = 0; i < REGS_COUNT; i++)
-                       if (IS_E2_ONLINE(reg_addrs[i].info))
-                               regdump_len += reg_addrs[i].size;
-
-               for (i = 0; i < WREGS_COUNT_E2; i++)
-                       if (IS_E2_ONLINE(wreg_addrs_e2[i].info))
-                               regdump_len += wreg_addrs_e2[i].size *
-                                       (1 + wreg_addrs_e2[i].read_regs_count);
-
-               for (i = 0; i < PAGE_MODE_VALUES_E2; i++)
-                       for (j = 0; j < PAGE_WRITE_REGS_E2; j++) {
-                               for (k = 0; k < PAGE_READ_REGS_E2; k++)
-                                       if (IS_E2_ONLINE(page_read_regs_e2[k].
-                                                        info))
-                                               regdump_len +=
-                                               page_read_regs_e2[k].size;
-                       }
-       }
+       regdump_len = __bnx2x_get_regs_len(bp);
        regdump_len *= 4;
        regdump_len += sizeof(struct dump_hdr);
 
        return regdump_len;
 }
 
-static inline void bnx2x_read_pages_regs_e2(struct bnx2x *bp, u32 *p)
+/**
+ * bnx2x_read_pages_regs - read "paged" registers
+ *
+ * @bp         device handle
+ * @p          output buffer
+ *
+ * Reads "paged" memories: memories that may only be read by first writing to a
+ * specific address ("write address") and then reading from a specific address
+ * ("read address"). There may be more than one write address per "page" and
+ * more than one read address per write address.
+ */
+static inline void bnx2x_read_pages_regs(struct bnx2x *bp, u32 *p)
 {
        u32 i, j, k, n;
-
-       for (i = 0; i < PAGE_MODE_VALUES_E2; i++) {
-               for (j = 0; j < PAGE_WRITE_REGS_E2; j++) {
-                       REG_WR(bp, page_write_regs_e2[j], page_vals_e2[i]);
-                       for (k = 0; k < PAGE_READ_REGS_E2; k++)
-                               if (IS_E2_ONLINE(page_read_regs_e2[k].info))
+       /* addresses of the paged registers */
+       const u32 *page_addr = __bnx2x_get_page_addr_ar(bp);
+       /* number of paged registers */
+       int num_pages = __bnx2x_get_page_reg_num(bp);
+       /* write addresses */
+       const u32 *write_addr = __bnx2x_get_page_write_ar(bp);
+       /* number of write addresses */
+       int write_num = __bnx2x_get_page_write_num(bp);
+       /* read addresses info */
+       const struct reg_addr *read_addr = __bnx2x_get_page_read_ar(bp);
+       /* number of read addresses */
+       int read_num = __bnx2x_get_page_read_num(bp);
+
+       for (i = 0; i < num_pages; i++) {
+               for (j = 0; j < write_num; j++) {
+                       REG_WR(bp, write_addr[j], page_addr[i]);
+                       for (k = 0; k < read_num; k++)
+                               if (bnx2x_is_reg_online(bp, &read_addr[k]))
                                        for (n = 0; n <
-                                             page_read_regs_e2[k].size; n++)
+                                             read_addr[k].size; n++)
                                                *p++ = REG_RD(bp,
-                                       page_read_regs_e2[k].addr + n*4);
+                                                      read_addr[k].addr + n*4);
                }
        }
 }
 
+static inline void __bnx2x_get_regs(struct bnx2x *bp, u32 *p)
+{
+       u32 i, j;
+
+       /* Read the regular registers */
+       for (i = 0; i < REGS_COUNT; i++)
+               if (bnx2x_is_reg_online(bp, &reg_addrs[i]))
+                       for (j = 0; j < reg_addrs[i].size; j++)
+                               *p++ = REG_RD(bp, reg_addrs[i].addr + j*4);
+
+       /* Read "paged" registes */
+       bnx2x_read_pages_regs(bp, p);
+}
+
 static void bnx2x_get_regs(struct net_device *dev,
                           struct ethtool_regs *regs, void *_p)
 {
-       u32 *p = _p, i, j;
+       u32 *p = _p;
        struct bnx2x *bp = netdev_priv(dev);
        struct dump_hdr dump_hdr = {0};
 
@@ -605,33 +706,9 @@ static void bnx2x_get_regs(struct net_device *dev,
        memcpy(p, &dump_hdr, sizeof(struct dump_hdr));
        p += dump_hdr.hdr_size + 1;
 
-       if (CHIP_IS_E1(bp)) {
-               for (i = 0; i < REGS_COUNT; i++)
-                       if (IS_E1_ONLINE(reg_addrs[i].info))
-                               for (j = 0; j < reg_addrs[i].size; j++)
-                                       *p++ = REG_RD(bp,
-                                                     reg_addrs[i].addr + j*4);
-
-       } else if (CHIP_IS_E1H(bp)) {
-               for (i = 0; i < REGS_COUNT; i++)
-                       if (IS_E1H_ONLINE(reg_addrs[i].info))
-                               for (j = 0; j < reg_addrs[i].size; j++)
-                                       *p++ = REG_RD(bp,
-                                                     reg_addrs[i].addr + j*4);
-
-       } else if (!CHIP_IS_E1x(bp)) {
-               for (i = 0; i < REGS_COUNT; i++)
-                       if (IS_E2_ONLINE(reg_addrs[i].info))
-                               for (j = 0; j < reg_addrs[i].size; j++)
-                                       *p++ = REG_RD(bp,
-                                             reg_addrs[i].addr + j*4);
-
-               if (CHIP_IS_E2(bp))
-                       bnx2x_read_pages_regs_e2(bp, p);
-               else
-                       /* E3 paged registers read is unimplemented yet */
-                       WARN_ON(1);
-       }
+       /* Actually read the registers */
+       __bnx2x_get_regs(bp, p);
+
        /* Re-enable parity attentions */
        bnx2x_clear_blocks_parity(bp);
        bnx2x_enable_blocks_parity(bp);
@@ -1616,6 +1693,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
        unsigned char *packet;
        struct bnx2x_fastpath *fp_rx = &bp->fp[0];
        struct bnx2x_fastpath *fp_tx = &bp->fp[0];
+       struct bnx2x_fp_txdata *txdata = &fp_tx->txdata[0];
        u16 tx_start_idx, tx_idx;
        u16 rx_start_idx, rx_idx;
        u16 pkt_prod, bd_prod, rx_comp_cons;
@@ -1670,17 +1748,17 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
 
        /* send the loopback packet */
        num_pkts = 0;
-       tx_start_idx = le16_to_cpu(*fp_tx->tx_cons_sb);
+       tx_start_idx = le16_to_cpu(*txdata->tx_cons_sb);
        rx_start_idx = le16_to_cpu(*fp_rx->rx_cons_sb);
 
-       pkt_prod = fp_tx->tx_pkt_prod++;
-       tx_buf = &fp_tx->tx_buf_ring[TX_BD(pkt_prod)];
-       tx_buf->first_bd = fp_tx->tx_bd_prod;
+       pkt_prod = txdata->tx_pkt_prod++;
+       tx_buf = &txdata->tx_buf_ring[TX_BD(pkt_prod)];
+       tx_buf->first_bd = txdata->tx_bd_prod;
        tx_buf->skb = skb;
        tx_buf->flags = 0;
 
-       bd_prod = TX_BD(fp_tx->tx_bd_prod);
-       tx_start_bd = &fp_tx->tx_desc_ring[bd_prod].start_bd;
+       bd_prod = TX_BD(txdata->tx_bd_prod);
+       tx_start_bd = &txdata->tx_desc_ring[bd_prod].start_bd;
        tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
        tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
        tx_start_bd->nbd = cpu_to_le16(2); /* start + pbd */
@@ -1697,27 +1775,27 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
        /* turn on parsing and get a BD */
        bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
 
-       pbd_e1x = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e1x;
-       pbd_e2 = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e2;
+       pbd_e1x = &txdata->tx_desc_ring[bd_prod].parse_bd_e1x;
+       pbd_e2 = &txdata->tx_desc_ring[bd_prod].parse_bd_e2;
 
        memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
        memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
 
        wmb();
 
-       fp_tx->tx_db.data.prod += 2;
+       txdata->tx_db.data.prod += 2;
        barrier();
-       DOORBELL(bp, fp_tx->index, fp_tx->tx_db.raw);
+       DOORBELL(bp, txdata->cid, txdata->tx_db.raw);
 
        mmiowb();
        barrier();
 
        num_pkts++;
-       fp_tx->tx_bd_prod += 2; /* start + pbd */
+       txdata->tx_bd_prod += 2; /* start + pbd */
 
        udelay(100);
 
-       tx_idx = le16_to_cpu(*fp_tx->tx_cons_sb);
+       tx_idx = le16_to_cpu(*txdata->tx_cons_sb);
        if (tx_idx != tx_start_idx + num_pkts)
                goto test_loopback_exit;
 
@@ -1731,7 +1809,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
                 * bnx2x_tx_int()), as both are taking netif_tx_lock().
                 */
                local_bh_disable();
-               bnx2x_tx_int(fp_tx);
+               bnx2x_tx_int(bp, txdata);
                local_bh_enable();
        }
 
@@ -1751,7 +1829,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
                goto test_loopback_rx_exit;
 
        rx_buf = &fp_rx->rx_buf_ring[RX_BD(fp_rx->rx_bd_cons)];
-       dma_sync_single_for_device(&bp->pdev->dev,
+       dma_sync_single_for_cpu(&bp->pdev->dev,
                                   dma_unmap_addr(rx_buf, mapping),
                                   fp_rx->rx_buf_size, DMA_FROM_DEVICE);
        skb = rx_buf->skb;