diff options
author | David S. Miller <davem@davemloft.net> | 2019-01-26 20:33:31 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-01-26 20:33:31 +0300 |
commit | 08c666b7033d72038f3dca1478b0d368aa4d0233 (patch) | |
tree | 1042e124a1e5b77ba7f60a737d238f1f86418e08 /drivers/net/ethernet | |
parent | 45e8fddd9b97a94e25a1644a853826e7e6fe8d7d (diff) | |
parent | f01f5559cac89e57f2420aa77abf35f2e7b09104 (diff) | |
download | linux-08c666b7033d72038f3dca1478b0d368aa4d0233.tar.xz |
Merge branch 'hns3-next'
Huazhong Tan says:
====================
code optimizations & bugfixes for HNS3 driver
This patchset includes bugfixes and code optimizations for the HNS3
ethernet controller driver
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
7 files changed, 138 insertions, 69 deletions
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index dc3db45361d3..585800e634e6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -477,7 +477,6 @@ struct hnae3_dcb_ops { u8 (*getdcbx)(struct hnae3_handle *); u8 (*setdcbx)(struct hnae3_handle *, u8); - int (*map_update)(struct hnae3_handle *); int (*setup_tc)(struct hnae3_handle *, u8, u8 *); }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 327dde2765ab..4b38c37eef8f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -348,6 +348,8 @@ static int hns3_nic_net_up(struct net_device *netdev) return ret; } + clear_bit(HNS3_NIC_STATE_DOWN, &priv->state); + /* enable the vectors */ for (i = 0; i < priv->vector_num; i++) hns3_vector_enable(&priv->tqp_vector[i]); @@ -361,11 +363,10 @@ static int hns3_nic_net_up(struct net_device *netdev) if (ret) goto out_start_err; - clear_bit(HNS3_NIC_STATE_DOWN, &priv->state); - return 0; out_start_err: + set_bit(HNS3_NIC_STATE_DOWN, &priv->state); while (j--) hns3_tqp_disable(h->kinfo.tqp[j]); @@ -506,7 +507,7 @@ static u8 hns3_get_netdev_flags(struct net_device *netdev) u8 flags = 0; if (netdev->flags & IFF_PROMISC) { - flags = HNAE3_USER_UPE | HNAE3_USER_MPE; + flags = HNAE3_USER_UPE | HNAE3_USER_MPE | HNAE3_BPE; } else { flags |= HNAE3_VLAN_FLTR; if (netdev->flags & IFF_ALLMULTI) @@ -541,13 +542,13 @@ static void hns3_nic_set_rx_mode(struct net_device *netdev) } } - hns3_update_promisc_mode(netdev, new_flags); /* User mode Promisc mode enable and vlan filtering is disabled to * let all packets in. MAC-VLAN Table overflow Promisc enabled and * vlan fitering is enabled */ hns3_enable_vlan_filter(netdev, new_flags & HNAE3_VLAN_FLTR); h->netdev_flags = new_flags; + hns3_update_promisc_mode(netdev, new_flags); } int hns3_update_promisc_mode(struct net_device *netdev, u8 promisc_flags) @@ -1133,6 +1134,7 @@ static int hns3_nic_maybe_stop_tso(struct sk_buff **out_skb, int *bnum, struct hns3_enet_ring *ring) { struct sk_buff *skb = *out_skb; + struct sk_buff *new_skb = NULL; struct skb_frag_struct *frag; int bdnum_for_frag; int frag_num; @@ -1155,7 +1157,19 @@ static int hns3_nic_maybe_stop_tso(struct sk_buff **out_skb, int *bnum, buf_num += bdnum_for_frag; } - if (buf_num > ring_space(ring)) + if (unlikely(buf_num > HNS3_MAX_BD_PER_FRAG)) { + buf_num = (skb->len + HNS3_MAX_BD_SIZE - 1) / HNS3_MAX_BD_SIZE; + if (ring_space(ring) < buf_num) + return -EBUSY; + /* manual split the send packet */ + new_skb = skb_copy(skb, GFP_ATOMIC); + if (!new_skb) + return -ENOMEM; + dev_kfree_skb_any(skb); + *out_skb = new_skb; + } + + if (unlikely(ring_space(ring) < buf_num)) return -EBUSY; *bnum = buf_num; @@ -1166,11 +1180,24 @@ static int hns3_nic_maybe_stop_tx(struct sk_buff **out_skb, int *bnum, struct hns3_enet_ring *ring) { struct sk_buff *skb = *out_skb; + struct sk_buff *new_skb = NULL; int buf_num; /* No. of segments (plus a header) */ buf_num = skb_shinfo(skb)->nr_frags + 1; + if (unlikely(buf_num > HNS3_MAX_BD_PER_FRAG)) { + buf_num = (skb->len + HNS3_MAX_BD_SIZE - 1) / HNS3_MAX_BD_SIZE; + if (ring_space(ring) < buf_num) + return -EBUSY; + /* manual split the send packet */ + new_skb = skb_copy(skb, GFP_ATOMIC); + if (!new_skb) + return -ENOMEM; + dev_kfree_skb_any(skb); + *out_skb = new_skb; + } + if (unlikely(ring_space(ring) < buf_num)) return -EBUSY; @@ -1425,9 +1452,7 @@ static void hns3_nic_get_stats64(struct net_device *netdev, start = u64_stats_fetch_begin_irq(&ring->syncp); tx_bytes += ring->stats.tx_bytes; tx_pkts += ring->stats.tx_pkts; - tx_drop += ring->stats.tx_busy; tx_drop += ring->stats.sw_err_cnt; - tx_errors += ring->stats.tx_busy; tx_errors += ring->stats.sw_err_cnt; } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); @@ -1438,7 +1463,6 @@ static void hns3_nic_get_stats64(struct net_device *netdev, rx_bytes += ring->stats.rx_bytes; rx_pkts += ring->stats.rx_pkts; rx_drop += ring->stats.non_vld_descs; - rx_drop += ring->stats.err_pkt_len; rx_drop += ring->stats.l2_err; rx_errors += ring->stats.non_vld_descs; rx_errors += ring->stats.l2_err; @@ -1485,8 +1509,6 @@ static int hns3_setup_tc(struct net_device *netdev, void *type_data) u8 tc = mqprio_qopt->qopt.num_tc; u16 mode = mqprio_qopt->mode; u8 hw = mqprio_qopt->qopt.hw; - bool if_running; - int ret; if (!((hw == TC_MQPRIO_HW_OFFLOAD_TCS && mode == TC_MQPRIO_MODE_CHANNEL) || (!hw && tc == 0))) @@ -1498,24 +1520,8 @@ static int hns3_setup_tc(struct net_device *netdev, void *type_data) if (!netdev) return -EINVAL; - if_running = netif_running(netdev); - if (if_running) { - hns3_nic_net_stop(netdev); - msleep(100); - } - - ret = (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ? + return (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ? kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : -EOPNOTSUPP; - if (ret) - goto out; - - ret = hns3_nic_set_real_num_queue(netdev); - -out: - if (if_running) - hns3_nic_net_open(netdev); - - return ret; } static int hns3_nic_setup_tc(struct net_device *dev, enum tc_setup_type type, @@ -1784,6 +1790,7 @@ static void hns3_remove(struct pci_dev *pdev) hns3_disable_sriov(pdev); hnae3_unregister_ae_dev(ae_dev); + pci_set_drvdata(pdev, NULL); } /** @@ -3608,6 +3615,7 @@ static int hns3_client_init(struct hnae3_handle *handle) priv->netdev = netdev; priv->ae_handle = handle; priv->tx_timeout_count = 0; + set_bit(HNS3_NIC_STATE_DOWN, &priv->state); handle->kinfo.netdev = netdev; handle->priv = (void *)priv; @@ -3752,7 +3760,6 @@ static int hns3_client_setup_tc(struct hnae3_handle *handle, u8 tc) { struct hnae3_knic_private_info *kinfo = &handle->kinfo; struct net_device *ndev = kinfo->netdev; - int ret; if (tc > HNAE3_MAX_TC) return -EINVAL; @@ -3760,14 +3767,7 @@ static int hns3_client_setup_tc(struct hnae3_handle *handle, u8 tc) if (!ndev) return -ENODEV; - ret = (kinfo->dcb_ops && kinfo->dcb_ops->map_update) ? - kinfo->dcb_ops->map_update(handle) : -EOPNOTSUPP; - if (ret) - return ret; - - ret = hns3_nic_set_real_num_queue(ndev); - - return ret; + return hns3_nic_set_real_num_queue(ndev); } static int hns3_recover_hw_addr(struct net_device *ndev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index abb78696d7ce..ed73f7fc9171 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -117,7 +117,7 @@ static int hns3_lp_up(struct net_device *ndev, enum hnae3_loop loop_mode) ret = hns3_lp_setup(ndev, loop_mode, true); usleep_range(10000, 20000); - return 0; + return ret; } static int hns3_lp_down(struct net_device *ndev, enum hnae3_loop loop_mode) @@ -334,10 +334,10 @@ static void hns3_self_test(struct net_device *ndev, continue; data[test_index] = hns3_lp_up(ndev, loop_type); - if (!data[test_index]) { + if (!data[test_index]) data[test_index] = hns3_lp_run_test(ndev, loop_type); - hns3_lp_down(ndev, loop_type); - } + + hns3_lp_down(ndev, loop_type); if (data[test_index]) eth_test->flags |= ETH_TEST_FL_FAILED; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index 3a4a54ee5204..961aedb0e20f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -156,10 +156,8 @@ static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets, return 0; } -static int hclge_map_update(struct hnae3_handle *h) +static int hclge_map_update(struct hclge_dev *hdev) { - struct hclge_vport *vport = hclge_get_vport(h); - struct hclge_dev *hdev = vport->back; int ret; ret = hclge_tm_schd_setup_hw(hdev); @@ -232,12 +230,17 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) ret = hclge_ieee_ets_to_tm_info(hdev, ets); if (ret) - return ret; + goto err_out; if (map_changed) { + ret = hclge_map_update(hdev); + if (ret) + goto err_out; + ret = hclge_client_setup_tc(hdev); if (ret) - return ret; + goto err_out; + ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT); if (ret) return ret; @@ -248,6 +251,16 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) } return hclge_tm_dwrr_cfg(hdev); + +err_out: + if (!map_changed) + return ret; + + if (hclge_notify_client(hdev, HNAE3_INIT_CLIENT)) + return ret; + + hclge_notify_client(hdev, HNAE3_UP_CLIENT); + return ret; } static int hclge_ieee_getpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) @@ -359,12 +372,24 @@ static int hclge_setup_tc(struct hnae3_handle *h, u8 tc, u8 *prio_tc) if (ret) return -EINVAL; + ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT); + if (ret) + return ret; + + ret = hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT); + if (ret) + return ret; + hclge_tm_schd_info_update(hdev, tc); hclge_tm_prio_tc_info_update(hdev, prio_tc); ret = hclge_tm_init_hw(hdev, false); if (ret) - return ret; + goto err_out; + + ret = hclge_client_setup_tc(hdev); + if (ret) + goto err_out; hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE; @@ -373,7 +398,18 @@ static int hclge_setup_tc(struct hnae3_handle *h, u8 tc, u8 *prio_tc) else hdev->flag &= ~HCLGE_FLAG_MQPRIO_ENABLE; - return 0; + ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT); + if (ret) + return ret; + + return hclge_notify_client(hdev, HNAE3_UP_CLIENT); + +err_out: + if (hclge_notify_client(hdev, HNAE3_INIT_CLIENT)) + return ret; + + hclge_notify_client(hdev, HNAE3_UP_CLIENT); + return ret; } static const struct hnae3_dcb_ops hns3_dcb_ops = { @@ -383,7 +419,6 @@ static const struct hnae3_dcb_ops hns3_dcb_ops = { .ieee_setpfc = hclge_ieee_setpfc, .getdcbx = hclge_getdcbx, .setdcbx = hclge_setdcbx, - .map_update = hclge_map_update, .setup_tc = hclge_setup_tc, }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 64b1589e549f..ae8336c18264 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3843,8 +3843,16 @@ static int hclge_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc, struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; struct hclge_promisc_param param; + bool en_bc_pmc = true; - hclge_promisc_param_init(¶m, en_uc_pmc, en_mc_pmc, true, + /* For revision 0x20, if broadcast promisc enabled, vlan filter is + * always bypassed. So broadcast promisc should be disabled until + * user enable promisc mode + */ + if (handle->pdev->revision == 0x20) + en_bc_pmc = handle->netdev_flags & HNAE3_BPE ? true : false; + + hclge_promisc_param_init(¶m, en_uc_pmc, en_mc_pmc, en_bc_pmc, vport->vport_id); return hclge_cmd_set_promisc_mode(hdev, ¶m); } @@ -5229,8 +5237,15 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en, { #define HCLGE_SERDES_RETRY_MS 10 #define HCLGE_SERDES_RETRY_NUM 100 + +#define HCLGE_MAC_LINK_STATUS_MS 20 +#define HCLGE_MAC_LINK_STATUS_NUM 10 +#define HCLGE_MAC_LINK_STATUS_DOWN 0 +#define HCLGE_MAC_LINK_STATUS_UP 1 + struct hclge_serdes_lb_cmd *req; struct hclge_desc desc; + int mac_link_ret = 0; int ret, i = 0; u8 loop_mode_b; @@ -5253,8 +5268,10 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en, if (en) { req->enable = loop_mode_b; req->mask = loop_mode_b; + mac_link_ret = HCLGE_MAC_LINK_STATUS_UP; } else { req->mask = loop_mode_b; + mac_link_ret = HCLGE_MAC_LINK_STATUS_DOWN; } ret = hclge_cmd_send(&hdev->hw, &desc, 1); @@ -5286,7 +5303,19 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en, } hclge_cfg_mac_mode(hdev, en); - return 0; + + i = 0; + do { + /* serdes Internal loopback, independent of the network cable.*/ + msleep(HCLGE_MAC_LINK_STATUS_MS); + ret = hclge_get_mac_link_status(hdev); + if (ret == mac_link_ret) + return 0; + } while (++i < HCLGE_MAC_LINK_STATUS_NUM); + + dev_err(&hdev->pdev->dev, "config mac mode timeout\n"); + + return -EBUSY; } static int hclge_tqp_enable(struct hclge_dev *hdev, int tqp_id, @@ -5332,6 +5361,9 @@ static int hclge_set_loopback(struct hnae3_handle *handle, break; } + if (ret) + return ret; + kinfo = &vport->nic.kinfo; for (i = 0; i < kinfo->num_tqps; i++) { ret = hclge_tqp_enable(hdev, i, 0, en); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index a1de451a85df..3603034aa45c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -203,12 +203,11 @@ static int hclge_map_unmap_ring_to_vf_vector(struct hclge_vport *vport, bool en, static int hclge_set_vf_promisc_mode(struct hclge_vport *vport, struct hclge_mbx_vf_to_pf_cmd *req) { - bool en_uc = req->msg[1] ? true : false; - bool en_mc = req->msg[2] ? true : false; + bool en_bc = req->msg[1] ? true : false; struct hclge_promisc_param param; - /* always enable broadcast promisc bit */ - hclge_promisc_param_init(¶m, en_uc, en_mc, true, vport->vport_id); + /* vf is not allowed to enable unicast/multicast broadcast */ + hclge_promisc_param_init(¶m, false, false, en_bc, vport->vport_id); return hclge_cmd_set_promisc_mode(vport->back, ¶m); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 24b54083b5f9..fc99a0c70164 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -969,33 +969,29 @@ static int hclgevf_put_vector(struct hnae3_handle *handle, int vector) } static int hclgevf_cmd_set_promisc_mode(struct hclgevf_dev *hdev, - bool en_uc_pmc, bool en_mc_pmc) + bool en_bc_pmc) { struct hclge_mbx_vf_to_pf_cmd *req; struct hclgevf_desc desc; - int status; + int ret; req = (struct hclge_mbx_vf_to_pf_cmd *)desc.data; hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_MBX_VF_TO_PF, false); req->msg[0] = HCLGE_MBX_SET_PROMISC_MODE; - req->msg[1] = en_uc_pmc ? 1 : 0; - req->msg[2] = en_mc_pmc ? 1 : 0; + req->msg[1] = en_bc_pmc ? 1 : 0; - status = hclgevf_cmd_send(&hdev->hw, &desc, 1); - if (status) + ret = hclgevf_cmd_send(&hdev->hw, &desc, 1); + if (ret) dev_err(&hdev->pdev->dev, - "Set promisc mode fail, status is %d.\n", status); + "Set promisc mode fail, status is %d.\n", ret); - return status; + return ret; } -static int hclgevf_set_promisc_mode(struct hnae3_handle *handle, - bool en_uc_pmc, bool en_mc_pmc) +static int hclgevf_set_promisc_mode(struct hclgevf_dev *hdev, bool en_bc_pmc) { - struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); - - return hclgevf_cmd_set_promisc_mode(hdev, en_uc_pmc, en_mc_pmc); + return hclgevf_cmd_set_promisc_mode(hdev, en_bc_pmc); } static int hclgevf_tqp_enable(struct hclgevf_dev *hdev, int tqp_id, @@ -2382,6 +2378,15 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) if (ret) goto err_config; + /* vf is not allowed to enable unicast/multicast promisc mode. + * For revision 0x20, default to disable broadcast promisc mode, + * firmware makes sure broadcast packets can be accepted. + * For revision 0x21, default to enable broadcast promisc mode. + */ + ret = hclgevf_set_promisc_mode(hdev, true); + if (ret) + goto err_config; + /* Initialize RSS for this VF */ ret = hclgevf_rss_init_hw(hdev); if (ret) { @@ -2646,7 +2651,6 @@ static const struct hnae3_ae_ops hclgevf_ops = { .get_vector = hclgevf_get_vector, .put_vector = hclgevf_put_vector, .reset_queue = hclgevf_reset_tqp, - .set_promisc_mode = hclgevf_set_promisc_mode, .get_mac_addr = hclgevf_get_mac_addr, .set_mac_addr = hclgevf_set_mac_addr, .add_uc_addr = hclgevf_add_uc_addr, |