Skip to content

Commit bcd197c

Browse files
Manish Chopradavem330
authored andcommitted
qed: Add vport WFQ configuration APIs
This patch adds relevant APIs needed to configure WFQ (Weighted fair queueing) values for the vports. WFQ configuration is used per vport basis when minimum bandwidth update/configuration is notified to the PF by the management firmware. Signed-off-by: Manish Chopra <[email protected]> Signed-off-by: Yuval Mintz <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 101e63b commit bcd197c

File tree

5 files changed

+223
-4
lines changed

5 files changed

+223
-4
lines changed

drivers/net/ethernet/qlogic/qed/qed.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ extern const struct qed_common_ops qed_common_ops_pass;
3232
#define NAME_SIZE 16
3333
#define VER_SIZE 16
3434

35+
#define QED_WFQ_UNIT 100
36+
3537
/* cau states */
3638
enum qed_coalescing_mode {
3739
QED_COAL_MODE_DISABLE,
@@ -237,6 +239,12 @@ struct qed_dmae_info {
237239
struct dmae_cmd *p_dmae_cmd;
238240
};
239241

242+
struct qed_wfq_data {
243+
/* when feature is configured for at least 1 vport */
244+
u32 min_speed;
245+
bool configured;
246+
};
247+
240248
struct qed_qm_info {
241249
struct init_qm_pq_params *qm_pq_params;
242250
struct init_qm_vport_params *qm_vport_params;
@@ -257,6 +265,7 @@ struct qed_qm_info {
257265
bool vport_wfq_en;
258266
u8 pf_wfq;
259267
u32 pf_rl;
268+
struct qed_wfq_data *wfq_data;
260269
};
261270

262271
struct storm_stats {
@@ -526,6 +535,8 @@ static inline u8 qed_concrete_to_sw_fid(struct qed_dev *cdev,
526535

527536
#define PURE_LB_TC 8
528537

538+
void qed_configure_vp_wfq_on_link_change(struct qed_dev *cdev, u32 min_pf_rate);
539+
529540
#define QED_LEADING_HWFN(dev) (&dev->hwfns[0])
530541

531542
/* Other Linux specific common definitions */

drivers/net/ethernet/qlogic/qed/qed_dev.c

Lines changed: 184 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ static void qed_qm_info_free(struct qed_hwfn *p_hwfn)
105105
qm_info->qm_vport_params = NULL;
106106
kfree(qm_info->qm_port_params);
107107
qm_info->qm_port_params = NULL;
108+
kfree(qm_info->wfq_data);
109+
qm_info->wfq_data = NULL;
108110
}
109111

110112
void qed_resc_free(struct qed_dev *cdev)
@@ -175,6 +177,11 @@ static int qed_init_qm_info(struct qed_hwfn *p_hwfn)
175177
if (!qm_info->qm_port_params)
176178
goto alloc_err;
177179

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+
178185
vport_id = (u8)RESC_START(p_hwfn, QED_VPORT);
179186

180187
/* First init per-TC PQs */
@@ -221,10 +228,7 @@ static int qed_init_qm_info(struct qed_hwfn *p_hwfn)
221228

222229
alloc_err:
223230
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);
228232
return -ENOMEM;
229233
}
230234

@@ -1595,3 +1599,179 @@ int qed_fw_rss_eng(struct qed_hwfn *p_hwfn,
15951599

15961600
return 0;
15971601
}
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+
}

drivers/net/ethernet/qlogic/qed/qed_hsi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5116,4 +5116,6 @@ struct hw_set_image {
51165116
struct hw_set_info hw_sets[1];
51175117
};
51185118

5119+
int qed_init_vport_wfq(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
5120+
u16 first_tx_pq_id[NUM_OF_TCS], u16 vport_wfq);
51195121
#endif

drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,31 @@ int qed_init_pf_rl(struct qed_hwfn *p_hwfn,
732732
return 0;
733733
}
734734

735+
int qed_init_vport_wfq(struct qed_hwfn *p_hwfn,
736+
struct qed_ptt *p_ptt,
737+
u16 first_tx_pq_id[NUM_OF_TCS],
738+
u16 vport_wfq)
739+
{
740+
u32 inc_val = QM_WFQ_INC_VAL(vport_wfq);
741+
u8 tc;
742+
743+
if (!inc_val || inc_val > QM_WFQ_MAX_INC_VAL) {
744+
DP_NOTICE(p_hwfn, "Invalid VPORT WFQ weight configuration");
745+
return -1;
746+
}
747+
748+
for (tc = 0; tc < NUM_OF_TCS; tc++) {
749+
u16 vport_pq_id = first_tx_pq_id[tc];
750+
751+
if (vport_pq_id != QM_INVALID_PQ_ID)
752+
qed_wr(p_hwfn, p_ptt,
753+
QM_REG_WFQVPWEIGHT + vport_pq_id * 4,
754+
inc_val);
755+
}
756+
757+
return 0;
758+
}
759+
735760
int qed_init_vport_rl(struct qed_hwfn *p_hwfn,
736761
struct qed_ptt *p_ptt,
737762
u8 vport_id,

drivers/net/ethernet/qlogic/qed/qed_reg_addr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,4 +458,5 @@
458458
#define PBF_REG_NGE_COMP_VER 0xd80524UL
459459
#define PRS_REG_NGE_COMP_VER 0x1f0878UL
460460

461+
#define QM_REG_WFQVPWEIGHT 0x2fa000UL
461462
#endif

0 commit comments

Comments
 (0)