Skip to content

Commit

Permalink
Merge branch 'hns3-VF-reset'
Browse files Browse the repository at this point in the history
Salil Mehta says:

====================
Add support of VF Reset to HNS3 VF driver

This patch-set adds the support of VF reset to the existing VF driver.
VF Reset can be triggered due to TX watchdog firing  as a result of TX
data-path not working. VF reset could also be a result of some internal
configuration changes if that requires reset, or as a result of the
PF/Core/Global/IMP(Integrated Management Processor) reset happened in
the PF.

Summary of Patches:
* Watchdog timer trigger chnages are present in Patch 1.
* Reset Service Task and related Event handling is present in Patches {2,3}
* Changes to send reset request to PF, reset stack and re-initialization
  of the hclge device is present in Patches {4,5,6}
* Changes related to ARQ (Asynchronous Receive Queue) and its event handling
  are present in Patches {7,8}
* Changes required in PF to handle the VF Reset request and actually perform
  hardware VF reset is there in Patch 9.

NOTE: This patch depends upon "[PATCH net-next 00/11] fix some bugs for HNS3 driver"
	Link: https://lkml.org/lkml/2018/3/21/72
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 22, 2018
2 parents 1a2e10a + 2bfbd35 commit 6686c45
Show file tree
Hide file tree
Showing 11 changed files with 534 additions and 71 deletions.
16 changes: 16 additions & 0 deletions drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

enum HCLGE_MBX_OPCODE {
HCLGE_MBX_RESET = 0x01, /* (VF -> PF) assert reset */
HCLGE_MBX_ASSERTING_RESET, /* (PF -> VF) PF is asserting reset*/
HCLGE_MBX_SET_UNICAST, /* (VF -> PF) set UC addr */
HCLGE_MBX_SET_MULTICAST, /* (VF -> PF) set MC addr */
HCLGE_MBX_SET_VLAN, /* (VF -> PF) set VLAN */
Expand Down Expand Up @@ -85,6 +86,21 @@ struct hclge_mbx_pf_to_vf_cmd {
u16 msg[8];
};

/* used by VF to store the received Async responses from PF */
struct hclgevf_mbx_arq_ring {
#define HCLGE_MBX_MAX_ARQ_MSG_SIZE 8
#define HCLGE_MBX_MAX_ARQ_MSG_NUM 1024
struct hclgevf_dev *hdev;
u32 head;
u32 tail;
u32 count;
u16 msg_q[HCLGE_MBX_MAX_ARQ_MSG_NUM][HCLGE_MBX_MAX_ARQ_MSG_SIZE];
};

#define hclge_mbx_ring_ptr_move_crq(crq) \
(crq->next_to_use = (crq->next_to_use + 1) % crq->desc_num)
#define hclge_mbx_tail_ptr_move_arq(arq) \
(arq.tail = (arq.tail + 1) % HCLGE_MBX_MAX_ARQ_MSG_SIZE)
#define hclge_mbx_head_ptr_move_arq(arq) \
(arq.head = (arq.head + 1) % HCLGE_MBX_MAX_ARQ_MSG_SIZE)
#endif
8 changes: 6 additions & 2 deletions drivers/net/ethernet/hisilicon/hns3/hnae3.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ enum hnae3_reset_notify_type {
};

enum hnae3_reset_type {
HNAE3_VF_RESET,
HNAE3_VF_FULL_RESET,
HNAE3_FUNC_RESET,
HNAE3_CORE_RESET,
HNAE3_GLOBAL_RESET,
Expand Down Expand Up @@ -400,8 +402,7 @@ struct hnae3_ae_ops {
int (*set_vf_vlan_filter)(struct hnae3_handle *handle, int vfid,
u16 vlan, u8 qos, __be16 proto);
int (*enable_hw_strip_rxvtag)(struct hnae3_handle *handle, bool enable);
void (*reset_event)(struct hnae3_handle *handle,
enum hnae3_reset_type reset);
void (*reset_event)(struct hnae3_handle *handle);
void (*get_channels)(struct hnae3_handle *handle,
struct ethtool_channels *ch);
void (*get_tqps_and_rss_info)(struct hnae3_handle *h,
Expand Down Expand Up @@ -495,6 +496,9 @@ struct hnae3_handle {
struct hnae3_ae_algo *ae_algo; /* the class who provides this handle */
u64 flags; /* Indicate the capabilities for this handle*/

unsigned long last_reset_time;
enum hnae3_reset_type reset_level;

union {
struct net_device *netdev; /* first member */
struct hnae3_knic_private_info kinfo;
Expand Down
30 changes: 7 additions & 23 deletions drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ static int hns3_nic_net_open(struct net_device *netdev)
return ret;
}

priv->last_reset_time = jiffies;
priv->ae_handle->last_reset_time = jiffies;
return 0;
}

Expand Down Expand Up @@ -1543,32 +1543,19 @@ static bool hns3_get_tx_timeo_queue_info(struct net_device *ndev)
static void hns3_nic_net_timeout(struct net_device *ndev)
{
struct hns3_nic_priv *priv = netdev_priv(ndev);
unsigned long last_reset_time = priv->last_reset_time;
struct hnae3_handle *h = priv->ae_handle;

if (!hns3_get_tx_timeo_queue_info(ndev))
return;

priv->tx_timeout_count++;

/* This timeout is far away enough from last timeout,
* if timeout again,set the reset type to PF reset
*/
if (time_after(jiffies, (last_reset_time + 20 * HZ)))
priv->reset_level = HNAE3_FUNC_RESET;

/* Don't do any new action before the next timeout */
else if (time_before(jiffies, (last_reset_time + ndev->watchdog_timeo)))
if (time_before(jiffies, (h->last_reset_time + ndev->watchdog_timeo)))
return;

priv->last_reset_time = jiffies;

/* request the reset */
if (h->ae_algo->ops->reset_event)
h->ae_algo->ops->reset_event(h, priv->reset_level);

priv->reset_level++;
if (priv->reset_level > HNAE3_GLOBAL_RESET)
priv->reset_level = HNAE3_GLOBAL_RESET;
h->ae_algo->ops->reset_event(h);
}

static const struct net_device_ops hns3_nic_netdev_ops = {
Expand Down Expand Up @@ -3122,8 +3109,8 @@ static int hns3_client_init(struct hnae3_handle *handle)
priv->dev = &pdev->dev;
priv->netdev = netdev;
priv->ae_handle = handle;
priv->last_reset_time = jiffies;
priv->reset_level = HNAE3_FUNC_RESET;
priv->ae_handle->reset_level = HNAE3_NONE_RESET;
priv->ae_handle->last_reset_time = jiffies;
priv->tx_timeout_count = 0;

handle->kinfo.netdev = netdev;
Expand Down Expand Up @@ -3355,7 +3342,6 @@ static int hns3_reset_notify_down_enet(struct hnae3_handle *handle)
static int hns3_reset_notify_up_enet(struct hnae3_handle *handle)
{
struct hnae3_knic_private_info *kinfo = &handle->kinfo;
struct hns3_nic_priv *priv = netdev_priv(kinfo->netdev);
int ret = 0;

if (netif_running(kinfo->netdev)) {
Expand All @@ -3365,8 +3351,7 @@ static int hns3_reset_notify_up_enet(struct hnae3_handle *handle)
"hns net up fail, ret=%d!\n", ret);
return ret;
}

priv->last_reset_time = jiffies;
handle->last_reset_time = jiffies;
}

return ret;
Expand All @@ -3378,7 +3363,6 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle)
struct hns3_nic_priv *priv = netdev_priv(netdev);
int ret;

priv->reset_level = 1;
hns3_init_mac_addr(netdev);
hns3_nic_set_rx_mode(netdev);
hns3_recover_hw_addr(netdev);
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
Original file line number Diff line number Diff line change
Expand Up @@ -532,8 +532,6 @@ struct hns3_nic_priv {
/* The most recently read link state */
int link;
u64 tx_timeout_count;
enum hnae3_reset_type reset_level;
unsigned long last_reset_time;

unsigned long state;

Expand Down
38 changes: 21 additions & 17 deletions drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2749,7 +2749,7 @@ static int hclge_reset_wait(struct hclge_dev *hdev)
return 0;
}

static int hclge_func_reset_cmd(struct hclge_dev *hdev, int func_id)
int hclge_func_reset_cmd(struct hclge_dev *hdev, int func_id)
{
struct hclge_desc desc;
struct hclge_reset_cmd *req = (struct hclge_reset_cmd *)desc.data;
Expand Down Expand Up @@ -2845,27 +2845,31 @@ static void hclge_reset(struct hclge_dev *hdev)
hclge_notify_client(hdev, HNAE3_UP_CLIENT);
}

static void hclge_reset_event(struct hnae3_handle *handle,
enum hnae3_reset_type reset)
static void hclge_reset_event(struct hnae3_handle *handle)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;

dev_info(&hdev->pdev->dev,
"Receive reset event , reset_type is %d", reset);
/* check if this is a new reset request and we are not here just because
* last reset attempt did not succeed and watchdog hit us again. We will
* know this if last reset request did not occur very recently (watchdog
* timer = 5*HZ, let us check after sufficiently large time, say 4*5*Hz)
* In case of new request we reset the "reset level" to PF reset.
*/
if (time_after(jiffies, (handle->last_reset_time + 4 * 5 * HZ)))
handle->reset_level = HNAE3_FUNC_RESET;

switch (reset) {
case HNAE3_FUNC_RESET:
case HNAE3_CORE_RESET:
case HNAE3_GLOBAL_RESET:
/* request reset & schedule reset task */
set_bit(reset, &hdev->reset_request);
hclge_reset_task_schedule(hdev);
break;
default:
dev_warn(&hdev->pdev->dev, "Unsupported reset event:%d", reset);
break;
}
dev_info(&hdev->pdev->dev, "received reset event , reset type is %d",
handle->reset_level);

/* request reset & schedule reset task */
set_bit(handle->reset_level, &hdev->reset_request);
hclge_reset_task_schedule(hdev);

if (handle->reset_level < HNAE3_GLOBAL_RESET)
handle->reset_level++;

handle->last_reset_time = jiffies;
}

static void hclge_reset_subtask(struct hclge_dev *hdev)
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -657,4 +657,5 @@ void hclge_mbx_handler(struct hclge_dev *hdev);
void hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id);
void hclge_reset_vf_queue(struct hclge_vport *vport, u16 queue_id);
int hclge_cfg_flowctrl(struct hclge_dev *hdev);
int hclge_func_reset_cmd(struct hclge_dev *hdev, int func_id);
#endif
42 changes: 42 additions & 0 deletions drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,18 @@ static int hclge_send_mbx_msg(struct hclge_vport *vport, u8 *msg, u16 msg_len,
return status;
}

int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport)
{
u8 msg_data[2];
u8 dest_vfid;

dest_vfid = (u8)vport->vport_id;

/* send this requested info to VF */
return hclge_send_mbx_msg(vport, msg_data, sizeof(u8),
HCLGE_MBX_ASSERTING_RESET, dest_vfid);
}

static void hclge_free_vector_ring_chain(struct hnae3_ring_chain_node *head)
{
struct hnae3_ring_chain_node *chain_tmp, *chain;
Expand Down Expand Up @@ -339,6 +351,33 @@ static void hclge_mbx_reset_vf_queue(struct hclge_vport *vport,
hclge_gen_resp_to_vf(vport, mbx_req, 0, NULL, 0);
}

static void hclge_reset_vf(struct hclge_vport *vport,
struct hclge_mbx_vf_to_pf_cmd *mbx_req)
{
struct hclge_dev *hdev = vport->back;
int ret;

dev_warn(&hdev->pdev->dev, "PF received VF reset request from VF %d!",
mbx_req->mbx_src_vfid);

/* Acknowledge VF that PF is now about to assert the reset for the VF.
* On receiving this message VF will get into pending state and will
* start polling for the hardware reset completion status.
*/
ret = hclge_inform_reset_assert_to_vf(vport);
if (ret) {
dev_err(&hdev->pdev->dev,
"PF fail(%d) to inform VF(%d)of reset, reset failed!\n",
ret, vport->vport_id);
return;
}

dev_warn(&hdev->pdev->dev, "PF is now resetting VF %d.\n",
mbx_req->mbx_src_vfid);
/* reset this virtual function */
hclge_func_reset_cmd(hdev, mbx_req->mbx_src_vfid);
}

void hclge_mbx_handler(struct hclge_dev *hdev)
{
struct hclge_cmq_ring *crq = &hdev->hw.cmq.crq;
Expand Down Expand Up @@ -416,6 +455,9 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
case HCLGE_MBX_QUEUE_RESET:
hclge_mbx_reset_vf_queue(vport, req);
break;
case HCLGE_MBX_RESET:
hclge_reset_vf(vport, req);
break;
default:
dev_err(&hdev->pdev->dev,
"un-supported mailbox message, code = %d\n",
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,12 @@ int hclgevf_cmd_init(struct hclgevf_dev *hdev)
goto err_csq;
}

/* initialize the pointers of async rx queue of mailbox */
hdev->arq.hdev = hdev;
hdev->arq.head = 0;
hdev->arq.tail = 0;
hdev->arq.count = 0;

/* get firmware version */
ret = hclgevf_cmd_query_firmware_version(&hdev->hw, &version);
if (ret) {
Expand Down
Loading

0 comments on commit 6686c45

Please sign in to comment.