Commit f406ce42 authored by Pavel Fedin's avatar Pavel Fedin Committed by David S. Miller

net: thunderx: Correctly distinguish between VF and LMAC count

Commit bc69fdfc
("net: thunderx: Enable BGX LMAC's RX/TX only after VF is up")
introduces lmac_cnt member and starts verifying VF number against it.
This is plain wrong, and works only because currently we have hardcoded
1:1 mapping between VFs and LMACs, and in this case num_vf_en and
lmac_cnt are always equal. However in future this may change, and the
code will badly misbehave. The worst consequence of this is failure to
deliver link status messages, causing VFs to go defunct because since
commit 0b72a9a1 ("net: thunderx: Switchon carrier only upon
interface link up") VF will not fully bring itself up without it.

This patch fixes the potential problem by doing VF number checks against
the num_vf_en. Since lmac_cnt is not used anywhere else, it is removed.

Additionally some duplicated code is factored out into nic_enable_vf()
Signed-off-by: default avatarPavel Fedin <p.fedin@samsung.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a322a1bc
...@@ -37,7 +37,6 @@ struct nicpf { ...@@ -37,7 +37,6 @@ struct nicpf {
#define NIC_GET_BGX_FROM_VF_LMAC_MAP(map) ((map >> 4) & 0xF) #define NIC_GET_BGX_FROM_VF_LMAC_MAP(map) ((map >> 4) & 0xF)
#define NIC_GET_LMAC_FROM_VF_LMAC_MAP(map) (map & 0xF) #define NIC_GET_LMAC_FROM_VF_LMAC_MAP(map) (map & 0xF)
u8 vf_lmac_map[MAX_LMAC]; u8 vf_lmac_map[MAX_LMAC];
u8 lmac_cnt;
struct delayed_work dwork; struct delayed_work dwork;
struct workqueue_struct *check_link; struct workqueue_struct *check_link;
u8 link[MAX_LMAC]; u8 link[MAX_LMAC];
...@@ -280,7 +279,6 @@ static void nic_set_lmac_vf_mapping(struct nicpf *nic) ...@@ -280,7 +279,6 @@ static void nic_set_lmac_vf_mapping(struct nicpf *nic)
u64 lmac_credit; u64 lmac_credit;
nic->num_vf_en = 0; nic->num_vf_en = 0;
nic->lmac_cnt = 0;
for (bgx = 0; bgx < NIC_MAX_BGX; bgx++) { for (bgx = 0; bgx < NIC_MAX_BGX; bgx++) {
if (!(bgx_map & (1 << bgx))) if (!(bgx_map & (1 << bgx)))
...@@ -290,7 +288,6 @@ static void nic_set_lmac_vf_mapping(struct nicpf *nic) ...@@ -290,7 +288,6 @@ static void nic_set_lmac_vf_mapping(struct nicpf *nic)
nic->vf_lmac_map[next_bgx_lmac++] = nic->vf_lmac_map[next_bgx_lmac++] =
NIC_SET_VF_LMAC_MAP(bgx, lmac); NIC_SET_VF_LMAC_MAP(bgx, lmac);
nic->num_vf_en += lmac_cnt; nic->num_vf_en += lmac_cnt;
nic->lmac_cnt += lmac_cnt;
/* Program LMAC credits */ /* Program LMAC credits */
lmac_credit = (1ull << 1); /* channel credit enable */ lmac_credit = (1ull << 1); /* channel credit enable */
...@@ -618,6 +615,21 @@ static int nic_config_loopback(struct nicpf *nic, struct set_loopback *lbk) ...@@ -618,6 +615,21 @@ static int nic_config_loopback(struct nicpf *nic, struct set_loopback *lbk)
return 0; return 0;
} }
static void nic_enable_vf(struct nicpf *nic, int vf, bool enable)
{
int bgx, lmac;
nic->vf_enabled[vf] = enable;
if (vf >= nic->num_vf_en)
return;
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
bgx_lmac_rx_tx_enable(nic->node, bgx, lmac, enable);
}
/* Interrupt handler to handle mailbox messages from VFs */ /* Interrupt handler to handle mailbox messages from VFs */
static void nic_handle_mbx_intr(struct nicpf *nic, int vf) static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
{ {
...@@ -717,29 +729,14 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) ...@@ -717,29 +729,14 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
break; break;
case NIC_MBOX_MSG_CFG_DONE: case NIC_MBOX_MSG_CFG_DONE:
/* Last message of VF config msg sequence */ /* Last message of VF config msg sequence */
nic->vf_enabled[vf] = true; nic_enable_vf(nic, vf, true);
if (vf >= nic->lmac_cnt)
goto unlock;
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
bgx_lmac_rx_tx_enable(nic->node, bgx, lmac, true);
goto unlock; goto unlock;
case NIC_MBOX_MSG_SHUTDOWN: case NIC_MBOX_MSG_SHUTDOWN:
/* First msg in VF teardown sequence */ /* First msg in VF teardown sequence */
nic->vf_enabled[vf] = false;
if (vf >= nic->num_vf_en) if (vf >= nic->num_vf_en)
nic->sqs_used[vf - nic->num_vf_en] = false; nic->sqs_used[vf - nic->num_vf_en] = false;
nic->pqs_vf[vf] = 0; nic->pqs_vf[vf] = 0;
nic_enable_vf(nic, vf, false);
if (vf >= nic->lmac_cnt)
break;
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
bgx_lmac_rx_tx_enable(nic->node, bgx, lmac, false);
break; break;
case NIC_MBOX_MSG_ALLOC_SQS: case NIC_MBOX_MSG_ALLOC_SQS:
nic_alloc_sqs(nic, &mbx.sqs_alloc); nic_alloc_sqs(nic, &mbx.sqs_alloc);
...@@ -958,7 +955,7 @@ static void nic_poll_for_link(struct work_struct *work) ...@@ -958,7 +955,7 @@ static void nic_poll_for_link(struct work_struct *work)
mbx.link_status.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE; mbx.link_status.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE;
for (vf = 0; vf < nic->lmac_cnt; vf++) { for (vf = 0; vf < nic->num_vf_en; vf++) {
/* Poll only if VF is UP */ /* Poll only if VF is UP */
if (!nic->vf_enabled[vf]) if (!nic->vf_enabled[vf])
continue; continue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment