Commit 371a982c authored by Keith Busch's avatar Keith Busch Committed by Christoph Hellwig

nvme: requeue aen after firmware activation

The driver prevents async event work while handling a processing paused
event, but someone needs to restart it after the controller returns to a
live state.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=216400Signed-off-by: default avatarKeith Busch <kbusch@kernel.org>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent b7e97872
...@@ -4702,6 +4702,8 @@ static void nvme_fw_act_work(struct work_struct *work) ...@@ -4702,6 +4702,8 @@ static void nvme_fw_act_work(struct work_struct *work)
nvme_start_queues(ctrl); nvme_start_queues(ctrl);
/* read FW slot information to clear the AER */ /* read FW slot information to clear the AER */
nvme_get_fw_slot_info(ctrl); nvme_get_fw_slot_info(ctrl);
queue_work(nvme_wq, &ctrl->async_event_work);
} }
static u32 nvme_aer_type(u32 result) static u32 nvme_aer_type(u32 result)
...@@ -4714,9 +4716,10 @@ static u32 nvme_aer_subtype(u32 result) ...@@ -4714,9 +4716,10 @@ static u32 nvme_aer_subtype(u32 result)
return (result & 0xff00) >> 8; return (result & 0xff00) >> 8;
} }
static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result) static bool nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
{ {
u32 aer_notice_type = nvme_aer_subtype(result); u32 aer_notice_type = nvme_aer_subtype(result);
bool requeue = true;
trace_nvme_async_event(ctrl, aer_notice_type); trace_nvme_async_event(ctrl, aer_notice_type);
...@@ -4733,6 +4736,7 @@ static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result) ...@@ -4733,6 +4736,7 @@ static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
*/ */
if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) { if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) {
nvme_auth_stop(ctrl); nvme_auth_stop(ctrl);
requeue = false;
queue_work(nvme_wq, &ctrl->fw_act_work); queue_work(nvme_wq, &ctrl->fw_act_work);
} }
break; break;
...@@ -4749,6 +4753,7 @@ static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result) ...@@ -4749,6 +4753,7 @@ static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
default: default:
dev_warn(ctrl->device, "async event result %08x\n", result); dev_warn(ctrl->device, "async event result %08x\n", result);
} }
return requeue;
} }
static void nvme_handle_aer_persistent_error(struct nvme_ctrl *ctrl) static void nvme_handle_aer_persistent_error(struct nvme_ctrl *ctrl)
...@@ -4764,13 +4769,14 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status, ...@@ -4764,13 +4769,14 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
u32 result = le32_to_cpu(res->u32); u32 result = le32_to_cpu(res->u32);
u32 aer_type = nvme_aer_type(result); u32 aer_type = nvme_aer_type(result);
u32 aer_subtype = nvme_aer_subtype(result); u32 aer_subtype = nvme_aer_subtype(result);
bool requeue = true;
if (le16_to_cpu(status) >> 1 != NVME_SC_SUCCESS) if (le16_to_cpu(status) >> 1 != NVME_SC_SUCCESS)
return; return;
switch (aer_type) { switch (aer_type) {
case NVME_AER_NOTICE: case NVME_AER_NOTICE:
nvme_handle_aen_notice(ctrl, result); requeue = nvme_handle_aen_notice(ctrl, result);
break; break;
case NVME_AER_ERROR: case NVME_AER_ERROR:
/* /*
...@@ -4791,7 +4797,9 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status, ...@@ -4791,7 +4797,9 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
default: default:
break; break;
} }
queue_work(nvme_wq, &ctrl->async_event_work);
if (requeue)
queue_work(nvme_wq, &ctrl->async_event_work);
} }
EXPORT_SYMBOL_GPL(nvme_complete_async_event); EXPORT_SYMBOL_GPL(nvme_complete_async_event);
......
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