diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 7f22240c90559caa2e0084c28f960d17a47cd336..bccb1ddc099a1aed2d08ef6401b4b58850c72409 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -852,6 +852,10 @@ struct hnae3_dcb_ops { int (*ieee_setpfc)(struct hnae3_handle *, struct ieee_pfc *); int (*ieee_setapp)(struct hnae3_handle *h, struct dcb_app *app); int (*ieee_delapp)(struct hnae3_handle *h, struct dcb_app *app); + int (*ieee_setmaxrate)(struct hnae3_handle *h, + struct ieee_maxrate *maxrate); + int (*ieee_getmaxrate)(struct hnae3_handle *h, + struct ieee_maxrate *maxrate); /* DCBX configuration */ u8 (*getdcbx)(struct hnae3_handle *); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c b/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c index f72dc0cee30e553dba0fac192308107e858da404..19fef1d417014d7855f5903f38c777e4767d25d2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c @@ -104,6 +104,28 @@ static u8 hns3_dcbnl_setdcbx(struct net_device *ndev, u8 mode) return 1; } +static int hns3_dcbnl_ieee_setmaxrate(struct net_device *netdev, + struct ieee_maxrate *maxrate) +{ + struct hnae3_handle *h = hns3_get_handle(netdev); + + if (h->kinfo.dcb_ops->ieee_setmaxrate) + return h->kinfo.dcb_ops->ieee_setmaxrate(h, maxrate); + + return -EOPNOTSUPP; +} + +static int hns3_dcbnl_ieee_getmaxrate(struct net_device *netdev, + struct ieee_maxrate *maxrate) +{ + struct hnae3_handle *h = hns3_get_handle(netdev); + + if (h->kinfo.dcb_ops->ieee_getmaxrate) + return h->kinfo.dcb_ops->ieee_getmaxrate(h, maxrate); + + return -EOPNOTSUPP; +} + static const struct dcbnl_rtnl_ops hns3_dcbnl_ops = { .ieee_getets = hns3_dcbnl_ieee_getets, .ieee_setets = hns3_dcbnl_ieee_setets, @@ -111,6 +133,8 @@ static const struct dcbnl_rtnl_ops hns3_dcbnl_ops = { .ieee_setpfc = hns3_dcbnl_ieee_setpfc, .ieee_setapp = hns3_dcbnl_ieee_setapp, .ieee_delapp = hns3_dcbnl_ieee_delapp, + .ieee_setmaxrate = hns3_dcbnl_ieee_setmaxrate, + .ieee_getmaxrate = hns3_dcbnl_ieee_getmaxrate, .getdcbx = hns3_dcbnl_getdcbx, .setdcbx = hns3_dcbnl_setdcbx, }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index a8b6cd7d77d1fd86312bfc32645962d15dca0cf6..71a650f8e02e1ffa1b103f9b0dee487b849a578c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -383,6 +383,15 @@ static const char * const dim_state_str[] = { "START", "IN_PROG", "APPLY" }; static const char * const dim_tune_stat_str[] = { "ON_TOP", "TIRED", "RIGHT", "LEFT" }; +static bool hns3_dbg_is_device_busy(struct hns3_nic_priv *priv) +{ + if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || + test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) + return true; + + return false; +} + static void hns3_get_coal_info(struct hns3_enet_tqp_vector *tqp_vector, struct seq_file *s, int i, bool is_tx) { @@ -428,13 +437,16 @@ static void hns3_get_coal_info(struct hns3_enet_tqp_vector *tqp_vector, } } -static void hns3_dump_coal_info(struct seq_file *s, bool is_tx) +static int hns3_dump_coal_info(struct seq_file *s, bool is_tx) { struct hnae3_handle *h = hnae3_seq_file_to_handle(s); struct hns3_enet_tqp_vector *tqp_vector; struct hns3_nic_priv *priv = h->priv; unsigned int i; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + seq_printf(s, "%s interrupt coalesce info:\n", is_tx ? "tx" : "rx"); seq_puts(s, "VEC_ID ALGO_STATE PROFILE_ID CQE_MODE TUNE_STATE "); @@ -442,18 +454,26 @@ static void hns3_dump_coal_info(struct seq_file *s, bool is_tx) seq_puts(s, "HW_GL HW_QL\n"); for (i = 0; i < priv->vector_num; i++) { + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + tqp_vector = &priv->tqp_vector[i]; hns3_get_coal_info(tqp_vector, s, i, is_tx); } + + return 0; } static int hns3_dbg_coal_info(struct seq_file *s, void *data) { - hns3_dump_coal_info(s, true); - seq_puts(s, "\n"); - hns3_dump_coal_info(s, false); + int ret; - return 0; + ret = hns3_dump_coal_info(s, true); + if (ret) + return ret; + + seq_puts(s, "\n"); + return hns3_dump_coal_info(s, false); } static void hns3_dump_rx_queue_info(struct hns3_enet_ring *ring, @@ -498,6 +518,9 @@ static int hns3_dbg_rx_queue_info(struct seq_file *s, void *data) struct hns3_enet_ring *ring; u32 i; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + if (!priv->ring) { dev_err(&h->pdev->dev, "priv->ring is NULL\n"); return -EFAULT; @@ -511,8 +534,7 @@ static int hns3_dbg_rx_queue_info(struct seq_file *s, void *data) * to prevent reference to invalid memory. And need to ensure * that the following code is executed within 100ms. */ - if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || - test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) + if (hns3_dbg_is_device_busy(priv)) return -EPERM; ring = &priv->ring[(u32)(i + h->kinfo.num_tqps)]; @@ -563,6 +585,9 @@ static int hns3_dbg_tx_queue_info(struct seq_file *s, void *data) struct hns3_enet_ring *ring; u32 i; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + if (!priv->ring) { dev_err(&h->pdev->dev, "priv->ring is NULL\n"); return -EFAULT; @@ -576,8 +601,7 @@ static int hns3_dbg_tx_queue_info(struct seq_file *s, void *data) * to prevent reference to invalid memory. And need to ensure * that the following code is executed within 100ms. */ - if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || - test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) + if (hns3_dbg_is_device_busy(priv)) return -EPERM; ring = &priv->ring[i]; @@ -596,6 +620,9 @@ static int hns3_dbg_queue_map(struct seq_file *s, void *data) if (!h->ae_algo->ops->get_global_queue_id) return -EOPNOTSUPP; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + seq_puts(s, "local_queue_id global_queue_id vector_id\n"); for (i = 0; i < h->kinfo.num_tqps; i++) { @@ -643,6 +670,9 @@ static int hns3_dbg_rx_bd_info(struct seq_file *s, void *private) struct hns3_desc *desc; unsigned int i; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + if (data->qid >= h->kinfo.num_tqps) { dev_err(&h->pdev->dev, "queue%u is not in use\n", data->qid); return -EINVAL; @@ -655,8 +685,10 @@ static int hns3_dbg_rx_bd_info(struct seq_file *s, void *private) ring = &priv->ring[data->qid + data->handle->kinfo.num_tqps]; for (i = 0; i < ring->desc_num; i++) { - desc = &ring->desc[i]; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + desc = &ring->desc[i]; hns3_dump_rx_bd_info(priv, desc, s, i); } @@ -688,6 +720,9 @@ static int hns3_dbg_tx_bd_info(struct seq_file *s, void *private) struct hns3_desc *desc; unsigned int i; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + if (data->qid >= h->kinfo.num_tqps) { dev_err(&h->pdev->dev, "queue%u is not in use\n", data->qid); return -EINVAL; @@ -700,8 +735,10 @@ static int hns3_dbg_tx_bd_info(struct seq_file *s, void *private) ring = &priv->ring[data->qid]; for (i = 0; i < ring->desc_num; i++) { - desc = &ring->desc[i]; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; + desc = &ring->desc[i]; hns3_dump_tx_bd_info(desc, s, i); } @@ -804,9 +841,8 @@ static int hns3_dbg_page_pool_info(struct seq_file *s, void *data) seq_puts(s, "POOL_SIZE(PAGE_NUM) ORDER NUMA_ID MAX_LEN\n"); for (i = 0; i < h->kinfo.num_tqps; i++) { - if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || - test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) - return -EPERM; + if (hns3_dbg_is_device_busy(priv)) + return -EBUSY; ring = &priv->ring[(u32)(i + h->kinfo.num_tqps)]; hns3_dump_page_pool_info(ring, s, i); @@ -821,8 +857,7 @@ static int hns3_dbg_bd_info_show(struct seq_file *s, void *private) struct hnae3_handle *h = data->handle; struct hns3_nic_priv *priv = h->priv; - if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || - test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) + if (hns3_dbg_is_device_busy(priv)) return -EBUSY; if (data->cmd == HNAE3_DBG_CMD_TX_BD) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index c0868305049a3d9f2a80de99df980822d4ac4c5e..a62d34e4e21fa890619f854e1075c9bc99362fb0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1356,7 +1356,7 @@ static int hns3_set_tso(struct sk_buff *skb, u32 *paylen_fdop_ol4cs, /* Software should clear the IPv4's checksum field when tso is * needed. */ - if (l3.v4->version == 4) + if (l3.v4->version == IP_VERSION_IPV4) l3.v4->check = 0; /* tunnel packet */ @@ -1371,7 +1371,7 @@ static int hns3_set_tso(struct sk_buff *skb, u32 *paylen_fdop_ol4cs, /* Software should clear the IPv4's checksum field when * tso is needed. */ - if (l3.v4->version == 4) + if (l3.v4->version == IP_VERSION_IPV4) l3.v4->check = 0; } @@ -1446,13 +1446,13 @@ static int hns3_get_l4_protocol(struct sk_buff *skb, u8 *ol4_proto, l3.hdr = skb_inner_network_header(skb); l4_hdr = skb_inner_transport_header(skb); - if (l3.v6->version == 6) { + if (l3.v6->version == IP_VERSION_IPV6) { exthdr = l3.hdr + sizeof(*l3.v6); l4_proto_tmp = l3.v6->nexthdr; if (l4_hdr != exthdr) ipv6_skip_exthdr(skb, exthdr - skb->data, &l4_proto_tmp, &frag_off); - } else if (l3.v4->version == 4) { + } else if (l3.v4->version == IP_VERSION_IPV4) { l4_proto_tmp = l3.v4->protocol; } @@ -1540,7 +1540,7 @@ static void hns3_set_outer_l2l3l4(struct sk_buff *skb, u8 ol4_proto, static void hns3_set_l3_type(struct sk_buff *skb, union l3_hdr_info l3, u32 *type_cs_vlan_tso) { - if (l3.v4->version == 4) { + if (l3.v4->version == IP_VERSION_IPV4) { hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_S, HNS3_L3T_IPV4); @@ -1549,7 +1549,7 @@ static void hns3_set_l3_type(struct sk_buff *skb, union l3_hdr_info l3, */ if (skb_is_gso(skb)) hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3CS_B, 1); - } else if (l3.v6->version == 6) { + } else if (l3.v6->version == IP_VERSION_IPV6) { hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_S, HNS3_L3T_IPV6); } @@ -3652,11 +3652,12 @@ static int hns3_alloc_buffer(struct hns3_enet_ring *ring, struct hns3_desc_cb *cb) { unsigned int order = hns3_page_order(ring); + u32 page_offset; struct page *p; if (ring->page_pool) { p = page_pool_dev_alloc_frag(ring->page_pool, - &cb->page_offset, + &page_offset, hns3_buf_size(ring)); if (unlikely(!p)) return -ENOMEM; @@ -3666,6 +3667,7 @@ static int hns3_alloc_buffer(struct hns3_enet_ring *ring, cb->dma = page_pool_get_dma_addr(p); cb->type = DESC_TYPE_PP_FRAG; cb->reuse_flag = 0; + cb->page_offset = page_offset; return 0; } @@ -3842,10 +3844,10 @@ static int hns3_alloc_ring_buffers(struct hns3_enet_ring *ring) static void hns3_replace_buffer(struct hns3_enet_ring *ring, int i, struct hns3_desc_cb *res_cb) { - if (!ring->page_pool) + if (!ring->page_pool) { hns3_unmap_buffer(ring, &ring->desc_cb[i]); - - ring->desc_cb[i] = *res_cb; + ring->desc_cb[i] = *res_cb; + } ring->desc_cb[i].refill = 1; ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma + ring->desc_cb[i].page_offset); @@ -3982,7 +3984,9 @@ static bool hns3_nic_alloc_rx_buffers(struct hns3_enet_ring *ring, hns3_reuse_buffer(ring, ring->next_to_use); } else { - ret = hns3_alloc_and_map_buffer(ring, &res_cbs); + if (!ring->page_pool) + desc_cb = &res_cbs; + ret = hns3_alloc_and_map_buffer(ring, desc_cb); if (ret) { hns3_ring_stats_update(ring, sw_err_cnt); @@ -3994,7 +3998,7 @@ static bool hns3_nic_alloc_rx_buffers(struct hns3_enet_ring *ring, HNS3_RING_RX_RING_HEAD_REG); return true; } - hns3_replace_buffer(ring, ring->next_to_use, &res_cbs); + hns3_replace_buffer(ring, ring->next_to_use, desc_cb); hns3_ring_stats_update(ring, non_reuse_pg); } @@ -5848,6 +5852,7 @@ static void hns3_clear_tx_ring(struct hns3_enet_ring *ring) static int hns3_clear_rx_ring(struct hns3_enet_ring *ring) { + struct hns3_desc_cb *desc_cb; struct hns3_desc_cb res_cbs; int ret; @@ -5856,8 +5861,11 @@ static int hns3_clear_rx_ring(struct hns3_enet_ring *ring) * freed in hns3_handle_rx_bd or will be freed by * stack, so we need to replace the buffer here. */ + desc_cb = &ring->desc_cb[ring->next_to_use]; if (!ring->desc_cb[ring->next_to_use].reuse_flag) { - ret = hns3_alloc_and_map_buffer(ring, &res_cbs); + if (!ring->page_pool) + desc_cb = &res_cbs; + ret = hns3_alloc_and_map_buffer(ring, desc_cb); if (ret) { hns3_ring_stats_update(ring, sw_err_cnt); /* if alloc new buffer fail, exit directly @@ -5868,7 +5876,7 @@ static int hns3_clear_rx_ring(struct hns3_enet_ring *ring) ret); return ret; } - hns3_replace_buffer(ring, ring->next_to_use, &res_cbs); + hns3_replace_buffer(ring, ring->next_to_use, desc_cb); } ring_ptr_move_fw(ring, next_to_use); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index cea9259f192f18d17c700685440e5bae5f8e1532..bb796114c2648c7d191cf1733a195297394cd783 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -898,12 +898,11 @@ static int hns3_get_link_ksettings(struct net_device *netdev, } static int hns3_check_ksettings_param(const struct net_device *netdev, - const struct ethtool_link_ksettings *cmd) + const struct ethtool_link_ksettings *cmd, + u8 media_type) { struct hnae3_handle *handle = hns3_get_handle(netdev); const struct hnae3_ae_ops *ops = hns3_get_ops(handle); - u8 module_type = HNAE3_MODULE_TYPE_UNKNOWN; - u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN; u32 lane_num; u8 autoneg; u32 speed; @@ -923,9 +922,6 @@ static int hns3_check_ksettings_param(const struct net_device *netdev, return 0; } - if (ops->get_media_type) - ops->get_media_type(handle, &media_type, &module_type); - if (cmd->base.duplex == DUPLEX_HALF && media_type != HNAE3_MEDIA_TYPE_COPPER) { netdev_err(netdev, @@ -950,6 +946,8 @@ static int hns3_set_link_ksettings(struct net_device *netdev, struct hnae3_handle *handle = hns3_get_handle(netdev); struct hnae3_ae_dev *ae_dev = hns3_get_ae_dev(handle); const struct hnae3_ae_ops *ops = hns3_get_ops(handle); + u8 module_type = HNAE3_MODULE_TYPE_UNKNOWN; + u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN; int ret; /* Chip don't support this mode. */ @@ -965,22 +963,20 @@ static int hns3_set_link_ksettings(struct net_device *netdev, cmd->base.autoneg, cmd->base.speed, cmd->base.duplex, cmd->lanes); - /* Only support ksettings_set for netdev with phy attached for now */ - if (netdev->phydev) { - if (cmd->base.speed == SPEED_1000 && - cmd->base.autoneg == AUTONEG_DISABLE) - return -EINVAL; + if (!ops->get_media_type) + return -EOPNOTSUPP; + ops->get_media_type(handle, &media_type, &module_type); - return phy_ethtool_ksettings_set(netdev->phydev, cmd); - } else if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) && - ops->set_phy_link_ksettings) { + if (media_type == HNAE3_MEDIA_TYPE_COPPER) { + if (!ops->set_phy_link_ksettings) + return -EOPNOTSUPP; return ops->set_phy_link_ksettings(handle, cmd); } if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2) return -EOPNOTSUPP; - ret = hns3_check_ksettings_param(netdev, cmd); + ret = hns3_check_ksettings_param(netdev, cmd, media_type); if (ret) return ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index 416bcac3bf70e2f0b28178565c7104b78ddd31be..140db47c2055f2de4fd440a5f4972c78223a1f6d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -509,6 +509,62 @@ static u8 hclge_setdcbx(struct hnae3_handle *h, u8 mode) return 0; } +static int hclge_ieee_getmaxrate(struct hnae3_handle *h, + struct ieee_maxrate *maxrate) +{ + struct hnae3_tc_info *tc_info = &h->kinfo.tc_info; + + memcpy(maxrate, tc_info->max_rate, sizeof(struct ieee_maxrate)); + return 0; +} + +static int hclge_check_maxrate(struct hclge_dev *hdev, + struct ieee_maxrate *maxrate) +{ + u64 max_speed = (u64)hdev->hw.mac.max_speed * TM_RATE_PORT_RATE_SCALE; + u8 i; + + for (i = 0; i < HNAE3_MAX_TC; i++) { + /* no limit */ + if (!maxrate->tc_maxrate[i]) + continue; + if (maxrate->tc_maxrate[i] < TM_RATE_PORT_RATE_SCALE || + maxrate->tc_maxrate[i] > max_speed) { + dev_err(&hdev->pdev->dev, + "invalid max_rate[%llubps]: the range is [1Mbps, %uMbps]\n", + maxrate->tc_maxrate[i] * HCLGE_BYTE_BITS, + hdev->hw.mac.max_speed); + return -EINVAL; + } + } + return 0; +} + +static int hclge_ieee_setmaxrate(struct hnae3_handle *h, + struct ieee_maxrate *maxrate) +{ + struct hnae3_tc_info *tc_info = &h->kinfo.tc_info; + struct hclge_vport *vport = hclge_get_vport(h); + struct hclge_dev *hdev = vport->back; + struct hnae3_tc_info old_tc_info; + int ret; + + if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || tc_info->mqprio_active) + return -EINVAL; + + ret = hclge_check_maxrate(hdev, maxrate); + if (ret) + return ret; + + old_tc_info = *tc_info; + memcpy(tc_info->max_rate, maxrate, sizeof(struct ieee_maxrate)); + ret = hclge_tm_set_tc_rate_limit(hdev, tc_info); + if (ret) + *tc_info = old_tc_info; + + return ret; +} + static int hclge_mqprio_qopt_check_rate(struct hclge_dev *hdev, u64 min_rate, u64 max_rate) { @@ -702,6 +758,8 @@ static const struct hnae3_dcb_ops hns3_dcb_ops = { .getdcbx = hclge_getdcbx, .setdcbx = hclge_setdcbx, .setup_tc = hclge_setup_tc, + .ieee_setmaxrate = hclge_ieee_setmaxrate, + .ieee_getmaxrate = hclge_ieee_getmaxrate, }; void hclge_dcb_ops_set(struct hclge_dev *hdev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h index b04702e656890e124ed54f77ee531f3d8880e0a1..23e35c643c15d47d03c4dac768acea40c166b242 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h @@ -12,4 +12,7 @@ void hclge_dcb_ops_set(struct hclge_dev *hdev); static inline void hclge_dcb_ops_set(struct hclge_dev *hdev) {} #endif +#define HCLGE_BYTE_BITS 8ULL +#define HCLGE_RATE_UNIT_MBPS 1000000ULL /* 1Mbps */ + #endif /* __HCLGE_DCB_H__ */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 008c8a5b6158b4789352e3c5d50e0a16ed8c2ea2..ae82bd55752a0cf6f3127eb48a06ced46688f3bb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -2542,6 +2542,9 @@ static int hclge_dbg_dump_umv_info(struct seq_file *s, void *data) struct hclge_vport *vport; u8 i; + if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) + return -EBUSY; + seq_printf(s, "num_alloc_vport : %u\n", hdev->num_alloc_vport); seq_printf(s, "max_umv_size : %u\n", hdev->max_umv_size); seq_printf(s, "wanted_umv_size : %u\n", hdev->wanted_umv_size); @@ -2752,6 +2755,9 @@ static int hclge_dbg_dump_vlan_offload_config(struct hclge_dev *hdev, int ret; u8 i; + if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) + return -EBUSY; + seq_puts(s, "FUNC_ID PVID ACCEPT_TAG1 ACCEPT_TAG2 ACCEPT_UNTAG1 "); seq_puts(s, "ACCEPT_UNTAG2 INSERT_TAG1 INSERT_TAG2 SHIFT_TAG "); seq_puts(s, "STRIP_TAG1 STRIP_TAG2 DROP_TAG1 DROP_TAG2 "); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 971340509b0d696cf40c3298559cb2f95d8391bf..1525f3c948cb7d3fa160ba8f79d5df22a2143a30 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1607,8 +1607,11 @@ static int hclge_configure(struct hclge_dev *hdev) return ret; } hdev->hw.mac.req_speed = hdev->hw.mac.speed; - hdev->hw.mac.req_autoneg = AUTONEG_ENABLE; hdev->hw.mac.req_duplex = DUPLEX_FULL; + if (hdev->hw.mac.media_type == HNAE3_MEDIA_TYPE_COPPER) + hdev->hw.mac.req_autoneg = AUTONEG_ENABLE; + else + hdev->hw.mac.req_autoneg = AUTONEG_DISABLE; hclge_parse_link_mode(hdev, cfg.speed_ability); @@ -2709,7 +2712,7 @@ static int hclge_cfg_mac_speed_dup_h(struct hnae3_handle *handle, int speed, hdev->hw.mac.req_speed = (u32)speed; hdev->hw.mac.req_duplex = duplex; - + hdev->hw.mac.req_lane_num = lane_num; return 0; } @@ -2739,6 +2742,7 @@ static int hclge_set_autoneg(struct hnae3_handle *handle, bool enable) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; + int ret; if (!hdev->hw.mac.support_autoneg) { if (enable) { @@ -2750,7 +2754,10 @@ static int hclge_set_autoneg(struct hnae3_handle *handle, bool enable) } } - return hclge_set_autoneg_en(hdev, enable); + ret = hclge_set_autoneg_en(hdev, enable); + if (!ret) + hdev->hw.mac.req_autoneg = enable; + return ret; } static int hclge_get_autoneg(struct hnae3_handle *handle) @@ -3027,21 +3034,6 @@ static int hclge_mac_init(struct hclge_dev *hdev) if (!test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) hdev->hw.mac.duplex = HCLGE_MAC_FULL; - - if (hdev->hw.mac.support_autoneg) { - ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.autoneg); - if (ret) - return ret; - } - - if (!hdev->hw.mac.autoneg) { - ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.req_speed, - hdev->hw.mac.req_duplex, - hdev->hw.mac.lane_num); - if (ret) - return ret; - } - mac->link = 0; if (mac->user_fec_mode & BIT(HNAE3_FEC_USER_DEF)) { @@ -3428,8 +3420,8 @@ static int hclge_get_phy_link_ksettings(struct hnae3_handle *handle, } static int -hclge_set_phy_link_ksettings(struct hnae3_handle *handle, - const struct ethtool_link_ksettings *cmd) +hclge_ethtool_ksettings_set(struct hnae3_handle *handle, + const struct ethtool_link_ksettings *cmd) { struct hclge_desc desc[HCLGE_PHY_LINK_SETTING_BD_NUM]; struct hclge_vport *vport = hclge_get_vport(handle); @@ -3439,12 +3431,6 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle, u32 advertising; int ret; - if (cmd->base.autoneg == AUTONEG_DISABLE && - ((cmd->base.speed != SPEED_100 && cmd->base.speed != SPEED_10) || - (cmd->base.duplex != DUPLEX_HALF && - cmd->base.duplex != DUPLEX_FULL))) - return -EINVAL; - hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_PHY_LINK_KSETTING, false); desc[0].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT); @@ -3464,6 +3450,32 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle, req1->master_slave_cfg = cmd->base.master_slave_cfg; ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_PHY_LINK_SETTING_BD_NUM); + + if (!ret) + linkmode_copy(hdev->hw.mac.advertising, cmd->link_modes.advertising); + + return ret; +} + +static int +hclge_set_phy_link_ksettings(struct hnae3_handle *handle, + const struct ethtool_link_ksettings *cmd) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + int ret; + + if (cmd->base.autoneg == AUTONEG_DISABLE && + ((cmd->base.speed != SPEED_100 && cmd->base.speed != SPEED_10) || + (cmd->base.duplex != DUPLEX_HALF && + cmd->base.duplex != DUPLEX_FULL))) + return -EINVAL; + + if (hnae3_dev_phy_imp_supported(hdev)) + ret = hclge_ethtool_ksettings_set(handle, cmd); + else + ret = phy_ethtool_ksettings_set(handle->netdev->phydev, cmd); + if (ret) { dev_err(&hdev->pdev->dev, "failed to set phy link ksettings, ret = %d.\n", ret); @@ -3471,9 +3483,10 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle, } hdev->hw.mac.req_autoneg = cmd->base.autoneg; - hdev->hw.mac.req_speed = cmd->base.speed; - hdev->hw.mac.req_duplex = cmd->base.duplex; - linkmode_copy(hdev->hw.mac.advertising, cmd->link_modes.advertising); + if (cmd->base.speed != SPEED_UNKNOWN) + hdev->hw.mac.req_speed = cmd->base.speed; + if (cmd->base.duplex != DUPLEX_UNKNOWN) + hdev->hw.mac.req_duplex = cmd->base.duplex; return 0; } @@ -10136,8 +10149,7 @@ static int hclge_mii_ioctl(struct hclge_dev *hdev, struct ifreq *ifr, int cmd) /* this command reads phy id and register at the same time */ fallthrough; case SIOCGMIIREG: - data->val_out = hclge_read_phy_reg(hdev, data->reg_num); - return 0; + return hclge_read_phy_reg(hdev, data->reg_num, &data->val_out); case SIOCSMIIREG: return hclge_write_phy_reg(hdev, data->reg_num, data->val_in); @@ -12506,6 +12518,28 @@ static int hclge_set_wol(struct hnae3_handle *handle, return ret; } +static int hclge_set_autoneg_speed_dup(struct hclge_dev *hdev) +{ + int ret; + + if (hdev->hw.mac.support_autoneg) { + ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.req_autoneg); + if (ret) + return ret; + } + + if (!hdev->hw.mac.req_autoneg) { + ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.req_speed, + hdev->hw.mac.req_duplex, + hdev->hw.mac.req_lane_num); + if (ret) + return ret; + } + + return 0; +} + + static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) { struct pci_dev *pdev = ae_dev->pdev; @@ -12667,6 +12701,23 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) if (ret) goto err_ptp_uninit; + if (hdev->hw.mac.media_type == HNAE3_MEDIA_TYPE_COPPER) + hdev->hw.mac.req_autoneg = AUTONEG_ENABLE; + else + hdev->hw.mac.req_autoneg = hdev->hw.mac.autoneg; + + /* When lane_num is 0, the firmware will automatically + * select the appropriate lane_num based on the speed. + */ + hdev->hw.mac.req_lane_num = 0; + + ret = hclge_set_autoneg_speed_dup(hdev); + if (ret) { + dev_err(&pdev->dev, + "failed to set autoneg speed duplex, ret = %d\n", ret); + goto err_ptp_uninit; + } + INIT_KFIFO(hdev->mac_tnl_log); hclge_dcb_ops_set(hdev); @@ -12999,6 +13050,13 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev) return ret; } + ret = hclge_set_autoneg_speed_dup(hdev); + if (ret) { + dev_err(&pdev->dev, + "failed to set autoneg speed duplex, ret = %d\n", ret); + return ret; + } + ret = hclge_tp_port_init(hdev); if (ret) { dev_err(&pdev->dev, "failed to init tp port, ret = %d\n", diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 4f723d7c037d38fdfc4f93665a403b34a2302a4a..a4171f59105c8776f27035fe56214daa5f539cb0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -286,9 +286,10 @@ struct hclge_mac { u8 req_autoneg; u8 duplex; u8 req_duplex; - u8 support_autoneg; + u8 support_autoneg; /* for non-copper port */ u8 speed_type; /* 0: sfp speed, 1: active speed */ u8 lane_num; + u8 req_lane_num; u32 speed; u32 req_speed; u32 max_speed; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 7b3709f480b3ad7ab40ae76e504d4d09b09c29cf..fdba02a469684bfab984f014bf72b535a26ce5fe 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -193,10 +193,10 @@ static int hclge_get_ring_chain_from_mbx( return -EINVAL; for (i = 0; i < ring_num; i++) { - if (req->msg.param[i].tqp_index >= vport->nic.kinfo.rss_size) { + if (req->msg.param[i].tqp_index >= vport->nic.kinfo.num_tqps) { dev_err(&hdev->pdev->dev, "tqp index(%u) is out of range(0-%u)\n", req->msg.param[i].tqp_index, - vport->nic.kinfo.rss_size - 1U); + vport->nic.kinfo.num_tqps - 1U); return -EINVAL; } } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c index e8b263a1f66f0afd03d2a9f0dd7005d55a7f8aca..17aa7fcd0706231b824cf53f1af0e0919b7c3634 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c @@ -274,7 +274,7 @@ void hclge_mac_stop_phy(struct hclge_dev *hdev) phy_stop(phydev); } -u16 hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr) +int hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 *val) { struct hclge_phy_reg_cmd *req; struct hclge_desc desc; @@ -286,11 +286,14 @@ u16 hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr) req->reg_addr = cpu_to_le16(reg_addr); ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) + if (ret) { dev_err(&hdev->pdev->dev, "failed to read phy reg, ret = %d.\n", ret); + return ret; + } - return le16_to_cpu(req->reg_val); + *val = le16_to_cpu(req->reg_val); + return 0; } int hclge_write_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 val) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h index 4200d0b6d9317bac879d7eed9a5636f1557d57ab..21d434c82475b317d8406172191ceb5553f45877 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h @@ -13,7 +13,7 @@ int hclge_mac_connect_phy(struct hnae3_handle *handle); void hclge_mac_disconnect_phy(struct hnae3_handle *handle); void hclge_mac_start_phy(struct hclge_dev *hdev); void hclge_mac_stop_phy(struct hclge_dev *hdev); -u16 hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr); +int hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 *val); int hclge_write_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 val); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index a8350940fd5efeb32ae961eac200421da36bf93b..da3d135a6e25b3812e3b28842ed143f0a222876a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -1734,7 +1734,7 @@ int hclge_tm_init_hw(struct hclge_dev *hdev, bool init) if (ret) return ret; - if (hnae3_dev_roh_supported(hdev)) + if (hdev->ae_dev->dev_version > HNAE3_DEVICE_VERSION_V2) return hclge_tm_set_tc_rate_limit(hdev, tc_info); return 0; @@ -2033,12 +2033,17 @@ int hclge_tm_get_q_to_tc(struct hclge_dev *hdev, u16 q_id, u8 *tc_id) #define HCLGE_TM_TC_MASK 0x7 struct hclge_tqp_tx_queue_tc_cmd *tc; + struct hclge_vport *vport; struct hclge_desc desc; int ret; + vport = container_of(hdev->htqp[q_id].q.handle, + struct hclge_vport, nic); tc = (struct hclge_tqp_tx_queue_tc_cmd *)desc.data; hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TQP_TX_QUEUE_TC, true); - tc->queue_id = cpu_to_le16(q_id); + tc->queue_id = cpu_to_le16(hdev->htqp[q_id].q.tqp_index); + tc->func_id = (u8)vport->vport_id; + ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { dev_err(&hdev->pdev->dev, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index 64b448370f9338ce2683f783fb1ed1b0500ded58..b3c81050394e04d291a7a93b063ab018794116c7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -65,9 +65,10 @@ struct hclge_nq_to_qs_link_cmd { struct hclge_tqp_tx_queue_tc_cmd { __le16 queue_id; - __le16 rsvd; + u8 func_id; + u8 rsvd1; u8 tc_id; - u8 rev[3]; + u8 rsvd2[3]; }; struct hclge_pg_weight_cmd { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 3f137cb15847a6b81fc58eb314aa834169efdc3b..7ccf6625b27e0b6625daa34180d28b9a30cc6e5a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -370,12 +370,12 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev) new_tqps = kinfo->rss_size * num_tc; kinfo->num_tqps = min(new_tqps, hdev->num_tqps); - kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps, + kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps, sizeof(struct hnae3_queue *), GFP_KERNEL); if (!kinfo->tqp) return -ENOMEM; - for (i = 0; i < kinfo->num_tqps; i++) { + for (i = 0; i < hdev->num_tqps; i++) { hdev->htqp[i].q.handle = &hdev->nic; hdev->htqp[i].q.tqp_index = i; kinfo->tqp[i] = &hdev->htqp[i].q; @@ -2256,12 +2256,21 @@ static int hclgevf_config_gro(struct hclgevf_dev *hdev) return ret; } +static int hclgevf_init_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size) +{ + u16 tc_offset[HNAE3_MAX_TC] = {0}; + u16 tc_valid[HNAE3_MAX_TC] = {0}; + u16 tc_size[HNAE3_MAX_TC] = {0}; + + hclge_comm_get_rss_tc_info(rss_size, hdev->hw_tc_map, + tc_offset, tc_valid, tc_size); + return hclge_comm_set_rss_tc_mode(&hdev->hw.hw, tc_offset, tc_valid, + tc_size); +} + static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev) { struct hclge_comm_rss_cfg *rss_cfg = &hdev->rss_cfg; - u16 tc_offset[HCLGE_COMM_MAX_TC_NUM]; - u16 tc_valid[HCLGE_COMM_MAX_TC_NUM]; - u16 tc_size[HCLGE_COMM_MAX_TC_NUM]; int ret; if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { @@ -2281,11 +2290,7 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev) if (ret) return ret; - hclge_comm_get_rss_tc_info(rss_cfg->rss_size, hdev->hw_tc_map, - tc_offset, tc_valid, tc_size); - - return hclge_comm_set_rss_tc_mode(&hdev->hw.hw, tc_offset, - tc_valid, tc_size); + return hclgevf_init_rss_tc_mode(hdev, rss_cfg->rss_size); } static int hclgevf_init_vlan_config(struct hclgevf_dev *hdev, @@ -3171,11 +3176,7 @@ static void hclgevf_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) static u32 hclgevf_get_max_channels(struct hclgevf_dev *hdev) { - struct hnae3_handle *nic = &hdev->nic; - struct hnae3_knic_private_info *kinfo = &nic->kinfo; - - return min_t(u32, hdev->rss_size_max, - hdev->num_tqps / kinfo->tc_info.num_tc); + return min_t(u32, hdev->rss_size_max, hdev->num_tqps); } /** @@ -3238,9 +3239,6 @@ static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, { struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); struct hnae3_knic_private_info *kinfo = &handle->kinfo; - u16 tc_offset[HCLGE_COMM_MAX_TC_NUM]; - u16 tc_valid[HCLGE_COMM_MAX_TC_NUM]; - u16 tc_size[HCLGE_COMM_MAX_TC_NUM]; u16 cur_rss_size = kinfo->rss_size; u16 cur_tqps = kinfo->num_tqps; u32 *rss_indir; @@ -3249,10 +3247,7 @@ static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, hclgevf_update_rss_size(handle, new_tqps_num); - hclge_comm_get_rss_tc_info(kinfo->rss_size, hdev->hw_tc_map, - tc_offset, tc_valid, tc_size); - ret = hclge_comm_set_rss_tc_mode(&hdev->hw.hw, tc_offset, - tc_valid, tc_size); + ret = hclgevf_init_rss_tc_mode(hdev, kinfo->rss_size); if (ret) return ret;