aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/nvme/nvme_sim.c
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2017-11-14 05:05:16 +0000
committerWarner Losh <imp@FreeBSD.org>2017-11-14 05:05:16 +0000
commit4e3b274457f7dd43f8f9b6d7a36a8c4d18624859 (patch)
treea37b7a1e81df9ab1bf0b0ad7b682b49e07fdf128 /sys/dev/nvme/nvme_sim.c
parentd505913c91e23bf1e7c2d4cd40e7ccec5e6967e8 (diff)
Notes
Diffstat (limited to 'sys/dev/nvme/nvme_sim.c')
-rw-r--r--sys/dev/nvme/nvme_sim.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/sys/dev/nvme/nvme_sim.c b/sys/dev/nvme/nvme_sim.c
index 94169055919c1..87532f9d9ab7e 100644
--- a/sys/dev/nvme/nvme_sim.c
+++ b/sys/dev/nvme/nvme_sim.c
@@ -44,6 +44,9 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_xpt_internal.h> // Yes, this is wrong.
#include <cam/cam_debug.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
#include "nvme_private.h"
#define ccb_accb_ptr spriv_ptr0
@@ -122,6 +125,22 @@ nvme_sim_nvmeio(struct cam_sim *sim, union ccb *ccb)
ccb->ccb_h.status |= CAM_SIM_QUEUED;
}
+static uint32_t
+nvme_link_kBps(struct nvme_controller *ctrlr)
+{
+ uint32_t speed, lanes, link[] = { 1, 250000, 500000, 985000, 1970000 };
+
+ speed = pcie_link_status(ctrlr->dev) & PCIEM_LINK_STA_SPEED;
+ lanes = (pcie_link_status(ctrlr->dev) & PCIEM_LINK_STA_WIDTH) >> 4;
+ /*
+ * Failsafe on link speed indicator. If it is insane report the number of
+ * lanes as the speed. Not 100% accurate, but may be diagnostic.
+ */
+ if (speed >= nitems(link))
+ speed = 0;
+ return link[speed] * lanes;
+}
+
static void
nvme_sim_action(struct cam_sim *sim, union ccb *ccb)
{
@@ -179,15 +198,15 @@ nvme_sim_action(struct cam_sim *sim, union ccb *ccb)
cpi->maxio = nvme_ns_get_max_io_xfer_size(ns);
cpi->initiator_id = 0;
cpi->bus_id = cam_sim_bus(sim);
- cpi->base_transfer_speed = 4000000; /* 4 GB/s 4 lanes pcie 3 */
+ cpi->base_transfer_speed = nvme_link_kBps(ctrlr);
strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strlcpy(cpi->hba_vid, "NVMe", HBA_IDLEN);
strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
cpi->unit_number = cam_sim_unit(sim);
cpi->transport = XPORT_NVME; /* XXX XPORT_PCIE ? */
- cpi->transport_version = 1; /* XXX Get PCIe spec ? */
+ cpi->transport_version = nvme_mmio_read_4(ctrlr, vs);
cpi->protocol = PROTO_NVME;
- cpi->protocol_version = NVME_REV_1; /* Groks all 1.x NVMe cards */
+ cpi->protocol_version = nvme_mmio_read_4(ctrlr, vs);
cpi->xport_specific.nvme.nsid = ns->id;
cpi->ccb_h.status = CAM_REQ_CMP;
break;
@@ -197,20 +216,24 @@ nvme_sim_action(struct cam_sim *sim, union ccb *ccb)
struct ccb_trans_settings *cts;
struct ccb_trans_settings_nvme *nvmep;
struct ccb_trans_settings_nvme *nvmex;
+ device_t dev;
+ dev = ctrlr->dev;
cts = &ccb->cts;
nvmex = &cts->xport_specific.nvme;
nvmep = &cts->proto_specific.nvme;
- nvmex->valid = CTS_NVME_VALID_SPEC;
- nvmex->spec_major = 1; /* XXX read from card */
- nvmex->spec_minor = 2;
- nvmex->spec_tiny = 0;
+ nvmex->valid = CTS_NVME_VALID_SPEC | CTS_NVME_VALID_LINK;
+ nvmex->spec = nvme_mmio_read_4(ctrlr, vs);
+ nvmex->speed = pcie_link_status(dev) & PCIEM_LINK_STA_SPEED;
+ nvmex->lanes = (pcie_link_status(dev) & PCIEM_LINK_STA_WIDTH) >> 4;
+ nvmex->max_speed = pcie_link_caps(dev) & PCIEM_LINK_CAP_MAX_SPEED;
+ nvmex->max_lanes = (pcie_link_caps(dev) & PCIEM_LINK_CAP_MAX_WIDTH) >> 4;
+
+ /* XXX these should be something else maybe ? */
+ nvmep->valid = 1;
+ nvmep->spec = nvmex->spec;
- nvmep->valid = CTS_NVME_VALID_SPEC;
- nvmep->spec_major = 1; /* XXX read from card */
- nvmep->spec_minor = 2;
- nvmep->spec_tiny = 0;
cts->transport = XPORT_NVME;
cts->protocol = PROTO_NVME;
cts->ccb_h.status = CAM_REQ_CMP;