summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-11-13 19:24:44 +0000
committermav <mav@FreeBSD.org>2015-11-13 19:24:44 +0000
commit747538c2de6eb571e0eff6a8129c0c9d7b0bd7b8 (patch)
tree3b3001bc4ed57f16d6d538305b52e778fea32318 /sys
parent800769b3180e3137c36d2185a689835c2b4dfd28 (diff)
downloadFreeBSD-src-747538c2de6eb571e0eff6a8129c0c9d7b0bd7b8.zip
FreeBSD-src-747538c2de6eb571e0eff6a8129c0c9d7b0bd7b8.tar.gz
MFC r289881: Give CTL support for PIM_EXTLUNS when talking to CAM.
CTL itself still lives in flat LUN space, but it can generate extended numbers if CAM SIM reports such capability.
Diffstat (limited to 'sys')
-rw-r--r--sys/cam/ctl/ctl.c94
-rw-r--r--sys/cam/ctl/ctl.h3
-rw-r--r--sys/cam/ctl/ctl_frontend_cam_sim.c11
-rw-r--r--sys/cam/ctl/ctl_frontend_iscsi.c61
-rw-r--r--sys/cam/ctl/scsi_ctl.c35
5 files changed, 103 insertions, 101 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 926ab75..9635d51 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -3540,6 +3540,67 @@ ctl_lun_map_to_port(struct ctl_port *port, uint32_t lun_id)
return (UINT32_MAX);
}
+uint32_t
+ctl_decode_lun(uint64_t encoded)
+{
+ uint8_t lun[8];
+ uint32_t result = 0xffffffff;
+
+ be64enc(lun, encoded);
+ switch (lun[0] & RPL_LUNDATA_ATYP_MASK) {
+ case RPL_LUNDATA_ATYP_PERIPH:
+ if ((lun[0] & 0x3f) == 0 && lun[2] == 0 && lun[3] == 0 &&
+ lun[4] == 0 && lun[5] == 0 && lun[6] == 0 && lun[7] == 0)
+ result = lun[1];
+ break;
+ case RPL_LUNDATA_ATYP_FLAT:
+ if (lun[2] == 0 && lun[3] == 0 && lun[4] == 0 && lun[5] == 0 &&
+ lun[6] == 0 && lun[7] == 0)
+ result = ((lun[0] & 0x3f) << 8) + lun[1];
+ break;
+ case RPL_LUNDATA_ATYP_EXTLUN:
+ switch (lun[0] & RPL_LUNDATA_EXT_EAM_MASK) {
+ case 0x02:
+ switch (lun[0] & RPL_LUNDATA_EXT_LEN_MASK) {
+ case 0x00:
+ result = lun[1];
+ break;
+ case 0x10:
+ result = (lun[1] << 16) + (lun[2] << 8) +
+ lun[3];
+ break;
+ case 0x20:
+ if (lun[1] == 0 && lun[6] == 0 && lun[7] == 0)
+ result = (lun[2] << 24) +
+ (lun[3] << 16) + (lun[4] << 8) +
+ lun[5];
+ break;
+ }
+ break;
+ case RPL_LUNDATA_EXT_EAM_NOT_SPEC:
+ result = 0xffffffff;
+ break;
+ }
+ break;
+ }
+ return (result);
+}
+
+uint64_t
+ctl_encode_lun(uint32_t decoded)
+{
+ uint64_t l = decoded;
+
+ if (l <= 0xff)
+ return (((uint64_t)RPL_LUNDATA_ATYP_PERIPH << 56) | (l << 48));
+ if (l <= 0x3fff)
+ return (((uint64_t)RPL_LUNDATA_ATYP_FLAT << 56) | (l << 48));
+ if (l <= 0xffffff)
+ return (((uint64_t)(RPL_LUNDATA_ATYP_EXTLUN | 0x12) << 56) |
+ (l << 32));
+ return ((((uint64_t)RPL_LUNDATA_ATYP_EXTLUN | 0x22) << 56) | (l << 16));
+}
+
static struct ctl_port *
ctl_io_port(struct ctl_io_hdr *io_hdr)
{
@@ -9063,36 +9124,9 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
if (lun == NULL)
continue;
- if (targ_lun_id <= 0xff) {
- /*
- * Peripheral addressing method, bus number 0.
- */
- lun_data->luns[num_filled].lundata[0] =
- RPL_LUNDATA_ATYP_PERIPH;
- lun_data->luns[num_filled].lundata[1] = targ_lun_id;
- num_filled++;
- } else if (targ_lun_id <= 0x3fff) {
- /*
- * Flat addressing method.
- */
- lun_data->luns[num_filled].lundata[0] =
- RPL_LUNDATA_ATYP_FLAT | (targ_lun_id >> 8);
- lun_data->luns[num_filled].lundata[1] =
- (targ_lun_id & 0xff);
- num_filled++;
- } else if (targ_lun_id <= 0xffffff) {
- /*
- * Extended flat addressing method.
- */
- lun_data->luns[num_filled].lundata[0] =
- RPL_LUNDATA_ATYP_EXTLUN | 0x12;
- scsi_ulto3b(targ_lun_id,
- &lun_data->luns[num_filled].lundata[1]);
- num_filled++;
- } else {
- printf("ctl_report_luns: bogus LUN number %jd, "
- "skipping\n", (intmax_t)targ_lun_id);
- }
+ be64enc(lun_data->luns[num_filled++].lundata,
+ ctl_encode_lun(targ_lun_id));
+
/*
* According to SPC-3, rev 14 section 6.21:
*
diff --git a/sys/cam/ctl/ctl.h b/sys/cam/ctl/ctl.h
index 35fc4c3..ba78ff0 100644
--- a/sys/cam/ctl/ctl.h
+++ b/sys/cam/ctl/ctl.h
@@ -191,6 +191,9 @@ void ctl_clr_ua_all(struct ctl_lun *lun, uint32_t except, ctl_ua_type ua);
void ctl_clr_ua_allluns(struct ctl_softc *ctl_softc, uint32_t initidx,
ctl_ua_type ua_type);
+uint32_t ctl_decode_lun(uint64_t encoded);
+uint64_t ctl_encode_lun(uint32_t decoded);
+
void ctl_isc_announce_lun(struct ctl_lun *lun);
void ctl_isc_announce_port(struct ctl_port *port);
void ctl_isc_announce_iid(struct ctl_port *port, int iid);
diff --git a/sys/cam/ctl/ctl_frontend_cam_sim.c b/sys/cam/ctl/ctl_frontend_cam_sim.c
index 428cf44..9f9ea15 100644
--- a/sys/cam/ctl/ctl_frontend_cam_sim.c
+++ b/sys/cam/ctl/ctl_frontend_cam_sim.c
@@ -549,7 +549,8 @@ cfcs_action(struct cam_sim *sim, union ccb *ccb)
io->io_hdr.io_type = CTL_IO_SCSI;
io->io_hdr.nexus.initid = 1;
io->io_hdr.nexus.targ_port = softc->port.targ_port;
- io->io_hdr.nexus.targ_lun = ccb->ccb_h.target_lun;
+ io->io_hdr.nexus.targ_lun = ctl_decode_lun(
+ CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
/*
* This tag scheme isn't the best, since we could in theory
* have a very long-lived I/O and tag collision, especially
@@ -638,7 +639,8 @@ cfcs_action(struct cam_sim *sim, union ccb *ccb)
io->io_hdr.io_type = CTL_IO_TASK;
io->io_hdr.nexus.initid = 1;
io->io_hdr.nexus.targ_port = softc->port.targ_port;
- io->io_hdr.nexus.targ_lun = ccb->ccb_h.target_lun;
+ io->io_hdr.nexus.targ_lun = ctl_decode_lun(
+ CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
io->taskio.task_action = CTL_TASK_ABORT_TASK;
io->taskio.tag_num = abort_ccb->csio.tag_id;
switch (abort_ccb->csio.tag_action) {
@@ -733,7 +735,8 @@ cfcs_action(struct cam_sim *sim, union ccb *ccb)
io->io_hdr.io_type = CTL_IO_TASK;
io->io_hdr.nexus.initid = 1;
io->io_hdr.nexus.targ_port = softc->port.targ_port;
- io->io_hdr.nexus.targ_lun = ccb->ccb_h.target_lun;
+ io->io_hdr.nexus.targ_lun = ctl_decode_lun(
+ CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
if (ccb->ccb_h.func_code == XPT_RESET_BUS)
io->taskio.task_action = CTL_TASK_BUS_RESET;
else
@@ -760,7 +763,7 @@ cfcs_action(struct cam_sim *sim, union ccb *ccb)
cpi->version_num = 0;
cpi->hba_inquiry = PI_TAG_ABLE;
cpi->target_sprt = 0;
- cpi->hba_misc = 0;
+ cpi->hba_misc = PIM_EXTLUNS;
cpi->hba_eng_cnt = 0;
cpi->max_target = 1;
cpi->max_lun = 1024;
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c
index 778a6ba..399e141 100644
--- a/sys/cam/ctl/ctl_frontend_iscsi.c
+++ b/sys/cam/ctl/ctl_frontend_iscsi.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/capsicum.h>
#include <sys/condvar.h>
+#include <sys/endian.h>
#include <sys/file.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
@@ -413,62 +414,6 @@ cfiscsi_pdu_queue(struct icl_pdu *response)
CFISCSI_SESSION_UNLOCK(cs);
}
-static uint32_t
-cfiscsi_decode_lun(uint64_t encoded)
-{
- uint8_t lun[8];
- uint32_t result;
-
- /*
- * The LUN field in iSCSI PDUs may look like an ordinary 64 bit number,
- * but is in fact an evil, multidimensional structure defined
- * in SCSI Architecture Model 5 (SAM-5), section 4.6.
- */
- memcpy(lun, &encoded, sizeof(lun));
- switch (lun[0] & 0xC0) {
- case 0x00:
- if ((lun[0] & 0x3f) != 0 || lun[2] != 0 || lun[3] != 0 ||
- lun[4] != 0 || lun[5] != 0 || lun[6] != 0 || lun[7] != 0) {
- CFISCSI_WARN("malformed LUN "
- "(peripheral device addressing method): 0x%jx",
- (uintmax_t)encoded);
- result = 0xffffffff;
- break;
- }
- result = lun[1];
- break;
- case 0x40:
- if (lun[2] != 0 || lun[3] != 0 || lun[4] != 0 || lun[5] != 0 ||
- lun[6] != 0 || lun[7] != 0) {
- CFISCSI_WARN("malformed LUN "
- "(flat address space addressing method): 0x%jx",
- (uintmax_t)encoded);
- result = 0xffffffff;
- break;
- }
- result = ((lun[0] & 0x3f) << 8) + lun[1];
- break;
- case 0xC0:
- if (lun[0] != 0xD2 || lun[4] != 0 || lun[5] != 0 ||
- lun[6] != 0 || lun[7] != 0) {
- CFISCSI_WARN("malformed LUN (extended flat "
- "address space addressing method): 0x%jx",
- (uintmax_t)encoded);
- result = 0xffffffff;
- break;
- }
- result = (lun[1] << 16) + (lun[2] << 8) + lun[3];
- break;
- default:
- CFISCSI_WARN("unsupported LUN format 0x%jx",
- (uintmax_t)encoded);
- result = 0xffffffff;
- break;
- }
-
- return (result);
-}
-
static void
cfiscsi_pdu_handle_nop_out(struct icl_pdu *request)
{
@@ -563,7 +508,7 @@ cfiscsi_pdu_handle_scsi_command(struct icl_pdu *request)
io->io_hdr.io_type = CTL_IO_SCSI;
io->io_hdr.nexus.initid = cs->cs_ctl_initid;
io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port;
- io->io_hdr.nexus.targ_lun = cfiscsi_decode_lun(bhssc->bhssc_lun);
+ io->io_hdr.nexus.targ_lun = ctl_decode_lun(be64toh(bhssc->bhssc_lun));
io->scsiio.tag_num = bhssc->bhssc_initiator_task_tag;
switch ((bhssc->bhssc_flags & BHSSC_FLAGS_ATTR)) {
case BHSSC_FLAGS_ATTR_UNTAGGED:
@@ -619,7 +564,7 @@ cfiscsi_pdu_handle_task_request(struct icl_pdu *request)
io->io_hdr.io_type = CTL_IO_TASK;
io->io_hdr.nexus.initid = cs->cs_ctl_initid;
io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port;
- io->io_hdr.nexus.targ_lun = cfiscsi_decode_lun(bhstmr->bhstmr_lun);
+ io->io_hdr.nexus.targ_lun = ctl_decode_lun(be64toh(bhstmr->bhstmr_lun));
io->taskio.tag_type = CTL_TAG_SIMPLE; /* XXX */
switch (bhstmr->bhstmr_function & ~0x80) {
diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c
index 85a341e..2705240 100644
--- a/sys/cam/ctl/scsi_ctl.c
+++ b/sys/cam/ctl/scsi_ctl.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2008, 2009 Silicon Graphics International Corp.
+ * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -73,13 +74,14 @@ __FBSDID("$FreeBSD$");
#include <cam/ctl/ctl_error.h>
struct ctlfe_softc {
- struct ctl_port port;
- path_id_t path_id;
- target_id_t target_id;
- u_int maxio;
+ struct ctl_port port;
+ path_id_t path_id;
+ target_id_t target_id;
+ uint32_t hba_misc;
+ u_int maxio;
struct cam_sim *sim;
- char port_name[DEV_IDLEN];
- struct mtx lun_softc_mtx;
+ char port_name[DEV_IDLEN];
+ struct mtx lun_softc_mtx;
STAILQ_HEAD(, ctlfe_lun_softc) lun_softc_list;
STAILQ_ENTRY(ctlfe_softc) links;
};
@@ -355,6 +357,7 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
softc->path_id = cpi->ccb_h.path_id;
softc->target_id = cpi->initiator_id;
softc->sim = xpt_path_sim(path);
+ softc->hba_misc = cpi->hba_misc;
if (cpi->maxio != 0)
softc->maxio = cpi->maxio;
else
@@ -1166,7 +1169,12 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
io->io_hdr.io_type = CTL_IO_SCSI;
io->io_hdr.nexus.initid = atio->init_id;
io->io_hdr.nexus.targ_port = bus_softc->port.targ_port;
- io->io_hdr.nexus.targ_lun = atio->ccb_h.target_lun;
+ if (bus_softc->hba_misc & PIM_EXTLUNS) {
+ io->io_hdr.nexus.targ_lun = ctl_decode_lun(
+ CAM_EXTLUN_BYTE_SWIZZLE(atio->ccb_h.target_lun));
+ } else {
+ io->io_hdr.nexus.targ_lun = atio->ccb_h.target_lun;
+ }
io->scsiio.tag_num = atio->tag_id;
switch (atio->tag_action) {
case CAM_TAG_ACTION_NONE:
@@ -1440,7 +1448,12 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
inot->ccb_h.io_ptr = io;
io->io_hdr.nexus.initid = inot->initiator_id;
io->io_hdr.nexus.targ_port = bus_softc->port.targ_port;
- io->io_hdr.nexus.targ_lun = inot->ccb_h.target_lun;
+ if (bus_softc->hba_misc & PIM_EXTLUNS) {
+ io->io_hdr.nexus.targ_lun = ctl_decode_lun(
+ CAM_EXTLUN_BYTE_SWIZZLE(inot->ccb_h.target_lun));
+ } else {
+ io->io_hdr.nexus.targ_lun = inot->ccb_h.target_lun;
+ }
/* XXX KDM should this be the tag_id? */
io->taskio.tag_num = inot->seq_id;
@@ -1820,9 +1833,11 @@ ctlfe_lun_enable(void *arg, int lun_id)
cam_status status;
bus_softc = (struct ctlfe_softc *)arg;
+ if (bus_softc->hba_misc & PIM_EXTLUNS)
+ lun_id = CAM_EXTLUN_BYTE_SWIZZLE(ctl_encode_lun(lun_id));
status = xpt_create_path(&path, /*periph*/ NULL,
- bus_softc->path_id, bus_softc->target_id, lun_id);
+ bus_softc->path_id, bus_softc->target_id, lun_id);
/* XXX KDM need some way to return status to CTL here? */
if (status != CAM_REQ_CMP) {
printf("%s: could not create path, status %#x\n", __func__,
@@ -1879,6 +1894,8 @@ ctlfe_lun_disable(void *arg, int lun_id)
struct ctlfe_lun_softc *lun_softc;
softc = (struct ctlfe_softc *)arg;
+ if (softc->hba_misc & PIM_EXTLUNS)
+ lun_id = CAM_EXTLUN_BYTE_SWIZZLE(ctl_encode_lun(lun_id));
mtx_lock(&softc->lun_softc_mtx);
STAILQ_FOREACH(lun_softc, &softc->lun_softc_list, links) {
OpenPOWER on IntegriCloud