be2net: fixup TX-rate setting code for Skyhawk-R
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>
This commit is contained in:
committed by
David S. Miller
parent
a079488570
commit
0f77ba7353
@@ -3562,33 +3562,47 @@ void be_reset_nic_desc(struct be_nic_res_desc *nic)
|
|||||||
nic->cq_count = 0xFFFF;
|
nic->cq_count = 0xFFFF;
|
||||||
nic->toe_conn_count = 0xFFFF;
|
nic->toe_conn_count = 0xFFFF;
|
||||||
nic->eq_count = 0xFFFF;
|
nic->eq_count = 0xFFFF;
|
||||||
|
nic->iface_count = 0xFFFF;
|
||||||
nic->link_param = 0xFF;
|
nic->link_param = 0xFF;
|
||||||
|
nic->channel_id_param = cpu_to_le16(0xF000);
|
||||||
nic->acpi_params = 0xFF;
|
nic->acpi_params = 0xFF;
|
||||||
nic->wol_param = 0x0F;
|
nic->wol_param = 0x0F;
|
||||||
nic->bw_min = 0xFFFFFFFF;
|
nic->tunnel_iface_count = 0xFFFF;
|
||||||
|
nic->direct_tenant_iface_count = 0xFFFF;
|
||||||
nic->bw_max = 0xFFFFFFFF;
|
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;
|
||||||
|
|
||||||
be_reset_nic_desc(&nic_desc);
|
if (BE3_chip(adapter))
|
||||||
|
return be_cmd_set_qos(adapter, max_rate / 10, domain);
|
||||||
|
|
||||||
|
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_type = NIC_RESOURCE_DESC_TYPE_V0;
|
||||||
nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0;
|
nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0;
|
||||||
nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) |
|
nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) |
|
||||||
(1 << NOSV_SHIFT);
|
(1 << NOSV_SHIFT);
|
||||||
nic_desc.pf_num = adapter->pf_number;
|
nic_desc.bw_max = cpu_to_le32(max_rate / 10);
|
||||||
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);
|
|
||||||
} else {
|
} 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)
|
int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op)
|
||||||
|
@@ -1891,16 +1891,20 @@ struct be_nic_res_desc {
|
|||||||
u16 cq_count;
|
u16 cq_count;
|
||||||
u16 toe_conn_count;
|
u16 toe_conn_count;
|
||||||
u16 eq_count;
|
u16 eq_count;
|
||||||
u32 rsvd5;
|
u16 vlan_id;
|
||||||
|
u16 iface_count;
|
||||||
u32 cap_flags;
|
u32 cap_flags;
|
||||||
u8 link_param;
|
u8 link_param;
|
||||||
u8 rsvd6[3];
|
u8 rsvd6;
|
||||||
|
u16 channel_id_param;
|
||||||
u32 bw_min;
|
u32 bw_min;
|
||||||
u32 bw_max;
|
u32 bw_max;
|
||||||
u8 acpi_params;
|
u8 acpi_params;
|
||||||
u8 wol_param;
|
u8 wol_param;
|
||||||
u16 rsvd7;
|
u16 rsvd7;
|
||||||
u32 rsvd8[7];
|
u16 tunnel_iface_count;
|
||||||
|
u16 direct_tenant_iface_count;
|
||||||
|
u32 rsvd8[6];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
/************ Multi-Channel type ***********/
|
/************ 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,
|
int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
|
||||||
u8 loopback_type, u8 enable);
|
u8 loopback_type, u8 enable);
|
||||||
int be_cmd_get_phy_info(struct be_adapter *adapter);
|
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);
|
void be_detect_error(struct be_adapter *adapter);
|
||||||
int be_cmd_get_die_temperature(struct be_adapter *adapter);
|
int be_cmd_get_die_temperature(struct be_adapter *adapter);
|
||||||
int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
|
int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
|
||||||
|
@@ -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)
|
int min_tx_rate, int max_tx_rate)
|
||||||
{
|
{
|
||||||
struct be_adapter *adapter = netdev_priv(netdev);
|
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))
|
if (!sriov_enabled(adapter))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
@@ -1363,18 +1366,47 @@ static int be_set_vf_tx_rate(struct net_device *netdev, int vf,
|
|||||||
if (min_tx_rate)
|
if (min_tx_rate)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (max_tx_rate < 100 || max_tx_rate > 10000) {
|
if (!max_tx_rate)
|
||||||
dev_err(&adapter->pdev->dev,
|
goto config_qos;
|
||||||
"max tx rate must be between 100 and 10000 Mbps\n");
|
|
||||||
return -EINVAL;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = be_cmd_config_qos(adapter, max_tx_rate / 10, vf + 1);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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)
|
if (status)
|
||||||
dev_err(&adapter->pdev->dev,
|
goto err;
|
||||||
"max tx rate %d on VF %d failed\n", max_tx_rate, vf);
|
|
||||||
else
|
adapter->vf_cfg[vf].tx_rate = max_tx_rate;
|
||||||
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;
|
return status;
|
||||||
}
|
}
|
||||||
static int be_set_vf_link_state(struct net_device *netdev, int vf,
|
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;
|
struct be_vf_cfg *vf_cfg;
|
||||||
int status, old_vfs, vf;
|
int status, old_vfs, vf;
|
||||||
u32 privileges;
|
u32 privileges;
|
||||||
u16 lnk_speed;
|
|
||||||
|
|
||||||
old_vfs = pci_num_vf(adapter->pdev);
|
old_vfs = pci_num_vf(adapter->pdev);
|
||||||
if (old_vfs) {
|
if (old_vfs) {
|
||||||
@@ -3191,16 +3222,9 @@ static int be_vf_setup(struct be_adapter *adapter)
|
|||||||
vf);
|
vf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BE3 FW, by default, caps VF TX-rate to 100mbps.
|
/* Allow full available bandwidth */
|
||||||
* Allow full available bandwidth
|
if (!old_vfs)
|
||||||
*/
|
be_cmd_config_qos(adapter, 0, 0, vf + 1);
|
||||||
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;
|
|
||||||
|
|
||||||
if (!old_vfs) {
|
if (!old_vfs) {
|
||||||
be_cmd_enable_vf(adapter, vf + 1);
|
be_cmd_enable_vf(adapter, vf + 1);
|
||||||
|
Reference in New Issue
Block a user