Skip to content

Commit 2edbff8

Browse files
Tomer Tayardavem330
authored andcommitted
qed: Learn resources from management firmware
Currently, each interfaces assumes it receives an equal portion of HW/FW resources, but this is wasteful - different partitions [and specifically, parititions exposing different protocol support] might require different resources. Implement a new resource learning scheme where the information is received directly from the management firmware [which has knowledge of all of the functions and can serve as arbiter]. Signed-off-by: Tomer Tayar <[email protected]> Signed-off-by: Yuval Mintz <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5a1f965 commit 2edbff8

File tree

7 files changed

+341
-63
lines changed

7 files changed

+341
-63
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,10 @@ struct qed_qm_iids {
154154
u32 tids;
155155
};
156156

157-
enum QED_RESOURCES {
157+
/* HW / FW resources, output of features supported below, most information
158+
* is received from MFW.
159+
*/
160+
enum qed_resources {
158161
QED_SB,
159162
QED_L2_QUEUE,
160163
QED_VPORT,
@@ -166,6 +169,7 @@ enum QED_RESOURCES {
166169
QED_RDMA_CNQ_RAM,
167170
QED_ILT,
168171
QED_LL2_QUEUE,
172+
QED_CMDQS_CQS,
169173
QED_RDMA_STATS_QUEUE,
170174
QED_MAX_RESC,
171175
};

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

Lines changed: 231 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,47 +1512,240 @@ static void qed_hw_set_feat(struct qed_hwfn *p_hwfn)
15121512
RESC_NUM(p_hwfn, QED_SB), num_features);
15131513
}
15141514

1515-
static int qed_hw_get_resc(struct qed_hwfn *p_hwfn)
1515+
static enum resource_id_enum qed_hw_get_mfw_res_id(enum qed_resources res_id)
1516+
{
1517+
enum resource_id_enum mfw_res_id = RESOURCE_NUM_INVALID;
1518+
1519+
switch (res_id) {
1520+
case QED_SB:
1521+
mfw_res_id = RESOURCE_NUM_SB_E;
1522+
break;
1523+
case QED_L2_QUEUE:
1524+
mfw_res_id = RESOURCE_NUM_L2_QUEUE_E;
1525+
break;
1526+
case QED_VPORT:
1527+
mfw_res_id = RESOURCE_NUM_VPORT_E;
1528+
break;
1529+
case QED_RSS_ENG:
1530+
mfw_res_id = RESOURCE_NUM_RSS_ENGINES_E;
1531+
break;
1532+
case QED_PQ:
1533+
mfw_res_id = RESOURCE_NUM_PQ_E;
1534+
break;
1535+
case QED_RL:
1536+
mfw_res_id = RESOURCE_NUM_RL_E;
1537+
break;
1538+
case QED_MAC:
1539+
case QED_VLAN:
1540+
/* Each VFC resource can accommodate both a MAC and a VLAN */
1541+
mfw_res_id = RESOURCE_VFC_FILTER_E;
1542+
break;
1543+
case QED_ILT:
1544+
mfw_res_id = RESOURCE_ILT_E;
1545+
break;
1546+
case QED_LL2_QUEUE:
1547+
mfw_res_id = RESOURCE_LL2_QUEUE_E;
1548+
break;
1549+
case QED_RDMA_CNQ_RAM:
1550+
case QED_CMDQS_CQS:
1551+
/* CNQ/CMDQS are the same resource */
1552+
mfw_res_id = RESOURCE_CQS_E;
1553+
break;
1554+
case QED_RDMA_STATS_QUEUE:
1555+
mfw_res_id = RESOURCE_RDMA_STATS_QUEUE_E;
1556+
break;
1557+
default:
1558+
break;
1559+
}
1560+
1561+
return mfw_res_id;
1562+
}
1563+
1564+
static u32 qed_hw_get_dflt_resc_num(struct qed_hwfn *p_hwfn,
1565+
enum qed_resources res_id)
15161566
{
1517-
u8 enabled_func_idx = p_hwfn->enabled_func_idx;
1518-
u32 *resc_start = p_hwfn->hw_info.resc_start;
15191567
u8 num_funcs = p_hwfn->num_funcs_on_engine;
1520-
u32 *resc_num = p_hwfn->hw_info.resc_num;
15211568
struct qed_sb_cnt_info sb_cnt_info;
1522-
int i, max_vf_vlan_filters;
1569+
u32 dflt_resc_num = 0;
15231570

1524-
memset(&sb_cnt_info, 0, sizeof(sb_cnt_info));
1571+
switch (res_id) {
1572+
case QED_SB:
1573+
memset(&sb_cnt_info, 0, sizeof(sb_cnt_info));
1574+
qed_int_get_num_sbs(p_hwfn, &sb_cnt_info);
1575+
dflt_resc_num = sb_cnt_info.sb_cnt;
1576+
break;
1577+
case QED_L2_QUEUE:
1578+
dflt_resc_num = MAX_NUM_L2_QUEUES_BB / num_funcs;
1579+
break;
1580+
case QED_VPORT:
1581+
dflt_resc_num = MAX_NUM_VPORTS_BB / num_funcs;
1582+
break;
1583+
case QED_RSS_ENG:
1584+
dflt_resc_num = ETH_RSS_ENGINE_NUM_BB / num_funcs;
1585+
break;
1586+
case QED_PQ:
1587+
/* The granularity of the PQs is 8 */
1588+
dflt_resc_num = MAX_QM_TX_QUEUES_BB / num_funcs;
1589+
dflt_resc_num &= ~0x7;
1590+
break;
1591+
case QED_RL:
1592+
dflt_resc_num = MAX_QM_GLOBAL_RLS / num_funcs;
1593+
break;
1594+
case QED_MAC:
1595+
case QED_VLAN:
1596+
/* Each VFC resource can accommodate both a MAC and a VLAN */
1597+
dflt_resc_num = ETH_NUM_MAC_FILTERS / num_funcs;
1598+
break;
1599+
case QED_ILT:
1600+
dflt_resc_num = PXP_NUM_ILT_RECORDS_BB / num_funcs;
1601+
break;
1602+
case QED_LL2_QUEUE:
1603+
dflt_resc_num = MAX_NUM_LL2_RX_QUEUES / num_funcs;
1604+
break;
1605+
case QED_RDMA_CNQ_RAM:
1606+
case QED_CMDQS_CQS:
1607+
/* CNQ/CMDQS are the same resource */
1608+
dflt_resc_num = NUM_OF_CMDQS_CQS / num_funcs;
1609+
break;
1610+
case QED_RDMA_STATS_QUEUE:
1611+
dflt_resc_num = RDMA_NUM_STATISTIC_COUNTERS_BB / num_funcs;
1612+
break;
1613+
default:
1614+
break;
1615+
}
15251616

1526-
#ifdef CONFIG_QED_SRIOV
1527-
max_vf_vlan_filters = QED_ETH_MAX_VF_NUM_VLAN_FILTERS;
1528-
#else
1529-
max_vf_vlan_filters = 0;
1530-
#endif
1617+
return dflt_resc_num;
1618+
}
1619+
1620+
static const char *qed_hw_get_resc_name(enum qed_resources res_id)
1621+
{
1622+
switch (res_id) {
1623+
case QED_SB:
1624+
return "SB";
1625+
case QED_L2_QUEUE:
1626+
return "L2_QUEUE";
1627+
case QED_VPORT:
1628+
return "VPORT";
1629+
case QED_RSS_ENG:
1630+
return "RSS_ENG";
1631+
case QED_PQ:
1632+
return "PQ";
1633+
case QED_RL:
1634+
return "RL";
1635+
case QED_MAC:
1636+
return "MAC";
1637+
case QED_VLAN:
1638+
return "VLAN";
1639+
case QED_RDMA_CNQ_RAM:
1640+
return "RDMA_CNQ_RAM";
1641+
case QED_ILT:
1642+
return "ILT";
1643+
case QED_LL2_QUEUE:
1644+
return "LL2_QUEUE";
1645+
case QED_CMDQS_CQS:
1646+
return "CMDQS_CQS";
1647+
case QED_RDMA_STATS_QUEUE:
1648+
return "RDMA_STATS_QUEUE";
1649+
default:
1650+
return "UNKNOWN_RESOURCE";
1651+
}
1652+
}
15311653

1532-
qed_int_get_num_sbs(p_hwfn, &sb_cnt_info);
1654+
static int qed_hw_set_resc_info(struct qed_hwfn *p_hwfn,
1655+
enum qed_resources res_id)
1656+
{
1657+
u32 dflt_resc_num = 0, dflt_resc_start = 0, mcp_resp, mcp_param;
1658+
u32 *p_resc_num, *p_resc_start;
1659+
struct resource_info resc_info;
1660+
int rc;
1661+
1662+
p_resc_num = &RESC_NUM(p_hwfn, res_id);
1663+
p_resc_start = &RESC_START(p_hwfn, res_id);
1664+
1665+
/* Default values assumes that each function received equal share */
1666+
dflt_resc_num = qed_hw_get_dflt_resc_num(p_hwfn, res_id);
1667+
if (!dflt_resc_num) {
1668+
DP_ERR(p_hwfn,
1669+
"Failed to get default amount for resource %d [%s]\n",
1670+
res_id, qed_hw_get_resc_name(res_id));
1671+
return -EINVAL;
1672+
}
1673+
dflt_resc_start = dflt_resc_num * p_hwfn->enabled_func_idx;
1674+
1675+
memset(&resc_info, 0, sizeof(resc_info));
1676+
resc_info.res_id = qed_hw_get_mfw_res_id(res_id);
1677+
if (resc_info.res_id == RESOURCE_NUM_INVALID) {
1678+
DP_ERR(p_hwfn,
1679+
"Failed to match resource %d [%s] with the MFW resources\n",
1680+
res_id, qed_hw_get_resc_name(res_id));
1681+
return -EINVAL;
1682+
}
1683+
1684+
rc = qed_mcp_get_resc_info(p_hwfn, p_hwfn->p_main_ptt, &resc_info,
1685+
&mcp_resp, &mcp_param);
1686+
if (rc) {
1687+
DP_NOTICE(p_hwfn,
1688+
"MFW response failure for an allocation request for resource %d [%s]\n",
1689+
res_id, qed_hw_get_resc_name(res_id));
1690+
return rc;
1691+
}
1692+
1693+
/* Default driver values are applied in the following cases:
1694+
* - The resource allocation MB command is not supported by the MFW
1695+
* - There is an internal error in the MFW while processing the request
1696+
* - The resource ID is unknown to the MFW
1697+
*/
1698+
if (mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_OK &&
1699+
mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_DEPRECATED) {
1700+
DP_NOTICE(p_hwfn,
1701+
"Resource %d [%s]: No allocation info was received [mcp_resp 0x%x]. Applying default values [num %d, start %d].\n",
1702+
res_id,
1703+
qed_hw_get_resc_name(res_id),
1704+
mcp_resp, dflt_resc_num, dflt_resc_start);
1705+
*p_resc_num = dflt_resc_num;
1706+
*p_resc_start = dflt_resc_start;
1707+
goto out;
1708+
}
1709+
1710+
/* Special handling for status blocks; Would be revised in future */
1711+
if (res_id == QED_SB) {
1712+
resc_info.size -= 1;
1713+
resc_info.offset -= p_hwfn->enabled_func_idx;
1714+
}
1715+
1716+
*p_resc_num = resc_info.size;
1717+
*p_resc_start = resc_info.offset;
1718+
1719+
out:
1720+
/* PQs have to divide by 8 [that's the HW granularity].
1721+
* Reduce number so it would fit.
1722+
*/
1723+
if ((res_id == QED_PQ) && ((*p_resc_num % 8) || (*p_resc_start % 8))) {
1724+
DP_INFO(p_hwfn,
1725+
"PQs need to align by 8; Number %08x --> %08x, Start %08x --> %08x\n",
1726+
*p_resc_num,
1727+
(*p_resc_num) & ~0x7,
1728+
*p_resc_start, (*p_resc_start) & ~0x7);
1729+
*p_resc_num &= ~0x7;
1730+
*p_resc_start &= ~0x7;
1731+
}
15331732

1534-
resc_num[QED_SB] = min_t(u32,
1535-
(MAX_SB_PER_PATH_BB / num_funcs),
1536-
sb_cnt_info.sb_cnt);
1537-
resc_num[QED_L2_QUEUE] = MAX_NUM_L2_QUEUES_BB / num_funcs;
1538-
resc_num[QED_VPORT] = MAX_NUM_VPORTS_BB / num_funcs;
1539-
resc_num[QED_RSS_ENG] = ETH_RSS_ENGINE_NUM_BB / num_funcs;
1540-
resc_num[QED_PQ] = MAX_QM_TX_QUEUES_BB / num_funcs;
1541-
resc_num[QED_RL] = min_t(u32, 64, resc_num[QED_VPORT]);
1542-
resc_num[QED_MAC] = ETH_NUM_MAC_FILTERS / num_funcs;
1543-
resc_num[QED_VLAN] = (ETH_NUM_VLAN_FILTERS - 1 /*For vlan0*/) /
1544-
num_funcs;
1545-
resc_num[QED_ILT] = PXP_NUM_ILT_RECORDS_BB / num_funcs;
1546-
resc_num[QED_LL2_QUEUE] = MAX_NUM_LL2_RX_QUEUES / num_funcs;
1547-
resc_num[QED_RDMA_CNQ_RAM] = NUM_OF_CMDQS_CQS / num_funcs;
1548-
resc_num[QED_RDMA_STATS_QUEUE] = RDMA_NUM_STATISTIC_COUNTERS_BB /
1549-
num_funcs;
1550-
1551-
for (i = 0; i < QED_MAX_RESC; i++)
1552-
resc_start[i] = resc_num[i] * enabled_func_idx;
1733+
return 0;
1734+
}
1735+
1736+
static int qed_hw_get_resc(struct qed_hwfn *p_hwfn)
1737+
{
1738+
u8 res_id;
1739+
int rc;
1740+
1741+
for (res_id = 0; res_id < QED_MAX_RESC; res_id++) {
1742+
rc = qed_hw_set_resc_info(p_hwfn, res_id);
1743+
if (rc)
1744+
return rc;
1745+
}
15531746

15541747
/* Sanity for ILT */
1555-
if (RESC_END(p_hwfn, QED_ILT) > PXP_NUM_ILT_RECORDS_BB) {
1748+
if ((RESC_END(p_hwfn, QED_ILT) > PXP_NUM_ILT_RECORDS_BB)) {
15561749
DP_NOTICE(p_hwfn, "Can't assign ILT pages [%08x,...,%08x]\n",
15571750
RESC_START(p_hwfn, QED_ILT),
15581751
RESC_END(p_hwfn, QED_ILT) - 1);
@@ -1562,34 +1755,12 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn)
15621755
qed_hw_set_feat(p_hwfn);
15631756

15641757
DP_VERBOSE(p_hwfn, NETIF_MSG_PROBE,
1565-
"The numbers for each resource are:\n"
1566-
"SB = %d start = %d\n"
1567-
"L2_QUEUE = %d start = %d\n"
1568-
"VPORT = %d start = %d\n"
1569-
"PQ = %d start = %d\n"
1570-
"RL = %d start = %d\n"
1571-
"MAC = %d start = %d\n"
1572-
"VLAN = %d start = %d\n"
1573-
"ILT = %d start = %d\n"
1574-
"LL2_QUEUE = %d start = %d\n",
1575-
p_hwfn->hw_info.resc_num[QED_SB],
1576-
p_hwfn->hw_info.resc_start[QED_SB],
1577-
p_hwfn->hw_info.resc_num[QED_L2_QUEUE],
1578-
p_hwfn->hw_info.resc_start[QED_L2_QUEUE],
1579-
p_hwfn->hw_info.resc_num[QED_VPORT],
1580-
p_hwfn->hw_info.resc_start[QED_VPORT],
1581-
p_hwfn->hw_info.resc_num[QED_PQ],
1582-
p_hwfn->hw_info.resc_start[QED_PQ],
1583-
p_hwfn->hw_info.resc_num[QED_RL],
1584-
p_hwfn->hw_info.resc_start[QED_RL],
1585-
p_hwfn->hw_info.resc_num[QED_MAC],
1586-
p_hwfn->hw_info.resc_start[QED_MAC],
1587-
p_hwfn->hw_info.resc_num[QED_VLAN],
1588-
p_hwfn->hw_info.resc_start[QED_VLAN],
1589-
p_hwfn->hw_info.resc_num[QED_ILT],
1590-
p_hwfn->hw_info.resc_start[QED_ILT],
1591-
RESC_NUM(p_hwfn, QED_LL2_QUEUE),
1592-
RESC_START(p_hwfn, QED_LL2_QUEUE));
1758+
"The numbers for each resource are:\n");
1759+
for (res_id = 0; res_id < QED_MAX_RESC; res_id++)
1760+
DP_VERBOSE(p_hwfn, NETIF_MSG_PROBE, "%s = %d start = %d\n",
1761+
qed_hw_get_resc_name(res_id),
1762+
RESC_NUM(p_hwfn, res_id),
1763+
RESC_START(p_hwfn, res_id));
15931764

15941765
return 0;
15951766
}

0 commit comments

Comments
 (0)