Basic MPSAFE locking for the AHC and AHD drivers.

This commit is contained in:
scottl 2007-04-17 06:26:25 +00:00
parent 5e201c93e8
commit 46e32eee32
13 changed files with 72 additions and 336 deletions

View File

@ -126,7 +126,6 @@ aic7770_find_device(uint32_t id)
int int
aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
{ {
u_long l;
int error; int error;
int have_seeprom; int have_seeprom;
u_int hostconf; u_int hostconf;
@ -254,7 +253,7 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
if (error != 0) if (error != 0)
return (error); return (error);
ahc_list_lock(&l); ahc_lock(ahc);
/* /*
* Link this softc in with all other ahc instances. * Link this softc in with all other ahc instances.
*/ */
@ -265,7 +264,7 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
*/ */
ahc_outb(ahc, BCTL, ENABLE); ahc_outb(ahc, BCTL, ENABLE);
ahc_list_unlock(&l); ahc_unlock(ahc);
return (0); return (0);
} }

View File

@ -5271,6 +5271,7 @@ ahd_alloc(void *platform_arg, char *name)
ahd_free(ahd); ahd_free(ahd);
ahd = NULL; ahd = NULL;
} }
ahd_lockinit(ahd);
#ifdef AHD_DEBUG #ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_MEMORY) != 0) { if ((ahd_debug & AHD_SHOW_MEMORY) != 0) {
printf("%s: scb size = 0x%x, hscb size = 0x%x\n", printf("%s: scb size = 0x%x, hscb size = 0x%x\n",
@ -5342,22 +5343,6 @@ ahd_softc_insert(struct ahd_softc *ahd)
ahd->init_level++; ahd->init_level++;
} }
/*
* Verify that the passed in softc pointer is for a
* controller that is still configured.
*/
struct ahd_softc *
ahd_find_softc(struct ahd_softc *ahd)
{
struct ahd_softc *list_ahd;
TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
if (list_ahd == ahd)
return (ahd);
}
return (NULL);
}
void void
ahd_set_unit(struct ahd_softc *ahd, int unit) ahd_set_unit(struct ahd_softc *ahd, int unit)
{ {
@ -6215,6 +6200,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
next_scb->col_scb = ahd_find_scb_by_tag(ahd, col_tag); next_scb->col_scb = ahd_find_scb_by_tag(ahd, col_tag);
if (next_scb->col_scb != NULL) if (next_scb->col_scb != NULL)
next_scb->col_scb->col_scb = next_scb; next_scb->col_scb->col_scb = next_scb;
aic_timer_init(&next_scb->io_timer);
ahd_free_scb(ahd, next_scb); ahd_free_scb(ahd, next_scb);
hscb++; hscb++;
hscb_busaddr += sizeof(*hscb); hscb_busaddr += sizeof(*hscb);
@ -8060,19 +8046,10 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
static void static void
ahd_reset_poll(void *arg) ahd_reset_poll(void *arg)
{ {
struct ahd_softc *ahd; struct ahd_softc *ahd = (struct ahd_softc *)arg;
u_int scsiseq1; u_int scsiseq1;
u_long l;
u_long s;
ahd_list_lock(&l); ahd_lock(ahd);
ahd = ahd_find_softc((struct ahd_softc *)arg);
if (ahd == NULL) {
printf("ahd_reset_poll: Instance %p no longer exists\n", arg);
ahd_list_unlock(&l);
return;
}
ahd_lock(ahd, &s);
ahd_pause(ahd); ahd_pause(ahd);
ahd_update_modes(ahd); ahd_update_modes(ahd);
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
@ -8081,8 +8058,7 @@ ahd_reset_poll(void *arg)
aic_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_MS, aic_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_MS,
ahd_reset_poll, ahd); ahd_reset_poll, ahd);
ahd_unpause(ahd); ahd_unpause(ahd);
ahd_unlock(ahd, &s); ahd_unlock(ahd);
ahd_list_unlock(&l);
return; return;
} }
@ -8092,29 +8068,18 @@ ahd_reset_poll(void *arg)
ahd_outb(ahd, SCSISEQ1, scsiseq1 & (ENSELI|ENRSELI|ENAUTOATNP)); ahd_outb(ahd, SCSISEQ1, scsiseq1 & (ENSELI|ENRSELI|ENAUTOATNP));
ahd_unpause(ahd); ahd_unpause(ahd);
ahd->flags &= ~AHD_RESET_POLL_ACTIVE; ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
ahd_unlock(ahd, &s);
aic_release_simq(ahd); aic_release_simq(ahd);
ahd_list_unlock(&l); ahd_unlock(ahd);
} }
/**************************** Statistics Processing ***************************/ /**************************** Statistics Processing ***************************/
static void static void
ahd_stat_timer(void *arg) ahd_stat_timer(void *arg)
{ {
struct ahd_softc *ahd; struct ahd_softc *ahd = (struct ahd_softc *)arg;
u_long l;
u_long s;
int enint_coal; int enint_coal;
ahd_list_lock(&l); ahd_lock(ahd);
ahd = ahd_find_softc((struct ahd_softc *)arg);
if (ahd == NULL) {
printf("ahd_stat_timer: Instance %p no longer exists\n", arg);
ahd_list_unlock(&l);
return;
}
ahd_lock(ahd, &s);
enint_coal = ahd->hs_mailbox & ENINT_COALESCE; enint_coal = ahd->hs_mailbox & ENINT_COALESCE;
if (ahd->cmdcmplt_total > ahd->int_coalescing_threshold) if (ahd->cmdcmplt_total > ahd->int_coalescing_threshold)
enint_coal |= ENINT_COALESCE; enint_coal |= ENINT_COALESCE;
@ -8138,8 +8103,7 @@ ahd_stat_timer(void *arg)
ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket] = 0; ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket] = 0;
aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_MS, aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_MS,
ahd_stat_timer, ahd); ahd_stat_timer, ahd);
ahd_unlock(ahd, &s); ahd_unlock(ahd);
ahd_list_unlock(&l);
} }
/****************************** Status Processing *****************************/ /****************************** Status Processing *****************************/
@ -9300,14 +9264,11 @@ ahd_recover_commands(struct ahd_softc *ahd)
{ {
struct scb *scb; struct scb *scb;
struct scb *active_scb; struct scb *active_scb;
long s;
int found; int found;
int was_paused; int was_paused;
u_int active_scbptr; u_int active_scbptr;
u_int last_phase; u_int last_phase;
ahd_lock(ahd, &s);
/* /*
* Pause the controller and manually flush any * Pause the controller and manually flush any
* commands that have just completed but that our * commands that have just completed but that our
@ -9333,7 +9294,6 @@ ahd_recover_commands(struct ahd_softc *ahd)
printf("%s: Timedout SCBs already complete. " printf("%s: Timedout SCBs already complete. "
"Interrupts may not be functioning.\n", ahd_name(ahd)); "Interrupts may not be functioning.\n", ahd_name(ahd));
ahd_unpause(ahd); ahd_unpause(ahd);
ahd_unlock(ahd, &s);
return; return;
} }
@ -9524,7 +9484,6 @@ bus_reset:
} }
ahd_unpause(ahd); ahd_unpause(ahd);
ahd_unlock(ahd, &s);
} }
/* /*
@ -9940,13 +9899,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
*/ */
if ((ahd->flags & AHD_TARGETROLE) == 0 if ((ahd->flags & AHD_TARGETROLE) == 0
&& ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
u_long s;
printf("Configuring Target Mode\n"); printf("Configuring Target Mode\n");
ahd_lock(ahd, &s);
if (LIST_FIRST(&ahd->pending_scbs) != NULL) { if (LIST_FIRST(&ahd->pending_scbs) != NULL) {
ccb->ccb_h.status = CAM_BUSY; ccb->ccb_h.status = CAM_BUSY;
ahd_unlock(ahd, &s);
return; return;
} }
ahd->flags |= AHD_TARGETROLE; ahd->flags |= AHD_TARGETROLE;
@ -9955,7 +9910,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
ahd_pause(ahd); ahd_pause(ahd);
ahd_loadseq(ahd); ahd_loadseq(ahd);
ahd_restart(ahd); ahd_restart(ahd);
ahd_unlock(ahd, &s);
} }
cel = &ccb->cel; cel = &ccb->cel;
target = ccb->ccb_h.target_id; target = ccb->ccb_h.target_id;
@ -10021,7 +9975,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
} }
SLIST_INIT(&lstate->accept_tios); SLIST_INIT(&lstate->accept_tios);
SLIST_INIT(&lstate->immed_notifies); SLIST_INIT(&lstate->immed_notifies);
ahd_lock(ahd, &s);
ahd_pause(ahd); ahd_pause(ahd);
if (target != CAM_TARGET_WILDCARD) { if (target != CAM_TARGET_WILDCARD) {
tstate->enabled_luns[lun] = lstate; tstate->enabled_luns[lun] = lstate;
@ -10080,7 +10033,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
ahd_outb(ahd, SCSISEQ1, scsiseq1); ahd_outb(ahd, SCSISEQ1, scsiseq1);
} }
ahd_unpause(ahd); ahd_unpause(ahd);
ahd_unlock(ahd, &s);
ccb->ccb_h.status = CAM_REQ_CMP; ccb->ccb_h.status = CAM_REQ_CMP;
xpt_print_path(ccb->ccb_h.path); xpt_print_path(ccb->ccb_h.path);
printf("Lun now enabled for target mode\n"); printf("Lun now enabled for target mode\n");
@ -10093,8 +10045,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
return; return;
} }
ahd_lock(ahd, &s);
ccb->ccb_h.status = CAM_REQ_CMP; ccb->ccb_h.status = CAM_REQ_CMP;
LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) { LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
struct ccb_hdr *ccbh; struct ccb_hdr *ccbh;
@ -10104,7 +10054,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
&& !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){ && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){
printf("CTIO pending\n"); printf("CTIO pending\n");
ccb->ccb_h.status = CAM_REQ_INVALID; ccb->ccb_h.status = CAM_REQ_INVALID;
ahd_unlock(ahd, &s);
return; return;
} }
} }
@ -10120,7 +10069,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
} }
if (ccb->ccb_h.status != CAM_REQ_CMP) { if (ccb->ccb_h.status != CAM_REQ_CMP) {
ahd_unlock(ahd, &s);
return; return;
} }
@ -10187,7 +10135,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
} }
} }
ahd_unpause(ahd); ahd_unpause(ahd);
ahd_unlock(ahd, &s);
} }
#endif #endif
} }

View File

@ -639,6 +639,7 @@ struct scb {
u_int sg_count;/* How full ahd_dma_seg is */ u_int sg_count;/* How full ahd_dma_seg is */
#define AHD_MAX_LQ_CRC_ERRORS 5 #define AHD_MAX_LQ_CRC_ERRORS 5
u_int crc_retry_count; u_int crc_retry_count;
aic_timer_t io_timer;
}; };
TAILQ_HEAD(scb_tailq, scb); TAILQ_HEAD(scb_tailq, scb);
@ -1397,7 +1398,6 @@ void ahd_pause_and_flushwork(struct ahd_softc *ahd);
int ahd_suspend(struct ahd_softc *ahd); int ahd_suspend(struct ahd_softc *ahd);
int ahd_resume(struct ahd_softc *ahd); int ahd_resume(struct ahd_softc *ahd);
void ahd_softc_insert(struct ahd_softc *); void ahd_softc_insert(struct ahd_softc *);
struct ahd_softc *ahd_find_softc(struct ahd_softc *ahd);
void ahd_set_unit(struct ahd_softc *, int); void ahd_set_unit(struct ahd_softc *, int);
void ahd_set_name(struct ahd_softc *, char *); void ahd_set_name(struct ahd_softc *, char *);
struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx); struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx);

View File

@ -95,8 +95,8 @@ ahd_map_int(struct ahd_softc *ahd)
/* Hook up our interrupt handler */ /* Hook up our interrupt handler */
error = bus_setup_intr(ahd->dev_softc, ahd->platform_data->irq, error = bus_setup_intr(ahd->dev_softc, ahd->platform_data->irq,
INTR_TYPE_CAM, NULL, ahd_platform_intr, ahd, INTR_TYPE_CAM|INTR_MPSAFE, NULL,
&ahd->platform_data->ih); ahd_platform_intr, ahd, &ahd->platform_data->ih);
if (error != 0) if (error != 0)
device_printf(ahd->dev_softc, "bus_setup_intr() failed: %d\n", device_printf(ahd->dev_softc, "bus_setup_intr() failed: %d\n",
error); error);
@ -114,7 +114,6 @@ ahd_attach(struct ahd_softc *ahd)
struct cam_devq *devq; struct cam_devq *devq;
struct cam_sim *sim; struct cam_sim *sim;
struct cam_path *path; struct cam_path *path;
long s;
int count; int count;
count = 0; count = 0;
@ -129,7 +128,7 @@ ahd_attach(struct ahd_softc *ahd)
ahd_controller_info(ahd, ahd_info); ahd_controller_info(ahd, ahd_info);
printf("%s\n", ahd_info); printf("%s\n", ahd_info);
ahd_lock(ahd, &s); ahd_lock(ahd);
/* /*
* Create the device queue for our SIM(s). * Create the device queue for our SIM(s).
@ -143,7 +142,7 @@ ahd_attach(struct ahd_softc *ahd)
*/ */
sim = cam_sim_alloc(ahd_action, ahd_poll, "ahd", ahd, sim = cam_sim_alloc(ahd_action, ahd_poll, "ahd", ahd,
device_get_unit(ahd->dev_softc), device_get_unit(ahd->dev_softc),
&Giant, 1, /*XXX*/256, devq); &ahd->platform_data->mtx, 1, /*XXX*/256, devq);
if (sim == NULL) { if (sim == NULL) {
cam_simq_free(devq); cam_simq_free(devq);
goto fail; goto fail;
@ -175,6 +174,7 @@ ahd_attach(struct ahd_softc *ahd)
fail: fail:
ahd->platform_data->sim = sim; ahd->platform_data->sim = sim;
ahd->platform_data->path = path; ahd->platform_data->path = path;
ahd_unlock(ahd);
if (count != 0) { if (count != 0) {
/* We have to wait until after any system dumps... */ /* We have to wait until after any system dumps... */
ahd->platform_data->eh = ahd->platform_data->eh =
@ -183,7 +183,6 @@ fail:
ahd_intr_enable(ahd, TRUE); ahd_intr_enable(ahd, TRUE);
} }
ahd_unlock(ahd, &s);
return (count); return (count);
} }
@ -197,7 +196,9 @@ ahd_platform_intr(void *arg)
struct ahd_softc *ahd; struct ahd_softc *ahd;
ahd = (struct ahd_softc *)arg; ahd = (struct ahd_softc *)arg;
ahd_lock(ahd);
ahd_intr(ahd); ahd_intr(ahd);
ahd_unlock(ahd);
} }
/* /*
@ -218,7 +219,7 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
if ((scb->flags & SCB_TIMEDOUT) != 0) if ((scb->flags & SCB_TIMEDOUT) != 0)
LIST_REMOVE(scb, timedout_links); LIST_REMOVE(scb, timedout_links);
untimeout(ahd_platform_timeout, (caddr_t)scb, ccb->ccb_h.timeout_ch); callout_stop(&scb->io_timer);
if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
bus_dmasync_op_t op; bus_dmasync_op_t op;
@ -348,7 +349,6 @@ ahd_action(struct cam_sim *sim, union ccb *ccb)
#endif #endif
u_int target_id; u_int target_id;
u_int our_id; u_int our_id;
long s;
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahd_action\n")); CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahd_action\n"));
@ -382,13 +382,11 @@ ahd_action(struct cam_sim *sim, union ccb *ccb)
} }
if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) { if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
ahd_lock(ahd, &s);
SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h, SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h,
sim_links.sle); sim_links.sle);
ccb->ccb_h.status = CAM_REQ_INPROG; ccb->ccb_h.status = CAM_REQ_INPROG;
if ((ahd->flags & AHD_TQINFIFO_BLOCKED) != 0) if ((ahd->flags & AHD_TQINFIFO_BLOCKED) != 0)
ahd_run_tqinfifo(ahd, /*paused*/FALSE); ahd_run_tqinfifo(ahd, /*paused*/FALSE);
ahd_unlock(ahd, &s);
break; break;
} }
@ -422,7 +420,6 @@ ahd_action(struct cam_sim *sim, union ccb *ccb)
/* /*
* get an scb to use. * get an scb to use.
*/ */
ahd_lock(ahd, &s);
tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, tinfo = ahd_fetch_transinfo(ahd, 'A', our_id,
target_id, &tstate); target_id, &tstate);
if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) == 0 if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) == 0
@ -437,12 +434,10 @@ ahd_action(struct cam_sim *sim, union ccb *ccb)
xpt_freeze_simq(sim, /*count*/1); xpt_freeze_simq(sim, /*count*/1);
ahd->flags |= AHD_RESOURCE_SHORTAGE; ahd->flags |= AHD_RESOURCE_SHORTAGE;
ahd_unlock(ahd, &s);
ccb->ccb_h.status = CAM_REQUEUE_REQ; ccb->ccb_h.status = CAM_REQUEUE_REQ;
xpt_done(ccb); xpt_done(ccb);
return; return;
} }
ahd_unlock(ahd, &s);
hscb = scb->hscb; hscb = scb->hscb;
@ -530,20 +525,16 @@ ahd_action(struct cam_sim *sim, union ccb *ccb)
} }
case XPT_SET_TRAN_SETTINGS: case XPT_SET_TRAN_SETTINGS:
{ {
ahd_lock(ahd, &s);
ahd_set_tran_settings(ahd, SIM_SCSI_ID(ahd, sim), ahd_set_tran_settings(ahd, SIM_SCSI_ID(ahd, sim),
SIM_CHANNEL(ahd, sim), &ccb->cts); SIM_CHANNEL(ahd, sim), &ccb->cts);
ahd_unlock(ahd, &s);
xpt_done(ccb); xpt_done(ccb);
break; break;
} }
case XPT_GET_TRAN_SETTINGS: case XPT_GET_TRAN_SETTINGS:
/* Get default/user set transfer settings for the target */ /* Get default/user set transfer settings for the target */
{ {
ahd_lock(ahd, &s);
ahd_get_tran_settings(ahd, SIM_SCSI_ID(ahd, sim), ahd_get_tran_settings(ahd, SIM_SCSI_ID(ahd, sim),
SIM_CHANNEL(ahd, sim), &ccb->cts); SIM_CHANNEL(ahd, sim), &ccb->cts);
ahd_unlock(ahd, &s);
xpt_done(ccb); xpt_done(ccb);
break; break;
} }
@ -557,10 +548,8 @@ ahd_action(struct cam_sim *sim, union ccb *ccb)
{ {
int found; int found;
ahd_lock(ahd, &s);
found = ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim), found = ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim),
/*initiate reset*/TRUE); /*initiate reset*/TRUE);
ahd_unlock(ahd, &s);
if (bootverbose) { if (bootverbose) {
xpt_print_path(SIM_PATH(ahd, sim)); xpt_print_path(SIM_PATH(ahd, sim));
printf("SCSI bus reset delivered. " printf("SCSI bus reset delivered. "
@ -817,7 +806,6 @@ ahd_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
case AC_LOST_DEVICE: case AC_LOST_DEVICE:
{ {
struct ahd_devinfo devinfo; struct ahd_devinfo devinfo;
long s;
ahd_compile_devinfo(&devinfo, SIM_SCSI_ID(ahd, sim), ahd_compile_devinfo(&devinfo, SIM_SCSI_ID(ahd, sim),
xpt_path_target_id(path), xpt_path_target_id(path),
@ -829,13 +817,11 @@ ahd_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
* Revert to async/narrow transfers * Revert to async/narrow transfers
* for the next device. * for the next device.
*/ */
ahd_lock(ahd, &s);
ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
AHD_TRANS_GOAL|AHD_TRANS_CUR, /*paused*/FALSE); AHD_TRANS_GOAL|AHD_TRANS_CUR, /*paused*/FALSE);
ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0, ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0,
/*ppr_options*/0, AHD_TRANS_GOAL|AHD_TRANS_CUR, /*ppr_options*/0, AHD_TRANS_GOAL|AHD_TRANS_CUR,
/*paused*/FALSE); /*paused*/FALSE);
ahd_unlock(ahd, &s);
break; break;
} }
default: default:
@ -853,7 +839,6 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
struct ahd_initiator_tinfo *tinfo; struct ahd_initiator_tinfo *tinfo;
struct ahd_tmode_tstate *tstate; struct ahd_tmode_tstate *tstate;
u_int mask; u_int mask;
u_long s;
scb = (struct scb *)arg; scb = (struct scb *)arg;
ccb = scb->io_ctx; ccb = scb->io_ctx;
@ -866,9 +851,7 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
aic_set_transaction_status(scb, CAM_REQ_CMP_ERR); aic_set_transaction_status(scb, CAM_REQ_CMP_ERR);
if (nsegments != 0) if (nsegments != 0)
bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap); bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap);
ahd_lock(ahd, &s);
ahd_free_scb(ahd, scb); ahd_free_scb(ahd, scb);
ahd_unlock(ahd, &s);
xpt_done(ccb); xpt_done(ccb);
return; return;
} }
@ -906,8 +889,6 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
} }
} }
ahd_lock(ahd, &s);
/* /*
* Last time we need to check if this SCB needs to * Last time we need to check if this SCB needs to
* be aborted. * be aborted.
@ -917,7 +898,6 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
bus_dmamap_unload(ahd->buffer_dmat, bus_dmamap_unload(ahd->buffer_dmat,
scb->dmamap); scb->dmamap);
ahd_free_scb(ahd, scb); ahd_free_scb(ahd, scb);
ahd_unlock(ahd, &s);
xpt_done(ccb); xpt_done(ccb);
return; return;
} }
@ -967,7 +947,6 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
ahd_queue_scb(ahd, scb); ahd_queue_scb(ahd, scb);
} }
ahd_unlock(ahd, &s);
} }
static void static void
@ -994,7 +973,6 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
if (hscb->cdb_len > MAX_CDB_LEN if (hscb->cdb_len > MAX_CDB_LEN
&& (ccb_h->flags & CAM_CDB_PHYS) == 0) { && (ccb_h->flags & CAM_CDB_PHYS) == 0) {
u_long s;
/* /*
* Should CAM start to support CDB sizes * Should CAM start to support CDB sizes
@ -1003,9 +981,7 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
*/ */
aic_set_transaction_status(scb, aic_set_transaction_status(scb,
CAM_REQ_INVALID); CAM_REQ_INVALID);
ahd_lock(ahd, &s);
ahd_free_scb(ahd, scb); ahd_free_scb(ahd, scb);
ahd_unlock(ahd, &s);
xpt_done((union ccb *)csio); xpt_done((union ccb *)csio);
return; return;
} }
@ -1022,13 +998,10 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
} }
} else { } else {
if (hscb->cdb_len > MAX_CDB_LEN) { if (hscb->cdb_len > MAX_CDB_LEN) {
u_long s;
aic_set_transaction_status(scb, aic_set_transaction_status(scb,
CAM_REQ_INVALID); CAM_REQ_INVALID);
ahd_lock(ahd, &s);
ahd_free_scb(ahd, scb); ahd_free_scb(ahd, scb);
ahd_unlock(ahd, &s);
xpt_done((union ccb *)csio); xpt_done((union ccb *)csio);
return; return;
} }
@ -1292,24 +1265,14 @@ int
ahd_detach(device_t dev) ahd_detach(device_t dev)
{ {
struct ahd_softc *ahd; struct ahd_softc *ahd;
u_long l;
u_long s;
ahd_list_lock(&l);
device_printf(dev, "detaching device\n"); device_printf(dev, "detaching device\n");
ahd = device_get_softc(dev); ahd = device_get_softc(dev);
ahd = ahd_find_softc(ahd); ahd_lock(ahd);
if (ahd == NULL) {
device_printf(dev, "aic7xxx already detached\n");
ahd_list_unlock(&l);
return (ENOENT);
}
TAILQ_REMOVE(&ahd_tailq, ahd, links); TAILQ_REMOVE(&ahd_tailq, ahd, links);
ahd_list_unlock(&l);
ahd_lock(ahd, &s);
ahd_intr_enable(ahd, FALSE); ahd_intr_enable(ahd, FALSE);
bus_teardown_intr(dev, ahd->platform_data->irq, ahd->platform_data->ih); bus_teardown_intr(dev, ahd->platform_data->irq, ahd->platform_data->ih);
ahd_unlock(ahd, &s); ahd_unlock(ahd);
ahd_free(ahd); ahd_free(ahd);
return (0); return (0);
} }

View File

@ -133,6 +133,7 @@ struct ahd_platform_data {
void *ih; void *ih;
eventhandler_tag eh; eventhandler_tag eh;
struct proc *recovery_thread; struct proc *recovery_thread;
struct mtx mtx;
}; };
struct scb_platform_data { struct scb_platform_data {
@ -189,66 +190,25 @@ ahd_flush_device_writes(struct ahd_softc *ahd)
/**************************** Locking Primitives ******************************/ /**************************** Locking Primitives ******************************/
/* Lock protecting internal data structures */ /* Lock protecting internal data structures */
static __inline void ahd_lockinit(struct ahd_softc *); static __inline void ahd_lockinit(struct ahd_softc *);
static __inline void ahd_lock(struct ahd_softc *, unsigned long *flags); static __inline void ahd_lock(struct ahd_softc *);
static __inline void ahd_unlock(struct ahd_softc *, unsigned long *flags); static __inline void ahd_unlock(struct ahd_softc *);
/* Lock held during command compeletion to the upper layer */
static __inline void ahd_done_lockinit(struct ahd_softc *);
static __inline void ahd_done_lock(struct ahd_softc *, unsigned long *flags);
static __inline void ahd_done_unlock(struct ahd_softc *, unsigned long *flags);
/* Lock held during ahd_list manipulation and ahd softc frees */
static __inline void ahd_list_lockinit(void);
static __inline void ahd_list_lock(unsigned long *flags);
static __inline void ahd_list_unlock(unsigned long *flags);
static __inline void static __inline void
ahd_lockinit(struct ahd_softc *ahd) ahd_lockinit(struct ahd_softc *ahd)
{ {
mtx_init(&ahd->platform_data->mtx, "ahd_lock", NULL, MTX_DEF);
} }
static __inline void static __inline void
ahd_lock(struct ahd_softc *ahd, unsigned long *flags) ahd_lock(struct ahd_softc *ahd)
{ {
*flags = splcam(); mtx_lock(&ahd->platform_data->mtx);
} }
static __inline void static __inline void
ahd_unlock(struct ahd_softc *ahd, unsigned long *flags) ahd_unlock(struct ahd_softc *ahd)
{
splx(*flags);
}
/* Lock held during command compeletion to the upper layer */
static __inline void
ahd_done_lockinit(struct ahd_softc *ahd)
{
}
static __inline void
ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags)
{
}
static __inline void
ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags)
{
}
/* Lock held during ahd_list manipulation and ahd softc frees */
static __inline void
ahd_list_lockinit(void)
{
}
static __inline void
ahd_list_lock(unsigned long *flags)
{
}
static __inline void
ahd_list_unlock(unsigned long *flags)
{ {
mtx_unlock(&ahd->platform_data->mtx);
} }
/********************************** PCI ***************************************/ /********************************** PCI ***************************************/

View File

@ -314,7 +314,6 @@ int
ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
{ {
struct scb_data *shared_scb_data; struct scb_data *shared_scb_data;
u_long l;
u_int command; u_int command;
uint32_t devconfig; uint32_t devconfig;
uint16_t device; uint16_t device;
@ -423,12 +422,12 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
if (error != 0) if (error != 0)
return (error); return (error);
ahd_list_lock(&l); ahd_lock(ahd);
/* /*
* Link this softc in with all other ahd instances. * Link this softc in with all other ahd instances.
*/ */
ahd_softc_insert(ahd); ahd_softc_insert(ahd);
ahd_list_unlock(&l); ahd_unlock(ahd);
return (0); return (0);
} }

View File

@ -3948,6 +3948,7 @@ ahc_alloc(void *platform_arg, char *name)
ahc_free(ahc); ahc_free(ahc);
ahc = NULL; ahc = NULL;
} }
ahc_lockinit(ahc);
return (ahc); return (ahc);
} }
@ -4029,22 +4030,6 @@ ahc_softc_insert(struct ahc_softc *ahc)
ahc->init_level++; ahc->init_level++;
} }
/*
* Verify that the passed in softc pointer is for a
* controller that is still configured.
*/
struct ahc_softc *
ahc_find_softc(struct ahc_softc *ahc)
{
struct ahc_softc *list_ahc;
TAILQ_FOREACH(list_ahc, &ahc_tailq, links) {
if (list_ahc == ahc)
return (ahc);
}
return (NULL);
}
void void
ahc_set_unit(struct ahc_softc *ahc, int unit) ahc_set_unit(struct ahc_softc *ahc, int unit)
{ {
@ -4606,6 +4591,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc)
#endif #endif
next_scb->hscb = &scb_data->hscbs[scb_data->numscbs]; next_scb->hscb = &scb_data->hscbs[scb_data->numscbs];
next_scb->hscb->tag = ahc->scb_data->numscbs; next_scb->hscb->tag = ahc->scb_data->numscbs;
aic_timer_init(&next_scb->io_timer);
SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs,
next_scb, links.sle); next_scb, links.sle);
segs += AHC_NSEG; segs += AHC_NSEG;
@ -6944,6 +6930,7 @@ ahc_timeout(struct scb *scb)
struct ahc_softc *ahc; struct ahc_softc *ahc;
ahc = scb->ahc_softc; ahc = scb->ahc_softc;
ahc_lock(ahc);
if ((scb->flags & SCB_ACTIVE) != 0) { if ((scb->flags & SCB_ACTIVE) != 0) {
if ((scb->flags & SCB_TIMEDOUT) == 0) { if ((scb->flags & SCB_TIMEDOUT) == 0) {
LIST_INSERT_HEAD(&ahc->timedout_scbs, scb, LIST_INSERT_HEAD(&ahc->timedout_scbs, scb,
@ -6952,6 +6939,7 @@ ahc_timeout(struct scb *scb)
} }
ahc_wakeup_recovery_thread(ahc); ahc_wakeup_recovery_thread(ahc);
} }
ahc_unlock(ahc);
} }
/* /*
@ -7017,13 +7005,10 @@ void
ahc_recover_commands(struct ahc_softc *ahc) ahc_recover_commands(struct ahc_softc *ahc)
{ {
struct scb *scb; struct scb *scb;
long s;
int found; int found;
int restart_needed; int restart_needed;
u_int last_phase; u_int last_phase;
ahc_lock(ahc, &s);
/* /*
* Pause the controller and manually flush any * Pause the controller and manually flush any
* commands that have just completed but that our * commands that have just completed but that our
@ -7043,7 +7028,6 @@ ahc_recover_commands(struct ahc_softc *ahc)
printf("%s: Timedout SCBs already complete. " printf("%s: Timedout SCBs already complete. "
"Interrupts may not be functioning.\n", ahc_name(ahc)); "Interrupts may not be functioning.\n", ahc_name(ahc));
ahc_unpause(ahc); ahc_unpause(ahc);
ahc_unlock(ahc, &s);
return; return;
} }
@ -7296,7 +7280,6 @@ bus_reset:
ahc_restart(ahc); ahc_restart(ahc);
else else
ahc_unpause(ahc); ahc_unpause(ahc);
ahc_unlock(ahc, &s);
} }
/************************* Target Mode ****************************************/ /************************* Target Mode ****************************************/
@ -7349,7 +7332,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
struct ahc_tmode_lstate *lstate; struct ahc_tmode_lstate *lstate;
struct ccb_en_lun *cel; struct ccb_en_lun *cel;
cam_status status; cam_status status;
u_long s;
u_int target; u_int target;
u_int lun; u_int lun;
u_int target_mask; u_int target_mask;
@ -7431,14 +7413,11 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
*/ */
if ((ahc->flags & AHC_TARGETROLE) == 0 if ((ahc->flags & AHC_TARGETROLE) == 0
&& ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
u_long s;
ahc_flag saved_flags; ahc_flag saved_flags;
printf("Configuring Target Mode\n"); printf("Configuring Target Mode\n");
ahc_lock(ahc, &s);
if (LIST_FIRST(&ahc->pending_scbs) != NULL) { if (LIST_FIRST(&ahc->pending_scbs) != NULL) {
ccb->ccb_h.status = CAM_BUSY; ccb->ccb_h.status = CAM_BUSY;
ahc_unlock(ahc, &s);
return; return;
} }
saved_flags = ahc->flags; saved_flags = ahc->flags;
@ -7459,12 +7438,10 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
ahc->flags = saved_flags; ahc->flags = saved_flags;
(void)ahc_loadseq(ahc); (void)ahc_loadseq(ahc);
ahc_restart(ahc); ahc_restart(ahc);
ahc_unlock(ahc, &s);
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
return; return;
} }
ahc_restart(ahc); ahc_restart(ahc);
ahc_unlock(ahc, &s);
} }
cel = &ccb->cel; cel = &ccb->cel;
target = ccb->ccb_h.target_id; target = ccb->ccb_h.target_id;
@ -7530,7 +7507,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
} }
SLIST_INIT(&lstate->accept_tios); SLIST_INIT(&lstate->accept_tios);
SLIST_INIT(&lstate->immed_notifies); SLIST_INIT(&lstate->immed_notifies);
ahc_lock(ahc, &s);
ahc_pause(ahc); ahc_pause(ahc);
if (target != CAM_TARGET_WILDCARD) { if (target != CAM_TARGET_WILDCARD) {
tstate->enabled_luns[lun] = lstate; tstate->enabled_luns[lun] = lstate;
@ -7596,7 +7572,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
ahc_outb(ahc, SCSISEQ, scsiseq); ahc_outb(ahc, SCSISEQ, scsiseq);
} }
ahc_unpause(ahc); ahc_unpause(ahc);
ahc_unlock(ahc, &s);
ccb->ccb_h.status = CAM_REQ_CMP; ccb->ccb_h.status = CAM_REQ_CMP;
xpt_print_path(ccb->ccb_h.path); xpt_print_path(ccb->ccb_h.path);
printf("Lun now enabled for target mode\n"); printf("Lun now enabled for target mode\n");
@ -7609,8 +7584,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
return; return;
} }
ahc_lock(ahc, &s);
ccb->ccb_h.status = CAM_REQ_CMP; ccb->ccb_h.status = CAM_REQ_CMP;
LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) { LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) {
struct ccb_hdr *ccbh; struct ccb_hdr *ccbh;
@ -7620,7 +7593,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
&& !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){ && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){
printf("CTIO pending\n"); printf("CTIO pending\n");
ccb->ccb_h.status = CAM_REQ_INVALID; ccb->ccb_h.status = CAM_REQ_INVALID;
ahc_unlock(ahc, &s);
return; return;
} }
} }
@ -7636,7 +7608,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
} }
if (ccb->ccb_h.status != CAM_REQ_CMP) { if (ccb->ccb_h.status != CAM_REQ_CMP) {
ahc_unlock(ahc, &s);
return; return;
} }
@ -7711,7 +7682,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
} }
} }
ahc_unpause(ahc); ahc_unpause(ahc);
ahc_unlock(ahc, &s);
} }
} }

View File

@ -597,6 +597,7 @@ struct scb {
struct ahc_dma_seg *sg_list; struct ahc_dma_seg *sg_list;
bus_addr_t sg_list_phys; bus_addr_t sg_list_phys;
u_int sg_count;/* How full ahc_dma_seg is */ u_int sg_count;/* How full ahc_dma_seg is */
aic_timer_t io_timer;
}; };
struct scb_data { struct scb_data {
@ -1224,7 +1225,6 @@ void ahc_pause_and_flushwork(struct ahc_softc *ahc);
int ahc_suspend(struct ahc_softc *ahc); int ahc_suspend(struct ahc_softc *ahc);
int ahc_resume(struct ahc_softc *ahc); int ahc_resume(struct ahc_softc *ahc);
void ahc_softc_insert(struct ahc_softc *); void ahc_softc_insert(struct ahc_softc *);
struct ahc_softc *ahc_find_softc(struct ahc_softc *ahc);
void ahc_set_unit(struct ahc_softc *, int); void ahc_set_unit(struct ahc_softc *, int);
void ahc_set_name(struct ahc_softc *, char *); void ahc_set_name(struct ahc_softc *, char *);
void ahc_alloc_scbs(struct ahc_softc *ahc); void ahc_alloc_scbs(struct ahc_softc *ahc);

View File

@ -107,8 +107,8 @@ ahc_map_int(struct ahc_softc *ahc)
/* Hook up our interrupt handler */ /* Hook up our interrupt handler */
error = bus_setup_intr(ahc->dev_softc, ahc->platform_data->irq, error = bus_setup_intr(ahc->dev_softc, ahc->platform_data->irq,
INTR_TYPE_CAM, NULL, ahc_platform_intr, ahc, INTR_TYPE_CAM|INTR_MPSAFE, NULL,
&ahc->platform_data->ih); ahc_platform_intr, ahc, &ahc->platform_data->ih);
if (error != 0) if (error != 0)
device_printf(ahc->dev_softc, "bus_setup_intr() failed: %d\n", device_printf(ahc->dev_softc, "bus_setup_intr() failed: %d\n",
@ -152,7 +152,6 @@ ahc_attach(struct ahc_softc *ahc)
struct cam_sim *sim2; struct cam_sim *sim2;
struct cam_path *path; struct cam_path *path;
struct cam_path *path2; struct cam_path *path2;
long s;
int count; int count;
count = 0; count = 0;
@ -161,6 +160,7 @@ ahc_attach(struct ahc_softc *ahc)
path = NULL; path = NULL;
path2 = NULL; path2 = NULL;
/* /*
* Create a thread to perform all recovery. * Create a thread to perform all recovery.
*/ */
@ -169,7 +169,7 @@ ahc_attach(struct ahc_softc *ahc)
ahc_controller_info(ahc, ahc_info); ahc_controller_info(ahc, ahc_info);
printf("%s\n", ahc_info); printf("%s\n", ahc_info);
ahc_lock(ahc, &s); ahc_lock(ahc);
/* /*
* Attach secondary channel first if the user has * Attach secondary channel first if the user has
@ -196,7 +196,7 @@ ahc_attach(struct ahc_softc *ahc)
*/ */
sim = cam_sim_alloc(ahc_action, ahc_poll, "ahc", ahc, sim = cam_sim_alloc(ahc_action, ahc_poll, "ahc", ahc,
device_get_unit(ahc->dev_softc), device_get_unit(ahc->dev_softc),
&Giant, 1, AHC_MAX_QUEUE, devq); &ahc->platform_data->mtx, 1, AHC_MAX_QUEUE, devq);
if (sim == NULL) { if (sim == NULL) {
cam_simq_free(devq); cam_simq_free(devq);
goto fail; goto fail;
@ -228,7 +228,7 @@ ahc_attach(struct ahc_softc *ahc)
if (ahc->features & AHC_TWIN) { if (ahc->features & AHC_TWIN) {
sim2 = cam_sim_alloc(ahc_action, ahc_poll, "ahc", sim2 = cam_sim_alloc(ahc_action, ahc_poll, "ahc",
ahc, device_get_unit(ahc->dev_softc), ahc, device_get_unit(ahc->dev_softc),
&Giant, 1, &ahc->platform_data->mtx, 1,
AHC_MAX_QUEUE, devq); AHC_MAX_QUEUE, devq);
if (sim2 == NULL) { if (sim2 == NULL) {
@ -279,6 +279,7 @@ fail:
ahc->platform_data->sim_b = sim2; ahc->platform_data->sim_b = sim2;
ahc->platform_data->path_b = path2; ahc->platform_data->path_b = path2;
} }
ahc_unlock(ahc);
if (count != 0) { if (count != 0) {
/* We have to wait until after any system dumps... */ /* We have to wait until after any system dumps... */
@ -288,7 +289,6 @@ fail:
ahc_intr_enable(ahc, TRUE); ahc_intr_enable(ahc, TRUE);
} }
ahc_unlock(ahc, &s);
return (count); return (count);
} }
@ -301,7 +301,9 @@ ahc_platform_intr(void *arg)
struct ahc_softc *ahc; struct ahc_softc *ahc;
ahc = (struct ahc_softc *)arg; ahc = (struct ahc_softc *)arg;
ahc_lock(ahc);
ahc_intr(ahc); ahc_intr(ahc);
ahc_unlock(ahc);
} }
/* /*
@ -332,7 +334,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
ahc_run_untagged_queue(ahc, untagged_q); ahc_run_untagged_queue(ahc, untagged_q);
} }
untimeout(ahc_platform_timeout, (caddr_t)scb, ccb->ccb_h.timeout_ch); callout_stop(&scb->io_timer);
if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
bus_dmasync_op_t op; bus_dmasync_op_t op;
@ -442,7 +444,6 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
struct ahc_tmode_lstate *lstate; struct ahc_tmode_lstate *lstate;
u_int target_id; u_int target_id;
u_int our_id; u_int our_id;
long s;
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahc_action\n")); CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahc_action\n"));
@ -475,13 +476,11 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
} }
if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) { if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
ahc_lock(ahc, &s);
SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h, SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h,
sim_links.sle); sim_links.sle);
ccb->ccb_h.status = CAM_REQ_INPROG; ccb->ccb_h.status = CAM_REQ_INPROG;
if ((ahc->flags & AHC_TQINFIFO_BLOCKED) != 0) if ((ahc->flags & AHC_TQINFIFO_BLOCKED) != 0)
ahc_run_tqinfifo(ahc, /*paused*/FALSE); ahc_run_tqinfifo(ahc, /*paused*/FALSE);
ahc_unlock(ahc, &s);
break; break;
} }
@ -511,17 +510,14 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
/* /*
* get an scb to use. * get an scb to use.
*/ */
ahc_lock(ahc, &s);
if ((scb = ahc_get_scb(ahc)) == NULL) { if ((scb = ahc_get_scb(ahc)) == NULL) {
xpt_freeze_simq(sim, /*count*/1); xpt_freeze_simq(sim, /*count*/1);
ahc->flags |= AHC_RESOURCE_SHORTAGE; ahc->flags |= AHC_RESOURCE_SHORTAGE;
ahc_unlock(ahc, &s);
ccb->ccb_h.status = CAM_REQUEUE_REQ; ccb->ccb_h.status = CAM_REQUEUE_REQ;
xpt_done(ccb); xpt_done(ccb);
return; return;
} }
ahc_unlock(ahc, &s);
hscb = scb->hscb; hscb = scb->hscb;
@ -651,8 +647,6 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
break; break;
} }
ahc_lock(ahc, &s);
if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
*discenable |= devinfo.target_mask; *discenable |= devinfo.target_mask;
@ -728,7 +722,6 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
spi->ppr_options, update_type, spi->ppr_options, update_type,
/*paused*/FALSE); /*paused*/FALSE);
} }
ahc_unlock(ahc, &s);
ccb->ccb_h.status = CAM_REQ_CMP; ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb); xpt_done(ccb);
break; break;
@ -737,10 +730,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
/* Get default/user set transfer settings for the target */ /* Get default/user set transfer settings for the target */
{ {
ahc_lock(ahc, &s);
ahc_get_tran_settings(ahc, SIM_SCSI_ID(ahc, sim), ahc_get_tran_settings(ahc, SIM_SCSI_ID(ahc, sim),
SIM_CHANNEL(ahc, sim), &ccb->cts); SIM_CHANNEL(ahc, sim), &ccb->cts);
ahc_unlock(ahc, &s);
xpt_done(ccb); xpt_done(ccb);
break; break;
} }
@ -759,10 +750,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
{ {
int found; int found;
ahc_lock(ahc, &s);
found = ahc_reset_channel(ahc, SIM_CHANNEL(ahc, sim), found = ahc_reset_channel(ahc, SIM_CHANNEL(ahc, sim),
/*initiate reset*/TRUE); /*initiate reset*/TRUE);
ahc_unlock(ahc, &s);
if (bootverbose) { if (bootverbose) {
xpt_print_path(SIM_PATH(ahc, sim)); xpt_print_path(SIM_PATH(ahc, sim));
printf("SCSI bus reset delivered. " printf("SCSI bus reset delivered. "
@ -910,7 +899,6 @@ ahc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
case AC_LOST_DEVICE: case AC_LOST_DEVICE:
{ {
struct ahc_devinfo devinfo; struct ahc_devinfo devinfo;
long s;
ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim), ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim),
xpt_path_target_id(path), xpt_path_target_id(path),
@ -922,14 +910,12 @@ ahc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
* Revert to async/narrow transfers * Revert to async/narrow transfers
* for the next device. * for the next device.
*/ */
ahc_lock(ahc, &s);
ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
AHC_TRANS_GOAL|AHC_TRANS_CUR, /*paused*/FALSE); AHC_TRANS_GOAL|AHC_TRANS_CUR, /*paused*/FALSE);
ahc_set_syncrate(ahc, &devinfo, /*syncrate*/NULL, ahc_set_syncrate(ahc, &devinfo, /*syncrate*/NULL,
/*period*/0, /*offset*/0, /*ppr_options*/0, /*period*/0, /*offset*/0, /*ppr_options*/0,
AHC_TRANS_GOAL|AHC_TRANS_CUR, AHC_TRANS_GOAL|AHC_TRANS_CUR,
/*paused*/FALSE); /*paused*/FALSE);
ahc_unlock(ahc, &s);
break; break;
} }
default: default:
@ -947,7 +933,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
struct ahc_initiator_tinfo *tinfo; struct ahc_initiator_tinfo *tinfo;
struct ahc_tmode_tstate *tstate; struct ahc_tmode_tstate *tstate;
u_int mask; u_int mask;
long s;
scb = (struct scb *)arg; scb = (struct scb *)arg;
ccb = scb->io_ctx; ccb = scb->io_ctx;
@ -960,9 +945,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
aic_set_transaction_status(scb, CAM_REQ_CMP_ERR); aic_set_transaction_status(scb, CAM_REQ_CMP_ERR);
if (nsegments != 0) if (nsegments != 0)
bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap);
ahc_lock(ahc, &s);
ahc_free_scb(ahc, scb); ahc_free_scb(ahc, scb);
ahc_unlock(ahc, &s);
xpt_done(ccb); xpt_done(ccb);
return; return;
} }
@ -1035,9 +1018,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
CAM_REQ_TOO_BIG); CAM_REQ_TOO_BIG);
bus_dmamap_unload(ahc->buffer_dmat, bus_dmamap_unload(ahc->buffer_dmat,
scb->dmamap); scb->dmamap);
ahc_lock(ahc, &s);
ahc_free_scb(ahc, scb); ahc_free_scb(ahc, scb);
ahc_unlock(ahc, &s);
xpt_done(ccb); xpt_done(ccb);
return; return;
} }
@ -1060,8 +1041,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
scb->sg_count = nsegments; scb->sg_count = nsegments;
ahc_lock(ahc, &s);
/* /*
* Last time we need to check if this SCB needs to * Last time we need to check if this SCB needs to
* be aborted. * be aborted.
@ -1070,7 +1049,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
if (nsegments != 0) if (nsegments != 0)
bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap);
ahc_free_scb(ahc, scb); ahc_free_scb(ahc, scb);
ahc_unlock(ahc, &s);
xpt_done(ccb); xpt_done(ccb);
return; return;
} }
@ -1121,7 +1099,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe); TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe);
scb->flags |= SCB_UNTAGGEDQ; scb->flags |= SCB_UNTAGGEDQ;
if (TAILQ_FIRST(untagged_q) != scb) { if (TAILQ_FIRST(untagged_q) != scb) {
ahc_unlock(ahc, &s);
return; return;
} }
} }
@ -1143,8 +1120,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
} else { } else {
ahc_queue_scb(ahc, scb); ahc_queue_scb(ahc, scb);
} }
ahc_unlock(ahc, &s);
} }
static void static void
@ -1174,13 +1149,9 @@ ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim,
if (hscb->cdb_len > sizeof(hscb->cdb32) if (hscb->cdb_len > sizeof(hscb->cdb32)
|| (ccb_h->flags & CAM_CDB_PHYS) != 0) { || (ccb_h->flags & CAM_CDB_PHYS) != 0) {
u_long s;
aic_set_transaction_status(scb, aic_set_transaction_status(scb,
CAM_REQ_INVALID); CAM_REQ_INVALID);
ahc_lock(ahc, &s);
ahc_free_scb(ahc, scb); ahc_free_scb(ahc, scb);
ahc_unlock(ahc, &s);
xpt_done((union ccb *)csio); xpt_done((union ccb *)csio);
return; return;
} }
@ -1462,24 +1433,14 @@ int
ahc_detach(device_t dev) ahc_detach(device_t dev)
{ {
struct ahc_softc *ahc; struct ahc_softc *ahc;
u_long l;
u_long s;
ahc_list_lock(&l);
device_printf(dev, "detaching device\n"); device_printf(dev, "detaching device\n");
ahc = device_get_softc(dev); ahc = device_get_softc(dev);
ahc = ahc_find_softc(ahc); ahc_lock(ahc);
if (ahc == NULL) {
device_printf(dev, "aic7xxx already detached\n");
ahc_list_unlock(&l);
return (ENOENT);
}
TAILQ_REMOVE(&ahc_tailq, ahc, links); TAILQ_REMOVE(&ahc_tailq, ahc, links);
ahc_list_unlock(&l);
ahc_lock(ahc, &s);
ahc_intr_enable(ahc, FALSE); ahc_intr_enable(ahc, FALSE);
bus_teardown_intr(dev, ahc->platform_data->irq, ahc->platform_data->ih); bus_teardown_intr(dev, ahc->platform_data->irq, ahc->platform_data->ih);
ahc_unlock(ahc, &s); ahc_unlock(ahc);
ahc_free(ahc); ahc_free(ahc);
return (0); return (0);
} }

View File

@ -146,6 +146,7 @@ struct ahc_platform_data {
void *ih; void *ih;
eventhandler_tag eh; eventhandler_tag eh;
struct proc *recovery_thread; struct proc *recovery_thread;
struct mtx mtx;
}; };
struct scb_platform_data { struct scb_platform_data {
@ -187,66 +188,25 @@ ahc_flush_device_writes(struct ahc_softc *ahc)
/**************************** Locking Primitives ******************************/ /**************************** Locking Primitives ******************************/
/* Lock protecting internal data structures */ /* Lock protecting internal data structures */
static __inline void ahc_lockinit(struct ahc_softc *); static __inline void ahc_lockinit(struct ahc_softc *);
static __inline void ahc_lock(struct ahc_softc *, unsigned long *flags); static __inline void ahc_lock(struct ahc_softc *);
static __inline void ahc_unlock(struct ahc_softc *, unsigned long *flags); static __inline void ahc_unlock(struct ahc_softc *);
/* Lock held during command compeletion to the upper layer */
static __inline void ahc_done_lockinit(struct ahc_softc *);
static __inline void ahc_done_lock(struct ahc_softc *, unsigned long *flags);
static __inline void ahc_done_unlock(struct ahc_softc *, unsigned long *flags);
/* Lock held during ahc_list manipulation and ahc softc frees */
static __inline void ahc_list_lockinit(void);
static __inline void ahc_list_lock(unsigned long *flags);
static __inline void ahc_list_unlock(unsigned long *flags);
static __inline void static __inline void
ahc_lockinit(struct ahc_softc *ahc) ahc_lockinit(struct ahc_softc *ahc)
{ {
mtx_init(&ahc->platform_data->mtx, "ahc_lock", NULL, MTX_DEF);
} }
static __inline void static __inline void
ahc_lock(struct ahc_softc *ahc, unsigned long *flags) ahc_lock(struct ahc_softc *ahc)
{ {
*flags = splcam(); mtx_lock(&ahc->platform_data->mtx);
} }
static __inline void static __inline void
ahc_unlock(struct ahc_softc *ahc, unsigned long *flags) ahc_unlock(struct ahc_softc *ahc)
{
splx(*flags);
}
/* Lock held during command compeletion to the upper layer */
static __inline void
ahc_done_lockinit(struct ahc_softc *ahc)
{
}
static __inline void
ahc_done_lock(struct ahc_softc *ahc, unsigned long *flags)
{
}
static __inline void
ahc_done_unlock(struct ahc_softc *ahc, unsigned long *flags)
{
}
/* Lock held during ahc_list manipulation and ahc softc frees */
static __inline void
ahc_list_lockinit(void)
{
}
static __inline void
ahc_list_lock(unsigned long *flags)
{
}
static __inline void
ahc_list_unlock(unsigned long *flags)
{ {
mtx_unlock(&ahc->platform_data->mtx);
} }
/************************* Initialization/Teardown ****************************/ /************************* Initialization/Teardown ****************************/

View File

@ -785,7 +785,6 @@ ahc_find_pci_device(aic_dev_softc_t pci)
int int
ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
{ {
u_long l;
u_int command; u_int command;
u_int our_id; u_int our_id;
u_int sxfrctl1; u_int sxfrctl1;
@ -1045,12 +1044,12 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
if (error != 0) if (error != 0)
return (error); return (error);
ahc_list_lock(&l); ahc_lock(ahc);
/* /*
* Link this softc in with all other ahc instances. * Link this softc in with all other ahc instances.
*/ */
ahc_softc_insert(ahc); ahc_softc_insert(ahc);
ahc_list_unlock(&l); ahc_unlock(ahc);
return (0); return (0);
} }

View File

@ -57,8 +57,7 @@ aic_set_recoveryscb(struct aic_softc *aic, struct scb *scb)
union ccb *ccb; union ccb *ccb;
ccb = list_scb->io_ctx; ccb = list_scb->io_ctx;
untimeout(aic_platform_timeout, list_scb, callout_stop(&scb->io_timer);
ccb->ccb_h.timeout_ch);
} }
} }
} }
@ -67,12 +66,11 @@ void
aic_platform_timeout(void *arg) aic_platform_timeout(void *arg)
{ {
struct scb *scb; struct scb *scb;
u_long s;
scb = (struct scb *)arg; scb = (struct scb *)arg;
aic_lock(scb->aic_softc, &s); aic_lock(scb->aic_softc);
aic_timeout(scb); aic_timeout(scb);
aic_unlock(scb->aic_softc, &s); aic_unlock(scb->aic_softc);
} }
int int
@ -93,11 +91,8 @@ aic_spawn_recovery_thread(struct aic_softc *aic)
void void
aic_terminate_recovery_thread(struct aic_softc *aic) aic_terminate_recovery_thread(struct aic_softc *aic)
{ {
u_long s;
aic_lock(aic, &s);
if (aic->platform_data->recovery_thread == NULL) { if (aic->platform_data->recovery_thread == NULL) {
aic_unlock(aic, &s);
return; return;
} }
aic->flags |= AIC_SHUTDOWN_RECOVERY; aic->flags |= AIC_SHUTDOWN_RECOVERY;
@ -106,40 +101,32 @@ aic_terminate_recovery_thread(struct aic_softc *aic)
* Sleep on a slightly different location * Sleep on a slightly different location
* for this interlock just for added safety. * for this interlock just for added safety.
*/ */
tsleep(aic->platform_data, PUSER, "thtrm", 0); msleep(aic->platform_data, &aic->platform_data->mtx, PUSER, "thtrm", 0);
aic_unlock(aic, &s);
} }
static void static void
aic_recovery_thread(void *arg) aic_recovery_thread(void *arg)
{ {
struct aic_softc *aic; struct aic_softc *aic;
u_long s;
#if __FreeBSD_version >= 500000
mtx_lock(&Giant);
#endif
aic = (struct aic_softc *)arg; aic = (struct aic_softc *)arg;
aic_lock(aic, &s); aic_lock(aic);
for (;;) { for (;;) {
if (LIST_EMPTY(&aic->timedout_scbs) != 0 if (LIST_EMPTY(&aic->timedout_scbs) != 0
&& (aic->flags & AIC_SHUTDOWN_RECOVERY) == 0) && (aic->flags & AIC_SHUTDOWN_RECOVERY) == 0)
tsleep(aic, PUSER, "idle", 0); msleep(aic, &aic->platform_data->mtx, PUSER, "idle", 0);
if ((aic->flags & AIC_SHUTDOWN_RECOVERY) != 0) if ((aic->flags & AIC_SHUTDOWN_RECOVERY) != 0)
break; break;
aic_unlock(aic, &s); aic_unlock(aic);
aic_recover_commands(aic); aic_recover_commands(aic);
aic_lock(aic, &s); aic_lock(aic);
} }
aic->platform_data->recovery_thread = NULL; aic->platform_data->recovery_thread = NULL;
wakeup(aic->platform_data); wakeup(aic->platform_data);
aic_unlock(aic, &s); aic_unlock(aic);
#if __FreeBSD_version >= 500000
mtx_unlock(&Giant);
#endif
kthread_exit(0); kthread_exit(0);
} }

View File

@ -143,7 +143,7 @@ aic_wakeup_recovery_thread(struct aic_softc *aic)
bus_dma_tag_create(parent_tag, alignment, boundary, \ bus_dma_tag_create(parent_tag, alignment, boundary, \
lowaddr, highaddr, filter, filterarg, \ lowaddr, highaddr, filter, filterarg, \
maxsize, nsegments, maxsegsz, flags, \ maxsize, nsegments, maxsegsz, flags, \
busdma_lock_mutex, &Giant, \ busdma_lock_mutex, &aic->platform_data->mtx, \
dma_tagp) dma_tagp)
#else #else
#define aic_dma_tag_create(aic, parent_tag, alignment, boundary, \ #define aic_dma_tag_create(aic, parent_tag, alignment, boundary, \
@ -187,7 +187,7 @@ aic_wakeup_recovery_thread(struct aic_softc *aic)
/***************************** Timer Facilities *******************************/ /***************************** Timer Facilities *******************************/
#if __FreeBSD_version >= 500000 #if __FreeBSD_version >= 500000
#define aic_timer_init(timer) callout_init(timer, /*mpsafe*/0) #define aic_timer_init(timer) callout_init(timer, /*mpsafe*/1)
#else #else
#define aic_timer_init callout_init #define aic_timer_init callout_init
#endif #endif
@ -223,10 +223,7 @@ aic_scb_timer_reset(struct scb *scb, u_int msec)
time = msec; time = msec;
time *= hz; time *= hz;
time /= 1000; time /= 1000;
untimeout(aic_platform_timeout, (caddr_t)scb, callout_reset(&scb->io_timer, time, aic_platform_timeout, scb);
scb->io_ctx->ccb_h.timeout_ch);
scb->io_ctx->ccb_h.timeout_ch =
timeout(aic_platform_timeout, scb, time);
} }
static __inline void static __inline void
@ -235,13 +232,7 @@ aic_scb_timer_start(struct scb *scb)
if (AIC_SCB_DATA(scb->aic_softc)->recovery_scbs == 0 if (AIC_SCB_DATA(scb->aic_softc)->recovery_scbs == 0
&& scb->io_ctx->ccb_h.timeout != CAM_TIME_INFINITY) { && scb->io_ctx->ccb_h.timeout != CAM_TIME_INFINITY) {
uint64_t time; aic_scb_timer_reset(scb, scb->io_ctx->ccb_h.timeout);
time = scb->io_ctx->ccb_h.timeout;
time *= hz;
time /= 1000;
scb->io_ctx->ccb_h.timeout_ch =
timeout(aic_platform_timeout, scb, time);
} }
} }