mirror of https://gitee.com/openkylin/linux.git
qed: Add PF max bandwidth configuration support
This patch adds support for PF maximum bandwidth update or configuration notified by management firmware. Signed-off-by: Manish Chopra <manish.chopra@qlogic.com> Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
bcd197c81f
commit
4b01e5192b
|
@ -579,7 +579,7 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn,
|
||||||
p_hwfn->qm_info.pf_wfq = p_info->bandwidth_min;
|
p_hwfn->qm_info.pf_wfq = p_info->bandwidth_min;
|
||||||
|
|
||||||
/* Update rate limit once we'll actually have a link */
|
/* Update rate limit once we'll actually have a link */
|
||||||
p_hwfn->qm_info.pf_rl = 100;
|
p_hwfn->qm_info.pf_rl = 100000;
|
||||||
}
|
}
|
||||||
|
|
||||||
qed_cxt_hw_init_pf(p_hwfn);
|
qed_cxt_hw_init_pf(p_hwfn);
|
||||||
|
@ -1775,3 +1775,69 @@ void qed_configure_vp_wfq_on_link_change(struct qed_dev *cdev, u32 min_pf_rate)
|
||||||
min_pf_rate);
|
min_pf_rate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int __qed_configure_pf_max_bandwidth(struct qed_hwfn *p_hwfn,
|
||||||
|
struct qed_ptt *p_ptt,
|
||||||
|
struct qed_mcp_link_state *p_link,
|
||||||
|
u8 max_bw)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
p_hwfn->mcp_info->func_info.bandwidth_max = max_bw;
|
||||||
|
|
||||||
|
if (!p_link->line_speed && (max_bw != 100))
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
p_link->speed = (p_link->line_speed * max_bw) / 100;
|
||||||
|
p_hwfn->qm_info.pf_rl = p_link->speed;
|
||||||
|
|
||||||
|
/* Since the limiter also affects Tx-switched traffic, we don't want it
|
||||||
|
* to limit such traffic in case there's no actual limit.
|
||||||
|
* In that case, set limit to imaginary high boundary.
|
||||||
|
*/
|
||||||
|
if (max_bw == 100)
|
||||||
|
p_hwfn->qm_info.pf_rl = 100000;
|
||||||
|
|
||||||
|
rc = qed_init_pf_rl(p_hwfn, p_ptt, p_hwfn->rel_pf_id,
|
||||||
|
p_hwfn->qm_info.pf_rl);
|
||||||
|
|
||||||
|
DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
|
||||||
|
"Configured MAX bandwidth to be %08x Mb/sec\n",
|
||||||
|
p_link->speed);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main API to configure PF max bandwidth where bw range is [1 - 100] */
|
||||||
|
int qed_configure_pf_max_bandwidth(struct qed_dev *cdev, u8 max_bw)
|
||||||
|
{
|
||||||
|
int i, rc = -EINVAL;
|
||||||
|
|
||||||
|
if (max_bw < 1 || max_bw > 100) {
|
||||||
|
DP_NOTICE(cdev, "PF max bw valid range is [1-100]\n");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
for_each_hwfn(cdev, i) {
|
||||||
|
struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
|
||||||
|
struct qed_hwfn *p_lead = QED_LEADING_HWFN(cdev);
|
||||||
|
struct qed_mcp_link_state *p_link;
|
||||||
|
struct qed_ptt *p_ptt;
|
||||||
|
|
||||||
|
p_link = &p_lead->mcp_info->link_output;
|
||||||
|
|
||||||
|
p_ptt = qed_ptt_acquire(p_hwfn);
|
||||||
|
if (!p_ptt)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
rc = __qed_configure_pf_max_bandwidth(p_hwfn, p_ptt,
|
||||||
|
p_link, max_bw);
|
||||||
|
|
||||||
|
qed_ptt_release(p_hwfn, p_ptt);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
|
@ -3837,7 +3837,7 @@ struct public_drv_mb {
|
||||||
|
|
||||||
#define DRV_MSG_CODE_SET_LLDP 0x24000000
|
#define DRV_MSG_CODE_SET_LLDP 0x24000000
|
||||||
#define DRV_MSG_CODE_SET_DCBX 0x25000000
|
#define DRV_MSG_CODE_SET_DCBX 0x25000000
|
||||||
|
#define DRV_MSG_CODE_BW_UPDATE_ACK 0x32000000
|
||||||
#define DRV_MSG_CODE_NIG_DRAIN 0x30000000
|
#define DRV_MSG_CODE_NIG_DRAIN 0x30000000
|
||||||
|
|
||||||
#define DRV_MSG_CODE_INITIATE_FLR 0x02000000
|
#define DRV_MSG_CODE_INITIATE_FLR 0x02000000
|
||||||
|
|
|
@ -473,6 +473,7 @@ static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn,
|
||||||
{
|
{
|
||||||
struct qed_mcp_link_state *p_link;
|
struct qed_mcp_link_state *p_link;
|
||||||
u32 status = 0;
|
u32 status = 0;
|
||||||
|
u8 max_bw;
|
||||||
|
|
||||||
p_link = &p_hwfn->mcp_info->link_output;
|
p_link = &p_hwfn->mcp_info->link_output;
|
||||||
memset(p_link, 0, sizeof(*p_link));
|
memset(p_link, 0, sizeof(*p_link));
|
||||||
|
@ -527,17 +528,15 @@ static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn,
|
||||||
p_link->speed = 0;
|
p_link->speed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_link->link_up && p_link->speed)
|
||||||
|
p_link->line_speed = p_link->speed;
|
||||||
|
else
|
||||||
|
p_link->line_speed = 0;
|
||||||
|
|
||||||
|
max_bw = p_hwfn->mcp_info->func_info.bandwidth_max;
|
||||||
|
|
||||||
/* Correct speed according to bandwidth allocation */
|
/* Correct speed according to bandwidth allocation */
|
||||||
if (p_hwfn->mcp_info->func_info.bandwidth_max && p_link->speed) {
|
__qed_configure_pf_max_bandwidth(p_hwfn, p_ptt, p_link, max_bw);
|
||||||
p_link->speed = p_link->speed *
|
|
||||||
p_hwfn->mcp_info->func_info.bandwidth_max /
|
|
||||||
100;
|
|
||||||
qed_init_pf_rl(p_hwfn, p_ptt, p_hwfn->rel_pf_id,
|
|
||||||
p_link->speed);
|
|
||||||
DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
|
|
||||||
"Configured MAX bandwidth to be %08x Mb/sec\n",
|
|
||||||
p_link->speed);
|
|
||||||
}
|
|
||||||
|
|
||||||
p_link->an = !!(status & LINK_STATUS_AUTO_NEGOTIATE_ENABLED);
|
p_link->an = !!(status & LINK_STATUS_AUTO_NEGOTIATE_ENABLED);
|
||||||
p_link->an_complete = !!(status &
|
p_link->an_complete = !!(status &
|
||||||
|
@ -648,6 +647,76 @@ int qed_mcp_set_link(struct qed_hwfn *p_hwfn,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void qed_read_pf_bandwidth(struct qed_hwfn *p_hwfn,
|
||||||
|
struct public_func *p_shmem_info)
|
||||||
|
{
|
||||||
|
struct qed_mcp_function_info *p_info;
|
||||||
|
|
||||||
|
p_info = &p_hwfn->mcp_info->func_info;
|
||||||
|
|
||||||
|
p_info->bandwidth_min = (p_shmem_info->config &
|
||||||
|
FUNC_MF_CFG_MIN_BW_MASK) >>
|
||||||
|
FUNC_MF_CFG_MIN_BW_SHIFT;
|
||||||
|
if (p_info->bandwidth_min < 1 || p_info->bandwidth_min > 100) {
|
||||||
|
DP_INFO(p_hwfn,
|
||||||
|
"bandwidth minimum out of bounds [%02x]. Set to 1\n",
|
||||||
|
p_info->bandwidth_min);
|
||||||
|
p_info->bandwidth_min = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_info->bandwidth_max = (p_shmem_info->config &
|
||||||
|
FUNC_MF_CFG_MAX_BW_MASK) >>
|
||||||
|
FUNC_MF_CFG_MAX_BW_SHIFT;
|
||||||
|
if (p_info->bandwidth_max < 1 || p_info->bandwidth_max > 100) {
|
||||||
|
DP_INFO(p_hwfn,
|
||||||
|
"bandwidth maximum out of bounds [%02x]. Set to 100\n",
|
||||||
|
p_info->bandwidth_max);
|
||||||
|
p_info->bandwidth_max = 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 qed_mcp_get_shmem_func(struct qed_hwfn *p_hwfn,
|
||||||
|
struct qed_ptt *p_ptt,
|
||||||
|
struct public_func *p_data,
|
||||||
|
int pfid)
|
||||||
|
{
|
||||||
|
u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
|
||||||
|
PUBLIC_FUNC);
|
||||||
|
u32 mfw_path_offsize = qed_rd(p_hwfn, p_ptt, addr);
|
||||||
|
u32 func_addr = SECTION_ADDR(mfw_path_offsize, pfid);
|
||||||
|
u32 i, size;
|
||||||
|
|
||||||
|
memset(p_data, 0, sizeof(*p_data));
|
||||||
|
|
||||||
|
size = min_t(u32, sizeof(*p_data),
|
||||||
|
QED_SECTION_SIZE(mfw_path_offsize));
|
||||||
|
for (i = 0; i < size / sizeof(u32); i++)
|
||||||
|
((u32 *)p_data)[i] = qed_rd(p_hwfn, p_ptt,
|
||||||
|
func_addr + (i << 2));
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qed_mcp_update_bw(struct qed_hwfn *p_hwfn,
|
||||||
|
struct qed_ptt *p_ptt)
|
||||||
|
{
|
||||||
|
struct qed_mcp_function_info *p_info;
|
||||||
|
struct public_func shmem_info;
|
||||||
|
u32 resp = 0, param = 0;
|
||||||
|
|
||||||
|
qed_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
|
||||||
|
MCP_PF_ID(p_hwfn));
|
||||||
|
|
||||||
|
qed_read_pf_bandwidth(p_hwfn, &shmem_info);
|
||||||
|
|
||||||
|
p_info = &p_hwfn->mcp_info->func_info;
|
||||||
|
|
||||||
|
qed_configure_pf_max_bandwidth(p_hwfn->cdev, p_info->bandwidth_max);
|
||||||
|
|
||||||
|
/* Acknowledge the MFW */
|
||||||
|
qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_BW_UPDATE_ACK, 0, &resp,
|
||||||
|
¶m);
|
||||||
|
}
|
||||||
|
|
||||||
int qed_mcp_handle_events(struct qed_hwfn *p_hwfn,
|
int qed_mcp_handle_events(struct qed_hwfn *p_hwfn,
|
||||||
struct qed_ptt *p_ptt)
|
struct qed_ptt *p_ptt)
|
||||||
{
|
{
|
||||||
|
@ -679,6 +748,9 @@ int qed_mcp_handle_events(struct qed_hwfn *p_hwfn,
|
||||||
case MFW_DRV_MSG_TRANSCEIVER_STATE_CHANGE:
|
case MFW_DRV_MSG_TRANSCEIVER_STATE_CHANGE:
|
||||||
qed_mcp_handle_transceiver_change(p_hwfn, p_ptt);
|
qed_mcp_handle_transceiver_change(p_hwfn, p_ptt);
|
||||||
break;
|
break;
|
||||||
|
case MFW_DRV_MSG_BW_UPDATE:
|
||||||
|
qed_mcp_update_bw(p_hwfn, p_ptt);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
DP_NOTICE(p_hwfn, "Unimplemented MFW message %d\n", i);
|
DP_NOTICE(p_hwfn, "Unimplemented MFW message %d\n", i);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
|
@ -758,28 +830,6 @@ int qed_mcp_get_media_type(struct qed_dev *cdev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 qed_mcp_get_shmem_func(struct qed_hwfn *p_hwfn,
|
|
||||||
struct qed_ptt *p_ptt,
|
|
||||||
struct public_func *p_data,
|
|
||||||
int pfid)
|
|
||||||
{
|
|
||||||
u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
|
|
||||||
PUBLIC_FUNC);
|
|
||||||
u32 mfw_path_offsize = qed_rd(p_hwfn, p_ptt, addr);
|
|
||||||
u32 func_addr = SECTION_ADDR(mfw_path_offsize, pfid);
|
|
||||||
u32 i, size;
|
|
||||||
|
|
||||||
memset(p_data, 0, sizeof(*p_data));
|
|
||||||
|
|
||||||
size = min_t(u32, sizeof(*p_data),
|
|
||||||
QED_SECTION_SIZE(mfw_path_offsize));
|
|
||||||
for (i = 0; i < size / sizeof(u32); i++)
|
|
||||||
((u32 *)p_data)[i] = qed_rd(p_hwfn, p_ptt,
|
|
||||||
func_addr + (i << 2));
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qed_mcp_get_shmem_proto(struct qed_hwfn *p_hwfn,
|
qed_mcp_get_shmem_proto(struct qed_hwfn *p_hwfn,
|
||||||
struct public_func *p_info,
|
struct public_func *p_info,
|
||||||
|
@ -818,26 +868,7 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qed_read_pf_bandwidth(p_hwfn, &shmem_info);
|
||||||
info->bandwidth_min = (shmem_info.config &
|
|
||||||
FUNC_MF_CFG_MIN_BW_MASK) >>
|
|
||||||
FUNC_MF_CFG_MIN_BW_SHIFT;
|
|
||||||
if (info->bandwidth_min < 1 || info->bandwidth_min > 100) {
|
|
||||||
DP_INFO(p_hwfn,
|
|
||||||
"bandwidth minimum out of bounds [%02x]. Set to 1\n",
|
|
||||||
info->bandwidth_min);
|
|
||||||
info->bandwidth_min = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
info->bandwidth_max = (shmem_info.config &
|
|
||||||
FUNC_MF_CFG_MAX_BW_MASK) >>
|
|
||||||
FUNC_MF_CFG_MAX_BW_SHIFT;
|
|
||||||
if (info->bandwidth_max < 1 || info->bandwidth_max > 100) {
|
|
||||||
DP_INFO(p_hwfn,
|
|
||||||
"bandwidth maximum out of bounds [%02x]. Set to 100\n",
|
|
||||||
info->bandwidth_max);
|
|
||||||
info->bandwidth_max = 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shmem_info.mac_upper || shmem_info.mac_lower) {
|
if (shmem_info.mac_upper || shmem_info.mac_lower) {
|
||||||
info->mac[0] = (u8)(shmem_info.mac_upper >> 8);
|
info->mac[0] = (u8)(shmem_info.mac_upper >> 8);
|
||||||
|
@ -938,9 +969,10 @@ qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn,
|
||||||
|
|
||||||
p_drv_version = &union_data.drv_version;
|
p_drv_version = &union_data.drv_version;
|
||||||
p_drv_version->version = p_ver->version;
|
p_drv_version->version = p_ver->version;
|
||||||
|
|
||||||
for (i = 0; i < MCP_DRV_VER_STR_SIZE - 1; i += 4) {
|
for (i = 0; i < MCP_DRV_VER_STR_SIZE - 1; i += 4) {
|
||||||
val = cpu_to_be32(p_ver->name[i]);
|
val = cpu_to_be32(p_ver->name[i]);
|
||||||
*(u32 *)&p_drv_version->name[i * sizeof(u32)] = val;
|
*(__be32 *)&p_drv_version->name[i * sizeof(u32)] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&mb_params, 0, sizeof(mb_params));
|
memset(&mb_params, 0, sizeof(mb_params));
|
||||||
|
|
|
@ -40,7 +40,13 @@ struct qed_mcp_link_capabilities {
|
||||||
struct qed_mcp_link_state {
|
struct qed_mcp_link_state {
|
||||||
bool link_up;
|
bool link_up;
|
||||||
|
|
||||||
u32 speed; /* In Mb/s */
|
/* Actual link speed in Mb/s */
|
||||||
|
u32 line_speed;
|
||||||
|
|
||||||
|
/* PF max speed in Mb/s, deduced from line_speed
|
||||||
|
* according to PF max bandwidth configuration.
|
||||||
|
*/
|
||||||
|
u32 speed;
|
||||||
bool full_duplex;
|
bool full_duplex;
|
||||||
|
|
||||||
bool an;
|
bool an;
|
||||||
|
@ -388,5 +394,9 @@ int qed_mcp_reset(struct qed_hwfn *p_hwfn,
|
||||||
* @return true iff MFW is running and mcp_info is initialized
|
* @return true iff MFW is running and mcp_info is initialized
|
||||||
*/
|
*/
|
||||||
bool qed_mcp_is_init(struct qed_hwfn *p_hwfn);
|
bool qed_mcp_is_init(struct qed_hwfn *p_hwfn);
|
||||||
|
int qed_configure_pf_max_bandwidth(struct qed_dev *cdev, u8 max_bw);
|
||||||
|
int __qed_configure_pf_max_bandwidth(struct qed_hwfn *p_hwfn,
|
||||||
|
struct qed_ptt *p_ptt,
|
||||||
|
struct qed_mcp_link_state *p_link,
|
||||||
|
u8 max_bw);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue