net: hns3: add PCIe FLR support for PF
This patch implements the .reset_prepare and .reset_done ops from pci framework to support the PF FLR. Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
6dd22bbc77
commit
6b9a97ee43
|
@ -127,6 +127,7 @@ enum hnae3_reset_type {
|
|||
HNAE3_VF_FUNC_RESET,
|
||||
HNAE3_VF_PF_FUNC_RESET,
|
||||
HNAE3_VF_FULL_RESET,
|
||||
HNAE3_FLR_RESET,
|
||||
HNAE3_FUNC_RESET,
|
||||
HNAE3_CORE_RESET,
|
||||
HNAE3_GLOBAL_RESET,
|
||||
|
@ -134,6 +135,11 @@ enum hnae3_reset_type {
|
|||
HNAE3_NONE_RESET,
|
||||
};
|
||||
|
||||
enum hnae3_flr_state {
|
||||
HNAE3_FLR_DOWN,
|
||||
HNAE3_FLR_DONE,
|
||||
};
|
||||
|
||||
struct hnae3_vector_info {
|
||||
u8 __iomem *io_addr;
|
||||
int vector;
|
||||
|
@ -299,7 +305,8 @@ struct hnae3_ae_dev {
|
|||
struct hnae3_ae_ops {
|
||||
int (*init_ae_dev)(struct hnae3_ae_dev *ae_dev);
|
||||
void (*uninit_ae_dev)(struct hnae3_ae_dev *ae_dev);
|
||||
|
||||
void (*flr_prepare)(struct hnae3_ae_dev *ae_dev);
|
||||
void (*flr_done)(struct hnae3_ae_dev *ae_dev);
|
||||
int (*init_client_instance)(struct hnae3_client *client,
|
||||
struct hnae3_ae_dev *ae_dev);
|
||||
void (*uninit_client_instance)(struct hnae3_client *client,
|
||||
|
|
|
@ -1851,9 +1851,29 @@ static pci_ers_result_t hns3_slot_reset(struct pci_dev *pdev)
|
|||
return PCI_ERS_RESULT_DISCONNECT;
|
||||
}
|
||||
|
||||
static void hns3_reset_prepare(struct pci_dev *pdev)
|
||||
{
|
||||
struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
|
||||
|
||||
dev_info(&pdev->dev, "hns3 flr prepare\n");
|
||||
if (ae_dev && ae_dev->ops && ae_dev->ops->flr_prepare)
|
||||
ae_dev->ops->flr_prepare(ae_dev);
|
||||
}
|
||||
|
||||
static void hns3_reset_done(struct pci_dev *pdev)
|
||||
{
|
||||
struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
|
||||
|
||||
dev_info(&pdev->dev, "hns3 flr done\n");
|
||||
if (ae_dev && ae_dev->ops && ae_dev->ops->flr_done)
|
||||
ae_dev->ops->flr_done(ae_dev);
|
||||
}
|
||||
|
||||
static const struct pci_error_handlers hns3_err_handler = {
|
||||
.error_detected = hns3_error_detected,
|
||||
.slot_reset = hns3_slot_reset,
|
||||
.reset_prepare = hns3_reset_prepare,
|
||||
.reset_done = hns3_reset_done,
|
||||
};
|
||||
|
||||
static struct pci_driver hns3_driver = {
|
||||
|
|
|
@ -594,7 +594,9 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value)
|
|||
static inline bool hns3_dev_ongoing_func_reset(struct hnae3_ae_dev *ae_dev)
|
||||
{
|
||||
return (ae_dev && (ae_dev->reset_type == HNAE3_FUNC_RESET ||
|
||||
ae_dev->reset_type == HNAE3_FLR_RESET ||
|
||||
ae_dev->reset_type == HNAE3_VF_FUNC_RESET ||
|
||||
ae_dev->reset_type == HNAE3_VF_FULL_RESET ||
|
||||
ae_dev->reset_type == HNAE3_VF_PF_FUNC_RESET));
|
||||
}
|
||||
|
||||
|
|
|
@ -2374,6 +2374,8 @@ static int hclge_reset_wait(struct hclge_dev *hdev)
|
|||
reg = HCLGE_FUN_RST_ING;
|
||||
reg_bit = HCLGE_FUN_RST_ING_B;
|
||||
break;
|
||||
case HNAE3_FLR_RESET:
|
||||
break;
|
||||
default:
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"Wait for unsupported reset type: %d\n",
|
||||
|
@ -2381,6 +2383,20 @@ static int hclge_reset_wait(struct hclge_dev *hdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (hdev->reset_type == HNAE3_FLR_RESET) {
|
||||
while (!test_bit(HNAE3_FLR_DONE, &hdev->flr_state) &&
|
||||
cnt++ < HCLGE_RESET_WAIT_CNT)
|
||||
msleep(HCLGE_RESET_WATI_MS);
|
||||
|
||||
if (!test_bit(HNAE3_FLR_DONE, &hdev->flr_state)) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"flr wait timeout: %d\n", cnt);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = hclge_read_dev(&hdev->hw, reg);
|
||||
while (hnae3_get_bit(val, reg_bit) && cnt < HCLGE_RESET_WAIT_CNT) {
|
||||
msleep(HCLGE_RESET_WATI_MS);
|
||||
|
@ -2488,6 +2504,12 @@ static void hclge_do_reset(struct hclge_dev *hdev)
|
|||
set_bit(HNAE3_FUNC_RESET, &hdev->reset_pending);
|
||||
hclge_reset_task_schedule(hdev);
|
||||
break;
|
||||
case HNAE3_FLR_RESET:
|
||||
dev_info(&pdev->dev, "FLR requested\n");
|
||||
/* schedule again to check later */
|
||||
set_bit(HNAE3_FLR_RESET, &hdev->reset_pending);
|
||||
hclge_reset_task_schedule(hdev);
|
||||
break;
|
||||
default:
|
||||
dev_warn(&pdev->dev,
|
||||
"Unsupported reset type: %d\n", hdev->reset_type);
|
||||
|
@ -2519,6 +2541,9 @@ static enum hnae3_reset_type hclge_get_reset_level(struct hclge_dev *hdev,
|
|||
} else if (test_bit(HNAE3_FUNC_RESET, addr)) {
|
||||
rst_level = HNAE3_FUNC_RESET;
|
||||
clear_bit(HNAE3_FUNC_RESET, addr);
|
||||
} else if (test_bit(HNAE3_FLR_RESET, addr)) {
|
||||
rst_level = HNAE3_FLR_RESET;
|
||||
clear_bit(HNAE3_FLR_RESET, addr);
|
||||
}
|
||||
|
||||
return rst_level;
|
||||
|
@ -2555,6 +2580,8 @@ static int hclge_reset_prepare_down(struct hclge_dev *hdev)
|
|||
|
||||
switch (hdev->reset_type) {
|
||||
case HNAE3_FUNC_RESET:
|
||||
/* fall through */
|
||||
case HNAE3_FLR_RESET:
|
||||
ret = hclge_set_all_vf_rst(hdev, true);
|
||||
break;
|
||||
default:
|
||||
|
@ -2589,6 +2616,14 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev)
|
|||
*/
|
||||
set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);
|
||||
break;
|
||||
case HNAE3_FLR_RESET:
|
||||
/* There is no mechanism for PF to know if VF has stopped IO
|
||||
* for now, just wait 100 ms for VF to stop IO
|
||||
*/
|
||||
msleep(100);
|
||||
set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);
|
||||
set_bit(HNAE3_FLR_DOWN, &hdev->flr_state);
|
||||
break;
|
||||
case HNAE3_IMP_RESET:
|
||||
reg_val = hclge_read_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG);
|
||||
hclge_write_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG,
|
||||
|
@ -2647,6 +2682,8 @@ static int hclge_reset_prepare_up(struct hclge_dev *hdev)
|
|||
|
||||
switch (hdev->reset_type) {
|
||||
case HNAE3_FUNC_RESET:
|
||||
/* fall through */
|
||||
case HNAE3_FLR_RESET:
|
||||
ret = hclge_set_all_vf_rst(hdev, false);
|
||||
break;
|
||||
default:
|
||||
|
@ -6917,6 +6954,34 @@ static void hclge_state_uninit(struct hclge_dev *hdev)
|
|||
cancel_work_sync(&hdev->mbx_service_task);
|
||||
}
|
||||
|
||||
static void hclge_flr_prepare(struct hnae3_ae_dev *ae_dev)
|
||||
{
|
||||
#define HCLGE_FLR_WAIT_MS 100
|
||||
#define HCLGE_FLR_WAIT_CNT 50
|
||||
struct hclge_dev *hdev = ae_dev->priv;
|
||||
int cnt = 0;
|
||||
|
||||
clear_bit(HNAE3_FLR_DOWN, &hdev->flr_state);
|
||||
clear_bit(HNAE3_FLR_DONE, &hdev->flr_state);
|
||||
set_bit(HNAE3_FLR_RESET, &hdev->default_reset_request);
|
||||
hclge_reset_event(hdev->pdev, NULL);
|
||||
|
||||
while (!test_bit(HNAE3_FLR_DOWN, &hdev->flr_state) &&
|
||||
cnt++ < HCLGE_FLR_WAIT_CNT)
|
||||
msleep(HCLGE_FLR_WAIT_MS);
|
||||
|
||||
if (!test_bit(HNAE3_FLR_DOWN, &hdev->flr_state))
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"flr wait down timeout: %d\n", cnt);
|
||||
}
|
||||
|
||||
static void hclge_flr_done(struct hnae3_ae_dev *ae_dev)
|
||||
{
|
||||
struct hclge_dev *hdev = ae_dev->priv;
|
||||
|
||||
set_bit(HNAE3_FLR_DONE, &hdev->flr_state);
|
||||
}
|
||||
|
||||
static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
|
||||
{
|
||||
struct pci_dev *pdev = ae_dev->pdev;
|
||||
|
@ -7575,6 +7640,8 @@ static void hclge_get_link_mode(struct hnae3_handle *handle,
|
|||
static const struct hnae3_ae_ops hclge_ops = {
|
||||
.init_ae_dev = hclge_init_ae_dev,
|
||||
.uninit_ae_dev = hclge_uninit_ae_dev,
|
||||
.flr_prepare = hclge_flr_prepare,
|
||||
.flr_done = hclge_flr_done,
|
||||
.init_client_instance = hclge_init_client_instance,
|
||||
.uninit_client_instance = hclge_uninit_client_instance,
|
||||
.map_ring_to_vector = hclge_map_ring_to_vector,
|
||||
|
|
|
@ -597,6 +597,7 @@ struct hclge_dev {
|
|||
struct hclge_misc_vector misc_vector;
|
||||
struct hclge_hw_stats hw_stats;
|
||||
unsigned long state;
|
||||
unsigned long flr_state;
|
||||
unsigned long last_reset_time;
|
||||
|
||||
enum hnae3_reset_type reset_type;
|
||||
|
|
|
@ -90,6 +90,8 @@ int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport)
|
|||
|
||||
if (hdev->reset_type == HNAE3_FUNC_RESET)
|
||||
reset_type = HNAE3_VF_PF_FUNC_RESET;
|
||||
else if (hdev->reset_type == HNAE3_FLR_RESET)
|
||||
reset_type = HNAE3_VF_FULL_RESET;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
|
|
Loading…
Reference in New Issue