@@ -2563,6 +2563,8 @@ static int cxgb_get_vf_config(struct net_device *dev,
2563
2563
if (vf >= adap -> num_vfs )
2564
2564
return - EINVAL ;
2565
2565
ivi -> vf = vf ;
2566
+ ivi -> max_tx_rate = adap -> vfinfo [vf ].tx_rate ;
2567
+ ivi -> min_tx_rate = 0 ;
2566
2568
ether_addr_copy (ivi -> mac , adap -> vfinfo [vf ].vf_mac_addr );
2567
2569
return 0 ;
2568
2570
}
@@ -2579,6 +2581,109 @@ static int cxgb_get_phys_port_id(struct net_device *dev,
2579
2581
return 0 ;
2580
2582
}
2581
2583
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
+
2582
2687
#endif
2583
2688
2584
2689
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 = {
2766
2871
.ndo_open = dummy_open ,
2767
2872
.ndo_set_vf_mac = cxgb_set_vf_mac ,
2768
2873
.ndo_get_vf_config = cxgb_get_vf_config ,
2874
+ .ndo_set_vf_rate = cxgb_set_vf_rate ,
2769
2875
.ndo_get_phys_port_id = cxgb_get_phys_port_id ,
2770
2876
};
2771
2877
#endif
0 commit comments