net/mlx4_en: adding loopback support
authorAmir Vadai <amirv@mellanox.co.il>
Sat, 26 Nov 2011 19:55:19 +0000 (19:55 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sun, 27 Nov 2011 22:17:04 +0000 (17:17 -0500)
Device must be in promiscuous mode or DMAC must be same as the host MAC, or
else packet will be dropped by the HW rx filtering.

Signed-off-by: Amir Vadai <amirv@mellanox.co.il>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
include/linux/mlx4/qp.h

index 78d776bc355c747d37fafa77a90117daead68ec3..4c5bbb3aad316f9de27b89a3698cf8f0501e40bd 100644 (file)
@@ -974,6 +974,21 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
+static int mlx4_en_set_features(struct net_device *netdev,
+               netdev_features_t features)
+{
+       struct mlx4_en_priv *priv = netdev_priv(netdev);
+
+       if (features & NETIF_F_LOOPBACK)
+               priv->ctrl_flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK);
+       else
+               priv->ctrl_flags &=
+                       cpu_to_be32(~MLX4_WQE_CTRL_FORCE_LOOPBACK);
+
+       return 0;
+
+}
+
 static const struct net_device_ops mlx4_netdev_ops = {
        .ndo_open               = mlx4_en_open,
        .ndo_stop               = mlx4_en_close,
@@ -990,6 +1005,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = mlx4_en_netpoll,
 #endif
+       .ndo_set_features       = mlx4_en_set_features,
 };
 
 int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
@@ -1022,6 +1038,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        priv->port = port;
        priv->port_up = false;
        priv->flags = prof->flags;
+       priv->ctrl_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
+                       MLX4_WQE_CTRL_SOLICITED);
        priv->tx_ring_num = prof->tx_ring_num;
        priv->rx_ring_num = prof->rx_ring_num;
        priv->mac_index = -1;
@@ -1088,6 +1106,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        dev->features = dev->hw_features | NETIF_F_HIGHDMA |
                        NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
                        NETIF_F_HW_VLAN_FILTER;
+       dev->hw_features |= NETIF_F_LOOPBACK;
 
        mdev->pndev[port] = dev;
 
index 3094f940b928bd71ae3f8ba3167610a89d80c10e..807c2186548c7a2c55106f36d10290cb61feaba2 100644 (file)
@@ -679,8 +679,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
        tx_desc->ctrl.vlan_tag = cpu_to_be16(vlan_tag);
        tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_VLAN * !!vlan_tag;
        tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f;
-       tx_desc->ctrl.srcrb_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
-                                               MLX4_WQE_CTRL_SOLICITED);
+       tx_desc->ctrl.srcrb_flags = priv->ctrl_flags;
        if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
                tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM |
                                                         MLX4_WQE_CTRL_TCP_UDP_CSUM);
index d2dd97fa091fbee1c731a2f04f86113fe879bfa3..ea2ba6899e9a8441b9bd48ebab2fd2029fc1642b 100644 (file)
@@ -453,6 +453,7 @@ struct mlx4_en_priv {
        int base_qpn;
 
        struct mlx4_en_rss_map rss_map;
+       u32 ctrl_flags;
        u32 flags;
 #define MLX4_EN_FLAG_PROMISC   0x1
 #define MLX4_EN_FLAG_MC_PROMISC        0x2
index 6562ff6aa9d69f9e92ed1b339cbff25f7b874c98..bee8fa231276e2d29d7b4419b9ac92e8620fb2d8 100644 (file)
@@ -210,6 +210,7 @@ struct mlx4_wqe_ctrl_seg {
         * [4]   IP checksum
         * [3:2] C (generate completion queue entry)
         * [1]   SE (solicited event)
+        * [0]   FL (force loopback)
         */
        __be32                  srcrb_flags;
        /*