* [patch 22/28] Sync up drivers/scsi/aic7xxx
@ 2004-09-28 13:07 Luben Tuikov
0 siblings, 0 replies; only message in thread
From: Luben Tuikov @ 2004-09-28 13:07 UTC (permalink / raw)
To: SCSI Mailing List
Sync up drivers/scsi/aic7xxx/. (2686-2789)
Signed-off-by: Luben Tuikov <luben_tuikov@adaptec.com>
==== //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Kconfig.aic79xx#4 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/Kconfig.aic79xx ====
--- /tmp/tmp.27147.0 2004-09-27 13:35:28.007370168 -0400
+++ /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/Kconfig.aic79xx 2004-02-09 12:10:50.000000000 -0500
@@ -1,10 +1,10 @@
#
# AIC79XX 2.5.X Kernel configuration File.
-# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Kconfig.aic79xx#4 $
+# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Kconfig.aic79xx#5 $
#
config SCSI_AIC79XX
tristate "Adaptec AIC79xx U320 support"
- depends on PCI
+ depends on PCI && SCSI
help
This driver supports all of Adaptec's Ultra 320 PCI-X
based SCSI controllers.
==== //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Kconfig.aic7xxx#8 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/Kconfig.aic7xxx ====
--- /tmp/tmp.27147.1 2004-09-27 13:35:28.047364088 -0400
+++ /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/Kconfig.aic7xxx 2004-02-09 12:10:57.000000000 -0500
@@ -1,10 +1,10 @@
#
# AIC7XXX and AIC79XX 2.5.X Kernel configuration File.
-# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Kconfig.aic7xxx#8 $
+# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Kconfig.aic7xxx#9 $
#
config SCSI_AIC7XXX
tristate "Adaptec AIC7xxx Fast -> U160 support (New Driver)"
- depends on PCI || EISA
+ depends on (PCI || EISA) && SCSI
---help---
This driver supports all of Adaptec's Fast through Ultra 160 PCI
based SCSI controllers as well as the aic7770 based EISA and VLB
==== //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Makefile#8 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/Makefile ====
--- /tmp/tmp.27147.2 2004-09-27 13:35:28.051363480 -0400
+++ /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/Makefile 2004-02-09 17:52:19.000000000 -0500
@@ -1,7 +1,7 @@
#
# Makefile for the Linux aic7xxx SCSI driver.
#
-# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Makefile#8 $
+# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Makefile#9 $
#
# Let kbuild descend into aicasm when cleaning
==== //depot/aic7xxx/aic7xxx/aic79xx.c#238 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic79xx_core.c ====
--- /tmp/tmp.27147.3 2004-09-27 13:35:29.495143992 -0400
+++ /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic79xx_core.c 2004-02-12 15:11:43.000000000 -0500
@@ -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#238 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#239 $
*/
#ifdef __linux__
@@ -338,6 +338,14 @@
ahd_outb(ahd, SCSISEQ1,
ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));
ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
+
+ /*
+ * Clear any pending sequencer interrupt. It is no
+ * longer relevant since we're resetting the Program
+ * Counter.
+ */
+ ahd_outb(ahd, CLRINT, CLRSEQINT);
+
ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
ahd_unpause(ahd);
}
==== //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#200 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic79xx_osm.c ====
--- /tmp/tmp.27147.4 2004-09-27 13:35:30.097052488 -0400
+++ /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic79xx_osm.c 2004-02-22 13:26:49.000000000 -0500
@@ -1,7 +1,7 @@
/*
* Adaptec AIC79xx device driver for Linux.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#200 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#205 $
*
* --------------------------------------------------------------------------
* Copyright (c) 1994-2000 Justin T. Gibbs.
@@ -480,8 +480,9 @@
static void ahd_linux_filter_inquiry(struct ahd_softc *ahd,
struct ahd_devinfo *devinfo);
static int __init ahd_linux_init(void);
-static void __exit ahd_linux_exit(void);
+static void ahd_linux_exit(void);
static void ahd_linux_dev_timed_unfreeze(u_long arg);
+static void ahd_linux_targ_timed_unfreeze(u_long arg);
static void ahd_linux_sem_timeout(u_long arg);
static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd);
static void ahd_linux_size_nseg(void);
@@ -1101,6 +1102,17 @@
printf("%s: aic79xx_linux_queue - Unable to allocate device!\n",
ahd_name(ahd));
return (0);
+ } else if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0
+ && cmd->device->type != -1) {
+ /*
+ * Configure devices that have already successfully
+ * completed an inquiry. This handles the case of
+ * devices being destroyed due to transient selection
+ * timeouts.
+ */
+ dev->flags &= ~AIC_DEV_UNCONFIGURED;
+ dev->scsi_device = cmd->device;
+ aic_linux_device_queue_depth(ahd, dev);
}
if (cmd->cmd_len > MAX_CDB_LEN) {
@@ -2026,7 +2038,6 @@
ahd_linux_setup_user_rd_strm_settings(ahd);
ahd_linux_initialize_scsi_bus(ahd);
ahd_unlock(ahd, &s);
- ahd_sysrq_key = aic_install_sysrq(&ahd_sysrq_op);
ahd_spawn_recovery_thread(ahd);
if (ahd->platform_data->recovery_pid < 0) {
printf("%s: Failed to create recovery thread, error= %d\n",
@@ -2190,7 +2201,6 @@
struct aic_linux_device *dev;
int i, j;
- aic_remove_sysrq(ahd_sysrq_key, &ahd_sysrq_op);
if (ahd->platform_data != NULL) {
del_timer_sync(&ahd->platform_data->completeq_timer);
ahd_linux_kill_dv_thread(ahd);
@@ -2208,7 +2218,19 @@
for (i = 0; i < AHD_NUM_TARGETS; i++) {
targ = ahd->platform_data->targets[i];
if (targ != NULL) {
- /* Keep target around through the loop. */
+
+ /*
+ * Stop any unfreeze timer from running.
+ */
+ del_timer_sync(&targ->timer);
+
+ /*
+ * Keep target around through the loop.
+ * The timer above may also have held
+ * a refcount, but since we forcibly
+ * delete the target, we don't care
+ * about the extra reference.
+ */
targ->refcount++;
for (j = 0; j < AHD_NUM_LUNS; j++) {
@@ -3955,7 +3977,8 @@
panic("running device on run list");
while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL
- && dev->openings > 0 && dev->qfrozen == 0) {
+ && dev->openings > 0 && dev->qfrozen == 0
+ && dev->target->qfrozen == 0) {
/*
* Schedule us to run later. The only reason we are not
@@ -4170,6 +4193,7 @@
targ->target = target;
targ->softc = ahd;
targ->flags = AIC_DV_REQUIRED;
+ init_timer(&targ->timer);
ahd->platform_data->targets[target] = targ;
return (targ);
}
@@ -4250,7 +4274,6 @@
{
struct aic_linux_target *targ;
- del_timer(&dev->timer);
targ = dev->target;
targ->devices[dev->lun] = NULL;
free(dev, M_DEVBUF);
@@ -4325,7 +4348,10 @@
}
case AC_SENT_BDR:
{
+ struct aic_linux_target *targ;
+ int target_offset;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+
WARN_ON(lun != CAM_LUN_WILDCARD);
scsi_report_device_reset(ahd->platform_data->host,
channel - 'A', target);
@@ -4347,6 +4373,36 @@
}
}
#endif
+ /*
+ * Freeze the target for a 500ms to give the
+ * target some time to recover from this BDR.
+ */
+ target_offset = target;
+ if (channel == 'B')
+ target_offset += 8;
+ targ = ahd->platform_data->targets[target_offset];
+ if (targ == NULL)
+ break;
+ if ((targ->flags & AIC_TARG_TIMER_ACTIVE) != 0) {
+ printf("%s:%c:%d: Target Timer still active during "
+ "BDR processing\n", ahd_name(ahd),
+ targ->channel, targ->target);
+ break;
+ }
+ /*
+ * Keep the reference count non-zero during
+ * the lifetime of the timer. This
+ * guarantees that the target will not
+ * be freed before our timer executes.
+ */
+ targ->refcount++;
+ targ->flags |= AIC_TARG_TIMER_ACTIVE;
+ targ->qfrozen++;
+ init_timer(&targ->timer);
+ targ->timer.data = (u_long)targ;
+ targ->timer.expires = jiffies + (HZ/2);
+ targ->timer.function = ahd_linux_targ_timed_unfreeze;
+ add_timer(&targ->timer);
break;
}
case AC_BUS_RESET:
@@ -4454,7 +4510,33 @@
} else if (aic_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
ahd_linux_handle_scsi_status(ahd, dev, scb);
} else if (aic_get_transaction_status(scb) == CAM_SEL_TIMEOUT) {
- dev->flags |= AIC_DEV_UNCONFIGURED;
+ struct aic_linux_target *targ;
+ struct aic_linux_device *cur_dev;
+ int i;
+
+ /*
+ * Mark all devices linked off this target
+ * as unconfigured.
+ */
+ targ = dev->target;
+ for (i = 0; i < AHD_NUM_LUNS; i++) {
+
+ if (targ->devices[i] == NULL)
+ continue;
+ cur_dev = targ->devices[i];
+ cur_dev->flags |= AIC_DEV_UNCONFIGURED;
+
+ /*
+ * Don't free the dev for this
+ * command prematurely.
+ */
+ if (cur_dev == dev)
+ continue;
+
+ if (TAILQ_EMPTY(&cur_dev->busyq)
+ && dev->active == 0)
+ ahd_linux_free_device(ahd, cur_dev);
+ }
if (AIC_DV_CMD(cmd) == FALSE)
dev->target->flags &= ~AIC_DV_REQUIRED;
}
@@ -4719,8 +4801,15 @@
dev->target->channel, dev->target->target);
break;
}
- dev->flags |= AIC_DEV_TIMER_ACTIVE;
dev->qfrozen++;
+ /*
+ * Keep the active count non-zero during
+ * the lifetime of the timer. This
+ * guarantees that the device will not
+ * be freed before our timer executes.
+ */
+ dev->active++;
+ dev->flags |= AIC_DEV_TIMER_ACTIVE;
init_timer(&dev->timer);
dev->timer.data = (u_long)dev;
dev->timer.expires = jiffies + (HZ/2);
@@ -5030,10 +5119,17 @@
dev = (struct aic_linux_device *)arg;
ahd = dev->target->softc;
ahd_lock(ahd, &s);
+
+ /*
+ * Release our hold on the device.
+ */
dev->flags &= ~AIC_DEV_TIMER_ACTIVE;
+ dev->active--;
+
if (dev->qfrozen > 0)
dev->qfrozen--;
if (dev->qfrozen == 0
+ && dev->target->qfrozen == 0
&& (dev->flags & AIC_DEV_ON_RUN_LIST) == 0)
ahd_linux_run_device_queue(ahd, dev);
if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0
@@ -5043,6 +5139,42 @@
ahd_unlock(ahd, &s);
}
+static void
+ahd_linux_targ_timed_unfreeze(u_long arg)
+{
+ struct aic_linux_target *targ;
+ struct ahd_softc *ahd;
+ u_long s;
+
+ targ = (struct aic_linux_target *)arg;
+ ahd = targ->softc;
+ ahd_lock(ahd, &s);
+
+ /*
+ * Release our hold on the target.
+ */
+ targ->flags &= ~AIC_TARG_TIMER_ACTIVE;
+ targ->refcount--;
+
+ if (targ->qfrozen > 0)
+ targ->qfrozen--;
+ if (targ->qfrozen == 0) {
+ u_int i;
+
+ for (i = 0; i < AHD_NUM_LUNS; i++) {
+ struct aic_linux_device *dev;
+
+ dev = targ->devices[i];
+ if (dev == NULL
+ || (dev->flags & AIC_DEV_ON_RUN_LIST) != 0)
+ continue;
+
+ aic_linux_check_device_queue(ahd, dev);
+ }
+ }
+ ahd_unlock(ahd, &s);
+}
+
void
ahd_platform_dump_card_state(struct ahd_softc *ahd)
{
@@ -5088,6 +5220,8 @@
{
int found;
+ ahd_sysrq_key = aic_install_sysrq(&ahd_sysrq_op);
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
found = ahd_linux_detect(&aic79xx_driver_template);
#else
@@ -5100,17 +5234,17 @@
#endif
if (ahd_init_status != 0) {
/*
- * Linux will only call our exit
- * routine if our init function
- * returns 0 status. Force cleanup
- * if initialization is not successful.
+ * Linux will not call our exit
+ * routine if we fail to load.
+ * Force cleanup if initialization
+ * is not successful.
*/
ahd_linux_exit();
}
return (ahd_init_status);
}
-static void __exit
+static void
ahd_linux_exit(void)
{
struct ahd_softc *ahd;
@@ -5135,6 +5269,8 @@
scsi_unregister_module(MODULE_SCSI_HA, &aic79xx_driver_template);
#endif
ahd_linux_pci_exit();
+
+ aic_remove_sysrq(ahd_sysrq_key, &ahd_sysrq_op);
}
module_init(ahd_linux_init);
==== //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#156 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic79xx_osm.h ====
--- /tmp/tmp.27147.5 2004-09-27 13:35:30.145045192 -0400
+++ /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic79xx_osm.h 2004-02-04 17:38:21.000000000 -0500
@@ -36,7 +36,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#156 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#157 $
*
*/
#ifndef _AIC79XX_LINUX_H_
@@ -94,7 +94,7 @@
#include <linux/smp.h>
#endif
-#define AIC79XX_DRIVER_VERSION "2.0.5"
+#define AIC79XX_DRIVER_VERSION "2.0.6"
/********************* Definitions Required by the Core ***********************/
/*
==== //depot/aic7xxx/aic7xxx/aic7xxx.c#148 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic7xxx_core.c ====
--- /tmp/tmp.27147.6 2004-09-27 13:35:30.998915384 -0400
+++ /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic7xxx_core.c 2004-02-19 16:52:54.000000000 -0500
@@ -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#148 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#150 $
*/
#ifdef __linux__
@@ -290,10 +290,19 @@
ahc_outb(ahc, SEQ_FLAGS2,
ahc_inb(ahc, SEQ_FLAGS2) & ~SCB_DMA);
}
+
+ /*
+ * Clear any pending sequencer interrupt. It is no
+ * longer relevant since we're resetting the Program
+ * Counter.
+ */
+ ahc_outb(ahc, CLRINT, CLRSEQINT);
+
ahc_outb(ahc, MWI_RESIDUAL, 0);
ahc_outb(ahc, SEQCTL, ahc->seqctl);
ahc_outb(ahc, SEQADDR0, 0);
ahc_outb(ahc, SEQADDR1, 0);
+
ahc_unpause(ahc);
}
@@ -365,6 +374,7 @@
if ((scb = TAILQ_FIRST(queue)) != NULL
&& (scb->flags & SCB_ACTIVE) == 0) {
scb->flags |= SCB_ACTIVE;
+ aic_scb_timer_start(scb);
ahc_queue_scb(ahc, scb);
}
}
==== //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#263 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic7xxx_osm.c ====
--- /tmp/tmp.27147.7 2004-09-27 13:35:31.557830416 -0400
+++ /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic7xxx_osm.c 2004-02-22 13:27:04.000000000 -0500
@@ -1,7 +1,7 @@
/*
* Adaptec AIC7xxx device driver for Linux.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#263 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#268 $
*
* Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science.
@@ -494,8 +494,9 @@
static void ahc_linux_filter_inquiry(struct ahc_softc*, struct ahc_devinfo*);
static void ahc_linux_sem_timeout(u_long arg);
static void ahc_linux_dev_timed_unfreeze(u_long arg);
+static void ahc_linux_targ_timed_unfreeze(u_long arg);
static int __init ahc_linux_init(void);
-static void __exit ahc_linux_exit(void);
+static void ahc_linux_exit(void);
static int ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag);
static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
static void ahc_linux_size_nseg(void);
@@ -1117,6 +1118,17 @@
printf("%s: aic7xxx_linux_queue - Unable to allocate device!\n",
ahc_name(ahc));
return (0);
+ } else if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0
+ && cmd->device->type != -1) {
+ /*
+ * Configure devices that have already successfully
+ * completed an inquiry. This handles the case of
+ * devices being destroyed due to transient selection
+ * timeouts.
+ */
+ dev->flags &= ~AIC_DEV_UNCONFIGURED;
+ dev->scsi_device = cmd->device;
+ aic_linux_device_queue_depth(ahc, dev);
}
if (cmd->cmd_len > MAX_CDB_LEN) {
@@ -1675,7 +1687,6 @@
#endif
ahc_linux_initialize_scsi_bus(ahc);
ahc_unlock(ahc, &s);
- ahc_sysrq_key = aic_install_sysrq(&ahc_sysrq_op);
ahc_spawn_recovery_thread(ahc);
if (ahc->platform_data->recovery_pid < 0) {
printf("%s: Failed to create recovery thread, error= %d\n",
@@ -1878,7 +1889,6 @@
struct aic_linux_device *dev;
int i, j;
- aic_remove_sysrq(ahc_sysrq_key, &ahc_sysrq_op);
if (ahc->platform_data != NULL) {
del_timer_sync(&ahc->platform_data->completeq_timer);
ahc_linux_kill_dv_thread(ahc);
@@ -1896,7 +1906,19 @@
for (i = 0; i < AHC_NUM_TARGETS; i++) {
targ = ahc->platform_data->targets[i];
if (targ != NULL) {
- /* Keep target around through the loop. */
+
+ /*
+ * Stop any unfreeze timer from running.
+ */
+ del_timer_sync(&targ->timer);
+
+ /*
+ * Keep target around through the loop.
+ * The timer above may also have held
+ * a refcount, but since we forcibly
+ * delete the target, we don't care
+ * about the extra reference.
+ */
targ->refcount++;
for (j = 0; j < AHC_NUM_LUNS; j++) {
@@ -3594,7 +3616,8 @@
panic("running device on run list");
while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL
- && dev->openings > 0 && dev->qfrozen == 0) {
+ && dev->openings > 0 && dev->qfrozen == 0
+ && dev->target->qfrozen == 0) {
/*
* Schedule us to run later. The only reason we are not
@@ -3863,6 +3886,7 @@
targ->target = target;
targ->softc = ahc;
targ->flags = AIC_DV_REQUIRED;
+ init_timer(&targ->timer);
ahc->platform_data->targets[target_offset] = targ;
return (targ);
}
@@ -3936,7 +3960,7 @@
* a tagged queuing capable device.
*/
dev->maxtags = 0;
-
+
targ->refcount++;
targ->devices[lun] = dev;
return (dev);
@@ -3947,7 +3971,6 @@
{
struct aic_linux_target *targ;
- del_timer(&dev->timer);
targ = dev->target;
targ->devices[dev->lun] = NULL;
free(dev, M_DEVBUF);
@@ -4028,7 +4051,10 @@
}
case AC_SENT_BDR:
{
+ struct aic_linux_target *targ;
+ int target_offset;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+
WARN_ON(lun != CAM_LUN_WILDCARD);
scsi_report_device_reset(ahc->platform_data->host,
channel - 'A', target);
@@ -4050,6 +4076,36 @@
}
}
#endif
+ /*
+ * Freeze the target for a 500ms to give the
+ * target some time to recover from this BDR.
+ */
+ target_offset = target;
+ if (channel == 'B')
+ target_offset += 8;
+ targ = ahc->platform_data->targets[target_offset];
+ if (targ == NULL)
+ break;
+ if ((targ->flags & AIC_TARG_TIMER_ACTIVE) != 0) {
+ printf("%s:%c:%d: Target Timer still active during "
+ "BDR processing\n", ahc_name(ahc),
+ targ->channel, targ->target);
+ break;
+ }
+ /*
+ * Keep the reference count non-zero during
+ * the lifetime of the timer. This
+ * guarantees that the target will not
+ * be freed before our timer executes.
+ */
+ targ->refcount++;
+ targ->flags |= AIC_TARG_TIMER_ACTIVE;
+ targ->qfrozen++;
+ init_timer(&targ->timer);
+ targ->timer.data = (u_long)targ;
+ targ->timer.expires = jiffies + (HZ/2);
+ targ->timer.function = ahc_linux_targ_timed_unfreeze;
+ add_timer(&targ->timer);
break;
}
case AC_BUS_RESET:
@@ -4169,7 +4225,33 @@
} else if (aic_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
ahc_linux_handle_scsi_status(ahc, dev, scb);
} else if (aic_get_transaction_status(scb) == CAM_SEL_TIMEOUT) {
- dev->flags |= AIC_DEV_UNCONFIGURED;
+ struct aic_linux_target *targ;
+ struct aic_linux_device *cur_dev;
+ int i;
+
+ /*
+ * Mark all devices linked off this target
+ * as unconfigured.
+ */
+ targ = dev->target;
+ for (i = 0; i < AHC_NUM_LUNS; i++) {
+
+ if (targ->devices[i] == NULL)
+ continue;
+ cur_dev = targ->devices[i];
+ cur_dev->flags |= AIC_DEV_UNCONFIGURED;
+
+ /*
+ * Don't free the dev for this
+ * command prematurely.
+ */
+ if (cur_dev == dev)
+ continue;
+
+ if (TAILQ_EMPTY(&cur_dev->busyq)
+ && dev->active == 0)
+ ahc_linux_free_device(ahc, cur_dev);
+ }
if (AIC_DV_CMD(cmd) == FALSE)
dev->target->flags &= ~AIC_DV_REQUIRED;
}
@@ -4417,8 +4499,15 @@
dev->target->channel, dev->target->target);
break;
}
- dev->flags |= AIC_DEV_TIMER_ACTIVE;
dev->qfrozen++;
+ /*
+ * Keep the active count non-zero during
+ * the lifetime of the timer. This
+ * guarantees that the device will not
+ * be freed before our timer executes.
+ */
+ dev->active++;
+ dev->flags |= AIC_DEV_TIMER_ACTIVE;
init_timer(&dev->timer);
dev->timer.data = (u_long)dev;
dev->timer.expires = jiffies + (HZ/2);
@@ -4699,10 +4788,17 @@
dev = (struct aic_linux_device *)arg;
ahc = dev->target->softc;
ahc_lock(ahc, &s);
+
+ /*
+ * Release our hold on the device.
+ */
dev->flags &= ~AIC_DEV_TIMER_ACTIVE;
+ dev->active--;
+
if (dev->qfrozen > 0)
dev->qfrozen--;
if (dev->qfrozen == 0
+ && dev->target->qfrozen == 0
&& (dev->flags & AIC_DEV_ON_RUN_LIST) == 0)
ahc_linux_run_device_queue(ahc, dev);
if ((dev->flags & AIC_DEV_UNCONFIGURED) != 0
@@ -4712,6 +4808,43 @@
ahc_unlock(ahc, &s);
}
+static void
+ahc_linux_targ_timed_unfreeze(u_long arg)
+{
+ struct aic_linux_target *targ;
+ struct ahc_softc *ahc;
+ u_long s;
+
+ targ = (struct aic_linux_target *)arg;
+ ahc = targ->softc;
+ ahc_lock(ahc, &s);
+
+ /*
+ * Release our hold on the target.
+ */
+ targ->flags &= ~AIC_TARG_TIMER_ACTIVE;
+ targ->refcount--;
+
+ targ->flags &= ~AIC_TARG_TIMER_ACTIVE;
+ if (targ->qfrozen > 0)
+ targ->qfrozen--;
+ if (targ->qfrozen == 0) {
+ u_int i;
+
+ for (i = 0; i < AHC_NUM_LUNS; i++) {
+ struct aic_linux_device *dev;
+
+ dev = targ->devices[i];
+ if (dev == NULL
+ || (dev->flags & AIC_DEV_ON_RUN_LIST) != 0)
+ continue;
+
+ aic_linux_check_device_queue(ahc, dev);
+ }
+ }
+ ahc_unlock(ahc, &s);
+}
+
static int
ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
{
@@ -5107,6 +5240,8 @@
{
int found;
+ ahc_sysrq_key = aic_install_sysrq(&ahc_sysrq_op);
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
found = ahc_linux_detect(&aic7xxx_driver_template);
#else
@@ -5119,17 +5254,17 @@
#endif
if (ahc_init_status != 0) {
/*
- * Linux will only call our exit
- * routine if our init function
- * returns 0 status. Force cleanup
- * if initialization is not successful.
+ * Linux will not call our exit
+ * routine if we fail to load.
+ * Force cleanup if initialization
+ * is not successful.
*/
ahc_linux_exit();
}
return (ahc_init_status);
}
-static void __exit
+static void
ahc_linux_exit(void)
{
struct ahc_softc *ahc;
@@ -5160,6 +5295,7 @@
#ifdef CONFIG_EISA
ahc_linux_eisa_exit();
#endif
+ aic_remove_sysrq(ahc_sysrq_key, &ahc_sysrq_op);
}
module_init(ahc_linux_init);
==== //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#168 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic7xxx_osm.h ====
--- /tmp/tmp.27147.8 2004-09-27 13:35:31.610822360 -0400
+++ /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aic7xxx_osm.h 2004-02-04 12:33:27.000000000 -0500
@@ -53,7 +53,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#168 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#169 $
*
*/
#ifndef _AIC7XXX_LINUX_H_
@@ -113,7 +113,7 @@
#include <linux/smp.h>
#endif
-#define AIC7XXX_DRIVER_VERSION "6.3.4"
+#define AIC7XXX_DRIVER_VERSION "6.3.5"
/********************* Definitions Required by the Core ***********************/
/*
==== //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#29 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y ====
--- /tmp/tmp.27147.9 2004-09-27 13:35:31.786795608 -0400
+++ /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y 2004-02-12 19:29:06.000000000 -0500
@@ -38,7 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#29 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#30 $
*
* $FreeBSD$
*/
@@ -157,6 +157,8 @@
%token T_END_CS
+%token T_PAD_PAGE
+
%token T_FIELD
%token T_ENUM
@@ -189,6 +191,10 @@
%token <value> T_OR
+/* 16 bit extensions */
+%token <value> T_OR16 T_AND16 T_XOR16 T_ADD16
+%token <value> T_ADC16 T_MVI16 T_TEST16 T_CMP16 T_CMPXCHG
+
%token T_RET
%token T_NOP
@@ -207,7 +213,7 @@
%type <expression> expression immediate immediate_or_a
-%type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne
+%type <value> export ret f1_opcode f2_opcode f4_opcode jmp_jc_jnc_call jz_jnz je_jne
%type <value> mode_value mode_list macro_arglist
@@ -1304,6 +1310,15 @@
| T_ROR { $$ = AIC_OP_ROR; }
;
+f4_opcode:
+ T_OR16 { $$ = AIC_OP_OR16; }
+| T_AND16 { $$ = AIC_OP_AND16; }
+| T_XOR16 { $$ = AIC_OP_XOR16; }
+| T_ADD16 { $$ = AIC_OP_ADD16; }
+| T_ADC16 { $$ = AIC_OP_ADC16; }
+| T_MVI16 { $$ = AIC_OP_MVI16; }
+;
+
code:
f2_opcode destination ',' expression opt_source ret ';'
{
==== //depot/aic7xxx/aic7xxx/aicasm/aicasm_insformat.h#11 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h ====
--- /tmp/tmp.27147.10 2004-09-27 13:35:31.795794240 -0400
+++ /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h 2004-02-12 19:28:11.000000000 -0500
@@ -37,11 +37,12 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_insformat.h#11 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_insformat.h#12 $
*
* $FreeBSD$
*/
+/* 8bit ALU logic operations */
struct ins_format1 {
#if BYTE_ORDER == LITTLE_ENDIAN
uint32_t immediate : 8,
@@ -60,6 +61,7 @@
#endif
};
+/* 8bit ALU shift/rotate operations */
struct ins_format2 {
#if BYTE_ORDER == LITTLE_ENDIAN
uint32_t shift_control : 8,
@@ -78,6 +80,7 @@
#endif
};
+/* 8bit branch control operations */
struct ins_format3 {
#if BYTE_ORDER == LITTLE_ENDIAN
uint32_t immediate : 8,
@@ -94,10 +97,68 @@
#endif
};
+/* 16bit ALU logic operations */
+struct ins_format4 {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint32_t opcode_ext : 8,
+ source : 9,
+ destination : 9,
+ ret : 1,
+ opcode : 4,
+ parity : 1;
+#else
+ uint32_t parity : 1,
+ opcode : 4,
+ ret : 1,
+ destination : 9,
+ source : 9,
+ opcode_ext : 8;
+#endif
+};
+
+/* 16bit branch control operations */
+struct ins_format5 {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint32_t opcode_ext : 8,
+ source : 9,
+ address : 10,
+ opcode : 4,
+ parity : 1;
+#else
+ uint32_t parity : 1,
+ opcode : 4,
+ address : 10,
+ source : 9,
+ opcode_ext : 8;
+#endif
+};
+
+/* Far branch operations */
+struct ins_format6 {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint32_t page : 3,
+ opcode_ext : 5,
+ source : 9,
+ address : 10,
+ opcode : 4,
+ parity : 1;
+#else
+ uint32_t parity : 1,
+ opcode : 4,
+ address : 10,
+ source : 9,
+ opcode_ext : 5,
+ page : 3;
+#endif
+};
+
union ins_formats {
struct ins_format1 format1;
struct ins_format2 format2;
struct ins_format3 format3;
+ struct ins_format4 format4;
+ struct ins_format5 format5;
+ struct ins_format6 format6;
uint8_t bytes[4];
uint32_t integer;
};
@@ -116,6 +177,8 @@
#define AIC_OP_ROL 0x5
#define AIC_OP_BMOV 0x6
+#define AIC_OP_MVI16 0x7
+
#define AIC_OP_JMP 0x8
#define AIC_OP_JC 0x9
#define AIC_OP_JNC 0xa
@@ -129,3 +192,26 @@
#define AIC_OP_SHL 0x10
#define AIC_OP_SHR 0x20
#define AIC_OP_ROR 0x30
+
+/* 16bit Ops. Low byte main opcode. High byte extended opcode. */
+#define AIC_OP_OR16 0x8005
+#define AIC_OP_AND16 0x8105
+#define AIC_OP_XOR16 0x8205
+#define AIC_OP_ADD16 0x8305
+#define AIC_OP_ADC16 0x8405
+#define AIC_OP_JNE16 0x8805
+#define AIC_OP_JNZ16 0x8905
+#define AIC_OP_JE16 0x8C05
+#define AIC_OP_JZ16 0x8B05
+#define AIC_OP_JMP16 0x9005
+#define AIC_OP_JC16 0x9105
+#define AIC_OP_JNC16 0x9205
+#define AIC_OP_CALL16 0x9305
+#define AIC_OP_CALL16 0x9305
+
+/* Page extension is low three bits of second opcode byte. */
+#define AIC_OP_JMPF 0xA005
+#define AIC_OP_CALLF 0xB005
+#define AIC_OP_JCF 0xC005
+#define AIC_OP_JNCF 0xD005
+#define AIC_OP_CMPXCHG 0xE005
==== //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#19 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l ====
--- /tmp/tmp.27147.11 2004-09-27 13:35:31.851785728 -0400
+++ /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aicasm/aicasm_scan.l 2004-02-12 19:08:30.000000000 -0500
@@ -38,7 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#19 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_scan.l#20 $
*
* $FreeBSD$
*/
@@ -132,7 +132,7 @@
*string_buf_ptr++ = *yptr++;
}
}
-
+else { return T_ELSE; }
VERSION { return T_VERSION; }
PREFIX { return T_PREFIX; }
PATCH_ARG_LIST { return T_PATCH_ARG_LIST; }
@@ -173,10 +173,6 @@
yylval.value = WO;
return T_MODE;
}
-BEGIN_CRITICAL { return T_BEGIN_CS; }
-END_CRITICAL { return T_END_CS; }
-SET_SRC_MODE { return T_SET_SRC_MODE; }
-SET_DST_MODE { return T_SET_DST_MODE; }
field { return T_FIELD; }
enum { return T_ENUM; }
mask { return T_MASK; }
@@ -192,6 +188,13 @@
sindex { return T_SINDEX; }
A { return T_A; }
+ /* Instruction Formatting */
+PAD_PAGE { return T_PAD_PAGE; }
+BEGIN_CRITICAL { return T_BEGIN_CS; }
+END_CRITICAL { return T_END_CS; }
+SET_SRC_MODE { return T_SET_SRC_MODE; }
+SET_DST_MODE { return T_SET_DST_MODE; }
+
/* Opcodes */
shl { return T_SHL; }
shr { return T_SHR; }
@@ -223,7 +226,17 @@
or { return T_OR; }
ret { return T_RET; }
nop { return T_NOP; }
-else { return T_ELSE; }
+
+ /* ARP2 16bit extensions */
+or16 { return T_OR16; }
+and16 { return T_AND16; }
+xor16 { return T_XOR16; }
+add16 { return T_ADD16; }
+adc16 { return T_ADC16; }
+mvi16 { return T_MVI16; }
+test16 { return T_TEST16; }
+cmp16 { return T_CMP16; }
+cmpxchg { return T_CMPXCHG; }
/* Allowed Symbols */
\<\< { return T_EXPR_LSHIFT; }
==== //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aiclib.h#37 - /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aiclib.h ====
--- /tmp/tmp.27147.12 2004-09-27 13:35:32.182735416 -0400
+++ /home/luben/projects/linux/2.6/linux-2.5/drivers/scsi/aic7xxx/aiclib.h 2004-02-20 16:48:43.000000000 -0500
@@ -648,7 +648,8 @@
AIC_DV_REQUIRED = 0x01,
AIC_INQ_VALID = 0x02,
AIC_BASIC_DV = 0x04,
- AIC_ENHANCED_DV = 0x08
+ AIC_ENHANCED_DV = 0x08,
+ AIC_TARG_TIMER_ACTIVE = 0x10
} aic_linux_targ_flags;
/* DV States */
@@ -667,6 +668,12 @@
} aic_dv_state;
struct aic_linux_target {
+ /*
+ * A positive count indicates that this
+ * target's queue is halted.
+ */
+ u_int qfrozen;
+
struct aic_linux_device *devices[AIC_NUM_LUNS];
int channel;
int target;
@@ -676,6 +683,11 @@
aic_linux_targ_flags flags;
struct scsi_inquiry_data *inq_data;
/*
+ * Per target timer.
+ */
+ struct timer_list timer;
+
+ /*
* The next "fallback" period to use for narrow/wide transfers.
*/
uint8_t dv_next_narrow_period;
@@ -2106,7 +2118,8 @@
}
if (TAILQ_FIRST(&dev->busyq) == NULL
- || dev->openings == 0 || dev->qfrozen != 0)
+ || dev->openings == 0 || dev->qfrozen != 0
+ || dev->target->qfrozen != 0)
return;
aic_linux_run_device_queue(aic, dev);
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2004-09-28 13:07 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-09-28 13:07 [patch 22/28] Sync up drivers/scsi/aic7xxx Luben Tuikov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).