Index: sys/cam/cam_ccb.h =================================================================== --- sys/cam/cam_ccb.h +++ sys/cam/cam_ccb.h @@ -341,7 +341,8 @@ 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; + u_int16_t retry_count; + u_int16_t allocated_len; void (*cbfcnp)(struct cam_periph *, union ccb *); /* Callback on completion function */ xpt_opcode func_code; /* XPT function code */ @@ -736,8 +737,6 @@ */ struct ccb_scsiio { struct ccb_hdr ccb_h; - union ccb *next_ccb; /* Ptr for next CCB for action */ - u_int8_t *req_map; /* Ptr to mapping info */ u_int8_t *data_ptr; /* Ptr to the data buf/SG list */ u_int32_t dxfer_len; /* Data transfer length */ /* Autosense storage */ @@ -747,10 +746,6 @@ u_int16_t sglist_cnt; /* Number of SG list entries */ u_int8_t scsi_status; /* Returned SCSI status */ u_int8_t sense_resid; /* Autosense resid length: 2's comp */ - u_int32_t resid; /* Transfer residual length: 2's comp */ - cdb_t cdb_io; /* Union for CDB bytes/pointer */ - u_int8_t *msg_ptr; /* Pointer to the message buffer */ - u_int16_t msg_len; /* Number of bytes for the Message */ u_int8_t tag_action; /* What to do for tag queueing */ /* * The tag action should be either the define below (to send a @@ -759,6 +754,9 @@ */ #define CAM_TAG_ACTION_NONE 0x00 uint8_t priority; /* Command priority for SIMPLE tag */ + u_int8_t *msg_ptr; /* Pointer to the message buffer */ + u_int32_t resid; /* Transfer residual length: 2's comp */ + cdb_t cdb_io; /* Union for CDB bytes/pointer */ u_int tag_id; /* tag id from initator (target mode) */ u_int init_id; /* initiator id of who selected */ #if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) @@ -913,11 +911,6 @@ union ccb *abort_ccb; /* Pointer to CCB to abort */ }; -/* Reset SCSI Bus CCB */ -struct ccb_resetbus { - struct ccb_hdr ccb_h; -}; - /* Reset SCSI Device CCB */ struct ccb_resetdev { struct ccb_hdr ccb_h; @@ -1205,12 +1198,6 @@ u_int8_t message_args[7]; /* Message Arguments */ }; -struct ccb_notify_ack { - struct ccb_hdr ccb_h; - u_int16_t seq_id; /* Sequence identifier */ - u_int8_t event; /* Event flags */ -}; - struct ccb_immediate_notify { struct ccb_hdr ccb_h; u_int tag_id; /* Tag for immediate notify */ @@ -1253,30 +1240,6 @@ EAD_LZ2V2 /* Engine algorithm ID: LZ2 var.2 */ } ei_algo; -struct ccb_eng_inq { - struct ccb_hdr ccb_h; - u_int16_t eng_num; /* The engine number for this inquiry */ - ei_type eng_type; /* Returned engine type */ - ei_algo eng_algo; /* Returned engine algorithm type */ - u_int32_t eng_memeory; /* Returned engine memory size */ -}; - -struct ccb_eng_exec { /* This structure must match SCSIIO size */ - struct ccb_hdr ccb_h; - u_int8_t *pdrv_ptr; /* Ptr used by the peripheral driver */ - u_int8_t *req_map; /* Ptr for mapping info on the req. */ - u_int8_t *data_ptr; /* Pointer to the data buf/SG list */ - u_int32_t dxfer_len; /* Data transfer length */ - u_int8_t *engdata_ptr; /* Pointer to the engine buffer data */ - u_int16_t sglist_cnt; /* Num of scatter gather list entries */ - u_int32_t dmax_len; /* Destination data maximum length */ - u_int32_t dest_len; /* Destination data length */ - int32_t src_resid; /* Source residual length: 2's comp */ - u_int32_t timeout; /* Timeout value */ - u_int16_t eng_num; /* Engine number for this request */ - u_int16_t vu_flags; /* Vendor Unique flags */ -}; - /* * Definitions for the timeout field in the SCSI I/O CCB. */ @@ -1350,18 +1313,14 @@ struct ccb_calc_geometry ccg; struct ccb_sim_knob knob; struct ccb_abort cab; - struct ccb_resetbus crb; struct ccb_resetdev crd; struct ccb_termio tio; struct ccb_accept_tio atio; struct ccb_scsiio ctio; struct ccb_en_lun cel; struct ccb_immed_notify cin; - struct ccb_notify_ack cna; struct ccb_immediate_notify cin1; struct ccb_notify_acknowledge cna2; - struct ccb_eng_inq cei; - struct ccb_eng_exec cee; struct ccb_smpio smpio; struct ccb_rescan crcn; struct ccb_debug cdbg; Index: sys/cam/cam_periph.h =================================================================== --- sys/cam/cam_periph.h +++ sys/cam/cam_periph.h @@ -147,6 +147,7 @@ ac_callback_t *deferred_callback; ac_code deferred_ac; struct task periph_run_task; + size_t small_ccb_len; }; #define CAM_PERIPH_MAXMAPS 2 Index: sys/cam/cam_periph.c =================================================================== --- sys/cam/cam_periph.c +++ sys/cam/cam_periph.c @@ -745,6 +745,7 @@ union ccb ccb; void *arg; + memset(&ccb, 0, sizeof(ccb)); switch (periph->deferred_ac) { case AC_FOUND_DEVICE: ccb.ccb_h.func_code = XPT_GDEV_TYPE; @@ -1314,6 +1315,7 @@ struct ccb_hdr ccb_h; CAM_DEBUG(path, CAM_DEBUG_TRACE, ("cam_freeze_devq\n")); + memset(&ccb_h, 0, sizeof(ccb_h)); xpt_setup_ccb(&ccb_h, path, /*priority*/1); ccb_h.func_code = XPT_NOOP; ccb_h.flags = CAM_DEV_QFREEZE; @@ -1329,6 +1331,7 @@ CAM_DEBUG(path, CAM_DEBUG_TRACE, ("cam_release_devq(%u, %u, %u, %d)\n", relsim_flags, openings, arg, getcount_only)); + memset(&crs, 0, sizeof(crs)); xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NORMAL); crs.ccb_h.func_code = XPT_REL_SIMQ; crs.ccb_h.flags = getcount_only ? CAM_DEV_QFREEZE : 0; @@ -1452,6 +1455,7 @@ { struct ccb_getdevstats cgds; + memset(&cgds, 0, sizeof(cgds)); xpt_setup_ccb(&cgds.ccb_h, periph->path, CAM_PRIORITY_NORMAL); cgds.ccb_h.func_code = XPT_GDEV_STATS; xpt_action((union ccb *)&cgds); @@ -1523,6 +1527,7 @@ * First off, find out what the current * transaction counts are. */ + memset(&cgds, 0, sizeof(cgds)); xpt_setup_ccb(&cgds.ccb_h, ccb->ccb_h.path, CAM_PRIORITY_NORMAL); @@ -1641,6 +1646,7 @@ /* * Grab the inquiry data for this device. */ + memset(&cgd, 0, sizeof(cgd)); xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path, CAM_PRIORITY_NORMAL); cgd.ccb_h.func_code = XPT_GDEV_TYPE; xpt_action((union ccb *)&cgd); Index: sys/cam/cam_xpt.h =================================================================== --- sys/cam/cam_xpt.h +++ sys/cam/cam_xpt.h @@ -146,6 +146,8 @@ void xpt_pollwait(union ccb *start_ccb, uint32_t timeout); uint32_t xpt_poll_setup(union ccb *start_ccb); void xpt_sim_poll(struct cam_sim *sim); +union ccb * cam_need_large_ccb_nowait(union ccb *ccb); +void xpt_assert_ccb_is_large(union ccb *ccb); /* * Perform a path inquiry at the request priority. The bzero may be Index: sys/cam/cam_xpt.c =================================================================== --- sys/cam/cam_xpt.c +++ sys/cam/cam_xpt.c @@ -497,6 +497,7 @@ * This is an immediate CCB, so it's okay to * allocate it on the stack. */ + memset(&ccb, 0, sizeof(ccb)); /* * Create a path using the bus, target, and lun the @@ -2584,6 +2585,7 @@ if ((device->flags & CAM_DEV_UNCONFIGURED) != 0) return (1); + memset(&cgd, 0, sizeof(cgd)); xpt_compile_path(&path, NULL, device->target->bus->path_id, @@ -4652,6 +4654,7 @@ union ccb *new_ccb; new_ccb = malloc(sizeof(*new_ccb), M_CAMCCB, M_ZERO|M_WAITOK); + new_ccb->ccb_h.allocated_len = sizeof(*new_ccb); return (new_ccb); } @@ -4661,6 +4664,8 @@ union ccb *new_ccb; new_ccb = malloc(sizeof(*new_ccb), M_CAMCCB, M_ZERO|M_NOWAIT); + if (new_ccb != NULL) + new_ccb->ccb_h.allocated_len = sizeof(*new_ccb); return (new_ccb); } @@ -4681,10 +4686,15 @@ xpt_get_ccb_nowait(struct cam_periph *periph) { union ccb *new_ccb; + size_t len; - new_ccb = malloc(sizeof(*new_ccb), M_CAMCCB, M_ZERO|M_NOWAIT); + len = periph->small_ccb_len > 0 ? + periph->small_ccb_len : sizeof(*new_ccb); + + new_ccb = malloc(len, M_CAMCCB, M_ZERO|M_NOWAIT); if (new_ccb == NULL) return (NULL); + new_ccb->ccb_h.allocated_len = len; periph->periph_allocated++; cam_ccbq_take_opening(&periph->path->device->ccbq); return (new_ccb); @@ -4694,15 +4704,53 @@ xpt_get_ccb(struct cam_periph *periph) { union ccb *new_ccb; + size_t len; + + len = periph->small_ccb_len > 0 ? + periph->small_ccb_len : sizeof(*new_ccb); cam_periph_unlock(periph); - new_ccb = malloc(sizeof(*new_ccb), M_CAMCCB, M_ZERO|M_WAITOK); + new_ccb = malloc(len, M_CAMCCB, M_ZERO|M_WAITOK); + new_ccb->ccb_h.allocated_len = len; cam_periph_lock(periph); periph->periph_allocated++; cam_ccbq_take_opening(&periph->path->device->ccbq); return (new_ccb); } +union ccb * +cam_need_large_ccb_nowait(union ccb *old_ccb) +{ + union ccb *new_ccb; + + /* + * It's either allocated on the stack, and thus doesn't + * have the length initialized, or is a large one already. + */ + if (old_ccb->ccb_h.allocated_len == 0 || + old_ccb->ccb_h.allocated_len >= sizeof(*new_ccb)) + return (old_ccb); + + //printf("%s: reallocating\n", __func__); + + new_ccb = realloc(old_ccb, sizeof(*new_ccb), M_CAMCCB, M_ZERO|M_NOWAIT); + if (new_ccb != NULL) + new_ccb->ccb_h.allocated_len = sizeof(*new_ccb); + return (new_ccb); +} + +void +xpt_assert_ccb_is_large(union ccb *ccb) +{ + + if (ccb->ccb_h.allocated_len != 0) { + KASSERT(ccb->ccb_h.allocated_len == sizeof(*ccb), + ("%s: ccb %p: allocated_len %zd != %zd\n", + __func__, ccb, (size_t)ccb->ccb_h.allocated_len, + sizeof(*ccb))); + } +} + union ccb * cam_periph_getccb(struct cam_periph *periph, u_int32_t priority) { @@ -5054,6 +5102,7 @@ sim->max_tagged_dev_openings); xpt_dev_ccbq_resize(path, newopenings); xpt_async(AC_GETDEV_CHANGED, path, NULL); + memset(&crs, 0, sizeof(crs)); xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NORMAL); crs.ccb_h.func_code = XPT_REL_SIMQ; crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY; @@ -5079,6 +5128,7 @@ device->inq_flags &= ~SID_CmdQue; xpt_dev_ccbq_resize(path, sim->max_dev_openings); xpt_async(AC_GETDEV_CHANGED, path, NULL); + memset(&crs, 0, sizeof(crs)); xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NORMAL); crs.ccb_h.func_code = XPT_REL_SIMQ; crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY; @@ -5236,6 +5286,7 @@ xptpath = 1; } + memset(&csa, 0, sizeof(csa)); xpt_setup_ccb(&csa.ccb_h, path, CAM_PRIORITY_NORMAL); csa.ccb_h.func_code = XPT_SASYNC_CB; csa.event_enable = event; Index: sys/cam/scsi/scsi_da.c =================================================================== --- sys/cam/scsi/scsi_da.c +++ sys/cam/scsi/scsi_da.c @@ -2848,6 +2848,11 @@ TASK_INIT(&softc->sysctl_task, 0, dasysctlinit, periph); + /* + * Let XPT know we can use small CCBs. + */ + periph->small_ccb_len = sizeof(struct ccb_scsiio); + /* * Take an exclusive section lock qon the periph while dastart is called * to finish the probe. The lock will be dropped in dadone at the end @@ -3302,6 +3307,18 @@ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dastart\n")); + if (softc->state != DA_STATE_NORMAL) { + /* + * The small CCBs are just enough to fit 'struct ccb_scsiio'; + * everything else might require a large CCB. + */ + start_ccb = cam_need_large_ccb_nowait(start_ccb); + if (start_ccb == NULL) { + printf("%s: cannot allocate large CCB; XXX what now\n", __func__); + return; + } + } + skipstate: switch (softc->state) { case DA_STATE_NORMAL: @@ -4878,6 +4895,7 @@ /*timeout*/0, /*getcount_only*/0); + memset(&cgd, 0, sizeof(cgd)); xpt_setup_ccb(&cgd.ccb_h, done_ccb->ccb_h.path, CAM_PRIORITY_NORMAL); cgd.ccb_h.func_code = XPT_GDEV_TYPE; @@ -6125,6 +6143,7 @@ * up with something that will make this a bootable * device. */ + memset(&ccg, 0, sizeof(ccg)); xpt_setup_ccb(&ccg.ccb_h, periph->path, CAM_PRIORITY_NORMAL); ccg.ccb_h.func_code = XPT_CALC_GEOMETRY; ccg.block_size = dp->secsize; @@ -6162,6 +6181,7 @@ min(sizeof(softc->rcaplong), rcap_len)) != 0)) { struct ccb_dev_advinfo cdai; + memset(&cdai, 0, sizeof(cdai)); xpt_setup_ccb(&cdai.ccb_h, periph->path, CAM_PRIORITY_NORMAL); cdai.ccb_h.func_code = XPT_DEV_ADVINFO; cdai.buftype = CDAI_TYPE_RCAPLONG; Index: sys/cam/scsi/scsi_xpt.c =================================================================== --- sys/cam/scsi/scsi_xpt.c +++ sys/cam/scsi/scsi_xpt.c @@ -1036,6 +1036,7 @@ { struct ccb_trans_settings cts; + memset(&cts, 0, sizeof(cts)); xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; cts.type = CTS_TYPE_USER_SETTINGS; @@ -2306,6 +2307,7 @@ CAM_DEBUG(path, CAM_DEBUG_TRACE, ("scsi_scan_lun\n")); + memset(&cpi, 0, sizeof(cpi)); xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); @@ -2432,6 +2434,7 @@ struct scsi_inquiry_data *inq_buf; /* Get transport information from the SIM */ + memset(&cpi, 0, sizeof(cpi)); xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); @@ -2492,6 +2495,7 @@ */ /* Tell the controller what we think */ + memset(&cts, 0, sizeof(cts)); xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; cts.type = CTS_TYPE_CURRENT_SETTINGS; @@ -2625,6 +2629,12 @@ scsi_action(union ccb *start_ccb) { + if (start_ccb->ccb_h.func_code != XPT_SCSI_IO && + start_ccb->ccb_h.path->periph != NULL && + start_ccb->ccb_h.path->periph->small_ccb_len != 0) { + xpt_assert_ccb_is_large(start_ccb); + } + switch (start_ccb->ccb_h.func_code) { case XPT_SET_TRAN_SETTINGS: { @@ -2754,6 +2764,7 @@ * Perform sanity checking against what the * controller and device can do. */ + memset(&cur_cts, 0, sizeof(cur_cts)); xpt_setup_ccb(&cur_cts.ccb_h, path, CAM_PRIORITY_NONE); cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; cur_cts.type = cts->type; @@ -2937,6 +2948,7 @@ && (dev->inq_flags & (SID_Sync|SID_WBus16|SID_WBus32)) != 0)) { struct ccb_trans_settings cts; + memset(&cts, 0, sizeof(cts)); xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); cts.protocol = PROTO_SCSI; cts.protocol_version = PROTO_VERSION_UNSPECIFIED; @@ -3044,6 +3056,7 @@ return; /* Ask the SIM for its base transfer speed */ + memset(&cpi, 0, sizeof(cpi)); xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi);