Commit e7f13f44 authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 074be7fd 0ecf1f7b
......@@ -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;
int ret1;
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;
}
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;
}
return hns3_reset_notify(h, HNAE3_UP_CLIENT);
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,
......
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