Skip to content

Commit 8ea4fae

Browse files
Ganesh Goudardavem330
Ganesh Goudar
authored andcommitted
cxgb4: implement ndo_set_vf_rate()
Implement ndo_set_vf_rate() for mgmt interface to support rate-limiting of VF traffic using 'ip' command. Based on the original work of Kumar Sanghvi <[email protected]> Signed-off-by: Ganesh Goudar <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4f5a984 commit 8ea4fae

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed

Diff for: drivers/net/ethernet/chelsio/cxgb4/cxgb4.h

+1
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,7 @@ struct uld_msix_info {
777777

778778
struct vf_info {
779779
unsigned char vf_mac_addr[ETH_ALEN];
780+
unsigned int tx_rate;
780781
bool pf_set_mac;
781782
};
782783

Diff for: drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c

+106
Original file line numberDiff line numberDiff line change
@@ -2563,6 +2563,8 @@ static int cxgb_get_vf_config(struct net_device *dev,
25632563
if (vf >= adap->num_vfs)
25642564
return -EINVAL;
25652565
ivi->vf = vf;
2566+
ivi->max_tx_rate = adap->vfinfo[vf].tx_rate;
2567+
ivi->min_tx_rate = 0;
25662568
ether_addr_copy(ivi->mac, adap->vfinfo[vf].vf_mac_addr);
25672569
return 0;
25682570
}
@@ -2579,6 +2581,109 @@ static int cxgb_get_phys_port_id(struct net_device *dev,
25792581
return 0;
25802582
}
25812583

2584+
static int cxgb_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate,
2585+
int max_tx_rate)
2586+
{
2587+
struct port_info *pi = netdev_priv(dev);
2588+
struct adapter *adap = pi->adapter;
2589+
struct fw_port_cmd port_cmd, port_rpl;
2590+
u32 link_status, speed = 0;
2591+
u32 fw_pfvf, fw_class;
2592+
int class_id = vf;
2593+
int link_ok, ret;
2594+
u16 pktsize;
2595+
2596+
if (vf >= adap->num_vfs)
2597+
return -EINVAL;
2598+
2599+
if (min_tx_rate) {
2600+
dev_err(adap->pdev_dev,
2601+
"Min tx rate (%d) (> 0) for VF %d is Invalid.\n",
2602+
min_tx_rate, vf);
2603+
return -EINVAL;
2604+
}
2605+
/* Retrieve link details for VF port */
2606+
memset(&port_cmd, 0, sizeof(port_cmd));
2607+
port_cmd.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) |
2608+
FW_CMD_REQUEST_F |
2609+
FW_CMD_READ_F |
2610+
FW_PORT_CMD_PORTID_V(pi->port_id));
2611+
port_cmd.action_to_len16 =
2612+
cpu_to_be32(FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_GET_PORT_INFO) |
2613+
FW_LEN16(port_cmd));
2614+
ret = t4_wr_mbox(adap, adap->mbox, &port_cmd, sizeof(port_cmd),
2615+
&port_rpl);
2616+
if (ret != FW_SUCCESS) {
2617+
dev_err(adap->pdev_dev,
2618+
"Failed to get link status for VF %d\n", vf);
2619+
return -EINVAL;
2620+
}
2621+
link_status = be32_to_cpu(port_rpl.u.info.lstatus_to_modtype);
2622+
link_ok = (link_status & FW_PORT_CMD_LSTATUS_F) != 0;
2623+
if (!link_ok) {
2624+
dev_err(adap->pdev_dev, "Link down for VF %d\n", vf);
2625+
return -EINVAL;
2626+
}
2627+
/* Determine link speed */
2628+
if (link_status & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M))
2629+
speed = 100;
2630+
else if (link_status & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G))
2631+
speed = 1000;
2632+
else if (link_status & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G))
2633+
speed = 10000;
2634+
else if (link_status & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_25G))
2635+
speed = 25000;
2636+
else if (link_status & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G))
2637+
speed = 40000;
2638+
else if (link_status & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100G))
2639+
speed = 100000;
2640+
2641+
if (max_tx_rate > speed) {
2642+
dev_err(adap->pdev_dev,
2643+
"Max tx rate %d for VF %d can't be > link-speed %u",
2644+
max_tx_rate, vf, speed);
2645+
return -EINVAL;
2646+
}
2647+
pktsize = be16_to_cpu(port_rpl.u.info.mtu);
2648+
/* subtract ethhdr size and 4 bytes crc since, f/w appends it */
2649+
pktsize = pktsize - sizeof(struct ethhdr) - 4;
2650+
/* subtract ipv4 hdr size, tcp hdr size to get typical IPv4 MSS size */
2651+
pktsize = pktsize - sizeof(struct iphdr) - sizeof(struct tcphdr);
2652+
/* configure Traffic Class for rate-limiting */
2653+
ret = t4_sched_params(adap, SCHED_CLASS_TYPE_PACKET,
2654+
SCHED_CLASS_LEVEL_CL_RL,
2655+
SCHED_CLASS_MODE_CLASS,
2656+
SCHED_CLASS_RATEUNIT_BITS,
2657+
SCHED_CLASS_RATEMODE_ABS,
2658+
pi->port_id, class_id, 0,
2659+
max_tx_rate * 1000, 0, pktsize);
2660+
if (ret) {
2661+
dev_err(adap->pdev_dev, "Err %d for Traffic Class config\n",
2662+
ret);
2663+
return -EINVAL;
2664+
}
2665+
dev_info(adap->pdev_dev,
2666+
"Class %d with MSS %u configured with rate %u\n",
2667+
class_id, pktsize, max_tx_rate);
2668+
2669+
/* bind VF to configured Traffic Class */
2670+
fw_pfvf = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_PFVF) |
2671+
FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_PFVF_SCHEDCLASS_ETH));
2672+
fw_class = class_id;
2673+
ret = t4_set_params(adap, adap->mbox, adap->pf, vf + 1, 1, &fw_pfvf,
2674+
&fw_class);
2675+
if (ret) {
2676+
dev_err(adap->pdev_dev,
2677+
"Err %d in binding VF %d to Traffic Class %d\n",
2678+
ret, vf, class_id);
2679+
return -EINVAL;
2680+
}
2681+
dev_info(adap->pdev_dev, "PF %d VF %d is bound to Class %d\n",
2682+
adap->pf, vf, class_id);
2683+
adap->vfinfo[vf].tx_rate = max_tx_rate;
2684+
return 0;
2685+
}
2686+
25822687
#endif
25832688

25842689
static int cxgb_set_mac_addr(struct net_device *dev, void *p)
@@ -2766,6 +2871,7 @@ static const struct net_device_ops cxgb4_mgmt_netdev_ops = {
27662871
.ndo_open = dummy_open,
27672872
.ndo_set_vf_mac = cxgb_set_vf_mac,
27682873
.ndo_get_vf_config = cxgb_get_vf_config,
2874+
.ndo_set_vf_rate = cxgb_set_vf_rate,
27692875
.ndo_get_phys_port_id = cxgb_get_phys_port_id,
27702876
};
27712877
#endif

0 commit comments

Comments
 (0)