Index: sys/cam/cam.h =================================================================== --- sys/cam/cam.h (revision 256369) +++ sys/cam/cam.h (working copy) @@ -50,6 +50,12 @@ #define CAM_TARGET_WILDCARD ((target_id_t)~0) #define CAM_LUN_WILDCARD ((lun_id_t)~0) +#define CAM_EXTLUN_BYTE_SWIZZLE(lun) ( \ + ((((u_int64_t)lun) & 0xffff000000000000L) >> 48) | \ + ((((u_int64_t)lun) & 0x0000ffff00000000L) >> 16) | \ + ((((u_int64_t)lun) & 0x00000000ffff0000L) << 16) | \ + ((((u_int64_t)lun) & 0x000000000000ffffL) << 48)) + /* * Maximum length for a CAM CDB. */ Index: sys/cam/scsi/scsi_xpt.c =================================================================== --- sys/cam/scsi/scsi_xpt.c (revision 256369) +++ sys/cam/scsi/scsi_xpt.c (working copy) @@ -100,6 +100,12 @@ (lval) <<= 8; \ (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) + /* * If we're not quirked to search <= the first 8 luns * and we are either quirked to search above lun 8, @@ -175,7 +181,8 @@ typedef enum { PROBE_INQUIRY_CKSUM = 0x01, PROBE_SERIAL_CKSUM = 0x02, - PROBE_NO_ANNOUNCE = 0x04 + PROBE_NO_ANNOUNCE = 0x04, + PROBE_EXTLUN = 0x08 } probe_flags; typedef struct { @@ -561,10 +568,9 @@ static int proberequestbackoff(struct cam_periph *periph, struct cam_ed *device); static void probedone(struct cam_periph *periph, union ccb *done_ccb); -static int probe_strange_rpl_data(struct scsi_report_luns_data *rp, - uint32_t maxlun); static void probe_purge_old(struct cam_path *path, - struct scsi_report_luns_data *new); + struct scsi_report_luns_data *new, + probe_flags flags); static void probecleanup(struct cam_periph *periph); static void scsi_find_quirk(struct cam_ed *device); static void scsi_scan_bus(struct cam_periph *periph, union ccb *ccb); @@ -699,6 +705,11 @@ else softc->flags &= ~PROBE_NO_ANNOUNCE; + if (cpi.hba_misc & PIM_EXTLUNS) + softc->flags |= PROBE_EXTLUN; + else + softc->flags &= ~PROBE_EXTLUN; + xpt_schedule(periph, CAM_PRIORITY_XPT); } @@ -1277,13 +1288,6 @@ */ free(lp, M_CAMXPT); lp = NULL; - } else if (probe_strange_rpl_data(lp, maxlun)) { - /* - * If we can't understand the lun format - * of any entry, bail. - */ - free(lp, M_CAMXPT); - lp = NULL; } else { lun_id_t lun; int idx; @@ -1291,7 +1295,7 @@ CAM_DEBUG(path, CAM_DEBUG_PROBE, ("Probe: %u lun(s) reported\n", nlun)); - CAM_GET_SIMPLE_LUN(lp, 0, lun); + CAM_GET_LUN(lp, 0, lun); /* * If the first lun is not lun 0, then either there * is no lun 0 in the list, or the list is unsorted. @@ -1298,7 +1302,7 @@ */ if (lun != 0) { for (idx = 0; idx < nlun; idx++) { - CAM_GET_SIMPLE_LUN(lp, idx, lun); + CAM_GET_LUN(lp, idx, lun); if (lun == 0) { break; } @@ -1330,7 +1334,7 @@ * This function will also install the new list * in the target structure. */ - probe_purge_old(path, lp); + probe_purge_old(path, lp, softc->flags); lp = NULL; } if (path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) { @@ -1702,26 +1706,14 @@ } } -static int -probe_strange_rpl_data(struct scsi_report_luns_data *rp, uint32_t maxlun) -{ - uint32_t idx; - uint32_t nlun = MIN(maxlun, (scsi_4btoul(rp->length) / 8)); - - for (idx = 0; idx < nlun; idx++) { - if (!CAM_CAN_GET_SIMPLE_LUN(rp, idx)) { - return (-1); - } - } - return (0); -} - static void -probe_purge_old(struct cam_path *path, struct scsi_report_luns_data *new) +probe_purge_old(struct cam_path *path, struct scsi_report_luns_data *new, + probe_flags flags) { struct cam_path *tp; struct scsi_report_luns_data *old; - u_int idx1, idx2, nlun_old, nlun_new, this_lun; + u_int idx1, idx2, nlun_old, nlun_new; + lun_id_t this_lun; u_int8_t *ol, *nl; if (path->target == NULL) { @@ -1755,17 +1747,26 @@ * that would be what the probe state * machine is currently working on, * so we won't do that. - * - * We also cannot nuke it if it is - * not in a lun format we understand. */ - if (!CAM_CAN_GET_SIMPLE_LUN(old, idx1)) { + CAM_GET_LUN(old, idx1, this_lun); + if (this_lun == 0) { continue; } - CAM_GET_SIMPLE_LUN(old, idx1, this_lun); - if (this_lun == 0) { + + /* + * We also cannot nuke it if it is + * not in a lun format we understand + * and replace the LUN with a "simple" LUN + * if that is all the HBA supports. + */ + if (!(flags & PROBE_EXTLUN)) { + if (!CAM_CAN_GET_SIMPLE_LUN(old, idx1)) + 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) { xpt_async(AC_LOST_DEVICE, tp, NULL); @@ -2001,7 +2002,7 @@ next_target = 1; if (target->luns) { - uint32_t first; + lun_id_t first; u_int nluns = scsi_4btoul(target->luns->length) / 8; /* @@ -2009,19 +2010,44 @@ * of the list as we've actually just finished probing * it. */ - CAM_GET_SIMPLE_LUN(target->luns, 0, first); + CAM_GET_LUN(target->luns, 0, first); if (first == 0 && scan_info->lunindex[target_id] == 0) { scan_info->lunindex[target_id]++; } + /* + * Skip any LUNs that the HBA can't deal with. + */ + while (scan_info->lunindex[target_id] < nluns) { + if (scan_info->cpi->hba_misc & PIM_EXTLUNS) { + CAM_GET_LUN(target->luns, + scan_info->lunindex[target_id], + lun_id); + 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, + scan_info->lunindex[target_id], + lun_id); + break; + } + + scan_info->lunindex[target_id]++; + } + if (scan_info->lunindex[target_id] < nluns) { - CAM_GET_SIMPLE_LUN(target->luns, - scan_info->lunindex[target_id], lun_id); next_target = 0; CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_PROBE, - ("next lun to try at index %u is %u\n", - scan_info->lunindex[target_id], lun_id)); + ("next lun to try at index %u is %jx\n", + scan_info->lunindex[target_id], + (uintmax_t)lun_id)); scan_info->lunindex[target_id]++; } else { /* Index: sys/powerpc/pseries/phyp_vscsi.c =================================================================== --- sys/powerpc/pseries/phyp_vscsi.c (revision 256369) +++ sys/powerpc/pseries/phyp_vscsi.c (working copy) @@ -548,12 +548,6 @@ TAILQ_REMOVE(&sc->free_xferq, xp, queue); TAILQ_INSERT_TAIL(&sc->active_xferq, xp, queue); - if (!(ccb->ccb_h.xflags & CAM_EXTLUN_VALID)) { - ccb->ccb_h.xflags |= CAM_EXTLUN_VALID; - ccb->ccb_h.ext_lun.lun64 = (0x1UL << 62) | - ((uint64_t)ccb->ccb_h.target_lun << 48); - } - xp->srp_iu_size = crq.iu_length = sizeof(*cmd); err = vmem_alloc(xp->sc->srp_iu_arena, xp->srp_iu_size, M_BESTFIT | M_NOWAIT, &xp->srp_iu_offset); @@ -565,7 +559,7 @@ bzero(cmd, xp->srp_iu_size); cmd->type = SRP_TSK_MGMT; cmd->tag = (uint64_t)xp; - cmd->lun = ccb->ccb_h.ext_lun.lun64; + cmd->lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun)); switch (ccb->ccb_h.func_code) { case XPT_RESET_DEV: @@ -608,12 +602,6 @@ cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ? ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes; - if (!(ccb->ccb_h.xflags & CAM_EXTLUN_VALID)) { - ccb->ccb_h.xflags |= CAM_EXTLUN_VALID; - ccb->ccb_h.ext_lun.lun64 = (0x1UL << 62) | - ((uint64_t)ccb->ccb_h.target_lun << 48); - } - /* Command format from Table 20, page 37 of SRP spec */ crq.iu_length = 48 + ((nsegs > 1) ? 20 : 16) + ((ccb->csio.cdb_len > 16) ? (ccb->csio.cdb_len - 16) : 0); @@ -635,7 +623,7 @@ memcpy(cmd->cdb, cdb, ccb->csio.cdb_len); cmd->tag = (uint64_t)(xp); /* Let the responder find this again */ - cmd->lun = ccb->ccb_h.ext_lun.lun64; + cmd->lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun)); if (nsegs > 1) { /* Use indirect descriptors */