{net, ib}/mlx5: Make cache line size determination at runtime.
[cascardo/linux.git] / drivers / infiniband / hw / mlx5 / main.c
index ed038b7..63036c7 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
-#include <linux/io-mapping.h>
 #if defined(CONFIG_X86)
 #include <asm/pat.h>
 #endif
@@ -54,7 +53,6 @@
 #include <linux/in.h>
 #include <linux/etherdevice.h>
 #include <linux/mlx5/fs.h>
-#include "user.h"
 #include "mlx5_ib.h"
 
 #define DRIVER_NAME "mlx5_ib"
@@ -118,8 +116,17 @@ static int mlx5_netdev_event(struct notifier_block *this,
                break;
 
        case NETDEV_UP:
-       case NETDEV_DOWN:
-               if (ndev == ibdev->roce.netdev && ibdev->ib_active) {
+       case NETDEV_DOWN: {
+               struct net_device *lag_ndev = mlx5_lag_get_roce_netdev(ibdev->mdev);
+               struct net_device *upper = NULL;
+
+               if (lag_ndev) {
+                       upper = netdev_master_upper_dev_get(lag_ndev);
+                       dev_put(lag_ndev);
+               }
+
+               if ((upper == ndev || (!upper && ndev == ibdev->roce.netdev))
+                   && ibdev->ib_active) {
                        struct ib_event ibev = {0};
 
                        ibev.device = &ibdev->ib_dev;
@@ -129,6 +136,7 @@ static int mlx5_netdev_event(struct notifier_block *this,
                        ib_dispatch_event(&ibev);
                }
                break;
+       }
 
        default:
                break;
@@ -143,6 +151,10 @@ static struct net_device *mlx5_ib_get_netdev(struct ib_device *device,
        struct mlx5_ib_dev *ibdev = to_mdev(device);
        struct net_device *ndev;
 
+       ndev = mlx5_lag_get_roce_netdev(ibdev->mdev);
+       if (ndev)
+               return ndev;
+
        /* Ensure ndev does not disappear before we invoke dev_hold()
         */
        read_lock(&ibdev->roce.netdev_lock);
@@ -158,7 +170,7 @@ static int mlx5_query_port_roce(struct ib_device *device, u8 port_num,
                                struct ib_port_attr *props)
 {
        struct mlx5_ib_dev *dev = to_mdev(device);
-       struct net_device *ndev;
+       struct net_device *ndev, *upper;
        enum ib_mtu ndev_ib_mtu;
        u16 qkey_viol_cntr;
 
@@ -182,6 +194,17 @@ static int mlx5_query_port_roce(struct ib_device *device, u8 port_num,
        if (!ndev)
                return 0;
 
+       if (mlx5_lag_is_active(dev->mdev)) {
+               rcu_read_lock();
+               upper = netdev_master_upper_dev_get_rcu(ndev);
+               if (upper) {
+                       dev_put(ndev);
+                       ndev = upper;
+                       dev_hold(ndev);
+               }
+               rcu_read_unlock();
+       }
+
        if (netif_running(ndev) && netif_carrier_ok(ndev)) {
                props->state      = IB_PORT_ACTIVE;
                props->phys_state = 5;
@@ -304,7 +327,9 @@ __be16 mlx5_get_roce_udp_sport(struct mlx5_ib_dev *dev, u8 port_num,
 
 static int mlx5_use_mad_ifc(struct mlx5_ib_dev *dev)
 {
-       return !MLX5_CAP_GEN(dev->mdev, ib_virt);
+       if (MLX5_CAP_GEN(dev->mdev, port_type) == MLX5_CAP_PORT_TYPE_IB)
+               return !MLX5_CAP_GEN(dev->mdev, ib_virt);
+       return 0;
 }
 
 enum {
@@ -447,7 +472,7 @@ static int mlx5_query_node_guid(struct mlx5_ib_dev *dev,
 }
 
 struct mlx5_reg_node_desc {
-       u8      desc[64];
+       u8      desc[IB_DEVICE_NODE_DESC_MAX];
 };
 
 static int mlx5_query_node_desc(struct mlx5_ib_dev *dev, char *node_desc)
@@ -895,13 +920,13 @@ static int mlx5_ib_modify_device(struct ib_device *ibdev, int mask,
         * If possible, pass node desc to FW, so it can generate
         * a 144 trap.  If cmd fails, just ignore.
         */
-       memcpy(&in, props->node_desc, 64);
+       memcpy(&in, props->node_desc, IB_DEVICE_NODE_DESC_MAX);
        err = mlx5_core_access_reg(dev->mdev, &in, sizeof(in), &out,
                                   sizeof(out), MLX5_REG_NODE_DESC, 0, 1);
        if (err)
                return err;
 
-       memcpy(ibdev->node_desc, props->node_desc, 64);
+       memcpy(ibdev->node_desc, props->node_desc, IB_DEVICE_NODE_DESC_MAX);
 
        return err;
 }
@@ -994,7 +1019,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
        resp.qp_tab_size = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp);
        if (mlx5_core_is_pf(dev->mdev) && MLX5_CAP_GEN(dev->mdev, bf))
                resp.bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev, log_bf_reg_size);
-       resp.cache_line_size = L1_CACHE_BYTES;
+       resp.cache_line_size = cache_line_size();
        resp.max_sq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq);
        resp.max_rq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq);
        resp.max_send_wqebb = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz);
@@ -1523,6 +1548,13 @@ static int parse_flow_attr(u32 *match_c, u32 *match_v,
                                             dmac_47_16),
                                ib_spec->eth.val.dst_mac);
 
+               ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
+                                            smac_47_16),
+                               ib_spec->eth.mask.src_mac);
+               ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_v,
+                                            smac_47_16),
+                               ib_spec->eth.val.src_mac);
+
                if (ib_spec->eth.mask.vlan_tag) {
                        MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
                                 vlan_tag, 1);
@@ -2026,6 +2058,7 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
                                           int domain)
 {
        struct mlx5_ib_dev *dev = to_mdev(qp->device);
+       struct mlx5_ib_qp *mqp = to_mqp(qp);
        struct mlx5_ib_flow_handler *handler = NULL;
        struct mlx5_flow_destination *dst = NULL;
        struct mlx5_ib_flow_prio *ft_prio_tx = NULL;
@@ -2061,7 +2094,10 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
        }
 
        dst->type = MLX5_FLOW_DESTINATION_TYPE_TIR;
-       dst->tir_num = to_mqp(qp)->raw_packet_qp.rq.tirn;
+       if (mqp->flags & MLX5_IB_QP_RSS)
+               dst->tir_num = mqp->rss_qp.tirn;
+       else
+               dst->tir_num = mqp->raw_packet_qp.rq.tirn;
 
        if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
                if (flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP)  {
@@ -2703,6 +2739,47 @@ static void get_dev_fw_str(struct ib_device *ibdev, char *str,
                       fw_rev_min(dev->mdev), fw_rev_sub(dev->mdev));
 }
 
+static int mlx5_roce_lag_init(struct mlx5_ib_dev *dev)
+{
+       struct mlx5_core_dev *mdev = dev->mdev;
+       struct mlx5_flow_namespace *ns = mlx5_get_flow_namespace(mdev,
+                                                                MLX5_FLOW_NAMESPACE_LAG);
+       struct mlx5_flow_table *ft;
+       int err;
+
+       if (!ns || !mlx5_lag_is_active(mdev))
+               return 0;
+
+       err = mlx5_cmd_create_vport_lag(mdev);
+       if (err)
+               return err;
+
+       ft = mlx5_create_lag_demux_flow_table(ns, 0, 0);
+       if (IS_ERR(ft)) {
+               err = PTR_ERR(ft);
+               goto err_destroy_vport_lag;
+       }
+
+       dev->flow_db.lag_demux_ft = ft;
+       return 0;
+
+err_destroy_vport_lag:
+       mlx5_cmd_destroy_vport_lag(mdev);
+       return err;
+}
+
+static void mlx5_roce_lag_cleanup(struct mlx5_ib_dev *dev)
+{
+       struct mlx5_core_dev *mdev = dev->mdev;
+
+       if (dev->flow_db.lag_demux_ft) {
+               mlx5_destroy_flow_table(dev->flow_db.lag_demux_ft);
+               dev->flow_db.lag_demux_ft = NULL;
+
+               mlx5_cmd_destroy_vport_lag(mdev);
+       }
+}
+
 static void mlx5_remove_roce_notifier(struct mlx5_ib_dev *dev)
 {
        if (dev->roce.nb.notifier_call) {
@@ -2726,8 +2803,15 @@ static int mlx5_enable_roce(struct mlx5_ib_dev *dev)
        if (err)
                goto err_unregister_netdevice_notifier;
 
+       err = mlx5_roce_lag_init(dev);
+       if (err)
+               goto err_disable_roce;
+
        return 0;
 
+err_disable_roce:
+       mlx5_nic_vport_disable_roce(dev->mdev);
+
 err_unregister_netdevice_notifier:
        mlx5_remove_roce_notifier(dev);
        return err;
@@ -2735,6 +2819,7 @@ err_unregister_netdevice_notifier:
 
 static void mlx5_disable_roce(struct mlx5_ib_dev *dev)
 {
+       mlx5_roce_lag_cleanup(dev);
        mlx5_nic_vport_disable_roce(dev->mdev);
 }
 
@@ -2850,6 +2935,7 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
        struct mlx5_ib_dev *dev;
        enum rdma_link_layer ll;
        int port_type_cap;
+       const char *name;
        int err;
        int i;
 
@@ -2882,7 +2968,12 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
 
        MLX5_INIT_DOORBELL_LOCK(&dev->uar_lock);
 
-       strlcpy(dev->ib_dev.name, "mlx5_%d", IB_DEVICE_NAME_MAX);
+       if (!mlx5_lag_is_active(mdev))
+               name = "mlx5_%d";
+       else
+               name = "mlx5_bond_%d";
+
+       strlcpy(dev->ib_dev.name, name, IB_DEVICE_NAME_MAX);
        dev->ib_dev.owner               = THIS_MODULE;
        dev->ib_dev.node_type           = RDMA_NODE_IB_CA;
        dev->ib_dev.local_dma_lkey      = 0 /* not supported for now */;