Merge CAM locking changes from the projects/camlock branch to radically

reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.

Replace big per-SIM locks with bunch of smaller ones:
 - per-LUN locks to protect device and peripheral drivers state;
 - per-target locks to protect list of LUNs on target;
 - per-bus locks to protect reference counting;
 - per-send queue locks to protect queue of CCBs to be sent;
 - per-done queue locks to protect queue of completed CCBs;
 - remaining per-SIM locks now protect only HBA driver internals.

While holding LUN lock it is allowed (while not recommended for performance
reasons) to take SIM lock.  The opposite acquisition order is forbidden.
All the other locks are leaf locks, that can be taken anywhere, but should
not be cascaded.  Many functions, such as: xpt_action(), xpt_done(),
xpt_async(), xpt_create_path(), etc. are no longer require (but allow) SIM
lock to be held.

To keep compatibility and solve cases where SIM lock can't be dropped, all
xpt_async() calls in addition to xpt_done() calls are queued to completion
threads for async processing in clean environment without SIM lock held.

Instead of single CAM SWI thread, used for commands completion processing
before, use multiple (depending on number of CPUs) threads.  Load balanced
between them using "hash" of the device B:T:L address.

HBA drivers that can drop SIM lock during completion processing and have
sufficient number of completion threads to efficiently scale to multiple
CPUs can use new function xpt_done_direct() to avoid extra context switch.
Make ahci(4) driver to use this mechanism depending on hardware setup.

Sponsored by:	iXsystems, Inc.
MFC after:	2 months
This commit is contained in:
Alexander Motin 2013-10-21 12:00:26 +00:00
parent e45e2255e8
commit 227d67aa54
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=256843
36 changed files with 1595 additions and 1593 deletions

View File

@ -103,7 +103,6 @@ typedef enum {
ADA_CCB_RAHEAD = 0x01,
ADA_CCB_WCACHE = 0x02,
ADA_CCB_BUFFER_IO = 0x03,
ADA_CCB_WAITING = 0x04,
ADA_CCB_DUMP = 0x05,
ADA_CCB_TRIM = 0x06,
ADA_CCB_TYPE_MASK = 0x0F,
@ -154,6 +153,7 @@ struct ada_softc {
struct sysctl_oid *sysctl_tree;
struct callout sendordered_c;
struct trim_request trim_req;
int refcount;
};
struct ada_quirk_entry {
@ -637,14 +637,8 @@ adaclose(struct disk *dp)
int error;
periph = (struct cam_periph *)dp->d_drv1;
cam_periph_lock(periph);
if (cam_periph_hold(periph, PRIBIO) != 0) {
cam_periph_unlock(periph);
cam_periph_release(periph);
return (0);
}
softc = (struct ada_softc *)periph->softc;
cam_periph_lock(periph);
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
("adaclose\n"));
@ -652,7 +646,8 @@ adaclose(struct disk *dp)
/* We only sync the cache if the drive is capable of it. */
if ((softc->flags & ADA_FLAG_DIRTY) != 0 &&
(softc->flags & ADA_FLAG_CAN_FLUSHCACHE) != 0 &&
(periph->flags & CAM_PERIPH_INVALID) == 0) {
(periph->flags & CAM_PERIPH_INVALID) == 0 &&
cam_periph_hold(periph, PRIBIO) == 0) {
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
cam_fill_ataio(&ccb->ataio,
@ -676,10 +671,13 @@ adaclose(struct disk *dp)
else
softc->flags &= ~ADA_FLAG_DIRTY;
xpt_release_ccb(ccb);
cam_periph_unhold(periph);
}
softc->flags &= ~ADA_FLAG_OPEN;
cam_periph_unhold(periph);
while (softc->refcount != 0)
cam_periph_sleep(periph, &softc->refcount, PRIBIO, "adaclose", 1);
cam_periph_unlock(periph);
cam_periph_release(periph);
return (0);
@ -689,23 +687,15 @@ static void
adaschedule(struct cam_periph *periph)
{
struct ada_softc *softc = (struct ada_softc *)periph->softc;
uint32_t prio;
if (softc->state != ADA_STATE_NORMAL)
return;
/* Check if cam_periph_getccb() was called. */
prio = periph->immediate_priority;
/* Check if we have more work to do. */
if (bioq_first(&softc->bio_queue) ||
(!softc->trim_running && bioq_first(&softc->trim_queue))) {
prio = CAM_PRIORITY_NORMAL;
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
}
/* Schedule CCB if any of above is true. */
if (prio != CAM_PRIORITY_NONE)
xpt_schedule(periph, prio);
}
/*
@ -969,7 +959,7 @@ adaasync(void *callback_arg, u_int32_t code,
status = cam_periph_alloc(adaregister, adaoninvalidate,
adacleanup, adastart,
"ada", CAM_PERIPH_BIO,
cgd->ccb_h.path, adaasync,
path, adaasync,
AC_FOUND_DEVICE, cgd);
if (status != CAM_REQ_CMP
@ -1045,8 +1035,10 @@ adaasync(void *callback_arg, u_int32_t code,
softc->state = ADA_STATE_WCACHE;
else
break;
cam_periph_acquire(periph);
xpt_schedule(periph, CAM_PRIORITY_DEV);
if (cam_periph_acquire(periph) != CAM_REQ_CMP)
softc->state = ADA_STATE_NORMAL;
else
xpt_schedule(periph, CAM_PRIORITY_DEV);
}
default:
cam_periph_async(periph, code, path, arg);
@ -1353,8 +1345,8 @@ adaregister(struct cam_periph *periph, void *arg)
* Create our sysctl variables, now that we know
* we have successfully attached.
*/
cam_periph_acquire(periph);
taskqueue_enqueue(taskqueue_thread, &softc->sysctl_task);
if (cam_periph_acquire(periph) == CAM_REQ_CMP)
taskqueue_enqueue(taskqueue_thread, &softc->sysctl_task);
/*
* Add async callbacks for bus reset and
@ -1372,7 +1364,7 @@ adaregister(struct cam_periph *periph, void *arg)
* Schedule a periodic event to occasionally send an
* ordered tag to a device.
*/
callout_init_mtx(&softc->sendordered_c, periph->sim->mtx, 0);
callout_init_mtx(&softc->sendordered_c, cam_periph_mtx(periph), 0);
callout_reset(&softc->sendordered_c,
(ada_default_timeout * hz) / ADA_ORDEREDTAG_INTERVAL,
adasendorderedtag, softc);
@ -1380,16 +1372,17 @@ adaregister(struct cam_periph *periph, void *arg)
if (ADA_RA >= 0 &&
cgd->ident_data.support.command1 & ATA_SUPPORT_LOOKAHEAD) {
softc->state = ADA_STATE_RAHEAD;
cam_periph_acquire(periph);
xpt_schedule(periph, CAM_PRIORITY_DEV);
} else if (ADA_WC >= 0 &&
cgd->ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) {
softc->state = ADA_STATE_WCACHE;
cam_periph_acquire(periph);
xpt_schedule(periph, CAM_PRIORITY_DEV);
} else
} else {
softc->state = ADA_STATE_NORMAL;
return(CAM_REQ_CMP);
}
if (cam_periph_acquire(periph) != CAM_REQ_CMP)
softc->state = ADA_STATE_NORMAL;
else
xpt_schedule(periph, CAM_PRIORITY_DEV);
return(CAM_REQ_CMP);
}
@ -1407,19 +1400,6 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
struct bio *bp;
u_int8_t tag_code;
/* Execute immediate CCB if waiting. */
if (periph->immediate_priority <= periph->pinfo.priority) {
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
("queuing for immediate ccb\n"));
start_ccb->ccb_h.ccb_state = ADA_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
wakeup(&periph->ccb_list);
/* Have more work to do, so ensure we stay scheduled */
adaschedule(periph);
break;
}
/* Run TRIM if not running yet. */
if (!softc->trim_running &&
(bp = bioq_first(&softc->trim_queue)) != 0) {
@ -1494,6 +1474,7 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
ATA_DSM_TRIM, 0, (ranges + ATA_DSM_BLK_RANGES -
1) / ATA_DSM_BLK_RANGES);
start_ccb->ccb_h.ccb_state = ADA_CCB_TRIM;
start_ccb->ccb_h.flags |= CAM_UNLOCKED;
goto out;
}
/* Run regular command. */
@ -1662,10 +1643,15 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
break;
}
start_ccb->ccb_h.ccb_state = ADA_CCB_BUFFER_IO;
start_ccb->ccb_h.flags |= CAM_UNLOCKED;
out:
start_ccb->ccb_h.ccb_bp = bp;
softc->outstanding_cmds++;
softc->refcount++;
cam_periph_unlock(periph);
xpt_action(start_ccb);
cam_periph_lock(periph);
softc->refcount--;
/* May have more work to do, so ensure we stay scheduled */
adaschedule(periph);
@ -1674,13 +1660,6 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
case ADA_STATE_RAHEAD:
case ADA_STATE_WCACHE:
{
if ((periph->flags & CAM_PERIPH_INVALID) != 0) {
softc->state = ADA_STATE_NORMAL;
xpt_release_ccb(start_ccb);
cam_periph_release_locked(periph);
return;
}
cam_fill_ataio(ataio,
1,
adadone,
@ -1729,10 +1708,12 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
struct bio *bp;
int error;
cam_periph_lock(periph);
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
error = adaerror(done_ccb, 0, 0);
if (error == ERESTART) {
/* A retry was scheduled, so just return. */
cam_periph_unlock(periph);
return;
}
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
@ -1762,6 +1743,7 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
softc->outstanding_cmds--;
if (softc->outstanding_cmds == 0)
softc->flags |= ADA_FLAG_WENT_IDLE;
xpt_release_ccb(done_ccb);
if (state == ADA_CCB_TRIM) {
TAILQ_HEAD(, bio) queue;
struct bio *bp1;
@ -1769,6 +1751,8 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
TAILQ_INIT(&queue);
TAILQ_CONCAT(&queue, &softc->trim_req.bps, bio_queue);
softc->trim_running = 0;
adaschedule(periph);
cam_periph_unlock(periph);
while ((bp1 = TAILQ_FIRST(&queue)) != NULL) {
TAILQ_REMOVE(&queue, bp1, bio_queue);
bp1->bio_error = error;
@ -1779,10 +1763,11 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
bp1->bio_resid = 0;
biodone(bp1);
}
adaschedule(periph);
} else
} else {
cam_periph_unlock(periph);
biodone(bp);
break;
}
return;
}
case ADA_CCB_RAHEAD:
{
@ -1858,12 +1843,6 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
cam_periph_release_locked(periph);
return;
}
case ADA_CCB_WAITING:
{
/* Caller will release the CCB */
wakeup(&done_ccb->ccb_h.cbfcnp);
return;
}
case ADA_CCB_DUMP:
/* No-op. We're polling */
return;

View File

@ -293,7 +293,7 @@ pmpasync(void *callback_arg, u_int32_t code,
status = cam_periph_alloc(pmpregister, pmponinvalidate,
pmpcleanup, pmpstart,
"pmp", CAM_PERIPH_BIO,
cgd->ccb_h.path, pmpasync,
path, pmpasync,
AC_FOUND_DEVICE, cgd);
if (status != CAM_REQ_CMP
@ -318,13 +318,17 @@ pmpasync(void *callback_arg, u_int32_t code,
if (code == AC_SENT_BDR || code == AC_BUS_RESET)
softc->found = 0; /* We have to reset everything. */
if (softc->state == PMP_STATE_NORMAL) {
if (softc->pm_pid == 0x37261095 ||
softc->pm_pid == 0x38261095)
softc->state = PMP_STATE_PM_QUIRKS_1;
else
softc->state = PMP_STATE_PRECONFIG;
cam_periph_acquire(periph);
xpt_schedule(periph, CAM_PRIORITY_DEV);
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
if (softc->pm_pid == 0x37261095 ||
softc->pm_pid == 0x38261095)
softc->state = PMP_STATE_PM_QUIRKS_1;
else
softc->state = PMP_STATE_PRECONFIG;
xpt_schedule(periph, CAM_PRIORITY_DEV);
} else {
pmprelease(periph, softc->found);
xpt_release_boot();
}
} else
softc->restart = 1;
break;

View File

@ -182,7 +182,7 @@ static struct cam_ed *
static void ata_device_transport(struct cam_path *path);
static void ata_get_transfer_settings(struct ccb_trans_settings *cts);
static void ata_set_transfer_settings(struct ccb_trans_settings *cts,
struct cam_ed *device,
struct cam_path *path,
int async_update);
static void ata_dev_async(u_int32_t async_code,
struct cam_eb *bus,
@ -249,6 +249,7 @@ proberegister(struct cam_periph *periph, void *arg)
return (status);
}
CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n"));
ata_device_transport(periph->path);
probeschedule(periph);
return(CAM_REQ_CMP);
}
@ -1320,6 +1321,7 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
struct cam_path *path;
ata_scan_bus_info *scan_info;
union ccb *work_ccb, *reset_ccb;
struct mtx *mtx;
cam_status status;
CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
@ -1395,11 +1397,14 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
xpt_done(request_ccb);
break;
}
mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path);
goto scan_next;
case XPT_SCAN_LUN:
work_ccb = request_ccb;
/* Reuse the same CCB to query if a device was really found */
scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0;
mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path);
mtx_lock(mtx);
/* If there is PMP... */
if ((scan_info->cpi->hba_inquiry & PI_SATAPM) &&
(scan_info->counter == scan_info->cpi->max_target)) {
@ -1428,6 +1433,7 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
((scan_info->cpi->hba_inquiry & PI_SATAPM) ?
0 : scan_info->cpi->max_target)) {
done:
mtx_unlock(mtx);
xpt_free_ccb(work_ccb);
xpt_free_ccb((union ccb *)scan_info->cpi);
request_ccb = scan_info->request_ccb;
@ -1444,6 +1450,8 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
scan_info->request_ccb->ccb_h.path_id,
scan_info->counter, 0);
if (status != CAM_REQ_CMP) {
if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN)
mtx_unlock(mtx);
printf("xpt_scan_bus: xpt_create_path failed"
" with status %#x, bus scan halted\n",
status);
@ -1459,9 +1467,15 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
scan_info->request_ccb->ccb_h.pinfo.priority);
work_ccb->ccb_h.func_code = XPT_SCAN_LUN;
work_ccb->ccb_h.cbfcnp = ata_scan_bus;
work_ccb->ccb_h.flags |= CAM_UNLOCKED;
work_ccb->ccb_h.ppriv_ptr0 = scan_info;
work_ccb->crcn.flags = scan_info->request_ccb->crcn.flags;
mtx_unlock(mtx);
if (request_ccb->ccb_h.func_code == XPT_SCAN_LUN)
mtx = NULL;
xpt_action(work_ccb);
if (mtx != NULL)
mtx_lock(mtx);
break;
default:
break;
@ -1476,6 +1490,7 @@ ata_scan_lun(struct cam_periph *periph, struct cam_path *path,
cam_status status;
struct cam_path *new_path;
struct cam_periph *old_periph;
int lock;
CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n"));
@ -1510,10 +1525,14 @@ ata_scan_lun(struct cam_periph *periph, struct cam_path *path,
}
xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT);
request_ccb->ccb_h.cbfcnp = xptscandone;
request_ccb->ccb_h.flags |= CAM_UNLOCKED;
request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
request_ccb->crcn.flags = flags;
}
lock = (xpt_path_owned(path) == 0);
if (lock)
xpt_path_lock(path);
if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) {
if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) {
probe_softc *softc;
@ -1540,6 +1559,8 @@ ata_scan_lun(struct cam_periph *periph, struct cam_path *path,
xpt_done(request_ccb);
}
}
if (lock)
xpt_path_unlock(path);
}
static void
@ -1553,7 +1574,6 @@ xptscandone(struct cam_periph *periph, union ccb *done_ccb)
static struct cam_ed *
ata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
{
struct cam_path path;
struct ata_quirk_entry *quirk;
struct cam_ed *device;
@ -1574,22 +1594,6 @@ ata_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
device->queue_flags = 0;
device->serial_num = NULL;
device->serial_num_len = 0;
/*
* XXX should be limited by number of CCBs this bus can
* do.
*/
bus->sim->max_ccbs += device->ccbq.devq_openings;
if (lun_id != CAM_LUN_WILDCARD) {
xpt_compile_path(&path,
NULL,
bus->path_id,
target->target_id,
lun_id);
ata_device_transport(&path);
xpt_release_path(&path);
}
return (device);
}
@ -1712,15 +1716,8 @@ ata_dev_advinfo(union ccb *start_ccb)
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);
}
}
@ -1732,7 +1729,7 @@ ata_action(union ccb *start_ccb)
case XPT_SET_TRAN_SETTINGS:
{
ata_set_transfer_settings(&start_ccb->cts,
start_ccb->ccb_h.path->device,
start_ccb->ccb_h.path,
/*async_update*/FALSE);
break;
}
@ -1791,11 +1788,9 @@ ata_get_transfer_settings(struct ccb_trans_settings *cts)
struct ccb_trans_settings_ata *ata;
struct ccb_trans_settings_scsi *scsi;
struct cam_ed *device;
struct cam_sim *sim;
device = cts->ccb_h.path->device;
sim = cts->ccb_h.path->bus->sim;
(*(sim->sim_action))(sim, (union ccb *)cts);
xpt_action_default((union ccb *)cts);
if (cts->protocol == PROTO_UNKNOWN ||
cts->protocol == PROTO_UNSPECIFIED) {
@ -1832,17 +1827,17 @@ ata_get_transfer_settings(struct ccb_trans_settings *cts)
}
static void
ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_path *path,
int async_update)
{
struct ccb_pathinq cpi;
struct ccb_trans_settings_ata *ata;
struct ccb_trans_settings_scsi *scsi;
struct cam_sim *sim;
struct ata_params *ident_data;
struct scsi_inquiry_data *inq_data;
struct cam_ed *device;
if (device == NULL) {
if (path == NULL || (device = path->device) == NULL) {
cts->ccb_h.status = CAM_PATH_INVALID;
xpt_done((union ccb *)cts);
return;
@ -1859,14 +1854,14 @@ ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
cts->protocol_version = device->protocol_version;
if (cts->protocol != device->protocol) {
xpt_print(cts->ccb_h.path, "Uninitialized Protocol %x:%x?\n",
xpt_print(path, "Uninitialized Protocol %x:%x?\n",
cts->protocol, device->protocol);
cts->protocol = device->protocol;
}
if (cts->protocol_version > device->protocol_version) {
if (bootverbose) {
xpt_print(cts->ccb_h.path, "Down reving Protocol "
xpt_print(path, "Down reving Protocol "
"Version from %d to %d?\n", cts->protocol_version,
device->protocol_version);
}
@ -1884,21 +1879,20 @@ ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
cts->transport_version = device->transport_version;
if (cts->transport != device->transport) {
xpt_print(cts->ccb_h.path, "Uninitialized Transport %x:%x?\n",
xpt_print(path, "Uninitialized Transport %x:%x?\n",
cts->transport, device->transport);
cts->transport = device->transport;
}
if (cts->transport_version > device->transport_version) {
if (bootverbose) {
xpt_print(cts->ccb_h.path, "Down reving Transport "
xpt_print(path, "Down reving Transport "
"Version from %d to %d?\n", cts->transport_version,
device->transport_version);
}
cts->transport_version = device->transport_version;
}
sim = cts->ccb_h.path->bus->sim;
ident_data = &device->ident_data;
inq_data = &device->inq_data;
if (cts->protocol == PROTO_ATA)
@ -1909,7 +1903,7 @@ ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
scsi = &cts->proto_specific.scsi;
else
scsi = NULL;
xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
@ -1953,11 +1947,11 @@ ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
device->tag_delay_count = CAM_TAG_DELAY_COUNT;
device->flags |= CAM_DEV_TAG_AFTER_COUNT;
} else if (nowt && !newt)
xpt_stop_tags(cts->ccb_h.path);
xpt_stop_tags(path);
}
if (async_update == FALSE)
(*(sim->sim_action))(sim, (union ccb *)cts);
xpt_action_default((union ccb *)cts);
}
/*
@ -2014,10 +2008,14 @@ ata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target,
xpt_release_device(device);
} else if (async_code == AC_TRANSFER_NEG) {
struct ccb_trans_settings *settings;
struct cam_path path;
settings = (struct ccb_trans_settings *)async_arg;
ata_set_transfer_settings(settings, device,
xpt_compile_path(&path, NULL, bus->path_id, target->target_id,
device->lun_id);
ata_set_transfer_settings(settings, &path,
/*async_update*/TRUE);
xpt_release_path(&path);
}
}
@ -2030,7 +2028,7 @@ ata_announce_periph(struct cam_periph *periph)
u_int speed;
u_int mb;
mtx_assert(periph->sim->mtx, MA_OWNED);
cam_periph_assert(periph, MA_OWNED);
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;

View File

@ -104,7 +104,9 @@ typedef enum {
CAM_SEND_SENSE = 0x08000000,/* Send sense data with status */
CAM_TERM_IO = 0x10000000,/* Terminate I/O Message sup. */
CAM_DISCONNECT = 0x20000000,/* Disconnects are mandatory */
CAM_SEND_STATUS = 0x40000000 /* Send status after data phase */
CAM_SEND_STATUS = 0x40000000,/* Send status after data phase */
CAM_UNLOCKED = 0x80000000 /* Call callback without lock. */
} ccb_flags;
typedef enum {
@ -151,6 +153,9 @@ typedef enum {
/* Device statistics (error counts, etc.) */
XPT_DEV_ADVINFO = 0x0e,
/* Get/Set Device advanced information */
XPT_ASYNC = 0x0f | XPT_FC_QUEUED | XPT_FC_USER_CCB
| XPT_FC_XPT_ONLY,
/* Asynchronous event */
/* SCSI Control Functions: 0x10->0x1F */
XPT_ABORT = 0x10,
/* Abort the specified CCB */
@ -1153,6 +1158,16 @@ struct ccb_dev_advinfo {
uint8_t *buf; /* IN/OUT: Buffer for requested data */
};
/*
* CCB for sending async events
*/
struct ccb_async {
struct ccb_hdr ccb_h;
uint32_t async_code;
off_t async_arg_size;
void *async_arg_ptr;
};
/*
* Union of all CCB types for kernel space allocation. This union should
* never be used for manipulating CCBs - its only use is for the allocation
@ -1192,6 +1207,7 @@ union ccb {
struct ccb_debug cdbg;
struct ccb_ataio ataio;
struct ccb_dev_advinfo cdai;
struct ccb_async casync;
};
__BEGIN_DECLS

View File

@ -196,12 +196,12 @@ cam_periph_alloc(periph_ctor_t *periph_ctor,
path_id = xpt_path_path_id(path);
target_id = xpt_path_target_id(path);
lun_id = xpt_path_lun_id(path);
cam_init_pinfo(&periph->pinfo);
periph->periph_start = periph_start;
periph->periph_dtor = periph_dtor;
periph->periph_oninval = periph_oninvalidate;
periph->type = type;
periph->periph_name = name;
periph->scheduled_priority = CAM_PRIORITY_NONE;
periph->immediate_priority = CAM_PRIORITY_NONE;
periph->refcount = 1; /* Dropped by invalidation. */
periph->sim = sim;
@ -298,7 +298,7 @@ cam_periph_find(struct cam_path *path, char *name)
TAILQ_FOREACH(periph, &(*p_drv)->units, unit_links) {
if (xpt_path_comp(periph->path, path) == 0) {
xpt_unlock_buses();
mtx_assert(periph->sim->mtx, MA_OWNED);
cam_periph_assert(periph, MA_OWNED);
return(periph);
}
}
@ -379,7 +379,7 @@ void
cam_periph_release_locked_buses(struct cam_periph *periph)
{
mtx_assert(periph->sim->mtx, MA_OWNED);
cam_periph_assert(periph, MA_OWNED);
KASSERT(periph->refcount >= 1, ("periph->refcount >= 1"));
if (--periph->refcount == 0)
camperiphfree(periph);
@ -400,16 +400,16 @@ cam_periph_release_locked(struct cam_periph *periph)
void
cam_periph_release(struct cam_periph *periph)
{
struct cam_sim *sim;
struct mtx *mtx;
if (periph == NULL)
return;
sim = periph->sim;
mtx_assert(sim->mtx, MA_NOTOWNED);
mtx_lock(sim->mtx);
cam_periph_assert(periph, MA_NOTOWNED);
mtx = cam_periph_mtx(periph);
mtx_lock(mtx);
cam_periph_release_locked(periph);
mtx_unlock(sim->mtx);
mtx_unlock(mtx);
}
int
@ -427,10 +427,10 @@ cam_periph_hold(struct cam_periph *periph, int priority)
if (cam_periph_acquire(periph) != CAM_REQ_CMP)
return (ENXIO);
mtx_assert(periph->sim->mtx, MA_OWNED);
cam_periph_assert(periph, MA_OWNED);
while ((periph->flags & CAM_PERIPH_LOCKED) != 0) {
periph->flags |= CAM_PERIPH_LOCK_WANTED;
if ((error = mtx_sleep(periph, periph->sim->mtx, priority,
if ((error = cam_periph_sleep(periph, periph, priority,
"caplck", 0)) != 0) {
cam_periph_release_locked(periph);
return (error);
@ -449,7 +449,7 @@ void
cam_periph_unhold(struct cam_periph *periph)
{
mtx_assert(periph->sim->mtx, MA_OWNED);
cam_periph_assert(periph, MA_OWNED);
periph->flags &= ~CAM_PERIPH_LOCKED;
if ((periph->flags & CAM_PERIPH_LOCK_WANTED) != 0) {
@ -577,7 +577,7 @@ void
cam_periph_invalidate(struct cam_periph *periph)
{
mtx_assert(periph->sim->mtx, MA_OWNED);
cam_periph_assert(periph, MA_OWNED);
/*
* We only call this routine the first time a peripheral is
* invalidated.
@ -600,7 +600,9 @@ camperiphfree(struct cam_periph *periph)
{
struct periph_driver **p_drv;
mtx_assert(periph->sim->mtx, MA_OWNED);
cam_periph_assert(periph, MA_OWNED);
KASSERT(periph->periph_allocating == 0, ("%s%d: freed while allocating",
periph->periph_name, periph->unit_number));
for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) {
if (strcmp((*p_drv)->driver_name, periph->periph_name) == 0)
break;
@ -947,40 +949,14 @@ cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
PRELE(curproc);
}
union ccb *
cam_periph_getccb(struct cam_periph *periph, u_int32_t priority)
{
struct ccb_hdr *ccb_h;
mtx_assert(periph->sim->mtx, MA_OWNED);
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdgetccb\n"));
while (SLIST_FIRST(&periph->ccb_list) == NULL) {
if (periph->immediate_priority > priority)
periph->immediate_priority = priority;
xpt_schedule(periph, priority);
if ((SLIST_FIRST(&periph->ccb_list) != NULL)
&& (SLIST_FIRST(&periph->ccb_list)->pinfo.priority == priority))
break;
mtx_assert(periph->sim->mtx, MA_OWNED);
mtx_sleep(&periph->ccb_list, periph->sim->mtx, PRIBIO, "cgticb",
0);
}
ccb_h = SLIST_FIRST(&periph->ccb_list);
SLIST_REMOVE_HEAD(&periph->ccb_list, periph_links.sle);
return ((union ccb *)ccb_h);
}
void
cam_periph_ccbwait(union ccb *ccb)
{
struct cam_sim *sim;
sim = xpt_path_sim(ccb->ccb_h.path);
if ((ccb->ccb_h.pinfo.index != CAM_UNQUEUED_INDEX)
|| ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG))
mtx_sleep(&ccb->ccb_h.cbfcnp, sim->mtx, PRIBIO, "cbwait", 0);
xpt_path_sleep(ccb->ccb_h.path, &ccb->ccb_h.cbfcnp, PRIBIO,
"cbwait", 0);
}
int
@ -1045,6 +1021,14 @@ cam_periph_ioctl(struct cam_periph *periph, u_long cmd, caddr_t addr,
return(error);
}
static void
cam_periph_done(struct cam_periph *periph, union ccb *done_ccb)
{
/* Caller will release the CCB */
wakeup(&done_ccb->ccb_h.cbfcnp);
}
int
cam_periph_runccb(union ccb *ccb,
int (*error_routine)(union ccb *ccb,
@ -1053,12 +1037,9 @@ cam_periph_runccb(union ccb *ccb,
cam_flags camflags, u_int32_t sense_flags,
struct devstat *ds)
{
struct cam_sim *sim;
int error;
error = 0;
sim = xpt_path_sim(ccb->ccb_h.path);
mtx_assert(sim->mtx, MA_OWNED);
xpt_path_assert(ccb->ccb_h.path, MA_OWNED);
/*
* If the user has supplied a stats structure, and if we understand
@ -1068,6 +1049,7 @@ cam_periph_runccb(union ccb *ccb,
ccb->ccb_h.func_code == XPT_ATA_IO))
devstat_start_transaction(ds, NULL);
ccb->ccb_h.cbfcnp = cam_periph_done;
xpt_action(ccb);
do {

View File

@ -35,6 +35,7 @@
#include <cam/cam_sim.h>
#ifdef _KERNEL
#include <sys/taskqueue.h>
#include <cam/cam_xpt.h>
@ -103,7 +104,6 @@ typedef cam_status periph_ctor_t (struct cam_periph *periph,
typedef void periph_oninv_t (struct cam_periph *periph);
typedef void periph_dtor_t (struct cam_periph *periph);
struct cam_periph {
cam_pinfo pinfo;
periph_start_t *periph_start;
periph_oninv_t *periph_oninval;
periph_dtor_t *periph_dtor;
@ -120,15 +120,20 @@ struct cam_periph {
#define CAM_PERIPH_INVALID 0x08
#define CAM_PERIPH_NEW_DEV_FOUND 0x10
#define CAM_PERIPH_RECOVERY_INPROG 0x20
#define CAM_PERIPH_RUN_TASK 0x40
#define CAM_PERIPH_FREE 0x80
#define CAM_PERIPH_ANNOUNCED 0x100
u_int32_t immediate_priority;
uint32_t scheduled_priority;
uint32_t immediate_priority;
int periph_allocating;
int periph_allocated;
u_int32_t refcount;
SLIST_HEAD(, ccb_hdr) ccb_list; /* For "immediate" requests */
SLIST_ENTRY(cam_periph) periph_links;
TAILQ_ENTRY(cam_periph) unit_links;
ac_callback_t *deferred_callback;
ac_code deferred_ac;
struct task periph_run_task;
};
#define CAM_PERIPH_MAXMAPS 2
@ -185,30 +190,26 @@ void cam_periph_freeze_after_event(struct cam_periph *periph,
int cam_periph_error(union ccb *ccb, cam_flags camflags,
u_int32_t sense_flags, union ccb *save_ccb);
static __inline void
cam_periph_lock(struct cam_periph *periph)
static __inline struct mtx *
cam_periph_mtx(struct cam_periph *periph)
{
mtx_lock(periph->sim->mtx);
return (xpt_path_mtx(periph->path));
}
static __inline void
cam_periph_unlock(struct cam_periph *periph)
{
mtx_unlock(periph->sim->mtx);
}
#define cam_periph_owned(periph) \
mtx_owned(xpt_path_mtx((periph)->path))
static __inline int
cam_periph_owned(struct cam_periph *periph)
{
return (mtx_owned(periph->sim->mtx));
}
#define cam_periph_lock(periph) \
mtx_lock(xpt_path_mtx((periph)->path))
static __inline int
cam_periph_sleep(struct cam_periph *periph, void *chan, int priority,
const char *wmesg, int timo)
{
return (msleep(chan, periph->sim->mtx, priority, wmesg, timo));
}
#define cam_periph_unlock(periph) \
mtx_unlock(xpt_path_mtx((periph)->path))
#define cam_periph_assert(periph, what) \
mtx_assert(xpt_path_mtx((periph)->path), (what))
#define cam_periph_sleep(periph, chan, priority, wmesg, timo) \
xpt_path_sleep((periph)->path, (chan), (priority), (wmesg), (timo))
static inline struct cam_periph *
cam_periph_acquire_first(struct periph_driver *driver)
@ -230,7 +231,7 @@ cam_periph_acquire_next(struct cam_periph *pperiph)
{
struct cam_periph *periph = pperiph;
mtx_assert(pperiph->sim->mtx, MA_NOTOWNED);
cam_periph_assert(pperiph, MA_NOTOWNED);
xpt_lock_buses();
do {
periph = TAILQ_NEXT(periph, unit_links);

View File

@ -220,27 +220,30 @@ cam_devq_alloc(int devices, int openings)
}
if (cam_devq_init(devq, devices, openings) != 0) {
free(devq, M_CAMDEVQ);
return (NULL);
return (NULL);
}
return (devq);
}
int
cam_devq_init(struct cam_devq *devq, int devices, int openings)
{
bzero(devq, sizeof(*devq));
mtx_init(&devq->send_mtx, "CAM queue lock", NULL, MTX_DEF);
if (camq_init(&devq->send_queue, devices) != 0)
return (1);
devq->send_openings = openings;
devq->send_active = 0;
return (0);
devq->send_active = 0;
return (0);
}
void
cam_devq_free(struct cam_devq *devq)
{
camq_fini(&devq->send_queue);
mtx_destroy(&devq->send_mtx);
free(devq, M_CAMDEVQ);
}
@ -286,6 +289,7 @@ cam_ccbq_resize(struct cam_ccbq *ccbq, int new_size)
int delta;
delta = new_size - (ccbq->dev_active + ccbq->dev_openings);
ccbq->total_openings += delta;
ccbq->devq_openings += delta;
ccbq->dev_openings += delta;
@ -303,6 +307,7 @@ cam_ccbq_init(struct cam_ccbq *ccbq, int openings)
if (camq_init(&ccbq->queue,
imax(64, 1 << fls(openings + openings / 2))) != 0)
return (1);
ccbq->total_openings = openings;
ccbq->devq_openings = openings;
ccbq->dev_openings = openings;
return (0);

View File

@ -33,6 +33,8 @@
#ifdef _KERNEL
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/queue.h>
#include <cam/cam.h>
@ -59,8 +61,8 @@ struct cam_ccbq {
struct camq queue;
struct ccb_hdr_tailq queue_extra_head;
int queue_extra_entries;
int total_openings;
int devq_openings;
int devq_allocating;
int dev_openings;
int dev_active;
int held;
@ -69,9 +71,10 @@ struct cam_ccbq {
struct cam_ed;
struct cam_devq {
struct camq send_queue;
int send_openings;
int send_active;
struct mtx send_mtx;
struct camq send_queue;
int send_openings;
int send_active;
};

View File

@ -87,7 +87,6 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
sim->flags = 0;
sim->refcount = 1;
sim->devq = queue;
sim->max_ccbs = 8; /* Reserve for management purposes. */
sim->mtx = mtx;
if (mtx == &Giant) {
sim->flags |= 0;
@ -96,17 +95,12 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
sim->flags |= CAM_SIM_MPSAFE;
callout_init(&sim->callout, 1);
}
SLIST_INIT(&sim->ccb_freeq);
TAILQ_INIT(&sim->sim_doneq);
return (sim);
}
void
cam_sim_free(struct cam_sim *sim, int free_devq)
{
union ccb *ccb;
int error;
mtx_assert(sim->mtx, MA_OWNED);
@ -118,10 +112,6 @@ cam_sim_free(struct cam_sim *sim, int free_devq)
KASSERT(sim->refcount == 0, ("sim->refcount == 0"));
while ((ccb = (union ccb *)SLIST_FIRST(&sim->ccb_freeq)) != NULL) {
SLIST_REMOVE_HEAD(&sim->ccb_freeq, xpt_links.sle);
xpt_free_ccb(ccb);
}
if (free_devq)
cam_simq_free(sim->devq);
free(sim, M_CAMSIM);
@ -130,21 +120,31 @@ cam_sim_free(struct cam_sim *sim, int free_devq)
void
cam_sim_release(struct cam_sim *sim)
{
KASSERT(sim->refcount >= 1, ("sim->refcount >= 1"));
mtx_assert(sim->mtx, MA_OWNED);
int lock;
lock = (mtx_owned(sim->mtx) == 0);
if (lock)
CAM_SIM_LOCK(sim);
KASSERT(sim->refcount >= 1, ("sim->refcount >= 1"));
sim->refcount--;
if (sim->refcount == 0)
wakeup(sim);
if (lock)
CAM_SIM_UNLOCK(sim);
}
void
cam_sim_hold(struct cam_sim *sim)
{
KASSERT(sim->refcount >= 1, ("sim->refcount >= 1"));
mtx_assert(sim->mtx, MA_OWNED);
int lock;
lock = (mtx_owned(sim->mtx) == 0);
if (lock)
CAM_SIM_LOCK(sim);
KASSERT(sim->refcount >= 1, ("sim->refcount >= 1"));
sim->refcount++;
if (lock)
CAM_SIM_UNLOCK(sim);
}
void

View File

@ -104,23 +104,9 @@ struct cam_sim {
u_int32_t flags;
#define CAM_SIM_REL_TIMEOUT_PENDING 0x01
#define CAM_SIM_MPSAFE 0x02
#define CAM_SIM_ON_DONEQ 0x04
#define CAM_SIM_POLLED 0x08
#define CAM_SIM_BATCH 0x10
struct callout callout;
struct cam_devq *devq; /* Device Queue to use for this SIM */
int refcount; /* References to the SIM. */
/* "Pool" of inactive ccbs managed by xpt_get_ccb and xpt_release_ccb */
SLIST_HEAD(,ccb_hdr) ccb_freeq;
/*
* Maximum size of ccb pool. Modified as devices are added/removed
* or have their * opening counts changed.
*/
u_int max_ccbs;
/* Current count of allocated ccbs */
u_int ccb_count;
};
#define CAM_SIM_LOCK(sim) mtx_lock((sim)->mtx)

File diff suppressed because it is too large Load Diff

View File

@ -56,6 +56,7 @@ struct cam_path;
struct async_node {
SLIST_ENTRY(async_node) links;
u_int32_t event_enable; /* Async Event enables */
u_int32_t event_lock; /* Take SIM lock for handlers. */
void (*callback)(void *arg, u_int32_t code,
struct cam_path *path, void *args);
void *callback_arg;
@ -110,6 +111,13 @@ void xpt_hold_boot(void);
void xpt_release_boot(void);
void xpt_lock_buses(void);
void xpt_unlock_buses(void);
struct mtx * xpt_path_mtx(struct cam_path *path);
#define xpt_path_lock(path) mtx_lock(xpt_path_mtx(path))
#define xpt_path_unlock(path) mtx_unlock(xpt_path_mtx(path))
#define xpt_path_assert(path, what) mtx_assert(xpt_path_mtx(path), (what))
#define xpt_path_owned(path) mtx_owned(xpt_path_mtx(path))
#define xpt_path_sleep(path, chan, priority, wmesg, timo) \
msleep((chan), xpt_path_mtx(path), (priority), (wmesg), (timo))
cam_status xpt_register_async(int event, ac_callback_t *cbfunc,
void *cbarg, struct cam_path *path);
cam_status xpt_compile_path(struct cam_path *new_path,
@ -117,6 +125,10 @@ cam_status xpt_compile_path(struct cam_path *new_path,
path_id_t path_id,
target_id_t target_id,
lun_id_t lun_id);
cam_status xpt_clone_path(struct cam_path **new_path,
struct cam_path *path);
void xpt_copy_path(struct cam_path *new_path,
struct cam_path *path);
void xpt_release_path(struct cam_path *path);

View File

@ -29,6 +29,8 @@
#ifndef _CAM_CAM_XPT_INTERNAL_H
#define _CAM_CAM_XPT_INTERNAL_H 1
#include <sys/taskqueue.h>
/* Forward Declarations */
struct cam_eb;
struct cam_et;
@ -54,31 +56,17 @@ struct xpt_xport {
xpt_announce_periph_func announce;
};
/*
* Structure for queueing a device in a run queue.
* There is one run queue for allocating new ccbs,
* and another for sending ccbs to the controller.
*/
struct cam_ed_qinfo {
cam_pinfo pinfo;
struct cam_ed *device;
};
/*
* The CAM EDT (Existing Device Table) contains the device information for
* all devices for all busses in the system. The table contains a
* cam_ed structure for each device on the bus.
*/
struct cam_ed {
cam_pinfo devq_entry;
TAILQ_ENTRY(cam_ed) links;
struct cam_ed_qinfo devq_entry;
struct cam_et *target;
struct cam_sim *sim;
lun_id_t lun_id;
struct camq drvq; /*
* Queue of type drivers wanting to do
* work on this device.
*/
struct cam_ccbq ccbq; /* Queue of pending ccbs */
struct async_list asyncs; /* Async callback info for this B/T/L */
struct periph_list periphs; /* All attached devices */
@ -125,6 +113,8 @@ struct cam_ed {
u_int32_t refcount;
struct callout callout;
STAILQ_ENTRY(cam_ed) highpowerq_entry;
struct mtx device_mtx;
struct task device_destroy_task;
};
/*
@ -143,6 +133,7 @@ struct cam_et {
struct timeval last_reset;
u_int rpl_size;
struct scsi_report_luns_data *luns;
struct mtx luns_mtx; /* Protection for luns field. */
};
/*
@ -162,6 +153,7 @@ struct cam_eb {
u_int generation;
device_t parent_dev;
struct xpt_xport *xport;
struct mtx eb_mtx; /* Bus topology mutex. */
};
struct cam_path {
@ -179,8 +171,6 @@ struct cam_ed * xpt_alloc_device(struct cam_eb *bus,
lun_id_t lun_id);
void xpt_acquire_device(struct cam_ed *device);
void xpt_release_device(struct cam_ed *device);
int xpt_schedule_dev(struct camq *queue, cam_pinfo *dev_pinfo,
u_int32_t new_priority);
u_int32_t xpt_dev_ccbq_resize(struct cam_path *path, int newopenings);
void xpt_start_tags(struct cam_path *path);
void xpt_stop_tags(struct cam_path *path);

View File

@ -46,8 +46,7 @@ u_int32_t xpt_freeze_devq(struct cam_path *path, u_int count);
void xpt_release_devq(struct cam_path *path,
u_int count, int run_queue);
void xpt_done(union ccb *done_ccb);
void xpt_batch_start(struct cam_sim *sim);
void xpt_batch_done(struct cam_sim *sim);
void xpt_done_direct(union ccb *done_ccb);
#endif
#endif /* _CAM_CAM_XPT_SIM_H */

View File

@ -504,14 +504,9 @@ static void
cfcs_done(union ctl_io *io)
{
union ccb *ccb;
struct cfcs_softc *softc;
struct cam_sim *sim;
ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
sim = xpt_path_sim(ccb->ccb_h.path);
softc = (struct cfcs_softc *)cam_sim_softc(sim);
/*
* At this point we should have status. If we don't, that's a bug.
*/
@ -550,10 +545,7 @@ cfcs_done(union ctl_io *io)
break;
}
mtx_lock(sim->mtx);
xpt_done(ccb);
mtx_unlock(sim->mtx);
ctl_free_io(io);
}

View File

@ -73,8 +73,7 @@ __FBSDID("$FreeBSD$");
#include <cam/ctl/ctl_error.h>
typedef enum {
CTLFE_CCB_DEFAULT = 0x00,
CTLFE_CCB_WAITING = 0x01
CTLFE_CCB_DEFAULT = 0x00
} ctlfe_ccb_types;
struct ctlfe_softc {
@ -82,6 +81,7 @@ struct ctlfe_softc {
path_id_t path_id;
struct cam_sim *sim;
char port_name[DEV_IDLEN];
struct mtx lun_softc_mtx;
STAILQ_HEAD(, ctlfe_lun_softc) lun_softc_list;
STAILQ_ENTRY(ctlfe_softc) links;
};
@ -320,7 +320,6 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
#ifdef CTLFE_INIT_ENABLE
if (ctlfe_num_targets >= ctlfe_max_targets) {
union ccb *ccb;
struct cam_sim *sim;
ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP,
M_NOWAIT | M_ZERO);
@ -328,18 +327,12 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
printf("%s: unable to malloc CCB!\n", __func__);
return;
}
xpt_setup_ccb(&ccb->ccb_h, cpi->ccb_h.path,
CAM_PRIORITY_NONE);
sim = xpt_path_sim(cpi->ccb_h.path);
xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_NONE);
ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
ccb->knob.xport_specific.valid = KNOB_VALID_ROLE;
ccb->knob.xport_specific.fc.role = KNOB_ROLE_INITIATOR;
/* We should hold the SIM lock here */
mtx_assert(sim->mtx, MA_OWNED);
xpt_action(ccb);
if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
@ -381,7 +374,9 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
}
bus_softc->path_id = cpi->ccb_h.path_id;
bus_softc->sim = xpt_path_sim(cpi->ccb_h.path);
bus_softc->sim = xpt_path_sim(path);
mtx_init(&bus_softc->lun_softc_mtx, "LUN softc mtx", NULL,
MTX_DEF);
STAILQ_INIT(&bus_softc->lun_softc_list);
fe = &bus_softc->fe;
@ -435,6 +430,7 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
if (retval != 0) {
printf("%s: ctl_frontend_register() failed with "
"error %d!\n", __func__, retval);
mtx_destroy(&bus_softc->lun_softc_mtx);
free(bus_softc, M_CTLFE);
break;
} else {
@ -464,6 +460,7 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
* are no outstanding commands for this frontend?
*/
ctl_frontend_deregister(&softc->fe);
mtx_destroy(&softc->lun_softc_mtx);
free(softc, M_CTLFE);
}
break;
@ -538,19 +535,18 @@ ctlferegister(struct cam_periph *periph, void *arg)
{
struct ctlfe_softc *bus_softc;
struct ctlfe_lun_softc *softc;
struct cam_sim *sim;
union ccb en_lun_ccb;
cam_status status;
int i;
softc = (struct ctlfe_lun_softc *)arg;
bus_softc = softc->parent_softc;
sim = xpt_path_sim(periph->path);
TAILQ_INIT(&softc->work_queue);
softc->periph = periph;
callout_init_mtx(&softc->dma_callout, sim->mtx, /*flags*/ 0);
callout_init_mtx(&softc->dma_callout, xpt_path_mtx(periph->path),
/*flags*/ 0);
periph->softc = softc;
xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, CAM_PRIORITY_NONE);
@ -580,6 +576,7 @@ ctlferegister(struct cam_periph *periph, void *arg)
xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1);
new_ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO;
new_ccb->ccb_h.cbfcnp = ctlfedone;
new_ccb->ccb_h.flags |= CAM_UNLOCKED;
xpt_action(new_ccb);
softc->atios_sent++;
status = new_ccb->ccb_h.status;
@ -615,6 +612,7 @@ ctlferegister(struct cam_periph *periph, void *arg)
xpt_setup_ccb(&new_ccb->ccb_h, periph->path, /*priority*/ 1);
new_ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
new_ccb->ccb_h.cbfcnp = ctlfedone;
new_ccb->ccb_h.flags |= CAM_UNLOCKED;
xpt_action(new_ccb);
softc->inots_sent++;
status = new_ccb->ccb_h.status;
@ -646,6 +644,7 @@ ctlfeoninvalidate(struct cam_periph *periph)
{
union ccb en_lun_ccb;
cam_status status;
struct ctlfe_softc *bus_softc;
struct ctlfe_lun_softc *softc;
softc = (struct ctlfe_lun_softc *)periph->softc;
@ -668,21 +667,22 @@ ctlfeoninvalidate(struct cam_periph *periph)
"INOTs outstanding, %d refs\n", softc->atios_sent -
softc->atios_returned, softc->inots_sent -
softc->inots_returned, periph->refcount);
bus_softc = softc->parent_softc;
mtx_lock(&bus_softc->lun_softc_mtx);
STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc, links);
mtx_unlock(&bus_softc->lun_softc_mtx);
}
static void
ctlfecleanup(struct cam_periph *periph)
{
struct ctlfe_lun_softc *softc;
struct ctlfe_softc *bus_softc;
xpt_print(periph->path, "%s: Called\n", __func__);
softc = (struct ctlfe_lun_softc *)periph->softc;
bus_softc = softc->parent_softc;
STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc, links);
/*
* XXX KDM is there anything else that needs to be done here?
*/
@ -705,14 +705,7 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
start_ccb->ccb_h.ccb_type = CTLFE_CCB_DEFAULT;
ccb_h = TAILQ_FIRST(&softc->work_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
panic("shouldn't get to the CCB waiting case!");
start_ccb->ccb_h.ccb_type = CTLFE_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
wakeup(&periph->ccb_list);
} else if (ccb_h == NULL) {
if (ccb_h == NULL) {
softc->ccbs_freed++;
xpt_release_ccb(start_ccb);
} else {
@ -791,7 +784,6 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
}
start_ccb->ccb_h.func_code = XPT_ABORT;
start_ccb->cab.abort_ccb = (union ccb *)atio;
start_ccb->ccb_h.cbfcnp = ctlfedone;
/* Tell the SIM that we've aborted this ATIO */
xpt_action(start_ccb);
@ -1004,6 +996,7 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
/*data_ptr*/ data_ptr,
/*dxfer_len*/ dxfer_len,
/*timeout*/ 5 * 1000);
start_ccb->ccb_h.flags |= CAM_UNLOCKED;
start_ccb->ccb_h.ccb_atio = atio;
if (((flags & CAM_SEND_STATUS) == 0)
&& (io != NULL))
@ -1011,7 +1004,9 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
softc->ctios_sent++;
cam_periph_unlock(periph);
xpt_action(start_ccb);
cam_periph_lock(periph);
if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) {
cam_release_devq(periph->path,
@ -1148,7 +1143,10 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
struct ctlfe_softc *bus_softc;
struct ccb_accept_tio *atio = NULL;
union ctl_io *io = NULL;
struct mtx *mtx;
KASSERT((done_ccb->ccb_h.flags & CAM_UNLOCKED) != 0,
("CCB in ctlfedone() without CAM_UNLOCKED flag"));
#ifdef CTLFE_DEBUG
printf("%s: entered, func_code = %#x, type = %#lx\n", __func__,
done_ccb->ccb_h.func_code, done_ccb->ccb_h.ccb_type);
@ -1156,12 +1154,8 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
softc = (struct ctlfe_lun_softc *)periph->softc;
bus_softc = softc->parent_softc;
if (done_ccb->ccb_h.ccb_type == CTLFE_CCB_WAITING) {
panic("shouldn't get to the CCB waiting case!");
wakeup(&done_ccb->ccb_h.cbfcnp);
return;
}
mtx = cam_periph_mtx(periph);
mtx_lock(mtx);
/*
* If the peripheral is invalid, ATIOs and immediate notify CCBs
@ -1177,7 +1171,7 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
case XPT_IMMEDIATE_NOTIFY:
case XPT_NOTIFY_ACKNOWLEDGE:
ctlfe_free_ccb(periph, done_ccb);
return;
goto out;
default:
break;
}
@ -1215,6 +1209,7 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
xpt_schedule(periph, /*priority*/ 1);
break;
}
mtx_unlock(mtx);
ctl_zero_io(io);
/* Save pointers on both sides */
@ -1271,7 +1266,7 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
#endif
ctl_queue(io);
break;
return;
}
case XPT_CONT_TARGET_IO: {
int srr = 0;
@ -1333,7 +1328,7 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
TAILQ_INSERT_HEAD(&softc->work_queue, &atio->ccb_h,
periph_links.tqe);
xpt_schedule(periph, /*priority*/ 1);
return;
break;
}
/*
@ -1359,10 +1354,11 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
}
if (periph->flags & CAM_PERIPH_INVALID) {
ctlfe_free_ccb(periph, (union ccb *)atio);
return;
} else {
xpt_action((union ccb *)atio);
softc->atios_sent++;
mtx_unlock(mtx);
xpt_action((union ccb *)atio);
return;
}
} else {
struct ctlfe_lun_cmd_info *cmd_info;
@ -1478,10 +1474,12 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
/*dxfer_len*/ dxfer_len,
/*timeout*/ 5 * 1000);
csio->ccb_h.flags |= CAM_UNLOCKED;
csio->resid = 0;
csio->ccb_h.ccb_atio = atio;
io->io_hdr.flags |= CTL_FLAG_DMA_INPROG;
softc->ctios_sent++;
mtx_unlock(mtx);
xpt_action((union ccb *)csio);
} else {
/*
@ -1490,10 +1488,12 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
*/
softc->ccbs_freed++;
xpt_release_ccb(done_ccb);
mtx_unlock(mtx);
/* Call the backend move done callback */
io->scsiio.be_move_done(io);
}
return;
}
break;
}
@ -1614,7 +1614,7 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
ctl_free_io(io);
ctlfe_free_ccb(periph, done_ccb);
return;
goto out;
}
if (send_ctl_io != 0) {
ctl_queue(io);
@ -1651,12 +1651,6 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
xpt_action(done_ccb);
softc->inots_sent++;
break;
case XPT_ABORT:
/*
* XPT_ABORT is an immediate CCB, we shouldn't get here.
*/
panic("%s: XPT_ABORT CCB returned!", __func__);
break;
case XPT_SET_SIM_KNOB:
case XPT_GET_SIM_KNOB:
break;
@ -1665,6 +1659,9 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
done_ccb->ccb_h.func_code);
break;
}
out:
mtx_unlock(mtx);
}
static void
@ -1674,17 +1671,12 @@ ctlfe_onoffline(void *arg, int online)
union ccb *ccb;
cam_status status;
struct cam_path *path;
struct cam_sim *sim;
int set_wwnn;
bus_softc = (struct ctlfe_softc *)arg;
set_wwnn = 0;
sim = bus_softc->sim;
mtx_assert(sim->mtx, MA_OWNED);
status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id,
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
if (status != CAM_REQ_CMP) {
@ -1844,12 +1836,8 @@ ctlfe_online(void *arg)
struct cam_path *path;
cam_status status;
struct ctlfe_lun_softc *lun_softc;
struct cam_sim *sim;
bus_softc = (struct ctlfe_softc *)arg;
sim = bus_softc->sim;
CAM_SIM_LOCK(sim);
/*
* Create the wildcard LUN before bringing the port online.
@ -1860,7 +1848,6 @@ ctlfe_online(void *arg)
if (status != CAM_REQ_CMP) {
printf("%s: unable to create path for wildcard periph\n",
__func__);
CAM_SIM_UNLOCK(sim);
return;
}
@ -1870,15 +1857,16 @@ ctlfe_online(void *arg)
xpt_print(path, "%s: unable to allocate softc for "
"wildcard periph\n", __func__);
xpt_free_path(path);
CAM_SIM_UNLOCK(sim);
return;
}
xpt_path_lock(path);
lun_softc->parent_softc = bus_softc;
lun_softc->flags |= CTLFE_LUN_WILDCARD;
mtx_lock(&bus_softc->lun_softc_mtx);
STAILQ_INSERT_TAIL(&bus_softc->lun_softc_list, lun_softc, links);
mtx_unlock(&bus_softc->lun_softc_mtx);
status = cam_periph_alloc(ctlferegister,
ctlfeoninvalidate,
@ -1901,11 +1889,10 @@ ctlfe_online(void *arg)
entry->status_text : "Unknown", status);
}
xpt_free_path(path);
ctlfe_onoffline(arg, /*online*/ 1);
CAM_SIM_UNLOCK(sim);
xpt_path_unlock(path);
xpt_free_path(path);
}
static void
@ -1915,14 +1902,8 @@ ctlfe_offline(void *arg)
struct cam_path *path;
cam_status status;
struct cam_periph *periph;
struct cam_sim *sim;
bus_softc = (struct ctlfe_softc *)arg;
sim = bus_softc->sim;
CAM_SIM_LOCK(sim);
ctlfe_onoffline(arg, /*online*/ 0);
/*
* Disable the wildcard LUN for this port now that we have taken
@ -1932,19 +1913,20 @@ ctlfe_offline(void *arg)
bus_softc->path_id, CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD);
if (status != CAM_REQ_CMP) {
CAM_SIM_UNLOCK(sim);
printf("%s: unable to create path for wildcard periph\n",
__func__);
return;
}
xpt_path_lock(path);
ctlfe_onoffline(arg, /*online*/ 0);
if ((periph = cam_periph_find(path, "ctl")) != NULL)
cam_periph_invalidate(periph);
xpt_path_unlock(path);
xpt_free_path(path);
CAM_SIM_UNLOCK(sim);
}
static int
@ -1970,15 +1952,13 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
struct ctlfe_lun_softc *softc;
struct cam_path *path;
struct cam_periph *periph;
struct cam_sim *sim;
cam_status status;
bus_softc = (struct ctlfe_softc *)arg;
sim = bus_softc->sim;
status = xpt_create_path_unlocked(&path, /*periph*/ NULL,
bus_softc->path_id,
targ_id.id, lun_id);
status = xpt_create_path(&path, /*periph*/ NULL,
bus_softc->path_id,
targ_id.id, lun_id);
/* XXX KDM need some way to return status to CTL here? */
if (status != CAM_REQ_CMP) {
printf("%s: could not create path, status %#x\n", __func__,
@ -1987,18 +1967,20 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
}
softc = malloc(sizeof(*softc), M_CTLFE, M_WAITOK | M_ZERO);
CAM_SIM_LOCK(sim);
xpt_path_lock(path);
periph = cam_periph_find(path, "ctl");
if (periph != NULL) {
/* We've already got a periph, no need to alloc a new one. */
xpt_path_unlock(path);
xpt_free_path(path);
free(softc, M_CTLFE);
CAM_SIM_UNLOCK(sim);
return (0);
}
softc->parent_softc = bus_softc;
mtx_lock(&bus_softc->lun_softc_mtx);
STAILQ_INSERT_TAIL(&bus_softc->lun_softc_list, softc, links);
mtx_unlock(&bus_softc->lun_softc_mtx);
status = cam_periph_alloc(ctlferegister,
ctlfeoninvalidate,
@ -2011,10 +1993,8 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
0,
softc);
xpt_path_unlock(path);
xpt_free_path(path);
CAM_SIM_UNLOCK(sim);
return (0);
}
@ -2027,12 +2007,10 @@ ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id)
{
struct ctlfe_softc *softc;
struct ctlfe_lun_softc *lun_softc;
struct cam_sim *sim;
softc = (struct ctlfe_softc *)arg;
sim = softc->sim;
CAM_SIM_LOCK(sim);
mtx_lock(&softc->lun_softc_mtx);
STAILQ_FOREACH(lun_softc, &softc->lun_softc_list, links) {
struct cam_path *path;
@ -2044,16 +2022,18 @@ ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id)
}
}
if (lun_softc == NULL) {
CAM_SIM_UNLOCK(sim);
mtx_unlock(&softc->lun_softc_mtx);
printf("%s: can't find target %d lun %d\n", __func__,
targ_id.id, lun_id);
return (1);
}
cam_periph_acquire(lun_softc->periph);
mtx_unlock(&softc->lun_softc_mtx);
cam_periph_lock(lun_softc->periph);
cam_periph_invalidate(lun_softc->periph);
CAM_SIM_UNLOCK(sim);
cam_periph_unlock(lun_softc->periph);
cam_periph_release(lun_softc->periph);
return (0);
}
@ -2064,12 +2044,6 @@ ctlfe_dump_sim(struct cam_sim *sim)
printf("%s%d: max tagged openings: %d, max dev openings: %d\n",
sim->sim_name, sim->unit_number,
sim->max_tagged_dev_openings, sim->max_dev_openings);
printf("%s%d: max_ccbs: %u, ccb_count: %u\n",
sim->sim_name, sim->unit_number,
sim->max_ccbs, sim->ccb_count);
printf("%s%d: ccb_freeq is %sempty\n",
sim->sim_name, sim->unit_number,
(SLIST_FIRST(&sim->ccb_freeq) == NULL) ? "" : "NOT ");
printf("\n");
}
@ -2200,17 +2174,13 @@ static void
ctlfe_datamove_done(union ctl_io *io)
{
union ccb *ccb;
struct cam_sim *sim;
struct cam_periph *periph;
struct ctlfe_lun_softc *softc;
ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
sim = xpt_path_sim(ccb->ccb_h.path);
CAM_SIM_LOCK(sim);
periph = xpt_path_periph(ccb->ccb_h.path);
cam_periph_lock(periph);
softc = (struct ctlfe_lun_softc *)periph->softc;
@ -2255,7 +2225,7 @@ ctlfe_datamove_done(union ctl_io *io)
xpt_schedule(periph, /*priority*/ 1);
}
CAM_SIM_UNLOCK(sim);
cam_periph_unlock(periph);
}
static void

View File

@ -118,7 +118,6 @@ typedef enum {
typedef enum {
CD_CCB_PROBE = 0x01,
CD_CCB_BUFFER_IO = 0x02,
CD_CCB_WAITING = 0x03,
CD_CCB_TUR = 0x04,
CD_CCB_TYPE_MASK = 0x0F,
CD_CCB_RETRY_UA = 0x10
@ -549,7 +548,7 @@ cdasync(void *callback_arg, u_int32_t code,
status = cam_periph_alloc(cdregister, cdoninvalidate,
cdcleanup, cdstart,
"cd", CAM_PERIPH_BIO,
cgd->ccb_h.path, cdasync,
path, cdasync,
AC_FOUND_DEVICE, cgd);
if (status != CAM_REQ_CMP
@ -980,9 +979,9 @@ cdregister(struct cam_periph *periph, void *arg)
STAILQ_INIT(&nchanger->chluns);
callout_init_mtx(&nchanger->long_handle,
periph->sim->mtx, 0);
cam_periph_mtx(periph), 0);
callout_init_mtx(&nchanger->short_handle,
periph->sim->mtx, 0);
cam_periph_mtx(periph), 0);
mtx_lock(&changerq_mtx);
num_changers++;
@ -1051,7 +1050,7 @@ cdregister(struct cam_periph *periph, void *arg)
/*
* Schedule a periodic media polling events.
*/
callout_init_mtx(&softc->mediapoll_c, periph->sim->mtx, 0);
callout_init_mtx(&softc->mediapoll_c, cam_periph_mtx(periph), 0);
if ((softc->flags & CD_FLAG_DISC_REMOVABLE) &&
(softc->flags & CD_FLAG_CHANGER) == 0 &&
(cgd->inq_flags & SID_AEN) == 0 &&
@ -1535,14 +1534,7 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
case CD_STATE_NORMAL:
{
bp = bioq_first(&softc->bio_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
start_ccb->ccb_h.ccb_state = CD_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
wakeup(&periph->ccb_list);
} else if (bp == NULL) {
if (bp == NULL) {
if (softc->tur) {
softc->tur = 0;
csio = &start_ccb->csio;
@ -1606,11 +1598,9 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
xpt_action(start_ccb);
}
if (bp != NULL || softc->tur ||
periph->immediate_priority != CAM_PRIORITY_NONE) {
if (bp != NULL || softc->tur) {
/* Have more work to do, so ensure we stay scheduled */
xpt_schedule(periph, min(CAM_PRIORITY_NORMAL,
periph->immediate_priority));
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
}
break;
}
@ -1895,15 +1885,6 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
cam_periph_unhold(periph);
return;
}
case CD_CCB_WAITING:
{
/* Caller will release the CCB */
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
("trying to wakeup ccbwait\n"));
wakeup(&done_ccb->ccb_h.cbfcnp);
return;
}
case CD_CCB_TUR:
{
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {

View File

@ -116,8 +116,7 @@ typedef enum {
} ch_state;
typedef enum {
CH_CCB_PROBE,
CH_CCB_WAITING
CH_CCB_PROBE
} ch_ccb_types;
typedef enum {
@ -248,20 +247,19 @@ chinit(void)
static void
chdevgonecb(void *arg)
{
struct cam_sim *sim;
struct ch_softc *softc;
struct cam_periph *periph;
struct mtx *mtx;
int i;
periph = (struct cam_periph *)arg;
sim = periph->sim;
softc = (struct ch_softc *)periph->softc;
mtx = cam_periph_mtx(periph);
mtx_lock(mtx);
softc = (struct ch_softc *)periph->softc;
KASSERT(softc->open_count >= 0, ("Negative open count %d",
softc->open_count));
mtx_lock(sim->mtx);
/*
* When we get this callback, we will get no more close calls from
* devfs. So if we have any dangling opens, we need to release the
@ -278,13 +276,13 @@ chdevgonecb(void *arg)
cam_periph_release_locked(periph);
/*
* We reference the SIM lock directly here, instead of using
* We reference the lock directly here, instead of using
* cam_periph_unlock(). The reason is that the final call to
* cam_periph_release_locked() above could result in the periph
* getting freed. If that is the case, dereferencing the periph
* with a cam_periph_unlock() call would cause a page fault.
*/
mtx_unlock(sim->mtx);
mtx_unlock(mtx);
}
static void
@ -350,7 +348,7 @@ chasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
*/
status = cam_periph_alloc(chregister, choninvalidate,
chcleanup, chstart, "ch",
CAM_PERIPH_BIO, cgd->ccb_h.path,
CAM_PERIPH_BIO, path,
chasync, AC_FOUND_DEVICE, cgd);
if (status != CAM_REQ_CMP
@ -503,25 +501,23 @@ chopen(struct cdev *dev, int flags, int fmt, struct thread *td)
static int
chclose(struct cdev *dev, int flag, int fmt, struct thread *td)
{
struct cam_sim *sim;
struct cam_periph *periph;
struct ch_softc *softc;
struct mtx *mtx;
periph = (struct cam_periph *)dev->si_drv1;
if (periph == NULL)
return(ENXIO);
mtx = cam_periph_mtx(periph);
mtx_lock(mtx);
sim = periph->sim;
softc = (struct ch_softc *)periph->softc;
mtx_lock(sim->mtx);
softc->open_count--;
cam_periph_release_locked(periph);
/*
* We reference the SIM lock directly here, instead of using
* We reference the lock directly here, instead of using
* cam_periph_unlock(). The reason is that the call to
* cam_periph_release_locked() above could result in the periph
* getting freed. If that is the case, dereferencing the periph
@ -532,7 +528,7 @@ chclose(struct cdev *dev, int flag, int fmt, struct thread *td)
* protect the open count and avoid another lock acquisition and
* release.
*/
mtx_unlock(sim->mtx);
mtx_unlock(mtx);
return(0);
}
@ -547,14 +543,7 @@ chstart(struct cam_periph *periph, union ccb *start_ccb)
switch (softc->state) {
case CH_STATE_NORMAL:
{
if (periph->immediate_priority <= periph->pinfo.priority){
start_ccb->ccb_h.ccb_state = CH_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
wakeup(&periph->ccb_list);
}
xpt_release_ccb(start_ccb);
break;
}
case CH_STATE_PROBE:
@ -734,12 +723,6 @@ chdone(struct cam_periph *periph, union ccb *done_ccb)
cam_periph_unhold(periph);
return;
}
case CH_CCB_WAITING:
{
/* Caller will release the CCB */
wakeup(&done_ccb->ccb_h.cbfcnp);
return;
}
default:
break;
}
@ -1724,10 +1707,8 @@ chscsiversion(struct cam_periph *periph)
struct scsi_inquiry_data *inq_data;
struct ccb_getdev *cgd;
int dev_scsi_version;
struct cam_sim *sim;
sim = xpt_path_sim(periph->path);
mtx_assert(sim->mtx, MA_OWNED);
cam_periph_assert(periph, MA_OWNED);
if ((cgd = (struct ccb_getdev *)xpt_alloc_ccb_nowait()) == NULL)
return (-1);
/*

View File

@ -118,7 +118,6 @@ typedef enum {
DA_CCB_PROBE_BDC = 0x05,
DA_CCB_PROBE_ATA = 0x06,
DA_CCB_BUFFER_IO = 0x07,
DA_CCB_WAITING = 0x08,
DA_CCB_DUMP = 0x0A,
DA_CCB_DELETE = 0x0B,
DA_CCB_TUR = 0x0C,
@ -229,6 +228,7 @@ struct da_softc {
uint8_t unmap_buf[UNMAP_BUF_SIZE];
struct scsi_read_capacity_data_long rcaplong;
struct callout mediapoll_c;
int refcount;
};
#define dadeleteflag(softc, delete_method, enable) \
@ -1277,86 +1277,72 @@ daclose(struct disk *dp)
{
struct cam_periph *periph;
struct da_softc *softc;
union ccb *ccb;
int error;
periph = (struct cam_periph *)dp->d_drv1;
cam_periph_lock(periph);
if (cam_periph_hold(periph, PRIBIO) != 0) {
cam_periph_unlock(periph);
cam_periph_release(periph);
return (0);
}
softc = (struct da_softc *)periph->softc;
cam_periph_lock(periph);
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
("daclose\n"));
if ((softc->flags & DA_FLAG_DIRTY) != 0 &&
(softc->quirks & DA_Q_NO_SYNC_CACHE) == 0 &&
(softc->flags & DA_FLAG_PACK_INVALID) == 0) {
union ccb *ccb;
if (cam_periph_hold(periph, PRIBIO) == 0) {
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
/* Flush disk cache. */
if ((softc->flags & DA_FLAG_DIRTY) != 0 &&
(softc->quirks & DA_Q_NO_SYNC_CACHE) == 0 &&
(softc->flags & DA_FLAG_PACK_INVALID) == 0) {
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
scsi_synchronize_cache(&ccb->csio, /*retries*/1,
/*cbfcnp*/dadone, MSG_SIMPLE_Q_TAG,
/*begin_lba*/0, /*lb_count*/0, SSD_FULL_SIZE,
5 * 60 * 1000);
error = cam_periph_runccb(ccb, daerror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA | SF_QUIET_IR,
softc->disk->d_devstat);
if (error == 0)
softc->flags &= ~DA_FLAG_DIRTY;
xpt_release_ccb(ccb);
}
scsi_synchronize_cache(&ccb->csio,
/*retries*/1,
/*cbfcnp*/dadone,
MSG_SIMPLE_Q_TAG,
/*begin_lba*/0,/* Cover the whole disk */
/*lb_count*/0,
SSD_FULL_SIZE,
5 * 60 * 1000);
error = cam_periph_runccb(ccb, daerror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA | SF_QUIET_IR,
softc->disk->d_devstat);
if (error == 0)
softc->flags &= ~DA_FLAG_DIRTY;
xpt_release_ccb(ccb);
}
if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0) {
if ((softc->quirks & DA_Q_NO_PREVENT) == 0)
/* Allow medium removal. */
if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0 &&
(softc->quirks & DA_Q_NO_PREVENT) == 0)
daprevent(periph, PR_ALLOW);
/*
* If we've got removeable media, mark the blocksize as
* unavailable, since it could change when new media is
* inserted.
*/
softc->disk->d_devstat->flags |= DEVSTAT_BS_UNAVAILABLE;
cam_periph_unhold(periph);
}
/*
* If we've got removeable media, mark the blocksize as
* unavailable, since it could change when new media is
* inserted.
*/
if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0)
softc->disk->d_devstat->flags |= DEVSTAT_BS_UNAVAILABLE;
softc->flags &= ~DA_FLAG_OPEN;
cam_periph_unhold(periph);
while (softc->refcount != 0)
cam_periph_sleep(periph, &softc->refcount, PRIBIO, "daclose", 1);
cam_periph_unlock(periph);
cam_periph_release(periph);
return (0);
return (0);
}
static void
daschedule(struct cam_periph *periph)
{
struct da_softc *softc = (struct da_softc *)periph->softc;
uint32_t prio;
if (softc->state != DA_STATE_NORMAL)
return;
/* Check if cam_periph_getccb() was called. */
prio = periph->immediate_priority;
/* Check if we have more work to do. */
if (bioq_first(&softc->bio_queue) ||
(!softc->delete_running && bioq_first(&softc->delete_queue)) ||
softc->tur) {
prio = CAM_PRIORITY_NORMAL;
xpt_schedule(periph, CAM_PRIORITY_NORMAL);
}
/* Schedule CCB if any of above is true. */
if (prio != CAM_PRIORITY_NONE)
xpt_schedule(periph, prio);
}
/*
@ -1390,9 +1376,7 @@ dastrategy(struct bio *bp)
* Place it in the queue of disk activities for this disk
*/
if (bp->bio_cmd == BIO_DELETE) {
if (bp->bio_bcount == 0)
biodone(bp);
else if (DA_SIO)
if (DA_SIO)
bioq_disksort(&softc->delete_queue, bp);
else
bioq_insert_tail(&softc->delete_queue, bp);
@ -1629,7 +1613,7 @@ daasync(void *callback_arg, u_int32_t code,
status = cam_periph_alloc(daregister, daoninvalidate,
dacleanup, dastart,
"da", CAM_PERIPH_BIO,
cgd->ccb_h.path, daasync,
path, daasync,
AC_FOUND_DEVICE, cgd);
if (status != CAM_REQ_CMP
@ -2074,7 +2058,7 @@ daregister(struct cam_periph *periph, void *arg)
* Schedule a periodic event to occasionally send an
* ordered tag to a device.
*/
callout_init_mtx(&softc->sendordered_c, periph->sim->mtx, 0);
callout_init_mtx(&softc->sendordered_c, cam_periph_mtx(periph), 0);
callout_reset(&softc->sendordered_c,
(da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL,
dasendorderedtag, softc);
@ -2194,7 +2178,7 @@ daregister(struct cam_periph *periph, void *arg)
/*
* Schedule a periodic media polling events.
*/
callout_init_mtx(&softc->mediapoll_c, periph->sim->mtx, 0);
callout_init_mtx(&softc->mediapoll_c, cam_periph_mtx(periph), 0);
if ((softc->flags & DA_FLAG_PACK_REMOVABLE) &&
(cgd->inq_flags & SID_AEN) == 0 &&
da_poll_period != 0)
@ -2222,20 +2206,6 @@ dastart(struct cam_periph *periph, union ccb *start_ccb)
struct bio *bp;
uint8_t tag_code;
/* Execute immediate CCB if waiting. */
if (periph->immediate_priority <= periph->pinfo.priority) {
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
("queuing for immediate ccb\n"));
start_ccb->ccb_h.ccb_state = DA_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
wakeup(&periph->ccb_list);
/* May have more work to do, so ensure we stay scheduled */
daschedule(periph);
break;
}
/* Run BIO_DELETE if not running yet. */
if (!softc->delete_running &&
(bp = bioq_first(&softc->delete_queue)) != NULL) {
@ -2324,6 +2294,7 @@ dastart(struct cam_periph *periph, union ccb *start_ccb)
break;
}
start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO;
start_ccb->ccb_h.flags |= CAM_UNLOCKED;
out:
/*
@ -2341,7 +2312,11 @@ dastart(struct cam_periph *periph, union ccb *start_ccb)
}
start_ccb->ccb_h.ccb_bp = bp;
softc->refcount++;
cam_periph_unlock(periph);
xpt_action(start_ccb);
cam_periph_lock(periph);
softc->refcount--;
/* May have more work to do, so ensure we stay scheduled */
daschedule(periph);
@ -2636,6 +2611,7 @@ da_delete_unmap(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
/*sense_len*/SSD_FULL_SIZE,
da_default_timeout * 1000);
ccb->ccb_h.ccb_state = DA_CCB_DELETE;
ccb->ccb_h.flags |= CAM_UNLOCKED;
}
static void
@ -2716,6 +2692,7 @@ da_delete_trim(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
/*sense_len*/SSD_FULL_SIZE,
da_default_timeout * 1000);
ccb->ccb_h.ccb_state = DA_CCB_DELETE;
ccb->ccb_h.flags |= CAM_UNLOCKED;
}
/*
@ -2772,6 +2749,7 @@ da_delete_ws(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
/*sense_len*/SSD_FULL_SIZE,
da_default_timeout * 1000);
ccb->ccb_h.ccb_state = DA_CCB_DELETE;
ccb->ccb_h.flags |= CAM_UNLOCKED;
}
static int
@ -2906,6 +2884,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
{
struct bio *bp, *bp1;
cam_periph_lock(periph);
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
int error;
@ -2922,6 +2901,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
* A retry was scheduled, so
* just return.
*/
cam_periph_unlock(periph);
return;
}
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
@ -2998,9 +2978,18 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
if (softc->outstanding_cmds == 0)
softc->flags |= DA_FLAG_WENT_IDLE;
xpt_release_ccb(done_ccb);
if (state == DA_CCB_DELETE) {
while ((bp1 = bioq_takefirst(&softc->delete_run_queue))
!= NULL) {
TAILQ_HEAD(, bio) queue;
TAILQ_INIT(&queue);
TAILQ_CONCAT(&queue, &softc->delete_run_queue.queue, bio_queue);
softc->delete_run_queue.insert_point = NULL;
softc->delete_running = 0;
daschedule(periph);
cam_periph_unlock(periph);
while ((bp1 = TAILQ_FIRST(&queue)) != NULL) {
TAILQ_REMOVE(&queue, bp1, bio_queue);
bp1->bio_error = bp->bio_error;
if (bp->bio_flags & BIO_ERROR) {
bp1->bio_flags |= BIO_ERROR;
@ -3009,13 +2998,11 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
bp1->bio_resid = 0;
biodone(bp1);
}
softc->delete_running = 0;
if (bp != NULL)
biodone(bp);
daschedule(periph);
} else if (bp != NULL)
} else
cam_periph_unlock(periph);
if (bp != NULL)
biodone(bp);
break;
return;
}
case DA_CCB_PROBE_RC:
case DA_CCB_PROBE_RC16:
@ -3465,12 +3452,6 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
daprobedone(periph, done_ccb);
return;
}
case DA_CCB_WAITING:
{
/* Caller will release the CCB */
wakeup(&done_ccb->ccb_h.cbfcnp);
return;
}
case DA_CCB_DUMP:
/* No-op. We're polling */
return;

View File

@ -69,7 +69,6 @@ static periph_init_t enc_init;
static periph_ctor_t enc_ctor;
static periph_oninv_t enc_oninvalidate;
static periph_dtor_t enc_dtor;
static periph_start_t enc_start;
static void enc_async(void *, uint32_t, struct cam_path *, void *);
static enctyp enc_type(struct ccb_getdev *);
@ -113,17 +112,16 @@ enc_init(void)
static void
enc_devgonecb(void *arg)
{
struct cam_sim *sim;
struct cam_periph *periph;
struct enc_softc *enc;
struct mtx *mtx;
int i;
periph = (struct cam_periph *)arg;
sim = periph->sim;
mtx = cam_periph_mtx(periph);
mtx_lock(mtx);
enc = (struct enc_softc *)periph->softc;
mtx_lock(sim->mtx);
/*
* When we get this callback, we will get no more close calls from
* devfs. So if we have any dangling opens, we need to release the
@ -140,13 +138,13 @@ enc_devgonecb(void *arg)
cam_periph_release_locked(periph);
/*
* We reference the SIM lock directly here, instead of using
* We reference the lock directly here, instead of using
* cam_periph_unlock(). The reason is that the final call to
* cam_periph_release_locked() above could result in the periph
* getting freed. If that is the case, dereferencing the periph
* with a cam_periph_unlock() call would cause a page fault.
*/
mtx_unlock(sim->mtx);
mtx_unlock(mtx);
}
static void
@ -243,8 +241,8 @@ enc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
}
status = cam_periph_alloc(enc_ctor, enc_oninvalidate,
enc_dtor, enc_start, "ses", CAM_PERIPH_BIO,
cgd->ccb_h.path, enc_async, AC_FOUND_DEVICE, cgd);
enc_dtor, NULL, "ses", CAM_PERIPH_BIO,
path, enc_async, AC_FOUND_DEVICE, cgd);
if (status != CAM_REQ_CMP && status != CAM_REQ_INPROG) {
printf("enc_async: Unable to probe new device due to "
@ -299,25 +297,23 @@ enc_open(struct cdev *dev, int flags, int fmt, struct thread *td)
static int
enc_close(struct cdev *dev, int flag, int fmt, struct thread *td)
{
struct cam_sim *sim;
struct cam_periph *periph;
struct enc_softc *enc;
struct mtx *mtx;
periph = (struct cam_periph *)dev->si_drv1;
if (periph == NULL)
return (ENXIO);
mtx = cam_periph_mtx(periph);
mtx_lock(mtx);
sim = periph->sim;
enc = periph->softc;
mtx_lock(sim->mtx);
enc->open_count--;
cam_periph_release_locked(periph);
/*
* We reference the SIM lock directly here, instead of using
* We reference the lock directly here, instead of using
* cam_periph_unlock(). The reason is that the call to
* cam_periph_release_locked() above could result in the periph
* getting freed. If that is the case, dereferencing the periph
@ -328,34 +324,11 @@ enc_close(struct cdev *dev, int flag, int fmt, struct thread *td)
* protect the open count and avoid another lock acquisition and
* release.
*/
mtx_unlock(sim->mtx);
mtx_unlock(mtx);
return (0);
}
static void
enc_start(struct cam_periph *p, union ccb *sccb)
{
struct enc_softc *enc;
enc = p->softc;
ENC_DLOG(enc, "%s enter imm=%d prio=%d\n",
__func__, p->immediate_priority, p->pinfo.priority);
if (p->immediate_priority <= p->pinfo.priority) {
SLIST_INSERT_HEAD(&p->ccb_list, &sccb->ccb_h, periph_links.sle);
p->immediate_priority = CAM_PRIORITY_NONE;
wakeup(&p->ccb_list);
} else
xpt_release_ccb(sccb);
ENC_DLOG(enc, "%s exit\n", __func__);
}
void
enc_done(struct cam_periph *periph, union ccb *dccb)
{
wakeup(&dccb->ccb_h.cbfcnp);
}
int
enc_error(union ccb *ccb, uint32_t cflags, uint32_t sflags)
{
@ -614,7 +587,7 @@ enc_runcmd(struct enc_softc *enc, char *cdb, int cdbl, char *dptr, int *dlenp)
if (enc->enc_type == ENC_SEMB_SES || enc->enc_type == ENC_SEMB_SAFT) {
tdlen = min(dlen, 1020);
tdlen = (tdlen + 3) & ~3;
cam_fill_ataio(&ccb->ataio, 0, enc_done, ddf, 0, dptr, tdlen,
cam_fill_ataio(&ccb->ataio, 0, NULL, ddf, 0, dptr, tdlen,
30 * 1000);
if (cdb[0] == RECEIVE_DIAGNOSTIC)
ata_28bit_cmd(&ccb->ataio,
@ -632,7 +605,7 @@ enc_runcmd(struct enc_softc *enc, char *cdb, int cdbl, char *dptr, int *dlenp)
0x80, tdlen / 4);
} else {
tdlen = dlen;
cam_fill_csio(&ccb->csio, 0, enc_done, ddf, MSG_SIMPLE_Q_TAG,
cam_fill_csio(&ccb->csio, 0, NULL, ddf, MSG_SIMPLE_Q_TAG,
dptr, dlen, sizeof (struct scsi_sense_data), cdbl,
60 * 1000);
bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cdbl);
@ -886,7 +859,7 @@ enc_kproc_init(enc_softc_t *enc)
{
int result;
callout_init_mtx(&enc->status_updater, enc->periph->sim->mtx, 0);
callout_init_mtx(&enc->status_updater, cam_periph_mtx(enc->periph), 0);
if (cam_periph_acquire(enc->periph) != CAM_REQ_CMP)
return (ENXIO);

View File

@ -192,7 +192,6 @@ struct ses_mgmt_mode_page {
/* Enclosure core interface for sub-drivers */
int enc_runcmd(struct enc_softc *, char *, int, char *, int *);
void enc_log(struct enc_softc *, const char *, ...);
void enc_done(struct cam_periph *, union ccb *);
int enc_error(union ccb *, uint32_t, uint32_t);
void enc_update_request(enc_softc_t *, uint32_t);

View File

@ -243,12 +243,12 @@ safte_fill_read_buf_io(enc_softc_t *enc, struct enc_fsm_state *state,
if (enc->enc_type == ENC_SEMB_SAFT) {
semb_read_buffer(&ccb->ataio, /*retries*/5,
enc_done, MSG_SIMPLE_Q_TAG,
NULL, MSG_SIMPLE_Q_TAG,
state->page_code, buf, state->buf_size,
state->timeout);
} else {
scsi_read_buffer(&ccb->csio, /*retries*/5,
enc_done, MSG_SIMPLE_Q_TAG, 1,
NULL, MSG_SIMPLE_Q_TAG, 1,
state->page_code, 0, buf, state->buf_size,
SSD_FULL_SIZE, state->timeout);
}
@ -942,11 +942,11 @@ safte_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
if (enc->enc_type == ENC_SEMB_SAFT) {
semb_write_buffer(&ccb->ataio, /*retries*/5,
enc_done, MSG_SIMPLE_Q_TAG,
NULL, MSG_SIMPLE_Q_TAG,
buf, xfer_len, state->timeout);
} else {
scsi_write_buffer(&ccb->csio, /*retries*/5,
enc_done, MSG_SIMPLE_Q_TAG, 1,
NULL, MSG_SIMPLE_Q_TAG, 1,
0, 0, buf, xfer_len,
SSD_FULL_SIZE, state->timeout);
}

View File

@ -888,7 +888,6 @@ ses_path_iter_devid_callback(enc_softc_t *enc, enc_element_t *elem,
struct device_match_result *device_match;
struct device_match_pattern *device_pattern;
ses_path_iter_args_t *args;
struct cam_sim *sim;
args = (ses_path_iter_args_t *)arg;
match_pattern.type = DEV_MATCH_DEVICE;
@ -901,10 +900,10 @@ ses_path_iter_devid_callback(enc_softc_t *enc, enc_element_t *elem,
device_pattern->data.devid_pat.id_len);
memset(&cdm, 0, sizeof(cdm));
if (xpt_create_path_unlocked(&cdm.ccb_h.path, /*periph*/NULL,
CAM_XPT_PATH_ID,
CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD) != CAM_REQ_CMP)
if (xpt_create_path(&cdm.ccb_h.path, /*periph*/NULL,
CAM_XPT_PATH_ID,
CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD) != CAM_REQ_CMP)
return;
cdm.ccb_h.func_code = XPT_DEV_MATCH;
@ -914,11 +913,8 @@ ses_path_iter_devid_callback(enc_softc_t *enc, enc_element_t *elem,
cdm.match_buf_len = sizeof(match_result);
cdm.matches = &match_result;
sim = xpt_path_sim(cdm.ccb_h.path);
CAM_SIM_LOCK(sim);
xpt_action((union ccb *)&cdm);
xpt_free_path(cdm.ccb_h.path);
CAM_SIM_UNLOCK(sim);
if ((cdm.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP
|| (cdm.status != CAM_DEV_MATCH_LAST
@ -927,18 +923,15 @@ ses_path_iter_devid_callback(enc_softc_t *enc, enc_element_t *elem,
return;
device_match = &match_result.result.device_result;
if (xpt_create_path_unlocked(&cdm.ccb_h.path, /*periph*/NULL,
device_match->path_id,
device_match->target_id,
device_match->target_lun) != CAM_REQ_CMP)
if (xpt_create_path(&cdm.ccb_h.path, /*periph*/NULL,
device_match->path_id,
device_match->target_id,
device_match->target_lun) != CAM_REQ_CMP)
return;
args->callback(enc, elem, cdm.ccb_h.path, args->callback_arg);
sim = xpt_path_sim(cdm.ccb_h.path);
CAM_SIM_LOCK(sim);
xpt_free_path(cdm.ccb_h.path);
CAM_SIM_UNLOCK(sim);
}
/**
@ -1186,7 +1179,7 @@ ses_set_timed_completion(enc_softc_t *enc, uint8_t tc_en)
if (mode_buf == NULL)
goto out;
scsi_mode_sense(&ccb->csio, /*retries*/4, enc_done, MSG_SIMPLE_Q_TAG,
scsi_mode_sense(&ccb->csio, /*retries*/4, NULL, MSG_SIMPLE_Q_TAG,
/*dbd*/FALSE, SMS_PAGE_CTRL_CURRENT, SES_MGMT_MODE_PAGE_CODE,
mode_buf, mode_buf_len, SSD_FULL_SIZE, /*timeout*/60 * 1000);
@ -1214,7 +1207,7 @@ ses_set_timed_completion(enc_softc_t *enc, uint8_t tc_en)
/* SES2r20: a completion time of zero means as long as possible */
bzero(&mgmt->max_comp_time, sizeof(mgmt->max_comp_time));
scsi_mode_select(&ccb->csio, 5, enc_done, MSG_SIMPLE_Q_TAG,
scsi_mode_select(&ccb->csio, 5, NULL, MSG_SIMPLE_Q_TAG,
/*page_fmt*/FALSE, /*save_pages*/TRUE, mode_buf, mode_buf_len,
SSD_FULL_SIZE, /*timeout*/60 * 1000);
@ -2030,12 +2023,12 @@ ses_fill_rcv_diag_io(enc_softc_t *enc, struct enc_fsm_state *state,
if (enc->enc_type == ENC_SEMB_SES) {
semb_receive_diagnostic_results(&ccb->ataio, /*retries*/5,
enc_done, MSG_SIMPLE_Q_TAG, /*pcv*/1,
NULL, MSG_SIMPLE_Q_TAG, /*pcv*/1,
state->page_code, buf, state->buf_size,
state->timeout);
} else {
scsi_receive_diagnostic_results(&ccb->csio, /*retries*/5,
enc_done, MSG_SIMPLE_Q_TAG, /*pcv*/1,
NULL, MSG_SIMPLE_Q_TAG, /*pcv*/1,
state->page_code, buf, state->buf_size,
SSD_FULL_SIZE, state->timeout);
}
@ -2153,12 +2146,12 @@ ses_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
/* Fill out the ccb */
if (enc->enc_type == ENC_SEMB_SES) {
semb_send_diagnostic(&ccb->ataio, /*retries*/5, enc_done,
semb_send_diagnostic(&ccb->ataio, /*retries*/5, NULL,
MSG_SIMPLE_Q_TAG,
buf, ses_page_length(&ses_cache->status_page->hdr),
state->timeout);
} else {
scsi_send_diagnostic(&ccb->csio, /*retries*/5, enc_done,
scsi_send_diagnostic(&ccb->csio, /*retries*/5, NULL,
MSG_SIMPLE_Q_TAG, /*unit_offline*/0,
/*device_offline*/0, /*self_test*/0,
/*page_format*/1, /*self_test_code*/0,

View File

@ -65,8 +65,7 @@ typedef enum {
} pass_state;
typedef enum {
PASS_CCB_BUFFER_IO,
PASS_CCB_WAITING
PASS_CCB_BUFFER_IO
} pass_ccb_types;
#define ccb_type ppriv_field0
@ -94,12 +93,9 @@ static periph_init_t passinit;
static periph_ctor_t passregister;
static periph_oninv_t passoninvalidate;
static periph_dtor_t passcleanup;
static periph_start_t passstart;
static void pass_add_physpath(void *context, int pending);
static void passasync(void *callback_arg, u_int32_t code,
struct cam_path *path, void *arg);
static void passdone(struct cam_periph *periph,
union ccb *done_ccb);
static int passerror(union ccb *ccb, u_int32_t cam_flags,
u_int32_t sense_flags);
static int passsendccb(struct cam_periph *periph, union ccb *ccb,
@ -143,20 +139,19 @@ passinit(void)
static void
passdevgonecb(void *arg)
{
struct cam_sim *sim;
struct cam_periph *periph;
struct mtx *mtx;
struct pass_softc *softc;
int i;
periph = (struct cam_periph *)arg;
sim = periph->sim;
softc = (struct pass_softc *)periph->softc;
mtx = cam_periph_mtx(periph);
mtx_lock(mtx);
softc = (struct pass_softc *)periph->softc;
KASSERT(softc->open_count >= 0, ("Negative open count %d",
softc->open_count));
mtx_lock(sim->mtx);
/*
* When we get this callback, we will get no more close calls from
* devfs. So if we have any dangling opens, we need to release the
@ -173,13 +168,13 @@ passdevgonecb(void *arg)
cam_periph_release_locked(periph);
/*
* We reference the SIM lock directly here, instead of using
* We reference the lock directly here, instead of using
* cam_periph_unlock(). The reason is that the final call to
* cam_periph_release_locked() above could result in the periph
* getting freed. If that is the case, dereferencing the periph
* with a cam_periph_unlock() call would cause a page fault.
*/
mtx_unlock(sim->mtx);
mtx_unlock(mtx);
}
static void
@ -295,8 +290,8 @@ passasync(void *callback_arg, u_int32_t code,
* process.
*/
status = cam_periph_alloc(passregister, passoninvalidate,
passcleanup, passstart, "pass",
CAM_PERIPH_BIO, cgd->ccb_h.path,
passcleanup, NULL, "pass",
CAM_PERIPH_BIO, path,
passasync, AC_FOUND_DEVICE, cgd);
if (status != CAM_REQ_CMP
@ -498,25 +493,23 @@ passopen(struct cdev *dev, int flags, int fmt, struct thread *td)
static int
passclose(struct cdev *dev, int flag, int fmt, struct thread *td)
{
struct cam_sim *sim;
struct cam_periph *periph;
struct pass_softc *softc;
struct mtx *mtx;
periph = (struct cam_periph *)dev->si_drv1;
if (periph == NULL)
return (ENXIO);
mtx = cam_periph_mtx(periph);
mtx_lock(mtx);
sim = periph->sim;
softc = periph->softc;
mtx_lock(sim->mtx);
softc->open_count--;
cam_periph_release_locked(periph);
/*
* We reference the SIM lock directly here, instead of using
* We reference the lock directly here, instead of using
* cam_periph_unlock(). The reason is that the call to
* cam_periph_release_locked() above could result in the periph
* getting freed. If that is the case, dereferencing the periph
@ -527,46 +520,11 @@ passclose(struct cdev *dev, int flag, int fmt, struct thread *td)
* protect the open count and avoid another lock acquisition and
* release.
*/
mtx_unlock(sim->mtx);
mtx_unlock(mtx);
return (0);
}
static void
passstart(struct cam_periph *periph, union ccb *start_ccb)
{
struct pass_softc *softc;
softc = (struct pass_softc *)periph->softc;
switch (softc->state) {
case PASS_STATE_NORMAL:
start_ccb->ccb_h.ccb_type = PASS_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
wakeup(&periph->ccb_list);
break;
}
}
static void
passdone(struct cam_periph *periph, union ccb *done_ccb)
{
struct pass_softc *softc;
struct ccb_scsiio *csio;
softc = (struct pass_softc *)periph->softc;
csio = &done_ccb->csio;
switch (csio->ccb_h.ccb_type) {
case PASS_CCB_WAITING:
/* Caller will release the CCB */
wakeup(&done_ccb->ccb_h.cbfcnp);
return;
}
xpt_release_ccb(done_ccb);
}
static int
passioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
{
@ -685,12 +643,6 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
*/
xpt_merge_ccb(ccb, inccb);
/*
* There's no way for the user to have a completion
* function, so we put our own completion function in here.
*/
ccb->ccb_h.cbfcnp = passdone;
/*
* Let cam_periph_mapmem do a sanity check on the data pointer format.
* Even if no data transfer is needed, it's a cheap check and it

View File

@ -66,7 +66,6 @@ typedef enum {
typedef enum {
PT_CCB_BUFFER_IO = 0x01,
PT_CCB_WAITING = 0x02,
PT_CCB_RETRY_UA = 0x04,
PT_CCB_BUFFER_IO_UA = PT_CCB_BUFFER_IO|PT_CCB_RETRY_UA
} pt_ccb_state;
@ -378,7 +377,7 @@ ptasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
*/
status = cam_periph_alloc(ptctor, ptoninvalidate, ptdtor,
ptstart, "pt", CAM_PERIPH_BIO,
cgd->ccb_h.path, ptasync,
path, ptasync,
AC_FOUND_DEVICE, cgd);
if (status != CAM_REQ_CMP
@ -423,15 +422,7 @@ ptstart(struct cam_periph *periph, union ccb *start_ccb)
* See if there is a buf with work for us to do..
*/
bp = bioq_first(&softc->bio_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
("queuing for immediate ccb\n"));
start_ccb->ccb_h.ccb_state = PT_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
wakeup(&periph->ccb_list);
} else if (bp == NULL) {
if (bp == NULL) {
xpt_release_ccb(start_ccb);
} else {
bioq_remove(&softc->bio_queue, bp);
@ -554,10 +545,6 @@ ptdone(struct cam_periph *periph, union ccb *done_ccb)
biofinish(bp, softc->device_stats, 0);
break;
}
case PT_CCB_WAITING:
/* Caller will release the CCB */
wakeup(&done_ccb->ccb_h.cbfcnp);
return;
}
xpt_release_ccb(done_ccb);
}

View File

@ -114,7 +114,6 @@ typedef enum {
#define ccb_bp ppriv_ptr1
#define SA_CCB_BUFFER_IO 0x0
#define SA_CCB_WAITING 0x1
#define SA_CCB_TYPEMASK 0x1
#define SA_POSITION_UPDATED 0x2
@ -1453,7 +1452,7 @@ saasync(void *callback_arg, u_int32_t code,
*/
status = cam_periph_alloc(saregister, saoninvalidate,
sacleanup, sastart,
"sa", CAM_PERIPH_BIO, cgd->ccb_h.path,
"sa", CAM_PERIPH_BIO, path,
saasync, AC_FOUND_DEVICE, cgd);
if (status != CAM_REQ_CMP
@ -1722,15 +1721,7 @@ sastart(struct cam_periph *periph, union ccb *start_ccb)
* See if there is a buf with work for us to do..
*/
bp = bioq_first(&softc->bio_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
("queuing for immediate ccb\n"));
Set_CCB_Type(start_ccb, SA_CCB_WAITING);
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
wakeup(&periph->ccb_list);
} else if (bp == NULL) {
if (bp == NULL) {
xpt_release_ccb(start_ccb);
} else if ((softc->flags & SA_FLAG_ERR_PENDING) != 0) {
struct bio *done_bp;
@ -1953,12 +1944,6 @@ sadone(struct cam_periph *periph, union ccb *done_ccb)
biofinish(bp, softc->device_stats, 0);
break;
}
case SA_CCB_WAITING:
{
/* Caller will release the CCB */
wakeup(&done_ccb->ccb_h.cbfcnp);
return;
}
}
xpt_release_ccb(done_ccb);
}
@ -2545,7 +2530,8 @@ saerror(union ccb *ccb, u_int32_t cflgs, u_int32_t sflgs)
/*
* If a read/write command, we handle it here.
*/
if (CCB_Type(csio) != SA_CCB_WAITING) {
if (csio->cdb_io.cdb_bytes[0] == SA_READ ||
csio->cdb_io.cdb_bytes[0] == SA_WRITE) {
break;
}
/*

View File

@ -76,8 +76,7 @@ typedef enum {
} sg_rdwr_state;
typedef enum {
SG_CCB_RDWR_IO,
SG_CCB_WAITING
SG_CCB_RDWR_IO
} sg_ccb_types;
#define ccb_type ppriv_field0
@ -119,7 +118,6 @@ static periph_init_t sginit;
static periph_ctor_t sgregister;
static periph_oninv_t sgoninvalidate;
static periph_dtor_t sgcleanup;
static periph_start_t sgstart;
static void sgasync(void *callback_arg, uint32_t code,
struct cam_path *path, void *arg);
static void sgdone(struct cam_periph *periph, union ccb *done_ccb);
@ -172,20 +170,19 @@ sginit(void)
static void
sgdevgonecb(void *arg)
{
struct cam_sim *sim;
struct cam_periph *periph;
struct sg_softc *softc;
struct mtx *mtx;
int i;
periph = (struct cam_periph *)arg;
sim = periph->sim;
softc = (struct sg_softc *)periph->softc;
mtx = cam_periph_mtx(periph);
mtx_lock(mtx);
softc = (struct sg_softc *)periph->softc;
KASSERT(softc->open_count >= 0, ("Negative open count %d",
softc->open_count));
mtx_lock(sim->mtx);
/*
* When we get this callback, we will get no more close calls from
* devfs. So if we have any dangling opens, we need to release the
@ -202,13 +199,13 @@ sgdevgonecb(void *arg)
cam_periph_release_locked(periph);
/*
* We reference the SIM lock directly here, instead of using
* We reference the lock directly here, instead of using
* cam_periph_unlock(). The reason is that the final call to
* cam_periph_release_locked() above could result in the periph
* getting freed. If that is the case, dereferencing the periph
* with a cam_periph_unlock() call would cause a page fault.
*/
mtx_unlock(sim->mtx);
mtx_unlock(mtx);
}
@ -277,8 +274,8 @@ sgasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
* start the probe process.
*/
status = cam_periph_alloc(sgregister, sgoninvalidate,
sgcleanup, sgstart, "sg",
CAM_PERIPH_BIO, cgd->ccb_h.path,
sgcleanup, NULL, "sg",
CAM_PERIPH_BIO, path,
sgasync, AC_FOUND_DEVICE, cgd);
if ((status != CAM_REQ_CMP) && (status != CAM_REQ_INPROG)) {
const struct cam_status_entry *entry;
@ -382,24 +379,6 @@ sgregister(struct cam_periph *periph, void *arg)
return (CAM_REQ_CMP);
}
static void
sgstart(struct cam_periph *periph, union ccb *start_ccb)
{
struct sg_softc *softc;
softc = (struct sg_softc *)periph->softc;
switch (softc->state) {
case SG_STATE_NORMAL:
start_ccb->ccb_h.ccb_type = SG_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
wakeup(&periph->ccb_list);
break;
}
}
static void
sgdone(struct cam_periph *periph, union ccb *done_ccb)
{
@ -409,10 +388,6 @@ sgdone(struct cam_periph *periph, union ccb *done_ccb)
softc = (struct sg_softc *)periph->softc;
csio = &done_ccb->csio;
switch (csio->ccb_h.ccb_type) {
case SG_CCB_WAITING:
/* Caller will release the CCB */
wakeup(&done_ccb->ccb_h.cbfcnp);
return;
case SG_CCB_RDWR_IO:
{
struct sg_rdwr *rdwr;
@ -480,25 +455,23 @@ sgopen(struct cdev *dev, int flags, int fmt, struct thread *td)
static int
sgclose(struct cdev *dev, int flag, int fmt, struct thread *td)
{
struct cam_sim *sim;
struct cam_periph *periph;
struct sg_softc *softc;
struct mtx *mtx;
periph = (struct cam_periph *)dev->si_drv1;
if (periph == NULL)
return (ENXIO);
mtx = cam_periph_mtx(periph);
mtx_lock(mtx);
sim = periph->sim;
softc = periph->softc;
mtx_lock(sim->mtx);
softc->open_count--;
cam_periph_release_locked(periph);
/*
* We reference the SIM lock directly here, instead of using
* We reference the lock directly here, instead of using
* cam_periph_unlock(). The reason is that the call to
* cam_periph_release_locked() above could result in the periph
* getting freed. If that is the case, dereferencing the periph
@ -509,7 +482,7 @@ sgclose(struct cdev *dev, int flag, int fmt, struct thread *td)
* protect the open count and avoid another lock acquisition and
* release.
*/
mtx_unlock(sim->mtx);
mtx_unlock(mtx);
return (0);
}
@ -879,7 +852,7 @@ sgread(struct cdev *dev, struct uio *uio, int ioflag)
break;
}
if ((rdwr == NULL) || (rdwr->state != SG_RDWR_DONE)) {
if (msleep(rdwr, periph->sim->mtx, PCATCH, "sgread", 0) == ERESTART)
if (cam_periph_sleep(periph, rdwr, PCATCH, "sgread", 0) == ERESTART)
return (EAGAIN);
goto search;
}

View File

@ -65,8 +65,7 @@ typedef enum {
} targbh_flags;
typedef enum {
TARGBH_CCB_WORKQ,
TARGBH_CCB_WAITING
TARGBH_CCB_WORKQ
} targbh_ccb_types;
#define MAX_ACCEPT 8
@ -431,7 +430,7 @@ targbhdtor(struct cam_periph *periph)
/* FALLTHROUGH */
default:
/* XXX Wait for callback of targbhdislun() */
msleep(softc, periph->sim->mtx, PRIBIO, "targbh", hz/2);
cam_periph_sleep(periph, softc, PRIBIO, "targbh", hz/2);
free(softc, M_SCSIBH);
break;
}
@ -450,13 +449,7 @@ targbhstart(struct cam_periph *periph, union ccb *start_ccb)
softc = (struct targbh_softc *)periph->softc;
ccbh = TAILQ_FIRST(&softc->work_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
start_ccb->ccb_h.ccb_type = TARGBH_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
wakeup(&periph->ccb_list);
} else if (ccbh == NULL) {
if (ccbh == NULL) {
xpt_release_ccb(start_ccb);
} else {
TAILQ_REMOVE(&softc->work_queue, ccbh, periph_links.tqe);
@ -535,12 +528,6 @@ targbhdone(struct cam_periph *periph, union ccb *done_ccb)
softc = (struct targbh_softc *)periph->softc;
if (done_ccb->ccb_h.ccb_type == TARGBH_CCB_WAITING) {
/* Caller will release the CCB */
wakeup(&done_ccb->ccb_h.cbfcnp);
return;
}
switch (done_ccb->ccb_h.func_code) {
case XPT_ACCEPT_TARGET_IO:
{

View File

@ -236,23 +236,21 @@ targioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
{
struct ioc_enable_lun *new_lun;
struct cam_path *path;
struct cam_sim *sim;
new_lun = (struct ioc_enable_lun *)addr;
status = xpt_create_path_unlocked(&path, /*periph*/NULL,
new_lun->path_id,
new_lun->target_id,
new_lun->lun_id);
status = xpt_create_path(&path, /*periph*/NULL,
new_lun->path_id,
new_lun->target_id,
new_lun->lun_id);
if (status != CAM_REQ_CMP) {
printf("Couldn't create path, status %#x\n", status);
break;
}
sim = xpt_path_sim(path);
mtx_lock(sim->mtx);
xpt_path_lock(path);
status = targenable(softc, path, new_lun->grp6_len,
new_lun->grp7_len);
xpt_path_unlock(path);
xpt_free_path(path);
mtx_unlock(sim->mtx);
break;
}
case TARGIOCDISABLE:
@ -278,13 +276,10 @@ targioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
cdbg.flags = CAM_DEBUG_PERIPH;
else
cdbg.flags = CAM_DEBUG_NONE;
cam_periph_lock(softc->periph);
xpt_setup_ccb(&cdbg.ccb_h, softc->path, CAM_PRIORITY_NORMAL);
cdbg.ccb_h.func_code = XPT_DEBUG;
cdbg.ccb_h.cbfcnp = targdone;
xpt_action((union ccb *)&cdbg);
cam_periph_unlock(softc->periph);
status = cdbg.ccb_h.status & CAM_STATUS_MASK;
break;
}
@ -823,7 +818,7 @@ targread(struct cdev *dev, struct uio *uio, int ioflag)
user_descr = TAILQ_FIRST(abort_queue);
while (ccb_h == NULL && user_descr == NULL) {
if ((ioflag & IO_NDELAY) == 0) {
error = msleep(user_queue, softc->periph->sim->mtx,
error = cam_periph_sleep(softc->periph, user_queue,
PRIBIO | PCATCH, "targrd", 0);
ccb_h = TAILQ_FIRST(user_queue);
user_descr = TAILQ_FIRST(abort_queue);
@ -1019,7 +1014,6 @@ abort_all_pending(struct targ_softc *softc)
struct targ_cmd_descr *descr;
struct ccb_abort cab;
struct ccb_hdr *ccb_h;
struct cam_sim *sim;
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("abort_all_pending\n"));
@ -1052,8 +1046,7 @@ abort_all_pending(struct targ_softc *softc)
/* If we aborted at least one pending CCB ok, wait for it. */
if (cab.ccb_h.status == CAM_REQ_CMP) {
sim = xpt_path_sim(softc->path);
msleep(&softc->pending_ccb_queue, sim->mtx,
cam_periph_sleep(softc->periph, &softc->pending_ccb_queue,
PRIBIO | PCATCH, "tgabrt", 0);
}

View File

@ -577,7 +577,7 @@ static struct cam_ed *
lun_id_t lun_id);
static void scsi_devise_transport(struct cam_path *path);
static void scsi_set_transfer_settings(struct ccb_trans_settings *cts,
struct cam_ed *device,
struct cam_path *path,
int async_update);
static void scsi_toggle_tags(struct cam_path *path);
static void scsi_dev_async(u_int32_t async_code,
@ -639,6 +639,7 @@ proberegister(struct cam_periph *periph, void *arg)
return (status);
}
CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n"));
scsi_devise_transport(periph->path);
/*
* Ensure we've waited at least a bus settle
@ -1727,11 +1728,12 @@ probe_purge_old(struct cam_path *path, struct scsi_report_luns_data *new)
if (path->target == NULL) {
return;
}
if (path->target->luns == NULL) {
path->target->luns = new;
return;
}
mtx_lock(&path->target->luns_mtx);
old = path->target->luns;
path->target->luns = new;
mtx_unlock(&path->target->luns_mtx);
if (old == NULL)
return;
nlun_old = scsi_4btoul(old->length) / 8;
nlun_new = scsi_4btoul(new->length) / 8;
@ -1773,7 +1775,6 @@ probe_purge_old(struct cam_path *path, struct scsi_report_luns_data *new)
}
}
free(old, M_CAMXPT);
path->target->luns = new;
}
static void
@ -1835,6 +1836,8 @@ typedef struct {
static void
scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
{
struct mtx *mtx;
CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
("scsi_scan_bus\n"));
switch (request_ccb->ccb_h.func_code) {
@ -1902,6 +1905,7 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
(work_ccb->cpi.max_target * sizeof (u_int)), M_CAMXPT, M_ZERO|M_NOWAIT);
if (scan_info == NULL) {
request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
xpt_free_ccb(work_ccb);
xpt_done(request_ccb);
return;
}
@ -1932,6 +1936,8 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
scan_info->counter--;
}
}
mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path);
mtx_unlock(mtx);
for (i = low_target; i <= max_target; i++) {
cam_status status;
@ -1964,10 +1970,13 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
request_ccb->ccb_h.pinfo.priority);
work_ccb->ccb_h.func_code = XPT_SCAN_LUN;
work_ccb->ccb_h.cbfcnp = scsi_scan_bus;
work_ccb->ccb_h.flags |= CAM_UNLOCKED;
work_ccb->ccb_h.ppriv_ptr0 = scan_info;
work_ccb->crcn.flags = request_ccb->crcn.flags;
xpt_action(work_ccb);
}
mtx_lock(mtx);
break;
}
case XPT_SCAN_LUN:
@ -2000,6 +2009,9 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
target = request_ccb->ccb_h.path->target;
next_target = 1;
mtx = xpt_path_mtx(scan_info->request_ccb->ccb_h.path);
mtx_lock(mtx);
mtx_lock(&target->luns_mtx);
if (target->luns) {
uint32_t first;
u_int nluns = scsi_4btoul(target->luns->length) / 8;
@ -2017,6 +2029,7 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
if (scan_info->lunindex[target_id] < nluns) {
CAM_GET_SIMPLE_LUN(target->luns,
scan_info->lunindex[target_id], lun_id);
mtx_unlock(&target->luns_mtx);
next_target = 0;
CAM_DEBUG(request_ccb->ccb_h.path,
CAM_DEBUG_PROBE,
@ -2024,6 +2037,7 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
scan_info->lunindex[target_id], lun_id));
scan_info->lunindex[target_id]++;
} else {
mtx_unlock(&target->luns_mtx);
/*
* We're done with scanning all luns.
*
@ -2042,7 +2056,9 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
}
}
}
} else if (request_ccb->ccb_h.status != CAM_REQ_CMP) {
} else {
mtx_unlock(&target->luns_mtx);
if (request_ccb->ccb_h.status != CAM_REQ_CMP) {
int phl;
/*
@ -2074,7 +2090,7 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
if (lun_id == request_ccb->ccb_h.target_lun
|| lun_id > scan_info->cpi->max_lun)
next_target = 1;
} else {
} else {
device = request_ccb->ccb_h.path->device;
@ -2090,6 +2106,7 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
if (lun_id == request_ccb->ccb_h.target_lun
|| lun_id > scan_info->cpi->max_lun)
next_target = 1;
}
}
/*
@ -2123,6 +2140,7 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
}
}
if (done) {
mtx_unlock(mtx);
xpt_free_ccb(request_ccb);
xpt_free_ccb((union ccb *)scan_info->cpi);
request_ccb = scan_info->request_ccb;
@ -2136,6 +2154,7 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
}
if ((scan_info->cpi->hba_misc & PIM_SEQSCAN) == 0) {
mtx_unlock(mtx);
xpt_free_ccb(request_ccb);
break;
}
@ -2143,6 +2162,7 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
scan_info->request_ccb->ccb_h.path_id,
scan_info->counter, 0);
if (status != CAM_REQ_CMP) {
mtx_unlock(mtx);
printf("scsi_scan_bus: xpt_create_path failed"
" with status %#x, bus scan halted\n",
status);
@ -2158,6 +2178,7 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
request_ccb->ccb_h.pinfo.priority);
request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
request_ccb->ccb_h.cbfcnp = scsi_scan_bus;
request_ccb->ccb_h.flags |= CAM_UNLOCKED;
request_ccb->ccb_h.ppriv_ptr0 = scan_info;
request_ccb->crcn.flags =
scan_info->request_ccb->crcn.flags;
@ -2181,10 +2202,12 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
request_ccb->ccb_h.pinfo.priority);
request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
request_ccb->ccb_h.cbfcnp = scsi_scan_bus;
request_ccb->ccb_h.flags |= CAM_UNLOCKED;
request_ccb->ccb_h.ppriv_ptr0 = scan_info;
request_ccb->crcn.flags =
scan_info->request_ccb->crcn.flags;
}
mtx_unlock(mtx);
xpt_action(request_ccb);
break;
}
@ -2201,6 +2224,7 @@ scsi_scan_lun(struct cam_periph *periph, struct cam_path *path,
cam_status status;
struct cam_path *new_path;
struct cam_periph *old_periph;
int lock;
CAM_DEBUG(path, CAM_DEBUG_TRACE, ("scsi_scan_lun\n"));
@ -2248,9 +2272,13 @@ scsi_scan_lun(struct cam_periph *periph, struct cam_path *path,
xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT);
request_ccb->ccb_h.cbfcnp = xptscandone;
request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
request_ccb->ccb_h.flags |= CAM_UNLOCKED;
request_ccb->crcn.flags = flags;
}
lock = (xpt_path_owned(path) == 0);
if (lock)
xpt_path_lock(path);
if ((old_periph = cam_periph_find(path, "probe")) != NULL) {
if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) {
probe_softc *softc;
@ -2276,6 +2304,8 @@ scsi_scan_lun(struct cam_periph *periph, struct cam_path *path,
xpt_done(request_ccb);
}
}
if (lock)
xpt_path_unlock(path);
}
static void
@ -2289,7 +2319,6 @@ xptscandone(struct cam_periph *periph, union ccb *done_ccb)
static struct cam_ed *
scsi_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
{
struct cam_path path;
struct scsi_quirk_entry *quirk;
struct cam_ed *device;
@ -2314,22 +2343,6 @@ scsi_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
device->device_id_len = 0;
device->supported_vpds = NULL;
device->supported_vpds_len = 0;
/*
* XXX should be limited by number of CCBs this bus can
* do.
*/
bus->sim->max_ccbs += device->ccbq.devq_openings;
if (lun_id != CAM_LUN_WILDCARD) {
xpt_compile_path(&path,
NULL,
bus->path_id,
target->target_id,
lun_id);
scsi_devise_transport(&path);
xpt_release_path(&path);
}
return (device);
}
@ -2508,15 +2521,8 @@ scsi_dev_advinfo(union ccb *start_ccb)
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);
}
}
@ -2528,7 +2534,7 @@ scsi_action(union ccb *start_ccb)
case XPT_SET_TRAN_SETTINGS:
{
scsi_set_transfer_settings(&start_ccb->cts,
start_ccb->ccb_h.path->device,
start_ccb->ccb_h.path,
/*async_update*/FALSE);
break;
}
@ -2541,14 +2547,6 @@ scsi_action(union ccb *start_ccb)
start_ccb->ccb_h.path, start_ccb->crcn.flags,
start_ccb);
break;
case XPT_GET_TRAN_SETTINGS:
{
struct cam_sim *sim;
sim = start_ccb->ccb_h.path->bus->sim;
(*(sim->sim_action))(sim, start_ccb);
break;
}
case XPT_DEV_ADVINFO:
{
scsi_dev_advinfo(start_ccb);
@ -2561,17 +2559,17 @@ scsi_action(union ccb *start_ccb)
}
static void
scsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
scsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_path *path,
int async_update)
{
struct ccb_pathinq cpi;
struct ccb_trans_settings cur_cts;
struct ccb_trans_settings_scsi *scsi;
struct ccb_trans_settings_scsi *cur_scsi;
struct cam_sim *sim;
struct scsi_inquiry_data *inq_data;
struct cam_ed *device;
if (device == NULL) {
if (path == NULL || (device = path->device) == NULL) {
cts->ccb_h.status = CAM_PATH_INVALID;
xpt_done((union ccb *)cts);
return;
@ -2588,14 +2586,14 @@ scsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device
cts->protocol_version = device->protocol_version;
if (cts->protocol != device->protocol) {
xpt_print(cts->ccb_h.path, "Uninitialized Protocol %x:%x?\n",
xpt_print(path, "Uninitialized Protocol %x:%x?\n",
cts->protocol, device->protocol);
cts->protocol = device->protocol;
}
if (cts->protocol_version > device->protocol_version) {
if (bootverbose) {
xpt_print(cts->ccb_h.path, "Down reving Protocol "
xpt_print(path, "Down reving Protocol "
"Version from %d to %d?\n", cts->protocol_version,
device->protocol_version);
}
@ -2613,22 +2611,20 @@ scsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device
cts->transport_version = device->transport_version;
if (cts->transport != device->transport) {
xpt_print(cts->ccb_h.path, "Uninitialized Transport %x:%x?\n",
xpt_print(path, "Uninitialized Transport %x:%x?\n",
cts->transport, device->transport);
cts->transport = device->transport;
}
if (cts->transport_version > device->transport_version) {
if (bootverbose) {
xpt_print(cts->ccb_h.path, "Down reving Transport "
xpt_print(path, "Down reving Transport "
"Version from %d to %d?\n", cts->transport_version,
device->transport_version);
}
cts->transport_version = device->transport_version;
}
sim = cts->ccb_h.path->bus->sim;
/*
* Nothing more of interest to do unless
* this is a device connected via the
@ -2636,13 +2632,13 @@ scsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device
*/
if (cts->protocol != PROTO_SCSI) {
if (async_update == FALSE)
(*(sim->sim_action))(sim, (union ccb *)cts);
xpt_action_default((union ccb *)cts);
return;
}
inq_data = &device->inq_data;
scsi = &cts->proto_specific.scsi;
xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
@ -2663,7 +2659,7 @@ scsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device
* Perform sanity checking against what the
* controller and device can do.
*/
xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
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;
xpt_action((union ccb *)&cur_cts);
@ -2784,7 +2780,7 @@ scsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device
&& (spi->flags & (CTS_SPI_VALID_SYNC_RATE|
CTS_SPI_VALID_SYNC_OFFSET|
CTS_SPI_VALID_BUS_WIDTH)) != 0)
scsi_toggle_tags(cts->ccb_h.path);
scsi_toggle_tags(path);
}
if (cts->type == CTS_TYPE_CURRENT_SETTINGS
@ -2821,12 +2817,12 @@ scsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device
device->tag_delay_count = CAM_TAG_DELAY_COUNT;
device->flags |= CAM_DEV_TAG_AFTER_COUNT;
} else {
xpt_stop_tags(cts->ccb_h.path);
xpt_stop_tags(path);
}
}
}
if (async_update == FALSE)
(*(sim->sim_action))(sim, (union ccb *)cts);
xpt_action_default((union ccb *)cts);
}
static void
@ -2854,10 +2850,10 @@ scsi_toggle_tags(struct cam_path *path)
cts.transport_version = XPORT_VERSION_UNSPECIFIED;
cts.proto_specific.scsi.flags = 0;
cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ;
scsi_set_transfer_settings(&cts, path->device,
scsi_set_transfer_settings(&cts, path,
/*async_update*/TRUE);
cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB;
scsi_set_transfer_settings(&cts, path->device,
scsi_set_transfer_settings(&cts, path,
/*async_update*/TRUE);
}
}
@ -2928,10 +2924,14 @@ scsi_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target,
xpt_release_device(device);
} else if (async_code == AC_TRANSFER_NEG) {
struct ccb_trans_settings *settings;
struct cam_path path;
settings = (struct ccb_trans_settings *)async_arg;
scsi_set_transfer_settings(settings, device,
xpt_compile_path(&path, NULL, bus->path_id, target->target_id,
device->lun_id);
scsi_set_transfer_settings(settings, &path,
/*async_update*/TRUE);
xpt_release_path(&path);
}
}
@ -2945,7 +2945,7 @@ scsi_announce_periph(struct cam_periph *periph)
u_int freq;
u_int mb;
mtx_assert(periph->sim->mtx, MA_OWNED);
cam_periph_assert(periph, MA_OWNED);
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;

View File

@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
static int ahci_setup_interrupt(device_t dev);
static void ahci_intr(void *data);
static void ahci_intr_one(void *data);
static void ahci_intr_one_edge(void *data);
static int ahci_suspend(device_t dev);
static int ahci_resume(device_t dev);
static int ahci_ch_init(device_t dev);
@ -62,8 +63,9 @@ static int ahci_ch_deinit(device_t dev);
static int ahci_ch_suspend(device_t dev);
static int ahci_ch_resume(device_t dev);
static void ahci_ch_pm(void *arg);
static void ahci_ch_intr_locked(void *data);
static void ahci_ch_intr(void *data);
static void ahci_ch_intr(void *arg);
static void ahci_ch_intr_direct(void *arg);
static void ahci_ch_intr_main(struct ahci_channel *ch, uint32_t istatus);
static int ahci_ctlr_reset(device_t dev);
static int ahci_ctlr_setup(device_t dev);
static void ahci_begin_transaction(device_t dev, union ccb *ccb);
@ -397,6 +399,7 @@ ahci_attach(device_t dev)
struct ahci_controller *ctlr = device_get_softc(dev);
device_t child;
int error, unit, speed, i;
u_int u;
uint32_t devid = pci_get_devid(dev);
uint8_t revid = pci_get_revid(dev);
u_int32_t version;
@ -496,6 +499,12 @@ ahci_attach(device_t dev)
rman_fini(&ctlr->sc_iomem);
return ENXIO;
}
i = 0;
for (u = ctlr->ichannels; u != 0; u >>= 1)
i += (u & 1);
ctlr->direct = (ctlr->msi && (ctlr->numirqs > 1 || i <= 3));
resource_int_value(device_get_name(dev), device_get_unit(dev),
"direct", &ctlr->direct);
/* Announce HW capabilities. */
speed = (ctlr->caps & AHCI_CAP_ISS) >> AHCI_CAP_ISS_SHIFT;
device_printf(dev,
@ -677,24 +686,26 @@ static int
ahci_setup_interrupt(device_t dev)
{
struct ahci_controller *ctlr = device_get_softc(dev);
int i, msi = 1;
int i;
ctlr->msi = 2;
/* Process hints. */
if (ctlr->quirks & AHCI_Q_NOMSI)
msi = 0;
ctlr->msi = 0;
resource_int_value(device_get_name(dev),
device_get_unit(dev), "msi", &msi);
if (msi < 0)
msi = 0;
else if (msi == 1)
msi = min(1, pci_msi_count(dev));
else if (msi > 1)
msi = pci_msi_count(dev);
device_get_unit(dev), "msi", &ctlr->msi);
ctlr->numirqs = 1;
if (ctlr->msi < 0)
ctlr->msi = 0;
else if (ctlr->msi == 1)
ctlr->msi = min(1, pci_msi_count(dev));
else if (ctlr->msi > 1) {
ctlr->msi = 2;
ctlr->numirqs = pci_msi_count(dev);
}
/* Allocate MSI if needed/present. */
if (msi && pci_alloc_msi(dev, &msi) == 0) {
ctlr->numirqs = msi;
} else {
msi = 0;
if (ctlr->msi && pci_alloc_msi(dev, &ctlr->numirqs) != 0) {
ctlr->msi = 0;
ctlr->numirqs = 1;
}
/* Check for single MSI vector fallback. */
@ -706,7 +717,7 @@ ahci_setup_interrupt(device_t dev)
/* Allocate all IRQs. */
for (i = 0; i < ctlr->numirqs; i++) {
ctlr->irqs[i].ctlr = ctlr;
ctlr->irqs[i].r_irq_rid = i + (msi ? 1 : 0);
ctlr->irqs[i].r_irq_rid = i + (ctlr->msi ? 1 : 0);
if (ctlr->numirqs == 1 || i >= ctlr->channels ||
(ctlr->ccc && i == ctlr->cccv))
ctlr->irqs[i].mode = AHCI_IRQ_MODE_ALL;
@ -720,7 +731,9 @@ ahci_setup_interrupt(device_t dev)
return ENXIO;
}
if ((bus_setup_intr(dev, ctlr->irqs[i].r_irq, ATA_INTR_FLAGS, NULL,
(ctlr->irqs[i].mode == AHCI_IRQ_MODE_ONE) ? ahci_intr_one : ahci_intr,
(ctlr->irqs[i].mode != AHCI_IRQ_MODE_ONE) ? ahci_intr :
((ctlr->quirks & AHCI_Q_EDGEIS) ? ahci_intr_one_edge :
ahci_intr_one),
&ctlr->irqs[i], &ctlr->irqs[i].handle))) {
/* SOS XXX release r_irq */
device_printf(dev, "unable to setup interrupt\n");
@ -789,14 +802,25 @@ ahci_intr_one(void *data)
int unit;
unit = irq->r_irq_rid - 1;
/* Some controllers have edge triggered IS. */
if (ctlr->quirks & AHCI_Q_EDGEIS)
ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit);
if ((arg = ctlr->interrupt[unit].argument))
ctlr->interrupt[unit].function(arg);
/* AHCI declares level triggered IS. */
if (!(ctlr->quirks & AHCI_Q_EDGEIS))
ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit);
ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit);
}
static void
ahci_intr_one_edge(void *data)
{
struct ahci_controller_irq *irq = data;
struct ahci_controller *ctlr = irq->ctlr;
void *arg;
int unit;
unit = irq->r_irq_rid - 1;
/* Some controllers have edge triggered IS. */
ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit);
if ((arg = ctlr->interrupt[unit].argument))
ctlr->interrupt[unit].function(arg);
}
static struct resource *
@ -1000,6 +1024,7 @@ ahci_ch_attach(device_t dev)
mtx_init(&ch->mtx, "AHCI channel lock", NULL, MTX_DEF);
resource_int_value(device_get_name(dev),
device_get_unit(dev), "pm_level", &ch->pm_level);
STAILQ_INIT(&ch->doneq);
if (ch->pm_level > 3)
callout_init_mtx(&ch->pm_timer, &ch->mtx, 0);
callout_init_mtx(&ch->reset_timer, &ch->mtx, 0);
@ -1045,7 +1070,8 @@ ahci_ch_attach(device_t dev)
goto err0;
}
if ((bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS, NULL,
ahci_ch_intr_locked, dev, &ch->ih))) {
ctlr->direct ? ahci_ch_intr_direct : ahci_ch_intr,
dev, &ch->ih))) {
device_printf(dev, "Unable to setup interrupt\n");
error = ENXIO;
goto err1;
@ -1465,18 +1491,60 @@ ahci_notify_events(device_t dev, u_int32_t status)
}
static void
ahci_ch_intr_locked(void *data)
ahci_done(struct ahci_channel *ch, union ccb *ccb)
{
device_t dev = (device_t)data;
mtx_assert(&ch->mtx, MA_OWNED);
if ((ccb->ccb_h.func_code & XPT_FC_QUEUED) == 0 ||
ch->batch == 0) {
xpt_done(ccb);
return;
}
STAILQ_INSERT_TAIL(&ch->doneq, &ccb->ccb_h, sim_links.stqe);
}
static void
ahci_ch_intr(void *arg)
{
device_t dev = (device_t)arg;
struct ahci_channel *ch = device_get_softc(dev);
uint32_t istatus;
/* Read interrupt statuses. */
istatus = ATA_INL(ch->r_mem, AHCI_P_IS);
if (istatus == 0)
return;
mtx_lock(&ch->mtx);
xpt_batch_start(ch->sim);
ahci_ch_intr(data);
xpt_batch_done(ch->sim);
ahci_ch_intr_main(ch, istatus);
mtx_unlock(&ch->mtx);
}
static void
ahci_ch_intr_direct(void *arg)
{
device_t dev = (device_t)arg;
struct ahci_channel *ch = device_get_softc(dev);
struct ccb_hdr *ccb_h;
uint32_t istatus;
/* Read interrupt statuses. */
istatus = ATA_INL(ch->r_mem, AHCI_P_IS);
if (istatus == 0)
return;
mtx_lock(&ch->mtx);
ch->batch = 1;
ahci_ch_intr_main(ch, istatus);
ch->batch = 0;
mtx_unlock(&ch->mtx);
while ((ccb_h = STAILQ_FIRST(&ch->doneq)) != NULL) {
STAILQ_REMOVE_HEAD(&ch->doneq, sim_links.stqe);
xpt_done_direct((union ccb *)ccb_h);
}
}
static void
ahci_ch_pm(void *arg)
{
@ -1495,18 +1563,14 @@ ahci_ch_pm(void *arg)
}
static void
ahci_ch_intr(void *data)
ahci_ch_intr_main(struct ahci_channel *ch, uint32_t istatus)
{
device_t dev = (device_t)data;
struct ahci_channel *ch = device_get_softc(dev);
uint32_t istatus, cstatus, serr = 0, sntf = 0, ok, err;
device_t dev = ch->dev;
uint32_t cstatus, serr = 0, sntf = 0, ok, err;
enum ahci_err_type et;
int i, ccs, port, reset = 0;
/* Read and clear interrupt statuses. */
istatus = ATA_INL(ch->r_mem, AHCI_P_IS);
if (istatus == 0)
return;
/* Clear interrupt statuses. */
ATA_OUTL(ch->r_mem, AHCI_P_IS, istatus);
/* Read command statuses. */
if (ch->numtslots != 0)
@ -1598,7 +1662,7 @@ ahci_ch_intr(void *data)
xpt_freeze_devq(fccb->ccb_h.path, 1);
fccb->ccb_h.status |= CAM_DEV_QFRZN;
}
xpt_done(fccb);
ahci_done(ch, fccb);
}
for (i = 0; i < ch->numslots; i++) {
/* XXX: reqests in loading state. */
@ -2007,7 +2071,7 @@ ahci_timeout(struct ahci_slot *slot)
xpt_freeze_devq(fccb->ccb_h.path, 1);
fccb->ccb_h.status |= CAM_DEV_QFRZN;
}
xpt_done(fccb);
ahci_done(ch, fccb);
}
if (!ch->fbs_enabled && !ch->wrongccs) {
/* Without FBS we know real timeout source. */
@ -2213,7 +2277,7 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
ch->hold[slot->slot] = ccb;
ch->numhslots++;
} else
xpt_done(ccb);
ahci_done(ch, ccb);
/* If we have no other active commands, ... */
if (ch->rslots == 0) {
/* if there was fatal error - reset port. */
@ -2273,7 +2337,7 @@ ahci_issue_recovery(device_t dev)
continue;
ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK;
ch->hold[i]->ccb_h.status |= CAM_RESRC_UNAVAIL;
xpt_done(ch->hold[i]);
ahci_done(ch, ch->hold[i]);
ch->hold[i] = NULL;
ch->numhslots--;
}
@ -2361,7 +2425,7 @@ ahci_process_read_log(device_t dev, union ccb *ccb)
ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK;
ch->hold[i]->ccb_h.status |= CAM_REQUEUE_REQ;
}
xpt_done(ch->hold[i]);
ahci_done(ch, ch->hold[i]);
ch->hold[i] = NULL;
ch->numhslots--;
}
@ -2376,7 +2440,7 @@ ahci_process_read_log(device_t dev, union ccb *ccb)
continue;
if (ch->hold[i]->ccb_h.func_code != XPT_ATA_IO)
continue;
xpt_done(ch->hold[i]);
ahci_done(ch, ch->hold[i]);
ch->hold[i] = NULL;
ch->numhslots--;
}
@ -2401,7 +2465,7 @@ ahci_process_request_sense(device_t dev, union ccb *ccb)
ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK;
ch->hold[i]->ccb_h.status |= CAM_AUTOSENSE_FAIL;
}
xpt_done(ch->hold[i]);
ahci_done(ch, ch->hold[i]);
ch->hold[i] = NULL;
ch->numhslots--;
xpt_free_ccb(ccb);
@ -2585,7 +2649,7 @@ ahci_reset(device_t dev)
xpt_freeze_devq(fccb->ccb_h.path, 1);
fccb->ccb_h.status |= CAM_DEV_QFRZN;
}
xpt_done(fccb);
ahci_done(ch, fccb);
}
/* Kill the engine and requeue all running commands. */
ahci_stop(dev);
@ -2599,7 +2663,7 @@ ahci_reset(device_t dev)
for (i = 0; i < ch->numslots; i++) {
if (!ch->hold[i])
continue;
xpt_done(ch->hold[i]);
ahci_done(ch, ch->hold[i]);
ch->hold[i] = NULL;
ch->numhslots--;
}
@ -2795,12 +2859,12 @@ ahci_check_ids(device_t dev, union ccb *ccb)
if (ccb->ccb_h.target_id > ((ch->caps & AHCI_CAP_SPM) ? 15 : 0)) {
ccb->ccb_h.status = CAM_TID_INVALID;
xpt_done(ccb);
ahci_done(ch, ccb);
return (-1);
}
if (ccb->ccb_h.target_lun != 0) {
ccb->ccb_h.status = CAM_LUN_INVALID;
xpt_done(ccb);
ahci_done(ch, ccb);
return (-1);
}
return (0);
@ -2992,15 +3056,19 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
ccb->ccb_h.status = CAM_REQ_INVALID;
break;
}
xpt_done(ccb);
ahci_done(ch, ccb);
}
static void
ahcipoll(struct cam_sim *sim)
{
struct ahci_channel *ch = (struct ahci_channel *)cam_sim_softc(sim);
uint32_t istatus;
ahci_ch_intr(ch->dev);
/* Read interrupt statuses and process if any. */
istatus = ATA_INL(ch->r_mem, AHCI_P_IS);
if (istatus != 0)
ahci_ch_intr_main(ch, istatus);
if (ch->resetting != 0 &&
(--ch->resetpolldiv <= 0 || !callout_pending(&ch->reset_timer))) {
ch->resetpolldiv = 1000;

View File

@ -409,6 +409,8 @@ struct ahci_channel {
struct ahci_slot slot[AHCI_MAX_SLOTS];
union ccb *hold[AHCI_MAX_SLOTS];
struct mtx mtx; /* state lock */
STAILQ_HEAD(, ccb_hdr) doneq; /* queue of completed CCBs */
int batch; /* doneq is in use */
int devices; /* What is present */
int pm_present; /* PM presence reported */
int fbs_enabled; /* FIS-based switching enabled */
@ -481,6 +483,8 @@ struct ahci_controller {
int ichannels;
int ccc; /* CCC timeout */
int cccv; /* CCC vector */
int direct; /* Direct command completion */
int msi; /* MSI interupts */
struct {
void (*function)(void *);
void *argument;

View File

@ -353,9 +353,7 @@ ata_interrupt(void *data)
struct ata_channel *ch = (struct ata_channel *)data;
mtx_lock(&ch->state_mtx);
xpt_batch_start(ch->sim);
ata_interrupt_locked(data);
xpt_batch_done(ch->sim);
mtx_unlock(&ch->state_mtx);
}

View File

@ -106,7 +106,7 @@ isp_attach_chan(ispsoftc_t *isp, struct cam_devq *devq, int chan)
return (EIO);
}
ISP_UNLOCK(isp);
if (xpt_create_path_unlocked(&path, NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
if (xpt_create_path(&path, NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
ISP_LOCK(isp);
xpt_bus_deregister(cam_sim_path(sim));
ISP_UNLOCK(isp);
@ -4131,12 +4131,12 @@ isp_target_thread(ispsoftc_t *isp, int chan)
periphdriver_register(&isptargdriver);
ISP_GET_PC(isp, chan, sim, sim);
ISP_GET_PC(isp, chan, path, path);
status = xpt_create_path_unlocked(&wpath, NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
status = xpt_create_path(&wpath, NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
if (status != CAM_REQ_CMP) {
isp_prt(isp, ISP_LOGERR, "%s: could not allocate wildcard path", __func__);
return;
}
status = xpt_create_path_unlocked(&path, NULL, cam_sim_path(sim), 0, 0);
status = xpt_create_path(&path, NULL, cam_sim_path(sim), 0, 0);
if (status != CAM_REQ_CMP) {
xpt_free_path(wpath);
isp_prt(isp, ISP_LOGERR, "%s: could not allocate path", __func__);

View File

@ -654,9 +654,7 @@ mvs_ch_intr_locked(void *data)
struct mvs_channel *ch = device_get_softc(dev);
mtx_lock(&ch->mtx);
xpt_batch_start(ch->sim);
mvs_ch_intr(data);
xpt_batch_done(ch->sim);
mtx_unlock(&ch->mtx);
}

View File

@ -838,9 +838,7 @@ siis_ch_intr_locked(void *data)
struct siis_channel *ch = device_get_softc(dev);
mtx_lock(&ch->mtx);
xpt_batch_start(ch->sim);
siis_ch_intr(data);
xpt_batch_done(ch->sim);
mtx_unlock(&ch->mtx);
}