Skip to content

Commit

Permalink
net: hns3: remove mailbox and reset work in hclge_main
Browse files Browse the repository at this point in the history
There are three work (mbx_service_task, service_task,
rst_service_task) in the HNS3 driver, mbx_service_task is for
handling mailbox work, service_task is for periodic management
issue and rst_service_task is for reset related issue, which can
be handled in a single work.

This patch removes the mbx_service_task and rst_service_task
work, and moves the related handling to the service_task work
in order to remove concurrency between the three work and to
improve efficiency.

BTW, since stats_timer in struct hclge_hw_stats is not needed
anymore, so removes the definition of struct hclge_hw_stats,
and moves mac_stats into struct hclge_dev.

Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Yunsheng Lin authored and David S. Miller committed Dec 17, 2019
1 parent b3c3fe8 commit 1c6dfe6
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 73 deletions.
10 changes: 10 additions & 0 deletions drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,14 @@ void hclge_dbg_dump_rst_info(struct hclge_dev *hdev)
dev_info(&hdev->pdev->dev, "hdev state: 0x%lx\n", hdev->state);
}

static void hclge_dbg_dump_serv_info(struct hclge_dev *hdev)
{
dev_info(&hdev->pdev->dev, "last_serv_processed: %lu\n",
hdev->last_serv_processed);
dev_info(&hdev->pdev->dev, "last_serv_cnt: %lu\n",
hdev->serv_processed_cnt);
}

static void hclge_dbg_get_m7_stats_info(struct hclge_dev *hdev)
{
struct hclge_desc *desc_src, *desc_tmp;
Expand Down Expand Up @@ -1227,6 +1235,8 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf)
hclge_dbg_dump_reg_cmd(hdev, &cmd_buf[sizeof(DUMP_REG)]);
} else if (strncmp(cmd_buf, "dump reset info", 15) == 0) {
hclge_dbg_dump_rst_info(hdev);
} else if (strncmp(cmd_buf, "dump serv info", 14) == 0) {
hclge_dbg_dump_serv_info(hdev);
} else if (strncmp(cmd_buf, "dump m7 info", 12) == 0) {
hclge_dbg_get_m7_stats_info(hdev);
} else if (strncmp(cmd_buf, "dump ncl_config", 15) == 0) {
Expand Down
163 changes: 102 additions & 61 deletions drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ static int hclge_mac_update_stats_defective(struct hclge_dev *hdev)
{
#define HCLGE_MAC_CMD_NUM 21

u64 *data = (u64 *)(&hdev->hw_stats.mac_stats);
u64 *data = (u64 *)(&hdev->mac_stats);
struct hclge_desc desc[HCLGE_MAC_CMD_NUM];
__le64 *desc_data;
int i, k, n;
Expand Down Expand Up @@ -453,7 +453,7 @@ static int hclge_mac_update_stats_defective(struct hclge_dev *hdev)

static int hclge_mac_update_stats_complete(struct hclge_dev *hdev, u32 desc_num)
{
u64 *data = (u64 *)(&hdev->hw_stats.mac_stats);
u64 *data = (u64 *)(&hdev->mac_stats);
struct hclge_desc *desc;
__le64 *desc_data;
u16 i, k, n;
Expand Down Expand Up @@ -802,7 +802,7 @@ static void hclge_get_stats(struct hnae3_handle *handle, u64 *data)
struct hclge_dev *hdev = vport->back;
u64 *p;

p = hclge_comm_get_stats(&hdev->hw_stats.mac_stats, g_mac_stats_string,
p = hclge_comm_get_stats(&hdev->mac_stats, g_mac_stats_string,
ARRAY_SIZE(g_mac_stats_string), data);
p = hclge_tqps_get_stats(handle, p);
}
Expand All @@ -815,8 +815,8 @@ static void hclge_get_mac_stat(struct hnae3_handle *handle,

hclge_update_stats(handle, NULL);

mac_stats->tx_pause_cnt = hdev->hw_stats.mac_stats.mac_tx_mac_pause_num;
mac_stats->rx_pause_cnt = hdev->hw_stats.mac_stats.mac_rx_mac_pause_num;
mac_stats->tx_pause_cnt = hdev->mac_stats.mac_tx_mac_pause_num;
mac_stats->rx_pause_cnt = hdev->mac_stats.mac_rx_mac_pause_num;
}

static int hclge_parse_func_status(struct hclge_dev *hdev,
Expand Down Expand Up @@ -2665,31 +2665,26 @@ static int hclge_mac_init(struct hclge_dev *hdev)

static void hclge_mbx_task_schedule(struct hclge_dev *hdev)
{
if (!test_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state) &&
if (!test_bit(HCLGE_STATE_REMOVING, &hdev->state) &&
!test_and_set_bit(HCLGE_STATE_MBX_SERVICE_SCHED, &hdev->state))
queue_work_on(cpumask_first(&hdev->affinity_mask), system_wq,
&hdev->mbx_service_task);
mod_delayed_work_on(cpumask_first(&hdev->affinity_mask),
system_wq, &hdev->service_task, 0);
}

static void hclge_reset_task_schedule(struct hclge_dev *hdev)
{
if (!test_bit(HCLGE_STATE_REMOVING, &hdev->state) &&
!test_and_set_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state))
queue_work_on(cpumask_first(&hdev->affinity_mask), system_wq,
&hdev->rst_service_task);
mod_delayed_work_on(cpumask_first(&hdev->affinity_mask),
system_wq, &hdev->service_task, 0);
}

void hclge_task_schedule(struct hclge_dev *hdev, unsigned long delay_time)
{
if (!test_bit(HCLGE_STATE_DOWN, &hdev->state) &&
!test_bit(HCLGE_STATE_REMOVING, &hdev->state) &&
!test_and_set_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state)) {
hdev->hw_stats.stats_timer++;
hdev->fd_arfs_expire_timer++;
if (!test_bit(HCLGE_STATE_REMOVING, &hdev->state))
mod_delayed_work_on(cpumask_first(&hdev->affinity_mask),
system_wq, &hdev->service_task,
delay_time);
}
}

static int hclge_get_mac_link_status(struct hclge_dev *hdev)
Expand Down Expand Up @@ -2748,6 +2743,10 @@ static void hclge_update_link_status(struct hclge_dev *hdev)

if (!client)
return;

if (test_and_set_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state))
return;

state = hclge_get_mac_phy_link(hdev);
if (state != hdev->hw.mac.link) {
for (i = 0; i < hdev->num_vmdq_vport + 1; i++) {
Expand All @@ -2761,6 +2760,8 @@ static void hclge_update_link_status(struct hclge_dev *hdev)
}
hdev->hw.mac.link = state;
}

clear_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state);
}

static void hclge_update_port_capability(struct hclge_mac *mac)
Expand Down Expand Up @@ -3352,6 +3353,18 @@ static int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset)
return 0;
}

static void hclge_mailbox_service_task(struct hclge_dev *hdev)
{
if (!test_and_clear_bit(HCLGE_STATE_MBX_SERVICE_SCHED, &hdev->state) ||
test_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state) ||
test_and_set_bit(HCLGE_STATE_MBX_HANDLING, &hdev->state))
return;

hclge_mbx_handler(hdev);

clear_bit(HCLGE_STATE_MBX_HANDLING, &hdev->state);
}

static int hclge_func_reset_sync_vf(struct hclge_dev *hdev)
{
struct hclge_pf_rst_sync_cmd *req;
Expand All @@ -3363,6 +3376,9 @@ static int hclge_func_reset_sync_vf(struct hclge_dev *hdev)
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_VF_RST_RDY, true);

do {
/* vf need to down netdev by mbx during PF or FLR reset */
hclge_mailbox_service_task(hdev);

ret = hclge_cmd_send(&hdev->hw, &desc, 1);
/* for compatible with old firmware, wait
* 100 ms for VF to stop IO
Expand Down Expand Up @@ -3939,36 +3955,19 @@ static void hclge_reset_subtask(struct hclge_dev *hdev)
hdev->reset_type = HNAE3_NONE_RESET;
}

static void hclge_reset_service_task(struct work_struct *work)
static void hclge_reset_service_task(struct hclge_dev *hdev)
{
struct hclge_dev *hdev =
container_of(work, struct hclge_dev, rst_service_task);
if (!test_and_clear_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state))
return;

if (test_and_set_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
return;

clear_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state);

hclge_reset_subtask(hdev);

clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
}

static void hclge_mailbox_service_task(struct work_struct *work)
{
struct hclge_dev *hdev =
container_of(work, struct hclge_dev, mbx_service_task);

if (test_and_set_bit(HCLGE_STATE_MBX_HANDLING, &hdev->state))
return;

clear_bit(HCLGE_STATE_MBX_SERVICE_SCHED, &hdev->state);

hclge_mbx_handler(hdev);

clear_bit(HCLGE_STATE_MBX_HANDLING, &hdev->state);
}

static void hclge_update_vport_alive(struct hclge_dev *hdev)
{
int i;
Expand All @@ -3986,29 +3985,62 @@ static void hclge_update_vport_alive(struct hclge_dev *hdev)
}
}

static void hclge_service_task(struct work_struct *work)
static void hclge_periodic_service_task(struct hclge_dev *hdev)
{
struct hclge_dev *hdev =
container_of(work, struct hclge_dev, service_task.work);
unsigned long delta = round_jiffies_relative(HZ);

clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state);
/* Always handle the link updating to make sure link state is
* updated when it is triggered by mbx.
*/
hclge_update_link_status(hdev);

if (hdev->hw_stats.stats_timer >= HCLGE_STATS_TIMER_INTERVAL) {
hclge_update_stats_for_all(hdev);
hdev->hw_stats.stats_timer = 0;
if (time_is_after_jiffies(hdev->last_serv_processed + HZ)) {
delta = jiffies - hdev->last_serv_processed;

if (delta < round_jiffies_relative(HZ)) {
delta = round_jiffies_relative(HZ) - delta;
goto out;
}
}

hclge_update_port_info(hdev);
hclge_update_link_status(hdev);
hdev->serv_processed_cnt++;
hclge_update_vport_alive(hdev);

if (test_bit(HCLGE_STATE_DOWN, &hdev->state)) {
hdev->last_serv_processed = jiffies;
goto out;
}

if (!(hdev->serv_processed_cnt % HCLGE_STATS_TIMER_INTERVAL))
hclge_update_stats_for_all(hdev);

hclge_update_port_info(hdev);
hclge_sync_vlan_filter(hdev);

if (hdev->fd_arfs_expire_timer >= HCLGE_FD_ARFS_EXPIRE_TIMER_INTERVAL) {
if (!(hdev->serv_processed_cnt % HCLGE_ARFS_EXPIRE_INTERVAL))
hclge_rfs_filter_expire(hdev);
hdev->fd_arfs_expire_timer = 0;
}

hclge_task_schedule(hdev, round_jiffies_relative(HZ));
hdev->last_serv_processed = jiffies;

out:
hclge_task_schedule(hdev, delta);
}

static void hclge_service_task(struct work_struct *work)
{
struct hclge_dev *hdev =
container_of(work, struct hclge_dev, service_task.work);

hclge_reset_service_task(hdev);
hclge_mailbox_service_task(hdev);
hclge_periodic_service_task(hdev);

/* Handle reset and mbx again in case periodical task delays the
* handling by calling hclge_task_schedule() in
* hclge_periodic_service_task().
*/
hclge_reset_service_task(hdev);
hclge_mailbox_service_task(hdev);
}

struct hclge_vport *hclge_get_vport(struct hnae3_handle *handle)
Expand Down Expand Up @@ -6734,6 +6766,19 @@ static void hclge_reset_tqp_stats(struct hnae3_handle *handle)
}
}

static void hclge_flush_link_update(struct hclge_dev *hdev)
{
#define HCLGE_FLUSH_LINK_TIMEOUT 100000

unsigned long last = hdev->serv_processed_cnt;
int i = 0;

while (test_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state) &&
i++ < HCLGE_FLUSH_LINK_TIMEOUT &&
last == hdev->serv_processed_cnt)
usleep_range(1, 1);
}

static void hclge_set_timer_task(struct hnae3_handle *handle, bool enable)
{
struct hclge_vport *vport = hclge_get_vport(handle);
Expand All @@ -6742,12 +6787,12 @@ static void hclge_set_timer_task(struct hnae3_handle *handle, bool enable)
if (enable) {
hclge_task_schedule(hdev, round_jiffies_relative(HZ));
} else {
/* Set the DOWN flag here to disable the service to be
* scheduled again
*/
/* Set the DOWN flag here to disable link updating */
set_bit(HCLGE_STATE_DOWN, &hdev->state);
cancel_delayed_work_sync(&hdev->service_task);
clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state);

/* flush memory to make sure DOWN is seen by service task */
smp_mb__before_atomic();
hclge_flush_link_update(hdev);
}
}

Expand Down Expand Up @@ -9269,10 +9314,6 @@ static void hclge_state_uninit(struct hclge_dev *hdev)
del_timer_sync(&hdev->reset_timer);
if (hdev->service_task.work.func)
cancel_delayed_work_sync(&hdev->service_task);
if (hdev->rst_service_task.func)
cancel_work_sync(&hdev->rst_service_task);
if (hdev->mbx_service_task.func)
cancel_work_sync(&hdev->mbx_service_task);
}

static void hclge_flr_prepare(struct hnae3_ae_dev *ae_dev)
Expand Down Expand Up @@ -9477,8 +9518,6 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)

timer_setup(&hdev->reset_timer, hclge_reset_timer, 0);
INIT_DELAYED_WORK(&hdev->service_task, hclge_service_task);
INIT_WORK(&hdev->rst_service_task, hclge_reset_service_task);
INIT_WORK(&hdev->mbx_service_task, hclge_mailbox_service_task);

/* Setup affinity after service timer setup because add_timer_on
* is called in affinity notify.
Expand Down Expand Up @@ -9512,6 +9551,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
dev_info(&hdev->pdev->dev, "%s driver initialization finished.\n",
HCLGE_DRIVER_NAME);

hclge_task_schedule(hdev, round_jiffies_relative(HZ));

return 0;

err_mdiobus_unreg:
Expand All @@ -9534,7 +9575,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)

static void hclge_stats_clear(struct hclge_dev *hdev)
{
memset(&hdev->hw_stats, 0, sizeof(hdev->hw_stats));
memset(&hdev->mac_stats, 0, sizeof(hdev->mac_stats));
}

static int hclge_set_mac_spoofchk(struct hclge_dev *hdev, int vf, bool enable)
Expand Down
Loading

0 comments on commit 1c6dfe6

Please sign in to comment.