summaryrefslogtreecommitdiffstats
path: root/sys/dev/mpr/mpr_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/mpr/mpr_user.c')
-rw-r--r--sys/dev/mpr/mpr_user.c82
1 files changed, 75 insertions, 7 deletions
diff --git a/sys/dev/mpr/mpr_user.c b/sys/dev/mpr/mpr_user.c
index 0a847de..b1c1109 100644
--- a/sys/dev/mpr/mpr_user.c
+++ b/sys/dev/mpr/mpr_user.c
@@ -99,6 +99,7 @@ __FBSDID("$FreeBSD$");
#include <dev/mpr/mpi/mpi2_cnfg.h>
#include <dev/mpr/mpi/mpi2_init.h>
#include <dev/mpr/mpi/mpi2_tool.h>
+#include <dev/mpr/mpi/mpi2_pci.h>
#include <dev/mpr/mpr_ioctl.h>
#include <dev/mpr/mprvar.h>
#include <dev/mpr/mpr_table.h>
@@ -747,6 +748,8 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
{
MPI2_REQUEST_HEADER *hdr, tmphdr;
MPI2_DEFAULT_REPLY *rpl;
+ Mpi26NVMeEncapsulatedErrorReply_t *nvme_error_reply = NULL;
+ Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request = NULL;
struct mpr_command *cm = NULL;
int i, err = 0, dir = 0, sz;
uint8_t tool, function = 0;
@@ -923,8 +926,8 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
cm->cm_data, data->DataSize);
}
if (err != 0)
- mpr_dprint(sc, MPR_FAULT, "%s: failed to copy "
- "IOCTL data from user space\n", __func__);
+ mpr_dprint(sc, MPR_FAULT, "%s: failed to copy IOCTL "
+ "data from user space\n", __func__);
}
/*
* Set this flag only if processing a command that does not need an
@@ -946,6 +949,35 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
}
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+ if (function == MPI2_FUNCTION_NVME_ENCAPSULATED) {
+ nvme_encap_request =
+ (Mpi26NVMeEncapsulatedRequest_t *)cm->cm_req;
+ cm->cm_desc.Default.RequestFlags =
+ MPI26_REQ_DESCRIPT_FLAGS_PCIE_ENCAPSULATED;
+
+ /*
+ * Get the Physical Address of the sense buffer.
+ * Save the user's Error Response buffer address and use that
+ * field to hold the sense buffer address.
+ * Clear the internal sense buffer, which will potentially hold
+ * the Completion Queue Entry on return, or 0 if no Entry.
+ * Build the PRPs and set direction bits.
+ * Send the request.
+ */
+ cm->nvme_error_response =
+ (uint64_t *)(uintptr_t)(((uint64_t)nvme_encap_request->
+ ErrorResponseBaseAddress.High << 32) |
+ (uint64_t)nvme_encap_request->
+ ErrorResponseBaseAddress.Low);
+ nvme_encap_request->ErrorResponseBaseAddress.High =
+ htole32((uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32));
+ nvme_encap_request->ErrorResponseBaseAddress.Low =
+ htole32(cm->cm_sense_busaddr);
+ memset(cm->cm_sense, 0, NVME_ERROR_RESPONSE_SIZE);
+ mpr_build_nvme_prp(sc, cm, nvme_encap_request, cm->cm_data,
+ data->DataSize, data->DataOutSize);
+ }
+
/*
* Set up Sense buffer and SGL offset for IO passthru. SCSI IO request
* uses SCSI IO or Fast Path SCSI IO descriptor.
@@ -994,15 +1026,19 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO) {
cm->cm_desc.FastPathSCSIIO.RequestFlags =
MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
- cm->cm_desc.FastPathSCSIIO.DevHandle =
- scsi_io_req->DevHandle;
+ if (!sc->atomic_desc_capable) {
+ cm->cm_desc.FastPathSCSIIO.DevHandle =
+ scsi_io_req->DevHandle;
+ }
scsi_io_req->IoFlags |=
MPI25_SCSIIO_IOFLAGS_FAST_PATH;
} else {
cm->cm_desc.SCSIIO.RequestFlags =
MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
- cm->cm_desc.SCSIIO.DevHandle =
- scsi_io_req->DevHandle;
+ if (!sc->atomic_desc_capable) {
+ cm->cm_desc.SCSIIO.DevHandle =
+ scsi_io_req->DevHandle;
+ }
}
/*
@@ -1079,6 +1115,38 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
mpr_lock(sc);
}
}
+
+ /*
+ * Copy out the NVMe Error Reponse to user. The Error Response
+ * buffer is given by the user, but a sense buffer is used to
+ * get that data from the IOC. The user's
+ * ErrorResponseBaseAddress is saved in the
+ * 'nvme_error_response' field before the command because that
+ * field is set to a sense buffer. When the command is
+ * complete, the Error Response data from the IOC is copied to
+ * that user address after it is checked for validity.
+ * Also note that 'sense' buffers are not defined for
+ * NVMe commands. Sense terminalogy is only used here so that
+ * the same IOCTL structure and sense buffers can be used for
+ * NVMe.
+ */
+ if (function == MPI2_FUNCTION_NVME_ENCAPSULATED) {
+ if (cm->nvme_error_response == NULL) {
+ mpr_dprint(sc, MPR_INFO, "NVMe Error Response "
+ "buffer is NULL. Response data will not be "
+ "returned.\n");
+ mpr_unlock(sc);
+ goto RetFreeUnlocked;
+ }
+
+ nvme_error_reply =
+ (Mpi26NVMeEncapsulatedErrorReply_t *)cm->cm_reply;
+ sz = MIN(le32toh(nvme_error_reply->ErrorResponseCount),
+ NVME_ERROR_RESPONSE_SIZE);
+ mpr_unlock(sc);
+ copyout(cm->cm_sense, cm->nvme_error_response, sz);
+ mpr_lock(sc);
+ }
}
mpr_unlock(sc);
@@ -2068,7 +2136,7 @@ mpr_user_btdh(struct mpr_softc *sc, mpr_btdh_mapping_t *data)
return (EINVAL);
if (target > sc->max_devices) {
- mpr_dprint(sc, MPR_FAULT, "Target ID is out of range "
+ mpr_dprint(sc, MPR_XINFO, "Target ID is out of range "
"for Bus/Target to DevHandle mapping.");
return (EINVAL);
}
OpenPOWER on IntegriCloud