On 2021/1/22 18:18, Lijun Ou wrote:
From: Chengwen Feng fengchengwen@huawei.com
This patch support LSC(Link Status Change) event report.
Signed-off-by: Chengwen Feng fengchengwen@huawei.com Signed-off-by: Lijun Ou oulijun@huawei.com
drivers/net/hns3/hns3_ethdev.c | 52 +++++++++++++++++++++++++++++++++++---- drivers/net/hns3/hns3_ethdev.h | 4 ++- drivers/net/hns3/hns3_ethdev_vf.c | 40 +++++++++++++++++++++++++++++- drivers/net/hns3/hns3_mbx.c | 14 ++++++----- 4 files changed, 97 insertions(+), 13 deletions(-)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index 94b6e44..bc77608 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -19,6 +19,7 @@ #define HNS3_DEFAULT_PORT_CONF_QUEUES_NUM 1
#define HNS3_SERVICE_INTERVAL 1000000 /* us */ +#define HNS3_SERVICE_QUICK_INTERVAL 10 #define HNS3_INVALID_PVID 0xFFFF
#define HNS3_FILTER_TYPE_VF 0 @@ -93,6 +94,7 @@ static int hns3_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); static int hns3_vlan_pvid_configure(struct hns3_adapter *hns, uint16_t pvid, int on); static int hns3_update_speed_duplex(struct rte_eth_dev *eth_dev); +static bool hns3_update_link_status(struct hns3_hw *hw);
static int hns3_add_mc_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr); @@ -4458,7 +4460,7 @@ hns3_get_mac_link_status(struct hns3_hw *hw) return !!link_status; }
-void +static bool hns3_update_link_status(struct hns3_hw *hw) { int state; @@ -4467,7 +4469,36 @@ hns3_update_link_status(struct hns3_hw *hw) if (state != hw->mac.link_status) { hw->mac.link_status = state; hns3_warn(hw, "Link status change to %s!", state ? "up" : "down");
}return true;
pls add check reseting logic: /* * There are many reset levels, some of them have no impact on port's * link status. But driver reset recover process are same (include stop * Rx/Tx & reinit hardware and so on), so if in resetting the link * status will be ETH_LINK_DOWN else get the link status from firmware. */ if (rte_atomic16_read(&hw->reset.resetting)) state = ETH_LINK_DOWN; else state = hns3_get_mac_link_status(hw); else will not report lse in flr reset scenes.
- return false;
+}
+/*
- Current, the PF driver get link status by two ways:
- Periodic polling in the intr thread context, driver call
- hns3_update_link_status to update link status.
- Firmware report async interrupt, driver process the event in the intr
- thread context, and call hns3_update_link_status to update link status.
- If detect link status changed, driver need report LSE. One method is add the
- report LSE logic in hns3_update_link_status.
- But the PF driver ops(link_update) also call hns3_update_link_status to
- update link status.
- If we report LSE in hns3_update_link_status, it may lead to deadlock in the
- bonding application.
- So add the one new API which used only in intr thread context.
- */
+void +hns3_update_link_status_and_event(struct hns3_hw *hw) +{
- struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
- bool changed = hns3_update_link_status(hw);
- if (changed)
rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
}
static void @@ -4479,9 +4510,10 @@ hns3_service_handler(void *param)
if (!hns3_is_reset_pending(hns)) { hns3_update_speed_duplex(eth_dev);
hns3_update_link_status(hw);
- } else
hns3_update_link_status_and_event(hw);
pls add hns3_update_link_status_and_event before hns3_update_speed_duplex
} else { hns3_warn(hw, "Cancel the query when reset is pending");
}
rte_eal_alarm_set(HNS3_SERVICE_INTERVAL, hns3_service_handler, eth_dev);
} @@ -5557,8 +5589,10 @@ hns3_stop_service(struct hns3_adapter *hns) struct rte_eth_dev *eth_dev;
eth_dev = &rte_eth_devices[hw->data->port_id];
- if (hw->adapter_state == HNS3_NIC_STARTED)
if (hw->adapter_state == HNS3_NIC_STARTED) { rte_eal_alarm_cancel(hns3_service_handler, eth_dev);
hns3_update_link_status_and_event(hw);
} hw->mac.link_status = ETH_LINK_DOWN;
hns3_set_rxtx_function(eth_dev);
@@ -5601,7 +5635,15 @@ hns3_start_service(struct hns3_adapter *hns) hns3_set_rxtx_function(eth_dev); hns3_mp_req_start_rxtx(eth_dev); if (hw->adapter_state == HNS3_NIC_STARTED) {
hns3_service_handler(eth_dev);
/*
* This API parent function already hold the hns3_hw.lock, the
* hns3_service_handler may report lse, in bonding application
* it will call driver's ops which may acquire the hns3_hw.lock
* again, thus lead to deadlock.
* We defer calls hns3_service_handler to avoid the deadlock.
*/
rte_eal_alarm_set(HNS3_SERVICE_QUICK_INTERVAL,
hns3_service_handler, eth_dev);
/* Enable interrupt of all rx queues before enabling queues */ hns3_dev_all_rx_queue_intr_enable(hw, true);
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h index 0d17170..547e991 100644 --- a/drivers/net/hns3/hns3_ethdev.h +++ b/drivers/net/hns3/hns3_ethdev.h @@ -946,11 +946,13 @@ int hns3_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg); bool hns3_is_reset_pending(struct hns3_adapter *hns); bool hns3vf_is_reset_pending(struct hns3_adapter *hns); -void hns3_update_link_status(struct hns3_hw *hw); +void hns3_update_link_status_and_event(struct hns3_hw *hw); void hns3_ether_format_addr(char *buf, uint16_t size, const struct rte_ether_addr *ether_addr); int hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info); +void hns3vf_update_link_status(struct hns3_hw *hw, uint8_t link_status,
uint32_t link_speed, uint8_t link_duplex);
static inline bool is_reset_pending(struct hns3_adapter *hns) diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c index 7eb0b11..470aaee 100644 --- a/drivers/net/hns3/hns3_ethdev_vf.c +++ b/drivers/net/hns3/hns3_ethdev_vf.c @@ -1440,6 +1440,41 @@ hns3vf_request_link_info(struct hns3_hw *hw) hns3_err(hw, "Failed to fetch link status from PF: %d", ret); }
+void +hns3vf_update_link_status(struct hns3_hw *hw, uint8_t link_status,
uint32_t link_speed, uint8_t link_duplex)
+{
- struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
- struct hns3_mac *mac = &hw->mac;
- bool report_lse;
- bool changed;
- changed = mac->link_status != link_status ||
mac->link_speed != link_speed ||
mac->link_duplex != link_duplex;
- if (!changed)
return;
- /*
* VF's link status/speed/duplex were updated by polling from PF driver,
* because the link status/speed/duplex may be changed in the polling
* interval, so driver will report lse (lsc event) once any of the above
* thress variables changed.
* But if the PF's link status is down and driver saved link status is
* also down, there are no need to report lse.
*/
- report_lse = true;
- if (link_status == ETH_LINK_DOWN && link_status == mac->link_status)
report_lse = false;
- mac->link_status = link_status;
- mac->link_speed = link_speed;
- mac->link_duplex = link_duplex;
- if (report_lse)
rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
+}
static int hns3vf_vlan_filter_configure(struct hns3_adapter *hns, uint16_t vlan_id, int on) { @@ -2373,8 +2408,11 @@ hns3vf_stop_service(struct hns3_adapter *hns) struct rte_eth_dev *eth_dev;
eth_dev = &rte_eth_devices[hw->data->port_id];
- if (hw->adapter_state == HNS3_NIC_STARTED)
if (hw->adapter_state == HNS3_NIC_STARTED) { rte_eal_alarm_cancel(hns3vf_service_handler, eth_dev);
hns3vf_update_link_status(hw, ETH_LINK_DOWN, hw->mac.link_speed,
hw->mac.link_duplex);
} hw->mac.link_status = ETH_LINK_DOWN;
hns3_set_rxtx_function(eth_dev);
diff --git a/drivers/net/hns3/hns3_mbx.c b/drivers/net/hns3/hns3_mbx.c index d2a5db8..3e44e3b 100644 --- a/drivers/net/hns3/hns3_mbx.c +++ b/drivers/net/hns3/hns3_mbx.c @@ -203,8 +203,9 @@ hns3_cmd_crq_empty(struct hns3_hw *hw) static void hns3_mbx_handler(struct hns3_hw *hw) {
- struct hns3_mac *mac = &hw->mac; enum hns3_reset_level reset_level;
- uint8_t link_status, link_duplex;
- uint32_t link_speed; uint16_t *msg_q; uint8_t opcode; uint32_t tail;
@@ -218,10 +219,11 @@ hns3_mbx_handler(struct hns3_hw *hw) opcode = msg_q[0] & 0xff; switch (opcode) { case HNS3_MBX_LINK_STAT_CHANGE:
memcpy(&mac->link_speed, &msg_q[2],
sizeof(mac->link_speed));
mac->link_status = rte_le_to_cpu_16(msg_q[1]);
mac->link_duplex = (uint8_t)rte_le_to_cpu_16(msg_q[4]);
memcpy(&link_speed, &msg_q[2], sizeof(link_speed));
link_status = rte_le_to_cpu_16(msg_q[1]);
link_duplex = (uint8_t)rte_le_to_cpu_16(msg_q[4]);
hns3vf_update_link_status(hw, link_status, link_speed,
case HNS3_MBX_ASSERTING_RESET: /* PF has asserted reset hence VF should go in pendinglink_duplex); break;
@@ -310,7 +312,7 @@ hns3_handle_link_change_event(struct hns3_hw *hw, if (!req->msg[LINK_STATUS_OFFSET]) hns3_link_fail_parse(hw, req->msg[LINK_FAIL_CODE_OFFSET]);
- hns3_update_link_status(hw);
- hns3_update_link_status_and_event(hw);
}
static void