Widen lun_id_t to 64 bits. This is a follow-on to r257345 to let the kernel

support all valid SAM-5 LUN IDs. CAM_VERSION is bumped, as the CAM ABI
(though not API) is changed. No behavior is changed relative to r257345
except that LUNs with non-zero high 32 bits will no longer be ignored
during device enumeration for SIMs that have set PIM_EXTLUNS.

Reviewed by:	scottl
This commit is contained in:
nwhitehorn 2013-12-14 22:07:40 +00:00
parent c4ffb19933
commit f9ad7a0406
5 changed files with 234 additions and 41 deletions

View File

@ -39,16 +39,12 @@
typedef u_int path_id_t;
typedef u_int target_id_t;
typedef u_int lun_id_t;
typedef union {
u_int64_t lun64;
u_int8_t lun[8];
} lun64_id_t;
typedef u_int64_t lun_id_t;
#define CAM_XPT_PATH_ID ((path_id_t)~0)
#define CAM_BUS_WILDCARD ((path_id_t)~0)
#define CAM_TARGET_WILDCARD ((target_id_t)~0)
#define CAM_LUN_WILDCARD ((lun_id_t)~0)
#define CAM_LUN_WILDCARD (~(u_int)0)
#define CAM_EXTLUN_BYTE_SWIZZLE(lun) ( \
((((u_int64_t)lun) & 0xffff000000000000L) >> 48) | \

View File

@ -109,10 +109,6 @@ typedef enum {
CAM_UNLOCKED = 0x80000000 /* Call callback without lock. */
} ccb_flags;
typedef enum {
CAM_EXTLUN_VALID = 0x00000001,/* 64bit lun field is valid */
} ccb_xflags;
/* XPT Opcodes for xpt_action */
typedef enum {
/* Function code flags are bits greater than 0xff */
@ -326,7 +322,6 @@ struct ccb_hdr {
path_id_t path_id; /* Path ID for the request */
target_id_t target_id; /* Target device ID */
lun_id_t target_lun; /* Target LUN number */
lun64_id_t ext_lun; /* 64bit extended/multi-level LUNs */
u_int32_t flags; /* ccb_flags */
u_int32_t xflags; /* Extended flags */
ccb_ppriv_area periph_priv;
@ -555,7 +550,7 @@ struct ccb_dev_match {
/*
* Definitions for the path inquiry CCB fields.
*/
#define CAM_VERSION 0x18 /* Hex value for current version */
#define CAM_VERSION 0x19 /* Hex value for current version */
typedef enum {
PI_MDP_ABLE = 0x80, /* Supports MDP message */

View File

@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_ccb.h>
#include <cam/cam_xpt.h>
#include <cam/cam_compat.h>
#include <cam/cam_periph.h>
#include <cam/scsi/scsi_pass.h>
@ -53,6 +54,9 @@ __FBSDID("$FreeBSD$");
static int cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr,
int flag, struct thread *td, d_ioctl_t *cbfnp);
static int cam_compat_handle_0x18(struct cdev *dev, u_long cmd, caddr_t addr,
int flag, struct thread *td, d_ioctl_t *cbfnp);
static int cam_compat_translate_dev_match_0x18(union ccb *ccb);
int
cam_compat_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
@ -63,28 +67,28 @@ cam_compat_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
switch (cmd) {
case CAMIOCOMMAND_0x16:
{
union ccb *ccb;
struct ccb_hdr_0x17 *hdr17;
ccb = (union ccb *)addr;
if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS_0x16) {
ccb->ccb_h.flags &= ~CAM_SG_LIST_PHYS_0x16;
ccb->ccb_h.flags |= CAM_DATA_SG_PADDR;
hdr17 = (struct ccb_hdr_0x17 *)addr;
if (hdr17->flags & CAM_SG_LIST_PHYS_0x16) {
hdr17->flags &= ~CAM_SG_LIST_PHYS_0x16;
hdr17->flags |= CAM_DATA_SG_PADDR;
}
if (ccb->ccb_h.flags & CAM_DATA_PHYS_0x16) {
ccb->ccb_h.flags &= ~CAM_DATA_PHYS_0x16;
ccb->ccb_h.flags |= CAM_DATA_PADDR;
if (hdr17->flags & CAM_DATA_PHYS_0x16) {
hdr17->flags &= ~CAM_DATA_PHYS_0x16;
hdr17->flags |= CAM_DATA_PADDR;
}
if (ccb->ccb_h.flags & CAM_SCATTER_VALID_0x16) {
ccb->ccb_h.flags &= CAM_SCATTER_VALID_0x16;
ccb->ccb_h.flags |= CAM_DATA_SG;
if (hdr17->flags & CAM_SCATTER_VALID_0x16) {
hdr17->flags &= CAM_SCATTER_VALID_0x16;
hdr17->flags |= CAM_DATA_SG;
}
cmd = CAMIOCOMMAND;
error = (cbfnp)(dev, cmd, addr, flag, td);
error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp);
break;
}
case CAMGETPASSTHRU_0x16:
cmd = CAMGETPASSTHRU;
error = (cbfnp)(dev, cmd, addr, flag, td);
error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp);
break;
case CAMIOCOMMAND_0x17:
cmd = CAMIOCOMMAND;
@ -94,6 +98,14 @@ cam_compat_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
cmd = CAMGETPASSTHRU;
error = cam_compat_handle_0x17(dev, cmd, addr, flag, td, cbfnp);
break;
case CAMIOCOMMAND_0x18:
cmd = CAMIOCOMMAND;
error = cam_compat_handle_0x18(dev, cmd, addr, flag, td, cbfnp);
break;
case CAMGETPASSTHRU_0x18:
cmd = CAMGETPASSTHRU;
error = cam_compat_handle_0x18(dev, cmd, addr, flag, td, cbfnp);
break;
default:
error = ENOTTY;
}
@ -127,7 +139,6 @@ cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
hdr->path_id = hdr17->path_id;
hdr->target_id = hdr17->target_id;
hdr->target_lun = hdr17->target_lun;
hdr->ext_lun.lun64 = 0;
hdr->flags = hdr17->flags;
hdr->xflags = 0;
hdr->periph_priv = hdr17->periph_priv;
@ -159,13 +170,11 @@ cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
hdr17->sim_priv = hdr->sim_priv;
hdr17->timeout = hdr->timeout;
/* The PATH_INQ only needs special handling on the way out */
if (ccb->ccb_h.func_code != XPT_PATH_INQ) {
bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN);
} else {
if (ccb->ccb_h.func_code == XPT_PATH_INQ) {
struct ccb_pathinq *cpi;
struct ccb_pathinq_0x17 *cpi17;
/* The PATH_INQ only needs special handling on the way out */
cpi = &ccb->cpi;
cpi17 = (struct ccb_pathinq_0x17 *)hdr17;
cpi17->version_num = cpi->version_num;
@ -196,9 +205,151 @@ cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
cpi17->hba_device = cpi->hba_device;
cpi17->hba_subvendor = cpi->hba_subvendor;
cpi17->hba_subdevice = cpi->hba_subdevice;
} else if (ccb->ccb_h.func_code == XPT_DEV_MATCH) {
/* Copy the rest of the header over */
bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN);
cam_compat_translate_dev_match_0x18(ccb);
} else {
bcopy(ccbb, ccbb17, CAM_0X17_DATA_LEN);
}
xpt_free_ccb(ccb);
return (error);
}
static int
cam_compat_handle_0x18(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
struct thread *td, d_ioctl_t *cbfnp)
{
union ccb *ccb;
struct ccb_hdr *hdr;
struct ccb_hdr_0x18 *hdr18;
uint8_t *ccbb, *ccbb18;
u_int error;
hdr18 = (struct ccb_hdr_0x18 *)addr;
ccb = xpt_alloc_ccb();
hdr = &ccb->ccb_h;
hdr->pinfo = hdr18->pinfo;
hdr->xpt_links = hdr18->xpt_links;
hdr->sim_links = hdr18->sim_links;
hdr->periph_links = hdr18->periph_links;
hdr->retry_count = hdr18->retry_count;
hdr->cbfcnp = hdr18->cbfcnp;
hdr->func_code = hdr18->func_code;
hdr->status = hdr18->status;
hdr->path = hdr18->path;
hdr->path_id = hdr18->path_id;
hdr->target_id = hdr18->target_id;
hdr->target_lun = hdr18->target_lun;
if (hdr18->xflags & CAM_EXTLUN_VALID_0x18)
hdr->target_lun = hdr18->ext_lun;
hdr->flags = hdr18->flags;
hdr->xflags = hdr18->xflags;
hdr->periph_priv = hdr18->periph_priv;
hdr->sim_priv = hdr18->sim_priv;
hdr->timeout = hdr18->timeout;
hdr->softtimeout.tv_sec = 0;
hdr->softtimeout.tv_usec = 0;
ccbb = (uint8_t *)&hdr[1];
ccbb18 = (uint8_t *)&hdr18[1];
bcopy(ccbb18, ccbb, CAM_0X18_DATA_LEN);
error = (cbfnp)(dev, cmd, (caddr_t)ccb, flag, td);
hdr18->pinfo = hdr->pinfo;
hdr18->xpt_links = hdr->xpt_links;
hdr18->sim_links = hdr->sim_links;
hdr18->periph_links = hdr->periph_links;
hdr18->retry_count = hdr->retry_count;
hdr18->cbfcnp = hdr->cbfcnp;
hdr18->func_code = hdr->func_code;
hdr18->status = hdr->status;
hdr18->path = hdr->path;
hdr18->path_id = hdr->path_id;
hdr18->target_id = hdr->target_id;
hdr18->target_lun = hdr->target_lun;
hdr18->ext_lun = hdr->target_lun;
hdr18->flags = hdr->flags;
hdr18->xflags = hdr->xflags | CAM_EXTLUN_VALID_0x18;
hdr18->periph_priv = hdr->periph_priv;
hdr18->sim_priv = hdr->sim_priv;
hdr18->timeout = hdr->timeout;
bcopy(ccbb, ccbb18, CAM_0X18_DATA_LEN);
if (ccb->ccb_h.func_code == XPT_DEV_MATCH)
cam_compat_translate_dev_match_0x18(ccb);
xpt_free_ccb(ccb);
return (error);
}
static int
cam_compat_translate_dev_match_0x18(union ccb *ccb)
{
struct dev_match_result *dm;
struct dev_match_result_0x18 *dm18;
struct cam_periph_map_info mapinfo;
int i;
/* Remap the CCB into kernel address space */
bzero(&mapinfo, sizeof(mapinfo));
cam_periph_mapmem(ccb, &mapinfo);
dm = ccb->cdm.matches;
/* Translate in-place: old fields are smaller */
dm18 = (struct dev_match_result_0x18 *)(dm);
for (i = 0; i < ccb->cdm.num_matches; i++) {
dm18[i].type = dm[i].type;
switch (dm[i].type) {
case DEV_MATCH_PERIPH:
memcpy(&dm18[i].result.periph_result.periph_name,
&dm[i].result.periph_result.periph_name,
DEV_IDLEN);
dm18[i].result.periph_result.unit_number =
dm[i].result.periph_result.unit_number;
dm18[i].result.periph_result.path_id =
dm[i].result.periph_result.path_id;
dm18[i].result.periph_result.target_id =
dm[i].result.periph_result.target_id;
dm18[i].result.periph_result.target_lun =
dm[i].result.periph_result.target_lun;
break;
case DEV_MATCH_DEVICE:
dm18[i].result.device_result.path_id =
dm[i].result.device_result.path_id;
dm18[i].result.device_result.target_id =
dm[i].result.device_result.target_id;
dm18[i].result.device_result.target_lun =
dm[i].result.device_result.target_lun;
dm18[i].result.device_result.protocol =
dm[i].result.device_result.protocol;
memcpy(&dm18[i].result.device_result.inq_data,
&dm[i].result.device_result.inq_data,
sizeof(struct scsi_inquiry_data));
memcpy(&dm18[i].result.device_result.ident_data,
&dm[i].result.device_result.ident_data,
sizeof(struct ata_params));
dm18[i].result.device_result.flags =
dm[i].result.device_result.flags;
break;
case DEV_MATCH_BUS:
memcpy(&dm18[i].result.bus_result,
&dm[i].result.bus_result,
sizeof(struct bus_match_result));
break;
}
}
cam_periph_unmapmem(ccb, &mapinfo);
return (0);
}

View File

@ -65,7 +65,7 @@ struct ccb_hdr_0x17 {
struct cam_path *path; /* Compiled path for this ccb */
path_id_t path_id; /* Path ID for the request */
target_id_t target_id; /* Target device ID */
lun_id_t target_lun; /* Target LUN number */
u_int target_lun; /* Target LUN number */
u_int32_t flags; /* ccb_flags */
ccb_ppriv_area periph_priv;
ccb_spriv_area sim_priv;
@ -116,5 +116,64 @@ struct ccb_pathinq_0x17 {
#define CAMIOCOMMAND_0x17 _IOC(IOC_INOUT, CAM_VERSION_0x17, 2, CAM_0X17_LEN)
#define CAMGETPASSTHRU_0x17 _IOC(IOC_INOUT, CAM_VERSION_0x17, 3, CAM_0X17_LEN)
/* Version 0x18 compatibility */
#define CAM_VERSION_0x18 0x18
struct ccb_hdr_0x18 {
cam_pinfo pinfo; /* Info for priority scheduling */
camq_entry xpt_links; /* For chaining in the XPT layer */
camq_entry sim_links; /* For chaining in the SIM layer */
camq_entry periph_links; /* For chaining in the type driver */
u_int32_t retry_count;
void (*cbfcnp)(struct cam_periph *, union ccb *);
xpt_opcode func_code; /* XPT function code */
u_int32_t status; /* Status returned by CAM subsystem */
struct cam_path *path; /* Compiled path for this ccb */
path_id_t path_id; /* Path ID for the request */
target_id_t target_id; /* Target device ID */
u_int target_lun; /* Target LUN number */
u_int64_t ext_lun; /* 64-bit LUN, more or less */
u_int32_t flags; /* ccb_flags */
u_int32_t xflags; /* extended ccb_flags */
ccb_ppriv_area periph_priv;
ccb_spriv_area sim_priv;
ccb_qos_area qos;
u_int32_t timeout; /* Hard timeout value in seconds */
struct timeval softtimeout; /* Soft timeout value in sec + usec */
};
typedef enum {
CAM_EXTLUN_VALID_0x18 = 0x00000001,/* 64bit lun field is valid */
} ccb_xflags_0x18;
struct dev_match_result_0x18 {
dev_match_type type;
union {
struct {
char periph_name[DEV_IDLEN];
u_int32_t unit_number;
path_id_t path_id;
target_id_t target_id;
u_int target_lun;
} periph_result;
struct {
path_id_t path_id;
target_id_t target_id;
u_int target_lun;
cam_proto protocol;
struct scsi_inquiry_data inq_data;
struct ata_params ident_data;
dev_result_flags flags;
} device_result;
struct bus_match_result bus_result;
} result;
};
#define CAM_0X18_LEN (sizeof(union ccb) - sizeof(struct ccb_hdr) + sizeof(struct ccb_hdr_0x18))
#define CAM_0X18_DATA_LEN (sizeof(union ccb) - sizeof(struct ccb_hdr_0x18))
#define CAMIOCOMMAND_0x18 _IOC(IOC_INOUT, CAM_VERSION_0x18, 2, CAM_0X18_LEN)
#define CAMGETPASSTHRU_0x18 _IOC(IOC_INOUT, CAM_VERSION_0x18, 3, CAM_0X18_LEN)
#endif
#endif

View File

@ -101,10 +101,8 @@ SYSCTL_PROC(_kern_cam, OID_AUTO, cam_srch_hi, CTLTYPE_INT|CTLFLAG_RW, 0, 0,
(lval) |= (lp)->luns[(i)].lundata[1]; \
}
#define CAM_GET_LUN(lp, i, lval) \
(lval) = scsi_4btoul((lp)->luns[(i)].lundata); \
(lval) = ((lval) >> 16) | ((lval) << 16);
#define CAM_LUN_ONLY_32BITS(lp, i) \
(scsi_4btoul(&((lp)->luns[(i)].lundata[4])) == 0)
(lval) = scsi_8btou64((lp)->luns[(i)].lundata); \
(lval) = CAM_EXTLUN_BYTE_SWIZZLE(lval);
/*
* If we're not quirked to search <= the first 8 luns
@ -1766,8 +1764,6 @@ probe_purge_old(struct cam_path *path, struct scsi_report_luns_data *new,
continue;
CAM_GET_SIMPLE_LUN(old, idx1, this_lun);
}
if (!CAM_LUN_ONLY_32BITS(old, idx1))
continue;
if (xpt_create_path(&tp, NULL, xpt_path_path_id(path),
xpt_path_target_id(path), this_lun) == CAM_REQ_CMP) {
@ -2038,10 +2034,6 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
break;
}
/* XXX print warning? */
if (!CAM_LUN_ONLY_32BITS(target->luns,
scan_info->lunindex[target_id]))
continue;
if (CAM_CAN_GET_SIMPLE_LUN(target->luns,
scan_info->lunindex[target_id])) {
CAM_GET_SIMPLE_LUN(target->luns,