Merge branch 'hns3-next'
Huazhong Tan says: ==================== net: hns3: add a feature & bugfixes & cleanups This patch-set includes a VF feature, bugfixes and cleanups for the HNS3 ethernet controller driver. [patch 01/07] adds ethtool_ops.set_channels support for HNS3 VF driver [patch 02/07] adds a recovery for setting channel fail. [patch 03/07] fixes an error related to shaper parameter algorithm. [patch 04/07] fixes an error related to ksetting. [patch 05/07] adds cleanups for some log pinting. [patch 06/07] adds a NULL pointer check before function calling. [patch 07/07] adds some debugging information for reset issue. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
e7f13f44c7
@ -166,6 +166,7 @@ static int hns3_dbg_bd_info(struct hnae3_handle *h, const char *cmd_buf)
|
||||
struct hns3_enet_ring *ring;
|
||||
u32 tx_index, rx_index;
|
||||
u32 q_num, value;
|
||||
dma_addr_t addr;
|
||||
int cnt;
|
||||
|
||||
cnt = sscanf(&cmd_buf[8], "%u %u", &q_num, &tx_index);
|
||||
@ -194,8 +195,9 @@ static int hns3_dbg_bd_info(struct hnae3_handle *h, const char *cmd_buf)
|
||||
}
|
||||
|
||||
tx_desc = &ring->desc[tx_index];
|
||||
addr = le64_to_cpu(tx_desc->addr);
|
||||
dev_info(dev, "TX Queue Num: %u, BD Index: %u\n", q_num, tx_index);
|
||||
dev_info(dev, "(TX)addr: 0x%llx\n", tx_desc->addr);
|
||||
dev_info(dev, "(TX)addr: %pad\n", &addr);
|
||||
dev_info(dev, "(TX)vlan_tag: %u\n", tx_desc->tx.vlan_tag);
|
||||
dev_info(dev, "(TX)send_size: %u\n", tx_desc->tx.send_size);
|
||||
dev_info(dev, "(TX)vlan_tso: %u\n", tx_desc->tx.type_cs_vlan_tso);
|
||||
@ -217,8 +219,9 @@ static int hns3_dbg_bd_info(struct hnae3_handle *h, const char *cmd_buf)
|
||||
rx_index = (cnt == 1) ? value : tx_index;
|
||||
rx_desc = &ring->desc[rx_index];
|
||||
|
||||
addr = le64_to_cpu(rx_desc->addr);
|
||||
dev_info(dev, "RX Queue Num: %u, BD Index: %u\n", q_num, rx_index);
|
||||
dev_info(dev, "(RX)addr: 0x%llx\n", rx_desc->addr);
|
||||
dev_info(dev, "(RX)addr: %pad\n", &addr);
|
||||
dev_info(dev, "(RX)l234_info: %u\n", rx_desc->rx.l234_info);
|
||||
dev_info(dev, "(RX)pkt_len: %u\n", rx_desc->rx.pkt_len);
|
||||
dev_info(dev, "(RX)size: %u\n", rx_desc->rx.size);
|
||||
|
@ -2006,7 +2006,8 @@ static pci_ers_result_t hns3_slot_reset(struct pci_dev *pdev)
|
||||
|
||||
ops = ae_dev->ops;
|
||||
/* request the reset */
|
||||
if (ops->reset_event && ops->get_reset_level) {
|
||||
if (ops->reset_event && ops->get_reset_level &&
|
||||
ops->set_default_reset_request) {
|
||||
if (ae_dev->hw_err_reset_req) {
|
||||
reset_type = ops->get_reset_level(ae_dev,
|
||||
&ae_dev->hw_err_reset_req);
|
||||
@ -4410,6 +4411,30 @@ static int hns3_reset_notify(struct hnae3_handle *handle,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns3_change_channels(struct hnae3_handle *handle, u32 new_tqp_num,
|
||||
bool rxfh_configured)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = handle->ae_algo->ops->set_channels(handle, new_tqp_num,
|
||||
rxfh_configured);
|
||||
if (ret) {
|
||||
dev_err(&handle->pdev->dev,
|
||||
"Change tqp num(%u) fail.\n", new_tqp_num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hns3_reset_notify(handle, HNAE3_INIT_CLIENT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = hns3_reset_notify(handle, HNAE3_UP_CLIENT);
|
||||
if (ret)
|
||||
hns3_reset_notify(handle, HNAE3_UNINIT_CLIENT);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hns3_set_channels(struct net_device *netdev,
|
||||
struct ethtool_channels *ch)
|
||||
{
|
||||
@ -4450,24 +4475,23 @@ int hns3_set_channels(struct net_device *netdev,
|
||||
return ret;
|
||||
|
||||
org_tqp_num = h->kinfo.num_tqps;
|
||||
ret = h->ae_algo->ops->set_channels(h, new_tqp_num, rxfh_configured);
|
||||
ret = hns3_change_channels(h, new_tqp_num, rxfh_configured);
|
||||
if (ret) {
|
||||
ret = h->ae_algo->ops->set_channels(h, org_tqp_num,
|
||||
rxfh_configured);
|
||||
if (ret) {
|
||||
/* If revert to old tqp failed, fatal error occurred */
|
||||
dev_err(&netdev->dev,
|
||||
"Revert to old tqp num fail, ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
dev_info(&netdev->dev,
|
||||
"Change tqp num fail, Revert to old tqp num");
|
||||
}
|
||||
ret = hns3_reset_notify(h, HNAE3_INIT_CLIENT);
|
||||
if (ret)
|
||||
return ret;
|
||||
int ret1;
|
||||
|
||||
return hns3_reset_notify(h, HNAE3_UP_CLIENT);
|
||||
netdev_warn(netdev,
|
||||
"Change channels fail, revert to old value\n");
|
||||
ret1 = hns3_change_channels(h, org_tqp_num, rxfh_configured);
|
||||
if (ret1) {
|
||||
netdev_err(netdev,
|
||||
"revert to old channel fail\n");
|
||||
return ret1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hns3_hw_error_info hns3_hw_err[] = {
|
||||
|
@ -726,6 +726,12 @@ static int hns3_check_ksettings_param(const struct net_device *netdev,
|
||||
u8 duplex;
|
||||
int ret;
|
||||
|
||||
/* hw doesn't support use specified speed and duplex to negotiate,
|
||||
* unnecessary to check them when autoneg on.
|
||||
*/
|
||||
if (cmd->base.autoneg)
|
||||
return 0;
|
||||
|
||||
if (ops->get_ksettings_an_result) {
|
||||
ops->get_ksettings_an_result(handle, &autoneg, &speed, &duplex);
|
||||
if (cmd->base.autoneg == autoneg && cmd->base.speed == speed &&
|
||||
@ -787,6 +793,15 @@ static int hns3_set_link_ksettings(struct net_device *netdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* hw doesn't support use specified speed and duplex to negotiate,
|
||||
* ignore them when autoneg on.
|
||||
*/
|
||||
if (cmd->base.autoneg) {
|
||||
netdev_info(netdev,
|
||||
"autoneg is on, ignore the speed and duplex\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ops->cfg_mac_speed_dup_h)
|
||||
ret = ops->cfg_mac_speed_dup_h(handle, cmd->base.speed,
|
||||
cmd->base.duplex);
|
||||
@ -1397,6 +1412,7 @@ static const struct ethtool_ops hns3vf_ethtool_ops = {
|
||||
.set_rxfh = hns3_set_rss,
|
||||
.get_link_ksettings = hns3_get_link_ksettings,
|
||||
.get_channels = hns3_get_channels,
|
||||
.set_channels = hns3_set_channels,
|
||||
.get_coalesce = hns3_get_coalesce,
|
||||
.set_coalesce = hns3_set_coalesce,
|
||||
.get_regs_len = hns3_get_regs_len,
|
||||
|
@ -342,7 +342,7 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
|
||||
hdev->tm_info.pfc_en = pfc->pfc_en;
|
||||
|
||||
netif_dbg(h, drv, netdev,
|
||||
"set pfc: pfc_en=%u, pfc_map=%u, num_tc=%u\n",
|
||||
"set pfc: pfc_en=%x, pfc_map=%x, num_tc=%u\n",
|
||||
pfc->pfc_en, pfc_map, hdev->tm_info.num_tc);
|
||||
|
||||
hclge_tm_pfc_info_update(hdev);
|
||||
|
@ -931,22 +931,36 @@ static void hclge_dbg_fd_tcam(struct hclge_dev *hdev)
|
||||
|
||||
static void hclge_dbg_dump_rst_info(struct hclge_dev *hdev)
|
||||
{
|
||||
dev_info(&hdev->pdev->dev, "PF reset count: %d\n",
|
||||
dev_info(&hdev->pdev->dev, "PF reset count: %u\n",
|
||||
hdev->rst_stats.pf_rst_cnt);
|
||||
dev_info(&hdev->pdev->dev, "FLR reset count: %d\n",
|
||||
dev_info(&hdev->pdev->dev, "FLR reset count: %u\n",
|
||||
hdev->rst_stats.flr_rst_cnt);
|
||||
dev_info(&hdev->pdev->dev, "CORE reset count: %d\n",
|
||||
hdev->rst_stats.core_rst_cnt);
|
||||
dev_info(&hdev->pdev->dev, "GLOBAL reset count: %d\n",
|
||||
dev_info(&hdev->pdev->dev, "GLOBAL reset count: %u\n",
|
||||
hdev->rst_stats.global_rst_cnt);
|
||||
dev_info(&hdev->pdev->dev, "IMP reset count: %d\n",
|
||||
dev_info(&hdev->pdev->dev, "IMP reset count: %u\n",
|
||||
hdev->rst_stats.imp_rst_cnt);
|
||||
dev_info(&hdev->pdev->dev, "reset done count: %d\n",
|
||||
dev_info(&hdev->pdev->dev, "reset done count: %u\n",
|
||||
hdev->rst_stats.reset_done_cnt);
|
||||
dev_info(&hdev->pdev->dev, "HW reset done count: %d\n",
|
||||
dev_info(&hdev->pdev->dev, "HW reset done count: %u\n",
|
||||
hdev->rst_stats.hw_reset_done_cnt);
|
||||
dev_info(&hdev->pdev->dev, "reset count: %d\n",
|
||||
dev_info(&hdev->pdev->dev, "reset count: %u\n",
|
||||
hdev->rst_stats.reset_cnt);
|
||||
dev_info(&hdev->pdev->dev, "reset count: %u\n",
|
||||
hdev->rst_stats.reset_cnt);
|
||||
dev_info(&hdev->pdev->dev, "reset fail count: %u\n",
|
||||
hdev->rst_stats.reset_fail_cnt);
|
||||
dev_info(&hdev->pdev->dev, "vector0 interrupt enable status: 0x%x\n",
|
||||
hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_REG_BASE));
|
||||
dev_info(&hdev->pdev->dev, "reset interrupt source: 0x%x\n",
|
||||
hclge_read_dev(&hdev->hw, HCLGE_MISC_RESET_STS_REG));
|
||||
dev_info(&hdev->pdev->dev, "reset interrupt status: 0x%x\n",
|
||||
hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_INT_STS));
|
||||
dev_info(&hdev->pdev->dev, "hardware reset status: 0x%x\n",
|
||||
hclge_read_dev(&hdev->hw, HCLGE_GLOBAL_RESET_REG));
|
||||
dev_info(&hdev->pdev->dev, "handshake status: 0x%x\n",
|
||||
hclge_read_dev(&hdev->hw, HCLGE_NIC_CSQ_DEPTH_REG));
|
||||
dev_info(&hdev->pdev->dev, "function reset status: 0x%x\n",
|
||||
hclge_read_dev(&hdev->hw, HCLGE_FUN_RST_ING));
|
||||
}
|
||||
|
||||
static void hclge_dbg_get_m7_stats_info(struct hclge_dev *hdev)
|
||||
|
@ -3547,12 +3547,12 @@ static bool hclge_reset_err_handle(struct hclge_dev *hdev)
|
||||
"reset failed because new reset interrupt\n");
|
||||
hclge_clear_reset_cause(hdev);
|
||||
return false;
|
||||
} else if (hdev->reset_fail_cnt < MAX_RESET_FAIL_CNT) {
|
||||
hdev->reset_fail_cnt++;
|
||||
} else if (hdev->rst_stats.reset_fail_cnt < MAX_RESET_FAIL_CNT) {
|
||||
hdev->rst_stats.reset_fail_cnt++;
|
||||
set_bit(hdev->reset_type, &hdev->reset_pending);
|
||||
dev_info(&hdev->pdev->dev,
|
||||
"re-schedule reset task(%d)\n",
|
||||
hdev->reset_fail_cnt);
|
||||
hdev->rst_stats.reset_fail_cnt);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3679,7 +3679,8 @@ static void hclge_reset(struct hclge_dev *hdev)
|
||||
/* ignore RoCE notify error if it fails HCLGE_RESET_MAX_FAIL_CNT - 1
|
||||
* times
|
||||
*/
|
||||
if (ret && hdev->reset_fail_cnt < HCLGE_RESET_MAX_FAIL_CNT - 1)
|
||||
if (ret &&
|
||||
hdev->rst_stats.reset_fail_cnt < HCLGE_RESET_MAX_FAIL_CNT - 1)
|
||||
goto err_reset;
|
||||
|
||||
rtnl_lock();
|
||||
@ -3695,7 +3696,7 @@ static void hclge_reset(struct hclge_dev *hdev)
|
||||
goto err_reset;
|
||||
|
||||
hdev->last_reset_time = jiffies;
|
||||
hdev->reset_fail_cnt = 0;
|
||||
hdev->rst_stats.reset_fail_cnt = 0;
|
||||
hdev->rst_stats.reset_done_cnt++;
|
||||
ae_dev->reset_type = HNAE3_NONE_RESET;
|
||||
|
||||
@ -3751,7 +3752,7 @@ static void hclge_reset_event(struct pci_dev *pdev, struct hnae3_handle *handle)
|
||||
else if (time_after(jiffies, (hdev->last_reset_time + 4 * 5 * HZ)))
|
||||
hdev->reset_level = HNAE3_FUNC_RESET;
|
||||
|
||||
dev_info(&hdev->pdev->dev, "received reset event , reset type is %d",
|
||||
dev_info(&hdev->pdev->dev, "received reset event, reset type is %d\n",
|
||||
hdev->reset_level);
|
||||
|
||||
/* request reset & schedule reset task */
|
||||
|
@ -659,6 +659,7 @@ struct hclge_rst_stats {
|
||||
u32 global_rst_cnt; /* the number of GLOBAL */
|
||||
u32 imp_rst_cnt; /* the number of IMP reset */
|
||||
u32 reset_cnt; /* the number of reset */
|
||||
u32 reset_fail_cnt; /* the number of reset fail */
|
||||
};
|
||||
|
||||
/* time and register status when mac tunnel interruption occur */
|
||||
@ -725,7 +726,6 @@ struct hclge_dev {
|
||||
unsigned long reset_request; /* reset has been requested */
|
||||
unsigned long reset_pending; /* client rst is pending to be served */
|
||||
struct hclge_rst_stats rst_stats;
|
||||
u32 reset_fail_cnt;
|
||||
u32 fw_version;
|
||||
u16 num_vmdq_vport; /* Num vmdq vport this PF has set up */
|
||||
u16 num_tqps; /* Num task queue pairs of this PF */
|
||||
|
@ -81,16 +81,13 @@ static int hclge_shaper_para_calc(u32 ir, u8 shaper_level,
|
||||
return 0;
|
||||
} else if (ir_calc > ir) {
|
||||
/* Increasing the denominator to select ir_s value */
|
||||
while (ir_calc > ir) {
|
||||
while (ir_calc >= ir && ir) {
|
||||
ir_s_calc++;
|
||||
ir_calc = DIVISOR_IR_B_126 / (tick * (1 << ir_s_calc));
|
||||
}
|
||||
|
||||
if (ir_calc == ir)
|
||||
*ir_b = 126;
|
||||
else
|
||||
*ir_b = (ir * tick * (1 << ir_s_calc) +
|
||||
(DIVISOR_CLK >> 1)) / DIVISOR_CLK;
|
||||
*ir_b = (ir * tick * (1 << ir_s_calc) + (DIVISOR_CLK >> 1)) /
|
||||
DIVISOR_CLK;
|
||||
} else {
|
||||
/* Increasing the numerator to select ir_u value */
|
||||
u32 numerator;
|
||||
@ -104,7 +101,7 @@ static int hclge_shaper_para_calc(u32 ir, u8 shaper_level,
|
||||
if (ir_calc == ir) {
|
||||
*ir_b = 126;
|
||||
} else {
|
||||
u32 denominator = (DIVISOR_CLK * (1 << --ir_u_calc));
|
||||
u32 denominator = DIVISOR_CLK * (1 << --ir_u_calc);
|
||||
*ir_b = (ir * tick + (denominator >> 1)) / denominator;
|
||||
}
|
||||
}
|
||||
|
@ -743,7 +743,7 @@ static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key,
|
||||
}
|
||||
|
||||
static int hclgevf_set_rss(struct hnae3_handle *handle, const u32 *indir,
|
||||
const u8 *key, const u8 hfunc)
|
||||
const u8 *key, const u8 hfunc)
|
||||
{
|
||||
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
|
||||
struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
|
||||
@ -2060,9 +2060,10 @@ static int hclgevf_config_gro(struct hclgevf_dev *hdev, bool en)
|
||||
static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev)
|
||||
{
|
||||
struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
|
||||
int i, ret;
|
||||
int ret;
|
||||
u32 i;
|
||||
|
||||
rss_cfg->rss_size = hdev->rss_size_max;
|
||||
rss_cfg->rss_size = hdev->nic.kinfo.rss_size;
|
||||
|
||||
if (hdev->pdev->revision >= 0x21) {
|
||||
rss_cfg->hash_algo = HCLGEVF_RSS_HASH_ALGO_SIMPLE;
|
||||
@ -2099,13 +2100,13 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev)
|
||||
|
||||
/* Initialize RSS indirect table */
|
||||
for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++)
|
||||
rss_cfg->rss_indirection_tbl[i] = i % hdev->rss_size_max;
|
||||
rss_cfg->rss_indirection_tbl[i] = i % rss_cfg->rss_size;
|
||||
|
||||
ret = hclgevf_set_rss_indir_table(hdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return hclgevf_set_rss_tc_mode(hdev, hdev->rss_size_max);
|
||||
return hclgevf_set_rss_tc_mode(hdev, rss_cfg->rss_size);
|
||||
}
|
||||
|
||||
static int hclgevf_init_vlan_config(struct hclgevf_dev *hdev)
|
||||
@ -2835,6 +2836,77 @@ static void hclgevf_get_tqps_and_rss_info(struct hnae3_handle *handle,
|
||||
*max_rss_size = hdev->rss_size_max;
|
||||
}
|
||||
|
||||
static void hclgevf_update_rss_size(struct hnae3_handle *handle,
|
||||
u32 new_tqps_num)
|
||||
{
|
||||
struct hnae3_knic_private_info *kinfo = &handle->kinfo;
|
||||
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
|
||||
u16 max_rss_size;
|
||||
|
||||
kinfo->req_rss_size = new_tqps_num;
|
||||
|
||||
max_rss_size = min_t(u16, hdev->rss_size_max,
|
||||
hdev->num_tqps / kinfo->num_tc);
|
||||
|
||||
/* Use the user's configuration when it is not larger than
|
||||
* max_rss_size, otherwise, use the maximum specification value.
|
||||
*/
|
||||
if (kinfo->req_rss_size != kinfo->rss_size && kinfo->req_rss_size &&
|
||||
kinfo->req_rss_size <= max_rss_size)
|
||||
kinfo->rss_size = kinfo->req_rss_size;
|
||||
else if (kinfo->rss_size > max_rss_size ||
|
||||
(!kinfo->req_rss_size && kinfo->rss_size < max_rss_size))
|
||||
kinfo->rss_size = max_rss_size;
|
||||
|
||||
kinfo->num_tqps = kinfo->num_tc * kinfo->rss_size;
|
||||
}
|
||||
|
||||
static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num,
|
||||
bool rxfh_configured)
|
||||
{
|
||||
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
|
||||
struct hnae3_knic_private_info *kinfo = &handle->kinfo;
|
||||
u16 cur_rss_size = kinfo->rss_size;
|
||||
u16 cur_tqps = kinfo->num_tqps;
|
||||
u32 *rss_indir;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
hclgevf_update_rss_size(handle, new_tqps_num);
|
||||
|
||||
ret = hclgevf_set_rss_tc_mode(hdev, kinfo->rss_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* RSS indirection table has been configuared by user */
|
||||
if (rxfh_configured)
|
||||
goto out;
|
||||
|
||||
/* Reinitializes the rss indirect table according to the new RSS size */
|
||||
rss_indir = kcalloc(HCLGEVF_RSS_IND_TBL_SIZE, sizeof(u32), GFP_KERNEL);
|
||||
if (!rss_indir)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < HCLGEVF_RSS_IND_TBL_SIZE; i++)
|
||||
rss_indir[i] = i % kinfo->rss_size;
|
||||
|
||||
ret = hclgevf_set_rss(handle, rss_indir, NULL, 0);
|
||||
if (ret)
|
||||
dev_err(&hdev->pdev->dev, "set rss indir table fail, ret=%d\n",
|
||||
ret);
|
||||
|
||||
kfree(rss_indir);
|
||||
|
||||
out:
|
||||
if (!ret)
|
||||
dev_info(&hdev->pdev->dev,
|
||||
"Channels changed, rss_size from %u to %u, tqps from %u to %u",
|
||||
cur_rss_size, kinfo->rss_size,
|
||||
cur_tqps, kinfo->rss_size * kinfo->num_tc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hclgevf_get_status(struct hnae3_handle *handle)
|
||||
{
|
||||
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
|
||||
@ -3042,6 +3114,7 @@ static const struct hnae3_ae_ops hclgevf_ops = {
|
||||
.enable_hw_strip_rxvtag = hclgevf_en_hw_strip_rxvtag,
|
||||
.reset_event = hclgevf_reset_event,
|
||||
.set_default_reset_request = hclgevf_set_def_reset_request,
|
||||
.set_channels = hclgevf_set_channels,
|
||||
.get_channels = hclgevf_get_channels,
|
||||
.get_tqps_and_rss_info = hclgevf_get_tqps_and_rss_info,
|
||||
.get_regs_len = hclgevf_get_regs_len,
|
||||
|
Loading…
x
Reference in New Issue
Block a user