aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/Kconfig14
-rw-r--r--drivers/scsi/Makefile5
-rw-r--r--drivers/scsi/aacraid/aachba.c15
-rw-r--r--drivers/scsi/aacraid/aacraid.h3
-rw-r--r--drivers/scsi/aacraid/rx.c8
-rw-r--r--drivers/scsi/aacraid/sa.c9
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm_gram.y1
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y1
-rw-r--r--drivers/scsi/aic94xx/aic94xx_tmf.c14
-rw-r--r--drivers/scsi/ipr.c7
-rw-r--r--drivers/scsi/jazz_esp.c429
-rw-r--r--drivers/scsi/libsrp.c1
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c67
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h14
-rw-r--r--drivers/scsi/pluto.c18
-rw-r--r--drivers/scsi/scsi_devinfo.c1
-rw-r--r--drivers/scsi/sd.c18
-rw-r--r--drivers/scsi/stex.c90
18 files changed, 370 insertions, 345 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index d28c14e..572034c 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1753,23 +1753,9 @@ config SUN3X_ESP
The ESP was an on-board SCSI controller used on Sun 3/80
machines. Say Y here to compile in support for it.
-config SCSI_ESP_CORE
- tristate "ESP Scsi Driver Core"
- depends on SCSI
- select SCSI_SPI_ATTRS
- help
- This is a core driver for NCR53c9x based scsi chipsets,
- also known as "ESP" for Emulex Scsi Processor or
- Enhanced Scsi Processor. This driver does not exist by
- itself, there are front-end drivers which, when enabled,
- select and enable this driver. One example is SCSI_SUNESP.
- These front-end drivers provide probing, DMA, and register
- access support for the core driver.
-
config SCSI_SUNESP
tristate "Sparc ESP Scsi Driver"
depends on SBUS && SCSI
- select SCSI_ESP_CORE
help
This is the driver for the Sun ESP SCSI host adapter. The ESP
chipset is present in most SPARC SBUS-based computers.
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 51e884f..b1b6327 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -106,8 +106,7 @@ obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
obj-$(CONFIG_MEGARAID_SAS) += megaraid/
obj-$(CONFIG_SCSI_ACARD) += atp870u.o
-obj-$(CONFIG_SCSI_ESP_CORE) += esp_scsi.o
-obj-$(CONFIG_SCSI_SUNESP) += sun_esp.o
+obj-$(CONFIG_SCSI_SUNESP) += esp_scsi.o sun_esp.o
obj-$(CONFIG_SCSI_GDTH) += gdth.o
obj-$(CONFIG_SCSI_INITIO) += initio.o
obj-$(CONFIG_SCSI_INIA100) += a100u2w.o
@@ -121,7 +120,7 @@ obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o
obj-$(CONFIG_SCSI_3W_9XXX) += 3w-9xxx.o
obj-$(CONFIG_SCSI_PPA) += ppa.o
obj-$(CONFIG_SCSI_IMM) += imm.o
-obj-$(CONFIG_JAZZ_ESP) += NCR53C9x.o jazz_esp.o
+obj-$(CONFIG_JAZZ_ESP) += esp_scsi.o jazz_esp.o
obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o
obj-$(CONFIG_SCSI_FCAL) += fcal.o
obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 1e82c69..8dcfe4e 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -146,7 +146,7 @@ static char *aac_get_status_string(u32 status);
static int nondasd = -1;
static int dacmode = -1;
-static int commit = -1;
+int aac_commit = -1;
int startup_timeout = 180;
int aif_timeout = 120;
@@ -154,7 +154,7 @@ module_param(nondasd, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");
module_param(dacmode, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on");
-module_param(commit, int, S_IRUGO|S_IWUSR);
+module_param_named(commit, aac_commit, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on");
module_param(startup_timeout, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(startup_timeout, "The duration of time in seconds to wait for adapter to have it's kernel up and\nrunning. This is typically adjusted for large systems that do not have a BIOS.");
@@ -173,6 +173,9 @@ int expose_physicals = -1;
module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on");
+int aac_reset_devices = 0;
+module_param_named(reset_devices, aac_reset_devices, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(reset_devices, "Force an adapter reset at initialization.");
static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
struct fib *fibptr) {
@@ -246,7 +249,7 @@ int aac_get_config_status(struct aac_dev *dev, int commit_flag)
aac_fib_complete(fibptr);
/* Send a CT_COMMIT_CONFIG to enable discovery of devices */
if (status >= 0) {
- if ((commit == 1) || commit_flag) {
+ if ((aac_commit == 1) || commit_flag) {
struct aac_commit_config * dinfo;
aac_fib_init(fibptr);
dinfo = (struct aac_commit_config *) fib_data(fibptr);
@@ -261,7 +264,7 @@ int aac_get_config_status(struct aac_dev *dev, int commit_flag)
1, 1,
NULL, NULL);
aac_fib_complete(fibptr);
- } else if (commit == 0) {
+ } else if (aac_commit == 0) {
printk(KERN_WARNING
"aac_get_config_status: Foreign device configurations are being ignored\n");
}
@@ -340,7 +343,7 @@ int aac_get_containers(struct aac_dev *dev)
static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
{
void *buf;
- unsigned int transfer_len;
+ int transfer_len;
struct scatterlist *sg = scsicmd->request_buffer;
if (scsicmd->use_sg) {
@@ -351,7 +354,7 @@ static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigne
transfer_len = min(scsicmd->request_bufflen, len + offset);
}
transfer_len -= offset;
- if (buf && transfer_len)
+ if (buf && transfer_len > 0)
memcpy(buf + offset, data, transfer_len);
if (scsicmd->use_sg)
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 45ca3e8..c81edf3 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -1823,9 +1823,12 @@ int aac_send_shutdown(struct aac_dev *dev);
int aac_probe_container(struct aac_dev *dev, int cid);
int _aac_rx_init(struct aac_dev *dev);
int aac_rx_select_comm(struct aac_dev *dev, int comm);
+int aac_rx_deliver_producer(struct fib * fib);
extern int numacb;
extern int acbsize;
extern char aac_driver_version[];
extern int startup_timeout;
extern int aif_timeout;
extern int expose_physicals;
+extern int aac_reset_devices;
+extern int aac_commit;
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 291cd14..ae978a3 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -378,7 +378,7 @@ static int aac_rx_check_health(struct aac_dev *dev)
*
* Will send a fib, returning 0 if successful.
*/
-static int aac_rx_deliver_producer(struct fib * fib)
+int aac_rx_deliver_producer(struct fib * fib)
{
struct aac_dev *dev = fib->dev;
struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
@@ -488,6 +488,8 @@ static int aac_rx_restart_adapter(struct aac_dev *dev, int bled)
return -EINVAL;
if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC)
return -ENODEV;
+ if (startup_timeout < 300)
+ startup_timeout = 300;
return 0;
}
@@ -542,7 +544,7 @@ int _aac_rx_init(struct aac_dev *dev)
dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
dev->a_ops.adapter_enable_int = aac_rx_disable_interrupt;
dev->OIMR = status = rx_readb (dev, MUnit.OIMR);
- if ((((status & 0x0c) != 0x0c) || reset_devices) &&
+ if ((((status & 0x0c) != 0x0c) || aac_reset_devices || reset_devices) &&
!aac_rx_restart_adapter(dev, 0))
++restart;
/*
@@ -594,6 +596,8 @@ int _aac_rx_init(struct aac_dev *dev)
}
msleep(1);
}
+ if (restart)
+ aac_commit = 1;
/*
* Fill in the common function dispatch table.
*/
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index f4b5e97..85b91bc 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -5,7 +5,7 @@
* based on the old aacraid driver that is..
* Adaptec aacraid device driver for Linux.
*
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -257,6 +257,11 @@ static void aac_sa_start_adapter(struct aac_dev *dev)
NULL, NULL, NULL, NULL, NULL);
}
+static int aac_sa_restart_adapter(struct aac_dev *dev, int bled)
+{
+ return -EINVAL;
+}
+
/**
* aac_sa_check_health
* @dev: device to check if healthy
@@ -366,7 +371,9 @@ int aac_sa_init(struct aac_dev *dev)
dev->a_ops.adapter_notify = aac_sa_notify_adapter;
dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
dev->a_ops.adapter_check_health = aac_sa_check_health;
+ dev->a_ops.adapter_restart = aac_sa_restart_adapter;
dev->a_ops.adapter_intr = aac_sa_intr;
+ dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
dev->a_ops.adapter_ioremap = aac_sa_ioremap;
/*
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
index c328596..6066998 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
@@ -106,6 +106,7 @@ static void make_expression(expression_t *immed, int value);
static void add_conditional(symbol_t *symbol);
static void add_version(const char *verstring);
static int is_download_const(expression_t *immed);
+void yyerror(const char *string);
#define SRAM_SYMNAME "SRAM_BASE"
#define SCB_SYMNAME "SCB_BASE"
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y b/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y
index 439f760..ff46aa6 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y
@@ -65,6 +65,7 @@
static symbol_t *macro_symbol;
static void add_macro_arg(const char *argtext, int position);
+void mmerror(const char *string);
%}
diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
index 9a14a6d..c0d0b7d 100644
--- a/drivers/scsi/aic94xx/aic94xx_tmf.c
+++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
@@ -290,6 +290,7 @@ static void asd_tmf_tasklet_complete(struct asd_ascb *ascb,
static inline int asd_clear_nexus(struct sas_task *task)
{
int res = TMF_RESP_FUNC_FAILED;
+ int leftover;
struct asd_ascb *tascb = task->lldd_task;
unsigned long flags;
@@ -298,10 +299,12 @@ static inline int asd_clear_nexus(struct sas_task *task)
res = asd_clear_nexus_tag(task);
else
res = asd_clear_nexus_index(task);
- wait_for_completion_timeout(&tascb->completion,
- AIC94XX_SCB_TIMEOUT);
+ leftover = wait_for_completion_timeout(&tascb->completion,
+ AIC94XX_SCB_TIMEOUT);
ASD_DPRINTK("came back from clear nexus\n");
spin_lock_irqsave(&task->task_state_lock, flags);
+ if (leftover < 1)
+ res = TMF_RESP_FUNC_FAILED;
if (task->task_state_flags & SAS_TASK_STATE_DONE)
res = TMF_RESP_FUNC_COMPLETE;
spin_unlock_irqrestore(&task->task_state_lock, flags);
@@ -350,6 +353,7 @@ int asd_abort_task(struct sas_task *task)
unsigned long flags;
struct asd_ascb *ascb = NULL;
struct scb *scb;
+ int leftover;
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
@@ -455,9 +459,11 @@ int asd_abort_task(struct sas_task *task)
break;
case TF_TMF_TASK_DONE + 0xFF00: /* done but not reported yet */
res = TMF_RESP_FUNC_FAILED;
- wait_for_completion_timeout(&tascb->completion,
- AIC94XX_SCB_TIMEOUT);
+ leftover = wait_for_completion_timeout(&tascb->completion,
+ AIC94XX_SCB_TIMEOUT);
spin_lock_irqsave(&task->task_state_lock, flags);
+ if (leftover < 1)
+ res = TMF_RESP_FUNC_FAILED;
if (task->task_state_flags & SAS_TASK_STATE_DONE)
res = TMF_RESP_FUNC_COMPLETE;
spin_unlock_irqrestore(&task->task_state_lock, flags);
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 4baa79e..fa6ff29 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -3954,6 +3954,13 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
spin_unlock_irq(scsi_cmd->device->host->host_lock);
ata_do_eh(ap, NULL, NULL, ipr_sata_reset, NULL);
spin_lock_irq(scsi_cmd->device->host->host_lock);
+
+ list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
+ if (ipr_cmd->ioarcb.res_handle == res->cfgte.res_handle) {
+ rc = -EIO;
+ break;
+ }
+ }
} else
rc = ipr_device_reset(ioa_cfg, res);
res->resetting_device = 0;
diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c
index 19dd4b9..81e497d 100644
--- a/drivers/scsi/jazz_esp.c
+++ b/drivers/scsi/jazz_esp.c
@@ -1,307 +1,244 @@
-/*
- * jazz_esp.c: Driver for SCSI chip on Mips Magnum Boards (JAZZ architecture)
+/* jazz_esp.c: ESP front-end for MIPS JAZZ systems.
*
- * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
- *
- * jazz_esp is based on David S. Miller's ESP driver and cyber_esp
+ * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)
*/
-#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/delay.h>
#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "NCR53C9x.h"
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
#include <asm/jazz.h>
#include <asm/jazzdma.h>
-#include <asm/dma.h>
-#include <asm/pgtable.h>
-
-static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
-static int dma_can_transfer(struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_dump_state(struct NCR_ESP *esp);
-static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void dma_ints_off(struct NCR_ESP *esp);
-static void dma_ints_on(struct NCR_ESP *esp);
-static int dma_irq_p(struct NCR_ESP *esp);
-static int dma_ports_p(struct NCR_ESP *esp);
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
-static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_advance_sg (struct scsi_cmnd *sp);
-static void dma_led_off(struct NCR_ESP *);
-static void dma_led_on(struct NCR_ESP *);
-
-
-static volatile unsigned char cmd_buffer[16];
- /* This is where all commands are put
- * before they are trasfered to the ESP chip
- * via PIO.
- */
-
-static int jazz_esp_release(struct Scsi_Host *shost)
-{
- if (shost->irq)
- free_irq(shost->irq, NULL);
- if (shost->dma_channel != 0xff)
- free_dma(shost->dma_channel);
- if (shost->io_port && shost->n_io_port)
- release_region(shost->io_port, shost->n_io_port);
- scsi_unregister(shost);
- return 0;
-}
+#include <scsi/scsi_host.h>
-/***************************************************************** Detection */
-static int jazz_esp_detect(struct scsi_host_template *tpnt)
-{
- struct NCR_ESP *esp;
- struct ConfigDev *esp_dev;
-
- /*
- * first assumption it is there:-)
- */
- if (1) {
- esp_dev = NULL;
- esp = esp_allocate(tpnt, esp_dev, 0);
-
- /* Do command transfer with programmed I/O */
- esp->do_pio_cmds = 1;
-
- /* Required functions */
- esp->dma_bytes_sent = &dma_bytes_sent;
- esp->dma_can_transfer = &dma_can_transfer;
- esp->dma_dump_state = &dma_dump_state;
- esp->dma_init_read = &dma_init_read;
- esp->dma_init_write = &dma_init_write;
- esp->dma_ints_off = &dma_ints_off;
- esp->dma_ints_on = &dma_ints_on;
- esp->dma_irq_p = &dma_irq_p;
- esp->dma_ports_p = &dma_ports_p;
- esp->dma_setup = &dma_setup;
-
- /* Optional functions */
- esp->dma_barrier = NULL;
- esp->dma_drain = NULL;
- esp->dma_invalidate = NULL;
- esp->dma_irq_entry = NULL;
- esp->dma_irq_exit = NULL;
- esp->dma_poll = NULL;
- esp->dma_reset = NULL;
- esp->dma_led_off = &dma_led_off;
- esp->dma_led_on = &dma_led_on;
-
- /* virtual DMA functions */
- esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one;
- esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl;
- esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one;
- esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl;
- esp->dma_advance_sg = &dma_advance_sg;
-
-
- /* SCSI chip speed */
- esp->cfreq = 40000000;
+#include "esp_scsi.h"
- /*
- * we don't give the address of DMA channel, but the number
- * of DMA channel, so we can use the jazz DMA functions
- *
- */
- esp->dregs = (void *) JAZZ_SCSI_DMA;
-
- /* ESP register base */
- esp->eregs = (struct ESP_regs *)(JAZZ_SCSI_BASE);
-
- /* Set the command buffer */
- esp->esp_command = (volatile unsigned char *)cmd_buffer;
-
- /* get virtual dma address for command buffer */
- esp->esp_command_dvma = vdma_alloc(CPHYSADDR(cmd_buffer), sizeof (cmd_buffer));
-
- esp->irq = JAZZ_SCSI_IRQ;
- request_irq(JAZZ_SCSI_IRQ, esp_intr, IRQF_DISABLED, "JAZZ SCSI",
- esp->ehost);
-
- /*
- * FIXME, look if the scsi id is available from NVRAM
- */
- esp->scsi_id = 7;
-
- /* Check for differential SCSI-bus */
- /* What is this stuff? */
- esp->diff = 0;
-
- esp_initialize(esp);
-
- printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,esps_in_use);
- esps_running = esps_in_use;
- return esps_in_use;
- }
- return 0;
-}
+#define DRV_MODULE_NAME "jazz_esp"
+#define PFX DRV_MODULE_NAME ": "
+#define DRV_VERSION "1.000"
+#define DRV_MODULE_RELDATE "May 19, 2007"
-/************************************************************* DMA Functions */
-static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+static void jazz_esp_write8(struct esp *esp, u8 val, unsigned long reg)
{
- return fifo_count;
+ *(volatile u8 *)(esp->regs + reg) = val;
}
-static int dma_can_transfer(struct NCR_ESP *esp, struct scsi_cmnd *sp)
+static u8 jazz_esp_read8(struct esp *esp, unsigned long reg)
{
- /*
- * maximum DMA size is 1MB
- */
- unsigned long sz = sp->SCp.this_residual;
- if(sz > 0x100000)
- sz = 0x100000;
- return sz;
+ return *(volatile u8 *)(esp->regs + reg);
}
-static void dma_dump_state(struct NCR_ESP *esp)
+static dma_addr_t jazz_esp_map_single(struct esp *esp, void *buf,
+ size_t sz, int dir)
{
-
- ESPLOG(("esp%d: dma -- enable <%08x> residue <%08x\n",
- esp->esp_id, vdma_get_enable((int)esp->dregs), vdma_get_residue((int)esp->dregs)));
+ return dma_map_single(esp->dev, buf, sz, dir);
}
-static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
+static int jazz_esp_map_sg(struct esp *esp, struct scatterlist *sg,
+ int num_sg, int dir)
{
- dma_cache_wback_inv ((unsigned long)phys_to_virt(vdma_log2phys(vaddress)), length);
- vdma_disable ((int)esp->dregs);
- vdma_set_mode ((int)esp->dregs, DMA_MODE_READ);
- vdma_set_addr ((int)esp->dregs, vaddress);
- vdma_set_count ((int)esp->dregs, length);
- vdma_enable ((int)esp->dregs);
+ return dma_map_sg(esp->dev, sg, num_sg, dir);
}
-static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
+static void jazz_esp_unmap_single(struct esp *esp, dma_addr_t addr,
+ size_t sz, int dir)
{
- dma_cache_wback_inv ((unsigned long)phys_to_virt(vdma_log2phys(vaddress)), length);
- vdma_disable ((int)esp->dregs);
- vdma_set_mode ((int)esp->dregs, DMA_MODE_WRITE);
- vdma_set_addr ((int)esp->dregs, vaddress);
- vdma_set_count ((int)esp->dregs, length);
- vdma_enable ((int)esp->dregs);
+ dma_unmap_single(esp->dev, addr, sz, dir);
}
-static void dma_ints_off(struct NCR_ESP *esp)
+static void jazz_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
+ int num_sg, int dir)
{
- disable_irq(esp->irq);
+ dma_unmap_sg(esp->dev, sg, num_sg, dir);
}
-static void dma_ints_on(struct NCR_ESP *esp)
+static int jazz_esp_irq_pending(struct esp *esp)
{
- enable_irq(esp->irq);
+ if (jazz_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR)
+ return 1;
+ return 0;
}
-static int dma_irq_p(struct NCR_ESP *esp)
+static void jazz_esp_reset_dma(struct esp *esp)
{
- return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
+ vdma_disable ((int)esp->dma_regs);
}
-static int dma_ports_p(struct NCR_ESP *esp)
+static void jazz_esp_dma_drain(struct esp *esp)
{
- int enable = vdma_get_enable((int)esp->dregs);
-
- return (enable & R4030_CHNL_ENABLE);
+ /* nothing to do */
}
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
+static void jazz_esp_dma_invalidate(struct esp *esp)
{
- /*
- * On the Sparc, DMA_ST_WRITE means "move data from device to memory"
- * so when (write) is true, it actually means READ!
- */
- if(write){
- dma_init_read(esp, addr, count);
- } else {
- dma_init_write(esp, addr, count);
- }
+ vdma_disable ((int)esp->dma_regs);
}
-static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp)
+static void jazz_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
+ u32 dma_count, int write, u8 cmd)
{
- sp->SCp.have_data_in = vdma_alloc(CPHYSADDR(sp->SCp.buffer), sp->SCp.this_residual);
- sp->SCp.ptr = (char *)((unsigned long)sp->SCp.have_data_in);
+ BUG_ON(!(cmd & ESP_CMD_DMA));
+
+ jazz_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+ jazz_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+ vdma_disable ((int)esp->dma_regs);
+ if (write)
+ vdma_set_mode ((int)esp->dma_regs, DMA_MODE_READ);
+ else
+ vdma_set_mode ((int)esp->dma_regs, DMA_MODE_WRITE);
+
+ vdma_set_addr ((int)esp->dma_regs, addr);
+ vdma_set_count ((int)esp->dma_regs, dma_count);
+ vdma_enable ((int)esp->dma_regs);
+
+ scsi_esp_cmd(esp, cmd);
}
-static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp)
-{
- int sz = sp->SCp.buffers_residual;
- struct scatterlist *sg = (struct scatterlist *) sp->SCp.buffer;
-
- while (sz >= 0) {
- sg[sz].dma_address = vdma_alloc(CPHYSADDR(page_address(sg[sz].page) + sg[sz].offset), sg[sz].length);
- sz--;
- }
- sp->SCp.ptr=(char *)(sp->SCp.buffer->dma_address);
-}
-
-static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp)
+static int jazz_esp_dma_error(struct esp *esp)
{
- vdma_free(sp->SCp.have_data_in);
+ u32 enable = vdma_get_enable((int)esp->dma_regs);
+
+ if (enable & (R4030_MEM_INTR|R4030_ADDR_INTR))
+ return 1;
+
+ return 0;
}
-static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp)
+static const struct esp_driver_ops jazz_esp_ops = {
+ .esp_write8 = jazz_esp_write8,
+ .esp_read8 = jazz_esp_read8,
+ .map_single = jazz_esp_map_single,
+ .map_sg = jazz_esp_map_sg,
+ .unmap_single = jazz_esp_unmap_single,
+ .unmap_sg = jazz_esp_unmap_sg,
+ .irq_pending = jazz_esp_irq_pending,
+ .reset_dma = jazz_esp_reset_dma,
+ .dma_drain = jazz_esp_dma_drain,
+ .dma_invalidate = jazz_esp_dma_invalidate,
+ .send_dma_cmd = jazz_esp_send_dma_cmd,
+ .dma_error = jazz_esp_dma_error,
+};
+
+static int __devinit esp_jazz_probe(struct platform_device *dev)
{
- int sz = sp->use_sg - 1;
- struct scatterlist *sg = (struct scatterlist *)sp->request_buffer;
-
- while(sz >= 0) {
- vdma_free(sg[sz].dma_address);
- sz--;
- }
+ struct scsi_host_template *tpnt = &scsi_esp_template;
+ struct Scsi_Host *host;
+ struct esp *esp;
+ struct resource *res;
+ int err;
+
+ host = scsi_host_alloc(tpnt, sizeof(struct esp));
+
+ err = -ENOMEM;
+ if (!host)
+ goto fail;
+
+ host->max_id = 8;
+ esp = host_to_esp(host);
+
+ esp->host = host;
+ esp->dev = dev;
+ esp->ops = &jazz_esp_ops;
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res)
+ goto fail_unlink;
+
+ esp->regs = (void __iomem *)res->start;
+ if (!esp->regs)
+ goto fail_unlink;
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 1);
+ if (!res)
+ goto fail_unlink;
+
+ esp->dma_regs = (void __iomem *)res->start;
+
+ esp->command_block = dma_alloc_coherent(esp->dev, 16,
+ &esp->command_block_dma,
+ GFP_KERNEL);
+ if (!esp->command_block)
+ goto fail_unmap_regs;
+
+ host->irq = platform_get_irq(dev, 0);
+ err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
+ if (err < 0)
+ goto fail_unmap_command_block;
+
+ esp->scsi_id = 7;
+ esp->host->this_id = esp->scsi_id;
+ esp->scsi_id_mask = (1 << esp->scsi_id);
+ esp->cfreq = 40000000;
+
+ dev_set_drvdata(&dev->dev, esp);
+
+ err = scsi_esp_register(esp, &dev->dev);
+ if (err)
+ goto fail_free_irq;
+
+ return 0;
+
+fail_free_irq:
+ free_irq(host->irq, esp);
+fail_unmap_command_block:
+ dma_free_coherent(esp->dev, 16,
+ esp->command_block,
+ esp->command_block_dma);
+fail_unmap_regs:
+fail_unlink:
+ scsi_host_put(host);
+fail:
+ return err;
}
-static void dma_advance_sg (struct scsi_cmnd *sp)
+static int __devexit esp_jazz_remove(struct platform_device *dev)
{
- sp->SCp.ptr = (char *)(sp->SCp.buffer->dma_address);
+ struct esp *esp = dev_get_drvdata(&dev->dev);
+ unsigned int irq = esp->host->irq;
+
+ scsi_esp_unregister(esp);
+
+ free_irq(irq, esp);
+ dma_free_coherent(esp->dev, 16,
+ esp->command_block,
+ esp->command_block_dma);
+
+ scsi_host_put(esp->host);
+
+ return 0;
}
-#define JAZZ_HDC_LED 0xe000d100 /* FIXME, find correct address */
+static struct platform_driver esp_jazz_driver = {
+ .probe = esp_jazz_probe,
+ .remove = __devexit_p(esp_jazz_remove),
+ .driver = {
+ .name = "jazz_esp",
+ },
+};
-static void dma_led_off(struct NCR_ESP *esp)
+static int __init jazz_esp_init(void)
{
-#if 0
- *(unsigned char *)JAZZ_HDC_LED = 0;
-#endif
+ return platform_driver_register(&esp_jazz_driver);
}
-static void dma_led_on(struct NCR_ESP *esp)
-{
-#if 0
- *(unsigned char *)JAZZ_HDC_LED = 1;
-#endif
+static void __exit jazz_esp_exit(void)
+{
+ platform_driver_unregister(&esp_jazz_driver);
}
-static struct scsi_host_template driver_template = {
- .proc_name = "jazz_esp",
- .proc_info = esp_proc_info,
- .name = "ESP 100/100a/200",
- .detect = jazz_esp_detect,
- .slave_alloc = esp_slave_alloc,
- .slave_destroy = esp_slave_destroy,
- .release = jazz_esp_release,
- .info = esp_info,
- .queuecommand = esp_queue,
- .eh_abort_handler = esp_abort,
- .eh_bus_reset_handler = esp_reset,
- .can_queue = 7,
- .this_id = 7,
- .sg_tablesize = SG_ALL,
- .cmd_per_lun = 1,
- .use_clustering = DISABLE_CLUSTERING,
-};
-#include "scsi_module.c"
+MODULE_DESCRIPTION("JAZZ ESP SCSI driver");
+MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(jazz_esp_init);
+module_exit(jazz_esp_exit);
diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c
index 5631c19..732446e 100644
--- a/drivers/scsi/libsrp.c
+++ b/drivers/scsi/libsrp.c
@@ -254,6 +254,7 @@ static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd,
sg_init_one(&dummy, md, id->table_desc.len);
sg_dma_address(&dummy) = token;
+ sg_dma_len(&dummy) = id->table_desc.len;
err = rdma_io(sc, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE,
id->table_desc.len);
if (err) {
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 7a81267..e2cf12e 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -10,7 +10,7 @@
* 2 of the License, or (at your option) any later version.
*
* FILE : megaraid_sas.c
- * Version : v00.00.03.10-rc1
+ * Version : v00.00.03.10-rc5
*
* Authors:
* (email-id : megaraidlinux@lsi.com)
@@ -886,6 +886,7 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
goto out_return_cmd;
cmd->scmd = scmd;
+ scmd->SCp.ptr = (char *)cmd;
/*
* Issue the command to the FW
@@ -919,7 +920,7 @@ static int megasas_slave_configure(struct scsi_device *sdev)
* The RAID firmware may require extended timeouts.
*/
if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS)
- sdev->timeout = 90 * HZ;
+ sdev->timeout = MEGASAS_DEFAULT_CMD_TIMEOUT * HZ;
return 0;
}
@@ -981,8 +982,8 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd)
instance = (struct megasas_instance *)scmd->device->host->hostdata;
- scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x\n",
- scmd->serial_number, scmd->cmnd[0]);
+ scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
+ scmd->serial_number, scmd->cmnd[0], scmd->retries);
if (instance->hw_crit_error) {
printk(KERN_ERR "megasas: cannot recover from previous reset "
@@ -1000,6 +1001,39 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd)
}
/**
+ * megasas_reset_timer - quiesce the adapter if required
+ * @scmd: scsi cmnd
+ *
+ * Sets the FW busy flag and reduces the host->can_queue if the
+ * cmd has not been completed within the timeout period.
+ */
+static enum
+scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
+{
+ struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
+ struct megasas_instance *instance;
+ unsigned long flags;
+
+ if (time_after(jiffies, scmd->jiffies_at_alloc +
+ (MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) {
+ return EH_NOT_HANDLED;
+ }
+
+ instance = cmd->instance;
+ if (!(instance->flag & MEGASAS_FW_BUSY)) {
+ /* FW is busy, throttle IO */
+ spin_lock_irqsave(instance->host->host_lock, flags);
+
+ instance->host->can_queue = 16;
+ instance->last_time = jiffies;
+ instance->flag |= MEGASAS_FW_BUSY;
+
+ spin_unlock_irqrestore(instance->host->host_lock, flags);
+ }
+ return EH_RESET_TIMER;
+}
+
+/**
* megasas_reset_device - Device reset handler entry point
*/
static int megasas_reset_device(struct scsi_cmnd *scmd)
@@ -1112,6 +1146,7 @@ static struct scsi_host_template megasas_template = {
.eh_device_reset_handler = megasas_reset_device,
.eh_bus_reset_handler = megasas_reset_bus_host,
.eh_host_reset_handler = megasas_reset_bus_host,
+ .eh_timed_out = megasas_reset_timer,
.bios_param = megasas_bios_param,
.use_clustering = ENABLE_CLUSTERING,
};
@@ -1215,9 +1250,8 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
int exception = 0;
struct megasas_header *hdr = &cmd->frame->hdr;
- if (cmd->scmd) {
- cmd->scmd->SCp.ptr = (char *)0;
- }
+ if (cmd->scmd)
+ cmd->scmd->SCp.ptr = NULL;
switch (hdr->cmd) {
@@ -1806,6 +1840,7 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
u32 context;
struct megasas_cmd *cmd;
struct megasas_instance *instance = (struct megasas_instance *)instance_addr;
+ unsigned long flags;
/* If we have already declared adapter dead, donot complete cmds */
if (instance->hw_crit_error)
@@ -1828,6 +1863,22 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr)
}
*instance->consumer = producer;
+
+ /*
+ * Check if we can restore can_queue
+ */
+ if (instance->flag & MEGASAS_FW_BUSY
+ && time_after(jiffies, instance->last_time + 5 * HZ)
+ && atomic_read(&instance->fw_outstanding) < 17) {
+
+ spin_lock_irqsave(instance->host->host_lock, flags);
+ instance->flag &= ~MEGASAS_FW_BUSY;
+ instance->host->can_queue =
+ instance->max_fw_cmds - MEGASAS_INT_CMDS;
+
+ spin_unlock_irqrestore(instance->host->host_lock, flags);
+ }
+
}
/**
@@ -2398,6 +2449,8 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
instance->init_id = MEGASAS_DEFAULT_INIT_ID;
megasas_dbg_lvl = 0;
+ instance->flag = 0;
+ instance->last_time = 0;
/*
* Initialize MFI Firmware
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index e862992..4dffc91 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -18,9 +18,9 @@
/*
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "00.00.03.10-rc1"
-#define MEGASAS_RELDATE "Feb 14, 2007"
-#define MEGASAS_EXT_VERSION "Wed Feb 14 10:14:25 PST 2007"
+#define MEGASAS_VERSION "00.00.03.10-rc5"
+#define MEGASAS_RELDATE "May 17, 2007"
+#define MEGASAS_EXT_VERSION "Thu May 17 10:09:32 PDT 2007"
/*
* Device IDs
@@ -539,6 +539,8 @@ struct megasas_ctrl_info {
#define MEGASAS_DBG_LVL 1
+#define MEGASAS_FW_BUSY 1
+
/*
* When SCSI mid-layer calls driver's reset routine, driver waits for
* MEGASAS_RESET_WAIT_TIME seconds for all outstanding IO to complete. Note
@@ -549,8 +551,8 @@ struct megasas_ctrl_info {
#define MEGASAS_RESET_WAIT_TIME 180
#define MEGASAS_INTERNAL_CMD_WAIT_TIME 180
#define MEGASAS_RESET_NOTICE_INTERVAL 5
-
#define MEGASAS_IOCTL_CMD 0
+#define MEGASAS_DEFAULT_CMD_TIMEOUT 90
/*
* FW reports the maximum of number of commands that it can accept (maximum
@@ -1073,7 +1075,6 @@ struct megasas_instance {
struct megasas_register_set __iomem *reg_set;
s8 init_id;
- u8 reserved[3];
u16 max_num_sge;
u16 max_fw_cmds;
@@ -1104,6 +1105,9 @@ struct megasas_instance {
struct megasas_instance_template *instancet;
struct tasklet_struct isr_tasklet;
+
+ u8 flag;
+ unsigned long last_time;
};
#define MEGASAS_IS_LOGICAL(scp) \
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
index 3b2e1a5..d953d43 100644
--- a/drivers/scsi/pluto.c
+++ b/drivers/scsi/pluto.c
@@ -4,6 +4,7 @@
*
*/
+#include <linux/completion.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/types.h>
@@ -50,16 +51,10 @@ static struct ctrl_inquiry {
} *fcs __initdata;
static int fcscount __initdata = 0;
static atomic_t fcss __initdata = ATOMIC_INIT(0);
-DECLARE_MUTEX_LOCKED(fc_sem);
+static DECLARE_COMPLETION(fc_detect_complete);
static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
-static void __init pluto_detect_timeout(unsigned long data)
-{
- PLND(("Timeout\n"))
- up(&fc_sem);
-}
-
static void __init pluto_detect_done(Scsi_Cmnd *SCpnt)
{
/* Do nothing */
@@ -69,7 +64,7 @@ static void __init pluto_detect_scsi_done(Scsi_Cmnd *SCpnt)
{
PLND(("Detect done %08lx\n", (long)SCpnt))
if (atomic_dec_and_test (&fcss))
- up(&fc_sem);
+ complete(&fc_detect_complete);
}
int pluto_slave_configure(struct scsi_device *device)
@@ -96,7 +91,6 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
int i, retry, nplutos;
fc_channel *fc;
struct scsi_device dev;
- DEFINE_TIMER(fc_timer, pluto_detect_timeout, 0, 0);
tpnt->proc_name = "pluto";
fcscount = 0;
@@ -187,15 +181,11 @@ int __init pluto_detect(struct scsi_host_template *tpnt)
}
}
- fc_timer.expires = jiffies + 10 * HZ;
- add_timer(&fc_timer);
-
- down(&fc_sem);
+ wait_for_completion_timeout(&fc_detect_complete, 10 * HZ);
PLND(("Woken up\n"))
if (!atomic_read(&fcss))
break; /* All fc channels have answered us */
}
- del_timer_sync(&fc_timer);
PLND(("Finished search\n"))
for (i = 0, nplutos = 0; i < fcscount; i++) {
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index ce63044..18dd5cc 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -209,6 +209,7 @@ static struct {
{"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
{"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
{"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+ {"Promise", "", NULL, BLIST_SPARSELUN},
{"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN},
{"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN},
{"SEAGATE", "ST34555N", "0930", BLIST_NOTQ}, /* Chokes on tagged INQUIRY */
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 00e4666..3d8c9cb 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1789,7 +1789,7 @@ static void sd_shutdown(struct device *dev)
static int sd_suspend(struct device *dev, pm_message_t mesg)
{
struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
- int ret;
+ int ret = 0;
if (!sdkp)
return 0; /* this can happen */
@@ -1798,30 +1798,34 @@ static int sd_suspend(struct device *dev, pm_message_t mesg)
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
ret = sd_sync_cache(sdkp);
if (ret)
- return ret;
+ goto done;
}
if (mesg.event == PM_EVENT_SUSPEND &&
sdkp->device->manage_start_stop) {
sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
ret = sd_start_stop_device(sdkp, 0);
- if (ret)
- return ret;
}
- return 0;
+done:
+ scsi_disk_put(sdkp);
+ return ret;
}
static int sd_resume(struct device *dev)
{
struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
+ int ret = 0;
if (!sdkp->device->manage_start_stop)
- return 0;
+ goto done;
sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
+ ret = sd_start_stop_device(sdkp, 1);
- return sd_start_stop_device(sdkp, 1);
+done:
+ scsi_disk_put(sdkp);
+ return ret;
}
/**
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 69be132..9ac83ab 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -32,11 +32,12 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_dbg.h>
#define DRV_NAME "stex"
-#define ST_DRIVER_VERSION "3.1.0.1"
+#define ST_DRIVER_VERSION "3.6.0000.1"
#define ST_VER_MAJOR 3
-#define ST_VER_MINOR 1
+#define ST_VER_MINOR 6
#define ST_OEM 0
#define ST_BUILD_VER 1
@@ -113,10 +114,6 @@ enum {
SG_CF_64B = 0x40, /* 64 bit item */
SG_CF_HOST = 0x20, /* sg in host memory */
- ST_MAX_ARRAY_SUPPORTED = 16,
- ST_MAX_TARGET_NUM = (ST_MAX_ARRAY_SUPPORTED+1),
- ST_MAX_LUN_PER_TARGET = 16,
-
st_shasta = 0,
st_vsc = 1,
st_vsc1 = 2,
@@ -586,7 +583,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
u16 tag;
host = cmd->device->host;
id = cmd->device->id;
- lun = cmd->device->channel; /* firmware lun issue work around */
+ lun = cmd->device->lun;
hba = (struct st_hba *) &host->hostdata[0];
switch (cmd->cmnd[0]) {
@@ -605,8 +602,26 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
stex_invalid_field(cmd, done);
return 0;
}
+ case REPORT_LUNS:
+ /*
+ * The shasta firmware does not report actual luns in the
+ * target, so fail the command to force sequential lun scan.
+ * Also, the console device does not support this command.
+ */
+ if (hba->cardtype == st_shasta || id == host->max_id - 1) {
+ stex_invalid_field(cmd, done);
+ return 0;
+ }
+ break;
+ case TEST_UNIT_READY:
+ if (id == host->max_id - 1) {
+ cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+ done(cmd);
+ return 0;
+ }
+ break;
case INQUIRY:
- if (id != ST_MAX_ARRAY_SUPPORTED)
+ if (id != host->max_id - 1)
break;
if (lun == 0 && (cmd->cmnd[1] & INQUIRY_EVPD) == 0) {
stex_direct_copy(cmd, console_inq_page,
@@ -624,7 +639,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
ver.oem = ST_OEM;
ver.build = ST_BUILD_VER;
ver.signature[0] = PASSTHRU_SIGNATURE;
- ver.console_id = ST_MAX_ARRAY_SUPPORTED;
+ ver.console_id = host->max_id - 1;
ver.host_no = hba->host->host_no;
cmd->result = stex_direct_copy(cmd, &ver, sizeof(ver)) ?
DID_OK << 16 | COMMAND_COMPLETE << 8 :
@@ -645,13 +660,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
req = stex_alloc_req(hba);
- if (hba->cardtype == st_yosemite) {
- req->lun = lun * (ST_MAX_TARGET_NUM - 1) + id;
- req->target = 0;
- } else {
- req->lun = lun;
- req->target = id;
- }
+ req->lun = lun;
+ req->target = id;
/* cdb */
memcpy(req->cdb, cmd->cmnd, STEX_CDB_LENGTH);
@@ -767,18 +777,6 @@ static void stex_ys_commands(struct st_hba *hba,
ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT;
else
ccb->srb_status = SRB_STATUS_SUCCESS;
- } else if (ccb->cmd->cmnd[0] == REPORT_LUNS) {
- u8 *report_lun_data = (u8 *)hba->copy_buffer;
-
- count = STEX_EXTRA_SIZE;
- stex_internal_copy(ccb->cmd, report_lun_data,
- &count, ccb->sg_count, ST_FROM_CMD);
- if (report_lun_data[2] || report_lun_data[3]) {
- report_lun_data[2] = 0x00;
- report_lun_data[3] = 0x08;
- stex_internal_copy(ccb->cmd, report_lun_data,
- &count, ccb->sg_count, ST_TO_CMD);
- }
}
}
@@ -995,6 +993,11 @@ static int stex_abort(struct scsi_cmnd *cmd)
u32 data;
int result = SUCCESS;
unsigned long flags;
+
+ printk(KERN_INFO DRV_NAME
+ "(%s): aborting command\n", pci_name(hba->pdev));
+ scsi_print_command(cmd);
+
base = hba->mmio_base;
spin_lock_irqsave(host->host_lock, flags);
if (tag < host->can_queue && hba->ccb[tag].cmd == cmd)
@@ -1051,7 +1054,12 @@ static void stex_hard_reset(struct st_hba *hba)
pci_read_config_byte(bus->self, PCI_BRIDGE_CONTROL, &pci_bctl);
pci_bctl |= PCI_BRIDGE_CTL_BUS_RESET;
pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, pci_bctl);
- msleep(1);
+
+ /*
+ * 1 ms may be enough for 8-port controllers. But 16-port controllers
+ * require more time to finish bus reset. Use 100 ms here for safety
+ */
+ msleep(100);
pci_bctl &= ~PCI_BRIDGE_CTL_BUS_RESET;
pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, pci_bctl);
@@ -1075,6 +1083,10 @@ static int stex_reset(struct scsi_cmnd *cmd)
unsigned long before;
hba = (struct st_hba *) &cmd->device->host->hostdata[0];
+ printk(KERN_INFO DRV_NAME
+ "(%s): resetting host\n", pci_name(hba->pdev));
+ scsi_print_command(cmd);
+
hba->mu_status = MU_STATE_RESETTING;
if (hba->cardtype == st_shasta)
@@ -1194,7 +1206,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_scsi_host_put;
}
- hba->mmio_base = ioremap(pci_resource_start(pdev, 0),
+ hba->mmio_base = ioremap_nocache(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
if ( !hba->mmio_base) {
printk(KERN_ERR DRV_NAME "(%s): memory map failed\n",
@@ -1229,12 +1241,18 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hba->copy_buffer = hba->dma_mem + MU_BUFFER_SIZE;
hba->mu_status = MU_STATE_STARTING;
- /* firmware uses id/lun pair for a logical drive, but lun would be
- always 0 if CONFIG_SCSI_MULTI_LUN not configured, so we use
- channel to map lun here */
- host->max_channel = ST_MAX_LUN_PER_TARGET - 1;
- host->max_id = ST_MAX_TARGET_NUM;
- host->max_lun = 1;
+ if (hba->cardtype == st_shasta) {
+ host->max_lun = 8;
+ host->max_id = 16 + 1;
+ } else if (hba->cardtype == st_yosemite) {
+ host->max_lun = 128;
+ host->max_id = 1 + 1;
+ } else {
+ /* st_vsc and st_vsc1 */
+ host->max_lun = 1;
+ host->max_id = 128 + 1;
+ }
+ host->max_channel = 0;
host->unique_id = host->host_no;
host->max_cmd_len = STEX_CDB_LENGTH;