Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151754416
D24896.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D24896.diff
View Options
Index: head/usr.sbin/bhyve/pci_nvme.c
===================================================================
--- head/usr.sbin/bhyve/pci_nvme.c
+++ head/usr.sbin/bhyve/pci_nvme.c
@@ -251,6 +251,11 @@
#define NVME_FID_MAX (NVME_FEAT_ENDURANCE_GROUP_EVENT_CONFIGURATION + 1)
+struct pci_nvme_aer {
+ STAILQ_ENTRY(pci_nvme_aer) link;
+ uint16_t cid; /* Command ID of the submitted AER */
+};
+
struct pci_nvme_softc {
struct pci_devinst *nsc_pi;
@@ -296,6 +301,9 @@
__uint128_t write_commands;
uint32_t read_dunits_remainder;
uint32_t write_dunits_remainder;
+
+ STAILQ_HEAD(, pci_nvme_aer) aer_list;
+ uint32_t aer_count;
};
@@ -604,6 +612,93 @@
}
static void
+pci_nvme_aer_init(struct pci_nvme_softc *sc)
+{
+
+ STAILQ_INIT(&sc->aer_list);
+ sc->aer_count = 0;
+}
+
+static void
+pci_nvme_aer_destroy(struct pci_nvme_softc *sc)
+{
+ struct pci_nvme_aer *aer = NULL;
+
+ while (!STAILQ_EMPTY(&sc->aer_list)) {
+ aer = STAILQ_FIRST(&sc->aer_list);
+ STAILQ_REMOVE_HEAD(&sc->aer_list, link);
+ free(aer);
+ }
+
+ pci_nvme_aer_init(sc);
+}
+
+static bool
+pci_nvme_aer_available(struct pci_nvme_softc *sc)
+{
+
+ return (!STAILQ_EMPTY(&sc->aer_list));
+}
+
+static bool
+pci_nvme_aer_limit_reached(struct pci_nvme_softc *sc)
+{
+ struct nvme_controller_data *cd = &sc->ctrldata;
+
+ /* AERL is a zero based value while aer_count is one's based */
+ return (sc->aer_count == (cd->aerl + 1));
+}
+
+/*
+ * Add an Async Event Request
+ *
+ * Stores an AER to be returned later if the Controller needs to notify the
+ * host of an event.
+ * Note that while the NVMe spec doesn't require Controllers to return AER's
+ * in order, this implementation does preserve the order.
+ */
+static int
+pci_nvme_aer_add(struct pci_nvme_softc *sc, uint16_t cid)
+{
+ struct pci_nvme_aer *aer = NULL;
+
+ if (pci_nvme_aer_limit_reached(sc))
+ return (-1);
+
+ aer = calloc(1, sizeof(struct pci_nvme_aer));
+ if (aer == NULL)
+ return (-1);
+
+ sc->aer_count++;
+
+ /* Save the Command ID for use in the completion message */
+ aer->cid = cid;
+ STAILQ_INSERT_TAIL(&sc->aer_list, aer, link);
+
+ return (0);
+}
+
+/*
+ * Get an Async Event Request structure
+ *
+ * Returns a pointer to an AER previously submitted by the host or NULL if
+ * no AER's exist. Caller is responsible for freeing the returned struct.
+ */
+static struct pci_nvme_aer *
+pci_nvme_aer_get(struct pci_nvme_softc *sc)
+{
+ struct pci_nvme_aer *aer = NULL;
+
+ aer = STAILQ_FIRST(&sc->aer_list);
+ if (aer != NULL) {
+ STAILQ_REMOVE_HEAD(&sc->aer_list, link);
+ sc->aer_count--;
+ }
+
+ return (aer);
+}
+
+static void
pci_nvme_reset_locked(struct pci_nvme_softc *sc)
{
uint32_t i;
@@ -641,6 +736,8 @@
}
sc->num_q_is_set = false;
+
+ pci_nvme_aer_destroy(sc);
}
static void
@@ -1376,13 +1473,26 @@
{
DPRINTF("%s async event request 0x%x", __func__, command->cdw11);
+ /* Don't exceed the Async Event Request Limit (AERL). */
+ if (pci_nvme_aer_limit_reached(sc)) {
+ pci_nvme_status_tc(&compl->status, NVME_SCT_COMMAND_SPECIFIC,
+ NVME_SC_ASYNC_EVENT_REQUEST_LIMIT_EXCEEDED);
+ return (1);
+ }
+
+ if (pci_nvme_aer_add(sc, command->cid)) {
+ pci_nvme_status_tc(&compl->status, NVME_SCT_GENERIC,
+ NVME_SC_INTERNAL_DEVICE_ERROR);
+ return (1);
+ }
+
/*
- * TODO: raise events when they happen based on the Set Features cmd.
+ * Raise events when they happen based on the Set Features cmd.
* These events happen async, so only set completion successful if
* there is an event reflective of the request to get event.
*/
- pci_nvme_status_tc(&compl->status, NVME_SCT_COMMAND_SPECIFIC,
- NVME_SC_ASYNC_EVENT_REQUEST_LIMIT_EXCEEDED);
+ compl->status = NVME_NO_STATUS;
+
return (0);
}
@@ -1449,10 +1559,7 @@
break;
case NVME_OPC_ASYNC_EVENT_REQUEST:
DPRINTF("%s command ASYNC_EVENT_REQ", __func__);
- /* XXX dont care, unhandled for now
nvme_opc_async_event_req(sc, cmd, &compl);
- */
- compl.status = NVME_NO_STATUS;
break;
case NVME_OPC_FORMAT_NVM:
DPRINTF("%s command FORMAT_NVM", __func__);
@@ -2619,6 +2726,8 @@
pci_nvme_init_ctrldata(sc);
pci_nvme_init_logpages(sc);
pci_nvme_init_features(sc);
+
+ pci_nvme_aer_init(sc);
pci_nvme_reset(sc);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 11, 11:01 AM (16 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31286582
Default Alt Text
D24896.diff (4 KB)
Attached To
Mode
D24896: bhyve: Add AER support to NVMe emulation
Attached
Detach File
Event Timeline
Log In to Comment