@@ -105,6 +105,8 @@ static void qed_qm_info_free(struct qed_hwfn *p_hwfn)
105
105
qm_info -> qm_vport_params = NULL ;
106
106
kfree (qm_info -> qm_port_params );
107
107
qm_info -> qm_port_params = NULL ;
108
+ kfree (qm_info -> wfq_data );
109
+ qm_info -> wfq_data = NULL ;
108
110
}
109
111
110
112
void qed_resc_free (struct qed_dev * cdev )
@@ -175,6 +177,11 @@ static int qed_init_qm_info(struct qed_hwfn *p_hwfn)
175
177
if (!qm_info -> qm_port_params )
176
178
goto alloc_err ;
177
179
180
+ qm_info -> wfq_data = kcalloc (num_vports , sizeof (* qm_info -> wfq_data ),
181
+ GFP_KERNEL );
182
+ if (!qm_info -> wfq_data )
183
+ goto alloc_err ;
184
+
178
185
vport_id = (u8 )RESC_START (p_hwfn , QED_VPORT );
179
186
180
187
/* First init per-TC PQs */
@@ -221,10 +228,7 @@ static int qed_init_qm_info(struct qed_hwfn *p_hwfn)
221
228
222
229
alloc_err :
223
230
DP_NOTICE (p_hwfn , "Failed to allocate memory for QM params\n" );
224
- kfree (qm_info -> qm_pq_params );
225
- kfree (qm_info -> qm_vport_params );
226
- kfree (qm_info -> qm_port_params );
227
-
231
+ qed_qm_info_free (p_hwfn );
228
232
return - ENOMEM ;
229
233
}
230
234
@@ -1595,3 +1599,179 @@ int qed_fw_rss_eng(struct qed_hwfn *p_hwfn,
1595
1599
1596
1600
return 0 ;
1597
1601
}
1602
+
1603
+ /* Calculate final WFQ values for all vports and configure them.
1604
+ * After this configuration each vport will have
1605
+ * approx min rate = min_pf_rate * (vport_wfq / QED_WFQ_UNIT)
1606
+ */
1607
+ static void qed_configure_wfq_for_all_vports (struct qed_hwfn * p_hwfn ,
1608
+ struct qed_ptt * p_ptt ,
1609
+ u32 min_pf_rate )
1610
+ {
1611
+ struct init_qm_vport_params * vport_params ;
1612
+ int i ;
1613
+
1614
+ vport_params = p_hwfn -> qm_info .qm_vport_params ;
1615
+
1616
+ for (i = 0 ; i < p_hwfn -> qm_info .num_vports ; i ++ ) {
1617
+ u32 wfq_speed = p_hwfn -> qm_info .wfq_data [i ].min_speed ;
1618
+
1619
+ vport_params [i ].vport_wfq = (wfq_speed * QED_WFQ_UNIT ) /
1620
+ min_pf_rate ;
1621
+ qed_init_vport_wfq (p_hwfn , p_ptt ,
1622
+ vport_params [i ].first_tx_pq_id ,
1623
+ vport_params [i ].vport_wfq );
1624
+ }
1625
+ }
1626
+
1627
+ static void qed_init_wfq_default_param (struct qed_hwfn * p_hwfn ,
1628
+ u32 min_pf_rate )
1629
+
1630
+ {
1631
+ int i ;
1632
+
1633
+ for (i = 0 ; i < p_hwfn -> qm_info .num_vports ; i ++ )
1634
+ p_hwfn -> qm_info .qm_vport_params [i ].vport_wfq = 1 ;
1635
+ }
1636
+
1637
+ static void qed_disable_wfq_for_all_vports (struct qed_hwfn * p_hwfn ,
1638
+ struct qed_ptt * p_ptt ,
1639
+ u32 min_pf_rate )
1640
+ {
1641
+ struct init_qm_vport_params * vport_params ;
1642
+ int i ;
1643
+
1644
+ vport_params = p_hwfn -> qm_info .qm_vport_params ;
1645
+
1646
+ for (i = 0 ; i < p_hwfn -> qm_info .num_vports ; i ++ ) {
1647
+ qed_init_wfq_default_param (p_hwfn , min_pf_rate );
1648
+ qed_init_vport_wfq (p_hwfn , p_ptt ,
1649
+ vport_params [i ].first_tx_pq_id ,
1650
+ vport_params [i ].vport_wfq );
1651
+ }
1652
+ }
1653
+
1654
+ /* This function performs several validations for WFQ
1655
+ * configuration and required min rate for a given vport
1656
+ * 1. req_rate must be greater than one percent of min_pf_rate.
1657
+ * 2. req_rate should not cause other vports [not configured for WFQ explicitly]
1658
+ * rates to get less than one percent of min_pf_rate.
1659
+ * 3. total_req_min_rate [all vports min rate sum] shouldn't exceed min_pf_rate.
1660
+ */
1661
+ static int qed_init_wfq_param (struct qed_hwfn * p_hwfn ,
1662
+ u16 vport_id , u32 req_rate ,
1663
+ u32 min_pf_rate )
1664
+ {
1665
+ u32 total_req_min_rate = 0 , total_left_rate = 0 , left_rate_per_vp = 0 ;
1666
+ int non_requested_count = 0 , req_count = 0 , i , num_vports ;
1667
+
1668
+ num_vports = p_hwfn -> qm_info .num_vports ;
1669
+
1670
+ /* Accounting for the vports which are configured for WFQ explicitly */
1671
+ for (i = 0 ; i < num_vports ; i ++ ) {
1672
+ u32 tmp_speed ;
1673
+
1674
+ if ((i != vport_id ) &&
1675
+ p_hwfn -> qm_info .wfq_data [i ].configured ) {
1676
+ req_count ++ ;
1677
+ tmp_speed = p_hwfn -> qm_info .wfq_data [i ].min_speed ;
1678
+ total_req_min_rate += tmp_speed ;
1679
+ }
1680
+ }
1681
+
1682
+ /* Include current vport data as well */
1683
+ req_count ++ ;
1684
+ total_req_min_rate += req_rate ;
1685
+ non_requested_count = num_vports - req_count ;
1686
+
1687
+ if (req_rate < min_pf_rate / QED_WFQ_UNIT ) {
1688
+ DP_VERBOSE (p_hwfn , NETIF_MSG_LINK ,
1689
+ "Vport [%d] - Requested rate[%d Mbps] is less than one percent of configured PF min rate[%d Mbps]\n" ,
1690
+ vport_id , req_rate , min_pf_rate );
1691
+ return - EINVAL ;
1692
+ }
1693
+
1694
+ if (num_vports > QED_WFQ_UNIT ) {
1695
+ DP_VERBOSE (p_hwfn , NETIF_MSG_LINK ,
1696
+ "Number of vports is greater than %d\n" ,
1697
+ QED_WFQ_UNIT );
1698
+ return - EINVAL ;
1699
+ }
1700
+
1701
+ if (total_req_min_rate > min_pf_rate ) {
1702
+ DP_VERBOSE (p_hwfn , NETIF_MSG_LINK ,
1703
+ "Total requested min rate for all vports[%d Mbps] is greater than configured PF min rate[%d Mbps]\n" ,
1704
+ total_req_min_rate , min_pf_rate );
1705
+ return - EINVAL ;
1706
+ }
1707
+
1708
+ total_left_rate = min_pf_rate - total_req_min_rate ;
1709
+
1710
+ left_rate_per_vp = total_left_rate / non_requested_count ;
1711
+ if (left_rate_per_vp < min_pf_rate / QED_WFQ_UNIT ) {
1712
+ DP_VERBOSE (p_hwfn , NETIF_MSG_LINK ,
1713
+ "Non WFQ configured vports rate [%d Mbps] is less than one percent of configured PF min rate[%d Mbps]\n" ,
1714
+ left_rate_per_vp , min_pf_rate );
1715
+ return - EINVAL ;
1716
+ }
1717
+
1718
+ p_hwfn -> qm_info .wfq_data [vport_id ].min_speed = req_rate ;
1719
+ p_hwfn -> qm_info .wfq_data [vport_id ].configured = true;
1720
+
1721
+ for (i = 0 ; i < num_vports ; i ++ ) {
1722
+ if (p_hwfn -> qm_info .wfq_data [i ].configured )
1723
+ continue ;
1724
+
1725
+ p_hwfn -> qm_info .wfq_data [i ].min_speed = left_rate_per_vp ;
1726
+ }
1727
+
1728
+ return 0 ;
1729
+ }
1730
+
1731
+ static int __qed_configure_vp_wfq_on_link_change (struct qed_hwfn * p_hwfn ,
1732
+ struct qed_ptt * p_ptt ,
1733
+ u32 min_pf_rate )
1734
+ {
1735
+ bool use_wfq = false;
1736
+ int rc = 0 ;
1737
+ u16 i ;
1738
+
1739
+ /* Validate all pre configured vports for wfq */
1740
+ for (i = 0 ; i < p_hwfn -> qm_info .num_vports ; i ++ ) {
1741
+ u32 rate ;
1742
+
1743
+ if (!p_hwfn -> qm_info .wfq_data [i ].configured )
1744
+ continue ;
1745
+
1746
+ rate = p_hwfn -> qm_info .wfq_data [i ].min_speed ;
1747
+ use_wfq = true;
1748
+
1749
+ rc = qed_init_wfq_param (p_hwfn , i , rate , min_pf_rate );
1750
+ if (rc ) {
1751
+ DP_NOTICE (p_hwfn ,
1752
+ "WFQ validation failed while configuring min rate\n" );
1753
+ break ;
1754
+ }
1755
+ }
1756
+
1757
+ if (!rc && use_wfq )
1758
+ qed_configure_wfq_for_all_vports (p_hwfn , p_ptt , min_pf_rate );
1759
+ else
1760
+ qed_disable_wfq_for_all_vports (p_hwfn , p_ptt , min_pf_rate );
1761
+
1762
+ return rc ;
1763
+ }
1764
+
1765
+ /* API to configure WFQ from mcp link change */
1766
+ void qed_configure_vp_wfq_on_link_change (struct qed_dev * cdev , u32 min_pf_rate )
1767
+ {
1768
+ int i ;
1769
+
1770
+ for_each_hwfn (cdev , i ) {
1771
+ struct qed_hwfn * p_hwfn = & cdev -> hwfns [i ];
1772
+
1773
+ __qed_configure_vp_wfq_on_link_change (p_hwfn ,
1774
+ p_hwfn -> p_dpc_ptt ,
1775
+ min_pf_rate );
1776
+ }
1777
+ }
0 commit comments