Skip to content

Commit

Permalink
net: hns3: Add mailbox interrupt handling to PF driver
Browse files Browse the repository at this point in the history
All PF mailbox events are conveyed through a common interrupt
(vector 0). This interrupt vector is shared by reset and mailbox.

This patch adds the handling of mailbox interrupt event and its
deferred processing in context to a separate mailbox task.

Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
Signed-off-by: lipeng <lipeng321@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Salil Mehta authored and David S. Miller committed Dec 15, 2017
1 parent 84e095d commit c1a8161
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 8 deletions.
68 changes: 61 additions & 7 deletions drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2227,6 +2227,12 @@ static int hclge_mac_init(struct hclge_dev *hdev)
return hclge_cfg_func_mta_filter(hdev, 0, hdev->accept_mta_mc);
}

static void hclge_mbx_task_schedule(struct hclge_dev *hdev)
{
if (!test_and_set_bit(HCLGE_STATE_MBX_SERVICE_SCHED, &hdev->state))
schedule_work(&hdev->mbx_service_task);
}

static void hclge_reset_task_schedule(struct hclge_dev *hdev)
{
if (!test_and_set_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state))
Expand Down Expand Up @@ -2372,9 +2378,18 @@ static void hclge_service_complete(struct hclge_dev *hdev)
static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
{
u32 rst_src_reg;
u32 cmdq_src_reg;

/* fetch the events from their corresponding regs */
rst_src_reg = hclge_read_dev(&hdev->hw, HCLGE_MISC_RESET_STS_REG);
cmdq_src_reg = hclge_read_dev(&hdev->hw, HCLGE_VECTOR0_CMDQ_SRC_REG);

/* Assumption: If by any chance reset and mailbox events are reported
* together then we will only process reset event in this go and will
* defer the processing of the mailbox events. Since, we would have not
* cleared RX CMDQ event this time we would receive again another
* interrupt from H/W just for the mailbox.
*/

/* check for vector0 reset event sources */
if (BIT(HCLGE_VECTOR0_GLOBALRESET_INT_B) & rst_src_reg) {
Expand All @@ -2395,18 +2410,27 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
return HCLGE_VECTOR0_EVENT_RST;
}

/* mailbox event sharing vector 0 interrupt would be placed here */
/* check for vector0 mailbox(=CMDQ RX) event source */
if (BIT(HCLGE_VECTOR0_RX_CMDQ_INT_B) & cmdq_src_reg) {
cmdq_src_reg &= ~BIT(HCLGE_VECTOR0_RX_CMDQ_INT_B);
*clearval = cmdq_src_reg;
return HCLGE_VECTOR0_EVENT_MBX;
}

return HCLGE_VECTOR0_EVENT_OTHER;
}

static void hclge_clear_event_cause(struct hclge_dev *hdev, u32 event_type,
u32 regclr)
{
if (event_type == HCLGE_VECTOR0_EVENT_RST)
switch (event_type) {
case HCLGE_VECTOR0_EVENT_RST:
hclge_write_dev(&hdev->hw, HCLGE_MISC_RESET_STS_REG, regclr);

/* mailbox event sharing vector 0 interrupt would be placed here */
break;
case HCLGE_VECTOR0_EVENT_MBX:
hclge_write_dev(&hdev->hw, HCLGE_VECTOR0_CMDQ_SRC_REG, regclr);
break;
}
}

static void hclge_enable_vector(struct hclge_misc_vector *vector, bool enable)
Expand All @@ -2423,13 +2447,23 @@ static irqreturn_t hclge_misc_irq_handle(int irq, void *data)
hclge_enable_vector(&hdev->misc_vector, false);
event_cause = hclge_check_event_cause(hdev, &clearval);

/* vector 0 interrupt is shared with reset and mailbox source events.
* For now, we are not handling mailbox events.
*/
/* vector 0 interrupt is shared with reset and mailbox source events.*/
switch (event_cause) {
case HCLGE_VECTOR0_EVENT_RST:
hclge_reset_task_schedule(hdev);
break;
case HCLGE_VECTOR0_EVENT_MBX:
/* If we are here then,
* 1. Either we are not handling any mbx task and we are not
* scheduled as well
* OR
* 2. We could be handling a mbx task but nothing more is
* scheduled.
* In both cases, we should schedule mbx task as there are more
* mbx messages reported by this interrupt.
*/
hclge_mbx_task_schedule(hdev);

default:
dev_dbg(&hdev->pdev->dev,
"received unknown or unhandled event of vector0\n");
Expand Down Expand Up @@ -2708,6 +2742,21 @@ static void hclge_reset_service_task(struct work_struct *work)
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_service_task(struct work_struct *work)
{
struct hclge_dev *hdev =
Expand Down Expand Up @@ -4815,6 +4864,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
timer_setup(&hdev->service_timer, hclge_service_timer, 0);
INIT_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);

/* Enable MISC vector(vector0) */
hclge_enable_vector(&hdev->misc_vector, true);
Expand All @@ -4823,6 +4873,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
set_bit(HCLGE_STATE_DOWN, &hdev->state);
clear_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state);
clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
clear_bit(HCLGE_STATE_MBX_SERVICE_SCHED, &hdev->state);
clear_bit(HCLGE_STATE_MBX_HANDLING, &hdev->state);

pr_info("%s driver initialization finished.\n", HCLGE_DRIVER_NAME);
return 0;
Expand Down Expand Up @@ -4936,6 +4988,8 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
cancel_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);

if (mac->phydev)
mdiobus_unregister(mac->mdio_bus);
Expand Down
8 changes: 7 additions & 1 deletion drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@
#define HCLGE_VECTOR0_CORERESET_INT_B 6
#define HCLGE_VECTOR0_IMPRESET_INT_B 7

/* Vector0 interrupt CMDQ event source register(RW) */
#define HCLGE_VECTOR0_CMDQ_SRC_REG 0x27100
/* CMDQ register bits for RX event(=MBX event) */
#define HCLGE_VECTOR0_RX_CMDQ_INT_B 1

enum HCLGE_DEV_STATE {
HCLGE_STATE_REINITING,
HCLGE_STATE_DOWN,
Expand All @@ -101,8 +106,8 @@ enum HCLGE_DEV_STATE {
HCLGE_STATE_SERVICE_SCHED,
HCLGE_STATE_RST_SERVICE_SCHED,
HCLGE_STATE_RST_HANDLING,
HCLGE_STATE_MBX_SERVICE_SCHED,
HCLGE_STATE_MBX_HANDLING,
HCLGE_STATE_MBX_IRQ,
HCLGE_STATE_MAX
};

Expand Down Expand Up @@ -479,6 +484,7 @@ struct hclge_dev {
struct timer_list service_timer;
struct work_struct service_task;
struct work_struct rst_service_task;
struct work_struct mbx_service_task;

bool cur_promisc;
int num_alloc_vfs; /* Actual number of VFs allocated */
Expand Down

0 comments on commit c1a8161

Please sign in to comment.