Basic MPSAFE locking for the AHC and AHD drivers.
This commit is contained in:
parent
5e201c93e8
commit
46e32eee32
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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 ***************************************/
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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 ****************************/
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user