be2net: fixup TX-rate setting code for Skyhawk-R
authorRavikumar Nelavelli <ravikumar.nelavelli@emulex.com>
Fri, 30 May 2014 13:36:24 +0000 (19:06 +0530)
committerDavid S. Miller <davem@davemloft.net>
Sat, 31 May 2014 00:27:33 +0000 (17:27 -0700)
Skyhawk-R FW supports TX-rate setting only as a % value of the link
speed, set via the SET_PROFILE_CONFIG cmd.

This patch makes the necessary changes to the FW cmd descriptors to support
the above change and also introduces checks in be_set_vf_tx_rate() to allow
only discrete values (that map to % of the link-speed).

Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_main.c

index 476752d0a6a4c84594838424b7cbfc07c4f9bbf1..216463bd128b490d58b7c6c493ade487e05bf934 100644 (file)
@@ -3562,33 +3562,47 @@ void be_reset_nic_desc(struct be_nic_res_desc *nic)
        nic->cq_count = 0xFFFF;
        nic->toe_conn_count = 0xFFFF;
        nic->eq_count = 0xFFFF;
+       nic->iface_count = 0xFFFF;
        nic->link_param = 0xFF;
+       nic->channel_id_param = cpu_to_le16(0xF000);
        nic->acpi_params = 0xFF;
        nic->wol_param = 0x0F;
-       nic->bw_min = 0xFFFFFFFF;
+       nic->tunnel_iface_count = 0xFFFF;
+       nic->direct_tenant_iface_count = 0xFFFF;
        nic->bw_max = 0xFFFFFFFF;
 }
 
-int be_cmd_config_qos(struct be_adapter *adapter, u32 bps, u8 domain)
+int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed,
+                     u8 domain)
 {
-       if (lancer_chip(adapter)) {
-               struct be_nic_res_desc nic_desc;
+       struct be_nic_res_desc nic_desc;
+       u32 bw_percent;
+       u16 version = 0;
+
+       if (BE3_chip(adapter))
+               return be_cmd_set_qos(adapter, max_rate / 10, domain);
 
-               be_reset_nic_desc(&nic_desc);
+       be_reset_nic_desc(&nic_desc);
+       nic_desc.pf_num = adapter->pf_number;
+       nic_desc.vf_num = domain;
+       if (lancer_chip(adapter)) {
                nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0;
                nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0;
                nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) |
                                        (1 << NOSV_SHIFT);
-               nic_desc.pf_num = adapter->pf_number;
-               nic_desc.vf_num = domain;
-               nic_desc.bw_max = cpu_to_le32(bps);
-
-               return be_cmd_set_profile_config(adapter, &nic_desc,
-                                                RESOURCE_DESC_SIZE_V0,
-                                                0, domain);
+               nic_desc.bw_max = cpu_to_le32(max_rate / 10);
        } else {
-               return be_cmd_set_qos(adapter, bps, domain);
+               version = 1;
+               nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
+               nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
+               nic_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
+               bw_percent = max_rate ? (max_rate * 100) / link_speed : 100;
+               nic_desc.bw_max = cpu_to_le32(bw_percent);
        }
+
+       return be_cmd_set_profile_config(adapter, &nic_desc,
+                                        nic_desc.hdr.desc_len,
+                                        version, domain);
 }
 
 int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op)
index 228d4b611084154f3e3699b7ac23ccc7e5bd6487..9df9d3bfe9073805956779d7c93dd2c2714e4711 100644 (file)
@@ -1891,16 +1891,20 @@ struct be_nic_res_desc {
        u16 cq_count;
        u16 toe_conn_count;
        u16 eq_count;
-       u32 rsvd5;
+       u16 vlan_id;
+       u16 iface_count;
        u32 cap_flags;
        u8 link_param;
-       u8 rsvd6[3];
+       u8 rsvd6;
+       u16 channel_id_param;
        u32 bw_min;
        u32 bw_max;
        u8 acpi_params;
        u8 wol_param;
        u16 rsvd7;
-       u32 rsvd8[7];
+       u16 tunnel_iface_count;
+       u16 direct_tenant_iface_count;
+       u32 rsvd8[6];
 } __packed;
 
 /************ Multi-Channel type ***********/
@@ -2101,7 +2105,8 @@ int be_cmd_get_seeprom_data(struct be_adapter *adapter,
 int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
                        u8 loopback_type, u8 enable);
 int be_cmd_get_phy_info(struct be_adapter *adapter);
-int be_cmd_config_qos(struct be_adapter *adapter, u32 bps, u8 domain);
+int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate,
+                     u16 link_speed, u8 domain);
 void be_detect_error(struct be_adapter *adapter);
 int be_cmd_get_die_temperature(struct be_adapter *adapter);
 int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
index 9116d5e26dab4223dda1ce99671037a678eedcbc..d39a1c611b3b55e554d971458aacd4975784fa3d 100644 (file)
@@ -1352,7 +1352,10 @@ static int be_set_vf_tx_rate(struct net_device *netdev, int vf,
                             int min_tx_rate, int max_tx_rate)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
-       int status = 0;
+       struct device *dev = &adapter->pdev->dev;
+       int percent_rate, status = 0;
+       u16 link_speed = 0;
+       u8 link_status;
 
        if (!sriov_enabled(adapter))
                return -EPERM;
@@ -1363,18 +1366,47 @@ static int be_set_vf_tx_rate(struct net_device *netdev, int vf,
        if (min_tx_rate)
                return -EINVAL;
 
-       if (max_tx_rate < 100 || max_tx_rate > 10000) {
-               dev_err(&adapter->pdev->dev,
-                       "max tx rate must be between 100 and 10000 Mbps\n");
-               return -EINVAL;
+       if (!max_tx_rate)
+               goto config_qos;
+
+       status = be_cmd_link_status_query(adapter, &link_speed,
+                                         &link_status, 0);
+       if (status)
+               goto err;
+
+       if (!link_status) {
+               dev_err(dev, "TX-rate setting not allowed when link is down\n");
+               status = -EPERM;
+               goto err;
+       }
+
+       if (max_tx_rate < 100 || max_tx_rate > link_speed) {
+               dev_err(dev, "TX-rate must be between 100 and %d Mbps\n",
+                       link_speed);
+               status = -EINVAL;
+               goto err;
        }
 
-       status = be_cmd_config_qos(adapter, max_tx_rate / 10, vf + 1);
+       /* On Skyhawk the QOS setting must be done only as a % value */
+       percent_rate = link_speed / 100;
+       if (skyhawk_chip(adapter) && (max_tx_rate % percent_rate)) {
+               dev_err(dev, "TX-rate must be a multiple of %d Mbps\n",
+                       percent_rate);
+               status = -EINVAL;
+               goto err;
+       }
+
+config_qos:
+       status = be_cmd_config_qos(adapter, max_tx_rate, link_speed, vf + 1);
        if (status)
-               dev_err(&adapter->pdev->dev,
-                       "max tx rate %d on VF %d failed\n", max_tx_rate, vf);
-       else
-               adapter->vf_cfg[vf].tx_rate = max_tx_rate;
+               goto err;
+
+       adapter->vf_cfg[vf].tx_rate = max_tx_rate;
+       return 0;
+
+err:
+       dev_err(dev, "TX-rate setting of %dMbps on VF%d failed\n",
+               max_tx_rate, vf);
        return status;
 }
 static int be_set_vf_link_state(struct net_device *netdev, int vf,
@@ -3135,7 +3167,6 @@ static int be_vf_setup(struct be_adapter *adapter)
        struct be_vf_cfg *vf_cfg;
        int status, old_vfs, vf;
        u32 privileges;
-       u16 lnk_speed;
 
        old_vfs = pci_num_vf(adapter->pdev);
        if (old_vfs) {
@@ -3191,16 +3222,9 @@ static int be_vf_setup(struct be_adapter *adapter)
                                         vf);
                }
 
-               /* BE3 FW, by default, caps VF TX-rate to 100mbps.
-                * Allow full available bandwidth
-                */
-               if (BE3_chip(adapter) && !old_vfs)
-                       be_cmd_config_qos(adapter, 1000, vf + 1);
-
-               status = be_cmd_link_status_query(adapter, &lnk_speed,
-                                                 NULL, vf + 1);
-               if (!status)
-                       vf_cfg->tx_rate = lnk_speed;
+               /* Allow full available bandwidth */
+               if (!old_vfs)
+                       be_cmd_config_qos(adapter, 0, 0, vf + 1);
 
                if (!old_vfs) {
                        be_cmd_enable_vf(adapter, vf + 1);