Merge branch 'mlx-next'
authorDavid S. Miller <davem@davemloft.net>
Wed, 24 Jun 2015 07:42:48 +0000 (00:42 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 24 Jun 2015 07:42:48 +0000 (00:42 -0700)
Or Gerlitz says:

====================
Mellanox NIC drivers update, June 23 2015

This series has two fixes from Eran to his recent SRIOV counters work in
mlx4 and few more updates from Saeed and Achiad to the mlx5 Ethernet
code. All fixes here relate to net-next code, so no need for -stable.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx4/en_port.c
drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c

index 73f6277d9ac1e454b726e5efecb8072f90420786..ee99e67187f5b1cc68fc224b91d5b2bf2d133b05 100644 (file)
@@ -203,6 +203,20 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
                priv->port_stats.tso_packets       += ring->tso_packets;
                priv->port_stats.xmit_more         += ring->xmit_more;
        }
+       if (mlx4_is_master(mdev->dev)) {
+               stats->rx_packets = en_stats_adder(&mlx4_en_stats->RTOT_prio_0,
+                                                  &mlx4_en_stats->RTOT_prio_1,
+                                                  NUM_PRIORITIES);
+               stats->tx_packets = en_stats_adder(&mlx4_en_stats->TTOT_prio_0,
+                                                  &mlx4_en_stats->TTOT_prio_1,
+                                                  NUM_PRIORITIES);
+               stats->rx_bytes = en_stats_adder(&mlx4_en_stats->ROCT_prio_0,
+                                                &mlx4_en_stats->ROCT_prio_1,
+                                                NUM_PRIORITIES);
+               stats->tx_bytes = en_stats_adder(&mlx4_en_stats->TOCT_prio_0,
+                                                &mlx4_en_stats->TOCT_prio_1,
+                                                NUM_PRIORITIES);
+       }
 
        /* net device stats */
        stats->rx_errors = be64_to_cpu(mlx4_en_stats->PCS) +
index c5c1de9cf2cec44a80b37ccc311872561e50501d..7fd466c0b929b63ede0111b1b7d03b961f992abd 100644 (file)
@@ -79,8 +79,7 @@ struct mlx4_en_flow_stats_tx {
 
 #define NUM_FLOW_STATS (NUM_FLOW_STATS_RX + NUM_FLOW_STATS_TX + \
                        NUM_FLOW_PRIORITY_STATS_TX + \
-                       NUM_FLOW_PRIORITY_STATS_RX + \
-                       NUM_PF_STATS)
+                       NUM_FLOW_PRIORITY_STATS_RX)
 
 struct mlx4_en_stat_out_flow_control_mbox {
        /* Total number of PAUSE frames received from the far-end port */
@@ -108,7 +107,7 @@ enum {
 };
 
 #define NUM_ALL_STATS  (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + \
-                        NUM_FLOW_STATS + NUM_PERF_STATS)
+                        NUM_FLOW_STATS + NUM_PERF_STATS + NUM_PF_STATS)
 
 #define MLX4_FIND_NETDEV_STAT(n) (offsetof(struct net_device_stats, n) / \
                                  sizeof(((struct net_device_stats *)0)->n))
index e14120eccf04ced0d5d641b4acb62a05668b5a4a..3d23bd657e3c0cf7dc6d1d61c530a2d15053712a 100644 (file)
@@ -208,7 +208,6 @@ enum cq_flags {
 struct mlx5e_cq {
        /* data path - accessed per cqe */
        struct mlx5_cqwq           wq;
-       void                      *sqrq;
        unsigned long              flags;
 
        /* data path - accessed per napi poll */
@@ -316,6 +315,7 @@ struct mlx5e_channel {
        __be32                     mkey_be;
        u8                         num_tc;
        unsigned long              flags;
+       int                        tc_to_txq_map[MLX5E_MAX_NUM_TC];
 
        /* control */
        struct mlx5e_priv         *priv;
@@ -379,10 +379,9 @@ struct mlx5e_flow_table {
 
 struct mlx5e_priv {
        /* priv data path fields - start */
-       int                        order_base_2_num_channels;
-       int                        queue_mapping_channel_mask;
        int                        num_tc;
        int                        default_vlan_prio;
+       struct mlx5e_sq            **txq_to_sq_map;
        /* priv data path fields - end */
 
        unsigned long              state;
@@ -460,7 +459,6 @@ void mlx5e_send_nop(struct mlx5e_sq *sq, bool notify_hw);
 u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb,
                       void *accel_priv, select_queue_fallback_t fallback);
 netdev_tx_t mlx5e_xmit(struct sk_buff *skb, struct net_device *dev);
-netdev_tx_t mlx5e_xmit_multi_tc(struct sk_buff *skb, struct net_device *dev);
 
 void mlx5e_completion_event(struct mlx5_core_cq *mcq);
 void mlx5e_cq_error_event(struct mlx5_core_cq *mcq, enum mlx5_event event);
index 9a48d8eac0fcc89227eef9d969ff69396093fe15..40206da1f9d7b9e24ebd972e2b798f05dc4be46b 100644 (file)
@@ -345,7 +345,6 @@ static int mlx5e_enable_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param)
        MLX5_SET(rqc,  rqc, cqn,                c->rq.cq.mcq.cqn);
        MLX5_SET(rqc,  rqc, state,              MLX5_RQC_STATE_RST);
        MLX5_SET(rqc,  rqc, flush_in_error_en,  1);
-       MLX5_SET(wq,   wq,  wq_type,            MLX5_WQ_TYPE_LINKED_LIST);
        MLX5_SET(wq,   wq,  log_wq_pg_sz,       rq->wq_ctrl.buf.page_shift -
                                                PAGE_SHIFT);
        MLX5_SET64(wq, wq,  dbr_addr,           rq->wq_ctrl.db.dma);
@@ -496,6 +495,7 @@ static int mlx5e_create_sq(struct mlx5e_channel *c,
 
        void *sqc = param->sqc;
        void *sqc_wq = MLX5_ADDR_OF(sqc, sqc, wq);
+       int txq_ix;
        int err;
 
        err = mlx5_alloc_map_uar(mdev, &sq->uar);
@@ -515,14 +515,15 @@ static int mlx5e_create_sq(struct mlx5e_channel *c,
        if (err)
                goto err_sq_wq_destroy;
 
-       sq->txq = netdev_get_tx_queue(priv->netdev,
-                                     c->ix + tc * priv->params.num_channels);
+       txq_ix = c->ix + tc * priv->params.num_channels;
+       sq->txq = netdev_get_tx_queue(priv->netdev, txq_ix);
 
        sq->pdev    = c->pdev;
        sq->mkey_be = c->mkey_be;
        sq->channel = c;
        sq->tc      = tc;
        sq->edge    = (sq->wq.sz_m1 + 1) - MLX5_SEND_WQE_MAX_WQEBBS;
+       priv->txq_to_sq_map[txq_ix] = sq;
 
        return 0;
 
@@ -852,8 +853,6 @@ static int mlx5e_open_tx_cqs(struct mlx5e_channel *c,
                                    priv->params.tx_cq_moderation_pkts);
                if (err)
                        goto err_close_tx_cqs;
-
-               c->sq[tc].cq.sqrq = &c->sq[tc];
        }
 
        return 0;
@@ -902,6 +901,15 @@ static void mlx5e_close_sqs(struct mlx5e_channel *c)
                mlx5e_close_sq(&c->sq[tc]);
 }
 
+static void mlx5e_build_tc_to_txq_map(struct mlx5e_channel *c,
+                                     int num_channels)
+{
+       int i;
+
+       for (i = 0; i < MLX5E_MAX_NUM_TC; i++)
+               c->tc_to_txq_map[i] = c->ix + i * num_channels;
+}
+
 static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
                              struct mlx5e_channel_param *cparam,
                              struct mlx5e_channel **cp)
@@ -923,6 +931,8 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
        c->mkey_be  = cpu_to_be32(priv->mr.key);
        c->num_tc   = priv->num_tc;
 
+       mlx5e_build_tc_to_txq_map(c, priv->params.num_channels);
+
        netif_napi_add(netdev, &c->napi, mlx5e_napi_poll, 64);
 
        err = mlx5e_open_tx_cqs(c, cparam);
@@ -934,7 +944,6 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
                            priv->params.rx_cq_moderation_pkts);
        if (err)
                goto err_close_tx_cqs;
-       c->rq.cq.sqrq = &c->rq;
 
        napi_enable(&c->napi);
 
@@ -1050,14 +1059,18 @@ static void mlx5e_build_channel_param(struct mlx5e_priv *priv,
 static int mlx5e_open_channels(struct mlx5e_priv *priv)
 {
        struct mlx5e_channel_param cparam;
-       int err;
+       int err = -ENOMEM;
        int i;
        int j;
 
        priv->channel = kcalloc(priv->params.num_channels,
                                sizeof(struct mlx5e_channel *), GFP_KERNEL);
-       if (!priv->channel)
-               return -ENOMEM;
+
+       priv->txq_to_sq_map = kcalloc(priv->params.num_channels * priv->num_tc,
+                                     sizeof(struct mlx5e_sq *), GFP_KERNEL);
+
+       if (!priv->channel || !priv->txq_to_sq_map)
+               goto err_free_txq_to_sq_map;
 
        mlx5e_build_channel_param(priv, &cparam);
        for (i = 0; i < priv->params.num_channels; i++) {
@@ -1078,6 +1091,8 @@ err_close_channels:
        for (i--; i >= 0; i--)
                mlx5e_close_channel(priv->channel[i]);
 
+err_free_txq_to_sq_map:
+       kfree(priv->txq_to_sq_map);
        kfree(priv->channel);
 
        return err;
@@ -1090,6 +1105,7 @@ static void mlx5e_close_channels(struct mlx5e_priv *priv)
        for (i = 0; i < priv->params.num_channels; i++)
                mlx5e_close_channel(priv->channel[i]);
 
+       kfree(priv->txq_to_sq_map);
        kfree(priv->channel);
 }
 
@@ -1384,8 +1400,7 @@ int mlx5e_open_locked(struct net_device *netdev)
        int num_txqs;
        int err;
 
-       num_txqs = roundup_pow_of_two(priv->params.num_channels) *
-                  priv->params.num_tc;
+       num_txqs = priv->params.num_channels * priv->params.num_tc;
        netif_set_real_num_tx_queues(netdev, num_txqs);
        netif_set_real_num_rx_queues(netdev, priv->params.num_channels);
 
@@ -1693,9 +1708,6 @@ static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev,
        priv->mdev                         = mdev;
        priv->netdev                       = netdev;
        priv->params.num_channels          = num_comp_vectors;
-       priv->order_base_2_num_channels    = order_base_2(num_comp_vectors);
-       priv->queue_mapping_channel_mask   =
-               roundup_pow_of_two(num_comp_vectors) - 1;
        priv->num_tc                       = priv->params.num_tc;
        priv->default_vlan_prio            = priv->params.default_vlan_prio;
 
@@ -1723,7 +1735,6 @@ static void mlx5e_build_netdev(struct net_device *netdev)
 
        if (priv->num_tc > 1) {
                mlx5e_netdev_ops.ndo_select_queue = mlx5e_select_queue;
-               mlx5e_netdev_ops.ndo_start_xmit   = mlx5e_xmit_multi_tc;
        }
 
        netdev->netdev_ops        = &mlx5e_netdev_ops;
@@ -1793,9 +1804,7 @@ static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev)
        if (mlx5e_check_required_hca_cap(mdev))
                return NULL;
 
-       netdev = alloc_etherdev_mqs(sizeof(struct mlx5e_priv),
-                                   roundup_pow_of_two(ncv) * MLX5E_MAX_NUM_TC,
-                                   ncv);
+       netdev = alloc_etherdev_mqs(sizeof(struct mlx5e_priv), ncv, ncv);
        if (!netdev) {
                mlx5_core_err(mdev, "alloc_etherdev_mqs() failed\n");
                return NULL;
index 06e7c744ed4a6071de2643a9c7ae3df0eaa3391b..9a9374131f5b45e7c740f80e2ef8b0e9ba175fa9 100644 (file)
@@ -191,7 +191,7 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe,
 
 bool mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
 {
-       struct mlx5e_rq *rq = cq->sqrq;
+       struct mlx5e_rq *rq = container_of(cq, struct mlx5e_rq, cq);
        int i;
 
        /* avoid accessing cq (dma coherent memory) if not needed */
@@ -209,10 +209,13 @@ bool mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
                if (!cqe)
                        break;
 
+               mlx5_cqwq_pop(&cq->wq);
+
                wqe_counter_be = cqe->wqe_counter;
                wqe_counter    = be16_to_cpu(wqe_counter_be);
                wqe            = mlx5_wq_ll_get_wqe(&rq->wq, wqe_counter);
                skb            = rq->skb[wqe_counter];
+               prefetch(skb->data);
                rq->skb[wqe_counter] = NULL;
 
                dma_unmap_single(rq->pdev,
index bac268a670f46b09a8c8f610453611c0ef218977..03f28f438e55ab690cc865b6bc3509a53d280e25 100644 (file)
@@ -106,7 +106,7 @@ u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb,
                 priv->default_vlan_prio;
        int tc = netdev_get_prio_tc_map(dev, up);
 
-       return (tc << priv->order_base_2_num_channels) | channel_ix;
+       return priv->channel[channel_ix]->tc_to_txq_map[tc];
 }
 
 static inline u16 mlx5e_get_inline_hdr_size(struct mlx5e_sq *sq,
@@ -143,20 +143,17 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
 
        if (skb_is_gso(skb)) {
                u32 payload_len;
-               int num_pkts;
 
                eseg->mss    = cpu_to_be16(skb_shinfo(skb)->gso_size);
                opcode       = MLX5_OPCODE_LSO;
                ihs          = skb_transport_offset(skb) + tcp_hdrlen(skb);
                payload_len  = skb->len - ihs;
-               num_pkts     =    (payload_len / skb_shinfo(skb)->gso_size) +
-                               !!(payload_len % skb_shinfo(skb)->gso_size);
                MLX5E_TX_SKB_CB(skb)->num_bytes = skb->len +
-                                                 (num_pkts - 1) * ihs;
+                                       (skb_shinfo(skb)->gso_segs - 1) * ihs;
                sq->stats.tso_packets++;
                sq->stats.tso_bytes += payload_len;
        } else {
-               ihs             = mlx5e_get_inline_hdr_size(sq, skb);
+               ihs = mlx5e_get_inline_hdr_size(sq, skb);
                MLX5E_TX_SKB_CB(skb)->num_bytes = max_t(unsigned int, skb->len,
                                                        ETH_ZLEN);
        }
@@ -164,7 +161,7 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
        skb_copy_from_linear_data(skb, eseg->inline_hdr_start, ihs);
        skb_pull_inline(skb, ihs);
 
-       eseg->inline_hdr_sz     = cpu_to_be16(ihs);
+       eseg->inline_hdr_sz = cpu_to_be16(ihs);
 
        ds_cnt  = sizeof(*wqe) / MLX5_SEND_WQE_DS;
        ds_cnt += DIV_ROUND_UP(ihs - sizeof(eseg->inline_hdr_start),
@@ -211,9 +208,8 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
 
        ds_cnt += MLX5E_TX_SKB_CB(skb)->num_dma;
 
-       cseg->opmod_idx_opcode  = cpu_to_be32((sq->pc << 8) | opcode);
-       cseg->qpn_ds            = cpu_to_be32((sq->sqn << 8) | ds_cnt);
-       cseg->fm_ce_se          = MLX5_WQE_CTRL_CQ_UPDATE;
+       cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8) | opcode);
+       cseg->qpn_ds           = cpu_to_be32((sq->sqn << 8) | ds_cnt);
 
        sq->skb[pi] = skb;
 
@@ -228,8 +224,10 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
                sq->stats.stopped++;
        }
 
-       if (!skb->xmit_more || netif_xmit_stopped(sq->txq))
+       if (!skb->xmit_more || netif_xmit_stopped(sq->txq)) {
+               cseg->fm_ce_se = MLX5_WQE_CTRL_CQ_UPDATE;
                mlx5e_tx_notify_hw(sq, wqe);
+       }
 
        /* fill sq edge with nops to avoid wqe wrap around */
        while ((sq->pc & wq->sz_m1) > sq->edge)
@@ -250,21 +248,7 @@ dma_unmap_wqe_err:
 netdev_tx_t mlx5e_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
-       int ix = skb->queue_mapping;
-       int tc = 0;
-       struct mlx5e_channel *c = priv->channel[ix];
-       struct mlx5e_sq *sq = &c->sq[tc];
-
-       return mlx5e_sq_xmit(sq, skb);
-}
-
-netdev_tx_t mlx5e_xmit_multi_tc(struct sk_buff *skb, struct net_device *dev)
-{
-       struct mlx5e_priv *priv = netdev_priv(dev);
-       int ix = skb->queue_mapping & priv->queue_mapping_channel_mask;
-       int tc = skb->queue_mapping >> priv->order_base_2_num_channels;
-       struct mlx5e_channel *c = priv->channel[ix];
-       struct mlx5e_sq *sq = &c->sq[tc];
+       struct mlx5e_sq *sq = priv->txq_to_sq_map[skb_get_queue_mapping(skb)];
 
        return mlx5e_sq_xmit(sq, skb);
 }
@@ -282,7 +266,7 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq)
        if (!test_and_clear_bit(MLX5E_CQ_HAS_CQES, &cq->flags))
                return false;
 
-       sq = cq->sqrq;
+       sq = container_of(cq, struct mlx5e_sq, cq);
 
        npkts = 0;
        nbytes = 0;
@@ -297,38 +281,48 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq)
 
        for (i = 0; i < MLX5E_TX_CQ_POLL_BUDGET; i++) {
                struct mlx5_cqe64 *cqe;
-               struct sk_buff *skb;
-               u16 ci;
-               int j;
+               u16 wqe_counter;
+               bool last_wqe;
 
                cqe = mlx5e_get_cqe(cq);
                if (!cqe)
                        break;
 
-               ci = sqcc & sq->wq.sz_m1;
-               skb = sq->skb[ci];
+               mlx5_cqwq_pop(&cq->wq);
+
+               wqe_counter = be16_to_cpu(cqe->wqe_counter);
+
+               do {
+                       struct sk_buff *skb;
+                       u16 ci;
+                       int j;
+
+                       last_wqe = (sqcc == wqe_counter);
 
-               if (unlikely(!skb)) { /* nop */
-                       sq->stats.nop++;
-                       sqcc++;
-                       goto free_skb;
-               }
+                       ci = sqcc & sq->wq.sz_m1;
+                       skb = sq->skb[ci];
 
-               for (j = 0; j < MLX5E_TX_SKB_CB(skb)->num_dma; j++) {
-                       dma_addr_t addr;
-                       u32 size;
+                       if (unlikely(!skb)) { /* nop */
+                               sq->stats.nop++;
+                               sqcc++;
+                               continue;
+                       }
 
-                       mlx5e_dma_get(sq, dma_fifo_cc, &addr, &size);
-                       dma_fifo_cc++;
-                       dma_unmap_single(sq->pdev, addr, size, DMA_TO_DEVICE);
-               }
+                       for (j = 0; j < MLX5E_TX_SKB_CB(skb)->num_dma; j++) {
+                               dma_addr_t addr;
+                               u32 size;
 
-               npkts++;
-               nbytes += MLX5E_TX_SKB_CB(skb)->num_bytes;
-               sqcc += MLX5E_TX_SKB_CB(skb)->num_wqebbs;
+                               mlx5e_dma_get(sq, dma_fifo_cc, &addr, &size);
+                               dma_fifo_cc++;
+                               dma_unmap_single(sq->pdev, addr, size,
+                                                DMA_TO_DEVICE);
+                       }
 
-free_skb:
-               dev_kfree_skb(skb);
+                       npkts++;
+                       nbytes += MLX5E_TX_SKB_CB(skb)->num_bytes;
+                       sqcc += MLX5E_TX_SKB_CB(skb)->num_wqebbs;
+                       dev_kfree_skb(skb);
+               } while (!last_wqe);
        }
 
        mlx5_cqwq_update_db_record(&cq->wq);
index 088bc424157c7a76f777c212a0cb2d6da7549a3d..2c7cb6755d1d7d73c48a89cf621a0c74d1dc745b 100644 (file)
@@ -43,8 +43,6 @@ struct mlx5_cqe64 *mlx5e_get_cqe(struct mlx5e_cq *cq)
        if (cqe_ownership_bit != sw_ownership_val)
                return NULL;
 
-       mlx5_cqwq_pop(wq);
-
        /* ensure cqe content is read after cqe ownership bit */
        rmb();
 
@@ -65,7 +63,7 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
 
        busy |= mlx5e_poll_rx_cq(&c->rq.cq, budget);
 
-       busy |= mlx5e_post_rx_wqes(c->rq.cq.sqrq);
+       busy |= mlx5e_post_rx_wqes(&c->rq);
 
        if (busy)
                return budget;