Lock the AMR driver:
- Introduce the amr_io_lock to control access to command queues, bio queues, and the hardware. - Eliminate the taskqueue and do all completion processing in the ithread. - Assign a static slot number to each command instead of doing a linear search for free slots each time a command is needed. - Modify the interrupt handler to more closely match what Linux does, for safety.
This commit is contained in:
parent
78cef7c552
commit
c0af288bed
@ -196,13 +196,6 @@ amr_attach(struct amr_softc *sc)
|
||||
TAILQ_INIT(&sc->amr_ready);
|
||||
bioq_init(&sc->amr_bioq);
|
||||
|
||||
#if __FreeBSD_version >= 500005
|
||||
/*
|
||||
* Initialise command-completion task.
|
||||
*/
|
||||
TASK_INIT(&sc->amr_task_complete, 0, amr_complete, sc);
|
||||
#endif
|
||||
|
||||
debug(2, "queue init done");
|
||||
|
||||
/*
|
||||
@ -350,6 +343,9 @@ amr_free(struct amr_softc *sc)
|
||||
/* destroy control device */
|
||||
if( sc->amr_dev_t != (struct cdev *)NULL)
|
||||
destroy_dev(sc->amr_dev_t);
|
||||
|
||||
if (mtx_initialized(&sc->amr_io_lock))
|
||||
mtx_destroy(&sc->amr_io_lock);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -361,8 +357,10 @@ amr_submit_bio(struct amr_softc *sc, struct bio *bio)
|
||||
{
|
||||
debug_called(2);
|
||||
|
||||
mtx_lock(&sc->amr_io_lock);
|
||||
amr_enqueue_bio(sc, bio);
|
||||
amr_startio(sc);
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -413,7 +411,6 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
|
||||
} arg;
|
||||
struct amr_command *ac;
|
||||
struct amr_mailbox_ioctl *mbi;
|
||||
struct amr_passthrough *ap;
|
||||
void *dp, *au_buffer;
|
||||
unsigned long au_length;
|
||||
unsigned char *au_cmd;
|
||||
@ -463,7 +460,6 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
|
||||
|
||||
error = 0;
|
||||
dp = NULL;
|
||||
ap = NULL;
|
||||
ac = NULL;
|
||||
|
||||
/* handle inbound data buffer */
|
||||
@ -471,11 +467,14 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
|
||||
if ((dp = malloc(au_length, M_DEVBUF, M_WAITOK)) == NULL)
|
||||
return(ENOMEM);
|
||||
|
||||
if ((error = copyin(au_buffer, dp, au_length)) != 0)
|
||||
goto out;
|
||||
if ((error = copyin(au_buffer, dp, au_length)) != 0) {
|
||||
free(dp, M_DEVBUF);
|
||||
return (error);
|
||||
}
|
||||
debug(2, "copyin %ld bytes from %p -> %p", au_length, au_buffer, dp);
|
||||
}
|
||||
|
||||
mtx_lock(&sc->amr_io_lock);
|
||||
if ((ac = amr_alloccmd(sc)) == NULL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
@ -483,29 +482,28 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
|
||||
|
||||
/* handle SCSI passthrough command */
|
||||
if (au_cmd[0] == AMR_CMD_PASS) {
|
||||
if ((ap = malloc(sizeof(*ap), M_DEVBUF, M_WAITOK | M_ZERO)) == NULL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
struct amr_passthrough ap; /* 60 bytes */
|
||||
int len;
|
||||
|
||||
/* copy cdb */
|
||||
ap->ap_cdb_length = au_cmd[2];
|
||||
bcopy(au_cmd + 3, ap->ap_cdb, ap->ap_cdb_length);
|
||||
len = au_cmd[2];
|
||||
ap.ap_cdb_length = len;
|
||||
bcopy(au_cmd + 3, ap.ap_cdb, len);
|
||||
|
||||
/* build passthrough */
|
||||
ap->ap_timeout = au_cmd[ap->ap_cdb_length + 3] & 0x07;
|
||||
ap->ap_ars = (au_cmd[ap->ap_cdb_length + 3] & 0x08) ? 1 : 0;
|
||||
ap->ap_islogical = (au_cmd[ap->ap_cdb_length + 3] & 0x80) ? 1 : 0;
|
||||
ap->ap_logical_drive_no = au_cmd[ap->ap_cdb_length + 4];
|
||||
ap->ap_channel = au_cmd[ap->ap_cdb_length + 5];
|
||||
ap->ap_scsi_id = au_cmd[ap->ap_cdb_length + 6];
|
||||
ap->ap_request_sense_length = 14;
|
||||
ap->ap_data_transfer_length = au_length;
|
||||
ap.ap_timeout = au_cmd[len + 3] & 0x07;
|
||||
ap.ap_ars = (au_cmd[len + 3] & 0x08) ? 1 : 0;
|
||||
ap.ap_islogical = (au_cmd[len + 3] & 0x80) ? 1 : 0;
|
||||
ap.ap_logical_drive_no = au_cmd[len + 4];
|
||||
ap.ap_channel = au_cmd[len + 5];
|
||||
ap.ap_scsi_id = au_cmd[len + 6];
|
||||
ap.ap_request_sense_length = 14;
|
||||
ap.ap_data_transfer_length = au_length;
|
||||
/* XXX what about the request-sense area? does the caller want it? */
|
||||
|
||||
/* build command */
|
||||
ac->ac_data = ap;
|
||||
ac->ac_length = sizeof(*ap);
|
||||
ac->ac_data = ≈
|
||||
ac->ac_length = sizeof(struct amr_passthrough);
|
||||
ac->ac_flags |= AMR_CMD_DATAOUT;
|
||||
ac->ac_ccb_data = dp;
|
||||
ac->ac_ccb_length = au_length;
|
||||
@ -541,20 +539,24 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *
|
||||
goto out;
|
||||
|
||||
/* copy out data and set status */
|
||||
if (au_length != 0)
|
||||
if (au_length != 0) {
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
error = copyout(dp, au_buffer, au_length);
|
||||
mtx_lock(&sc->amr_io_lock);
|
||||
}
|
||||
debug(2, "copyout %ld bytes from %p -> %p", au_length, dp, au_buffer);
|
||||
if (dp != NULL)
|
||||
debug(2, "%16d", (int)dp);
|
||||
*au_statusp = ac->ac_status;
|
||||
|
||||
out:
|
||||
if (dp != NULL)
|
||||
free(dp, M_DEVBUF);
|
||||
if (ap != NULL)
|
||||
free(ap, M_DEVBUF);
|
||||
if (ac != NULL)
|
||||
amr_releasecmd(ac);
|
||||
/*
|
||||
* At this point, we know that there is a lock held and that these
|
||||
* objects have been allocated.
|
||||
*/
|
||||
free(dp, M_DEVBUF);
|
||||
amr_releasecmd(ac);
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
return(error);
|
||||
}
|
||||
|
||||
@ -600,6 +602,8 @@ amr_query_controller(struct amr_softc *sc)
|
||||
struct amr_enquiry *ae;
|
||||
int ldrv;
|
||||
|
||||
mtx_lock(&sc->amr_io_lock);
|
||||
|
||||
/*
|
||||
* If we haven't found the real limit yet, let us have a couple of commands in
|
||||
* order to be able to probe.
|
||||
@ -639,6 +643,7 @@ amr_query_controller(struct amr_softc *sc)
|
||||
*/
|
||||
if ((ap = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODUCT_INFO, 0)) == NULL) {
|
||||
device_printf(sc->amr_dev, "can't obtain product data from controller\n");
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
return(1);
|
||||
}
|
||||
sc->amr_maxdrives = 40;
|
||||
@ -653,6 +658,7 @@ amr_query_controller(struct amr_softc *sc)
|
||||
if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_EXT_ENQUIRY2, 0, 0)) == NULL) {
|
||||
if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_ENQUIRY, 0, 0)) == NULL) {
|
||||
device_printf(sc->amr_dev, "can't obtain configuration data from controller\n");
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
return(1);
|
||||
}
|
||||
ae->ae_signature = 0;
|
||||
@ -687,6 +693,7 @@ amr_query_controller(struct amr_softc *sc)
|
||||
*/
|
||||
sc->amr_maxio = imin(sc->amr_maxio, AMR_LIMITCMD);
|
||||
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -752,6 +759,7 @@ amr_flush(struct amr_softc *sc)
|
||||
|
||||
/* get ourselves a command buffer */
|
||||
error = 1;
|
||||
mtx_lock(&sc->amr_io_lock);
|
||||
if ((ac = amr_alloccmd(sc)) == NULL)
|
||||
goto out;
|
||||
/* set command flags */
|
||||
@ -768,6 +776,7 @@ amr_flush(struct amr_softc *sc)
|
||||
out:
|
||||
if (ac != NULL)
|
||||
amr_releasecmd(ac);
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
return(error);
|
||||
}
|
||||
|
||||
@ -859,7 +868,7 @@ static void
|
||||
amr_completeio(struct amr_command *ac)
|
||||
{
|
||||
struct amr_softc *sc = ac->ac_sc;
|
||||
|
||||
|
||||
if (ac->ac_status != AMR_STATUS_SUCCESS) { /* could be more verbose here? */
|
||||
ac->ac_bio->bio_error = EIO;
|
||||
ac->ac_bio->bio_flags |= BIO_ERROR;
|
||||
@ -894,16 +903,16 @@ amr_bio_command(struct amr_softc *sc, struct amr_command **acp)
|
||||
ac = NULL;
|
||||
error = 0;
|
||||
|
||||
/* get a bio to work on */
|
||||
if ((bio = amr_dequeue_bio(sc)) == NULL)
|
||||
goto out;
|
||||
|
||||
/* get a command */
|
||||
if ((ac = amr_alloccmd(sc)) == NULL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((ac = amr_alloccmd(sc)) == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
/* get a bio to work on */
|
||||
if ((bio = amr_dequeue_bio(sc)) == NULL) {
|
||||
amr_releasecmd(ac);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* connect the bio to the command */
|
||||
ac->ac_complete = amr_completeio;
|
||||
ac->ac_bio = bio;
|
||||
@ -931,13 +940,6 @@ amr_bio_command(struct amr_softc *sc, struct amr_command **acp)
|
||||
(long long)bio->bio_pblkno, blkcount,
|
||||
(u_long)sc->amr_drive[driveno].al_size);
|
||||
|
||||
out:
|
||||
if (error != 0) {
|
||||
if (ac != NULL)
|
||||
amr_releasecmd(ac);
|
||||
if (bio != NULL) /* this breaks ordering... */
|
||||
amr_enqueue_bio(sc, bio);
|
||||
}
|
||||
*acp = ac;
|
||||
return(error);
|
||||
}
|
||||
@ -961,7 +963,7 @@ amr_wait_command(struct amr_command *ac)
|
||||
count = 0;
|
||||
/* XXX better timeout? */
|
||||
while ((ac->ac_flags & AMR_CMD_BUSY) && (count < 30)) {
|
||||
tsleep(ac, PRIBIO | PCATCH, "amrwcmd", hz);
|
||||
msleep(ac, &ac->ac_sc->amr_io_lock, PRIBIO | PCATCH, "amrwcmd", hz);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@ -1049,7 +1051,7 @@ amr_quartz_poll_command1(struct amr_softc *sc, struct amr_command *ac)
|
||||
if ((sc->amr_state & AMR_STATE_CRASHDUMP) == 0) {
|
||||
count=0;
|
||||
while (sc->amr_busyslots) {
|
||||
tsleep(sc, PRIBIO | PCATCH, "amrpoll", hz);
|
||||
msleep(sc, &sc->amr_io_lock, PRIBIO | PCATCH, "amrpoll", hz);
|
||||
if(count++>10) {
|
||||
break;
|
||||
}
|
||||
@ -1104,36 +1106,18 @@ static int
|
||||
amr_getslot(struct amr_command *ac)
|
||||
{
|
||||
struct amr_softc *sc = ac->ac_sc;
|
||||
int s, slot, limit, error;
|
||||
int slot;
|
||||
|
||||
debug_called(3);
|
||||
|
||||
/* if the command already has a slot, don't try to give it another one */
|
||||
if (ac->ac_slot != 0)
|
||||
return(0);
|
||||
slot = ac->ac_slot;
|
||||
if (sc->amr_busycmd[slot] != NULL)
|
||||
panic("amr: slot %d busy?\n", slot);
|
||||
|
||||
/* enforce slot usage limit */
|
||||
limit = (ac->ac_flags & AMR_CMD_PRIORITY) ? sc->amr_maxio : sc->amr_maxio - 4;
|
||||
if (sc->amr_busyslots > limit)
|
||||
return(EBUSY);
|
||||
|
||||
/*
|
||||
* Allocate a slot. XXX linear scan is slow
|
||||
*/
|
||||
error = EBUSY;
|
||||
s = splbio();
|
||||
for (slot = 0; slot < sc->amr_maxio; slot++) {
|
||||
if (sc->amr_busycmd[slot] == NULL) {
|
||||
sc->amr_busycmd[slot] = ac;
|
||||
sc->amr_busyslots++;
|
||||
ac->ac_slot = slot;
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
splx(s);
|
||||
sc->amr_busycmd[slot] = ac;
|
||||
sc->amr_busyslots++;
|
||||
|
||||
return(error);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
@ -1362,8 +1346,9 @@ amr_start(struct amr_command *ac)
|
||||
ac->ac_flags |= AMR_CMD_BUSY;
|
||||
|
||||
/* get a command slot (freed in amr_done) */
|
||||
if (amr_getslot(ac))
|
||||
if (amr_getslot(ac)) {
|
||||
return(EBUSY);
|
||||
}
|
||||
|
||||
/* Now we have a slot, we can map the command (unmapped in amr_complete). */
|
||||
if ((error = amr_mapcmd(ac)) == ENOMEM) {
|
||||
@ -1449,6 +1434,7 @@ amr_start1(struct amr_softc *sc, struct amr_command *ac)
|
||||
*
|
||||
* Returns nonzero if any commands on the work queue were marked as completed.
|
||||
*/
|
||||
|
||||
int
|
||||
amr_done(struct amr_softc *sc)
|
||||
{
|
||||
@ -1493,18 +1479,8 @@ amr_done(struct amr_softc *sc)
|
||||
}
|
||||
}
|
||||
|
||||
/* if we've completed any commands, try posting some more */
|
||||
sc->amr_state &= ~AMR_STATE_QUEUE_FRZN;
|
||||
if (result)
|
||||
amr_startio(sc);
|
||||
|
||||
/* handle completion and timeouts */
|
||||
#if __FreeBSD_version >= 500005
|
||||
if (sc->amr_state & AMR_STATE_INTEN)
|
||||
taskqueue_enqueue(taskqueue_swi_giant, &sc->amr_task_complete);
|
||||
else
|
||||
#endif
|
||||
amr_complete(sc, 0);
|
||||
amr_complete(sc, 0);
|
||||
|
||||
return(result);
|
||||
}
|
||||
@ -1512,6 +1488,7 @@ amr_done(struct amr_softc *sc)
|
||||
/********************************************************************************
|
||||
* Do completion processing on done commands on (sc)
|
||||
*/
|
||||
|
||||
static void
|
||||
amr_complete(void *context, int pending)
|
||||
{
|
||||
@ -1549,7 +1526,9 @@ amr_complete(void *context, int pending)
|
||||
wakeup(sc);
|
||||
}
|
||||
}
|
||||
amr_startio(sc);
|
||||
|
||||
sc->amr_state &= ~AMR_STATE_QUEUE_FRZN;
|
||||
amr_startio(sc);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
@ -1577,11 +1556,12 @@ amr_alloccmd(struct amr_softc *sc)
|
||||
amr_alloccmd_cluster(sc);
|
||||
ac = amr_dequeue_free(sc);
|
||||
}
|
||||
if (ac == NULL)
|
||||
if (ac == NULL) {
|
||||
sc->amr_state |= AMR_STATE_QUEUE_FRZN;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* clear out significant fields */
|
||||
ac->ac_slot = 0;
|
||||
ac->ac_status = 0;
|
||||
bzero(&ac->ac_mailbox, sizeof(struct amr_mailbox));
|
||||
ac->ac_flags = 0;
|
||||
@ -1611,21 +1591,27 @@ amr_alloccmd_cluster(struct amr_softc *sc)
|
||||
{
|
||||
struct amr_command_cluster *acc;
|
||||
struct amr_command *ac;
|
||||
int s, i;
|
||||
int s, i, nextslot;
|
||||
|
||||
acc = malloc(AMR_CMD_CLUSTERSIZE, M_DEVBUF, M_NOWAIT);
|
||||
if (sc->amr_nextslot > sc->amr_maxio)
|
||||
return;
|
||||
acc = malloc(AMR_CMD_CLUSTERSIZE, M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
if (acc != NULL) {
|
||||
s = splbio();
|
||||
nextslot = sc->amr_nextslot;
|
||||
TAILQ_INSERT_TAIL(&sc->amr_cmd_clusters, acc, acc_link);
|
||||
splx(s);
|
||||
for (i = 0; i < AMR_CMD_CLUSTERCOUNT; i++) {
|
||||
ac = &acc->acc_command[i];
|
||||
bzero(ac, sizeof(*ac));
|
||||
ac->ac_sc = sc;
|
||||
ac->ac_slot = nextslot;
|
||||
if (!bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_dmamap) &&
|
||||
!bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_ccb_dmamap))
|
||||
amr_releasecmd(ac);
|
||||
if (++nextslot > sc->amr_maxio)
|
||||
break;
|
||||
}
|
||||
sc->amr_nextslot = nextslot;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1683,6 +1669,7 @@ amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave)
|
||||
{
|
||||
int s, worked;
|
||||
u_int32_t outd;
|
||||
u_int8_t nstatus;
|
||||
|
||||
debug_called(3);
|
||||
|
||||
@ -1692,14 +1679,19 @@ amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave)
|
||||
/* work waiting for us? */
|
||||
if ((outd = AMR_QGET_ODB(sc)) == AMR_QODB_READY) {
|
||||
|
||||
/* save mailbox, which contains a list of completed commands */
|
||||
bcopy((void *)(uintptr_t)(volatile void *)sc->amr_mailbox, mbsave, sizeof(*mbsave));
|
||||
|
||||
/* acknowledge interrupt */
|
||||
AMR_QPUT_ODB(sc, AMR_QODB_READY);
|
||||
|
||||
while ((nstatus = sc->amr_mailbox->mb_nstatus) == 0xff)
|
||||
;
|
||||
sc->amr_mailbox->mb_nstatus = 0xff;
|
||||
|
||||
/* save mailbox, which contains a list of completed commands */
|
||||
bcopy((void *)(uintptr_t)(volatile void *)sc->amr_mailbox, mbsave, sizeof(*mbsave));
|
||||
mbsave->mb_nstatus = nstatus;
|
||||
|
||||
/* acknowledge that we have the commands */
|
||||
AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_ACK);
|
||||
AMR_QPUT_IDB(sc, AMR_QIDB_ACK);
|
||||
|
||||
#ifndef AMR_QUARTZ_GOFASTER
|
||||
/*
|
||||
@ -1843,6 +1835,7 @@ amr_describe_controller(struct amr_softc *sc)
|
||||
struct amr_enquiry *ae;
|
||||
char *prod;
|
||||
|
||||
mtx_lock(&sc->amr_io_lock);
|
||||
/*
|
||||
* Try to get 40LD product info, which tells us what the card is labelled as.
|
||||
*/
|
||||
@ -1852,6 +1845,7 @@ amr_describe_controller(struct amr_softc *sc)
|
||||
ap->ap_memsize);
|
||||
|
||||
free(ap, M_DEVBUF);
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1918,6 +1912,7 @@ amr_describe_controller(struct amr_softc *sc)
|
||||
ae->ae_adapter.aa_memorysize);
|
||||
}
|
||||
free(ae, M_DEVBUF);
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -262,8 +262,10 @@ amr_cam_action(struct cam_sim *sim, union ccb *ccb)
|
||||
/* save the channel number in the ccb */
|
||||
csio->ccb_h.sim_priv.entries[0].field = cam_sim_bus(sim);
|
||||
|
||||
mtx_lock(&sc->amr_io_lock);
|
||||
amr_enqueue_ccb(sc, ccb);
|
||||
amr_startio(sc);
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -491,7 +493,11 @@ amr_cam_command(struct amr_softc *sc, struct amr_command **acp)
|
||||
static void
|
||||
amr_cam_poll(struct cam_sim *sim)
|
||||
{
|
||||
struct amr_softc *sc = cam_sim_softc(sim);
|
||||
|
||||
mtx_lock(&sc->amr_io_lock);
|
||||
amr_done(cam_sim_softc(sim));
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
@ -500,6 +506,7 @@ amr_cam_poll(struct cam_sim *sim)
|
||||
static void
|
||||
amr_cam_complete(struct amr_command *ac)
|
||||
{
|
||||
struct amr_softc *sc = ac->ac_sc;
|
||||
struct amr_passthrough *ap = (struct amr_passthrough *)ac->ac_data;
|
||||
struct ccb_scsiio *csio = (struct ccb_scsiio *)ac->ac_private;
|
||||
struct scsi_inquiry_data *inq = (struct scsi_inquiry_data *)csio->data_ptr;
|
||||
@ -552,7 +559,11 @@ amr_cam_complete(struct amr_command *ac)
|
||||
free(ap, M_DEVBUF);
|
||||
if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
|
||||
debug(2, "%*D\n", imin(csio->dxfer_len, 16), csio->data_ptr, " ");
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
mtx_lock(&Giant);
|
||||
xpt_done((union ccb *)csio);
|
||||
mtx_unlock(&Giant);
|
||||
mtx_lock(&sc->amr_io_lock);
|
||||
amr_releasecmd(ac);
|
||||
}
|
||||
|
||||
@ -563,6 +574,7 @@ amr_cam_complete(struct amr_command *ac)
|
||||
static void
|
||||
amr_cam_complete_extcdb(struct amr_command *ac)
|
||||
{
|
||||
struct amr_softc *sc = ac->ac_sc;
|
||||
struct amr_ext_passthrough *aep = (struct amr_ext_passthrough *)ac->ac_data;
|
||||
struct ccb_scsiio *csio = (struct ccb_scsiio *)ac->ac_private;
|
||||
struct scsi_inquiry_data *inq = (struct scsi_inquiry_data *)csio->data_ptr;
|
||||
@ -615,6 +627,10 @@ amr_cam_complete_extcdb(struct amr_command *ac)
|
||||
free(aep, M_DEVBUF);
|
||||
if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
|
||||
debug(2, "%*D\n", imin(csio->dxfer_len, 16), csio->data_ptr, " ");
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
mtx_lock(&Giant);
|
||||
xpt_done((union ccb *)csio);
|
||||
mtx_unlock(&Giant);
|
||||
mtx_lock(&sc->amr_io_lock);
|
||||
amr_releasecmd(ac);
|
||||
}
|
||||
|
@ -256,7 +256,7 @@ amrd_attach(device_t dev)
|
||||
sc->amrd_disk->d_name = "amrd";
|
||||
sc->amrd_disk->d_dump = (dumper_t *)amrd_dump;
|
||||
sc->amrd_disk->d_unit = sc->amrd_unit;
|
||||
sc->amrd_disk->d_flags = DISKFLAG_NEEDSGIANT;
|
||||
sc->amrd_disk->d_flags = 0;
|
||||
disk_create(sc->amrd_disk, DISK_VERSION);
|
||||
#ifdef FREEBSD_4
|
||||
disks_registered++;
|
||||
|
@ -173,6 +173,7 @@ amr_pci_attach(device_t dev)
|
||||
sc = device_get_softc(dev);
|
||||
bzero(sc, sizeof(*sc));
|
||||
sc->amr_dev = dev;
|
||||
mtx_init(&sc->amr_io_lock, "AMR IO Lock", NULL, MTX_DEF);
|
||||
|
||||
/* assume failure is 'not configured' */
|
||||
error = ENXIO;
|
||||
@ -233,7 +234,7 @@ amr_pci_attach(device_t dev)
|
||||
device_printf(sc->amr_dev, "can't allocate interrupt\n");
|
||||
goto out;
|
||||
}
|
||||
if (bus_setup_intr(sc->amr_dev, sc->amr_irq, INTR_TYPE_BIO | INTR_ENTROPY, amr_pci_intr, sc, &sc->amr_intr)) {
|
||||
if (bus_setup_intr(sc->amr_dev, sc->amr_irq, INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE, amr_pci_intr, sc, &sc->amr_intr)) {
|
||||
device_printf(sc->amr_dev, "can't set up interrupt\n");
|
||||
goto out;
|
||||
}
|
||||
@ -271,7 +272,7 @@ amr_pci_attach(device_t dev)
|
||||
MAXBSIZE, AMR_NSEG, /* maxsize, nsegments */
|
||||
MAXBSIZE, /* maxsegsize */
|
||||
BUS_DMA_ALLOCNOW, /* flags */
|
||||
busdma_lock_mutex, &Giant, /* lockfunc, lockarg */
|
||||
busdma_lock_mutex, &sc->amr_io_lock, /* lockfunc, lockarg */
|
||||
&sc->amr_buffer_dmat)) {
|
||||
device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n");
|
||||
goto out;
|
||||
@ -423,7 +424,9 @@ amr_pci_intr(void *arg)
|
||||
debug_called(2);
|
||||
|
||||
/* collect finished commands, queue anything waiting */
|
||||
mtx_lock(&sc->amr_io_lock);
|
||||
amr_done(sc);
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
|
@ -57,8 +57,9 @@
|
||||
*/
|
||||
|
||||
#if __FreeBSD_version >= 500005
|
||||
# include <sys/taskqueue.h>
|
||||
# include <geom/geom_disk.h>
|
||||
# include <sys/lock.h>
|
||||
# include <sys/mutex.h>
|
||||
#endif
|
||||
|
||||
#ifdef AMR_DEBUG
|
||||
@ -174,6 +175,7 @@ struct amr_softc
|
||||
bus_dmamap_t amr_sg_dmamap; /* map for s/g buffers */
|
||||
|
||||
/* controller limits and features */
|
||||
int amr_nextslot; /* Next slot to use for newly allocated commands */
|
||||
int amr_maxio; /* maximum number of I/O transactions */
|
||||
int amr_maxdrives; /* max number of logical drives */
|
||||
int amr_maxchan; /* count of SCSI channels */
|
||||
@ -222,9 +224,7 @@ struct amr_softc
|
||||
/* misc glue */
|
||||
struct intr_config_hook amr_ich; /* wait-for-interrupts probe hook */
|
||||
struct callout_handle amr_timeout; /* periodic status check */
|
||||
#if __FreeBSD_version >= 500005
|
||||
struct task amr_task_complete; /* deferred-completion task */
|
||||
#endif
|
||||
struct mtx amr_io_lock;
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user