summaryrefslogtreecommitdiffstats
path: root/sys/dev/aic7xxx
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>2000-10-06 04:01:06 +0000
committergibbs <gibbs@FreeBSD.org>2000-10-06 04:01:06 +0000
commit1cc3d5d7b74546d67cdf228f04b3fc2d5dc6dfb4 (patch)
tree17fcaf8a3e1fa4a919079d07440bdc33add5f8b8 /sys/dev/aic7xxx
parentfd275a78bd168fffc26552c4b2debf6f105a43ed (diff)
downloadFreeBSD-src-1cc3d5d7b74546d67cdf228f04b3fc2d5dc6dfb4.zip
FreeBSD-src-1cc3d5d7b74546d67cdf228f04b3fc2d5dc6dfb4.tar.gz
Bring in a slew of fixes that were supposed to be in the last commit.
In ahc_search_qinfifo, the SEARCH_REMOVE case must also handle an SCB that has been removed from the QINFIFO but not yet been fully dmaed to the card. Correct locking for ahc_get_scb() calls. Set SCB syncrate settings in ahc_execute_scb() to avoid a race condition that could allow a newly queued SCB to be missed by ahc_update_pending_syncrates(). When notifying the system of transfer negotiation updates, only set the valid bits for tagged queuing and disconnection if the path is fully qualified. Sync/Wide settins apply to all luns of a target, but tagged queuing and disconnection may change on a per-lun basis. Add missing ahc_unlock() calls in ahc_timeout() for the target mode case.
Diffstat (limited to 'sys/dev/aic7xxx')
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c4
-rw-r--r--sys/dev/aic7xxx/aic7xxx_freebsd.c78
-rw-r--r--sys/dev/aic7xxx/aic7xxx_osm.c78
3 files changed, 90 insertions, 70 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index cc4f9d7..0cf506d 100644
--- a/sys/dev/aic7xxx/aic7xxx.c
+++ b/sys/dev/aic7xxx/aic7xxx.c
@@ -4279,6 +4279,8 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
printf("Inactive SCB in qinfifo\n");
ahc_done(ahc, scb);
+ /* FALLTHROUGH */
+ case SEARCH_REMOVE:
/*
* The sequencer increments its position in
* the qinfifo as soon as it determines that
@@ -4299,8 +4301,6 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
ahc_qinfifo_requeue(ahc, prev_scb, scb);
prev_scb = scb;
break;
- case SEARCH_REMOVE:
- break;
}
} else {
ahc_qinfifo_requeue(ahc, prev_scb, scb);
diff --git a/sys/dev/aic7xxx/aic7xxx_freebsd.c b/sys/dev/aic7xxx/aic7xxx_freebsd.c
index 0cafccc..70fd7d8 100644
--- a/sys/dev/aic7xxx/aic7xxx_freebsd.c
+++ b/sys/dev/aic7xxx/aic7xxx_freebsd.c
@@ -424,18 +424,15 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
case XPT_SCSI_IO: /* Execute the requested I/O operation */
case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
{
- struct scb *scb;
- struct hardware_scb *hscb;
- struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
- uint16_t mask;
+ struct scb *scb;
+ struct hardware_scb *hscb;
/*
* get an scb to use.
*/
+ ahc_lock(ahc, &s);
if ((scb = ahc_get_scb(ahc)) == NULL) {
- ahc_lock(ahc, &s);
ahc->flags |= AHC_RESOURCE_SHORTAGE;
ahc_unlock(ahc, &s);
xpt_freeze_simq(sim, /*count*/1);
@@ -443,6 +440,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
xpt_done(ccb);
return;
}
+ ahc_unlock(ahc, &s);
hscb = scb->hscb;
@@ -461,25 +459,6 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
hscb->control = 0;
hscb->scsiid = BUILD_SCSIID(ahc, sim, target_id, our_id);
hscb->lun = ccb->ccb_h.target_lun;
- mask = SCB_GET_TARGET_MASK(ahc, scb);
- tinfo = ahc_fetch_transinfo(ahc, SIM_CHANNEL(ahc, sim), our_id,
- target_id, &tstate);
-
- hscb->scsirate = tinfo->scsirate;
- hscb->scsioffset = tinfo->current.offset;
- if ((tstate->ultraenb & mask) != 0)
- hscb->control |= ULTRAENB;
-
- if ((tstate->discenable & mask) != 0
- && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0)
- hscb->control |= DISCENB;
-
- if ((ccb->ccb_h.flags & CAM_NEGOTIATE) != 0
- && (tinfo->current.width != 0 || tinfo->current.period != 0)) {
- scb->flags |= SCB_NEGOTIATE;
- hscb->control |= MK_MESSAGE;
- }
-
if (ccb->ccb_h.func_code == XPT_RESET_DEV) {
hscb->cdb_len = 0;
scb->flags |= SCB_DEVICE_RESET;
@@ -954,13 +933,18 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
cts->protocol = PROTO_SCSI;
cts->transport = XPORT_SPI;
- scsi->valid = CTS_SCSI_VALID_TQ;
spi->valid = CTS_SPI_VALID_SYNC_RATE
| CTS_SPI_VALID_SYNC_OFFSET
| CTS_SPI_VALID_BUS_WIDTH
- | CTS_SPI_VALID_DISC
| CTS_SPI_VALID_PPR_OPTIONS;
+ if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
+ scsi->valid = CTS_SCSI_VALID_TQ;
+ spi->valid |= CTS_SPI_VALID_DISC;
+ } else {
+ scsi->valid = 0;
+ }
+
cts->ccb_h.status = CAM_REQ_CMP;
#else
struct ahc_devinfo devinfo;
@@ -1006,9 +990,10 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
cts->valid = CCB_TRANS_SYNC_RATE_VALID
| CCB_TRANS_SYNC_OFFSET_VALID
- | CCB_TRANS_BUS_WIDTH_VALID
- | CCB_TRANS_DISC_VALID
- | CCB_TRANS_TQ_VALID;
+ | CCB_TRANS_BUS_WIDTH_VALID;
+
+ if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD)
+ cts->valid |= CCB_TRANS_DISC_VALID|CCB_TRANS_TQ_VALID;
cts->ccb_h.status = CAM_REQ_CMP;
#endif
@@ -1057,10 +1042,13 @@ static void
ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
int error)
{
- struct scb *scb;
- union ccb *ccb;
- struct ahc_softc *ahc;
- long s;
+ struct scb *scb;
+ union ccb *ccb;
+ struct ahc_softc *ahc;
+ struct ahc_initiator_tinfo *tinfo;
+ struct tmode_tstate *tstate;
+ u_int mask;
+ long s;
scb = (struct scb *)arg;
ccb = scb->io_ctx;
@@ -1183,6 +1171,26 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
return;
}
+ tinfo = ahc_fetch_transinfo(ahc, SCSIID_CHANNEL(ahc, scb->hscb->scsiid),
+ SCSIID_OUR_ID(scb->hscb->scsiid),
+ ccb->ccb_h.target_id, &tstate);
+
+ mask = SCB_GET_TARGET_MASK(ahc, scb);
+ scb->hscb->scsirate = tinfo->scsirate;
+ scb->hscb->scsioffset = tinfo->current.offset;
+ if ((tstate->ultraenb & mask) != 0)
+ scb->hscb->control |= ULTRAENB;
+
+ if ((tstate->discenable & mask) != 0
+ && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0)
+ scb->hscb->control |= DISCENB;
+
+ if ((ccb->ccb_h.flags & CAM_NEGOTIATE) != 0
+ && (tinfo->current.width != 0 || tinfo->current.period != 0)) {
+ scb->flags |= SCB_NEGOTIATE;
+ scb->hscb->control |= MK_MESSAGE;
+ }
+
LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
ccb->ccb_h.status |= CAM_SIM_QUEUED;
@@ -1526,6 +1534,7 @@ bus_reset:
/* Will clear us from the bus */
restart_sequencer(ahc);
+ ahc_unlock(ahc, &s);
return;
}
@@ -1552,6 +1561,7 @@ bus_reset:
printf("%s: Hung target selection\n",
ahc_name(ahc));
restart_sequencer(ahc);
+ ahc_unlock(ahc, &s);
return;
}
diff --git a/sys/dev/aic7xxx/aic7xxx_osm.c b/sys/dev/aic7xxx/aic7xxx_osm.c
index 0cafccc..70fd7d8 100644
--- a/sys/dev/aic7xxx/aic7xxx_osm.c
+++ b/sys/dev/aic7xxx/aic7xxx_osm.c
@@ -424,18 +424,15 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
case XPT_SCSI_IO: /* Execute the requested I/O operation */
case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
{
- struct scb *scb;
- struct hardware_scb *hscb;
- struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
- uint16_t mask;
+ struct scb *scb;
+ struct hardware_scb *hscb;
/*
* get an scb to use.
*/
+ ahc_lock(ahc, &s);
if ((scb = ahc_get_scb(ahc)) == NULL) {
- ahc_lock(ahc, &s);
ahc->flags |= AHC_RESOURCE_SHORTAGE;
ahc_unlock(ahc, &s);
xpt_freeze_simq(sim, /*count*/1);
@@ -443,6 +440,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
xpt_done(ccb);
return;
}
+ ahc_unlock(ahc, &s);
hscb = scb->hscb;
@@ -461,25 +459,6 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
hscb->control = 0;
hscb->scsiid = BUILD_SCSIID(ahc, sim, target_id, our_id);
hscb->lun = ccb->ccb_h.target_lun;
- mask = SCB_GET_TARGET_MASK(ahc, scb);
- tinfo = ahc_fetch_transinfo(ahc, SIM_CHANNEL(ahc, sim), our_id,
- target_id, &tstate);
-
- hscb->scsirate = tinfo->scsirate;
- hscb->scsioffset = tinfo->current.offset;
- if ((tstate->ultraenb & mask) != 0)
- hscb->control |= ULTRAENB;
-
- if ((tstate->discenable & mask) != 0
- && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0)
- hscb->control |= DISCENB;
-
- if ((ccb->ccb_h.flags & CAM_NEGOTIATE) != 0
- && (tinfo->current.width != 0 || tinfo->current.period != 0)) {
- scb->flags |= SCB_NEGOTIATE;
- hscb->control |= MK_MESSAGE;
- }
-
if (ccb->ccb_h.func_code == XPT_RESET_DEV) {
hscb->cdb_len = 0;
scb->flags |= SCB_DEVICE_RESET;
@@ -954,13 +933,18 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
cts->protocol = PROTO_SCSI;
cts->transport = XPORT_SPI;
- scsi->valid = CTS_SCSI_VALID_TQ;
spi->valid = CTS_SPI_VALID_SYNC_RATE
| CTS_SPI_VALID_SYNC_OFFSET
| CTS_SPI_VALID_BUS_WIDTH
- | CTS_SPI_VALID_DISC
| CTS_SPI_VALID_PPR_OPTIONS;
+ if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
+ scsi->valid = CTS_SCSI_VALID_TQ;
+ spi->valid |= CTS_SPI_VALID_DISC;
+ } else {
+ scsi->valid = 0;
+ }
+
cts->ccb_h.status = CAM_REQ_CMP;
#else
struct ahc_devinfo devinfo;
@@ -1006,9 +990,10 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
cts->valid = CCB_TRANS_SYNC_RATE_VALID
| CCB_TRANS_SYNC_OFFSET_VALID
- | CCB_TRANS_BUS_WIDTH_VALID
- | CCB_TRANS_DISC_VALID
- | CCB_TRANS_TQ_VALID;
+ | CCB_TRANS_BUS_WIDTH_VALID;
+
+ if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD)
+ cts->valid |= CCB_TRANS_DISC_VALID|CCB_TRANS_TQ_VALID;
cts->ccb_h.status = CAM_REQ_CMP;
#endif
@@ -1057,10 +1042,13 @@ static void
ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
int error)
{
- struct scb *scb;
- union ccb *ccb;
- struct ahc_softc *ahc;
- long s;
+ struct scb *scb;
+ union ccb *ccb;
+ struct ahc_softc *ahc;
+ struct ahc_initiator_tinfo *tinfo;
+ struct tmode_tstate *tstate;
+ u_int mask;
+ long s;
scb = (struct scb *)arg;
ccb = scb->io_ctx;
@@ -1183,6 +1171,26 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
return;
}
+ tinfo = ahc_fetch_transinfo(ahc, SCSIID_CHANNEL(ahc, scb->hscb->scsiid),
+ SCSIID_OUR_ID(scb->hscb->scsiid),
+ ccb->ccb_h.target_id, &tstate);
+
+ mask = SCB_GET_TARGET_MASK(ahc, scb);
+ scb->hscb->scsirate = tinfo->scsirate;
+ scb->hscb->scsioffset = tinfo->current.offset;
+ if ((tstate->ultraenb & mask) != 0)
+ scb->hscb->control |= ULTRAENB;
+
+ if ((tstate->discenable & mask) != 0
+ && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0)
+ scb->hscb->control |= DISCENB;
+
+ if ((ccb->ccb_h.flags & CAM_NEGOTIATE) != 0
+ && (tinfo->current.width != 0 || tinfo->current.period != 0)) {
+ scb->flags |= SCB_NEGOTIATE;
+ scb->hscb->control |= MK_MESSAGE;
+ }
+
LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
ccb->ccb_h.status |= CAM_SIM_QUEUED;
@@ -1526,6 +1534,7 @@ bus_reset:
/* Will clear us from the bus */
restart_sequencer(ahc);
+ ahc_unlock(ahc, &s);
return;
}
@@ -1552,6 +1561,7 @@ bus_reset:
printf("%s: Hung target selection\n",
ahc_name(ahc));
restart_sequencer(ahc);
+ ahc_unlock(ahc, &s);
return;
}
OpenPOWER on IntegriCloud