Skip to contentSkip to conversation

Sync up drivers/scsi/aic7xxx

PATCH In review Luben Tuikov 3 participants 4 messages Sep 28, 2004 SCSI

lore
Share & tools
lore
#0 lore raw

PATCH 1/28 Sync up drivers/scsi/aic7xxx

Sync up drivers/scsi/aic7xxx/. (2231-2232)

==== //depot/aic7xxx/aic7xxx/aic79xx.h#95 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic79xx.h ====

home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic79xx.h renamed from tmp/tmp.26033.0 +1 -1
@@ -37,7 +37,7 @@
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#95 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#96 $
 *
 * $FreeBSD$
 */
@@ -375,7 +375,8 @@
	AHD_RESET_POLL_ACTIVE = 0x200000,
	AHD_UPDATE_PEND_CMDS  = 0x400000,
	AHD_RUNNING_QOUTFIFO  = 0x800000,

- AHD_HAD_FIRST_SEL = 0x1000000
+ AHD_HAD_FIRST_SEL = 0x1000000,
+ AHD_SHUTDOWN_RECOVERY = 0x2000000 /* Terminate recovery thread. */
} ahd_flag;

/************************* Hardware SCB Definition ***************************/ @@ -591,12 +592,16 @@

	SCB_PKT_SENSE		= 0x02000,
	SCB_CMDPHASE_ABORT	= 0x04000,
	SCB_ON_COL_LIST		= 0x08000,

- SCB_SILENT = 0x10000 /*
+ SCB_SILENT = 0x10000,/*
* Be quiet about transmission type
* errors. They are expected and we
* don't want to upset the user. This
* flag is typically used during DV. */
+ SCB_TIMEDOUT = 0x20000/*

+					  * SCB has timed out and is on the
+					  * timedout list.
+					  */

} scb_flag;

struct scb {
@@ -613,6 +618,7 @@

	} links2;
#define pending_links links2.le
#define collision_links links2.le
+	LIST_ENTRY(scb)		  timedout_links;
	struct scb		 *col_scb;
	ahd_io_ctx_t		  io_ctx;
	struct ahd_softc	 *ahd_softc;
@@ -1069,6 +1075,11 @@
	LIST_HEAD(, scb)	  pending_scbs;

	/*

+ * SCBs whose timeout routine has been called.
+ */
+ LIST_HEAD(, scb) timedout_scbs;
+
+ /*

	 * Current register window mode information.
	 */
	ahd_mode		  dst_mode;
@@ -1433,6 +1444,8 @@
					       struct scb *scb);
void			ahd_calc_residual(struct ahd_softc *ahd,
					  struct scb *scb);

+void ahd_timeout(struct scb *scb);
+void ahd_recover_commands(struct ahd_softc *ahd);
/*************************** Utility Functions ********************************/ struct ahd_phase_table_entry*

			ahd_lookup_phase_entry(int phase);

==== //depot/aic7xxx/aic7xxx/aic79xx.c#202 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic79xx_core.c ====

home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic79xx_core.c renamed from tmp/tmp.26033.1 +1 -1
@@ -37,7 +37,7 @@
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#202 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#203 $
 *
 * $FreeBSD$
 */
@@ -224,6 +224,9 @@

static void ahd_download_instr(struct ahd_softc *ahd,

					   u_int instrptr, uint8_t *dconsts);

static int ahd_probe_stack_size(struct ahd_softc *ahd);
+static void ahd_other_scb_timeout(struct ahd_softc *ahd,
+ struct scb *scb,
+ struct scb *other_scb);
static int ahd_scb_active_in_fifo(struct ahd_softc *ahd,

					       struct scb *scb);
static void		ahd_run_data_fifo(struct ahd_softc *ahd,
@@ -5266,6 +5269,7 @@
{
	int i;
+	ahd_terminate_recovery_thread(ahd);
	switch (ahd->init_level) {
	default:
	case 5:
@@ -7810,7 +7814,7 @@
	 */
	ahd_clear_msg_state(ahd);
	ahd_outb(ahd, SIMODE1,

- ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE));
+ ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));

	if (initiate_reset)
		ahd_reset_current_bus(ahd);
@@ -9072,6 +9076,270 @@
	ahd_restore_modes(ahd, saved_modes);
}

+
+/*************************** Timeout Handling *********************************/
+void
+ahd_timeout(struct scb *scb)
+{
+ struct ahd_softc *ahd;
+ u_long s;
+
+ ahd = scb->ahd_softc;
+ ahd_lock(ahd, &s);
+ if ((scb->flags & SCB_ACTIVE) != 0) {
+ if ((scb->flags & SCB_TIMEDOUT) != 0) {
+ LIST_INSERT_HEAD(&ahd->timedout_scbs, scb,
+ timedout_links);
+ scb->flags |= SCB_TIMEDOUT;
+ }
+ ahd_wakeup_recovery_thread(ahd);
+ }
+ ahd_unlock(ahd, &s);
+}
+
+/*
+ * ahd_recover_commands determines if any of the commands that have currently
+ * timedout are the root cause for this timeout. Innocent commands are given
+ * a new timeout while we wait for the command executing on the bus to timeout.
+ * This routine is invoked from a thread context so we are allowed to sleep.
+ * Our lock is not held on entry.
+ */
+void
+ahd_recover_commands(struct ahd_softc *ahd)
+{
+ struct scb *scb;
+ struct scb *active_scb;
+ long s;
+ int found;
+ int was_paused;
+ u_int active_scbptr;
+ u_int last_phase;
+
+ ahd_lock(ahd, &s);
+
+ /*
+ * Pause the controller and manually flush any
+ * commands that have just completed but that our
+ * interrupt handler has yet to see.
+ */
+ was_paused = ahd_is_paused(ahd);
+ ahd_pause_and_flushwork(ahd);
+
+ if (LIST_EMPTY(&ahd->timedout_scbs) != 0) {
+ /*
+ * The timedout commands have already
+ * completed. This typically means
+ * that either the timeout value was on
+ * the hairy edge of what the device
+ * requires or - more likely - interrupts
+ * are not happening.
+ */
+ printf("%s: Timedout SCBs already complete. "
+ "Interrupts may not be functioning.\n", ahd_name(ahd));
+ ahd_unpause(ahd);
+ ahd_unlock(ahd, &s);
+ return;
+ }
+
+ printf("%s: Recovery Initiated - Card was %spaused\n", ahd_name(ahd),
+ was_paused ? "" : "not ");
+ ahd_dump_card_state(ahd);
+
+ /*
+ * Determine identity of SCB acting on the bus.
+ * This test only catches non-packetized transactions.
+ * Due to the fleeting nature of packetized operations,
+ * we can't easily determine that a packetized operation
+ * is on the bus.
+ */
+ ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
+ last_phase = ahd_inb(ahd, LASTPHASE);
+ active_scbptr = ahd_get_scbptr(ahd);
+ active_scb = NULL;
+ if (last_phase != P_BUSFREE
+ || (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)
+ active_scb = ahd_lookup_scb(ahd, active_scbptr);
+
+ while ((scb = LIST_FIRST(&ahd->timedout_scbs)) != NULL) {
+ int target;
+ int lun;
+ char channel;
+
+ target = SCB_GET_TARGET(ahd, scb);
+ channel = SCB_GET_CHANNEL(ahd, scb);
+ lun = SCB_GET_LUN(scb);
+
+ ahd_print_path(ahd, scb);
+ printf("SCB 0x%x - timed out\n", scb->hscb->tag);
+
+ if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) {
+ /*
+ * Been down this road before.
+ * Do a full bus reset.
+ */
+ ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
+ found = ahd_reset_channel(ahd, channel,
+ /*Initiate Reset*/TRUE);
+ printf("%s: Issued Channel %c Bus Reset. "
+ "%d SCBs aborted\n", ahd_name(ahd), channel,
+ found);
+ continue;
+ }
+
+ /*
+ * Remove the command from the timedout list in
+ * preparation for requeing it.
+ */
+ LIST_REMOVE(scb, timedout_links);
+ scb->flags &= ~SCB_TIMEDOUT;
+
+ if (active_scb != NULL) {
+
+ if (active_scb != scb) {
+ /*
+ * If the active SCB is not us, assume that
+ * the active SCB has a longer timeout than
+ * the timedout SCB, and wait for the active
+ * SCB to timeout.
+ */
+ ahd_other_scb_timeout(ahd, scb, active_scb);
+ continue;
+ }
+
+ /*
+ * We're active on the bus, so assert ATN
+ * and hope that the target responds.
+ */
+ ahd_set_recoveryscb(ahd, active_scb);
+ active_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET;
+ ahd_outb(ahd, MSG_OUT, HOST_MSG);
+ ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
+ ahd_print_path(ahd, active_scb);
+ printf("BDR message in message buffer\n");
+ ahd_scb_timer_reset(scb, 2 * 1000000);
+ break;
+ } else if (ahd_search_qinfifo(ahd, target, channel, lun,
+ scb->hscb->tag, ROLE_INITIATOR,
+ /*status*/0, SEARCH_COUNT) > 0) {
+
+ /*
+ * We haven't even gone out on the bus
+ * yet, so the timeout must be due to
+ * some other command. Reset the timer
+ * and go on.
+ */
+ ahd_other_scb_timeout(ahd, scb, scb);
+ } else {
+ /*
+ * This SCB is for a disconnected transaction
+ * and we haven't found a better candidate on
+ * the bus to explain this timeout.
+ */
+ ahd_set_recoveryscb(ahd, scb);
+
+ /*
+ * Actually re-queue this SCB in an attempt
+ * to select the device before it reconnects.
+ * In either case (selection or reselection),
+ * we will now issue a target reset to the
+ * timed-out device.
+ *
+ * Set the MK_MESSAGE control bit indicating
+ * that we desire to send a message. We
+ * also set the disconnected flag since
+ * in the paging case there is no guarantee
+ * that our SCB control byte matches the
+ * version on the card. We don't want the
+ * sequencer to abort the command thinking
+ * an unsolicited reselection occurred.
+ */
+ scb->flags |= SCB_DEVICE_RESET;
+ scb->hscb->cdb_len = 0;
+ scb->hscb->task_attribute = 0;
+ scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
+
+ ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
+ if ((scb->flags & SCB_PACKETIZED) != 0) {
+ /*
+ * Mark the SCB has having an outstanding
+ * task management function. Should the command
+ * complete normally before the task management
+ * function can be sent, the host will be
+ * notified to abort our requeued SCB.
+ */
+ ahd_outb(ahd, SCB_TASK_MANAGEMENT,
+ scb->hscb->task_management);
+ } else {
+ /*
+ * If non-packetized, set the MK_MESSAGE control
+ * bit indicating that we desire to send a
+ * message. We also set the disconnected flag
+ * since there is no guarantee that our SCB
+ * control byte matches the version on the
+ * card. We don't want the sequencer to abort
+ * the command thinking an unsolicited
+ * reselection occurred.
+ */
+ scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
+
+ /*
+ * The sequencer will never re-reference the
+ * in-core SCB. To make sure we are notified
+ * during reslection, set the MK_MESSAGE flag in
+ * the card's copy of the SCB.
+ */
+ ahd_outb(ahd, SCB_CONTROL,
+ ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
+ }
+
+ /*
+ * Clear out any entries in the QINFIFO first
+ * so we are the next SCB for this target
+ * to run.
+ */
+ ahd_search_qinfifo(ahd, target, channel, lun,
+ SCB_LIST_NULL, ROLE_INITIATOR,
+ CAM_REQUEUE_REQ, SEARCH_COMPLETE);
+ ahd_qinfifo_requeue_tail(ahd, scb);
+ ahd_set_scbptr(ahd, active_scbptr);
+ ahd_print_path(ahd, scb);
+ printf("Queuing a BDR SCB\n");
+ ahd_scb_timer_reset(scb, 2 * 1000000);
+ break;
+ }
+ }
+
+ /*
+ * Any remaining SCBs were not the "culprit", so give
+ * them a new lease on life.
+ */
+ while ((scb = LIST_FIRST(&ahd->timedout_scbs)) != NULL) {
+
+ LIST_REMOVE(scb, timedout_links);
+ scb->flags &= ~SCB_TIMEDOUT;
+ ahd_scb_timer_reset(scb, ahd_get_timeout(scb));
+ }
+
+ ahd_unpause(ahd);
+ ahd_unlock(ahd, &s);
+}
+
+static void
+ahd_other_scb_timeout(struct ahd_softc *ahd, struct scb *scb,
+ struct scb *other_scb)
+{
+ u_int newtimeout;
+
+ ahd_print_path(ahd, scb);
+ printf("Other SCB Timeout%s",
+ (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0
+ ? " again\n" : "\n");
+ scb->flags |= SCB_OTHERTCL_TIMEOUT;
+ newtimeout = MAX(ahd_get_timeout(other_scb),
+ ahd_get_timeout(scb));
+ ahd_scb_timer_reset(scb, newtimeout);
+}
+
/**************************** Flexport Logic **********************************/
/*
* Read count 16bit words from 16bit word address start_addr from the
==== //depot/aic7xxx/aic7xxx/aic7xxx.h#79 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic7xxx.h ====

home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic7xxx.h renamed from tmp/tmp.26033.2 +1 -1
@@ -37,7 +37,7 @@
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#79 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#80 $
 *
 * $FreeBSD$
 */
@@ -366,7 +366,8 @@
	AHC_SCB_CONFIG_USED   = 0x4000000, /* No SEEPROM but SCB2 had info. */
	AHC_NO_BIOS_INIT      = 0x8000000, /* No BIOS left over settings. */
	AHC_DISABLE_PCI_PERR  = 0x10000000,

- AHC_HAS_TERM_LOGIC = 0x20000000
+ AHC_HAS_TERM_LOGIC = 0x20000000,
+ AHC_SHUTDOWN_RECOVERY = 0x40000000 /* Terminate recovery thread. */
} ahc_flag;

/************************* Hardware SCB Definition ***************************/ @@ -560,12 +561,16 @@

					  * to report the error.
					  */
	SCB_TARGET_SCB		= 0x2000,

- SCB_SILENT = 0x4000 /*
+ SCB_SILENT = 0x4000,/*
* Be quiet about transmission type
* errors. They are expected and we
* don't want to upset the user. This
* flag is typically used during DV. */
+ SCB_TIMEDOUT = 0x8000 /*

+					  * SCB has timed out and is on the
+					  * timedout list.
+					  */

} scb_flag;

struct scb {
@@ -575,6 +580,7 @@

		TAILQ_ENTRY(scb)  tqe;
	} links;
	LIST_ENTRY(scb)		  pending_links;
+	LIST_ENTRY(scb)		  timedout_links;
	ahc_io_ctx_t		  io_ctx;
	struct ahc_softc	 *ahc_softc;
	scb_flag		  flags;
@@ -929,6 +935,11 @@
	LIST_HEAD(, scb)	  pending_scbs;

	/*

+ * SCBs whose timeout routine has been called.
+ */
+ LIST_HEAD(, scb) timedout_scbs;
+
+ /*
* Counting lock for deferring the release of additional
* untagged transactions from the untagged_queues. When
* the lock is decremented to 0, all queues in the
@@ -1248,6 +1259,8 @@
void ahc_restart(struct ahc_softc *ahc);
void ahc_calc_residual(struct ahc_softc *ahc,

					  struct scb *scb);

+void ahc_timeout(struct scb *scb);
+void ahc_recover_commands(struct ahc_softc *ahc);
/*************************** Utility Functions ********************************/ struct ahc_phase_table_entry*

			ahc_lookup_phase_entry(int phase);

==== //depot/aic7xxx/aic7xxx/aic7xxx.c#134 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic7xxx_core.c ====

home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic7xxx_core.c renamed from tmp/tmp.26033.3 +1 -1
@@ -37,7 +37,7 @@
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
- * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#134 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#135 $
 *
 * $FreeBSD$
 */
@@ -3969,6 +3969,7 @@
{
	int i;
+	ahc_terminate_recovery_thread(ahc);
	switch (ahc->init_level) {
	default:
	case 5:

@@ -4046,6 +4047,9 @@

	ahc = (struct ahc_softc *)arg;

+ /* Kill off our recovery thread. */
+ ahc_terminate_recovery_thread(ahc);
+

	/* This will reset most registers to 0, but not all */
	ahc_reset(ahc, /*reinit*/FALSE);
	ahc_outb(ahc, SCSISEQ, 0);
@@ -4760,6 +4764,7 @@
ahc_init(struct ahc_softc *ahc)
{
	int	 max_targ;
+	int	 error;
	u_int	 i;
	u_int	 scsi_conf;
	u_int	 ultraenb;
@@ -4915,6 +4920,13 @@
		}
	}

+ /*
+ * Fire up a recovery thread for this controller.
+ */
+ error = ahc_spawn_recovery_thread(ahc);
+ if (error != 0)
+ return (error);
+

	if (ahc->scb_data->maxhscbs < AHC_SCB_MAX_ALLOC) {
		ahc->flags |= AHC_PAGESCBS;
	} else {
@@ -6827,6 +6839,315 @@
		ahc_unpause(ahc);
}

+/*************************** Timeout Handling *********************************/ +void
+ahc_timeout(struct scb *scb)
+{
+ struct ahc_softc *ahc;
+ u_long s;
+
+ ahc = scb->ahc_softc;
+ ahc_lock(ahc, &s);
+ if ((scb->flags & SCB_ACTIVE) != 0) {
+ if ((scb->flags & SCB_TIMEDOUT) != 0) {
+ LIST_INSERT_HEAD(&ahc->timedout_scbs, scb,
+ timedout_links);
+ scb->flags |= SCB_TIMEDOUT;
+ }
+ ahc_wakeup_recovery_thread(ahc);
+ }
+ ahc_unlock(ahc, &s);
+}
+
+/*
+ * ahc_recover_commands determines if any of the commands that have currently
+ * timedout are the root cause for this timeout. Innocent commands are given
+ * a new timeout while we wait for the command executing on the bus to timeout.
+ * This routine is invoked from a thread context so we are allowed to sleep.
+ * Our lock is not held on entry.
+ */
+void
+ahc_recover_commands(struct ahc_softc *ahc)
+{
+ struct scb *scb;
+ long s;
+ int found;
+ int restart_needed;
+ u_int last_phase;
+
+ ahc_lock(ahc, &s);
+
+ /*
+ * Pause the controller and manually flush any
+ * commands that have just completed but that our
+ * interrupt handler has yet to see.
+ */
+ ahc_pause_and_flushwork(ahc);
+
+ if (LIST_EMPTY(&ahc->timedout_scbs) != 0) {
+ /*
+ * The timedout commands have already
+ * completed. This typically means
+ * that either the timeout value was on
+ * the hairy edge of what the device
+ * requires or - more likely - interrupts
+ * are not happening.
+ */
+ printf("%s: Timedout SCBs already complete. "
+ "Interrupts may not be functioning.\n", ahc_name(ahc));
+ ahc_unpause(ahc);
+ ahc_unlock(ahc, &s);
+ return;
+ }
+
+ restart_needed = 0;
+ printf("%s: Recovery Initiated\n", ahc_name(ahc));
+ ahc_dump_card_state(ahc);
+
+ last_phase = ahc_inb(ahc, LASTPHASE);
+ while ((scb = LIST_FIRST(&ahc->timedout_scbs)) != NULL) {
+ u_int active_scb_index;
+ u_int saved_scbptr;
+ int target;
+ int lun;
+ int i;
+ char channel;
+
+ target = SCB_GET_TARGET(ahc, scb);
+ channel = SCB_GET_CHANNEL(ahc, scb);
+ lun = SCB_GET_LUN(scb);
+
+ ahc_print_path(ahc, scb);
+ printf("SCB 0x%x - timed out\n", scb->hscb->tag);
+ if (scb->sg_count > 0) {
+ for (i = 0; i < scb->sg_count; i++) {
+ printf("sg[%d] - Addr 0x%x : Length %d\n",

+				       i,
+				       scb->sg_list[i].addr,
+				       scb->sg_list[i].len & AHC_SG_LEN_MASK);

+ }
+ }
+ if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) {
+ /*
+ * Been down this road before.
+ * Do a full bus reset.
+ */
+bus_reset:
+ ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT);
+ found = ahc_reset_channel(ahc, channel,
+ /*Initiate Reset*/TRUE);
+ printf("%s: Issued Channel %c Bus Reset. "
+ "%d SCBs aborted\n", ahc_name(ahc), channel,
+ found);
+ continue;
+ }
+
+ /*
+ * Remove the command from the timedout list in
+ * preparation for requeing it.
+ */
+ LIST_REMOVE(scb, timedout_links);
+ scb->flags &= ~SCB_TIMEDOUT;
+
+ /*
+ * If we are a target, transition to bus free and report
+ * the timeout.
+ *
+ * The target/initiator that is holding up the bus may not
+ * be the same as the one that triggered this timeout
+ * (different commands have different timeout lengths).
+ * If the bus is idle and we are actiing as the initiator
+ * for this request, queue a BDR message to the timed out
+ * target. Otherwise, if the timed out transaction is
+ * active:
+ * Initiator transaction:
+ * Stuff the message buffer with a BDR message and assert
+ * ATN in the hopes that the target will let go of the bus
+ * and go to the mesgout phase. If this fails, we'll
+ * get another timeout 2 seconds later which will attempt
+ * a bus reset.
+ *
+ * Target transaction:
+ * Transition to BUS FREE and report the error.
+ * It's good to be the target!
+ */
+ saved_scbptr = ahc_inb(ahc, SCBPTR);
+ active_scb_index = ahc_inb(ahc, SCB_TAG);
+
+ if ((ahc_inb(ahc, SEQ_FLAGS) & NOT_IDENTIFIED) == 0
+ && (active_scb_index < ahc->scb_data->numscbs)) {
+ struct scb *active_scb;
+
+ /*
+ * If the active SCB is not us, assume that
+ * the active SCB has a longer timeout than
+ * the timedout SCB, and wait for the active
+ * SCB to timeout.
+ */
+ active_scb = ahc_lookup_scb(ahc, active_scb_index);
+ if (active_scb != scb) {
+ u_int newtimeout;
+
+ ahc_print_path(ahc, scb);
+ printf("Other SCB Timeout%s",
+ (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0
+ ? " again\n" : "\n");
+ scb->flags |= SCB_OTHERTCL_TIMEOUT;
+ newtimeout =
+ MAX(ahc_get_timeout(active_scb),
+ ahc_get_timeout(scb));
+ ahc_scb_timer_reset(scb, newtimeout);
+ continue;
+ }
+
+ /* It's us */
+ if ((scb->flags & SCB_TARGET_SCB) != 0) {
+
+ /*
+ * Send back any queued up transactions
+ * and properly record the error condition.
+ */
+ ahc_abort_scbs(ahc, SCB_GET_TARGET(ahc, scb),

+					       SCB_GET_CHANNEL(ahc, scb),
+					       SCB_GET_LUN(scb),
+					       scb->hscb->tag,
+					       ROLE_TARGET,
+					       CAM_CMD_TIMEOUT);

+
+ /* Will clear us from the bus */
+ restart_needed = 1;
+ break;
+ }
+
+ ahc_set_recoveryscb(ahc, active_scb);
+ ahc_outb(ahc, MSG_OUT, HOST_MSG);
+ ahc_outb(ahc, SCSISIGO, last_phase|ATNO);
+ ahc_print_path(ahc, active_scb);
+ printf("BDR message in message buffer\n");
+ active_scb->flags |= SCB_DEVICE_RESET;
+ ahc_scb_timer_reset(scb, 2 * 1000000);
+ } else {
+ int disconnected;
+
+ if (last_phase != P_BUSFREE
+ && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) {
+ /* Hung target selection. Goto busfree */
+ printf("%s: Hung target selection\n",
+ ahc_name(ahc));
+ restart_needed = 1;
+ break;
+ }
+
+ /* XXX Shouldn't panic. Just punt instead? */
+ if ((scb->flags & SCB_TARGET_SCB) != 0)
+ panic("Timed-out target SCB but bus idle");
+
+ if (ahc_search_qinfifo(ahc, target, channel, lun,
+ scb->hscb->tag, ROLE_INITIATOR,
+ /*status*/0, SEARCH_COUNT) > 0) {
+ disconnected = FALSE;
+ } else {
+ disconnected = TRUE;
+ }
+
+ if (disconnected) {
+
+ ahc_set_recoveryscb(ahc, scb);
+ /*
+ * Actually re-queue this SCB in an attempt
+ * to select the device before it reconnects.
+ * In either case (selection or reselection),
+ * we will now issue a target reset to the
+ * timed-out device.
+ *
+ * Set the MK_MESSAGE control bit indicating
+ * that we desire to send a message. We
+ * also set the disconnected flag since
+ * in the paging case there is no guarantee
+ * that our SCB control byte matches the
+ * version on the card. We don't want the
+ * sequencer to abort the command thinking
+ * an unsolicited reselection occurred.
+ */
+ scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
+ scb->flags |= SCB_DEVICE_RESET;
+
+ /*
+ * Remove any cached copy of this SCB in the
+ * disconnected list in preparation for the
+ * queuing of our abort SCB. We use the
+ * same element in the SCB, SCB_NEXT, for
+ * both the qinfifo and the disconnected list.
+ */
+ ahc_search_disc_list(ahc, target, channel,

+						     lun, scb->hscb->tag,
+						     /*stop_on_first*/TRUE,
+						     /*remove*/TRUE,
+						     /*save_state*/FALSE);

+
+ /*
+ * In the non-paging case, the sequencer will
+ * never re-reference the in-core SCB.
+ * To make sure we are notified during
+ * reslection, set the MK_MESSAGE flag in
+ * the card's copy of the SCB.
+ */
+ if ((ahc->flags & AHC_PAGESCBS) == 0) {
+ ahc_outb(ahc, SCBPTR, scb->hscb->tag);
+ ahc_outb(ahc, SCB_CONTROL,
+ ahc_inb(ahc, SCB_CONTROL)
+ | MK_MESSAGE);
+ }
+
+ /*
+ * Clear out any entries in the QINFIFO first
+ * so we are the next SCB for this target
+ * to run.
+ */
+ ahc_search_qinfifo(ahc,

+						   SCB_GET_TARGET(ahc, scb),
+						   channel, SCB_GET_LUN(scb),
+						   SCB_LIST_NULL,
+						   ROLE_INITIATOR,
+						   CAM_REQUEUE_REQ,
+						   SEARCH_COMPLETE);

+ ahc_print_path(ahc, scb);
+ printf("Queuing a BDR SCB\n");
+ ahc_qinfifo_requeue_tail(ahc, scb);
+ ahc_outb(ahc, SCBPTR, saved_scbptr);
+ ahc_scb_timer_reset(scb, 2 * 1000000);
+ } else {
+ /* Go "immediatly" to the bus reset */
+ /* This shouldn't happen */
+ ahc_set_recoveryscb(ahc, scb);
+ ahc_print_path(ahc, scb);
+ printf("SCB %d: Immediate reset. "
+ "Flags = 0x%x\n", scb->hscb->tag,
+ scb->flags);
+ goto bus_reset;
+ }
+ }
+ break;
+ }
+
+ /*
+ * Any remaining SCBs were not the "culprit", so give
+ * them a new lease on life.
+ */
+ while ((scb = LIST_FIRST(&ahc->timedout_scbs)) != NULL) {
+
+ LIST_REMOVE(scb, timedout_links);
+ scb->flags &= ~SCB_TIMEDOUT;
+ ahc_scb_timer_reset(scb, ahc_get_timeout(scb));
+ }
+
+ if (restart_needed)
+ ahc_restart(ahc);
+ else
+ ahc_unpause(ahc);
+ ahc_unlock(ahc, &s);
+}
+
/************************* Target Mode ****************************************/ #ifdef AHC_TARGET_MODE
cam_status

#1 lore raw
Quoted 1 line · Luben Tuikov

Sync up drivers/scsi/aic7xxx/. (2231-2232)

This looks a lot like the internal command timeout handling that has been rejected.

Please stop "syncup" madness. We couldn't care less what's in Adaptecs internal repository, especially if it's so bogus. Please submit patches that actually fix things. One patch per issue, with a proper explanation.

#2 lore raw
Quoted 7 lines · Christoph Hellwig
Quoted 1 line · Luben Tuikov

Sync up drivers/scsi/aic7xxx/. (2231-2232)

This looks a lot like the internal command timeout handling that has been rejected.

That's true. As there are other fixes alongside all the 205 patches of AIC into our SCM, I wanted to level it off and submit the timeout, dma, PCI fixes off of the latest version which we have here.

Those patches are simply for a review as other member of the community wanted. PCI, dma naming and timeout fixes would be off of those so as to not lose other important fixes in the drivers.

Luben

Quoted 4 lines

Please stop "syncup" madness. We couldn't care less what's in Adaptecs internal repository, especially if it's so bogus. Please submit patches that actually fix things. One patch per issue, with a proper explanation.

#3 lore raw
Quoted 7 lines · Luben Tuikov

That's true. As there are other fixes alongside all the 205 patches of AIC into our SCM, I wanted to level it off and submit the timeout, dma, PCI fixes off of the latest version which we have here.

Those patches are simply for a review as other member of the community wanted. PCI, dma naming and timeout fixes would be off of those so as to not lose other important fixes in the drivers.

There is no reasonable way to review this. You need to diff your current internal driver against the one in mainline, pull out logical changes and send those one at a time. That is reviewable, both by us and by you. When I've done this before, I've often found things I could have done better.

Signature · 6 lines
"Next the statesmen will invent cheap lies, putting the blame upon 
the nation that is attacked, and every man will be glad of those
conscience-soothing falsities, and will diligently study them, and refuse
to examine any refutations of them; and thus he will by and by convince 
himself that the war is just, and will thank God for the better sleep 
he enjoys after this process of grotesque self-deception." -- Mark Twain