Commit 2c632ad8 authored by Vadim Lomovtsev's avatar Vadim Lomovtsev Committed by David S. Miller

net: thunderx: move link state polling function to VF

Move the link change polling task to VF side in order to
prevent races between VF and PF while sending link change
message(s). This commit is to implement link change request
to be initiated by VF.
Signed-off-by: default avatarVadim Lomovtsev <vlomovtsev@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 609ea65c
...@@ -331,7 +331,7 @@ struct nicvf { ...@@ -331,7 +331,7 @@ struct nicvf {
struct workqueue_struct *nicvf_rx_mode_wq; struct workqueue_struct *nicvf_rx_mode_wq;
/* mutex to protect VF's mailbox contents from concurrent access */ /* mutex to protect VF's mailbox contents from concurrent access */
struct mutex rx_mode_mtx; struct mutex rx_mode_mtx;
struct delayed_work link_change_work;
/* PTP timestamp */ /* PTP timestamp */
struct cavium_ptp *ptp_clock; struct cavium_ptp *ptp_clock;
/* Inbound timestamping is on */ /* Inbound timestamping is on */
......
...@@ -929,6 +929,35 @@ static void nic_config_timestamp(struct nicpf *nic, int vf, struct set_ptp *ptp) ...@@ -929,6 +929,35 @@ static void nic_config_timestamp(struct nicpf *nic, int vf, struct set_ptp *ptp)
nic_reg_write(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3), pkind_val); nic_reg_write(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3), pkind_val);
} }
static void nic_link_status_get(struct nicpf *nic, u8 vf)
{
union nic_mbx mbx = {};
struct bgx_link_status link;
u8 bgx, lmac;
mbx.link_status.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE;
/* Get BGX, LMAC indices for the VF */
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]);
/* Get interface link status */
bgx_get_lmac_link_state(nic->node, bgx, lmac, &link);
nic->link[vf] = link.link_up;
nic->duplex[vf] = link.duplex;
nic->speed[vf] = link.speed;
/* Send a mbox message to VF with current link status */
mbx.link_status.link_up = link.link_up;
mbx.link_status.duplex = link.duplex;
mbx.link_status.speed = link.speed;
mbx.link_status.mac_type = link.mac_type;
/* reply with link status */
nic_send_msg_to_vf(nic, vf, &mbx);
}
/* 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)
{ {
...@@ -1108,6 +1137,13 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) ...@@ -1108,6 +1137,13 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
bgx_set_xcast_mode(nic->node, bgx, lmac, mbx.xcast.mode); bgx_set_xcast_mode(nic->node, bgx, lmac, mbx.xcast.mode);
break; break;
case NIC_MBOX_MSG_BGX_LINK_CHANGE:
if (vf >= nic->num_vf_en) {
ret = -1; /* NACK */
break;
}
nic_link_status_get(nic, vf);
goto unlock;
default: default:
dev_err(&nic->pdev->dev, dev_err(&nic->pdev->dev,
"Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg); "Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg);
...@@ -1419,9 +1455,6 @@ static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1419,9 +1455,6 @@ static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_disable_sriov; goto err_disable_sriov;
} }
INIT_DELAYED_WORK(&nic->dwork, nic_poll_for_link);
queue_delayed_work(nic->check_link, &nic->dwork, 0);
return 0; return 0;
err_disable_sriov: err_disable_sriov:
......
...@@ -242,21 +242,24 @@ static void nicvf_handle_mbx_intr(struct nicvf *nic) ...@@ -242,21 +242,24 @@ static void nicvf_handle_mbx_intr(struct nicvf *nic)
break; break;
case NIC_MBOX_MSG_BGX_LINK_CHANGE: case NIC_MBOX_MSG_BGX_LINK_CHANGE:
nic->pf_acked = true; nic->pf_acked = true;
nic->link_up = mbx.link_status.link_up; if (nic->link_up != mbx.link_status.link_up) {
nic->duplex = mbx.link_status.duplex; nic->link_up = mbx.link_status.link_up;
nic->speed = mbx.link_status.speed; nic->duplex = mbx.link_status.duplex;
nic->mac_type = mbx.link_status.mac_type; nic->speed = mbx.link_status.speed;
if (nic->link_up) { nic->mac_type = mbx.link_status.mac_type;
netdev_info(nic->netdev, "Link is Up %d Mbps %s duplex\n", if (nic->link_up) {
nic->speed, netdev_info(nic->netdev,
nic->duplex == DUPLEX_FULL ? "Link is Up %d Mbps %s duplex\n",
"Full" : "Half"); nic->speed,
netif_carrier_on(nic->netdev); nic->duplex == DUPLEX_FULL ?
netif_tx_start_all_queues(nic->netdev); "Full" : "Half");
} else { netif_carrier_on(nic->netdev);
netdev_info(nic->netdev, "Link is Down\n"); netif_tx_start_all_queues(nic->netdev);
netif_carrier_off(nic->netdev); } else {
netif_tx_stop_all_queues(nic->netdev); netdev_info(nic->netdev, "Link is Down\n");
netif_carrier_off(nic->netdev);
netif_tx_stop_all_queues(nic->netdev);
}
} }
break; break;
case NIC_MBOX_MSG_ALLOC_SQS: case NIC_MBOX_MSG_ALLOC_SQS:
...@@ -1325,6 +1328,8 @@ int nicvf_stop(struct net_device *netdev) ...@@ -1325,6 +1328,8 @@ int nicvf_stop(struct net_device *netdev)
struct nicvf_cq_poll *cq_poll = NULL; struct nicvf_cq_poll *cq_poll = NULL;
union nic_mbx mbx = {}; union nic_mbx mbx = {};
cancel_delayed_work_sync(&nic->link_change_work);
/* wait till all queued set_rx_mode tasks completes */ /* wait till all queued set_rx_mode tasks completes */
drain_workqueue(nic->nicvf_rx_mode_wq); drain_workqueue(nic->nicvf_rx_mode_wq);
...@@ -1427,6 +1432,18 @@ static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu) ...@@ -1427,6 +1432,18 @@ static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
return nicvf_send_msg_to_pf(nic, &mbx); return nicvf_send_msg_to_pf(nic, &mbx);
} }
static void nicvf_link_status_check_task(struct work_struct *work_arg)
{
struct nicvf *nic = container_of(work_arg,
struct nicvf,
link_change_work.work);
union nic_mbx mbx = {};
mbx.msg.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE;
nicvf_send_msg_to_pf(nic, &mbx);
queue_delayed_work(nic->nicvf_rx_mode_wq,
&nic->link_change_work, 2 * HZ);
}
int nicvf_open(struct net_device *netdev) int nicvf_open(struct net_device *netdev)
{ {
int cpu, err, qidx; int cpu, err, qidx;
...@@ -1533,6 +1550,11 @@ int nicvf_open(struct net_device *netdev) ...@@ -1533,6 +1550,11 @@ int nicvf_open(struct net_device *netdev)
/* Send VF config done msg to PF */ /* Send VF config done msg to PF */
nicvf_send_cfg_done(nic); nicvf_send_cfg_done(nic);
INIT_DELAYED_WORK(&nic->link_change_work,
nicvf_link_status_check_task);
queue_delayed_work(nic->nicvf_rx_mode_wq,
&nic->link_change_work, 0);
return 0; return 0;
cleanup: cleanup:
nicvf_disable_intr(nic, NICVF_INTR_MBOX, 0); nicvf_disable_intr(nic, NICVF_INTR_MBOX, 0);
......
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