Move protocol specific stuff into a linker set object that's

per-protocol. This reduces the number scsi symbols references by
cam_xpt significantly, and eliminates all ata / nvme symbols. There's
still some NVME / ATA specific code for dealing with XPT_NVME_IO and
XPT_ATA_IO respectively, and a bunch of scsi-specific code, but this
is progress.

Differential Revision: https://reviews.freebsd.org/D7289
This commit is contained in:
Warner Losh 2016-07-28 22:55:21 +00:00
parent ded2b70617
commit 08f1387933
6 changed files with 219 additions and 52 deletions

View File

@ -188,6 +188,11 @@ static void ata_dev_async(u_int32_t async_code,
void *async_arg);
static void ata_action(union ccb *start_ccb);
static void ata_announce_periph(struct cam_periph *periph);
static void ata_proto_announce(struct cam_ed *device);
static void ata_proto_denounce(struct cam_ed *device);
static void ata_proto_debug_out(union ccb *ccb);
static void semb_proto_announce(struct cam_ed *device);
static void semb_proto_denounce(struct cam_ed *device);
static int ata_dma = 1;
static int atapi_dma = 1;
@ -214,6 +219,43 @@ ATA_XPT_XPORT(sata, SATA);
#undef ATA_XPORT_XPORT
static struct xpt_proto_ops ata_proto_ops_ata = {
.announce = ata_proto_announce,
.denounce = ata_proto_denounce,
.debug_out = ata_proto_debug_out,
};
static struct xpt_proto ata_proto_ata = {
.proto = PROTO_ATA,
.name = "ata",
.ops = &ata_proto_ops_ata,
};
static struct xpt_proto_ops ata_proto_ops_satapm = {
.announce = ata_proto_announce,
.denounce = ata_proto_denounce,
.debug_out = ata_proto_debug_out,
};
static struct xpt_proto ata_proto_satapm = {
.proto = PROTO_SATAPM,
.name = "satapm",
.ops = &ata_proto_ops_satapm,
};
static struct xpt_proto_ops ata_proto_ops_semb = {
.announce = semb_proto_announce,
.denounce = semb_proto_denounce,
.debug_out = ata_proto_debug_out,
};
static struct xpt_proto ata_proto_semb = {
.proto = PROTO_SEMB,
.name = "semb",
.ops = &ata_proto_ops_semb,
};
CAM_XPT_PROTO(ata_proto_ata);
CAM_XPT_PROTO(ata_proto_satapm);
CAM_XPT_PROTO(ata_proto_semb);
static void
probe_periph_init()
{
@ -2094,3 +2136,40 @@ ata_announce_periph(struct cam_periph *periph)
}
printf("\n");
}
static void
ata_proto_announce(struct cam_ed *device)
{
ata_print_ident(&device->ident_data);
}
static void
ata_proto_denounce(struct cam_ed *device)
{
ata_print_ident_short(&device->ident_data);
}
static void
semb_proto_announce(struct cam_ed *device)
{
semb_print_ident((struct sep_identify_data *)&device->ident_data);
}
static void
semb_proto_denounce(struct cam_ed *device)
{
semb_print_ident_short((struct sep_identify_data *)&device->ident_data);
}
static void
ata_proto_debug_out(union ccb *ccb)
{
char cdb_str[(sizeof(struct ata_cmd) * 3) + 1];
if (ccb->ccb_h.func_code != XPT_ATA_IO)
return;
CAM_DEBUG(ccb->ccb_h.path,
CAM_DEBUG_CDB,("%s. ACB: %s\n", ata_op_string(&ccb->ataio.cmd),
ata_cmd_string(&ccb->ataio.cmd, cdb_str, sizeof(cdb_str))));
}

View File

@ -746,6 +746,19 @@ cam_module_event_handler(module_t mod, int what, void *arg)
return 0;
}
static struct xpt_proto *
xpt_proto_find(cam_proto proto)
{
struct xpt_proto **pp;
SET_FOREACH(pp, cam_xpt_proto_set) {
if ((*pp)->proto == proto)
return *pp;
}
return NULL;
}
static void
xpt_rescan_done(struct cam_periph *periph, union ccb *done_ccb)
{
@ -1012,6 +1025,7 @@ void
xpt_announce_periph(struct cam_periph *periph, char *announce_string)
{
struct cam_path *path = periph->path;
struct xpt_proto *proto;
cam_periph_assert(periph, MA_OWNED);
periph->flags |= CAM_PERIPH_ANNOUNCED;
@ -1025,25 +1039,20 @@ xpt_announce_periph(struct cam_periph *periph, char *announce_string)
path->target->target_id,
(uintmax_t)path->device->lun_id);
printf("%s%d: ", periph->periph_name, periph->unit_number);
if (path->device->protocol == PROTO_SCSI)
scsi_print_inquiry(&path->device->inq_data);
else if (path->device->protocol == PROTO_ATA ||
path->device->protocol == PROTO_SATAPM)
ata_print_ident(&path->device->ident_data);
else if (path->device->protocol == PROTO_SEMB)
semb_print_ident(
(struct sep_identify_data *)&path->device->ident_data);
else if (path->device->protocol == PROTO_NVME)
nvme_print_ident(path->device->nvme_cdata, path->device->nvme_data);
proto = xpt_proto_find(path->device->protocol);
if (proto)
proto->ops->announce(path->device);
else
printf("Unknown protocol device\n");
printf("%s%d: Unknown protocol device %d\n",
periph->periph_name, periph->unit_number,
path->device->protocol);
if (path->device->serial_num_len > 0) {
/* Don't wrap the screen - print only the first 60 chars */
printf("%s%d: Serial Number %.60s\n", periph->periph_name,
periph->unit_number, path->device->serial_num);
}
/* Announce transport details. */
(*(path->bus->xport->ops->announce))(periph);
path->bus->xport->ops->announce(periph);
/* Announce command queueing. */
if (path->device->inq_flags & SID_CmdQue
|| path->device->flags & CAM_DEV_TAG_AFTER_COUNT) {
@ -1069,6 +1078,7 @@ void
xpt_denounce_periph(struct cam_periph *periph)
{
struct cam_path *path = periph->path;
struct xpt_proto *proto;
cam_periph_assert(periph, MA_OWNED);
printf("%s%d at %s%d bus %d scbus%d target %d lun %jx\n",
@ -1080,18 +1090,13 @@ xpt_denounce_periph(struct cam_periph *periph)
path->target->target_id,
(uintmax_t)path->device->lun_id);
printf("%s%d: ", periph->periph_name, periph->unit_number);
if (path->device->protocol == PROTO_SCSI)
scsi_print_inquiry_short(&path->device->inq_data);
else if (path->device->protocol == PROTO_ATA ||
path->device->protocol == PROTO_SATAPM)
ata_print_ident_short(&path->device->ident_data);
else if (path->device->protocol == PROTO_SEMB)
semb_print_ident_short(
(struct sep_identify_data *)&path->device->ident_data);
else if (path->device->protocol == PROTO_NVME)
nvme_print_ident(path->device->nvme_cdata, path->device->nvme_data);
proto = xpt_proto_find(path->device->protocol);
if (proto)
proto->ops->denounce(path->device);
else
printf("Unknown protocol device");
printf("%s%d: Unknown protocol device %d\n",
periph->periph_name, periph->unit_number,
path->device->protocol);
if (path->device->serial_num_len > 0)
printf(" s/n %.60s", path->device->serial_num);
printf(" detached\n");
@ -3234,7 +3239,6 @@ xpt_run_allocq(struct cam_periph *periph, int sleep)
static void
xpt_run_devq(struct cam_devq *devq)
{
char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
int lock;
CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_devq\n"));
@ -3246,6 +3250,7 @@ xpt_run_devq(struct cam_devq *devq)
struct cam_ed *device;
union ccb *work_ccb;
struct cam_sim *sim;
struct xpt_proto *proto;
device = (struct cam_ed *)camq_remove(&devq->send_queue,
CAMQ_HEAD);
@ -3311,32 +3316,12 @@ xpt_run_devq(struct cam_devq *devq)
work_ccb->ccb_h.flags &= ~CAM_TAG_ACTION_VALID;
}
switch (work_ccb->ccb_h.func_code) {
case XPT_SCSI_IO:
CAM_DEBUG(work_ccb->ccb_h.path,
CAM_DEBUG_CDB,("%s. CDB: %s\n",
scsi_op_desc(work_ccb->csio.cdb_io.cdb_bytes[0],
&device->inq_data),
scsi_cdb_string(work_ccb->csio.cdb_io.cdb_bytes,
cdb_str, sizeof(cdb_str))));
break;
case XPT_ATA_IO:
CAM_DEBUG(work_ccb->ccb_h.path,
CAM_DEBUG_CDB,("%s. ACB: %s\n",
ata_op_string(&work_ccb->ataio.cmd),
ata_cmd_string(&work_ccb->ataio.cmd,
cdb_str, sizeof(cdb_str))));
break;
case XPT_NVME_IO:
CAM_DEBUG(work_ccb->ccb_h.path,
CAM_DEBUG_CDB,("%s. NCB: %s\n",
nvme_op_string(&work_ccb->nvmeio.cmd),
nvme_cmd_string(&work_ccb->nvmeio.cmd,
cdb_str, sizeof(cdb_str))));
break;
default:
break;
}
KASSERT(device == work_ccb->ccb_h.path->device,
("device (%p) / path->device (%p) mismatch",
device, work_ccb->ccb_h.path->device));
proto = xpt_proto_find(device->protocol);
if (proto && proto->ops->debug_out)
proto->ops->debug_out(work_ccb);
/*
* Device queues can be shared among multiple SIM instances

View File

@ -66,6 +66,26 @@ SET_DECLARE(cam_xpt_xport_set, struct xpt_xport);
#define CAM_XPT_XPORT(data) \
DATA_SET(cam_xpt_xport_set, data)
typedef void (*xpt_proto_announce_func)(struct cam_ed *);
typedef void (*xpt_proto_debug_out_func)(union ccb *);
struct xpt_proto_ops {
xpt_proto_announce_func announce;
xpt_proto_announce_func denounce;
xpt_proto_debug_out_func debug_out;
};
struct xpt_proto {
cam_proto proto;
const char *name;
struct xpt_proto_ops *ops;
};
SET_DECLARE(cam_xpt_proto_set, struct xpt_proto);
#define CAM_XPT_PROTO(data) \
DATA_SET(cam_xpt_proto_set, data)
/*
* The CAM EDT (Existing Device Table) contains the device information for
* all devices for all busses in the system. The table contains a

View File

@ -152,6 +152,9 @@ static void nvme_dev_async(u_int32_t async_code,
void *async_arg);
static void nvme_action(union ccb *start_ccb);
static void nvme_announce_periph(struct cam_periph *periph);
static void nvme_proto_announce(struct cam_ed *device);
static void nvme_proto_denounce(struct cam_ed *device);
static void nvme_proto_debug_out(union ccb *ccb);
static struct xpt_xport_ops nvme_xport_ops = {
.alloc_device = nvme_alloc_device,
@ -171,6 +174,18 @@ NVME_XPT_XPORT(nvme, NVME);
#undef NVME_XPT_XPORT
static struct xpt_proto_ops nvme_proto_ops = {
.announce = nvme_proto_announce,
.denounce = nvme_proto_denounce,
.debug_out = nvme_proto_debug_out,
};
static struct xpt_proto nvme_proto = {
.proto = PROTO_NVME,
.name = "nvme",
.ops = &nvme_proto_ops,
};
CAM_XPT_PROTO(nvme_proto);
static void
nvme_probe_periph_init()
{
@ -602,3 +617,29 @@ nvme_announce_periph(struct cam_periph *periph)
/* XXX NVME STUFF HERE */
printf("\n");
}
static void
nvme_proto_announce(struct cam_ed *device)
{
nvme_print_ident(device->nvme_cdata, device->nvme_data);
}
static void
nvme_proto_denounce(struct cam_ed *device)
{
nvme_print_ident(device->nvme_cdata, device->nvme_data);
}
static void
nvme_proto_debug_out(union ccb *ccb)
{
char cdb_str[(sizeof(struct nvme_command) * 3) + 1];
if (ccb->ccb_h.func_code != XPT_NVME_IO)
return;
CAM_DEBUG(ccb->ccb_h.path,
CAM_DEBUG_CDB,("%s. NCB: %s\n", nvme_op_string(&ccb->nvmeio.cmd),
nvme_cmd_string(&ccb->nvmeio.cmd, cdb_str, sizeof(cdb_str))));
}

View File

@ -589,6 +589,9 @@ static void scsi_dev_async(u_int32_t async_code,
void *async_arg);
static void scsi_action(union ccb *start_ccb);
static void scsi_announce_periph(struct cam_periph *periph);
static void scsi_proto_announce(struct cam_ed *device);
static void scsi_proto_denounce(struct cam_ed *device);
static void scsi_proto_debug_out(union ccb *ccb);
static struct xpt_xport_ops scsi_xport_ops = {
.alloc_device = scsi_alloc_device,
@ -614,6 +617,18 @@ SCSI_XPT_XPORT(ppb, PPB);
#undef SCSI_XPORT_XPORT
static struct xpt_proto_ops scsi_proto_ops = {
.announce = scsi_proto_announce,
.denounce = scsi_proto_denounce,
.debug_out = scsi_proto_debug_out,
};
static struct xpt_proto scsi_proto = {
.proto = PROTO_SCSI,
.name = "scsi",
.ops = &scsi_proto_ops,
};
CAM_XPT_PROTO(scsi_proto);
static void
probe_periph_init()
{
@ -3100,3 +3115,30 @@ scsi_announce_periph(struct cam_periph *periph)
printf("\n");
}
static void
scsi_proto_announce(struct cam_ed *device)
{
scsi_print_inquiry(&device->inq_data);
}
static void
scsi_proto_denounce(struct cam_ed *device)
{
scsi_print_inquiry_short(&device->inq_data);
}
static void
scsi_proto_debug_out(union ccb *ccb)
{
char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
struct cam_ed *device;
if (ccb->ccb_h.func_code != XPT_SCSI_IO)
return;
device = ccb->ccb_h.path->device;
CAM_DEBUG(ccb->ccb_h.path,
CAM_DEBUG_CDB,("%s. CDB: %s\n",
scsi_op_desc(ccb->csio.cdb_io.cdb_bytes[0], &device->inq_data),
scsi_cdb_string(ccb->csio.cdb_io.cdb_bytes, cdb_str, sizeof(cdb_str))));
}

View File

@ -86,9 +86,9 @@ cam/cam_xpt.c optional scbus
cam/ata/ata_all.c optional scbus
cam/ata/ata_xpt.c optional scbus
cam/ata/ata_pmp.c optional scbus
cam/nvme/nvme_all.c optional scbus
cam/nvme/nvme_all.c optional scbus nvmd !nvd
cam/nvme/nvme_da.c optional scbus nvme da !nvd
cam/nvme/nvme_xpt.c optional scbus
cam/nvme/nvme_xpt.c optional scbus nvmd !nvd
cam/scsi/scsi_xpt.c optional scbus
cam/scsi/scsi_all.c optional scbus
cam/scsi/scsi_cd.c optional cd