net/mlx4_core: Add retrieval of CONFIG_DEV parameters
authorMatan Barak <matanb@mellanox.com>
Sun, 2 Nov 2014 14:26:17 +0000 (16:26 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 3 Nov 2014 17:28:14 +0000 (12:28 -0500)
Add code to issue CONFIG_DEV "get" firmware command.

This command is used in order to obtain certain parameters used for
supporting various RX checksumming options and vxlan UDP port.

The GET operation is allowed for VFs too.

Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Shani Michaeli <shanim@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
include/linux/mlx4/cmd.h
include/linux/mlx4/device.h

index 1312ccf8b83a4f7b277bc70cfeb8851af0f68478..3c05e5878b49f07477d716160980ab63be07f70f 100644 (file)
@@ -990,11 +990,11 @@ static struct mlx4_cmd_info cmd_info[] = {
        {
                .opcode = MLX4_CMD_CONFIG_DEV,
                .has_inbox = false,
-               .has_outbox = false,
+               .has_outbox = true,
                .out_is_imm = false,
                .encode_slave_id = false,
                .verify = NULL,
-               .wrapper = mlx4_CMD_EPERM_wrapper
+               .wrapper = mlx4_CONFIG_DEV_wrapper
        },
        {
                .opcode = MLX4_CMD_ALLOC_RES,
index e7639e31fc8a60e5be50170efa40c4e25dda522d..d6dba77ae4ba1eae6ffb30e4b9c8892b1892d758 100644 (file)
@@ -141,7 +141,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
                [12] = "Large cache line (>64B) CQE stride support",
                [13] = "Large cache line (>64B) EQE stride support",
                [14] = "Ethernet protocol control support",
-               [15] = "Ethernet Backplane autoneg support"
+               [15] = "Ethernet Backplane autoneg support",
+               [16] = "CONFIG DEV support"
        };
        int i;
 
@@ -574,6 +575,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 #define QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET      0x90
 #define QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET    0x92
 #define QUERY_DEV_CAP_BMME_FLAGS_OFFSET                0x94
+#define QUERY_DEV_CAP_CONFIG_DEV_OFFSET                0x94
 #define QUERY_DEV_CAP_RSVD_LKEY_OFFSET         0x98
 #define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET                0xa0
 #define QUERY_DEV_CAP_ETH_BACKPL_OFFSET                0x9c
@@ -749,6 +751,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
                dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_EQE_STRIDE;
        MLX4_GET(dev_cap->bmme_flags, outbox,
                 QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
+       MLX4_GET(field, outbox, QUERY_DEV_CAP_CONFIG_DEV_OFFSET);
+       if (field & 0x20)
+               dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_CONFIG_DEV;
        MLX4_GET(dev_cap->reserved_lkey, outbox,
                 QUERY_DEV_CAP_RSVD_LKEY_OFFSET);
        MLX4_GET(field32, outbox, QUERY_DEV_CAP_ETH_BACKPL_OFFSET);
@@ -1849,14 +1854,18 @@ int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic)
 
 struct mlx4_config_dev {
        __be32  update_flags;
-       __be32  rsdv1[3];
+       __be32  rsvd1[3];
        __be16  vxlan_udp_dport;
        __be16  rsvd2;
+       __be32  rsvd3[27];
+       __be16  rsvd4;
+       u8      rsvd5;
+       u8      rx_checksum_val;
 };
 
 #define MLX4_VXLAN_UDP_DPORT (1 << 0)
 
-static int mlx4_CONFIG_DEV(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev)
+static int mlx4_CONFIG_DEV_set(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev)
 {
        int err;
        struct mlx4_cmd_mailbox *mailbox;
@@ -1874,6 +1883,77 @@ static int mlx4_CONFIG_DEV(struct mlx4_dev *dev, struct mlx4_config_dev *config_
        return err;
 }
 
+static int mlx4_CONFIG_DEV_get(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev)
+{
+       int err;
+       struct mlx4_cmd_mailbox *mailbox;
+
+       mailbox = mlx4_alloc_cmd_mailbox(dev);
+       if (IS_ERR(mailbox))
+               return PTR_ERR(mailbox);
+
+       err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 1, MLX4_CMD_CONFIG_DEV,
+                          MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
+
+       if (!err)
+               memcpy(config_dev, mailbox->buf, sizeof(*config_dev));
+
+       mlx4_free_cmd_mailbox(dev, mailbox);
+       return err;
+}
+
+/* Conversion between the HW values and the actual functionality.
+ * The value represented by the array index,
+ * and the functionality determined by the flags.
+ */
+static const u8 config_dev_csum_flags[] = {
+       [0] =   0,
+       [1] =   MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP,
+       [2] =   MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP       |
+               MLX4_RX_CSUM_MODE_L4,
+       [3] =   MLX4_RX_CSUM_MODE_L4                    |
+               MLX4_RX_CSUM_MODE_IP_OK_IP_NON_TCP_UDP  |
+               MLX4_RX_CSUM_MODE_MULTI_VLAN
+};
+
+int mlx4_config_dev_retrieval(struct mlx4_dev *dev,
+                             struct mlx4_config_dev_params *params)
+{
+       struct mlx4_config_dev config_dev;
+       int err;
+       u8 csum_mask;
+
+#define CONFIG_DEV_RX_CSUM_MODE_MASK                   0x7
+#define CONFIG_DEV_RX_CSUM_MODE_PORT1_BIT_OFFSET       0
+#define CONFIG_DEV_RX_CSUM_MODE_PORT2_BIT_OFFSET       4
+
+       if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_CONFIG_DEV))
+               return -ENOTSUPP;
+
+       err = mlx4_CONFIG_DEV_get(dev, &config_dev);
+       if (err)
+               return err;
+
+       csum_mask = (config_dev.rx_checksum_val >> CONFIG_DEV_RX_CSUM_MODE_PORT1_BIT_OFFSET) &
+                       CONFIG_DEV_RX_CSUM_MODE_MASK;
+
+       if (csum_mask >= sizeof(config_dev_csum_flags)/sizeof(config_dev_csum_flags[0]))
+               return -EINVAL;
+       params->rx_csum_flags_port_1 = config_dev_csum_flags[csum_mask];
+
+       csum_mask = (config_dev.rx_checksum_val >> CONFIG_DEV_RX_CSUM_MODE_PORT2_BIT_OFFSET) &
+                       CONFIG_DEV_RX_CSUM_MODE_MASK;
+
+       if (csum_mask >= sizeof(config_dev_csum_flags)/sizeof(config_dev_csum_flags[0]))
+               return -EINVAL;
+       params->rx_csum_flags_port_2 = config_dev_csum_flags[csum_mask];
+
+       params->vxlan_udp_dport = be16_to_cpu(config_dev.vxlan_udp_dport);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_config_dev_retrieval);
+
 int mlx4_config_vxlan_port(struct mlx4_dev *dev, __be16 udp_port)
 {
        struct mlx4_config_dev config_dev;
@@ -1882,7 +1962,7 @@ int mlx4_config_vxlan_port(struct mlx4_dev *dev, __be16 udp_port)
        config_dev.update_flags    = cpu_to_be32(MLX4_VXLAN_UDP_DPORT);
        config_dev.vxlan_udp_dport = udp_port;
 
-       return mlx4_CONFIG_DEV(dev, &config_dev);
+       return mlx4_CONFIG_DEV_set(dev, &config_dev);
 }
 EXPORT_SYMBOL_GPL(mlx4_config_vxlan_port);
 
index 254ec7b1ca2ff16773883830ff575f0607d553b6..f8fc7bd6f48bbfdc3368eada86ba9b4f1fb04409 100644 (file)
@@ -947,6 +947,11 @@ int mlx4_SW2HW_EQ_wrapper(struct mlx4_dev *dev, int slave,
                          struct mlx4_cmd_mailbox *inbox,
                          struct mlx4_cmd_mailbox *outbox,
                          struct mlx4_cmd_info *cmd);
+int mlx4_CONFIG_DEV_wrapper(struct mlx4_dev *dev, int slave,
+                           struct mlx4_vhcr *vhcr,
+                           struct mlx4_cmd_mailbox *inbox,
+                           struct mlx4_cmd_mailbox *outbox,
+                           struct mlx4_cmd_info *cmd);
 int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave,
                     struct mlx4_vhcr *vhcr,
                     struct mlx4_cmd_mailbox *inbox,
index 5d2498dcf536d5e96cc13b9274b00137d4508c5d..d718ca0f88dab618f19e55178f7d5a0edb94bcb4 100644 (file)
@@ -2872,6 +2872,23 @@ out_add:
        return err;
 }
 
+int mlx4_CONFIG_DEV_wrapper(struct mlx4_dev *dev, int slave,
+                           struct mlx4_vhcr *vhcr,
+                           struct mlx4_cmd_mailbox *inbox,
+                           struct mlx4_cmd_mailbox *outbox,
+                           struct mlx4_cmd_info *cmd)
+{
+       int err;
+       u8 get = vhcr->op_modifier;
+
+       if (get != 1)
+               return -EPERM;
+
+       err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
+
+       return err;
+}
+
 static int get_containing_mtt(struct mlx4_dev *dev, int slave, int start,
                              int len, struct res_mtt **res)
 {
index ff5f5deb3dcf70703e75e69f357710b8a073239a..64d25941b329918e2c8f232e02431dabfcbc3c8f 100644 (file)
@@ -199,6 +199,33 @@ enum {
        MLX4_CMD_NATIVE
 };
 
+/*
+ * MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP -
+ * Receive checksum value is reported in CQE also for non TCP/UDP packets.
+ *
+ * MLX4_RX_CSUM_MODE_L4 -
+ * L4_CSUM bit in CQE, which indicates whether or not L4 checksum
+ * was validated correctly, is supported.
+ *
+ * MLX4_RX_CSUM_MODE_IP_OK_IP_NON_TCP_UDP -
+ * IP_OK CQE's field is supported also for non TCP/UDP IP packets.
+ *
+ * MLX4_RX_CSUM_MODE_MULTI_VLAN -
+ * Receive Checksum offload is supported for packets with more than 2 vlan headers.
+ */
+enum mlx4_rx_csum_mode {
+       MLX4_RX_CSUM_MODE_VAL_NON_TCP_UDP               = 1UL << 0,
+       MLX4_RX_CSUM_MODE_L4                            = 1UL << 1,
+       MLX4_RX_CSUM_MODE_IP_OK_IP_NON_TCP_UDP          = 1UL << 2,
+       MLX4_RX_CSUM_MODE_MULTI_VLAN                    = 1UL << 3
+};
+
+struct mlx4_config_dev_params {
+       u16     vxlan_udp_dport;
+       u8      rx_csum_flags_port_1;
+       u8      rx_csum_flags_port_2;
+};
+
 struct mlx4_dev;
 
 struct mlx4_cmd_mailbox {
@@ -250,6 +277,8 @@ int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos);
 int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting);
 int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla_vf_info *ivf);
 int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_state);
+int mlx4_config_dev_retrieval(struct mlx4_dev *dev,
+                             struct mlx4_config_dev_params *params);
 /*
  * mlx4_get_slave_default_vlan -
  * return true if VST ( default vlan)
index e4c136ebe79bc9e72c0b493e7ca65e51723f3f8e..5cc5eac47d1b815b0ce9c8e4db62e915b4839d58 100644 (file)
@@ -188,7 +188,8 @@ enum {
        MLX4_DEV_CAP_FLAG2_CQE_STRIDE           = 1LL <<  12,
        MLX4_DEV_CAP_FLAG2_EQE_STRIDE           = 1LL <<  13,
        MLX4_DEV_CAP_FLAG2_ETH_PROT_CTRL        = 1LL <<  14,
-       MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP    = 1LL <<  15
+       MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP    = 1LL <<  15,
+       MLX4_DEV_CAP_FLAG2_CONFIG_DEV           = 1LL <<  16
 };
 
 enum {