summaryrefslogtreecommitdiffstats
path: root/sys/cam/scsi/scsi_xpt.c
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>2011-06-14 14:53:17 +0000
committergibbs <gibbs@FreeBSD.org>2011-06-14 14:53:17 +0000
commit19d8ec29e28e58cef157c30a2f54c482dc840241 (patch)
treed9c9817bd94776da1147e878d4d36db265371c63 /sys/cam/scsi/scsi_xpt.c
parenta060389e5b178c7324442c0723886c8fda798998 (diff)
downloadFreeBSD-src-19d8ec29e28e58cef157c30a2f54c482dc840241.zip
FreeBSD-src-19d8ec29e28e58cef157c30a2f54c482dc840241.tar.gz
Lay groundwork in CAM for recording and reporting physical path and
other device attributes stored in the CAM Existing Device Table (EDT). This includes some infrastructure requried by the enclosure services driver to export physical path information. Make the CAM device advanced info interface accept store requests. sys/cam/scsi/scsi_all.c: sys/cam/scsi/scsi_all.h: - Replace scsi_get_sas_addr() with a scsi_get_devid() which takes a callback that decides whether to accept a particular descriptor. Provide callbacks for NAA IEEE Registered addresses and for SAS addresses, replacing the old function. This is needed because the old function doesn't work for an enclosure address for a SAS device, which is not flagged as a SAS address, but is NAA IEEE Registered. It may be worthwhile merging this interface with the devid match interface. - Add a few more defines for some device ID fields. sbin/camcontrol/camcontrol.c: - Update for the CCB_DEV_ADVINFO interface change. cam/cam_xpt_internal.h: - Add the new fields for the physical path string to the CAM EDT. cam/cam_ccb.h: - Rename CCB_GDEV_ADVINFO to simply CCB_DEV_ADVINFO, and the ccb structure to ccb_dev_advinfo. - Add a flag that changes this CCB's action to store, rather than the default, retrieve. - Add a new buffer type, CDAI_TYPE_PHYS_PATH, for the new CAM EDT physpath field. - Remove the never-implemented transport & proto flags. cam/cam_xpt.c: cam/cam_xpt.h: - Add xpt_getattr(), which provides a wrapper for fetching a device's attribute using the GEOM strings as key. This method currently supports "GEOM::ident" and "GEOM::physpath". Submitted by: will Reviewed by : gibbs Extend the XPT_DEV_MATCH api to allow a device search by device ID. As far as the API is concerned, device ID is a binary blob to be interpreted by the transport layer. The SCSI implementation assumes it is an array of VPD device ID descriptors. sys/cam/cam_ccb.h: Create a new structure, device_id_match_pattern, and update the XPT_DEV_MATCH datastructures and flags so that this pattern type can be used. sys/cam/cam_xpt.c: - A single pattern matching on both inquiry data and device ID is invalid. Report any violators. - Pass device ID match requests through to the new routine scsi_devid_match(). The direct call of a SCSI routine is a layering violation, but no worse than the one a few lines up that checks inquiry data. Defer cleaning this up until our future, larger, rototilling of CAM. - Zero out cam_ed and cam_et nodes on allocation. Prior to this change, device_id_len and device_id were not inialized, preventing proper detection of the presence of this information. sys/cam/scsi/scsi_all.c: sys/cam/scsi/scsi_all.h: Add the scsi_match_devid() routine. Add a helper function for extracting peripherial driver names sys/cam/cam_periph.c: sys/cam/cam_periph.h: Add the cam_periph_list() method which fills an sbuf with a comma delimited list of the peripheral instances associated with a given CAM path. Add a helper functions for SCSI commands used by the SES driver. sys/cam/scsi/scsi_all.c: sys/cam/scsi/scsi_all.h: Add structure definitions and csio filling functions for the receive diagnostic results and send diagnostic commands. Misc CAM XPT cleanups. sys/cam/cam_xpt.c: Broadcast AC_FOUND_DEVICE and AC_PATH_REGISTERED events at the time async event handlers are attached even when registering just for events on a partitular SIM. Previously, you had to register for these events on all SIMs in the system in order to get the initial broadcast even though subsequent device and path arrivals would be delivered. sys/cam/cam_xpt.c: Remove SIM mutex held asserts from path accessors. CAM paths are reference counted and it is this reference count, not the sim mutex, that garantees they are stable. Sponsored by: Spectra Logic Corporation
Diffstat (limited to 'sys/cam/scsi/scsi_xpt.c')
-rw-r--r--sys/cam/scsi/scsi_xpt.c80
1 files changed, 65 insertions, 15 deletions
diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c
index 2a38128..1b507ca 100644
--- a/sys/cam/scsi/scsi_xpt.c
+++ b/sys/cam/scsi/scsi_xpt.c
@@ -542,6 +542,7 @@ static const int scsi_quirk_table_size =
static cam_status proberegister(struct cam_periph *periph,
void *arg);
static void probeschedule(struct cam_periph *probe_periph);
+static int device_has_vpd(struct cam_ed *device, uint8_t page_id);
static void probestart(struct cam_periph *periph, union ccb *start_ccb);
static void proberequestdefaultnegotiation(struct cam_periph *periph);
static int proberequestbackoff(struct cam_periph *periph,
@@ -1460,7 +1461,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
path->device->device_id = (uint8_t *)devid;
}
} else if (cam_periph_error(done_ccb, 0,
- SF_RETRY_UA|SF_NO_PRINT,
+ SF_RETRY_UA,
&softc->saved_ccb) == ERESTART) {
return;
} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
@@ -1506,9 +1507,9 @@ probe_device_check:
(u_int8_t *)malloc((serial_buf->length + 1),
M_CAMXPT, M_NOWAIT);
if (path->device->serial_num != NULL) {
- bcopy(serial_buf->serial_num,
- path->device->serial_num,
- serial_buf->length);
+ memcpy(path->device->serial_num,
+ serial_buf->serial_num,
+ serial_buf->length);
path->device->serial_num_len =
serial_buf->length;
path->device->serial_num[serial_buf->length]
@@ -2433,28 +2434,77 @@ scsi_devise_transport(struct cam_path *path)
}
static void
-scsi_getdev_advinfo(union ccb *start_ccb)
+scsi_dev_advinfo(union ccb *start_ccb)
{
struct cam_ed *device;
- struct ccb_getdev_advinfo *cgdai;
+ struct ccb_dev_advinfo *cdai;
off_t amt;
device = start_ccb->ccb_h.path->device;
- cgdai = &start_ccb->cgdai;
- switch(cgdai->buftype) {
- case CGDAI_TYPE_SCSI_DEVID:
- cgdai->provsiz = device->device_id_len;
+ cdai = &start_ccb->cdai;
+ switch(cdai->buftype) {
+ case CDAI_TYPE_SCSI_DEVID:
+ if (cdai->flags & CDAI_FLAG_STORE)
+ break;
+ cdai->provsiz = device->device_id_len;
if (device->device_id_len == 0)
break;
amt = device->device_id_len;
- if (cgdai->provsiz > cgdai->bufsiz)
- amt = cgdai->bufsiz;
- bcopy(device->device_id, cgdai->buf, amt);
+ if (cdai->provsiz > cdai->bufsiz)
+ amt = cdai->bufsiz;
+ memcpy(cdai->buf, device->device_id, amt);
+ break;
+ case CDAI_TYPE_SERIAL_NUM:
+ if (cdai->flags & CDAI_FLAG_STORE)
+ break;
+ cdai->provsiz = device->serial_num_len;
+ if (device->serial_num_len == 0)
+ break;
+ amt = device->serial_num_len;
+ if (cdai->provsiz > cdai->bufsiz)
+ amt = cdai->bufsiz;
+ memcpy(cdai->buf, device->serial_num, amt);
+ break;
+ case CDAI_TYPE_PHYS_PATH:
+ if (cdai->flags & CDAI_FLAG_STORE) {
+ if (device->physpath != NULL)
+ free(device->physpath, M_CAMXPT);
+ device->physpath_len = cdai->bufsiz;
+ /* Clear existing buffer if zero length */
+ if (cdai->bufsiz == 0)
+ break;
+ device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT);
+ if (device->physpath == NULL) {
+ start_ccb->ccb_h.status = CAM_REQ_ABORTED;
+ return;
+ }
+ memcpy(device->physpath, cdai->buf, cdai->bufsiz);
+ } else {
+ cdai->provsiz = device->physpath_len;
+ if (device->physpath_len == 0)
+ break;
+ amt = device->physpath_len;
+ if (cdai->provsiz > cdai->bufsiz)
+ amt = cdai->bufsiz;
+ memcpy(cdai->buf, device->physpath, amt);
+ }
break;
default:
break;
}
start_ccb->ccb_h.status = CAM_REQ_CMP;
+
+ if (cdai->flags & CDAI_FLAG_STORE) {
+ int owned;
+
+ owned = mtx_owned(start_ccb->ccb_h.path->bus->sim->mtx);
+ if (owned == 0)
+ mtx_lock(start_ccb->ccb_h.path->bus->sim->mtx);
+ xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path,
+ (void *)(uintptr_t)cdai->buftype);
+ if (owned == 0)
+ mtx_unlock(start_ccb->ccb_h.path->bus->sim->mtx);
+ }
}
static void
@@ -2486,9 +2536,9 @@ scsi_action(union ccb *start_ccb)
(*(sim->sim_action))(sim, start_ccb);
break;
}
- case XPT_GDEV_ADVINFO:
+ case XPT_DEV_ADVINFO:
{
- scsi_getdev_advinfo(start_ccb);
+ scsi_dev_advinfo(start_ccb);
break;
}
default:
OpenPOWER on IntegriCloud