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

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=216400


Signed-off-by: default avatarKeith Busch <kbusch@kernel.org>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent b7e97872
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -4702,6 +4702,8 @@ static void nvme_fw_act_work(struct work_struct *work)
	nvme_start_queues(ctrl);
	/* read FW slot information to clear the AER */
	nvme_get_fw_slot_info(ctrl);

	queue_work(nvme_wq, &ctrl->async_event_work);
}

static u32 nvme_aer_type(u32 result)
@@ -4714,9 +4716,10 @@ static u32 nvme_aer_subtype(u32 result)
	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);
	bool requeue = true;

	trace_nvme_async_event(ctrl, aer_notice_type);

@@ -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)) {
			nvme_auth_stop(ctrl);
			requeue = false;
			queue_work(nvme_wq, &ctrl->fw_act_work);
		}
		break;
@@ -4749,6 +4753,7 @@ static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
	default:
		dev_warn(ctrl->device, "async event result %08x\n", result);
	}
	return requeue;
}

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,
	u32 result = le32_to_cpu(res->u32);
	u32 aer_type = nvme_aer_type(result);
	u32 aer_subtype = nvme_aer_subtype(result);
	bool requeue = true;

	if (le16_to_cpu(status) >> 1 != NVME_SC_SUCCESS)
		return;

	switch (aer_type) {
	case NVME_AER_NOTICE:
		nvme_handle_aen_notice(ctrl, result);
		requeue = nvme_handle_aen_notice(ctrl, result);
		break;
	case NVME_AER_ERROR:
		/*
@@ -4791,6 +4797,8 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
	default:
		break;
	}

	if (requeue)
		queue_work(nvme_wq, &ctrl->async_event_work);
}
EXPORT_SYMBOL_GPL(nvme_complete_async_event);