From f67a9c1592b3a0292376bdcbdcc34cbe353967a8 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Mon, 25 Dec 2006 21:30:08 +0100 Subject: [SCSI] 53c700: Allow setting burst length This is a patch, which allows not only disabling bursting but to specify different burst lenghts. This feature is needed to get the 53c700 driver working for the onboard SCSI controller of SNI RM machines, which only work reliably with a 4 word burst length. Signed-off-by: James Bottomley --- drivers/scsi/53c700.c | 24 +++++++++++++++++++++--- drivers/scsi/53c700.h | 2 +- drivers/scsi/lasi700.c | 1 + drivers/scsi/sim710.c | 1 + 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 68103e508db7..88e061d13d0b 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -667,12 +667,30 @@ NCR_700_chip_setup(struct Scsi_Host *host) __u8 min_xferp = (hostdata->chip710 ? NCR_710_MIN_XFERP : NCR_700_MIN_XFERP); if(hostdata->chip710) { - __u8 burst_disable = hostdata->burst_disable - ? BURST_DISABLE : 0; + __u8 burst_disable = 0; + __u8 burst_length = 0; + + switch (hostdata->burst_length) { + case 1: + burst_length = BURST_LENGTH_1; + break; + case 2: + burst_length = BURST_LENGTH_2; + break; + case 4: + burst_length = BURST_LENGTH_4; + break; + case 8: + burst_length = BURST_LENGTH_8; + break; + default: + burst_disable = BURST_DISABLE; + break; + } dcntl_extra = COMPAT_700_MODE; NCR_700_writeb(dcntl_extra, host, DCNTL_REG); - NCR_700_writeb(BURST_LENGTH_8 | hostdata->dmode_extra, + NCR_700_writeb(burst_length | hostdata->dmode_extra, host, DMODE_710_REG); NCR_700_writeb(burst_disable | (hostdata->differential ? DIFF : 0), host, CTEST7_REG); diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h index f38822db4210..841e1bb27d57 100644 --- a/drivers/scsi/53c700.h +++ b/drivers/scsi/53c700.h @@ -203,7 +203,7 @@ struct NCR_700_Host_Parameters { __u32 force_le_on_be:1; #endif __u32 chip710:1; /* set if really a 710 not 700 */ - __u32 burst_disable:1; /* set to 1 to disable 710 bursting */ + __u32 burst_length:4; /* set to 0 to disable 710 bursting */ /* NOTHING BELOW HERE NEEDS ALTERING */ __u32 fast:1; /* if we can alter the SCSI bus clock diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index f0871c3ac3d9..2aae1b081fcf 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -123,6 +123,7 @@ lasi700_probe(struct parisc_device *dev) hostdata->force_le_on_be = 0; hostdata->chip710 = 1; hostdata->dmode_extra = DMODE_FC2; + hostdata->burst_length = 8; } host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev); diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c index 551baccec523..018c65f73ac4 100644 --- a/drivers/scsi/sim710.c +++ b/drivers/scsi/sim710.c @@ -123,6 +123,7 @@ sim710_probe_common(struct device *dev, unsigned long base_addr, hostdata->differential = differential; hostdata->clock = clock; hostdata->chip710 = 1; + hostdata->burst_length = 8; /* and register the chip */ if((host = NCR_700_detect(&sim710_driver_template, hostdata, dev)) -- cgit v1.2.3 From 3b1ca5a12ce9849a794019c4b51cdbd456c1e8e7 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 13 Jan 2007 13:46:51 -0600 Subject: [SCSI] NCR_D700: needs burst length setting to 8 The D700 needs the burst length setting to the previous 53c700 default of 8 otherwise it will be effectively disabled. Signed-off-by: James Bottomley --- drivers/scsi/NCR_D700.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c index 9859cd17fc57..01967a59479d 100644 --- a/drivers/scsi/NCR_D700.c +++ b/drivers/scsi/NCR_D700.c @@ -200,6 +200,7 @@ NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq, hostdata->base = ioport_map(region, 64); hostdata->differential = (((1<clock = NCR_D700_CLOCK_MHZ; + hostdata->busrt_length = 8; /* and register the siop */ host = NCR_700_detect(&NCR_D700_driver_template, hostdata, p->dev); -- cgit v1.2.3 From c27d85f3f3c5c663d6b6295730e8a7c0c3f9a296 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Mon, 25 Dec 2006 21:32:04 +0100 Subject: [SCSI] SNI RM 53c710 driver This patch adds a SCSI driver for the onboard 53c710 chip of some SNI RM machines. Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 9 +++ drivers/scsi/Makefile | 1 + drivers/scsi/sni_53c710.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 drivers/scsi/sni_53c710.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 60f582727185..0133f3a6977d 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -973,6 +973,15 @@ config SCSI_LASI700 many PA-RISC workstations & servers. If you do not know whether you have a Lasi chip, it is safe to say "Y" here. +config SCSI_SNI_53C710 + tristate "SNI RM SCSI support for 53c710" + depends on SNI_RM && SCSI + select SCSI_SPI_ATTRS + select 53C700_LE_ON_BE + help + This is a driver for the onboard SCSI controller found in older + SNI RM workstations & servers. + config 53C700_LE_ON_BE bool depends on SCSI_LASI700 diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index bd7c9888f7f4..79ecf4ebe6eb 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -124,6 +124,7 @@ obj-$(CONFIG_JAZZ_ESP) += NCR53C9x.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 +obj-$(CONFIG_SCSI_SNI_53C710) += 53c700.o sni_53c710.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o obj-$(CONFIG_SCSI_IPR) += ipr.o obj-$(CONFIG_SCSI_SRP) += libsrp.o diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c new file mode 100644 index 000000000000..6bc505115841 --- /dev/null +++ b/drivers/scsi/sni_53c710.c @@ -0,0 +1,159 @@ +/* -*- mode: c; c-basic-offset: 8 -*- */ + +/* SNI RM driver + * + * Copyright (C) 2001 by James.Bottomley@HansenPartnership.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 +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +** +**----------------------------------------------------------------------------- + */ + +/* + * Based on lasi700.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "53c700.h" + +MODULE_AUTHOR("Thomas Bogendörfer"); +MODULE_DESCRIPTION("SNI RM 53c710 SCSI Driver"); +MODULE_LICENSE("GPL"); + +#define SNIRM710_CLOCK 32 + +static struct scsi_host_template snirm710_template = { + .name = "SNI RM SCSI 53c710", + .proc_name = "snirm_53c710", + .this_id = 7, + .module = THIS_MODULE, +}; + +static int __init snirm710_probe(struct platform_device *dev) +{ + unsigned long base; + struct NCR_700_Host_Parameters *hostdata; + struct Scsi_Host *host; + struct resource *res; + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + base = res->start; + hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL); + if (!hostdata) { + printk(KERN_ERR "%s: Failed to allocate host data\n", + dev->dev.bus_id); + return -ENOMEM; + } + + hostdata->dev = &dev->dev; + dma_set_mask(&dev->dev, DMA_32BIT_MASK); + hostdata->base = ioremap_nocache(CPHYSADDR(base), 0x100); + hostdata->differential = 0; + + hostdata->clock = SNIRM710_CLOCK; + hostdata->force_le_on_be = 1; + hostdata->chip710 = 1; + hostdata->burst_length = 4; + + host = NCR_700_detect(&snirm710_template, hostdata, &dev->dev); + if (!host) + goto out_kfree; + host->this_id = 7; + host->base = base; + host->irq = platform_get_irq(dev, 0); + if(request_irq(host->irq, NCR_700_intr, SA_SHIRQ, "snirm710", host)) { + printk(KERN_ERR "snirm710: request_irq failed!\n"); + goto out_put_host; + } + + dev_set_drvdata(&dev->dev, host); + scsi_scan_host(host); + + return 0; + + out_put_host: + scsi_host_put(host); + out_kfree: + iounmap(hostdata->base); + kfree(hostdata); + return -ENODEV; +} + +static int __exit snirm710_driver_remove(struct platform_device *dev) +{ + struct Scsi_Host *host = dev_get_drvdata(&dev->dev); + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)host->hostdata[0]; + + scsi_remove_host(host); + NCR_700_release(host); + free_irq(host->irq, host); + iounmap(hostdata->base); + kfree(hostdata); + + return 0; +} + +static struct platform_driver snirm710_driver = { + .probe = snirm710_probe, + .remove = __devexit_p(snirm710_driver_remove), + .driver = { + .name = "snirm_53c710", + }, +}; + +static int __init snirm710_init(void) +{ + int err; + + if ((err = platform_driver_register(&snirm710_driver))) { + printk(KERN_ERR "Driver registration failed\n"); + return err; + } + return 0; +} + +static void __exit snirm710_exit(void) +{ + platform_driver_unregister(&snirm710_driver); +} + +module_init(snirm710_init); +module_exit(snirm710_exit); -- cgit v1.2.3 From 596f482a90ae27ea1b3da6a12ee42909045fbfd0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 2 Jan 2007 12:56:00 +0100 Subject: [SCSI] kill scsi_rety_command scsi_retry_command only has a single caller, so there is no point in having this function. Additionally the memset of the sense buffer it does is entirely superflous as scsi_request_fn already calls scsi_init_cmd_errh to perform this memset before the command is reissued. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/scsi/scsi.c | 21 --------------------- drivers/scsi/scsi_lib.c | 2 +- drivers/scsi/scsi_priv.h | 1 - 3 files changed, 1 insertion(+), 23 deletions(-) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 24cffd98ee63..f33e2eb9f1b9 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -672,27 +672,6 @@ void __scsi_done(struct scsi_cmnd *cmd) blk_complete_request(rq); } -/* - * Function: scsi_retry_command - * - * Purpose: Send a command back to the low level to be retried. - * - * Notes: This command is always executed in the context of the - * bottom half handler, or the error handler thread. Low - * level drivers should not become re-entrant as a result of - * this. - */ -int scsi_retry_command(struct scsi_cmnd *cmd) -{ - /* - * Zero the sense information from the last time we tried - * this command. - */ - memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); - - return scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY); -} - /* * Function: scsi_finish_command * diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index f02f48a882a9..503f09c2f05f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1400,7 +1400,7 @@ static void scsi_softirq_done(struct request *rq) scsi_finish_command(cmd); break; case NEEDS_RETRY: - scsi_retry_command(cmd); + scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY); break; case ADD_TO_MLQUEUE: scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index f458c2f686d2..d4faa19609d9 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -28,7 +28,6 @@ extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); extern int scsi_setup_command_freelist(struct Scsi_Host *shost); extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); extern void __scsi_done(struct scsi_cmnd *cmd); -extern int scsi_retry_command(struct scsi_cmnd *cmd); #ifdef CONFIG_SCSI_LOGGING void scsi_log_send(struct scsi_cmnd *cmd); void scsi_log_completion(struct scsi_cmnd *cmd, int disposition); -- cgit v1.2.3 From d780c3bf2150264947870bb68c057c26c2aff7cc Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Thu, 4 Jan 2007 23:48:54 -0500 Subject: [SCSI] mptctl for mptsas This patch makes the mptctl pass through available if the mptsas driver is selected. Without this patch if mptsas is the only fusion driver chosen, then the mptctl is not presented as an option. smp_utils uses the mptctl driver to pass SAS SMP functions through a MPT SAS HBA. Signed-off-by: Douglas Gilbert Acked-by: "Moore, Eric" Signed-off-by: James Bottomley --- drivers/message/fusion/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index ea31d8470510..71037f91c222 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig @@ -66,7 +66,7 @@ config FUSION_MAX_SGE config FUSION_CTL tristate "Fusion MPT misc device (ioctl) driver" - depends on FUSION_SPI || FUSION_FC + depends on FUSION_SPI || FUSION_FC || FUSION_SAS ---help--- The Fusion MPT misc device driver provides specialized control of MPT adapters via system ioctl calls. Use of ioctl calls to -- cgit v1.2.3 From 6f3cbf552e0557a463ad421f07b2e873a608406f Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Fri, 5 Jan 2007 00:05:25 -0500 Subject: [SCSI] scsi_debug: error processing After discussions in the thread titled: [PATCH] scsi_debug: illegal blocking memory allocation here is a patch containing the discussed fix and some other fixes and additions. The patch is against lk 2.6.20-rc3 . The version is bumped to 1.81 . ChangeLog: - Change several GFP_KERNEL allocations to GFP_ATOMIC as they can be called from queuecommand() context - check above allocation returns and if out of memory report DID_REQUEUE in two cases, DID_NO_CONNECT in another, and fail slave configure() in another - add support for WRITE BUFFER command - add aborted_command error injection support (opts mask 0x10), similar mechanism to recovered_error injection. Signed-off-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 30ee3d72c021..5adbbeedec38 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -51,10 +51,10 @@ #include "scsi_logging.h" #include "scsi_debug.h" -#define SCSI_DEBUG_VERSION "1.80" -static const char * scsi_debug_version_date = "20061018"; +#define SCSI_DEBUG_VERSION "1.81" +static const char * scsi_debug_version_date = "20070104"; -/* Additional Sense Code (ASC) used */ +/* Additional Sense Code (ASC) */ #define NO_ADDITIONAL_SENSE 0x0 #define LOGICAL_UNIT_NOT_READY 0x4 #define UNRECOVERED_READ_ERR 0x11 @@ -65,9 +65,13 @@ static const char * scsi_debug_version_date = "20061018"; #define INVALID_FIELD_IN_PARAM_LIST 0x26 #define POWERON_RESET 0x29 #define SAVING_PARAMS_UNSUP 0x39 +#define TRANSPORT_PROBLEM 0x4b #define THRESHOLD_EXCEEDED 0x5d #define LOW_POWER_COND_ON 0x5e +/* Additional Sense Code Qualifier (ASCQ) */ +#define ACK_NAK_TO 0x3 + #define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ /* Default values for driver parameters */ @@ -95,15 +99,20 @@ static const char * scsi_debug_version_date = "20061018"; #define SCSI_DEBUG_OPT_MEDIUM_ERR 2 #define SCSI_DEBUG_OPT_TIMEOUT 4 #define SCSI_DEBUG_OPT_RECOVERED_ERR 8 +#define SCSI_DEBUG_OPT_TRANSPORT_ERR 16 /* When "every_nth" > 0 then modulo "every_nth" commands: * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. + * - a TRANSPORT_ERROR is simulated on successful read and write + * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set. * * When "every_nth" < 0 then after "- every_nth" commands: * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. + * - a TRANSPORT_ERROR is simulated on successful read and write + * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set. * This will continue until some other action occurs (e.g. the user * writing a new value (other than -1 or 1) to every_nth via sysfs). */ @@ -315,6 +324,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) int target = SCpnt->device->id; struct sdebug_dev_info * devip = NULL; int inj_recovered = 0; + int inj_transport = 0; int delay_override = 0; if (done == NULL) @@ -352,6 +362,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) return 0; /* ignore command causing timeout */ else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts) inj_recovered = 1; /* to reads and writes below */ + else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts) + inj_transport = 1; /* to reads and writes below */ } if (devip->wlun) { @@ -468,7 +480,11 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) mk_sense_buffer(devip, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); errsts = check_condition_result; - } + } else if (inj_transport && (0 == errsts)) { + mk_sense_buffer(devip, ABORTED_COMMAND, + TRANSPORT_PROBLEM, ACK_NAK_TO); + errsts = check_condition_result; + } break; case REPORT_LUNS: /* mandatory, ignore unit attention */ delay_override = 1; @@ -531,6 +547,9 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) delay_override = 1; errsts = check_readiness(SCpnt, 0, devip); break; + case WRITE_BUFFER: + errsts = check_readiness(SCpnt, 1, devip); + break; default: if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " @@ -954,7 +973,9 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, int alloc_len, n, ret; alloc_len = (cmd[3] << 8) + cmd[4]; - arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_KERNEL); + arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC); + if (! arr) + return DID_REQUEUE << 16; if (devip->wlun) pq_pdt = 0x1e; /* present, wlun */ else if (scsi_debug_no_lun_0 && (0 == devip->lun)) @@ -1217,7 +1238,9 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp, alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8) + cmd[9]); - arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_KERNEL); + arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC); + if (! arr) + return DID_REQUEUE << 16; /* * EVPD page 0x88 states we have two ports, one * real and a fake port with no device connected. @@ -1996,6 +2019,8 @@ static int scsi_debug_slave_configure(struct scsi_device * sdp) if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; devip = devInfoReg(sdp); + if (NULL == devip) + return 1; /* no resources, will be marked offline */ sdp->hostdata = devip; if (sdp->host->cmd_per_lun) scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING, @@ -2044,7 +2069,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) } } if (NULL == open_devip) { /* try and make a new one */ - open_devip = kzalloc(sizeof(*open_devip),GFP_KERNEL); + open_devip = kzalloc(sizeof(*open_devip),GFP_ATOMIC); if (NULL == open_devip) { printk(KERN_ERR "%s: out of memory at line %d\n", __FUNCTION__, __LINE__); @@ -2388,7 +2413,7 @@ MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)"); MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)"); MODULE_PARM_DESC(num_parts, "number of partitions(def=0)"); MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)"); -MODULE_PARM_DESC(opts, "1->noise, 2->medium_error, 4->... (def=0)"); +MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)"); MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])"); MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); @@ -2943,7 +2968,6 @@ static int sdebug_add_adapter(void) struct list_head *lh, *lh_sf; sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL); - if (NULL == sdbg_host) { printk(KERN_ERR "%s: out of memory at line %d\n", __FUNCTION__, __LINE__); -- cgit v1.2.3 From cd96d96f20f2509dfeb302548132e30f471c071a Mon Sep 17 00:00:00 2001 From: Sumant Patro Date: Fri, 5 Jan 2007 07:10:09 -0800 Subject: [SCSI] megaraid_{mm,mbox}: init fix for kdump 1. Changes in Initialization to fix kdump failure. Send SYNC command on loading. This command clears the pending commands in the adapter and re-initialize its internal RAID structure. Without this change, megaraid driver either panics or fails to initialize the adapter during kdump's second kernel boot if there are pending commands or interrupts from other devices sharing the same IRQ. 2. Authors email-id domain name changed from lsil.com to lsi.com. Also modified the MODULE_AUTHOR to megaraidlinux@lsi.com Signed-off-by: Sumant Patro Signed-off-by: James Bottomley --- Documentation/scsi/ChangeLog.megaraid | 16 ++++ drivers/scsi/megaraid/megaraid_mbox.c | 140 +++++++++++++++++++++++++++------- drivers/scsi/megaraid/megaraid_mbox.h | 4 +- 3 files changed, 130 insertions(+), 30 deletions(-) diff --git a/Documentation/scsi/ChangeLog.megaraid b/Documentation/scsi/ChangeLog.megaraid index a056bbe67c7e..37796fe45bd0 100644 --- a/Documentation/scsi/ChangeLog.megaraid +++ b/Documentation/scsi/ChangeLog.megaraid @@ -1,3 +1,19 @@ +Release Date : Thu Nov 16 15:32:35 EST 2006 - + Sumant Patro +Current Version : 2.20.5.1 (scsi module), 2.20.2.6 (cmm module) +Older Version : 2.20.4.9 (scsi module), 2.20.2.6 (cmm module) + +1. Changes in Initialization to fix kdump failure. + Send SYNC command on loading. + This command clears the pending commands in the adapter + and re-initialize its internal RAID structure. + Without this change, megaraid driver either panics or fails to + initialize the adapter during kdump's second kernel boot + if there are pending commands or interrupts from other devices + sharing the same IRQ. +2. Authors email-id domain name changed from lsil.com to lsi.com. + Also modified the MODULE_AUTHOR to megaraidlinux@lsi.com + Release Date : Fri May 19 09:31:45 EST 2006 - Seokmann Ju Current Version : 2.20.4.9 (scsi module), 2.20.2.6 (cmm module) Older Version : 2.20.4.8 (scsi module), 2.20.2.6 (cmm module) diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 7bac86dda88f..49ee50cc4e84 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -10,13 +10,13 @@ * 2 of the License, or (at your option) any later version. * * FILE : megaraid_mbox.c - * Version : v2.20.4.9 (Jul 16 2006) + * Version : v2.20.5.1 (Nov 16 2006) * * Authors: - * Atul Mukker - * Sreenivas Bagalkote - * Manoj Jose - * Seokmann Ju + * Atul Mukker + * Sreenivas Bagalkote + * Manoj Jose + * Seokmann Ju * * List of supported controllers * @@ -107,6 +107,7 @@ static int megaraid_mbox_support_random_del(adapter_t *); static int megaraid_mbox_get_max_sg(adapter_t *); static void megaraid_mbox_enum_raid_scsi(adapter_t *); static void megaraid_mbox_flush_cache(adapter_t *); +static int megaraid_mbox_fire_sync_cmd(adapter_t *); static void megaraid_mbox_display_scb(adapter_t *, scb_t *); static void megaraid_mbox_setup_device_map(adapter_t *); @@ -137,7 +138,7 @@ static int wait_till_fw_empty(adapter_t *); -MODULE_AUTHOR("sju@lsil.com"); +MODULE_AUTHOR("megaraidlinux@lsi.com"); MODULE_DESCRIPTION("LSI Logic MegaRAID Mailbox Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(MEGARAID_VERSION); @@ -779,33 +780,39 @@ megaraid_init_mbox(adapter_t *adapter) goto out_release_regions; } - // - // Setup the rest of the soft state using the library of FW routines - // + /* initialize the mutual exclusion lock for the mailbox */ + spin_lock_init(&raid_dev->mailbox_lock); + + /* allocate memory required for commands */ + if (megaraid_alloc_cmd_packets(adapter) != 0) + goto out_iounmap; - // request IRQ and register the interrupt service routine + /* + * Issue SYNC cmd to flush the pending cmds in the adapter + * and initialize its internal state + */ + + if (megaraid_mbox_fire_sync_cmd(adapter)) + con_log(CL_ANN, ("megaraid: sync cmd failed\n")); + + /* + * Setup the rest of the soft state using the library of + * FW routines + */ + + /* request IRQ and register the interrupt service routine */ if (request_irq(adapter->irq, megaraid_isr, IRQF_SHARED, "megaraid", adapter)) { con_log(CL_ANN, (KERN_WARNING "megaraid: Couldn't register IRQ %d!\n", adapter->irq)); + goto out_alloc_cmds; - goto out_iounmap; - } - - - // initialize the mutual exclusion lock for the mailbox - spin_lock_init(&raid_dev->mailbox_lock); - - // allocate memory required for commands - if (megaraid_alloc_cmd_packets(adapter) != 0) { - goto out_free_irq; } // Product info - if (megaraid_mbox_product_info(adapter) != 0) { - goto out_alloc_cmds; - } + if (megaraid_mbox_product_info(adapter) != 0) + goto out_free_irq; // Do we support extended CDBs adapter->max_cdb_sz = 10; @@ -874,9 +881,8 @@ megaraid_init_mbox(adapter_t *adapter) * Allocate resources required to issue FW calls, when sysfs is * accessed */ - if (megaraid_sysfs_alloc_resources(adapter) != 0) { - goto out_alloc_cmds; - } + if (megaraid_sysfs_alloc_resources(adapter) != 0) + goto out_free_irq; // Set the DMA mask to 64-bit. All supported controllers as capable of // DMA in this range @@ -920,10 +926,10 @@ megaraid_init_mbox(adapter_t *adapter) out_free_sysfs_res: megaraid_sysfs_free_resources(adapter); -out_alloc_cmds: - megaraid_free_cmd_packets(adapter); out_free_irq: free_irq(adapter->irq, adapter); +out_alloc_cmds: + megaraid_free_cmd_packets(adapter); out_iounmap: iounmap(raid_dev->baseaddr); out_release_regions: @@ -3379,6 +3385,84 @@ megaraid_mbox_flush_cache(adapter_t *adapter) } +/** + * megaraid_mbox_fire_sync_cmd - fire the sync cmd + * @param adapter : soft state for the controller + * + * Clears the pending cmds in FW and reinits its RAID structs + */ +static int +megaraid_mbox_fire_sync_cmd(adapter_t *adapter) +{ + mbox_t *mbox; + uint8_t raw_mbox[sizeof(mbox_t)]; + mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); + mbox64_t *mbox64; + int status = 0; + int i; + uint32_t dword; + + mbox = (mbox_t *)raw_mbox; + + memset((caddr_t)raw_mbox, 0, sizeof(mbox_t)); + + raw_mbox[0] = 0xFF; + + mbox64 = raid_dev->mbox64; + mbox = raid_dev->mbox; + + /* Wait until mailbox is free */ + if (megaraid_busywait_mbox(raid_dev) != 0) { + status = 1; + goto blocked_mailbox; + } + + /* Copy mailbox data into host structure */ + memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 16); + mbox->cmdid = 0xFE; + mbox->busy = 1; + mbox->poll = 0; + mbox->ack = 0; + mbox->numstatus = 0; + mbox->status = 0; + + wmb(); + WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1); + + /* Wait for maximum 1 min for status to post. + * If the Firmware SUPPORTS the ABOVE COMMAND, + * mbox->cmd will be set to 0 + * else + * the firmware will reject the command with + * mbox->numstatus set to 1 + */ + + i = 0; + status = 0; + while (!mbox->numstatus && mbox->cmd == 0xFF) { + rmb(); + msleep(1); + i++; + if (i > 1000 * 60) { + status = 1; + break; + } + } + if (mbox->numstatus == 1) + status = 1; /*cmd not supported*/ + + /* Check for interrupt line */ + dword = RDOUTDOOR(raid_dev); + WROUTDOOR(raid_dev, dword); + WRINDOOR(raid_dev,2); + + return status; + +blocked_mailbox: + con_log(CL_ANN, (KERN_WARNING "megaraid: blocked mailbox\n")); + return status; +} + /** * megaraid_mbox_display_scb - display SCB information, mostly debug purposes * @param adapter : controllers' soft state diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h index 2b5a3285f799..963e0d2dbd97 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.h +++ b/drivers/scsi/megaraid/megaraid_mbox.h @@ -21,8 +21,8 @@ #include "megaraid_ioctl.h" -#define MEGARAID_VERSION "2.20.4.9" -#define MEGARAID_EXT_VERSION "(Release Date: Sun Jul 16 12:27:22 EST 2006)" +#define MEGARAID_VERSION "2.20.5.1" +#define MEGARAID_EXT_VERSION "(Release Date: Thu Nov 16 15:32:35 EST 2006)" /* -- cgit v1.2.3 From a69b74d39f50b3e3ca9a6641bd71f3fc55d32d98 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 5 Jan 2007 22:41:48 -0800 Subject: [SCSI] megaraid: fix kernel-doc kernel-doc modifications: - change "@param var" notation to @var; - change function/description separator from ':' to '-'; - change var/description separator from '-' to ':'; - fix a few doc. typos; - don't use kernel-doc /** lead-in when the doc. block is not kernel-doc; - use Linux common */ ending comment format instead of **/; - use correct function parameter names; - place function parameters immediately after the function short description; - place kernel-doc immediately before its function or macro; Signed-off-by: Randy Dunlap Acked-by: Sumant Patro Signed-off-by: James Bottomley --- drivers/scsi/megaraid/mega_common.h | 120 +++++++------- drivers/scsi/megaraid/megaraid_ioctl.h | 36 ++--- drivers/scsi/megaraid/megaraid_mbox.c | 285 ++++++++++++++++----------------- drivers/scsi/megaraid/megaraid_mbox.h | 42 ++--- drivers/scsi/megaraid/megaraid_mm.c | 65 ++++---- drivers/scsi/megaraid/megaraid_sas.h | 14 +- 6 files changed, 275 insertions(+), 287 deletions(-) diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h index b50e27e66024..ab45e7a27d8c 100644 --- a/drivers/scsi/megaraid/mega_common.h +++ b/drivers/scsi/megaraid/mega_common.h @@ -46,17 +46,17 @@ /** * scb_t - scsi command control block - * @param ccb : command control block for individual driver - * @param list : list of control blocks - * @param gp : general purpose field for LLDs - * @param sno : all SCBs have a serial number - * @param scp : associated scsi command - * @param state : current state of scb - * @param dma_dir : direction of data transfer - * @param dma_type : transfer with sg list, buffer, or no data transfer - * @param dev_channel : actual channel on the device - * @param dev_target : actual target on the device - * @param status : completion status + * @ccb : command control block for individual driver + * @list : list of control blocks + * @gp : general purpose field for LLDs + * @sno : all SCBs have a serial number + * @scp : associated scsi command + * @state : current state of scb + * @dma_dir : direction of data transfer + * @dma_type : transfer with sg list, buffer, or no data transfer + * @dev_channel : actual channel on the device + * @dev_target : actual target on the device + * @status : completion status * * This is our central data structure to issue commands the each driver. * Driver specific data structures are maintained in the ccb field. @@ -99,42 +99,42 @@ typedef struct { /** * struct adapter_t - driver's initialization structure - * @param dpc_h : tasklet handle - * @param pdev : pci configuration pointer for kernel - * @param host : pointer to host structure of mid-layer - * @param lock : synchronization lock for mid-layer and driver - * @param quiescent : driver is quiescent for now. - * @param outstanding_cmds : number of commands pending in the driver - * @param kscb_list : pointer to the bulk of SCBs pointers for IO - * @param kscb_pool : pool of free scbs for IO - * @param kscb_pool_lock : lock for pool of free scbs - * @param pend_list : pending commands list - * @param pend_list_lock : exlusion lock for pending commands list - * @param completed_list : list of completed commands - * @param completed_list_lock : exclusion lock for list of completed commands - * @param sglen : max sg elements supported - * @param device_ids : to convert kernel device addr to our devices. - * @param raid_device : raid adapter specific pointer - * @param max_channel : maximum channel number supported - inclusive - * @param max_target : max target supported - inclusive - * @param max_lun : max lun supported - inclusive - * @param unique_id : unique identifier for each adapter - * @param irq : IRQ for this adapter - * @param ito : internal timeout value, (-1) means no timeout - * @param ibuf : buffer to issue internal commands - * @param ibuf_dma_h : dma handle for the above buffer - * @param uscb_list : SCB pointers for user cmds, common mgmt module - * @param uscb_pool : pool of SCBs for user commands - * @param uscb_pool_lock : exclusion lock for these SCBs - * @param max_cmds : max outstanding commands - * @param fw_version : firmware version - * @param bios_version : bios version - * @param max_cdb_sz : biggest CDB size supported. - * @param ha : is high availability present - clustering - * @param init_id : initiator ID, the default value should be 7 - * @param max_sectors : max sectors per request - * @param cmd_per_lun : max outstanding commands per LUN - * @param being_detached : set when unloading, no more mgmt calls + * @aram dpc_h : tasklet handle + * @pdev : pci configuration pointer for kernel + * @host : pointer to host structure of mid-layer + * @lock : synchronization lock for mid-layer and driver + * @quiescent : driver is quiescent for now. + * @outstanding_cmds : number of commands pending in the driver + * @kscb_list : pointer to the bulk of SCBs pointers for IO + * @kscb_pool : pool of free scbs for IO + * @kscb_pool_lock : lock for pool of free scbs + * @pend_list : pending commands list + * @pend_list_lock : exclusion lock for pending commands list + * @completed_list : list of completed commands + * @completed_list_lock : exclusion lock for list of completed commands + * @sglen : max sg elements supported + * @device_ids : to convert kernel device addr to our devices. + * @raid_device : raid adapter specific pointer + * @max_channel : maximum channel number supported - inclusive + * @max_target : max target supported - inclusive + * @max_lun : max lun supported - inclusive + * @unique_id : unique identifier for each adapter + * @irq : IRQ for this adapter + * @ito : internal timeout value, (-1) means no timeout + * @ibuf : buffer to issue internal commands + * @ibuf_dma_h : dma handle for the above buffer + * @uscb_list : SCB pointers for user cmds, common mgmt module + * @uscb_pool : pool of SCBs for user commands + * @uscb_pool_lock : exclusion lock for these SCBs + * @max_cmds : max outstanding commands + * @fw_version : firmware version + * @bios_version : bios version + * @max_cdb_sz : biggest CDB size supported. + * @ha : is high availability present - clustering + * @init_id : initiator ID, the default value should be 7 + * @max_sectors : max sectors per request + * @cmd_per_lun : max outstanding commands per LUN + * @being_detached : set when unloading, no more mgmt calls * * * mraid_setup_device_map() can be called anytime after the device map is @@ -211,23 +211,23 @@ typedef struct { #define SCP2ADAPTER(scp) (adapter_t *)SCSIHOST2ADAP(SCP2HOST(scp)) -/** - * MRAID_GET_DEVICE_MAP - device ids - * @param adp - Adapter's soft state - * @param scp - mid-layer scsi command pointer - * @param p_chan - physical channel on the controller - * @param target - target id of the device or logical drive number - * @param islogical - set if the command is for the logical drive - * - * Macro to retrieve information about device class, logical or physical and - * the corresponding physical channel and target or logical drive number - **/ #define MRAID_IS_LOGICAL(adp, scp) \ (SCP2CHANNEL(scp) == (adp)->max_channel) ? 1 : 0 #define MRAID_IS_LOGICAL_SDEV(adp, sdev) \ (sdev->channel == (adp)->max_channel) ? 1 : 0 +/** + * MRAID_GET_DEVICE_MAP - device ids + * @adp : adapter's soft state + * @scp : mid-layer scsi command pointer + * @p_chan : physical channel on the controller + * @target : target id of the device or logical drive number + * @islogical : set if the command is for the logical drive + * + * Macro to retrieve information about device class, logical or physical and + * the corresponding physical channel and target or logical drive number + */ #define MRAID_GET_DEVICE_MAP(adp, scp, p_chan, target, islogical) \ /* \ * Is the request coming for the virtual channel \ @@ -273,8 +273,8 @@ typedef struct { /* * struct mraid_pci_blk - structure holds DMA memory block info - * @param vaddr : virtual address to a memory block - * @param dma_addr : DMA handle to a memory block + * @vaddr : virtual address to a memory block + * @dma_addr : DMA handle to a memory block * * This structure is filled up for the caller. It is the responsibilty of the * caller to allocate this array big enough to store addresses for all diff --git a/drivers/scsi/megaraid/megaraid_ioctl.h b/drivers/scsi/megaraid/megaraid_ioctl.h index b8aa34202ec3..706fa05a187a 100644 --- a/drivers/scsi/megaraid/megaraid_ioctl.h +++ b/drivers/scsi/megaraid/megaraid_ioctl.h @@ -22,23 +22,23 @@ #include "mbox_defs.h" +/* + * console messages debug levels + */ +#define CL_ANN 0 /* print unconditionally, announcements */ +#define CL_DLEVEL1 1 /* debug level 1, informative */ +#define CL_DLEVEL2 2 /* debug level 2, verbose */ +#define CL_DLEVEL3 3 /* debug level 3, very verbose */ + /** * con_log() - console log routine - * @param level : indicates the severity of the message. - * @fparam mt : format string + * @level : indicates the severity of the message. + * @fmt : format string * * con_log displays the error messages on the console based on the current * debug level. Also it attaches the appropriate kernel severity level with * the message. - * - * - * consolge messages debug levels */ -#define CL_ANN 0 /* print unconditionally, announcements */ -#define CL_DLEVEL1 1 /* debug level 1, informative */ -#define CL_DLEVEL2 2 /* debug level 2, verbose */ -#define CL_DLEVEL3 3 /* debug level 3, very verbose */ - #define con_log(level, fmt) if (LSI_DBGLVL >= level) printk fmt; /* @@ -157,14 +157,14 @@ typedef struct uioc { /** * struct mraid_hba_info - information about the controller * - * @param pci_vendor_id : PCI vendor id - * @param pci_device_id : PCI device id - * @param subsystem_vendor_id : PCI subsystem vendor id - * @param subsystem_device_id : PCI subsystem device id - * @param baseport : base port of hba memory - * @param pci_bus : PCI bus - * @param pci_dev_fn : PCI device/function values - * @param irq : interrupt vector for the device + * @pci_vendor_id : PCI vendor id + * @pci_device_id : PCI device id + * @subsystem_vendor_id : PCI subsystem vendor id + * @subsystem_device_id : PCI subsystem device id + * @baseport : base port of hba memory + * @pci_bus : PCI bus + * @pci_dev_fn : PCI device/function values + * @irq : interrupt vector for the device * * Extended information of 256 bytes about the controller. Align on the single * byte boundary so that 32-bit applications can be run on 64-bit platform diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 49ee50cc4e84..04d0b6918c61 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -147,7 +147,7 @@ MODULE_VERSION(MEGARAID_VERSION); * ### modules parameters for driver ### */ -/** +/* * Set to enable driver to expose unconfigured disk to kernel */ static int megaraid_expose_unconf_disks = 0; @@ -155,7 +155,7 @@ module_param_named(unconf_disks, megaraid_expose_unconf_disks, int, 0); MODULE_PARM_DESC(unconf_disks, "Set to expose unconfigured disks to kernel (default=0)"); -/** +/* * driver wait time if the adapter's mailbox is busy */ static unsigned int max_mbox_busy_wait = MBOX_BUSY_WAIT; @@ -163,7 +163,7 @@ module_param_named(busy_wait, max_mbox_busy_wait, int, 0); MODULE_PARM_DESC(busy_wait, "Max wait for mailbox in microseconds if busy (default=10)"); -/** +/* * number of sectors per IO command */ static unsigned int megaraid_max_sectors = MBOX_MAX_SECTORS; @@ -171,7 +171,7 @@ module_param_named(max_sectors, megaraid_max_sectors, int, 0); MODULE_PARM_DESC(max_sectors, "Maximum number of sectors per IO command (default=128)"); -/** +/* * number of commands per logical unit */ static unsigned int megaraid_cmd_per_lun = MBOX_DEF_CMD_PER_LUN; @@ -180,7 +180,7 @@ MODULE_PARM_DESC(cmd_per_lun, "Maximum number of commands per logical unit (default=64)"); -/** +/* * Fast driver load option, skip scanning for physical devices during load. * This would result in non-disk devices being skipped during driver load * time. These can be later added though, using /proc/scsi/scsi @@ -191,7 +191,7 @@ MODULE_PARM_DESC(fast_load, "Faster loading of the driver, skips physical devices! (default=0)"); -/** +/* * mraid_debug level - threshold for amount of information to be displayed by * the driver. This level can be changed through modules parameters, ioctl or * sysfs/proc interface. By default, print the announcement messages only. @@ -338,7 +338,7 @@ static struct device_attribute *megaraid_sdev_attrs[] = { * * Return value: * actual depth set - **/ + */ static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth) { if (qdepth > MBOX_MAX_SCSI_CMDS) @@ -370,8 +370,8 @@ static struct scsi_host_template megaraid_template_g = { * megaraid_init - module load hook * * We register ourselves as hotplug enabled module and let PCI subsystem - * discover our adaters - **/ + * discover our adapters. + */ static int __init megaraid_init(void) { @@ -406,7 +406,7 @@ megaraid_init(void) /** * megaraid_exit - driver unload entry point * - * We simply unwrap the megaraid_init routine here + * We simply unwrap the megaraid_init routine here. */ static void __exit megaraid_exit(void) @@ -422,12 +422,12 @@ megaraid_exit(void) /** * megaraid_probe_one - PCI hotplug entry point - * @param pdev : handle to this controller's PCI configuration space - * @param id : pci device id of the class of controllers + * @pdev : handle to this controller's PCI configuration space + * @id : pci device id of the class of controllers * * This routine should be called whenever a new adapter is detected by the * PCI hotplug susbsytem. - **/ + */ static int __devinit megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -543,16 +543,15 @@ out_probe_one: /** - * megaraid_detach_one - release the framework resources and call LLD release - * routine - * @param pdev : handle for our PCI cofiguration space + * megaraid_detach_one - release framework resources and call LLD release routine + * @pdev : handle for our PCI cofiguration space * * This routine is called during driver unload. We free all the allocated * resources and call the corresponding LLD so that it can also release all * its resources. * - * This routine is also called from the PCI hotplug system - **/ + * This routine is also called from the PCI hotplug system. + */ static void megaraid_detach_one(struct pci_dev *pdev) { @@ -616,9 +615,9 @@ megaraid_detach_one(struct pci_dev *pdev) /** * megaraid_mbox_shutdown - PCI shutdown for megaraid HBA - * @param device : generice driver model device + * @pdev : generic driver model device * - * Shutdown notification, perform flush cache + * Shutdown notification, perform flush cache. */ static void megaraid_mbox_shutdown(struct pci_dev *pdev) @@ -644,10 +643,10 @@ megaraid_mbox_shutdown(struct pci_dev *pdev) /** * megaraid_io_attach - attach a device with the IO subsystem - * @param adapter : controller's soft state + * @adapter : controller's soft state * - * Attach this device with the IO subsystem - **/ + * Attach this device with the IO subsystem. + */ static int megaraid_io_attach(adapter_t *adapter) { @@ -696,10 +695,10 @@ megaraid_io_attach(adapter_t *adapter) /** * megaraid_io_detach - detach a device from the IO subsystem - * @param adapter : controller's soft state + * @adapter : controller's soft state * - * Detach this device from the IO subsystem - **/ + * Detach this device from the IO subsystem. + */ static void megaraid_io_detach(adapter_t *adapter) { @@ -723,13 +722,13 @@ megaraid_io_detach(adapter_t *adapter) /** * megaraid_init_mbox - initialize controller - * @param adapter - our soft state + * @adapter : our soft state * - * . Allocate 16-byte aligned mailbox memory for firmware handshake - * . Allocate controller's memory resources - * . Find out all initialization data - * . Allocate memory required for all the commands - * . Use internal library of FW routines, build up complete soft state + * - Allocate 16-byte aligned mailbox memory for firmware handshake + * - Allocate controller's memory resources + * - Find out all initialization data + * - Allocate memory required for all the commands + * - Use internal library of FW routines, build up complete soft state */ static int __devinit megaraid_init_mbox(adapter_t *adapter) @@ -943,7 +942,7 @@ out_free_raid_dev: /** * megaraid_fini_mbox - undo controller initialization - * @param adapter : our soft state + * @adapter : our soft state */ static void megaraid_fini_mbox(adapter_t *adapter) @@ -973,12 +972,12 @@ megaraid_fini_mbox(adapter_t *adapter) /** * megaraid_alloc_cmd_packets - allocate shared mailbox - * @param adapter : soft state of the raid controller + * @adapter : soft state of the raid controller * * Allocate and align the shared mailbox. This maibox is used to issue * all the commands. For IO based controllers, the mailbox is also regsitered * with the FW. Allocate memory for all commands as well. - * This is our big allocator + * This is our big allocator. */ static int megaraid_alloc_cmd_packets(adapter_t *adapter) @@ -1138,9 +1137,9 @@ out_free_common_mbox: /** * megaraid_free_cmd_packets - free memory - * @param adapter : soft state of the raid controller + * @adapter : soft state of the raid controller * - * Release memory resources allocated for commands + * Release memory resources allocated for commands. */ static void megaraid_free_cmd_packets(adapter_t *adapter) @@ -1162,10 +1161,10 @@ megaraid_free_cmd_packets(adapter_t *adapter) /** * megaraid_mbox_setup_dma_pools - setup dma pool for command packets - * @param adapter : HBA soft state + * @adapter : HBA soft state * - * setup the dma pools for mailbox, passthru and extended passthru structures, - * and scatter-gather lists + * Setup the dma pools for mailbox, passthru and extended passthru structures, + * and scatter-gather lists. */ static int megaraid_mbox_setup_dma_pools(adapter_t *adapter) @@ -1258,10 +1257,10 @@ fail_setup_dma_pool: /** * megaraid_mbox_teardown_dma_pools - teardown dma pools for command packets - * @param adapter : HBA soft state + * @adapter : HBA soft state * - * teardown the dma pool for mailbox, passthru and extended passthru - * structures, and scatter-gather lists + * Teardown the dma pool for mailbox, passthru and extended passthru + * structures, and scatter-gather lists. */ static void megaraid_mbox_teardown_dma_pools(adapter_t *adapter) @@ -1306,10 +1305,11 @@ megaraid_mbox_teardown_dma_pools(adapter_t *adapter) /** * megaraid_alloc_scb - detach and return a scb from the free list * @adapter : controller's soft state + * @scp : pointer to the scsi command to be executed * - * return the scb from the head of the free list. NULL if there are none - * available - **/ + * Return the scb from the head of the free list. %NULL if there are none + * available. + */ static scb_t * megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp) { @@ -1343,11 +1343,11 @@ megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp) * @adapter : controller's soft state * @scb : scb to be freed * - * return the scb back to the free list of scbs. The caller must 'flush' the + * Return the scb back to the free list of scbs. The caller must 'flush' the * SCB before calling us. E.g., performing pci_unamp and/or pci_sync etc. * NOTE NOTE: Make sure the scb is not on any list before calling this * routine. - **/ + */ static inline void megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb) { @@ -1368,10 +1368,10 @@ megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb) /** * megaraid_mbox_mksgl - make the scatter-gather list - * @adapter - controller's soft state - * @scb - scsi control block + * @adapter : controller's soft state + * @scb : scsi control block * - * prepare the scatter-gather list + * Prepare the scatter-gather list. */ static int megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) @@ -1441,10 +1441,10 @@ megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb) /** * mbox_post_cmd - issue a mailbox command - * @adapter - controller's soft state - * @scb - command to be issued + * @adapter : controller's soft state + * @scb : command to be issued * - * post the command to the controller if mailbox is availble. + * Post the command to the controller if mailbox is available. */ static int mbox_post_cmd(adapter_t *adapter, scb_t *scb) @@ -1524,7 +1524,7 @@ mbox_post_cmd(adapter_t *adapter, scb_t *scb) * Queue entry point for mailbox based controllers. */ static int -megaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *)) +megaraid_queue_command(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *)) { adapter_t *adapter; scb_t *scb; @@ -1554,15 +1554,15 @@ megaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *)) } /** - * megaraid_mbox_build_cmd - transform the mid-layer scsi command to megaraid - * firmware lingua - * @adapter - controller's soft state - * @scp - mid-layer scsi command pointer - * @busy - set if request could not be completed because of lack of + * megaraid_mbox_build_cmd - transform the mid-layer scsi commands + * @adapter : controller's soft state + * @scp : mid-layer scsi command pointer + * @busy : set if request could not be completed because of lack of * resources * - * convert the command issued by mid-layer to format understood by megaraid - * firmware. We also complete certain command without sending them to firmware + * Transform the mid-layer scsi command to megaraid firmware lingua. + * Convert the command issued by mid-layer to format understood by megaraid + * firmware. We also complete certain commands without sending them to firmware. */ static scb_t * megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy) @@ -1943,9 +1943,9 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy) /** * megaraid_mbox_runpendq - execute commands queued in the pending queue * @adapter : controller's soft state - * @scb : SCB to be queued in the pending list + * @scb_q : SCB to be queued in the pending list * - * scan the pending list for commands which are not yet issued and try to + * Scan the pending list for commands which are not yet issued and try to * post to the controller. The SCB can be a null pointer, which would indicate * no SCB to be queue, just try to execute the ones in the pending list. * @@ -2018,11 +2018,11 @@ megaraid_mbox_runpendq(adapter_t *adapter, scb_t *scb_q) /** * megaraid_mbox_prepare_pthru - prepare a command for physical devices - * @adapter - pointer to controller's soft state - * @scb - scsi control block - * @scp - scsi command from the mid-layer + * @adapter : pointer to controller's soft state + * @scb : scsi control block + * @scp : scsi command from the mid-layer * - * prepare a command for the scsi physical devices + * Prepare a command for the scsi physical devices. */ static void megaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb, @@ -2066,12 +2066,12 @@ megaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb, /** * megaraid_mbox_prepare_epthru - prepare a command for physical devices - * @adapter - pointer to controller's soft state - * @scb - scsi control block - * @scp - scsi command from the mid-layer + * @adapter : pointer to controller's soft state + * @scb : scsi control block + * @scp : scsi command from the mid-layer * - * prepare a command for the scsi physical devices. This rountine prepares - * commands for devices which can take extended CDBs (>10 bytes) + * Prepare a command for the scsi physical devices. This rountine prepares + * commands for devices which can take extended CDBs (>10 bytes). */ static void megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb, @@ -2115,9 +2115,9 @@ megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb, /** * megaraid_ack_sequence - interrupt ack sequence for memory mapped HBAs - * @adapter - controller's soft state + * @adapter : controller's soft state * - * Interrupt ackrowledgement sequence for memory mapped HBAs. Find out the + * Interrupt acknowledgement sequence for memory mapped HBAs. Find out the * completed command and put them on the completed list for later processing. * * Returns: 1 if the interrupt is valid, 0 otherwise @@ -2230,9 +2230,8 @@ megaraid_ack_sequence(adapter_t *adapter) /** * megaraid_isr - isr for memory based mailbox based controllers - * @irq - irq - * @devp - pointer to our soft state - * @regs - unused + * @irq : irq + * @devp : pointer to our soft state * * Interrupt service routine for memory-mapped mailbox controllers. */ @@ -2677,7 +2676,7 @@ megaraid_abort_handler(struct scsi_cmnd *scp) * the FW is still live, in which case the outstanding commands counter mut go * down to 0. If that happens, also issue the reservation reset command to * relinquish (possible) reservations on the logical drives connected to this - * host + * host. **/ static int megaraid_reset_handler(struct scsi_cmnd *scp) @@ -2829,11 +2828,11 @@ megaraid_reset_handler(struct scsi_cmnd *scp) /** * mbox_post_sync_cmd() - blocking command to the mailbox based controllers - * @adapter - controller's soft state - * @raw_mbox - the mailbox + * @adapter : controller's soft state + * @raw_mbox : the mailbox * * Issue a scb in synchronous and non-interrupt mode for mailbox based - * controllers + * controllers. */ static int mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[]) @@ -2961,12 +2960,12 @@ blocked_mailbox: /** * mbox_post_sync_cmd_fast - blocking command to the mailbox based controllers - * @adapter - controller's soft state - * @raw_mbox - the mailbox + * @adapter : controller's soft state + * @raw_mbox : the mailbox * * Issue a scb in synchronous and non-interrupt mode for mailbox based * controllers. This is a faster version of the synchronous command and - * therefore can be called in interrupt-context as well + * therefore can be called in interrupt-context as well. */ static int mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[]) @@ -3014,10 +3013,10 @@ mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[]) /** * megaraid_busywait_mbox() - Wait until the controller's mailbox is available - * @raid_dev - RAID device (HBA) soft state + * @raid_dev : RAID device (HBA) soft state * - * wait until the controller's mailbox is available to accept more commands. - * wait for at most 1 second + * Wait until the controller's mailbox is available to accept more commands. + * Wait for at most 1 second. */ static int megaraid_busywait_mbox(mraid_device_t *raid_dev) @@ -3038,9 +3037,9 @@ megaraid_busywait_mbox(mraid_device_t *raid_dev) /** * megaraid_mbox_product_info - some static information about the controller - * @adapter - our soft state + * @adapter : our soft state * - * issue commands to the controller to grab some parameters required by our + * Issue commands to the controller to grab some parameters required by our * caller. */ static int @@ -3163,10 +3162,10 @@ megaraid_mbox_product_info(adapter_t *adapter) /** * megaraid_mbox_extended_cdb - check for support for extended CDBs - * @adapter - soft state for the controller + * @adapter : soft state for the controller * - * this routine check whether the controller in question supports extended - * ( > 10 bytes ) CDBs + * This routine check whether the controller in question supports extended + * ( > 10 bytes ) CDBs. */ static int megaraid_mbox_extended_cdb(adapter_t *adapter) @@ -3199,8 +3198,8 @@ megaraid_mbox_extended_cdb(adapter_t *adapter) /** * megaraid_mbox_support_ha - Do we support clustering - * @adapter - soft state for the controller - * @init_id - ID of the initiator + * @adapter : soft state for the controller + * @init_id : ID of the initiator * * Determine if the firmware supports clustering and the ID of the initiator. */ @@ -3242,9 +3241,9 @@ megaraid_mbox_support_ha(adapter_t *adapter, uint16_t *init_id) /** * megaraid_mbox_support_random_del - Do we support random deletion - * @adapter - soft state for the controller + * @adapter : soft state for the controller * - * Determine if the firmware supports random deletion + * Determine if the firmware supports random deletion. * Return: 1 is operation supported, 0 otherwise */ static int @@ -3277,10 +3276,10 @@ megaraid_mbox_support_random_del(adapter_t *adapter) /** * megaraid_mbox_get_max_sg - maximum sg elements supported by the firmware - * @adapter - soft state for the controller + * @adapter : soft state for the controller * * Find out the maximum number of scatter-gather elements supported by the - * firmware + * firmware. */ static int megaraid_mbox_get_max_sg(adapter_t *adapter) @@ -3317,10 +3316,10 @@ megaraid_mbox_get_max_sg(adapter_t *adapter) /** * megaraid_mbox_enum_raid_scsi - enumerate the RAID and SCSI channels - * @adapter - soft state for the controller + * @adapter : soft state for the controller * - * Enumerate the RAID and SCSI channels for ROMB platoforms so that channels - * can be exported as regular SCSI channels + * Enumerate the RAID and SCSI channels for ROMB platforms so that channels + * can be exported as regular SCSI channels. */ static void megaraid_mbox_enum_raid_scsi(adapter_t *adapter) @@ -3354,9 +3353,9 @@ megaraid_mbox_enum_raid_scsi(adapter_t *adapter) /** * megaraid_mbox_flush_cache - flush adapter and disks cache - * @param adapter : soft state for the controller + * @adapter : soft state for the controller * - * Flush adapter cache followed by disks cache + * Flush adapter cache followed by disks cache. */ static void megaraid_mbox_flush_cache(adapter_t *adapter) @@ -3387,9 +3386,9 @@ megaraid_mbox_flush_cache(adapter_t *adapter) /** * megaraid_mbox_fire_sync_cmd - fire the sync cmd - * @param adapter : soft state for the controller + * @adapter : soft state for the controller * - * Clears the pending cmds in FW and reinits its RAID structs + * Clears the pending cmds in FW and reinits its RAID structs. */ static int megaraid_mbox_fire_sync_cmd(adapter_t *adapter) @@ -3465,12 +3464,12 @@ blocked_mailbox: /** * megaraid_mbox_display_scb - display SCB information, mostly debug purposes - * @param adapter : controllers' soft state - * @param scb : SCB to be displayed - * @param level : debug level for console print + * @adapter : controller's soft state + * @scb : SCB to be displayed + * @level : debug level for console print * * Diplay information about the given SCB iff the current debug level is - * verbose + * verbose. */ static void megaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb) @@ -3518,7 +3517,7 @@ megaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb) * scsi addresses and megaraid scsi and logical drive addresses. We export * scsi devices on their actual addresses, whereas the logical drives are * exported on a virtual scsi channel. - **/ + */ static void megaraid_mbox_setup_device_map(adapter_t *adapter) { @@ -3556,7 +3555,7 @@ megaraid_mbox_setup_device_map(adapter_t *adapter) /** * megaraid_cmm_register - register with the mangement module - * @param adapter : HBA soft state + * @adapter : HBA soft state * * Register with the management module, which allows applications to issue * ioctl calls to the drivers. This interface is used by the management module @@ -3646,11 +3645,11 @@ megaraid_cmm_register(adapter_t *adapter) /** * megaraid_cmm_unregister - un-register with the mangement module - * @param adapter : HBA soft state + * @adapter : HBA soft state * * Un-register with the management module. * FIXME: mgmt module must return failure for unregister if it has pending - * commands in LLD + * commands in LLD. */ static int megaraid_cmm_unregister(adapter_t *adapter) @@ -3663,9 +3662,9 @@ megaraid_cmm_unregister(adapter_t *adapter) /** * megaraid_mbox_mm_handler - interface for CMM to issue commands to LLD - * @param drvr_data : LLD specific data - * @param kioc : CMM interface packet - * @param action : command action + * @drvr_data : LLD specific data + * @kioc : CMM interface packet + * @action : command action * * This routine is invoked whenever the Common Mangement Module (CMM) has a * command for us. The 'action' parameter specifies if this is a new command @@ -3718,8 +3717,8 @@ megaraid_mbox_mm_handler(unsigned long drvr_data, uioc_t *kioc, uint32_t action) /** * megaraid_mbox_mm_command - issues commands routed through CMM - * @param adapter : HBA soft state - * @param kioc : management command packet + * @adapter : HBA soft state + * @kioc : management command packet * * Issues commands, which are routed through the management module. */ @@ -3888,8 +3887,8 @@ megaraid_mbox_mm_done(adapter_t *adapter, scb_t *scb) /** * gather_hbainfo - HBA characteristics for the applications - * @param adapter : HBA soft state - * @param hinfo : pointer to the caller's host info strucuture + * @adapter : HBA soft state + * @hinfo : pointer to the caller's host info strucuture */ static int gather_hbainfo(adapter_t *adapter, mraid_hba_info_t *hinfo) @@ -3923,16 +3922,15 @@ gather_hbainfo(adapter_t *adapter, mraid_hba_info_t *hinfo) /** * megaraid_sysfs_alloc_resources - allocate sysfs related resources + * @adapter : controller's soft state * * Allocate packets required to issue FW calls whenever the sysfs attributes * are read. These attributes would require up-to-date information from the * FW. Also set up resources for mutual exclusion to share these resources and * the wait queue. * - * @param adapter : controller's soft state - * - * @return 0 on success - * @return -ERROR_CODE on failure + * Return 0 on success. + * Return -ERROR_CODE on failure. */ static int megaraid_sysfs_alloc_resources(adapter_t *adapter) @@ -3969,10 +3967,9 @@ megaraid_sysfs_alloc_resources(adapter_t *adapter) /** * megaraid_sysfs_free_resources - free sysfs related resources + * @adapter : controller's soft state * * Free packets allocated for sysfs FW commands - * - * @param adapter : controller's soft state */ static void megaraid_sysfs_free_resources(adapter_t *adapter) @@ -3991,10 +3988,9 @@ megaraid_sysfs_free_resources(adapter_t *adapter) /** * megaraid_sysfs_get_ldmap_done - callback for get ldmap + * @uioc : completed packet * * Callback routine called in the ISR/tasklet context for get ldmap call - * - * @param uioc : completed packet */ static void megaraid_sysfs_get_ldmap_done(uioc_t *uioc) @@ -4010,12 +4006,11 @@ megaraid_sysfs_get_ldmap_done(uioc_t *uioc) /** * megaraid_sysfs_get_ldmap_timeout - timeout handling for get ldmap + * @data : timed out packet * * Timeout routine to recover and return to application, in case the adapter - * has stopped responding. A timeout of 60 seconds for this command seem like - * a good value - * - * @param uioc : timed out packet + * has stopped responding. A timeout of 60 seconds for this command seems like + * a good value. */ static void megaraid_sysfs_get_ldmap_timeout(unsigned long data) @@ -4032,6 +4027,7 @@ megaraid_sysfs_get_ldmap_timeout(unsigned long data) /** * megaraid_sysfs_get_ldmap - get update logical drive map + * @adapter : controller's soft state * * This routine will be called whenever user reads the logical drive * attributes, go get the current logical drive mapping table from the @@ -4043,10 +4039,8 @@ megaraid_sysfs_get_ldmap_timeout(unsigned long data) * standalone libary. For now, this should suffice since there is no other * user of this interface. * - * @param adapter : controller's soft state - * - * @return 0 on success - * @return -1 on failure + * Return 0 on success. + * Return -1 on failure. */ static int megaraid_sysfs_get_ldmap(adapter_t *adapter) @@ -4148,13 +4142,12 @@ megaraid_sysfs_get_ldmap(adapter_t *adapter) /** * megaraid_sysfs_show_app_hndl - display application handle for this adapter + * @cdev : class device object representation for the host + * @buf : buffer to send data to * * Display the handle used by the applications while executing management * tasks on the adapter. We invoke a management module API to get the adapter * handle, since we do not interface with applications directly. - * - * @param cdev : class device object representation for the host - * @param buf : buffer to send data to */ static ssize_t megaraid_sysfs_show_app_hndl(struct class_device *cdev, char *buf) @@ -4171,16 +4164,18 @@ megaraid_sysfs_show_app_hndl(struct class_device *cdev, char *buf) /** * megaraid_sysfs_show_ldnum - display the logical drive number for this device + * @dev : device object representation for the scsi device + * @attr : device attribute to show + * @buf : buffer to send data to * * Display the logical drive number for the device in question, if it a valid - * logical drive. For physical devices, "-1" is returned - * The logical drive number is displayed in following format + * logical drive. For physical devices, "-1" is returned. + * + * The logical drive number is displayed in following format: * * - * * - * @param dev : device object representation for the scsi device - * @param buf : buffer to send data to + * */ static ssize_t megaraid_sysfs_show_ldnum(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h index 963e0d2dbd97..9de803cebd4b 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.h +++ b/drivers/scsi/megaraid/megaraid_mbox.h @@ -146,27 +146,27 @@ typedef struct { /** * mraid_device_t - adapter soft state structure for mailbox controllers - * @param una_mbox64 : 64-bit mbox - unaligned - * @param una_mbox64_dma : mbox dma addr - unaligned - * @param mbox : 32-bit mbox - aligned - * @param mbox64 : 64-bit mbox - aligned - * @param mbox_dma : mbox dma addr - aligned - * @param mailbox_lock : exclusion lock for the mailbox - * @param baseport : base port of hba memory - * @param baseaddr : mapped addr of hba memory - * @param mbox_pool : pool of mailboxes - * @param mbox_pool_handle : handle for the mailbox pool memory - * @param epthru_pool : a pool for extended passthru commands - * @param epthru_pool_handle : handle to the pool above - * @param sg_pool : pool of scatter-gather lists for this driver - * @param sg_pool_handle : handle to the pool above - * @param ccb_list : list of our command control blocks - * @param uccb_list : list of cmd control blocks for mgmt module - * @param umbox64 : array of mailbox for user commands (cmm) - * @param pdrv_state : array for state of each physical drive. - * @param last_disp : flag used to show device scanning - * @param hw_error : set if FW not responding - * @param fast_load : If set, skip physical device scanning + * @una_mbox64 : 64-bit mbox - unaligned + * @una_mbox64_dma : mbox dma addr - unaligned + * @mbox : 32-bit mbox - aligned + * @mbox64 : 64-bit mbox - aligned + * @mbox_dma : mbox dma addr - aligned + * @mailbox_lock : exclusion lock for the mailbox + * @baseport : base port of hba memory + * @baseaddr : mapped addr of hba memory + * @mbox_pool : pool of mailboxes + * @mbox_pool_handle : handle for the mailbox pool memory + * @epthru_pool : a pool for extended passthru commands + * @epthru_pool_handle : handle to the pool above + * @sg_pool : pool of scatter-gather lists for this driver + * @sg_pool_handle : handle to the pool above + * @ccb_list : list of our command control blocks + * @uccb_list : list of cmd control blocks for mgmt module + * @umbox64 : array of mailbox for user commands (cmm) + * @pdrv_state : array for state of each physical drive. + * @last_disp : flag used to show device scanning + * @hw_error : set if FW not responding + * @fast_load : If set, skip physical device scanning * @channel_class : channel class, RAID or SCSI * @sysfs_sem : semaphore to serialize access to sysfs res. * @sysfs_uioc : management packet to issue FW calls from sysfs diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index d85b9a8f1b8d..c1ff20c4747d 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c @@ -78,10 +78,10 @@ static struct file_operations lsi_fops = { /** * mraid_mm_open - open routine for char node interface - * @inod : unused + * @inode : unused * @filep : unused * - * allow ioctl operations by apps only if they superuser privilege + * Allow ioctl operations by apps only if they have superuser privilege. */ static int mraid_mm_open(struct inode *inode, struct file *filep) @@ -214,7 +214,9 @@ mraid_mm_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, /** * mraid_mm_get_adapter - Returns corresponding adapters for the mimd packet * @umimd : User space mimd_t ioctl packet - * @adapter : pointer to the adapter (OUT) + * @rval : returned success/error status + * + * The function return value is a pointer to the located @adapter. */ static mraid_mmadp_t * mraid_mm_get_adapter(mimd_t __user *umimd, int *rval) @@ -252,11 +254,11 @@ mraid_mm_get_adapter(mimd_t __user *umimd, int *rval) return adapter; } -/* - * handle_drvrcmd - This routine checks if the opcode is a driver - * cmd and if it is, handles it. +/** + * handle_drvrcmd - Checks if the opcode is a driver cmd and if it is, handles it. * @arg : packet sent by the user app * @old_ioctl : mimd if 1; uioc otherwise + * @rval : pointer for command's returned value (not function status) */ static int handle_drvrcmd(void __user *arg, uint8_t old_ioctl, int *rval) @@ -322,8 +324,8 @@ old_packet: /** * mimd_to_kioc - Converter from old to new ioctl format - * * @umimd : user space old MIMD IOCTL + * @adp : adapter softstate * @kioc : kernel space new format IOCTL * * Routine to convert MIMD interface IOCTL to new interface IOCTL packet. The @@ -474,7 +476,6 @@ mimd_to_kioc(mimd_t __user *umimd, mraid_mmadp_t *adp, uioc_t *kioc) /** * mraid_mm_attch_buf - Attach a free dma buffer for required size - * * @adp : Adapter softstate * @kioc : kioc that the buffer needs to be attached to * @xferlen : required length for buffer @@ -607,7 +608,6 @@ mraid_mm_alloc_kioc(mraid_mmadp_t *adp) /** * mraid_mm_dealloc_kioc - Return kioc to free pool - * * @adp : Adapter softstate * @kioc : uioc_t node to be returned to free pool */ @@ -652,7 +652,6 @@ mraid_mm_dealloc_kioc(mraid_mmadp_t *adp, uioc_t *kioc) /** * lld_ioctl - Routine to issue ioctl to low level drvr - * * @adp : The adapter handle * @kioc : The ioctl packet with kernel addresses */ @@ -705,7 +704,6 @@ lld_ioctl(mraid_mmadp_t *adp, uioc_t *kioc) /** * ioctl_done - callback from the low level driver - * * @kioc : completed ioctl packet */ static void @@ -756,9 +754,8 @@ ioctl_done(uioc_t *kioc) } -/* - * lld_timedout : callback from the expired timer - * +/** + * lld_timedout - callback from the expired timer * @ptr : ioctl packet that timed out */ static void @@ -776,8 +773,7 @@ lld_timedout(unsigned long ptr) /** - * kioc_to_mimd : Converter from new back to old format - * + * kioc_to_mimd - Converter from new back to old format * @kioc : Kernel space IOCTL packet (successfully issued) * @mimd : User space MIMD packet */ @@ -855,7 +851,6 @@ kioc_to_mimd(uioc_t *kioc, mimd_t __user *mimd) /** * hinfo_to_cinfo - Convert new format hba info into old format - * * @hinfo : New format, more comprehensive adapter info * @cinfo : Old format adapter info to support mimd_t apps */ @@ -878,10 +873,9 @@ hinfo_to_cinfo(mraid_hba_info_t *hinfo, mcontroller_t *cinfo) } -/* - * mraid_mm_register_adp - Registration routine for low level drvrs - * - * @adp : Adapter objejct +/** + * mraid_mm_register_adp - Registration routine for low level drivers + * @lld_adp : Adapter objejct */ int mraid_mm_register_adp(mraid_mmadp_t *lld_adp) @@ -1007,15 +1001,14 @@ memalloc_error: /** * mraid_mm_adapter_app_handle - return the application handle for this adapter + * @unique_id : adapter unique identifier * - * For the given driver data, locate the adadpter in our global list and + * For the given driver data, locate the adapter in our global list and * return the corresponding handle, which is also used by applications to * uniquely identify an adapter. * - * @param unique_id : adapter unique identifier - * - * @return adapter handle if found in the list - * @return 0 if adapter could not be located, should never happen though + * Return adapter handle if found in the list. + * Return 0 if adapter could not be located, should never happen though. */ uint32_t mraid_mm_adapter_app_handle(uint32_t unique_id) @@ -1040,7 +1033,6 @@ mraid_mm_adapter_app_handle(uint32_t unique_id) /** * mraid_mm_setup_dma_pools - Set up dma buffer pools per adapter - * * @adp : Adapter softstate * * We maintain a pool of dma buffers per each adapter. Each pool has one @@ -1093,11 +1085,11 @@ dma_pool_setup_error: } -/* +/** * mraid_mm_unregister_adp - Unregister routine for low level drivers - * Assume no outstanding ioctls to llds. - * * @unique_id : UID of the adpater + * + * Assumes no outstanding ioctls to llds. */ int mraid_mm_unregister_adp(uint32_t unique_id) @@ -1131,7 +1123,6 @@ mraid_mm_unregister_adp(uint32_t unique_id) /** * mraid_mm_free_adp_resources - Free adapter softstate - * * @adp : Adapter softstate */ static void @@ -1162,7 +1153,6 @@ mraid_mm_free_adp_resources(mraid_mmadp_t *adp) /** * mraid_mm_teardown_dma_pools - Free all per adapter dma buffers - * * @adp : Adapter softstate */ static void @@ -1190,7 +1180,7 @@ mraid_mm_teardown_dma_pools(mraid_mmadp_t *adp) } /** - * mraid_mm_init : Module entry point + * mraid_mm_init - Module entry point */ static int __init mraid_mm_init(void) @@ -1214,10 +1204,13 @@ mraid_mm_init(void) } +#ifdef CONFIG_COMPAT /** - * mraid_mm_compat_ioctl : 32bit to 64bit ioctl conversion routine + * mraid_mm_compat_ioctl - 32bit to 64bit ioctl conversion routine + * @filep : file operations pointer (ignored) + * @cmd : ioctl command + * @arg : user ioctl packet */ -#ifdef CONFIG_COMPAT static long mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) @@ -1231,7 +1224,7 @@ mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd, #endif /** - * mraid_mm_exit : Module exit point + * mraid_mm_exit - Module exit point */ static void __exit mraid_mm_exit(void) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 55eddcf8eb15..cacb3ad92527 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -15,7 +15,7 @@ #ifndef LSI_MEGARAID_SAS_H #define LSI_MEGARAID_SAS_H -/** +/* * MegaRAID SAS Driver meta data */ #define MEGASAS_VERSION "00.00.03.05" @@ -40,7 +40,7 @@ * "message frames" */ -/** +/* * FW posts its state in upper 4 bits of outbound_msg_0 register */ #define MFI_STATE_MASK 0xF0000000 @@ -58,7 +58,7 @@ #define MEGAMFI_FRAME_SIZE 64 -/** +/* * During FW init, clear pending cmds & reset state using inbound_msg_0 * * ABORT : Abort all pending cmds @@ -78,7 +78,7 @@ MFI_INIT_MFIMODE| \ MFI_INIT_ABORT -/** +/* * MFI frame flags */ #define MFI_FRAME_POST_IN_REPLY_QUEUE 0x0000 @@ -92,12 +92,12 @@ #define MFI_FRAME_DIR_READ 0x0010 #define MFI_FRAME_DIR_BOTH 0x0018 -/** +/* * Definition for cmd_status */ #define MFI_CMD_STATUS_POLL_MODE 0xFF -/** +/* * MFI command opcodes */ #define MFI_CMD_INIT 0x00 @@ -128,7 +128,7 @@ #define MR_DCMD_CLUSTER_RESET_ALL 0x08010100 #define MR_DCMD_CLUSTER_RESET_LD 0x08010200 -/** +/* * MFI command completion codes */ enum MFI_STAT { -- cgit v1.2.3 From 59f19a9efc3949f4e5675186bdcb6db1f46258a1 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 9 Jan 2007 21:40:52 -0800 Subject: [SCSI] megaraid: more kernel-doc fixes More megaraid kernel-doc fixes. Signed-off-by: Randy Dunlap Acked-by: Sumant Patro Signed-off-by: James Bottomley --- drivers/scsi/megaraid/mbox_defs.h | 2 +- drivers/scsi/megaraid/mega_common.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/megaraid/mbox_defs.h b/drivers/scsi/megaraid/mbox_defs.h index 3052869f51f4..170399ef06f4 100644 --- a/drivers/scsi/megaraid/mbox_defs.h +++ b/drivers/scsi/megaraid/mbox_defs.h @@ -748,7 +748,7 @@ typedef struct { /** - * private_bios_data - bios private data for boot devices + * struct private_bios_data - bios private data for boot devices * @geometry : bits 0-3 - BIOS geometry, 0x0001 - 1GB, 0x0010 - 2GB, * 0x1000 - 8GB, Others values are invalid * @unused : bits 4-7 are unused diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h index ab45e7a27d8c..26e1e6c55654 100644 --- a/drivers/scsi/megaraid/mega_common.h +++ b/drivers/scsi/megaraid/mega_common.h @@ -271,7 +271,7 @@ typedef struct { #define ASSERT(expression) #endif -/* +/** * struct mraid_pci_blk - structure holds DMA memory block info * @vaddr : virtual address to a memory block * @dma_addr : DMA handle to a memory block -- cgit v1.2.3 From 3424a65d717ca87ce11acfb03cfd2f713886bfb4 Mon Sep 17 00:00:00 2001 From: Kurt Garloff Date: Tue, 9 Jan 2007 02:28:54 +0100 Subject: [SCSI] scsi_scan message cosmetic error Hi, Minor typo ... In my first iteration of patches (that got merged), the BLIST_ATTACH_PQ3 actually had the value 0x800000, but that got changed later to avoid conflicts. This piece must have been overlooked. You could obviously do something like %x and then add the bitflags, but that looks overkill for something that does not tend to change. Please merge. (Patch applied against latest 2.6.20rc version that I tested.) From: Kurt Garloff Subject: [SCSI SCAN] Fix logging message for PQ3 devices The blacklist flags BLIST_ATTACH_PQ3 has value 0x1000000, not 0x800000. Signed-off-by: Kurt Garloff Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 14e635aa44ce..b8f0cab57813 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1012,7 +1012,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, sdev_printk(KERN_INFO, sdev, "scsi scan: consider passing scsi_mod." - "dev_flags=%s:%s:0x240 or 0x800240\n", + "dev_flags=%s:%s:0x240 or 0x1000240\n", scsi_inq_str(vend, result, 8, 16), scsi_inq_str(mod, result, 16, 32)); }); -- cgit v1.2.3 From befede3dabd204e9c546cbfbe391b29286c57da2 Mon Sep 17 00:00:00 2001 From: Seokmann Ju Date: Tue, 9 Jan 2007 11:37:52 -0800 Subject: [SCSI] qla2xxx: correct locking while call starget_for_each_device() Removed spin_unlock_irq()/spin_lock_irq() pairs surrounding starget_for_each_device() calls. As Matthew W. pointed out, starget_for_each_device() can be called under a spinlock being held. The change has been tested and verified on qla2xxx.ko module. Thanks Matthew W. and Hisashi H. for help. Signed-off-by: Andrew Vasquez Signed-off-by: Seokmann Ju Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index d3b6df4d55c8..b95fcb2c065e 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -650,10 +650,8 @@ qla2x00_ramp_up_queue_depth(scsi_qla_host_t *ha, srb_t *sp) fcport->last_queue_full + ql2xqfullrampup * HZ)) return; - spin_unlock_irq(&ha->hardware_lock); starget_for_each_device(sdev->sdev_target, fcport, qla2x00_adjust_sdev_qdepth_up); - spin_lock_irq(&ha->hardware_lock); } /** @@ -923,10 +921,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) /* Adjust queue depth for all luns on the port. */ fcport->last_queue_full = jiffies; - spin_unlock_irq(&ha->hardware_lock); starget_for_each_device(cp->device->sdev_target, fcport, qla2x00_adjust_sdev_qdepth_down); - spin_lock_irq(&ha->hardware_lock); break; } if (lscsi_status != SS_CHECK_CONDITION) -- cgit v1.2.3 From 8880839815265ccc0edaff52ba08d750eea57acb Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:14:49 -0800 Subject: [SCSI] libsas: Clean up rphys/port dev list after a discovery error. sas_get_port_device assigns a rphy to a domain device in anticipation of finding a disk. When a discovery error occurs in sas_discover_{sata,sas,expander}*, however, we need to clean up that rphy and the port device list so that we don't GPF. In addition, we need to check the result of the second sas_notify_lldd_dev_found. This patch seems ok on a x260, x366 and x206m. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_discover.c | 39 ++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index fb7df7b75811..21f538e4a0b5 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -548,7 +548,7 @@ int sas_discover_sata(struct domain_device *dev) res = sas_notify_lldd_dev_found(dev); if (res) - return res; + goto out_err2; switch (dev->dev_type) { case SATA_DEV: @@ -560,11 +560,25 @@ int sas_discover_sata(struct domain_device *dev) default: break; } + if (res) + goto out_err; sas_notify_lldd_dev_gone(dev); - if (!res) { - sas_notify_lldd_dev_found(dev); - } + res = sas_notify_lldd_dev_found(dev); + if (res) + goto out_err2; + + res = sas_rphy_add(dev->rphy); + if (res) + goto out_err; + + return res; + +out_err: + sas_notify_lldd_dev_gone(dev); +out_err2: + sas_rphy_free(dev->rphy); + dev->rphy = NULL; return res; } @@ -580,7 +594,7 @@ int sas_discover_end_dev(struct domain_device *dev) res = sas_notify_lldd_dev_found(dev); if (res) - return res; + goto out_err2; res = sas_rphy_add(dev->rphy); if (res) @@ -589,12 +603,21 @@ int sas_discover_end_dev(struct domain_device *dev) /* do this to get the end device port attributes which will have * been scanned in sas_rphy_add */ sas_notify_lldd_dev_gone(dev); - sas_notify_lldd_dev_found(dev); + res = sas_notify_lldd_dev_found(dev); + if (res) + goto out_err3; return 0; out_err: sas_notify_lldd_dev_gone(dev); +out_err2: + sas_rphy_free(dev->rphy); + dev->rphy = NULL; + return res; +out_err3: + sas_rphy_delete(dev->rphy); + dev->rphy = NULL; return res; } @@ -686,6 +709,10 @@ static void sas_discover_domain(struct work_struct *work) } if (error) { + spin_lock(&port->dev_list_lock); + list_del_init(&port->port_dev->dev_list_node); + spin_unlock(&port->dev_list_lock); + kfree(port->port_dev); /* not kobject_register-ed yet */ port->port_dev = NULL; } -- cgit v1.2.3 From bf451207511d049189ddb0a4eae3acdb086a3c82 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:14:52 -0800 Subject: [SCSI] libsas: Clean up rphys/port dev list after a discovery error on an expander sas_get_port_device assigns a rphy to a domain device in anticipation of finding a disk. When a discovery error occurs in sas_discover_{sata,sas,expander}*, however, we need to clean up that rphy and the port device list so that we don't GPF. In addition, we need to check the result of the second sas_notify_lldd_dev_found. This patch seems ok on a x260, x366 and x206m. This patch fixes up sas_expander.c separately because jejb has some cleanup patches of his own that are a prerequisite. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_expander.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index d31e6fa466f7..0dfd97e7e96c 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -668,7 +668,6 @@ static struct domain_device *sas_ex_discover_end_dev( out_list_del: list_del(&child->dev_list_node); - sas_rphy_free(rphy); out_free: sas_port_delete(phy->port); out_err: @@ -1431,14 +1430,27 @@ int sas_discover_root_expander(struct domain_device *dev) int res; struct sas_expander_device *ex = rphy_to_expander_device(dev->rphy); - sas_rphy_add(dev->rphy); + res = sas_rphy_add(dev->rphy); + if (res) + goto out_err; ex->level = dev->port->disc.max_level; /* 0 */ res = sas_discover_expander(dev); - if (!res) - sas_ex_bfs_disc(dev->port); + if (res) + goto out_err2; + + sas_ex_bfs_disc(dev->port); return res; + +out_err2: + sas_rphy_delete(dev->rphy); + dev->rphy = NULL; + return res; +out_err: + sas_rphy_free(dev->rphy); + dev->rphy = NULL; + return res; } /* ---------- Domain revalidation ---------- */ -- cgit v1.2.3 From b218a0d8e250e0ae8fd4d4e45bd66a588b380752 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:14:55 -0800 Subject: [SCSI] libsas: Don't give scsi_cmnds to the EH if they never made it to the SAS LLDD or have already returned On a system with many SAS targets, it appears possible that a scsi_cmnd can time out without ever making it to the SAS LLDD or at the same time that a completion is occurring. In both of these cases, telling the LLDD to abort the sas_task makes no sense because the LLDD won't know about the sas_task; what we really want to do is to increase the timer. Note that this involves creating another sas_task bit to indicate whether or not the task has been sent to the LLDD; I could have implemented this by slightly redefining SAS_TASK_STATE_PENDING, but this way seems cleaner. This second version amends the aic94xx portion to set the TASK_AT_INITIATOR flag for all sas_tasks that were passed to lldd_execute_task. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_task.c | 9 +++++++++ drivers/scsi/libsas/sas_scsi_host.c | 7 +++++++ include/scsi/libsas.h | 1 + 3 files changed, 17 insertions(+) diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c index d202ed5a6709..e2ad5bed9403 100644 --- a/drivers/scsi/aic94xx/aic94xx_task.c +++ b/drivers/scsi/aic94xx/aic94xx_task.c @@ -349,6 +349,7 @@ Again: spin_lock_irqsave(&task->task_state_lock, flags); task->task_state_flags &= ~SAS_TASK_STATE_PENDING; + task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; task->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&task->task_state_lock, flags); @@ -557,6 +558,7 @@ int asd_execute_task(struct sas_task *task, const int num, struct sas_task *t = task; struct asd_ascb *ascb = NULL, *a; struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha; + unsigned long flags; res = asd_can_queue(asd_ha, num); if (res) @@ -599,6 +601,10 @@ int asd_execute_task(struct sas_task *task, const int num, } if (res) goto out_err_unmap; + + spin_lock_irqsave(&t->task_state_lock, flags); + t->task_state_flags |= SAS_TASK_AT_INITIATOR; + spin_unlock_irqrestore(&t->task_state_lock, flags); } list_del_init(&alist); @@ -617,6 +623,9 @@ out_err_unmap: if (a == b) break; t = a->uldd_task; + spin_lock_irqsave(&t->task_state_lock, flags); + t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; + spin_unlock_irqrestore(&t->task_state_lock, flags); switch (t->task_proto) { case SATA_PROTO: case SAS_PROTO_STP: diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 22672d54aa27..21bd24775980 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -542,6 +542,13 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) cmd, task); return EH_HANDLED; } + if (!(task->task_state_flags & SAS_TASK_AT_INITIATOR)) { + spin_unlock_irqrestore(&task->task_state_lock, flags); + SAS_DPRINTK("command 0x%p, task 0x%p, not at initiator: " + "EH_RESET_TIMER\n", + cmd, task); + return EH_RESET_TIMER; + } task->task_state_flags |= SAS_TASK_STATE_ABORTED; spin_unlock_irqrestore(&task->task_state_lock, flags); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 0c775fceb675..da96bcfb9e46 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -554,6 +554,7 @@ struct sas_task { #define SAS_TASK_STATE_DONE 2 #define SAS_TASK_STATE_ABORTED 4 #define SAS_TASK_INITIATOR_ABORTED 8 +#define SAS_TASK_AT_INITIATOR 16 static inline struct sas_task *sas_alloc_task(gfp_t flags) { -- cgit v1.2.3 From acbf167d4ad8c27f9743a4b539d51ae9535bf21c Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:14:57 -0800 Subject: [SCSI] libsas: Add a sysfs knob to enable/disable a phy This patch lets a user arbitrarily enable or disable a phy via sysfs. Potential applications include shutting down a phy to replace one lane of wide port, and (more importantly) providing a method for the libata SATL to control the phy. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_init.c | 35 +++++++++++++++++++++++-- drivers/scsi/libsas/sas_scsi_host.c | 1 + drivers/scsi/scsi_transport_sas.c | 51 +++++++++++++++++++++++++++++++++++++ include/scsi/libsas.h | 3 +++ include/scsi/scsi_transport_sas.h | 2 ++ 5 files changed, 90 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index 2f0c07fc3f48..90cce34cb6f5 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -146,6 +146,36 @@ static int sas_get_linkerrors(struct sas_phy *phy) return sas_smp_get_phy_events(phy); } +int sas_phy_enable(struct sas_phy *phy, int enable) +{ + int ret; + enum phy_func command; + + if (enable) + command = PHY_FUNC_LINK_RESET; + else + command = PHY_FUNC_DISABLE; + + if (scsi_is_sas_phy_local(phy)) { + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); + struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); + struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number]; + struct sas_internal *i = + to_sas_internal(sas_ha->core.shost->transportt); + + if (!enable) { + sas_phy_disconnected(asd_phy); + sas_ha->notify_phy_event(asd_phy, PHYE_LOSS_OF_SIGNAL); + } + ret = i->dft->lldd_control_phy(asd_phy, command, NULL); + } else { + struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); + struct domain_device *ddev = sas_find_dev_by_rphy(rphy); + ret = sas_smp_phy_control(ddev, phy->number, command, NULL); + } + return ret; +} + int sas_phy_reset(struct sas_phy *phy, int hard_reset) { int ret; @@ -172,8 +202,8 @@ int sas_phy_reset(struct sas_phy *phy, int hard_reset) return ret; } -static int sas_set_phy_speed(struct sas_phy *phy, - struct sas_phy_linkrates *rates) +int sas_set_phy_speed(struct sas_phy *phy, + struct sas_phy_linkrates *rates) { int ret; @@ -212,6 +242,7 @@ static int sas_set_phy_speed(struct sas_phy *phy, } static struct sas_function_template sft = { + .phy_enable = sas_phy_enable, .phy_reset = sas_phy_reset, .set_phy_speed = sas_set_phy_speed, .get_linkerrors = sas_get_linkerrors, diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 21bd24775980..7774eb3628ad 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -875,3 +875,4 @@ EXPORT_SYMBOL_GPL(sas_change_queue_type); EXPORT_SYMBOL_GPL(sas_bios_param); EXPORT_SYMBOL_GPL(sas_task_abort); EXPORT_SYMBOL_GPL(sas_phy_reset); +EXPORT_SYMBOL_GPL(sas_phy_enable); diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 5c0b75bbfa10..9e38c1894bb2 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -336,6 +336,51 @@ show_sas_device_type(struct class_device *cdev, char *buf) } static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); +static ssize_t do_sas_phy_enable(struct class_device *cdev, + size_t count, int enable) +{ + struct sas_phy *phy = transport_class_to_phy(cdev); + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); + struct sas_internal *i = to_sas_internal(shost->transportt); + int error; + + error = i->f->phy_enable(phy, enable); + if (error) + return error; + phy->enabled = enable; + return count; +}; + +static ssize_t store_sas_phy_enable(struct class_device *cdev, + const char *buf, size_t count) +{ + if (count < 1) + return -EINVAL; + + switch (buf[0]) { + case '0': + do_sas_phy_enable(cdev, count, 0); + break; + case '1': + do_sas_phy_enable(cdev, count, 1); + break; + default: + return -EINVAL; + } + + return count; +} + +static ssize_t show_sas_phy_enable(struct class_device *cdev, char *buf) +{ + struct sas_phy *phy = transport_class_to_phy(cdev); + + return snprintf(buf, 20, "%d", phy->enabled); +} + +static CLASS_DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable, + store_sas_phy_enable); + static ssize_t do_sas_phy_reset(struct class_device *cdev, size_t count, int hard_reset) { @@ -435,6 +480,7 @@ struct sas_phy *sas_phy_alloc(struct device *parent, int number) return NULL; phy->number = number; + phy->enabled = 1; device_initialize(&phy->dev); phy->dev.parent = get_device(parent); @@ -1389,6 +1435,10 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1, \ !i->f->set_phy_speed, S_IRUGO) +#define SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(field, func) \ + SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1, \ + !i->f->func, S_IRUGO) + #define SETUP_PORT_ATTRIBUTE(field) \ SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1) @@ -1479,6 +1529,7 @@ sas_attach_transport(struct sas_function_template *ft) SETUP_PHY_ATTRIBUTE(phy_reset_problem_count); SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(link_reset, phy_reset); SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(hard_reset, phy_reset); + SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(enable, phy_enable); i->phy_attrs[count] = NULL; count = 0; diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index da96bcfb9e46..0689d6682aa3 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -614,6 +614,9 @@ struct sas_domain_function_template { extern int sas_register_ha(struct sas_ha_struct *); extern int sas_unregister_ha(struct sas_ha_struct *); +int sas_set_phy_speed(struct sas_phy *phy, + struct sas_phy_linkrates *rates); +int sas_phy_enable(struct sas_phy *phy, int enabled); int sas_phy_reset(struct sas_phy *phy, int hard_reset); extern int sas_queuecommand(struct scsi_cmnd *, void (*scsi_done)(struct scsi_cmnd *)); diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 59633a82de47..45d58598c3ee 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -54,6 +54,7 @@ struct sas_identify { struct sas_phy { struct device dev; int number; + int enabled; /* phy identification */ struct sas_identify identify; @@ -163,6 +164,7 @@ struct sas_function_template { int (*get_enclosure_identifier)(struct sas_rphy *, u64 *); int (*get_bay_identifier)(struct sas_rphy *); int (*phy_reset)(struct sas_phy *, int); + int (*phy_enable)(struct sas_phy *, int); int (*set_phy_speed)(struct sas_phy *, struct sas_phy_linkrates *); }; -- cgit v1.2.3 From 6d4dcd4dae25c48e8932326aaedfe560d7f2c7bb Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:00 -0800 Subject: [SCSI] libsas: Reset timer on taskless scsi_cmnds in sas_scsi_timed_out Every so often, a scsi_cmnd will time out, and the libsas timeout handler will discover that the scsi_cmnd does not have a sas_task attached to it. This can happen in two cases: (1) the scsi_cmnd actually made it through libsas to the HBA and is now going through scsi_done, or (2) the scsi_cmnd has been held up (host lock, slab alloc, etc) and libsas has not yet attached a sas_task. In both cases, it is safe to ask SCSI for more time to process the command via EH_RESET_TIMER; we cannot blindly return EH_HANDLED because if (2) happens, we could end up calling scsi_done while another CPU is heading towards sas_queuecommand, which causes slab corruption when sas_task_done updates the freed scsi_cmnd. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_scsi_host.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 7774eb3628ad..3f647c695da5 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -524,9 +524,13 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) unsigned long flags; if (!task) { - SAS_DPRINTK("command 0x%p, task 0x%p, gone: EH_HANDLED\n", - cmd, task); - return EH_HANDLED; + cmd->timeout_per_command /= 2; + SAS_DPRINTK("command 0x%p, task 0x%p, gone: %s\n", + cmd, task, (cmd->timeout_per_command ? + "EH_RESET_TIMER" : "EH_NOT_HANDLED")); + if (!cmd->timeout_per_command) + return EH_NOT_HANDLED; + return EH_RESET_TIMER; } spin_lock_irqsave(&task->task_state_lock, flags); -- cgit v1.2.3 From cde3f74bac3e4a6bcdc3a6370af38179fd8ef1f2 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:03 -0800 Subject: [SCSI] libsas: Destroy the task collector thread after releasing ports If we use task collector mode, we can end up destroying the task collector thread before we release the ports, which is bad if a port release causes a disk I/O (such as cache flushing). Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index 90cce34cb6f5..4df73d69bb3c 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -127,12 +127,13 @@ Undo_phys: int sas_unregister_ha(struct sas_ha_struct *sas_ha) { + sas_unregister_ports(sas_ha); + if (sas_ha->lldd_max_execute_num > 1) { sas_shutdown_queue(sas_ha); + sas_ha->lldd_max_execute_num = 1; } - sas_unregister_ports(sas_ha); - return 0; } -- cgit v1.2.3 From f12164200f09ec10764f2cf96da335fd83062bc4 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:06 -0800 Subject: [SCSI] aic94xx: Set lldd_max_execute_num in sas_ha The aic94xx module has a parameter that looks like it should set lldd_max_execute_num in the sas_ha, but it never sets this value. Either we should set it or remove the parameter. This allows us to enable task collector mode for this driver, though it is still off by default. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index fbc82b00a418..9a9ea74c8d9e 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -526,6 +526,7 @@ static int asd_register_sas_ha(struct asd_ha_struct *asd_ha) asd_ha->sas_ha.num_phys= ASD_MAX_PHYS; asd_ha->sas_ha.lldd_queue_size = asd_ha->seq.can_queue; + asd_ha->sas_ha.lldd_max_execute_num = lldd_max_execute_num; return sas_register_ha(&asd_ha->sas_ha); } -- cgit v1.2.3 From c8490f3a77805d04321d9e44486a679801a035b8 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:09 -0800 Subject: [SCSI] libsas: Use SCAN_WILD_CARD instead of ~0 Magic number cleanup. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 9e38c1894bb2..e57b02e8afa5 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1283,7 +1283,7 @@ int sas_rphy_add(struct sas_rphy *rphy) if (identify->device_type == SAS_END_DEVICE && rphy->scsi_target_id != -1) { scsi_scan_target(&rphy->dev, 0, - rphy->scsi_target_id, ~0, 0); + rphy->scsi_target_id, SCAN_WILD_CARD, 0); } return 0; -- cgit v1.2.3 From 8f3b8fa9afe75cafc4feb317d305444f6c5271fb Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:12 -0800 Subject: [SCSI] aic94xx: Don't eat TMF_QUERY_TASK results In this driver, TMF_QUERY_TASK translates to QUERY_SSP_TASK. The sequencer, it seems, is perfectly happy sending us a SSP response, which this function promptly "converts" into TMF_RESP_FUNC_FAILED. This leads to the SAS EH making bad decisions based on bad data, so we should not perform the conversion in this case. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_tmf.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c index 61234384503b..fd5269e086a6 100644 --- a/drivers/scsi/aic94xx/aic94xx_tmf.c +++ b/drivers/scsi/aic94xx/aic94xx_tmf.c @@ -566,6 +566,11 @@ static int asd_initiate_ssp_tmf(struct domain_device *dev, u8 *lun, res = TMF_RESP_FUNC_ESUPP; break; default: + if (tmf == TMF_QUERY_TASK) { + ASD_DPRINTK("%s: QUERY_SSP_TASK response: 0x%x\n", + __FUNCTION__, res); + break; + } ASD_DPRINTK("%s: converting result 0x%x to TMF_RESP_FUNC_FAILED\n", __FUNCTION__, res); res = TMF_RESP_FUNC_FAILED; -- cgit v1.2.3 From 37958fb040cf6f88b354b9fa7e846014ffbd3b73 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:15 -0800 Subject: [SCSI] libsas: Remove SAS_TASK_INITIATOR_ABORTED flag This flag is no longer necessary because we push tasks to be aborted into the EH as soon as we possibly can, and let the SCSI EH code take care of the coordination for which this flag was used. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_scsi_host.c | 17 ----------------- include/scsi/libsas.h | 1 - 2 files changed, 18 deletions(-) diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 3f647c695da5..f90c332474c8 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -310,15 +310,6 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task) spin_unlock_irqrestore(&core->task_queue_lock, flags); } - spin_lock_irqsave(&task->task_state_lock, flags); - if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) { - spin_unlock_irqrestore(&task->task_state_lock, flags); - SAS_DPRINTK("%s: task 0x%p already aborted\n", - __FUNCTION__, task); - return TASK_IS_ABORTED; - } - spin_unlock_irqrestore(&task->task_state_lock, flags); - for (i = 0; i < 5; i++) { SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task); res = si->dft->lldd_abort_task(task); @@ -534,12 +525,6 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) } spin_lock_irqsave(&task->task_state_lock, flags); - if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) { - spin_unlock_irqrestore(&task->task_state_lock, flags); - SAS_DPRINTK("command 0x%p, task 0x%p, aborted by initiator: " - "EH_NOT_HANDLED\n", cmd, task); - return EH_NOT_HANDLED; - } if (task->task_state_flags & SAS_TASK_STATE_DONE) { spin_unlock_irqrestore(&task->task_state_lock, flags); SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", @@ -826,7 +811,6 @@ static int do_sas_task_abort(struct sas_task *task) return 0; } - task->task_state_flags |= SAS_TASK_INITIATOR_ABORTED; if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) task->task_state_flags |= SAS_TASK_STATE_ABORTED; spin_unlock_irqrestore(&task->task_state_lock, flags); @@ -849,7 +833,6 @@ static int do_sas_task_abort(struct sas_task *task) } spin_lock_irqsave(&task->task_state_lock, flags); - task->task_state_flags &= ~SAS_TASK_INITIATOR_ABORTED; if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) task->task_state_flags &= ~SAS_TASK_STATE_ABORTED; spin_unlock_irqrestore(&task->task_state_lock, flags); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 0689d6682aa3..1d394855b366 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -553,7 +553,6 @@ struct sas_task { #define SAS_TASK_STATE_PENDING 1 #define SAS_TASK_STATE_DONE 2 #define SAS_TASK_STATE_ABORTED 4 -#define SAS_TASK_INITIATOR_ABORTED 8 #define SAS_TASK_AT_INITIATOR 16 static inline struct sas_task *sas_alloc_task(gfp_t flags) -- cgit v1.2.3 From 3ebf6922b0833807e54c73f4794c74baf9945fc8 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:17 -0800 Subject: [SCSI] libsas: Enable the EH strategy handler to reset a phy after a command When a SAS LLDD needs to request a device port reset, it needs to have all commands aborted before it can reset the port. Since commands are put on the EH's list in the order that they were queued, the LLDD can set a "need reset" flag in the last task to be aborted so that the EH can reset the port after all commands are aborted. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_scsi_host.c | 37 ++++++++++++++++++++++++++++++++++++- include/scsi/libsas.h | 1 + 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index f90c332474c8..d0c04ebeb8b0 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -389,6 +389,19 @@ static int sas_recover_I_T(struct domain_device *dev) return res; } +static int eh_reset_phy_helper(struct sas_phy *phy) +{ + int tmf_resp; + + tmf_resp = sas_phy_reset(phy, 1); + if (tmf_resp) + SAS_DPRINTK("Hard reset of phy %d failed 0x%x\n", + phy->identify.phy_identifier, + tmf_resp); + + return tmf_resp; +} + void sas_scsi_recover_host(struct Scsi_Host *shost) { struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); @@ -396,8 +409,9 @@ void sas_scsi_recover_host(struct Scsi_Host *shost) LIST_HEAD(error_q); struct scsi_cmnd *cmd, *n; enum task_disposition res = TASK_IS_DONE; - int tmf_resp; + int tmf_resp, need_reset; struct sas_internal *i = to_sas_internal(shost->transportt); + struct sas_phy *task_sas_phy = NULL; spin_lock_irqsave(shost->host_lock, flags); list_splice_init(&shost->eh_cmd_q, &error_q); @@ -418,6 +432,13 @@ Again: SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__); continue; } + + spin_lock_irqsave(&task->task_state_lock, flags); + need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; + if (need_reset) + task_sas_phy = task->dev->port->phy; + spin_unlock_irqrestore(&task->task_state_lock, flags); + SAS_DPRINTK("trying to find task 0x%p\n", task); res = sas_scsi_find_task(task); @@ -428,11 +449,15 @@ Again: SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, task); task->task_done(task); + if (need_reset) + eh_reset_phy_helper(task_sas_phy); continue; case TASK_IS_ABORTED: SAS_DPRINTK("%s: task 0x%p is aborted\n", __FUNCTION__, task); task->task_done(task); + if (need_reset) + eh_reset_phy_helper(task_sas_phy); continue; case TASK_IS_AT_LU: SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); @@ -443,6 +468,8 @@ Again: SAS_ADDR(task->dev), cmd->device->lun); task->task_done(task); + if (need_reset) + eh_reset_phy_helper(task_sas_phy); sas_scsi_clear_queue_lu(&error_q, cmd); goto Again; } @@ -455,6 +482,8 @@ Again: SAS_DPRINTK("I_T %016llx recovered\n", SAS_ADDR(task->dev->sas_addr)); task->task_done(task); + if (need_reset) + eh_reset_phy_helper(task_sas_phy); sas_scsi_clear_queue_I_T(&error_q, task->dev); goto Again; } @@ -468,6 +497,8 @@ Again: SAS_DPRINTK("clear nexus port:%d " "succeeded\n", port->id); task->task_done(task); + if (need_reset) + eh_reset_phy_helper(task_sas_phy); sas_scsi_clear_queue_port(&error_q, port); goto Again; @@ -480,6 +511,8 @@ Again: SAS_DPRINTK("clear nexus ha " "succeeded\n"); task->task_done(task); + if (need_reset) + eh_reset_phy_helper(task_sas_phy); goto out; } } @@ -493,6 +526,8 @@ Again: cmd->device->lun); task->task_done(task); + if (need_reset) + eh_reset_phy_helper(task_sas_phy); goto clear_q; } } diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 1d394855b366..75df71f08ce1 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -553,6 +553,7 @@ struct sas_task { #define SAS_TASK_STATE_PENDING 1 #define SAS_TASK_STATE_DONE 2 #define SAS_TASK_STATE_ABORTED 4 +#define SAS_TASK_NEED_DEV_RESET 8 #define SAS_TASK_AT_INITIATOR 16 static inline struct sas_task *sas_alloc_task(gfp_t flags) -- cgit v1.2.3 From 396819fba821ad56f1b90090d256f0ab726c89c5 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:20 -0800 Subject: [SCSI] libsas: Delay issuing ABORT TASK TMF until the error handler sas_task_abort() should simply abort the upper-level SCSI command and wait until the error handler to send the actual ABORT TASK command. By deferring things to the EH we simplify the concurrency coordination and eliminate some race conditions. Note that sas_task_abort has a few hooks to handle libsas internal commands properly too. Also rename do_sas_task_abort to __sas_task_abort just in case we really want to abort the task *right now* and we don't have a scsi_cmnd attached to the command. This is a hook for libata internal commands to abort. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_scsi_host.c | 51 +++++++++++++++++++++---------------- include/scsi/libsas.h | 3 ++- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index d0c04ebeb8b0..f867455dd339 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -560,6 +560,7 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) } spin_lock_irqsave(&task->task_state_lock, flags); + BUG_ON(task->task_state_flags & SAS_TASK_STATE_ABORTED); if (task->task_state_flags & SAS_TASK_STATE_DONE) { spin_unlock_irqrestore(&task->task_state_lock, flags); SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", @@ -830,44 +831,42 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha) spin_unlock_irqrestore(&core->task_queue_lock, flags); } -static int do_sas_task_abort(struct sas_task *task) +/* + * Call the LLDD task abort routine directly. This function is intended for + * use by upper layers that need to tell the LLDD to abort a task. + */ +int __sas_task_abort(struct sas_task *task) { - struct scsi_cmnd *sc = task->uldd_task; struct sas_internal *si = to_sas_internal(task->dev->port->ha->core.shost->transportt); unsigned long flags; int res; spin_lock_irqsave(&task->task_state_lock, flags); - if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { + if (task->task_state_flags & SAS_TASK_STATE_ABORTED || + task->task_state_flags & SAS_TASK_STATE_DONE) { spin_unlock_irqrestore(&task->task_state_lock, flags); - SAS_DPRINTK("%s: Task %p already aborted.\n", __FUNCTION__, + SAS_DPRINTK("%s: Task %p already finished.\n", __FUNCTION__, task); return 0; } - - if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) - task->task_state_flags |= SAS_TASK_STATE_ABORTED; + task->task_state_flags |= SAS_TASK_STATE_ABORTED; spin_unlock_irqrestore(&task->task_state_lock, flags); if (!si->dft->lldd_abort_task) return -ENODEV; res = si->dft->lldd_abort_task(task); + + spin_lock_irqsave(&task->task_state_lock, flags); if ((task->task_state_flags & SAS_TASK_STATE_DONE) || (res == TMF_RESP_FUNC_COMPLETE)) { - /* SMP commands don't have scsi_cmds(?) */ - if (!sc) { - task->task_done(task); - return 0; - } - scsi_req_abort_cmd(sc); - scsi_schedule_eh(sc->device->host); + spin_unlock_irqrestore(&task->task_state_lock, flags); + task->task_done(task); return 0; } - spin_lock_irqsave(&task->task_state_lock, flags); if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) task->task_state_flags &= ~SAS_TASK_STATE_ABORTED; spin_unlock_irqrestore(&task->task_state_lock, flags); @@ -875,17 +874,24 @@ static int do_sas_task_abort(struct sas_task *task) return -EAGAIN; } -void sas_task_abort(struct work_struct *work) +/* + * Tell an upper layer that it needs to initiate an abort for a given task. + * This should only ever be called by an LLDD. + */ +void sas_task_abort(struct sas_task *task) { - struct sas_task *task = - container_of(work, struct sas_task, abort_work); - int i; + struct scsi_cmnd *sc = task->uldd_task; - for (i = 0; i < 5; i++) - if (!do_sas_task_abort(task)) + /* Escape for libsas internal commands */ + if (!sc) { + if (!del_timer(&task->timer)) return; + task->timer.function(task->timer.data); + return; + } - SAS_DPRINTK("%s: Could not kill task!\n", __FUNCTION__); + scsi_req_abort_cmd(sc); + scsi_schedule_eh(sc->device->host); } EXPORT_SYMBOL_GPL(sas_queuecommand); @@ -895,6 +901,7 @@ EXPORT_SYMBOL_GPL(sas_slave_destroy); EXPORT_SYMBOL_GPL(sas_change_queue_depth); EXPORT_SYMBOL_GPL(sas_change_queue_type); EXPORT_SYMBOL_GPL(sas_bios_param); +EXPORT_SYMBOL_GPL(__sas_task_abort); EXPORT_SYMBOL_GPL(sas_task_abort); EXPORT_SYMBOL_GPL(sas_phy_reset); EXPORT_SYMBOL_GPL(sas_phy_enable); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 75df71f08ce1..c83426344e8f 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -650,6 +650,7 @@ void sas_unregister_dev(struct domain_device *); void sas_init_dev(struct domain_device *); -void sas_task_abort(struct work_struct *); +void sas_task_abort(struct sas_task *); +int __sas_task_abort(struct sas_task *); #endif /* _SASLIB_H_ */ -- cgit v1.2.3 From 3cd041fb7f50f4cee3bc3a2b0ce02b1562894894 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:23 -0800 Subject: [SCSI] aic94xx: Remove workqueue code from REQ_TASK_ABORT/REQ_DEVICE_RESET code Now that task aborts and device port resets are done by the EH, we can remove all the code that set up workqueues and such and simply call sas_task_abort and let libsas figure things out. Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_scb.c | 122 ++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 56 deletions(-) diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index 75ed6b0569d1..8f43ff772f23 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c @@ -413,40 +413,6 @@ void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id) } } -/* hard reset a phy later */ -static void do_phy_reset_later(struct work_struct *work) -{ - struct sas_phy *sas_phy = - container_of(work, struct sas_phy, reset_work); - int error; - - ASD_DPRINTK("%s: About to hard reset phy %d\n", __FUNCTION__, - sas_phy->identify.phy_identifier); - /* Reset device port */ - error = sas_phy_reset(sas_phy, 1); - if (error) - ASD_DPRINTK("%s: Hard reset of phy %d failed (%d).\n", - __FUNCTION__, sas_phy->identify.phy_identifier, error); -} - -static void phy_reset_later(struct sas_phy *sas_phy, struct Scsi_Host *shost) -{ - INIT_WORK(&sas_phy->reset_work, do_phy_reset_later); - queue_work(shost->work_q, &sas_phy->reset_work); -} - -/* start up the ABORT TASK tmf... */ -static void task_kill_later(struct asd_ascb *ascb) -{ - struct asd_ha_struct *asd_ha = ascb->ha; - struct sas_ha_struct *sas_ha = &asd_ha->sas_ha; - struct Scsi_Host *shost = sas_ha->core.shost; - struct sas_task *task = ascb->uldd_task; - - INIT_WORK(&task->abort_work, sas_task_abort); - queue_work(shost->work_q, &task->abort_work); -} - static void escb_tasklet_complete(struct asd_ascb *ascb, struct done_list_struct *dl) { @@ -479,26 +445,55 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, case REQ_TASK_ABORT: { struct asd_ascb *a, *b; u16 tc_abort; + struct domain_device *failed_dev = NULL; + + ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n", + __FUNCTION__, dl->status_block[3]); + /* + * Find the task that caused the abort and abort it first. + * The sequencer won't put anything on the done list until + * that happens. + */ tc_abort = *((u16*)(&dl->status_block[1])); tc_abort = le16_to_cpu(tc_abort); - ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n", - __FUNCTION__, dl->status_block[3]); + list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) { + struct sas_task *task = ascb->uldd_task; - /* Find the pending task and abort it. */ - list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) - if (a->tc_index == tc_abort) { - task_kill_later(a); + if (task && a->tc_index == tc_abort) { + failed_dev = task->dev; + sas_task_abort(task); break; } + } + + if (!failed_dev) { + ASD_DPRINTK("%s: Can't find task (tc=%d) to abort!\n", + __FUNCTION__, tc_abort); + goto out; + } + + /* + * Now abort everything else for that device (hba?) so + * that the EH will wake up and do something. + */ + list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) { + struct sas_task *task = ascb->uldd_task; + + if (task && + task->dev == failed_dev && + a->tc_index != tc_abort) + sas_task_abort(task); + } + goto out; } case REQ_DEVICE_RESET: { - struct Scsi_Host *shost = sas_ha->core.shost; - struct sas_phy *dev_phy; struct asd_ascb *a; u16 conn_handle; + unsigned long flags; + struct sas_task *last_dev_task = NULL; conn_handle = *((u16*)(&dl->status_block[1])); conn_handle = le16_to_cpu(conn_handle); @@ -506,32 +501,47 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __FUNCTION__, dl->status_block[3]); - /* Kill all pending tasks and reset the device */ - dev_phy = NULL; + /* Find the last pending task for the device... */ list_for_each_entry(a, &asd_ha->seq.pend_q, list) { - struct sas_task *task; - struct domain_device *dev; u16 x; + struct domain_device *dev; + struct sas_task *task = a->uldd_task; - task = a->uldd_task; if (!task) continue; dev = task->dev; x = (unsigned long)dev->lldd_dev; - if (x == conn_handle) { - dev_phy = dev->port->phy; - task_kill_later(a); - } + if (x == conn_handle) + last_dev_task = task; } - /* Reset device port */ - if (!dev_phy) { - ASD_DPRINTK("%s: No pending commands; can't reset.\n", - __FUNCTION__); + if (!last_dev_task) { + ASD_DPRINTK("%s: Device reset for idle device %d?\n", + __FUNCTION__, conn_handle); goto out; } - phy_reset_later(dev_phy, shost); + + /* ...and set the reset flag */ + spin_lock_irqsave(&last_dev_task->task_state_lock, flags); + last_dev_task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; + spin_unlock_irqrestore(&last_dev_task->task_state_lock, flags); + + /* Kill all pending tasks for the device */ + list_for_each_entry(a, &asd_ha->seq.pend_q, list) { + u16 x; + struct domain_device *dev; + struct sas_task *task = a->uldd_task; + + if (!task) + continue; + dev = task->dev; + + x = (unsigned long)dev->lldd_dev; + if (x == conn_handle) + sas_task_abort(task); + } + goto out; } case SIGNAL_NCQ_ERROR: -- cgit v1.2.3 From bf2a1928f3e5d44934e974940a8260a57fcc8a58 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:26 -0800 Subject: [SCSI] aic94xx: Match request_firmware with release_firmware The vmalloc() blob holding the sequencer firmware wasn't being released at module unload time, which resulted in a memory leak. Signed-off-by: Alexis Bruemmer Acked-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_init.c | 1 + drivers/scsi/aic94xx/aic94xx_seq.c | 7 +++++++ drivers/scsi/aic94xx/aic94xx_seq.h | 1 + 3 files changed, 9 insertions(+) diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 9a9ea74c8d9e..6faa10f59c18 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -886,6 +886,7 @@ static void __exit aic94xx_exit(void) asd_remove_driver_attrs(&aic94xx_pci_driver.driver); pci_unregister_driver(&aic94xx_pci_driver); sas_release_transport(aic94xx_transport_template); + asd_release_firmware(); asd_destroy_global_caches(); asd_printk("%s version %s unloaded\n", ASD_DRIVER_DESCRIPTION, ASD_DRIVER_VERSION); diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c index 845112539d05..21569ecd8ec8 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.c +++ b/drivers/scsi/aic94xx/aic94xx_seq.c @@ -1232,6 +1232,13 @@ static int asd_seq_start_lseq(struct asd_ha_struct *asd_ha, int lseq) return asd_seq_unpause_lseq(asd_ha, lseq); } +int asd_release_firmware(void) +{ + if (sequencer_fw) + release_firmware(sequencer_fw); + return 0; +} + static int asd_request_firmware(struct asd_ha_struct *asd_ha) { int err, i; diff --git a/drivers/scsi/aic94xx/aic94xx_seq.h b/drivers/scsi/aic94xx/aic94xx_seq.h index 9e715e5496af..9437ff0ae3a4 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.h +++ b/drivers/scsi/aic94xx/aic94xx_seq.h @@ -63,6 +63,7 @@ int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask); int asd_unpause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask); int asd_init_seqs(struct asd_ha_struct *asd_ha); int asd_start_seqs(struct asd_ha_struct *asd_ha); +int asd_release_firmware(void); void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy); #endif -- cgit v1.2.3 From 3b709df5f7c83b6b0907217a248a1414a37ffcb6 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:29 -0800 Subject: [SCSI] aic94xx: Fix DDB and SCB initialization Ed Chim of Adaptec informs us that the DDB registers need to be zeroed at initialization time and that some SCB initializations need to happen even if we don't use the SCB. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_init.c | 2 +- drivers/scsi/aic94xx/aic94xx_sas.h | 1 + drivers/scsi/aic94xx/aic94xx_seq.c | 33 +++++++++++++++++++++++---------- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 6faa10f59c18..7344f4d59a7d 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -234,7 +234,7 @@ static int __devinit asd_common_setup(struct asd_ha_struct *asd_ha) } /* Provide some sane default values. */ asd_ha->hw_prof.max_scbs = 512; - asd_ha->hw_prof.max_ddbs = 128; + asd_ha->hw_prof.max_ddbs = ASD_MAX_DDBS; asd_ha->hw_prof.num_phys = ASD_MAX_PHYS; /* All phys are enabled, by default. */ asd_ha->hw_prof.enabled_phys = 0xFF; diff --git a/drivers/scsi/aic94xx/aic94xx_sas.h b/drivers/scsi/aic94xx/aic94xx_sas.h index 9050e93bfd5e..fa7c5290257d 100644 --- a/drivers/scsi/aic94xx/aic94xx_sas.h +++ b/drivers/scsi/aic94xx/aic94xx_sas.h @@ -34,6 +34,7 @@ * domain that this sequencer can maintain low-level connections for * us. They are be 64 bytes. */ +#define ASD_MAX_DDBS 128 struct asd_ddb_ssp_smp_target_port { u8 conn_type; /* byte 0 */ diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c index 21569ecd8ec8..0d343cfd4333 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.c +++ b/drivers/scsi/aic94xx/aic94xx_seq.c @@ -907,6 +907,16 @@ static void asd_init_scb_sites(struct asd_ha_struct *asd_ha) for (i = 0; i < ASD_SCB_SIZE; i += 4) asd_scbsite_write_dword(asd_ha, site_no, i, 0); + /* Initialize SCB Site Opcode field to invalid. */ + asd_scbsite_write_byte(asd_ha, site_no, + offsetof(struct scb_header, opcode), + 0xFF); + + /* Initialize SCB Site Flags field to mean a response + * frame has been received. This means inadvertent + * frames received to be dropped. */ + asd_scbsite_write_byte(asd_ha, site_no, 0x49, 0x01); + /* Workaround needed by SEQ to fix a SATA issue is to exclude * certain SCB sites from the free list. */ if (!SCB_SITE_VALID(site_no)) @@ -922,16 +932,6 @@ static void asd_init_scb_sites(struct asd_ha_struct *asd_ha) /* Q_NEXT field of the last SCB is invalidated. */ asd_scbsite_write_word(asd_ha, site_no, 0, first_scb_site_no); - /* Initialize SCB Site Opcode field to invalid. */ - asd_scbsite_write_byte(asd_ha, site_no, - offsetof(struct scb_header, opcode), - 0xFF); - - /* Initialize SCB Site Flags field to mean a response - * frame has been received. This means inadvertent - * frames received to be dropped. */ - asd_scbsite_write_byte(asd_ha, site_no, 0x49, 0x01); - first_scb_site_no = site_no; max_scbs++; } @@ -1173,6 +1173,16 @@ static void asd_init_ddb_0(struct asd_ha_struct *asd_ha) set_bit(0, asd_ha->hw_prof.ddb_bitmap); } +static void asd_seq_init_ddb_sites(struct asd_ha_struct *asd_ha) +{ + unsigned int i; + unsigned int ddb_site; + + for (ddb_site = 0 ; ddb_site < ASD_MAX_DDBS; ddb_site++) + for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4) + asd_ddbsite_write_dword(asd_ha, ddb_site, i, 0); +} + /** * asd_seq_setup_seqs -- setup and initialize central and link sequencers * @asd_ha: pointer to host adapter structure @@ -1182,6 +1192,9 @@ static void asd_seq_setup_seqs(struct asd_ha_struct *asd_ha) int lseq; u8 lseq_mask; + /* Initialize DDB sites */ + asd_seq_init_ddb_sites(asd_ha); + /* Initialize SCB sites. Done first to compute some values which * the rest of the init code depends on. */ asd_init_scb_sites(asd_ha); -- cgit v1.2.3 From 57ba07dc54b7657e69fe8ac42d83df21e415c85b Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:32 -0800 Subject: [SCSI] aic94xx: Lock DDB read/write accesses Extend the use of the DDB lock to include all DDB accesses, because DDB updates now occur from multiple threads. This fixes the SMP timeout problems that we were occasionally seeing with a x260, because the controller got confused when the DDBs got corrupted. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_dev.c | 16 ++++++++-------- drivers/scsi/aic94xx/aic94xx_seq.c | 3 +++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c index 6f8901b748f7..c520e5b41fb5 100644 --- a/drivers/scsi/aic94xx/aic94xx_dev.c +++ b/drivers/scsi/aic94xx/aic94xx_dev.c @@ -37,18 +37,14 @@ static inline int asd_get_ddb(struct asd_ha_struct *asd_ha) { - unsigned long flags; int ddb, i; - spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); ddb = FIND_FREE_DDB(asd_ha); if (ddb >= asd_ha->hw_prof.max_ddbs) { ddb = -ENOMEM; - spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); goto out; } SET_DDB(ddb, asd_ha); - spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4) asd_ddbsite_write_dword(asd_ha, ddb, i, 0); @@ -77,14 +73,10 @@ out: static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb) { - unsigned long flags; - if (!ddb || ddb >= 0xFFFF) return; asd_ddbsite_write_byte(asd_ha, ddb, DDB_TYPE, DDB_TYPE_UNUSED); - spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); CLEAR_DDB(ddb, asd_ha); - spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); } static inline void asd_set_ddb_type(struct domain_device *dev) @@ -320,8 +312,11 @@ out: int asd_dev_found(struct domain_device *dev) { + unsigned long flags; int res = 0; + struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; + spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); switch (dev->dev_type) { case SATA_PM: res = asd_init_sata_pm_ddb(dev); @@ -335,14 +330,18 @@ int asd_dev_found(struct domain_device *dev) else res = asd_init_initiator_ddb(dev); } + spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); + return res; } void asd_dev_gone(struct domain_device *dev) { int ddb, sister_ddb; + unsigned long flags; struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; + spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); ddb = (int) (unsigned long) dev->lldd_dev; sister_ddb = asd_ddbsite_read_word(asd_ha, ddb, SISTER_DDB); @@ -350,4 +349,5 @@ void asd_dev_gone(struct domain_device *dev) asd_free_ddb(asd_ha, sister_ddb); asd_free_ddb(asd_ha, ddb); dev->lldd_dev = NULL; + spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); } diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c index 0d343cfd4333..2768fe4d66ba 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.c +++ b/drivers/scsi/aic94xx/aic94xx_seq.c @@ -1395,7 +1395,9 @@ void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy) u8 phy_is_up; u8 mask; int i, err; + unsigned long flags; + spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); for_each_phy(phy_mask, mask, i) asd_ddbsite_write_byte(asd_ha, 0, offsetof(struct asd_ddb_seq_shared, @@ -1415,6 +1417,7 @@ void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy) break; } } + spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); if (err) asd_printk("couldn't update DDB 0:error:%d\n", err); -- cgit v1.2.3 From fe3b5bfe73ace420709f0cfb198b0ffc704bd38b Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:35 -0800 Subject: [SCSI] libsas: sysfs phy control attributes should not be S_IWUGO Allowing the phy reset controls to be world-triggerable does not seem like a terribly good idea because SAS devices can be disrupted (and ATA devices are really disrupted) by a phy reset. By default only root should be able to do things like that. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index e57b02e8afa5..bfbcf5fa72b9 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1446,10 +1446,10 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel, SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func) #define SETUP_PHY_ATTRIBUTE_WRONLY(field) \ - SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, 1) + SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, 1) #define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func) \ - SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, i->f->func) + SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, i->f->func) #define SETUP_END_DEV_ATTRIBUTE(field) \ SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1) -- cgit v1.2.3 From e7571c152dea576f8c80ca240befc93d4f16551d Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:38 -0800 Subject: [SCSI] aic94xx: Scan SAS devices asynchronously Add the necessary hooks to the aic94xx driver to support the asynchronous SCSI device scan infrastructure. Signed-off-by: Darrick J. Wong Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_init.c | 41 +++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 7344f4d59a7d..a6fb33f1412d 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -57,6 +57,8 @@ MODULE_PARM_DESC(collector, "\n" char sas_addr_str[2*SAS_ADDR_SIZE + 1] = ""; static struct scsi_transport_template *aic94xx_transport_template; +static int asd_scan_finished(struct Scsi_Host *, unsigned long); +static void asd_scan_start(struct Scsi_Host *); static struct scsi_host_template aic94xx_sht = { .module = THIS_MODULE, @@ -66,6 +68,8 @@ static struct scsi_host_template aic94xx_sht = { .target_alloc = sas_target_alloc, .slave_configure = sas_slave_configure, .slave_destroy = sas_slave_destroy, + .scan_finished = asd_scan_finished, + .scan_start = asd_scan_start, .change_queue_depth = sas_change_queue_depth, .change_queue_type = sas_change_queue_type, .bios_param = sas_bios_param, @@ -672,21 +676,10 @@ static int __devinit asd_pci_probe(struct pci_dev *dev, if (err) goto Err_reg_sas; - err = asd_enable_phys(asd_ha, asd_ha->hw_prof.enabled_phys); - if (err) { - asd_printk("coudln't enable phys, err:%d\n", err); - goto Err_en_phys; - } - ASD_DPRINTK("enabled phys\n"); - /* give the phy enabling interrupt event time to come in (1s - * is empirically about all it takes) */ - ssleep(1); - /* Wait for discovery to finish */ - scsi_flush_work(asd_ha->sas_ha.core.shost); + scsi_scan_host(shost); return 0; -Err_en_phys: - asd_unregister_sas_ha(asd_ha); + Err_reg_sas: asd_remove_dev_attrs(asd_ha); Err_dev_attrs: @@ -779,6 +772,28 @@ static void __devexit asd_pci_remove(struct pci_dev *dev) return; } +static void asd_scan_start(struct Scsi_Host *shost) +{ + struct asd_ha_struct *asd_ha; + int err; + + asd_ha = SHOST_TO_SAS_HA(shost)->lldd_ha; + err = asd_enable_phys(asd_ha, asd_ha->hw_prof.enabled_phys); + if (err) + asd_printk("Couldn't enable phys, err:%d\n", err); +} + +static int asd_scan_finished(struct Scsi_Host *shost, unsigned long time) +{ + /* give the phy enabling interrupt event time to come in (1s + * is empirically about all it takes) */ + if (time < HZ) + return 0; + /* Wait for discovery to finish */ + scsi_flush_work(shost); + return 1; +} + static ssize_t asd_version_show(struct device_driver *driver, char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", ASD_DRIVER_VERSION); -- cgit v1.2.3 From 980fa2f9d64b9be96107c89e165953ace311af54 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:40 -0800 Subject: [SCSI] libsas: phy port lock needs irq spinlocks Convert the phy port locks to use irq spinlocks. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_port.c | 12 +++++++----- drivers/scsi/libsas/sas_scsi_host.c | 5 +++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index 971c37ceecb4..a796ae31430e 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c @@ -42,6 +42,7 @@ static void sas_form_port(struct asd_sas_phy *phy) struct asd_sas_port *port = phy->port; struct sas_internal *si = to_sas_internal(sas_ha->core.shost->transportt); + unsigned long flags; if (port) { if (memcmp(port->attached_sas_addr, phy->attached_sas_addr, @@ -56,7 +57,7 @@ static void sas_form_port(struct asd_sas_phy *phy) } /* find a port */ - spin_lock(&sas_ha->phy_port_lock); + spin_lock_irqsave(&sas_ha->phy_port_lock, flags); for (i = 0; i < sas_ha->num_phys; i++) { port = sas_ha->sas_port[i]; spin_lock(&port->phy_list_lock); @@ -78,7 +79,7 @@ static void sas_form_port(struct asd_sas_phy *phy) if (i >= sas_ha->num_phys) { printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n", __FUNCTION__); - spin_unlock(&sas_ha->phy_port_lock); + spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags); return; } @@ -105,7 +106,7 @@ static void sas_form_port(struct asd_sas_phy *phy) } else port->linkrate = max(port->linkrate, phy->linkrate); spin_unlock(&port->phy_list_lock); - spin_unlock(&sas_ha->phy_port_lock); + spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags); if (!port->port) { port->port = sas_port_alloc(phy->phy->dev.parent, port->id); @@ -137,6 +138,7 @@ void sas_deform_port(struct asd_sas_phy *phy) struct asd_sas_port *port = phy->port; struct sas_internal *si = to_sas_internal(sas_ha->core.shost->transportt); + unsigned long flags; if (!port) return; /* done by a phy event */ @@ -155,7 +157,7 @@ void sas_deform_port(struct asd_sas_phy *phy) if (si->dft->lldd_port_deformed) si->dft->lldd_port_deformed(phy); - spin_lock(&sas_ha->phy_port_lock); + spin_lock_irqsave(&sas_ha->phy_port_lock, flags); spin_lock(&port->phy_list_lock); list_del_init(&phy->port_phy_el); @@ -174,7 +176,7 @@ void sas_deform_port(struct asd_sas_phy *phy) port->phy_mask = 0; } spin_unlock(&port->phy_list_lock); - spin_unlock(&sas_ha->phy_port_lock); + spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags); return; } diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index f867455dd339..8a1b98e3943c 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -589,8 +589,9 @@ struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy) struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); struct domain_device *found_dev = NULL; int i; + unsigned long flags; - spin_lock(&ha->phy_port_lock); + spin_lock_irqsave(&ha->phy_port_lock, flags); for (i = 0; i < ha->num_phys; i++) { struct asd_sas_port *port = ha->sas_port[i]; struct domain_device *dev; @@ -606,7 +607,7 @@ struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy) spin_unlock(&port->dev_list_lock); } found: - spin_unlock(&ha->phy_port_lock); + spin_unlock_irqrestore(&ha->phy_port_lock, flags); return found_dev; } -- cgit v1.2.3 From 6b0efb8516a5298e12033df61f9e0c376a306adb Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:43 -0800 Subject: [SCSI] libsas: Add SAS_HA state flags to avoid queueing events while unloading Track sas_ha_struct state so that we ignore events that come in while we're shutting things down. Signed-off-by: Malahal Naineni Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_discover.c | 2 +- drivers/scsi/libsas/sas_event.c | 6 +++--- drivers/scsi/libsas/sas_init.c | 12 ++++++++++++ drivers/scsi/libsas/sas_internal.h | 9 +++++++-- include/scsi/libsas.h | 8 ++++++++ 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index 21f538e4a0b5..b6ba0e053d1a 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -753,7 +753,7 @@ int sas_discover_event(struct asd_sas_port *port, enum discover_event ev) BUG_ON(ev >= DISC_NUM_EVENTS); sas_queue_event(ev, &disc->disc_event_lock, &disc->pending, - &disc->disc_work[ev].work, port->ha->core.shost); + &disc->disc_work[ev].work, port->ha); return 0; } diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c index d83392ee6823..9db30fb5caf2 100644 --- a/drivers/scsi/libsas/sas_event.c +++ b/drivers/scsi/libsas/sas_event.c @@ -31,7 +31,7 @@ static void notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event) BUG_ON(event >= HA_NUM_EVENTS); sas_queue_event(event, &sas_ha->event_lock, &sas_ha->pending, - &sas_ha->ha_events[event].work, sas_ha->core.shost); + &sas_ha->ha_events[event].work, sas_ha); } static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) @@ -41,7 +41,7 @@ static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) BUG_ON(event >= PORT_NUM_EVENTS); sas_queue_event(event, &ha->event_lock, &phy->port_events_pending, - &phy->port_events[event].work, ha->core.shost); + &phy->port_events[event].work, ha); } static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) @@ -51,7 +51,7 @@ static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) BUG_ON(event >= PHY_NUM_EVENTS); sas_queue_event(event, &ha->event_lock, &phy->phy_events_pending, - &phy->phy_events[event].work, ha->core.shost); + &phy->phy_events[event].work, ha); } int sas_init_events(struct sas_ha_struct *sas_ha) diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index 4df73d69bb3c..965698c8b7bf 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -87,6 +87,9 @@ int sas_register_ha(struct sas_ha_struct *sas_ha) else if (sas_ha->lldd_queue_size == -1) sas_ha->lldd_queue_size = 128; /* Sanity */ + sas_ha->state = SAS_HA_REGISTERED; + spin_lock_init(&sas_ha->state_lock); + error = sas_register_phys(sas_ha); if (error) { printk(KERN_NOTICE "couldn't register sas phys:%d\n", error); @@ -127,6 +130,15 @@ Undo_phys: int sas_unregister_ha(struct sas_ha_struct *sas_ha) { + unsigned long flags; + + /* Set the state to unregistered to avoid further + * events to be queued */ + spin_lock_irqsave(&sas_ha->state_lock, flags); + sas_ha->state = SAS_HA_UNREGISTERED; + spin_unlock_irqrestore(&sas_ha->state_lock, flags); + scsi_flush_work(sas_ha->core.shost); + sas_unregister_ports(sas_ha); if (sas_ha->lldd_max_execute_num > 1) { diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index 137d7e496b6d..a78638df2018 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -80,7 +80,7 @@ void sas_hae_reset(struct work_struct *work); static inline void sas_queue_event(int event, spinlock_t *lock, unsigned long *pending, struct work_struct *work, - struct Scsi_Host *shost) + struct sas_ha_struct *sas_ha) { unsigned long flags; @@ -91,7 +91,12 @@ static inline void sas_queue_event(int event, spinlock_t *lock, } __set_bit(event, pending); spin_unlock_irqrestore(lock, flags); - scsi_queue_work(shost, work); + + spin_lock_irqsave(&sas_ha->state_lock, flags); + if (sas_ha->state != SAS_HA_UNREGISTERED) { + scsi_queue_work(sas_ha->core.shost, work); + } + spin_unlock_irqrestore(&sas_ha->state_lock, flags); } static inline void sas_begin_event(int event, spinlock_t *lock, diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index c83426344e8f..ca393929c10b 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -323,12 +323,20 @@ struct sas_ha_event { struct sas_ha_struct *ha; }; +enum sas_ha_state { + SAS_HA_REGISTERED, + SAS_HA_UNREGISTERED +}; + struct sas_ha_struct { /* private: */ spinlock_t event_lock; struct sas_ha_event ha_events[HA_NUM_EVENTS]; unsigned long pending; + enum sas_ha_state state; + spinlock_t state_lock; + struct scsi_core core; /* public: */ -- cgit v1.2.3 From 02cd743bb3a37f27681c487608fb819493fa4010 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 11 Jan 2007 14:15:46 -0800 Subject: [SCSI] libsas: Start I_T recovery if ABORT TASK fails The EH should fall into I_T recovery (and potentially stronger remedies) if ABORT TASK fails. Signed-off-by: Alexis Bruemmer Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_scsi_host.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 8a1b98e3943c..9ffe7605fb9d 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -281,6 +281,7 @@ enum task_disposition { TASK_IS_ABORTED, TASK_IS_AT_LU, TASK_IS_NOT_AT_LU, + TASK_ABORT_FAILED, }; static enum task_disposition sas_scsi_find_task(struct sas_task *task) @@ -331,15 +332,21 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task) SAS_DPRINTK("%s: querying task 0x%p\n", __FUNCTION__, task); res = si->dft->lldd_query_task(task); - if (res == TMF_RESP_FUNC_SUCC) { + switch (res) { + case TMF_RESP_FUNC_SUCC: SAS_DPRINTK("%s: task 0x%p at LU\n", __FUNCTION__, task); return TASK_IS_AT_LU; - } else if (res == TMF_RESP_FUNC_COMPLETE) { + case TMF_RESP_FUNC_COMPLETE: SAS_DPRINTK("%s: task 0x%p not at LU\n", __FUNCTION__, task); return TASK_IS_NOT_AT_LU; - } + case TMF_RESP_FUNC_FAILED: + SAS_DPRINTK("%s: task 0x%p failed to abort\n", + __FUNCTION__, task); + return TASK_ABORT_FAILED; + } + } } return res; @@ -475,6 +482,7 @@ Again: } /* fallthrough */ case TASK_IS_NOT_AT_LU: + case TASK_ABORT_FAILED: SAS_DPRINTK("task 0x%p is not at LU: I_T recover\n", task); tmf_resp = sas_recover_I_T(task->dev); -- cgit v1.2.3 From 86b9c4c16a1589d05959af2d96d52a4352c6306e Mon Sep 17 00:00:00 2001 From: Alexis Bruemmer Date: Tue, 16 Jan 2007 15:36:12 -0800 Subject: [SCSI] aic94xx: fix typos and update verison number fix typos and bump version number Signed-off-by: Darrick J. Wong Acked-by: Alexis Bruemmer Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_init.c | 2 +- drivers/scsi/aic94xx/aic94xx_sds.c | 10 +++++----- drivers/scsi/scsi_transport_sas.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index a6fb33f1412d..421e98e1d522 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -38,7 +38,7 @@ #include "aic94xx_seq.h" /* The format is "version.release.patchlevel" */ -#define ASD_DRIVER_VERSION "1.0.2" +#define ASD_DRIVER_VERSION "1.0.3" static int use_msi = 0; module_param_named(use_msi, use_msi, int, S_IRUGO); diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c index e5a0ec37e954..5b0932f61473 100644 --- a/drivers/scsi/aic94xx/aic94xx_sds.c +++ b/drivers/scsi/aic94xx/aic94xx_sds.c @@ -427,7 +427,7 @@ struct asd_manuf_sec { struct asd_manuf_phy_desc { u8 state; /* low 4 bits */ -#define MS_PHY_STATE_ENABLEABLE 0 +#define MS_PHY_STATE_ENABLED 0 #define MS_PHY_STATE_REPORTED 1 #define MS_PHY_STATE_HIDDEN 2 u8 phy_id; @@ -756,11 +756,11 @@ static void *asd_find_ll_by_id(void * const start, const u8 id0, const u8 id1) * * HIDDEN phys do not count in the total count. REPORTED phys cannot * be enabled but are reported and counted towards the total. - * ENEBLEABLE phys are enabled by default and count towards the total. + * ENABLED phys are enabled by default and count towards the total. * The absolute total phy number is ASD_MAX_PHYS. hw_prof->num_phys * merely specifies the number of phys the host adapter decided to * report. E.g., it is possible for phys 0, 1 and 2 to be HIDDEN, - * phys 3, 4 and 5 to be REPORTED and phys 6 and 7 to be ENEBLEABLE. + * phys 3, 4 and 5 to be REPORTED and phys 6 and 7 to be ENABLED. * In this case ASD_MAX_PHYS is 8, hw_prof->num_phys is 5, and only 2 * are actually enabled (enabled by default, max number of phys * enableable in this case). @@ -816,8 +816,8 @@ static int asd_ms_get_phy_params(struct asd_ha_struct *asd_ha, asd_ha->hw_prof.enabled_phys &= ~(1 << i); rep_phys++; continue; - case MS_PHY_STATE_ENABLEABLE: - ASD_DPRINTK("ms: phy%d: ENEBLEABLE\n", i); + case MS_PHY_STATE_ENABLED: + ASD_DPRINTK("ms: phy%d: ENABLED\n", i); asd_ha->hw_prof.enabled_phys |= (1 << i); en_phys++; break; diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index bfbcf5fa72b9..ce232803f433 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1638,7 +1638,7 @@ static void __exit sas_transport_exit(void) } MODULE_AUTHOR("Christoph Hellwig"); -MODULE_DESCRIPTION("SAS Transphy Attributes"); +MODULE_DESCRIPTION("SAS Transport Attributes"); MODULE_LICENSE("GPL"); module_init(sas_transport_init); -- cgit v1.2.3 From eae225eb5947825bc4e845c33ded9aedd74407cf Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 19 Jan 2007 18:46:17 -0700 Subject: [SCSI] fusion: mpi header update - version 1.05.14 Here are the lastest mpi headers for mpt fusion driver, which defines the firmware to driver interface. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/lsi/mpi.h | 7 +- drivers/message/fusion/lsi/mpi_cnfg.h | 131 ++++++++++--- drivers/message/fusion/lsi/mpi_history.txt | 77 +++++--- drivers/message/fusion/lsi/mpi_init.h | 7 +- drivers/message/fusion/lsi/mpi_ioc.h | 75 +++++++- drivers/message/fusion/lsi/mpi_log_sas.h | 284 +++++++++++++++++------------ drivers/message/fusion/lsi/mpi_sas.h | 9 +- 7 files changed, 410 insertions(+), 180 deletions(-) diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h index 81ad77622dac..75223bf24ae8 100644 --- a/drivers/message/fusion/lsi/mpi.h +++ b/drivers/message/fusion/lsi/mpi.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2005 LSI Logic Corporation. + * Copyright (c) 2000-2006 LSI Logic Corporation. * * * Name: mpi.h * Title: MPI Message independent structures and definitions * Creation Date: July 27, 2000 * - * mpi.h Version: 01.05.11 + * mpi.h Version: 01.05.12 * * Version History * --------------- @@ -77,6 +77,7 @@ * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT. * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target. * 03-27-06 01.05.11 Bumped MPI_HEADER_VERSION_UNIT. + * 10-11-06 01.05.12 Bumped MPI_HEADER_VERSION_UNIT. * -------------------------------------------------------------------------- */ @@ -107,7 +108,7 @@ /* Note: The major versions of 0xe0 through 0xff are reserved */ /* versioning for this MPI header set */ -#define MPI_HEADER_VERSION_UNIT (0x0D) +#define MPI_HEADER_VERSION_UNIT (0x0E) #define MPI_HEADER_VERSION_DEV (0x00) #define MPI_HEADER_VERSION_UNIT_MASK (0xFF00) #define MPI_HEADER_VERSION_UNIT_SHIFT (8) diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h index 47e13e360c10..0e4c8e77a81d 100644 --- a/drivers/message/fusion/lsi/mpi_cnfg.h +++ b/drivers/message/fusion/lsi/mpi_cnfg.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2005 LSI Logic Corporation. + * Copyright (c) 2000-2006 LSI Logic Corporation. * * * Name: mpi_cnfg.h * Title: MPI Config message, structures, and Pages * Creation Date: July 27, 2000 * - * mpi_cnfg.h Version: 01.05.12 + * mpi_cnfg.h Version: 01.05.13 * * Version History * --------------- @@ -276,6 +276,23 @@ * Added AdditionalControlFlags, MaxTargetPortConnectTime, * ReportDeviceMissingDelay, and IODeviceMissingDelay * fields to SAS IO Unit Page 1. + * 10-11-06 01.05.13 Added NumForceWWID field and ForceWWID array to + * Manufacturing Page 5. + * Added Manufacturing pages 8 through 10. + * Added defines for supported metadata size bits in + * CapabilitiesFlags field of IOC Page 6. + * Added defines for metadata size bits in VolumeSettings + * field of RAID Volume Page 0. + * Added SATA Link Reset settings, Enable SATA Asynchronous + * Notification bit, and HideNonZeroAttachedPhyIdentifiers + * bit to AdditionalControlFlags field of SAS IO Unit + * Page 1. + * Added defines for Enclosure Devices Unmapped and + * Device Limit Exceeded bits in Status field of SAS IO + * Unit Page 2. + * Added more AccessStatus values for SAS Device Page 0. + * Added bit for SATA Asynchronous Notification Support in + * Flags field of SAS Device Page 0. * -------------------------------------------------------------------------- */ @@ -654,17 +671,24 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4 #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01) +#ifndef MPI_MANPAGE5_NUM_FORCEWWID +#define MPI_MANPAGE5_NUM_FORCEWWID (1) +#endif + typedef struct _CONFIG_PAGE_MANUFACTURING_5 { CONFIG_PAGE_HEADER Header; /* 00h */ U64 BaseWWID; /* 04h */ U8 Flags; /* 0Ch */ - U8 Reserved1; /* 0Dh */ + U8 NumForceWWID; /* 0Dh */ U16 Reserved2; /* 0Eh */ + U32 Reserved3; /* 10h */ + U32 Reserved4; /* 14h */ + U64 ForceWWID[MPI_MANPAGE5_NUM_FORCEWWID]; /* 18h */ } CONFIG_PAGE_MANUFACTURING_5, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_5, ManufacturingPage5_t, MPI_POINTER pManufacturingPage5_t; -#define MPI_MANUFACTURING5_PAGEVERSION (0x01) +#define MPI_MANUFACTURING5_PAGEVERSION (0x02) /* defines for the Flags field */ #define MPI_MANPAGE5_TWO_WWID_PER_PHY (0x01) @@ -740,6 +764,36 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_7 #define MPI_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001) +typedef struct _CONFIG_PAGE_MANUFACTURING_8 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 ProductSpecificInfo;/* 04h */ +} CONFIG_PAGE_MANUFACTURING_8, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_8, + ManufacturingPage8_t, MPI_POINTER pManufacturingPage8_t; + +#define MPI_MANUFACTURING8_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_MANUFACTURING_9 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 ProductSpecificInfo;/* 04h */ +} CONFIG_PAGE_MANUFACTURING_9, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_9, + ManufacturingPage9_t, MPI_POINTER pManufacturingPage9_t; + +#define MPI_MANUFACTURING6_PAGEVERSION (0x00) + + +typedef struct _CONFIG_PAGE_MANUFACTURING_10 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + U32 ProductSpecificInfo;/* 04h */ +} CONFIG_PAGE_MANUFACTURING_10, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_10, + ManufacturingPage10_t, MPI_POINTER pManufacturingPage10_t; + +#define MPI_MANUFACTURING10_PAGEVERSION (0x00) + + /**************************************************************************** * IO Unit Config Pages ****************************************************************************/ @@ -1080,10 +1134,14 @@ typedef struct _CONFIG_PAGE_IOC_6 } CONFIG_PAGE_IOC_6, MPI_POINTER PTR_CONFIG_PAGE_IOC_6, IOCPage6_t, MPI_POINTER pIOCPage6_t; -#define MPI_IOCPAGE6_PAGEVERSION (0x00) +#define MPI_IOCPAGE6_PAGEVERSION (0x01) /* IOC Page 6 Capabilities Flags */ +#define MPI_IOCPAGE6_CAP_FLAGS_MASK_METADATA_SIZE (0x00000006) +#define MPI_IOCPAGE6_CAP_FLAGS_64MB_METADATA_SIZE (0x00000000) +#define MPI_IOCPAGE6_CAP_FLAGS_512MB_METADATA_SIZE (0x00000002) + #define MPI_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE (0x00000001) @@ -2160,6 +2218,11 @@ typedef struct _RAID_VOL0_SETTINGS #define MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE (0x0004) #define MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC (0x0008) #define MPI_RAIDVOL0_SETTING_FAST_DATA_SCRUBBING_0102 (0x0020) /* obsolete */ + +#define MPI_RAIDVOL0_SETTING_MASK_METADATA_SIZE (0x00C0) +#define MPI_RAIDVOL0_SETTING_64MB_METADATA_SIZE (0x0000) +#define MPI_RAIDVOL0_SETTING_512MB_METADATA_SIZE (0x0040) + #define MPI_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0010) #define MPI_RAIDVOL0_SETTING_USE_DEFAULTS (0x8000) @@ -2203,7 +2266,7 @@ typedef struct _CONFIG_PAGE_RAID_VOL_0 } CONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0, RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t; -#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x06) +#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x07) /* values for RAID Volume Page 0 InactiveStatus field */ #define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00) @@ -2518,7 +2581,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1 } CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1, SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t; -#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x06) +#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x07) /* values for SAS IO Unit Page 1 ControlFlags */ #define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000) @@ -2544,7 +2607,13 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1 #define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) /* values for SAS IO Unit Page 1 AdditionalControlFlags */ -#define MPI_SAS_IOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001) +#define MPI_SAS_IOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040) +#define MPI_SAS_IOUNIT1_ACONTROL_HIDE_NONZERO_ATTACHED_PHY_IDENT (0x0020) +#define MPI_SAS_IOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010) +#define MPI_SAS_IOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008) +#define MPI_SAS_IOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004) +#define MPI_SAS_IOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002) +#define MPI_SAS_IOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001) /* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */ #define MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK (0x7F) @@ -2585,9 +2654,11 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2 } CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2, SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t; -#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x05) +#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x06) /* values for SAS IO Unit Page 2 Status field */ +#define MPI_SAS_IOUNIT2_STATUS_DEVICE_LIMIT_EXCEEDED (0x08) +#define MPI_SAS_IOUNIT2_STATUS_ENCLOSURE_DEVICES_UNMAPPED (0x04) #define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02) #define MPI_SAS_IOUNIT2_STATUS_FULL_PERSISTENT_MAPPINGS (0x01) @@ -2739,24 +2810,38 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_0 } CONFIG_PAGE_SAS_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_0, SasDevicePage0_t, MPI_POINTER pSasDevicePage0_t; -#define MPI_SASDEVICE0_PAGEVERSION (0x04) +#define MPI_SASDEVICE0_PAGEVERSION (0x05) /* values for SAS Device Page 0 AccessStatus field */ -#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00) -#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01) -#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02) +#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00) +#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01) +#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02) +#define MPI_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT (0x03) +/* specific values for SATA Init failures */ +#define MPI_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN (0x10) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x11) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_DIAG (0x12) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x13) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x14) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_PIO_SN (0x15) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN (0x16) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN (0x17) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x18) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x19) +#define MPI_SAS_DEVICE0_ASTATUS_SIF_MAX (0x1F) /* values for SAS Device Page 0 Flags field */ -#define MPI_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200) -#define MPI_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100) -#define MPI_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080) -#define MPI_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040) -#define MPI_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020) -#define MPI_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010) -#define MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008) -#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT (0x0004) -#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED (0x0002) -#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) +#define MPI_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY (0x0400) +#define MPI_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200) +#define MPI_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100) +#define MPI_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080) +#define MPI_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040) +#define MPI_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020) +#define MPI_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010) +#define MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008) +#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT (0x0004) +#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED (0x0002) +#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) /* see mpi_sas.h for values for SAS Device Page 0 DeviceInfo values */ diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt index 582cfe7c2aa1..d6b4c607453b 100644 --- a/drivers/message/fusion/lsi/mpi_history.txt +++ b/drivers/message/fusion/lsi/mpi_history.txt @@ -3,28 +3,28 @@ MPI Header File Change History ============================== - Copyright (c) 2000-2005 LSI Logic Corporation. + Copyright (c) 2000-2006 LSI Logic Corporation. --------------------------------------- - Header Set Release Version: 01.05.13 - Header Set Release Date: 03-27-06 + Header Set Release Version: 01.05.14 + Header Set Release Date: 10-11-06 --------------------------------------- Filename Current version Prior version ---------- --------------- ------------- - mpi.h 01.05.11 01.05.10 - mpi_ioc.h 01.05.11 01.05.10 - mpi_cnfg.h 01.05.12 01.05.11 - mpi_init.h 01.05.07 01.05.06 - mpi_targ.h 01.05.06 01.05.05 + mpi.h 01.05.12 01.05.11 + mpi_ioc.h 01.05.12 01.05.11 + mpi_cnfg.h 01.05.13 01.05.12 + mpi_init.h 01.05.08 01.05.07 + mpi_targ.h 01.05.06 01.05.06 mpi_fc.h 01.05.01 01.05.01 mpi_lan.h 01.05.01 01.05.01 mpi_raid.h 01.05.02 01.05.02 mpi_tool.h 01.05.03 01.05.03 mpi_inb.h 01.05.01 01.05.01 - mpi_sas.h 01.05.03 01.05.02 + mpi_sas.h 01.05.04 01.05.03 mpi_type.h 01.05.02 01.05.02 - mpi_history.txt 01.05.13 01.05.12 + mpi_history.txt 01.05.14 01.05.13 * Date Version Description @@ -94,6 +94,7 @@ mpi.h * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT. * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target. * 03-27-06 01.05.11 Bumped MPI_HEADER_VERSION_UNIT. + * 10-11-06 01.05.12 Bumped MPI_HEADER_VERSION_UNIT. * -------------------------------------------------------------------------- mpi_ioc.h @@ -182,6 +183,14 @@ mpi_ioc.h * Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event * data structure. * Added MPI_EXT_IMAGE_TYPE_INITIALIZATION. + * 10-11-06 01.05.12 Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED. + * Added MaxInitiators field to PortFacts reply. + * Added SAS Device Status Change ReasonCode for + * asynchronous notificaiton. + * Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event + * data structure. + * Added new ImageType values for FWDownload and FWUpload + * requests. * -------------------------------------------------------------------------- mpi_cnfg.h @@ -447,6 +456,23 @@ mpi_cnfg.h * Added AdditionalControlFlags, MaxTargetPortConnectTime, * ReportDeviceMissingDelay, and IODeviceMissingDelay * fields to SAS IO Unit Page 1. + * 10-11-06 01.05.13 Added NumForceWWID field and ForceWWID array to + * Manufacturing Page 5. + * Added Manufacturing pages 8 through 10. + * Added defines for supported metadata size bits in + * CapabilitiesFlags field of IOC Page 6. + * Added defines for metadata size bits in VolumeSettings + * field of RAID Volume Page 0. + * Added SATA Link Reset settings, Enable SATA Asynchronous + * Notification bit, and HideNonZeroAttachedPhyIdentifiers + * bit to AdditionalControlFlags field of SAS IO Unit + * Page 1. + * Added defines for Enclosure Devices Unmapped and + * Device Limit Exceeded bits in Status field of SAS IO + * Unit Page 2. + * Added more AccessStatus values for SAS Device Page 0. + * Added bit for SATA Asynchronous Notification Support in + * Flags field of SAS Device Page 0. * -------------------------------------------------------------------------- mpi_init.h @@ -490,6 +516,7 @@ mpi_init.h * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them * unique in the first 32 characters. * 03-27-06 01.05.07 Added Task Management type of Clear ACA. + * 10-11-06 01.05.08 Shortened define for Task Management type of Clear ACA. * -------------------------------------------------------------------------- mpi_targ.h @@ -638,6 +665,8 @@ mpi_sas.h * and Remove Device operations to SAS IO Unit Control. * Added DevHandle field to SAS IO Unit Control request and * reply. + * 10-11-06 01.05.04 Fixed the name of a define for Operation field of SAS IO + * Unit Control request. * -------------------------------------------------------------------------- mpi_type.h @@ -653,20 +682,20 @@ mpi_type.h mpi_history.txt Parts list history -Filename 01.05.13 01.05.12 01.05.11 01.05.10 01.05.09 ----------- -------- -------- -------- -------- -------- -mpi.h 01.05.11 01.05.10 01.05.09 01.05.08 01.05.07 -mpi_ioc.h 01.05.11 01.05.10 01.05.09 01.05.09 01.05.08 -mpi_cnfg.h 01.05.12 01.05.11 01.05.10 01.05.09 01.05.08 -mpi_init.h 01.05.07 01.05.06 01.05.06 01.05.05 01.05.04 -mpi_targ.h 01.05.06 01.05.05 01.05.05 01.05.05 01.05.04 -mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 -mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 -mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02 -mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03 01.05.03 -mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 -mpi_sas.h 01.05.03 01.05.02 01.05.01 01.05.01 01.05.01 -mpi_type.h 01.05.02 01.05.02 01.05.01 01.05.01 01.05.01 +Filename 01.05.13 01.05.13 01.05.12 01.05.11 01.05.10 01.05.09 +---------- -------- -------- -------- -------- -------- -------- +mpi.h 01.05.12 01.05.11 01.05.10 01.05.09 01.05.08 01.05.07 +mpi_ioc.h 01.05.12 01.05.11 01.05.10 01.05.09 01.05.09 01.05.08 +mpi_cnfg.h 01.05.13 01.05.12 01.05.11 01.05.10 01.05.09 01.05.08 +mpi_init.h 01.05.08 01.05.07 01.05.06 01.05.06 01.05.05 01.05.04 +mpi_targ.h 01.05.06 01.05.06 01.05.05 01.05.05 01.05.05 01.05.04 +mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 +mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 +mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02 +mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03 01.05.03 01.05.03 +mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 +mpi_sas.h 01.05.04 01.05.03 01.05.02 01.05.01 01.05.01 01.05.01 +mpi_type.h 01.05.02 01.05.02 01.05.02 01.05.01 01.05.01 01.05.01 Filename 01.05.08 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03 ---------- -------- -------- -------- -------- -------- -------- diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h index c1c678989a23..ec9dff2249a7 100644 --- a/drivers/message/fusion/lsi/mpi_init.h +++ b/drivers/message/fusion/lsi/mpi_init.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2005 LSI Logic Corporation. + * Copyright (c) 2000-2006 LSI Logic Corporation. * * * Name: mpi_init.h * Title: MPI initiator mode messages and structures * Creation Date: June 8, 2000 * - * mpi_init.h Version: 01.05.07 + * mpi_init.h Version: 01.05.08 * * Version History * --------------- @@ -53,6 +53,7 @@ * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them * unique in the first 32 characters. * 03-27-06 01.05.07 Added Task Management type of Clear ACA. + * 10-11-06 01.05.08 Shortened define for Task Management type of Clear ACA. * -------------------------------------------------------------------------- */ @@ -428,7 +429,7 @@ typedef struct _MSG_SCSI_TASK_MGMT #define MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05) #define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06) #define MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07) -#define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_ACA (0x08) +#define MPI_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08) /* MsgFlags bits */ #define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION (0x00) diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h index 18ba407fd399..6c33e3353375 100644 --- a/drivers/message/fusion/lsi/mpi_ioc.h +++ b/drivers/message/fusion/lsi/mpi_ioc.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2005 LSI Logic Corporation. + * Copyright (c) 2000-2006 LSI Logic Corporation. * * * Name: mpi_ioc.h * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages * Creation Date: August 11, 2000 * - * mpi_ioc.h Version: 01.05.11 + * mpi_ioc.h Version: 01.05.12 * * Version History * --------------- @@ -98,6 +98,14 @@ * Added MPI_EVENT_SAS_INIT_TABLE_OVERFLOW and event * data structure. * Added MPI_EXT_IMAGE_TYPE_INITIALIZATION. + * 10-11-06 01.05.12 Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED. + * Added MaxInitiators field to PortFacts reply. + * Added SAS Device Status Change ReasonCode for + * asynchronous notificaiton. + * Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event + * data structure. + * Added new ImageType values for FWDownload and FWUpload + * requests. * -------------------------------------------------------------------------- */ @@ -264,6 +272,7 @@ typedef struct _MSG_IOC_FACTS_REPLY #define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002) #define MPI_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004) #define MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL (0x0008) +#define MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED (0x0010) #define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT (0x01) #define MPI_IOCFACTS_FLAGS_REPLY_FIFO_HOST_SIGNAL (0x02) @@ -328,7 +337,8 @@ typedef struct _MSG_PORT_FACTS_REPLY U16 MaxPostedCmdBuffers; /* 1Ch */ U16 MaxPersistentIDs; /* 1Eh */ U16 MaxLanBuckets; /* 20h */ - U16 Reserved4; /* 22h */ + U8 MaxInitiators; /* 22h */ + U8 Reserved4; /* 23h */ U32 Reserved5; /* 24h */ } MSG_PORT_FACTS_REPLY, MPI_POINTER PTR_MSG_PORT_FACTS_REPLY, PortFactsReply_t, MPI_POINTER pPortFactsReply_t; @@ -487,6 +497,7 @@ typedef struct _MSG_EVENT_ACK_REPLY #define MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x00000018) #define MPI_EVENT_SAS_INIT_TABLE_OVERFLOW (0x00000019) #define MPI_EVENT_SAS_SMP_ERROR (0x0000001A) +#define MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE (0x0000001B) #define MPI_EVENT_LOG_ENTRY_ADDED (0x00000021) /* AckRequired field values */ @@ -593,6 +604,7 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE #define MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A) #define MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B) #define MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C) +#define MPI_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D) /* SCSI Event data for Queue Full event */ @@ -895,6 +907,54 @@ typedef struct _EVENT_DATA_SAS_INIT_TABLE_OVERFLOW MpiEventDataSasInitTableOverflow_t, MPI_POINTER pMpiEventDataSasInitTableOverflow_t; +/* SAS Expander Status Change Event data */ + +typedef struct _EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE +{ + U8 ReasonCode; /* 00h */ + U8 Reserved1; /* 01h */ + U16 Reserved2; /* 02h */ + U8 PhysicalPort; /* 04h */ + U8 Reserved3; /* 05h */ + U16 EnclosureHandle; /* 06h */ + U64 SASAddress; /* 08h */ + U32 DiscoveryStatus; /* 10h */ + U16 DevHandle; /* 14h */ + U16 ParentDevHandle; /* 16h */ + U16 ExpanderChangeCount; /* 18h */ + U16 ExpanderRouteIndexes; /* 1Ah */ + U8 NumPhys; /* 1Ch */ + U8 SASLevel; /* 1Dh */ + U8 Flags; /* 1Eh */ + U8 Reserved4; /* 1Fh */ +} EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE, + MPI_POINTER PTR_EVENT_DATA_SAS_EXPANDER_STATUS_CHANGE, + MpiEventDataSasExpanderStatusChange_t, + MPI_POINTER pMpiEventDataSasExpanderStatusChange_t; + +/* values for ReasonCode field of SAS Expander Status Change Event data */ +#define MPI_EVENT_SAS_EXP_RC_ADDED (0x00) +#define MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING (0x01) + +/* values for DiscoveryStatus field of SAS Expander Status Change Event data */ +#define MPI_EVENT_SAS_EXP_DS_LOOP_DETECTED (0x00000001) +#define MPI_EVENT_SAS_EXP_DS_UNADDRESSABLE_DEVICE (0x00000002) +#define MPI_EVENT_SAS_EXP_DS_MULTIPLE_PORTS (0x00000004) +#define MPI_EVENT_SAS_EXP_DS_EXPANDER_ERR (0x00000008) +#define MPI_EVENT_SAS_EXP_DS_SMP_TIMEOUT (0x00000010) +#define MPI_EVENT_SAS_EXP_DS_OUT_ROUTE_ENTRIES (0x00000020) +#define MPI_EVENT_SAS_EXP_DS_INDEX_NOT_EXIST (0x00000040) +#define MPI_EVENT_SAS_EXP_DS_SMP_FUNCTION_FAILED (0x00000080) +#define MPI_EVENT_SAS_EXP_DS_SMP_CRC_ERROR (0x00000100) +#define MPI_EVENT_SAS_EXP_DS_SUBTRACTIVE_LINK (0x00000200) +#define MPI_EVENT_SAS_EXP_DS_TABLE_LINK (0x00000400) +#define MPI_EVENT_SAS_EXP_DS_UNSUPPORTED_DEVICE (0x00000800) + +/* values for Flags field of SAS Expander Status Change Event data */ +#define MPI_EVENT_SAS_EXP_FLAGS_ROUTE_TABLE_CONFIG (0x02) +#define MPI_EVENT_SAS_EXP_FLAGS_CONFIG_IN_PROGRESS (0x01) + + /***************************************************************************** * @@ -926,6 +986,10 @@ typedef struct _MSG_FW_DOWNLOAD #define MPI_FW_DOWNLOAD_ITYPE_BIOS (0x02) #define MPI_FW_DOWNLOAD_ITYPE_NVDATA (0x03) #define MPI_FW_DOWNLOAD_ITYPE_BOOTLOADER (0x04) +#define MPI_FW_DOWNLOAD_ITYPE_MANUFACTURING (0x06) +#define MPI_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07) +#define MPI_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08) +#define MPI_FW_DOWNLOAD_ITYPE_MEGARAID (0x09) typedef struct _FWDownloadTCSGE @@ -980,6 +1044,11 @@ typedef struct _MSG_FW_UPLOAD #define MPI_FW_UPLOAD_ITYPE_NVDATA (0x03) #define MPI_FW_UPLOAD_ITYPE_BOOTLOADER (0x04) #define MPI_FW_UPLOAD_ITYPE_FW_BACKUP (0x05) +#define MPI_FW_UPLOAD_ITYPE_MANUFACTURING (0x06) +#define MPI_FW_UPLOAD_ITYPE_CONFIG_1 (0x07) +#define MPI_FW_UPLOAD_ITYPE_CONFIG_2 (0x08) +#define MPI_FW_UPLOAD_ITYPE_MEGARAID (0x09) +#define MPI_FW_UPLOAD_ITYPE_COMPLETE (0x0A) typedef struct _FWUploadTCSGE { diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h index 871ebc08b706..635bbe04513e 100644 --- a/drivers/message/fusion/lsi/mpi_log_sas.h +++ b/drivers/message/fusion/lsi/mpi_log_sas.h @@ -1,4 +1,3 @@ - /*************************************************************************** * * * Copyright 2003 LSI Logic Corporation. All rights reserved. * @@ -14,7 +13,7 @@ #define IOPI_IOCLOGINFO_H_INCLUDED #define SAS_LOGINFO_NEXUS_LOSS 0x31170000 -#define SAS_LOGINFO_MASK 0xFFFF0000 +#define SAS_LOGINFO_MASK 0xFFFF0000 /****************************************************************************/ /* IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF */ @@ -43,129 +42,172 @@ /****************************************************************************/ /* IOP LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IOP */ /****************************************************************************/ -#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS (0x00010000) -#define IOP_LOGINFO_CODE_UNUSED2 (0x00020000) -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x00030000) -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT (0x00030100) /* Route Table Entry not found */ -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN (0x00030200) /* Invalid Page Number */ -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x00030300) /* Invalid FORM */ -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x00030400) /* Invalid Page Type */ -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM (0x00030500) /* Device Not Mapped */ -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST (0x00030600) /* Persistent Page not found */ -#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */ - -#define IOP_LOGINFO_CODE_DIAG_MSG_ERROR (0x00040000) /* Error handling diag msg - or'd with diag status */ - -#define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000) - -#define IOP_LOGINFO_CODE_ENCL_MGMT_READ_ACTION_ERR0R (0x00060001) /* Read Action not supported for SEP msg */ -#define IOP_LOGINFO_CODE_ENCL_MGMT_INVALID_BUS_ID_ERR0R (0x00060002) /* Invalid Bus/ID in SEP msg */ - -#define IOP_LOGINFO_CODE_TARGET_ASSIST_TERMINATED (0x00070001) -#define IOP_LOGINFO_CODE_TARGET_STATUS_SEND_TERMINATED (0x00070002) -#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_ALL_IO (0x00070003) -#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO (0x00070004) -#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ (0x00070005) +#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS (0x00010000) +#define IOP_LOGINFO_CODE_UNUSED2 (0x00020000) +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x00030000) +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT (0x00030100) /* Route Table Entry not found */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN (0x00030200) /* Invalid Page Number */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x00030300) /* Invalid FORM */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x00030400) /* Invalid Page Type */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM (0x00030500) /* Device Not Mapped */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST (0x00030600) /* Persistent Page not found */ +#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */ + +#define IOP_LOGINFO_CODE_FWUPLOAD_NO_FLASH_AVAILABLE (0x0003E000) /* Tried to upload from flash, but there is none */ +#define IOP_LOGINFO_CODE_FWUPLOAD_UNKNOWN_IMAGE_TYPE (0x0003E001) /* ImageType field contents were invalid */ +#define IOP_LOGINFO_CODE_FWUPLOAD_WRONG_IMAGE_SIZE (0x0003E002) /* ImageSize field in TCSGE was bad/offset in MfgPg 4 was wrong */ +#define IOP_LOGINFO_CODE_FWUPLOAD_ENTIRE_FLASH_UPLOAD_FAILED (0x0003E003) /* Error occured while attempting to upload the entire flash */ +#define IOP_LOGINFO_CODE_FWUPLOAD_REGION_UPLOAD_FAILED (0x0003E004) /* Error occured while attempting to upload single flash region */ +#define IOP_LOGINFO_CODE_FWUPLOAD_DMA_FAILURE (0x0003E005) /* Problem occured while DMAing FW to host memory */ + +#define IOP_LOGINFO_CODE_DIAG_MSG_ERROR (0x00040000) /* Error handling diag msg - or'd with diag status */ + +#define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000) + +#define IOP_LOGINFO_CODE_ENCL_MGMT_READ_ACTION_ERR0R (0x00060001) /* Read Action not supported for SEP msg */ +#define IOP_LOGINFO_CODE_ENCL_MGMT_INVALID_BUS_ID_ERR0R (0x00060002) /* Invalid Bus/ID in SEP msg */ + +#define IOP_LOGINFO_CODE_TARGET_ASSIST_TERMINATED (0x00070001) +#define IOP_LOGINFO_CODE_TARGET_STATUS_SEND_TERMINATED (0x00070002) +#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_ALL_IO (0x00070003) +#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO (0x00070004) +#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ (0x00070005) /****************************************************************************/ /* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */ /****************************************************************************/ -#define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000) -#define PL_LOG_INFO_CODE_OPEN_FAILURE_NO_DEST_TIME_OUT (0x00010001) -#define PL_LOGINFO_CODE_OPEN_FAILURE_BAD_DESTINATION (0x00010011) -#define PL_LOGINFO_CODE_OPEN_FAILURE_PROTOCOL_NOT_SUPPORTED (0x00010013) -#define PL_LOGINFO_CODE_OPEN_FAILURE_STP_RESOURCES_BSY (0x00010018) -#define PL_LOGINFO_CODE_OPEN_FAILURE_WRONG_DESTINATION (0x00010019) -#define PL_LOGINFO_CODE_OPEN_FAILURE_ORR_TIMEOUT (0X0001001A) -#define PL_LOGINFO_CODE_OPEN_FAILURE_PATHWAY_BLOCKED (0x0001001B) -#define PL_LOGINFO_CODE_OPEN_FAILURE_AWT_MAXED (0x0001001C) -#define PL_LOGINFO_CODE_INVALID_SGL (0x00020000) -#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000) -#define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000) -#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW (0x00050000) -#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00060000) -#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00070000) -#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00080000) -#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00090000) -#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE (0x000A0000) -#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x000B0000) -#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR (0x000C0000) -#define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000) -#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000) -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000) -#define PL_LOGINFO_CODE_CONFIG_PL_NOT_INITIALIZED (0x000F0001) /* PL not yet initialized, can't do config page req. */ -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */ -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */ -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */ -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV (0x000F0400) /* No Device Found */ -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x000F0500) /* Invalid FORM */ -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */ -#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */ -#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000) -#define PL_LOGINFO_CODE_RESET (0x00110000) /* See Sub-Codes below */ -#define PL_LOGINFO_CODE_ABORT (0x00120000) /* See Sub-Codes below */ -#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000) -#define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000) -#define PL_LOGINFO_CODE_PERS_RESV_OUT_NOT_AFFIL_OWNER (0x00150000) -#define PL_LOGINFO_CODE_OPEN_TXDMA_ABORT (0x00160000) -#define PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY (0x00170000) -#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100) -#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_NO_DEST_TIMEOUT (0x00000101) -#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ORR_TIMEOUT (0x0000011A) /* Open Reject (Retry) Timeout */ -#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_PATHWAY_BLOCKED (0x0000011B) -#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_AWT_MAXED (0x0000011C) /* Arbitration Wait Timer Maxed */ - -#define PL_LOGINFO_SUB_CODE_TARGET_BUS_RESET (0x00000120) -#define PL_LOGINFO_SUB_CODE_TRANSPORT_LAYER (0x00000130) /* Leave lower nibble (1-f) reserved. */ -#define PL_LOGINFO_SUB_CODE_PORT_LAYER (0x00000140) /* Leave lower nibble (1-f) reserved. */ - - -#define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200) -#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300) -#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400) -#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW (0x00000500) -#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00000600) -#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00000700) -#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800) -#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900) -#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE (0x00000A00) -#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x00000B00) -#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00) -#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00) -#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00) -#define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET (0x00000E01) -#define PL_LOGINFO_SUB_CODE_SECOND_OPEN (0x00000F00) -#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000) - - -#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200010) /* Error occured on SMP Read */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200020) /* Error occured on SMP Write */ -#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200040) /* Encl Mgmt services not available for this WWID */ -#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200050) /* Address Mode not suppored */ -#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200060) /* Invalid Slot Number in SEP Msg */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200070) /* SGPIO not present/enabled */ -#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_NOT_CONFIGURED (0x00200080) /* GPIO not configured */ -#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_FRAME_ERROR (0x00200090) /* GPIO can't allocate a frame */ -#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_CONFIG_PAGE_ERROR (0x002000A0) /* GPIO failed config page request */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SES_FRAME_ALLOC_ERROR (0x002000B0) /* Can't get frame for SES command */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SES_IO_ERROR (0x002000C0) /* I/O execution error */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SES_RETRIES_EXHAUSTED (0x002000D0) /* SEP I/O retries exhausted */ -#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_ALLOC_ERROR (0x002000E0) /* Can't get frame for SMP command */ - -#define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */ -#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */ -#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */ -#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */ -#define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */ -#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200105) /* SEP stopped or sent bad chksum in Hdr */ -#define PL_LOGINFO_DA_SEP_STOP_ON_DATA (0x00200106) /* SEP stopped while transfering data */ -#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA (0x00200107) /* SEP stopped while transfering sense data */ -#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200108) /* SEP returned unknown scsi status */ -#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200109) /* SEP returned unknown scsi status */ -#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x0020010A) /* SEP returned bad chksum after STOP */ -#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x0020010B) /* SEP returned bad chksum after STOP while gettin data*/ -#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND (0x0020010C) /* SEP doesn't support CDB opcode */ +#define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000) /* see SUB_CODE_OPEN_FAIL_ below */ + +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_NO_DEST_TIME_OUT (0x00000001) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PATHWAY_BLOCKED (0x00000002) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_CONTINUE0 (0x00000003) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_CONTINUE1 (0x00000004) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_INITIALIZE0 (0x00000005) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_INITIALIZE1 (0x00000006) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_STOP0 (0x00000007) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RES_STOP1 (0x00000008) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RETRY (0x00000009) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_BREAK (0x0000000A) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_UNUSED_0B (0x0000000B) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_OPEN_TIMEOUT_EXP (0x0000000C) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_UNUSED_0D (0x0000000D) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_DVTBLE_ACCSS_FAIL (0x0000000E) +#define PL_LOGINFO_SUB CODE_OPEN_FAIL_BAD_DEST (0x00000011) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RATE_NOT_SUPP (0x00000012) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PROT_NOT_SUPP (0x00000013) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON0 (0x00000014) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON1 (0x00000015) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON2 (0x00000016) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON3 (0x00000017) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_STP_RESOURCES_BSY (0x00000018) +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_WRONG_DESTINATION (0x00000019) + +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PATH_BLOCKED (0x0000001B) /* Retry Timeout */ +#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_AWT_MAXED (0x0000001C) /* Retry Timeout */ + + + +#define PL_LOGINFO_CODE_INVALID_SGL (0x00020000) +#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000) +#define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000) +#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW (0x00050000) +#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00060000) +#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00070000) +#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00080000) +#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00090000) +#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE (0x000A0000) +#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x000B0000) +#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR (0x000C0000) +#define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000) +#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000) +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000) +#define PL_LOGINFO_CODE_CONFIG_PL_NOT_INITIALIZED (0x000F0001) /* PL not yet initialized, can't do config page req. */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV (0x000F0400) /* No Device Found */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x000F0500) /* Invalid FORM */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */ +#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */ +#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000) +#define PL_LOGINFO_CODE_RESET (0x00110000) /* See Sub-Codes below (PL_LOGINFO_SUB_CODE) */ +#define PL_LOGINFO_CODE_ABORT (0x00120000) /* See Sub-Codes below (PL_LOGINFO_SUB_CODE)*/ +#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000) +#define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000) +#define PL_LOGINFO_CODE_PERS_RESV_OUT_NOT_AFFIL_OWNER (0x00150000) +#define PL_LOGINFO_CODE_OPEN_TXDMA_ABORT (0x00160000) +#define PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY (0x00170000) +#define PL_LOGINFO_CODE_IO_CANCELLED_DUE_TO_R_ERR (0x00180000) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_NO_DEST_TIMEOUT (0x00000101) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_SATA_NEG_RATE_2HI (0x00000102) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_RATE_NOT_SUPPORTED (0x00000103) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_BREAK (0x00000104) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ZONE_VIOLATION (0x00000114) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON0 (0x00000114) /* Open Reject (Zone Violation) - available on SAS-2 devices */ +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON1 (0x00000115) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON2 (0x00000116) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ABANDON3 (0x00000117) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_ORR_TIMEOUT (0x0000011A) /* Open Reject (Retry) Timeout */ +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_PATH_BLOCKED (0x0000011B) +#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE_AWT_MAXED (0x0000011C) /* Arbitration Wait Timer Maxed */ + +#define PL_LOGINFO_SUB_CODE_TARGET_BUS_RESET (0x00000120) +#define PL_LOGINFO_SUB_CODE_TRANSPORT_LAYER (0x00000130) /* Leave lower nibble (1-f) reserved. */ +#define PL_LOGINFO_SUB_CODE_PORT_LAYER (0x00000140) /* Leave lower nibble (1-f) reserved. */ + + +#define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200) +#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300) +#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400) /* Bits 0-3 encode Transport Status Register (offset 0x08) */ + /* Bit 0 is Status Bit 0: FrameXferErr */ + /* Bit 1 & 2 are Status Bits 16 and 17: FrameXmitErrStatus */ + /* Bit 3 is Status Bit 18 WriteDataLenghtGTDataLengthErr */ + +#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW (0x00000500) +#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00000600) +#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00000700) +#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800) +#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900) +#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE (0x00000A00) +#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x00000B00) +#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00) +#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00) +#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00) +#define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET (0x00000E01) +#define PL_LOGINFO_SUB_CODE_SECOND_OPEN (0x00000F00) +#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000) + +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200010) /* Error occured on SMP Read */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200020) /* Error occured on SMP Write */ +#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200040) /* Encl Mgmt services not available for this WWID */ +#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200050) /* Address Mode not suppored */ +#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200060) /* Invalid Slot Number in SEP Msg */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200070) /* SGPIO not present/enabled */ +#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_NOT_CONFIGURED (0x00200080) /* GPIO not configured */ +#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_FRAME_ERROR (0x00200090) /* GPIO can't allocate a frame */ +#define PL_LOGINFO_CODE_ENCL_MGMT_GPIO_CONFIG_PAGE_ERROR (0x002000A0) /* GPIO failed config page request */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SES_FRAME_ALLOC_ERROR (0x002000B0) /* Can't get frame for SES command */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SES_IO_ERROR (0x002000C0) /* I/O execution error */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SES_RETRIES_EXHAUSTED (0x002000D0) /* SEP I/O retries exhausted */ +#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_ALLOC_ERROR (0x002000E0) /* Can't get frame for SMP command */ + +#define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */ +#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */ +#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */ +#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */ +#define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */ +#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200105) /* SEP stopped or sent bad chksum in Hdr */ +#define PL_LOGINFO_DA_SEP_STOP_ON_DATA (0x00200106) /* SEP stopped while transfering data */ +#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA (0x00200107) /* SEP stopped while transfering sense data */ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200108) /* SEP returned unknown scsi status */ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200109) /* SEP returned unknown scsi status */ +#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x0020010A) /* SEP returned bad chksum after STOP */ +#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x0020010B) /* SEP returned bad chksum after STOP while gettin data*/ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND (0x0020010C) /* SEP doesn't support CDB opcode f/w location 1 */ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND_2 (0x0020010D) /* SEP doesn't support CDB opcode f/w location 2 */ +#define PL_LOGINFO_DA_SEP_UNSUPPORTED_COMMAND_3 (0x0020010E) /* SEP doesn't support CDB opcode f/w location 3 */ /****************************************************************************/ diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h index 50b8f0a8f456..8e990a0fa7a2 100644 --- a/drivers/message/fusion/lsi/mpi_sas.h +++ b/drivers/message/fusion/lsi/mpi_sas.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2004 LSI Logic Corporation. + * Copyright (c) 2004-2006 LSI Logic Corporation. * * * Name: mpi_sas.h * Title: MPI Serial Attached SCSI structures and definitions * Creation Date: August 19, 2004 * - * mpi_sas.h Version: 01.05.03 + * mpi_sas.h Version: 01.05.04 * * Version History * --------------- @@ -21,6 +21,8 @@ * and Remove Device operations to SAS IO Unit Control. * Added DevHandle field to SAS IO Unit Control request and * reply. + * 10-11-06 01.05.04 Fixed the name of a define for Operation field of SAS IO + * Unit Control request. * -------------------------------------------------------------------------- */ @@ -237,7 +239,8 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST #define MPI_SAS_OP_SEND_PRIMITIVE (0x0A) #define MPI_SAS_OP_FORCE_FULL_DISCOVERY (0x0B) #define MPI_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C) -#define MPI_SAS_OP_TRANSMIT_REMOVE_DEVICE (0x0D) +#define MPI_SAS_OP_TRANSMIT_REMOVE_DEVICE (0x0D) /* obsolete name */ +#define MPI_SAS_OP_REMOVE_DEVICE (0x0D) /* values for the PrimFlags field */ #define MPI_SAS_PRIMFLAGS_SINGLE (0x08) -- cgit v1.2.3 From 6d84c944fa17cf4e65660df50a0772f8a4836e0b Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 23 Jan 2007 11:25:23 -0600 Subject: [SCSI] ipr: Remove usage of pci driver data Since ipr handles dynamic ids, it must handle driver_data not being set, so remove the current usage of driver_data so it can be used for other things in future patches. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 63 +++++++++++++++++------------------------------------- 1 file changed, 20 insertions(+), 43 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index b318500785e5..0f1d654ea352 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -7166,9 +7166,6 @@ ipr_get_chip_cfg(const struct pci_device_id *dev_id) { int i; - if (dev_id->driver_data) - return (const struct ipr_chip_cfg_t *)dev_id->driver_data; - for (i = 0; i < ARRAY_SIZE(ipr_chip); i++) if (ipr_chip[i].vendor == dev_id->vendor && ipr_chip[i].device == dev_id->device) @@ -7517,65 +7514,45 @@ static void ipr_shutdown(struct pci_dev *pdev) static struct pci_device_id ipr_pci_table[] __devinitdata = { { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5702, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5702, 0, 0, 0 }, { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5703, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5703, 0, 0, 0 }, { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573D, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573D, 0, 0, 0 }, { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573E, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573E, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571B, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571B, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572E, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572E, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571A, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571A, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B8, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B8, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571E, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571E, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0, 0 }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, - 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0, 0 }, { } }; MODULE_DEVICE_TABLE(pci, ipr_pci_table); -- cgit v1.2.3 From 7dce0e1c84cfa8fb2a4b41877c20def386cade2b Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 23 Jan 2007 11:25:30 -0600 Subject: [SCSI] ipr: Tolerate not finding PCI-X registers Don't fail initialization of an adapter if the PCI-X registers cannot be found since it may be a PCI-E adapter. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 0f1d654ea352..39133748fb73 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -595,10 +595,8 @@ static int ipr_save_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg) { int pcix_cmd_reg = pci_find_capability(ioa_cfg->pdev, PCI_CAP_ID_PCIX); - if (pcix_cmd_reg == 0) { - dev_err(&ioa_cfg->pdev->dev, "Failed to save PCI-X command register\n"); - return -EIO; - } + if (pcix_cmd_reg == 0) + return 0; if (pci_read_config_word(ioa_cfg->pdev, pcix_cmd_reg + PCI_X_CMD, &ioa_cfg->saved_pcix_cmd_reg) != PCIBIOS_SUCCESSFUL) { @@ -627,10 +625,6 @@ static int ipr_set_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg) dev_err(&ioa_cfg->pdev->dev, "Failed to setup PCI-X command register\n"); return -EIO; } - } else { - dev_err(&ioa_cfg->pdev->dev, - "Failed to setup PCI-X command register\n"); - return -EIO; } return 0; -- cgit v1.2.3 From e619e1a7cbf73c27eacf53856443b1aa67cc1234 Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 23 Jan 2007 11:25:37 -0600 Subject: [SCSI] ipr: PCI error recovery fix Since the pci_block_user_cfg_access API was modified to track block/unblocks, it was discovered that the ipr driver had a path through its code (in PCI error recovery) which would unblock when not previously blocked. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 39133748fb73..4f5273ea2772 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -6308,7 +6308,6 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) int rc; ENTER; - pci_unblock_user_cfg_access(ioa_cfg->pdev); rc = pci_restore_state(ioa_cfg->pdev); if (rc != PCIBIOS_SUCCESSFUL) { @@ -6348,6 +6347,24 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) return IPR_RC_JOB_CONTINUE; } +/** + * ipr_reset_bist_done - BIST has completed on the adapter. + * @ipr_cmd: ipr command struct + * + * Description: Unblock config space and resume the reset process. + * + * Return value: + * IPR_RC_JOB_CONTINUE + **/ +static int ipr_reset_bist_done(struct ipr_cmnd *ipr_cmd) +{ + ENTER; + pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); + ipr_cmd->job_step = ipr_reset_restore_cfg_space; + LEAVE; + return IPR_RC_JOB_CONTINUE; +} + /** * ipr_reset_start_bist - Run BIST on the adapter. * @ipr_cmd: ipr command struct @@ -6370,7 +6387,7 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd) ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); rc = IPR_RC_JOB_CONTINUE; } else { - ipr_cmd->job_step = ipr_reset_restore_cfg_space; + ipr_cmd->job_step = ipr_reset_bist_done; ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT); rc = IPR_RC_JOB_RETURN; } -- cgit v1.2.3 From 9cd065ab80d6c14c6693a93c8f47ef4cb80e770f Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 23 Jan 2007 11:25:43 -0600 Subject: [SCSI] ipr: Driver version 2.3.1 Bump driver version to 2.3.1. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 9f62a1d4d511..88f285de97bb 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -37,8 +37,8 @@ /* * Literals */ -#define IPR_DRIVER_VERSION "2.3.0" -#define IPR_DRIVER_DATE "(November 8, 2006)" +#define IPR_DRIVER_VERSION "2.3.1" +#define IPR_DRIVER_DATE "(January 23, 2007)" /* * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding -- cgit v1.2.3 From 28713324a0f3c055186ecec27239673c36ba1de5 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Tue, 23 Jan 2007 14:59:20 -0800 Subject: [SCSI] aacraid: rework communication support code Received from Mark Salyzyn, Replace all if/else communication transports with a platform function call. This is in recognition of the need to migrate to up-and-coming transports. Currently the Linux driver does not support two available communication transports provided by our products, these will be added in future patches, and will expand the platform function set. Signed-off-by Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aacraid.h | 27 ++++- drivers/scsi/aacraid/comminit.c | 14 ++- drivers/scsi/aacraid/commsup.c | 40 +----- drivers/scsi/aacraid/rkt.c | 64 +++++----- drivers/scsi/aacraid/rx.c | 263 +++++++++++++++++++++++++--------------- drivers/scsi/aacraid/sa.c | 33 +++-- 6 files changed, 262 insertions(+), 179 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 4f8b4c53d435..813e68993aa6 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -5,6 +5,7 @@ #define _nblank(x) #x #define nblank(x) _nblank(x)[0] +#include /*------------------------------------------------------------------------------ * D E F I N E S @@ -488,13 +489,20 @@ struct fib; struct adapter_ops { + /* Low level operations */ void (*adapter_interrupt)(struct aac_dev *dev); void (*adapter_notify)(struct aac_dev *dev, u32 event); void (*adapter_disable_int)(struct aac_dev *dev); + void (*adapter_enable_int)(struct aac_dev *dev); int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4); int (*adapter_check_health)(struct aac_dev *dev); - int (*adapter_send)(struct fib * fib); + /* Transport operations */ int (*adapter_ioremap)(struct aac_dev * dev, u32 size); + irqreturn_t (*adapter_intr)(int irq, void *dev_id); + /* Packet operations */ + int (*adapter_deliver)(struct fib * fib); + /* Administrative operations */ + int (*adapter_comm)(struct aac_dev * dev, int comm); }; /* @@ -1018,7 +1026,9 @@ struct aac_dev u8 nondasd_support; u8 dac_support; u8 raid_scsi_mode; - u8 new_comm_interface; + u8 comm_interface; +# define AAC_COMM_PRODUCER 0 +# define AAC_COMM_MESSAGE 1 /* macro side-effects BEWARE */ # define raw_io_interface \ init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4) @@ -1036,18 +1046,24 @@ struct aac_dev #define aac_adapter_disable_int(dev) \ (dev)->a_ops.adapter_disable_int(dev) +#define aac_adapter_enable_int(dev) \ + (dev)->a_ops.adapter_enable_int(dev) + #define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \ (dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) #define aac_adapter_check_health(dev) \ (dev)->a_ops.adapter_check_health(dev) -#define aac_adapter_send(fib) \ - ((fib)->dev)->a_ops.adapter_send(fib) - #define aac_adapter_ioremap(dev, size) \ (dev)->a_ops.adapter_ioremap(dev, size) +#define aac_adapter_deliver(fib) \ + ((fib)->dev)->a_ops.adapter_deliver(fib) + +#define aac_adapter_comm(dev,comm) \ + (dev)->a_ops.adapter_comm(dev, comm) + #define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001) /* @@ -1795,6 +1811,7 @@ int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg); int aac_rx_init(struct aac_dev *dev); int aac_rkt_init(struct aac_dev *dev); int aac_sa_init(struct aac_dev *dev); +int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify); unsigned int aac_response_normal(struct aac_queue * q); unsigned int aac_command_normal(struct aac_queue * q); unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index); diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 6d305b2f854e..df67ba686023 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -95,7 +95,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES); init->InitFlags = 0; - if (dev->new_comm_interface) { + if (dev->comm_interface == AAC_COMM_MESSAGE) { init->InitFlags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED); dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n")); } @@ -297,21 +297,23 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) - sizeof(struct aac_fibhdr) - sizeof(struct aac_write) + sizeof(struct sgentry)) / sizeof(struct sgentry); - dev->new_comm_interface = 0; + dev->comm_interface = AAC_COMM_PRODUCER; dev->raw_io_64 = 0; if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) && (status[0] == 0x00000001)) { if (status[1] & AAC_OPT_NEW_COMM_64) dev->raw_io_64 = 1; - if (status[1] & AAC_OPT_NEW_COMM) - dev->new_comm_interface = dev->a_ops.adapter_send != 0; - if (dev->new_comm_interface && (status[2] > dev->base_size)) { + if (dev->a_ops.adapter_comm && + (status[1] & AAC_OPT_NEW_COMM)) + dev->comm_interface = AAC_COMM_MESSAGE; + if ((dev->comm_interface == AAC_COMM_MESSAGE) && + (status[2] > dev->base_size)) { aac_adapter_ioremap(dev, 0); dev->base_size = status[2]; if (aac_adapter_ioremap(dev, status[2])) { /* remap failed, go back ... */ - dev->new_comm_interface = 0; + dev->comm_interface = AAC_COMM_PRODUCER; if (aac_adapter_ioremap(dev, AAC_MIN_FOOTPRINT_SIZE)) { printk(KERN_WARNING "aacraid: unable to map adapter.\n"); diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 4893a6d06a33..1b97f60652ba 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -317,7 +317,7 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr * success. */ -static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify) +int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify) { struct aac_entry * entry = NULL; int map = 0; @@ -387,7 +387,6 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, { struct aac_dev * dev = fibptr->dev; struct hw_fib * hw_fib = fibptr->hw_fib; - struct aac_queue * q; unsigned long flags = 0; unsigned long qflags; @@ -469,38 +468,10 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, if (!dev->queues) return -EBUSY; - q = &dev->queues->queue[AdapNormCmdQueue]; if(wait) spin_lock_irqsave(&fibptr->event_lock, flags); - spin_lock_irqsave(q->lock, qflags); - if (dev->new_comm_interface) { - unsigned long count = 10000000L; /* 50 seconds */ - q->numpending++; - spin_unlock_irqrestore(q->lock, qflags); - while (aac_adapter_send(fibptr) != 0) { - if (--count == 0) { - if (wait) - spin_unlock_irqrestore(&fibptr->event_lock, flags); - spin_lock_irqsave(q->lock, qflags); - q->numpending--; - spin_unlock_irqrestore(q->lock, qflags); - return -ETIMEDOUT; - } - udelay(5); - } - } else { - u32 index; - unsigned long nointr = 0; - aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr); - - q->numpending++; - *(q->headers.producer) = cpu_to_le32(index + 1); - spin_unlock_irqrestore(q->lock, qflags); - dprintk((KERN_DEBUG "aac_fib_send: inserting a queue entry at index %d.\n",index)); - if (!(nointr & aac_config.irq_mod)) - aac_adapter_notify(dev, AdapNormCmdQueue); - } + aac_adapter_deliver(fibptr); /* * If the caller wanted us to wait for response wait now. @@ -520,6 +491,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, while (down_trylock(&fibptr->event_wait)) { int blink; if (--count == 0) { + struct aac_queue * q = &dev->queues->queue[AdapNormCmdQueue]; spin_lock_irqsave(q->lock, qflags); q->numpending--; spin_unlock_irqrestore(q->lock, qflags); @@ -659,7 +631,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) unsigned long qflags; if (hw_fib->header.XferState == 0) { - if (dev->new_comm_interface) + if (dev->comm_interface == AAC_COMM_MESSAGE) kfree (hw_fib); return 0; } @@ -667,7 +639,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) * If we plan to do anything check the structure type first. */ if ( hw_fib->header.StructType != FIB_MAGIC ) { - if (dev->new_comm_interface) + if (dev->comm_interface == AAC_COMM_MESSAGE) kfree (hw_fib); return -EINVAL; } @@ -679,7 +651,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) * send the completed cdb to the adapter. */ if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) { - if (dev->new_comm_interface) { + if (dev->comm_interface == AAC_COMM_MESSAGE) { kfree (hw_fib); } else { u32 index; diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index 643f23b5ded8..d953c3fe998a 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c @@ -34,6 +34,40 @@ #include "aacraid.h" +#define AAC_NUM_IO_FIB_RKT (246 - AAC_NUM_MGT_FIB) + +/** + * aac_rkt_select_comm - Select communications method + * @dev: Adapter + * @comm: communications method + */ + +static int aac_rkt_select_comm(struct aac_dev *dev, int comm) +{ + int retval; + extern int aac_rx_select_comm(struct aac_dev *dev, int comm); + retval = aac_rx_select_comm(dev, comm); + if (comm == AAC_COMM_MESSAGE) { + /* + * FIB Setup has already been done, but we can minimize the + * damage by at least ensuring the OS never issues more + * commands than we can handle. The Rocket adapters currently + * can only handle 246 commands and 8 AIFs at the same time, + * and in fact do notify us accordingly if we negotiate the + * FIB size. The problem that causes us to add this check is + * to ensure that we do not overdo it with the adapter when a + * hard coded FIB override is being utilized. This special + * case warrants this half baked, but convenient, check here. + */ + if (dev->scsi_host_ptr->can_queue > AAC_NUM_IO_FIB_RKT) { + dev->init->MaxIoCommands = + cpu_to_le32(AAC_NUM_IO_FIB_RKT + AAC_NUM_MGT_FIB); + dev->scsi_host_ptr->can_queue = AAC_NUM_IO_FIB_RKT; + } + } + return retval; +} + /** * aac_rkt_ioremap * @size: mapping resize request @@ -63,39 +97,13 @@ static int aac_rkt_ioremap(struct aac_dev * dev, u32 size) int aac_rkt_init(struct aac_dev *dev) { - int retval; extern int _aac_rx_init(struct aac_dev *dev); - extern void aac_rx_start_adapter(struct aac_dev *dev); /* * Fill in the function dispatch table. */ dev->a_ops.adapter_ioremap = aac_rkt_ioremap; + dev->a_ops.adapter_comm = aac_rkt_select_comm; - retval = _aac_rx_init(dev); - if (retval) - return retval; - if (dev->new_comm_interface) { - /* - * FIB Setup has already been done, but we can minimize the - * damage by at least ensuring the OS never issues more - * commands than we can handle. The Rocket adapters currently - * can only handle 246 commands and 8 AIFs at the same time, - * and in fact do notify us accordingly if we negotiate the - * FIB size. The problem that causes us to add this check is - * to ensure that we do not overdo it with the adapter when a - * hard coded FIB override is being utilized. This special - * case warrants this half baked, but convenient, check here. - */ - if (dev->scsi_host_ptr->can_queue > (246 - AAC_NUM_MGT_FIB)) { - dev->init->MaxIoCommands = cpu_to_le32(246); - dev->scsi_host_ptr->can_queue = 246 - AAC_NUM_MGT_FIB; - } - } - /* - * Tell the adapter that all is configured, and it can start - * accepting requests - */ - aac_rx_start_adapter(dev); - return 0; + return _aac_rx_init(dev); } diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index dcc8b0ea7a9d..c632d9354a26 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -46,60 +46,60 @@ #include "aacraid.h" -static irqreturn_t aac_rx_intr(int irq, void *dev_id) +static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id) { struct aac_dev *dev = dev_id; + unsigned long bellbits; + u8 intstat = rx_readb(dev, MUnit.OISR); - dprintk((KERN_DEBUG "aac_rx_intr(%d,%p)\n", irq, dev_id)); - if (dev->new_comm_interface) { - u32 Index = rx_readl(dev, MUnit.OutboundQueue); - if (Index == 0xFFFFFFFFL) - Index = rx_readl(dev, MUnit.OutboundQueue); - if (Index != 0xFFFFFFFFL) { - do { - if (aac_intr_normal(dev, Index)) { - rx_writel(dev, MUnit.OutboundQueue, Index); - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady); - } - Index = rx_readl(dev, MUnit.OutboundQueue); - } while (Index != 0xFFFFFFFFL); - return IRQ_HANDLED; + /* + * Read mask and invert because drawbridge is reversed. + * This allows us to only service interrupts that have + * been enabled. + * Check to see if this is our interrupt. If it isn't just return + */ + if (intstat & ~(dev->OIMR)) { + bellbits = rx_readl(dev, OutboundDoorbellReg); + if (bellbits & DoorBellPrintfReady) { + aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5])); + rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); + rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); } - } else { - unsigned long bellbits; - u8 intstat; - intstat = rx_readb(dev, MUnit.OISR); - /* - * Read mask and invert because drawbridge is reversed. - * This allows us to only service interrupts that have - * been enabled. - * Check to see if this is our interrupt. If it isn't just return - */ - if (intstat & ~(dev->OIMR)) - { - bellbits = rx_readl(dev, OutboundDoorbellReg); - if (bellbits & DoorBellPrintfReady) { - aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5])); - rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); - rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); - } - else if (bellbits & DoorBellAdapterNormCmdReady) { - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); - aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); - } - else if (bellbits & DoorBellAdapterNormRespReady) { - rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); - aac_response_normal(&dev->queues->queue[HostNormRespQueue]); - } - else if (bellbits & DoorBellAdapterNormCmdNotFull) { - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); - } - else if (bellbits & DoorBellAdapterNormRespNotFull) { - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); - rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); - } - return IRQ_HANDLED; + else if (bellbits & DoorBellAdapterNormCmdReady) { + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); + aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); + } + else if (bellbits & DoorBellAdapterNormRespReady) { + rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); + aac_response_normal(&dev->queues->queue[HostNormRespQueue]); + } + else if (bellbits & DoorBellAdapterNormCmdNotFull) { + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); } + else if (bellbits & DoorBellAdapterNormRespNotFull) { + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); + } + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +static irqreturn_t aac_rx_intr_message(int irq, void *dev_id) +{ + struct aac_dev *dev = dev_id; + u32 Index = rx_readl(dev, MUnit.OutboundQueue); + if (Index == 0xFFFFFFFFL) + Index = rx_readl(dev, MUnit.OutboundQueue); + if (Index != 0xFFFFFFFFL) { + do { + if (aac_intr_normal(dev, Index)) { + rx_writel(dev, MUnit.OutboundQueue, Index); + rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady); + } + Index = rx_readl(dev, MUnit.OutboundQueue); + } while (Index != 0xFFFFFFFFL); + return IRQ_HANDLED; } return IRQ_NONE; } @@ -114,6 +114,26 @@ static void aac_rx_disable_interrupt(struct aac_dev *dev) rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); } +/** + * aac_rx_enable_interrupt_producer - Enable interrupts + * @dev: Adapter + */ + +static void aac_rx_enable_interrupt_producer(struct aac_dev *dev) +{ + rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); +} + +/** + * aac_rx_enable_interrupt_message - Enable interrupts + * @dev: Adapter + */ + +static void aac_rx_enable_interrupt_message(struct aac_dev *dev) +{ + rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); +} + /** * rx_sync_cmd - send a command and wait * @dev: Adapter @@ -189,10 +209,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, /* * Restore interrupt mask even though we timed out */ - if (dev->new_comm_interface) - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); - else - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); + aac_adapter_enable_int(dev); return -ETIMEDOUT; } /* @@ -215,10 +232,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, /* * Restore interrupt mask */ - if (dev->new_comm_interface) - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); - else - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); + aac_adapter_enable_int(dev); return 0; } @@ -360,35 +374,72 @@ static int aac_rx_check_health(struct aac_dev *dev) } /** - * aac_rx_send + * aac_rx_deliver_producer * @fib: fib to issue * * Will send a fib, returning 0 if successful. */ -static int aac_rx_send(struct fib * fib) +static int aac_rx_deliver_producer(struct fib * fib) { - u64 addr = fib->hw_fib_pa; struct aac_dev *dev = fib->dev; - volatile void __iomem *device = dev->regs.rx; + struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; + unsigned long qflags; u32 Index; + unsigned long nointr = 0; - dprintk((KERN_DEBUG "%p->aac_rx_send(%p->%llx)\n", dev, fib, addr)); - Index = rx_readl(dev, MUnit.InboundQueue); - if (Index == 0xFFFFFFFFL) + spin_lock_irqsave(q->lock, qflags); + aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib, 1, fib, &nointr); + + q->numpending++; + *(q->headers.producer) = cpu_to_le32(Index + 1); + spin_unlock_irqrestore(q->lock, qflags); + if (!(nointr & aac_config.irq_mod)) + aac_adapter_notify(dev, AdapNormCmdQueue); + + return 0; +} + +/** + * aac_rx_deliver_message + * @fib: fib to issue + * + * Will send a fib, returning 0 if successful. + */ +static int aac_rx_deliver_message(struct fib * fib) +{ + struct aac_dev *dev = fib->dev; + struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; + unsigned long qflags; + u32 Index; + u64 addr; + volatile void __iomem *device; + + unsigned long count = 10000000L; /* 50 seconds */ + spin_lock_irqsave(q->lock, qflags); + q->numpending++; + spin_unlock_irqrestore(q->lock, qflags); + for(;;) { Index = rx_readl(dev, MUnit.InboundQueue); - dprintk((KERN_DEBUG "Index = 0x%x\n", Index)); - if (Index == 0xFFFFFFFFL) - return Index; + if (Index == 0xFFFFFFFFL) + Index = rx_readl(dev, MUnit.InboundQueue); + if (Index != 0xFFFFFFFFL) + break; + if (--count == 0) { + spin_lock_irqsave(q->lock, qflags); + q->numpending--; + spin_unlock_irqrestore(q->lock, qflags); + return -ETIMEDOUT; + } + udelay(5); + } device = dev->base + Index; - dprintk((KERN_DEBUG "entry = %x %x %u\n", (u32)(addr & 0xffffffff), - (u32)(addr >> 32), (u32)le16_to_cpu(fib->hw_fib->header.Size))); + addr = fib->hw_fib_pa; writel((u32)(addr & 0xffffffff), device); device += sizeof(u32); writel((u32)(addr >> 32), device); device += sizeof(u32); writel(le16_to_cpu(fib->hw_fib->header.Size), device); rx_writel(dev, MUnit.InboundQueue, Index); - dprintk((KERN_DEBUG "aac_rx_send - return 0\n")); return 0; } @@ -429,6 +480,31 @@ static int aac_rx_restart_adapter(struct aac_dev *dev) return 0; } +/** + * aac_rx_select_comm - Select communications method + * @dev: Adapter + * @comm: communications method + */ + +int aac_rx_select_comm(struct aac_dev *dev, int comm) +{ + switch (comm) { + case AAC_COMM_PRODUCER: + dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_producer; + dev->a_ops.adapter_intr = aac_rx_intr_producer; + dev->a_ops.adapter_deliver = aac_rx_deliver_producer; + break; + case AAC_COMM_MESSAGE: + dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_message; + dev->a_ops.adapter_intr = aac_rx_intr_message; + dev->a_ops.adapter_deliver = aac_rx_deliver_message; + break; + default: + return 1; + } + return 0; +} + /** * aac_rx_init - initialize an i960 based AAC card * @dev: device to configure @@ -489,40 +565,42 @@ int _aac_rx_init(struct aac_dev *dev) } msleep(1); } - if (request_irq(dev->scsi_host_ptr->irq, aac_rx_intr, IRQF_SHARED|IRQF_DISABLED, "aacraid", (void *)dev)<0) - { - printk(KERN_ERR "%s%d: Interrupt unavailable.\n", name, instance); - goto error_iounmap; - } /* - * Fill in the function dispatch table. + * Fill in the common function dispatch table. */ dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter; dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt; dev->a_ops.adapter_notify = aac_rx_notify_adapter; dev->a_ops.adapter_sync_cmd = rx_sync_cmd; dev->a_ops.adapter_check_health = aac_rx_check_health; - dev->a_ops.adapter_send = aac_rx_send; /* * First clear out all interrupts. Then enable the one's that we * can handle. */ - rx_writeb(dev, MUnit.OIMR, 0xff); + aac_adapter_comm(dev, AAC_COMM_PRODUCER); + aac_adapter_disable_int(dev); rx_writel(dev, MUnit.ODR, 0xffffffff); - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); + aac_adapter_enable_int(dev); if (aac_init_adapter(dev) == NULL) - goto error_irq; - if (dev->new_comm_interface) - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); + goto error_iounmap; + aac_adapter_comm(dev, dev->comm_interface); + if (request_irq(dev->scsi_host_ptr->irq, dev->a_ops.adapter_intr, + IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) { + printk(KERN_ERR "%s%d: Interrupt unavailable.\n", + name, instance); + goto error_iounmap; + } + aac_adapter_enable_int(dev); + /* + * Tell the adapter that all is configured, and it can + * start accepting requests + */ + aac_rx_start_adapter(dev); return 0; -error_irq: - rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); - free_irq(dev->scsi_host_ptr->irq, (void *)dev); - error_iounmap: return -1; @@ -530,20 +608,11 @@ error_iounmap: int aac_rx_init(struct aac_dev *dev) { - int retval; - /* * Fill in the function dispatch table. */ dev->a_ops.adapter_ioremap = aac_rx_ioremap; + dev->a_ops.adapter_comm = aac_rx_select_comm; - retval = _aac_rx_init(dev); - if (!retval) { - /* - * Tell the adapter that all is configured, and it can - * start accepting requests - */ - aac_rx_start_adapter(dev); - } - return retval; + return _aac_rx_init(dev); } diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c index 511b0a938fb1..8535db068c2f 100644 --- a/drivers/scsi/aacraid/sa.c +++ b/drivers/scsi/aacraid/sa.c @@ -91,6 +91,17 @@ static void aac_sa_disable_interrupt (struct aac_dev *dev) sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff); } +/** + * aac_sa_enable_interrupt - enable interrupt + * @dev: Which adapter to enable. + */ + +static void aac_sa_enable_interrupt (struct aac_dev *dev) +{ + sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | + DOORBELL_2 | DOORBELL_3 | DOORBELL_4)); +} + /** * aac_sa_notify_adapter - handle adapter notification * @dev: Adapter that notification is for @@ -347,32 +358,36 @@ int aac_sa_init(struct aac_dev *dev) msleep(1); } - if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, IRQF_SHARED|IRQF_DISABLED, "aacraid", (void *)dev ) < 0) { - printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", name, instance); - goto error_iounmap; - } - /* * Fill in the function dispatch table. */ dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter; dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt; + dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt; 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_intr = aac_sa_intr; dev->a_ops.adapter_ioremap = aac_sa_ioremap; /* * First clear out all interrupts. Then enable the one's that * we can handle. */ - sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff); - sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | - DOORBELL_2 | DOORBELL_3 | DOORBELL_4)); + aac_adapter_disable_int(dev); + aac_adapter_enable_int(dev); if(aac_init_adapter(dev) == NULL) goto error_irq; + if (request_irq(dev->scsi_host_ptr->irq, dev->a_ops.adapter_intr, + IRQF_SHARED|IRQF_DISABLED, + "aacraid", (void *)dev ) < 0) { + printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", + name, instance); + goto error_iounmap; + } + aac_adapter_enable_int(dev); /* * Tell the adapter that all is configure, and it can start @@ -382,7 +397,7 @@ int aac_sa_init(struct aac_dev *dev) return 0; error_irq: - sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff); + aac_sa_disable_interrupt(dev); free_irq(dev->scsi_host_ptr->irq, (void *)dev); error_iounmap: -- cgit v1.2.3 From 239eab19559b3d74a029dff3f0c792bc0770a062 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Tue, 23 Jan 2007 15:00:13 -0800 Subject: [SCSI] aacraid: Begin adding support for new adapter type Received from Mark Salyzyn, Add in the NEMER/ARK physical register mapping, represented in up and coming products currently under test at Adaptec. Signed-off-by Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/Makefile | 2 +- drivers/scsi/aacraid/aacraid.h | 1 + drivers/scsi/aacraid/linit.c | 5 ++- drivers/scsi/aacraid/nark.c | 87 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 drivers/scsi/aacraid/nark.c diff --git a/drivers/scsi/aacraid/Makefile b/drivers/scsi/aacraid/Makefile index 28d133a3094f..f1cca4ee5410 100644 --- a/drivers/scsi/aacraid/Makefile +++ b/drivers/scsi/aacraid/Makefile @@ -3,6 +3,6 @@ obj-$(CONFIG_SCSI_AACRAID) := aacraid.o aacraid-objs := linit.o aachba.o commctrl.o comminit.o commsup.o \ - dpcsup.o rx.o sa.o rkt.o + dpcsup.o rx.o sa.o rkt.o nark.o EXTRA_CFLAGS := -Idrivers/scsi diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 813e68993aa6..bdbd81e73f18 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1810,6 +1810,7 @@ int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg); int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg); int aac_rx_init(struct aac_dev *dev); int aac_rkt_init(struct aac_dev *dev); +int aac_nark_init(struct aac_dev *dev); int aac_sa_init(struct aac_dev *dev); int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify); unsigned int aac_response_normal(struct aac_queue * q); diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 359e7ddfdb47..1326c0a1bdae 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -157,6 +157,7 @@ static struct pci_device_id aac_pci_tbl[] = { { 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 58 }, /* Legend Catchall */ { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */ { 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */ + { 0x9005, 0x0288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 61 }, /* Adaptec NEMER/ARK Catch All */ { 0,} }; MODULE_DEVICE_TABLE(pci, aac_pci_tbl); @@ -230,7 +231,8 @@ static struct aac_driver_ident aac_drivers[] = { { aac_rx_init, "aacraid", "DELL ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell Catchall */ { aac_rx_init, "aacraid", "Legend ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend Catchall */ { aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec Catch All */ - { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec Rocket Catch All */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Rocket Catch All */ + { aac_nark_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec NEMER/ARK Catch All */ }; /** @@ -804,7 +806,6 @@ static struct scsi_host_template aac_driver_template = { .emulated = 1, }; - static int __devinit aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { diff --git a/drivers/scsi/aacraid/nark.c b/drivers/scsi/aacraid/nark.c new file mode 100644 index 000000000000..c76b611b6afb --- /dev/null +++ b/drivers/scsi/aacraid/nark.c @@ -0,0 +1,87 @@ +/* + * Adaptec AAC series RAID controller driver + * (c) Copyright 2001 Red Hat Inc. + * + * based on the old aacraid driver that is.. + * Adaptec aacraid device driver for Linux. + * + * Copyright (c) 2000 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 + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Module Name: + * nark.c + * + * Abstract: Hardware Device Interface for NEMER/ARK + * + */ + +#include +#include + +#include + +#include "aacraid.h" + +/** + * aac_nark_ioremap + * @size: mapping resize request + * + */ +static int aac_nark_ioremap(struct aac_dev * dev, u32 size) +{ + if (!size) { + iounmap(dev->regs.rx); + dev->regs.rx = NULL; + iounmap(dev->base); + dev->base = NULL; + return 0; + } + dev->scsi_host_ptr->base = pci_resource_start(dev->pdev, 2); + dev->regs.rx = ioremap((u64)pci_resource_start(dev->pdev, 0) | + ((u64)pci_resource_start(dev->pdev, 1) << 32), + sizeof(struct rx_registers) - sizeof(struct rx_inbound)); + dev->base = NULL; + if (dev->regs.rx == NULL) + return -1; + dev->base = ioremap(dev->scsi_host_ptr->base, size); + if (dev->base == NULL) { + iounmap(dev->regs.rx); + dev->regs.rx = NULL; + return -1; + } + dev->IndexRegs = &((struct rx_registers __iomem *)dev->base)->IndexRegs; + return 0; +} + +/** + * aac_nark_init - initialize an NEMER/ARK Split Bar card + * @dev: device to configure + * + */ + +int aac_nark_init(struct aac_dev * dev) +{ + extern int _aac_rx_init(struct aac_dev *dev); + extern int aac_rx_select_comm(struct aac_dev *dev, int comm); + + /* + * Fill in the function dispatch table. + */ + dev->a_ops.adapter_ioremap = aac_nark_ioremap; + dev->a_ops.adapter_comm = aac_rx_select_comm; + + return _aac_rx_init(dev); +} -- cgit v1.2.3 From e8f32de52c0d74d397d21afc655a4e2a7dfe1f98 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Tue, 23 Jan 2007 15:00:30 -0800 Subject: [SCSI] aacraid: rework packet support code Received from Mark Salyzyn, Replace all if/else packet formations with platform function calls. This is in recognition of the proliferation of read and write packet types, and in the need to migrate to up-and-coming packets for new products. Signed-off-by Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 598 ++++++++++++++++++++++------------------- drivers/scsi/aacraid/aacraid.h | 18 +- 2 files changed, 343 insertions(+), 273 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 426cd6f49f5d..971425557f74 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -706,6 +706,309 @@ static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code, } } +static int aac_bounds_32(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba) +{ + if (lba & 0xffffffff00000000LL) { + int cid = scmd_id(cmd); + dprintk((KERN_DEBUG "aacraid: Illegal lba\n")); + cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | + SAM_STAT_CHECK_CONDITION; + set_sense((u8 *) &dev->fsa_dev[cid].sense_data, + HARDWARE_ERROR, + SENCODE_INTERNAL_TARGET_FAILURE, + ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, + 0, 0); + memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data, + (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(cmd->sense_buffer)) + ? sizeof(cmd->sense_buffer) + : sizeof(dev->fsa_dev[cid].sense_data)); + cmd->scsi_done(cmd); + return 1; + } + return 0; +} + +static int aac_bounds_64(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba) +{ + return 0; +} + +static void io_callback(void *context, struct fib * fibptr); + +static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +{ + u16 fibsize; + struct aac_raw_io *readcmd; + aac_fib_init(fib); + readcmd = (struct aac_raw_io *) fib_data(fib); + readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); + readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); + readcmd->count = cpu_to_le32(count<<9); + readcmd->cid = cpu_to_le16(scmd_id(cmd)); + readcmd->flags = cpu_to_le16(1); + readcmd->bpTotal = 0; + readcmd->bpComplete = 0; + + aac_build_sgraw(cmd, &readcmd->sg); + fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw)); + BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ContainerRawIo, + fib, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) io_callback, + (void *) cmd); +} + +static int aac_read_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +{ + u16 fibsize; + struct aac_read64 *readcmd; + aac_fib_init(fib); + readcmd = (struct aac_read64 *) fib_data(fib); + readcmd->command = cpu_to_le32(VM_CtHostRead64); + readcmd->cid = cpu_to_le16(scmd_id(cmd)); + readcmd->sector_count = cpu_to_le16(count); + readcmd->block = cpu_to_le32((u32)(lba&0xffffffff)); + readcmd->pad = 0; + readcmd->flags = 0; + + aac_build_sg64(cmd, &readcmd->sg); + fibsize = sizeof(struct aac_read64) + + ((le32_to_cpu(readcmd->sg.count) - 1) * + sizeof (struct sgentry64)); + BUG_ON (fibsize > (fib->dev->max_fib_size - + sizeof(struct aac_fibhdr))); + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ContainerCommand64, + fib, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) io_callback, + (void *) cmd); +} + +static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +{ + u16 fibsize; + struct aac_read *readcmd; + aac_fib_init(fib); + readcmd = (struct aac_read *) fib_data(fib); + readcmd->command = cpu_to_le32(VM_CtBlockRead); + readcmd->cid = cpu_to_le16(scmd_id(cmd)); + readcmd->block = cpu_to_le32((u32)(lba&0xffffffff)); + readcmd->count = cpu_to_le32(count * 512); + + aac_build_sg(cmd, &readcmd->sg); + fibsize = sizeof(struct aac_read) + + ((le32_to_cpu(readcmd->sg.count) - 1) * + sizeof (struct sgentry)); + BUG_ON (fibsize > (fib->dev->max_fib_size - + sizeof(struct aac_fibhdr))); + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ContainerCommand, + fib, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) io_callback, + (void *) cmd); +} + +static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +{ + u16 fibsize; + struct aac_raw_io *writecmd; + aac_fib_init(fib); + writecmd = (struct aac_raw_io *) fib_data(fib); + writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); + writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); + writecmd->count = cpu_to_le32(count<<9); + writecmd->cid = cpu_to_le16(scmd_id(cmd)); + writecmd->flags = 0; + writecmd->bpTotal = 0; + writecmd->bpComplete = 0; + + aac_build_sgraw(cmd, &writecmd->sg); + fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw)); + BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ContainerRawIo, + fib, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) io_callback, + (void *) cmd); +} + +static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +{ + u16 fibsize; + struct aac_write64 *writecmd; + aac_fib_init(fib); + writecmd = (struct aac_write64 *) fib_data(fib); + writecmd->command = cpu_to_le32(VM_CtHostWrite64); + writecmd->cid = cpu_to_le16(scmd_id(cmd)); + writecmd->sector_count = cpu_to_le16(count); + writecmd->block = cpu_to_le32((u32)(lba&0xffffffff)); + writecmd->pad = 0; + writecmd->flags = 0; + + aac_build_sg64(cmd, &writecmd->sg); + fibsize = sizeof(struct aac_write64) + + ((le32_to_cpu(writecmd->sg.count) - 1) * + sizeof (struct sgentry64)); + BUG_ON (fibsize > (fib->dev->max_fib_size - + sizeof(struct aac_fibhdr))); + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ContainerCommand64, + fib, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) io_callback, + (void *) cmd); +} + +static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) +{ + u16 fibsize; + struct aac_write *writecmd; + aac_fib_init(fib); + writecmd = (struct aac_write *) fib_data(fib); + writecmd->command = cpu_to_le32(VM_CtBlockWrite); + writecmd->cid = cpu_to_le16(scmd_id(cmd)); + writecmd->block = cpu_to_le32((u32)(lba&0xffffffff)); + writecmd->count = cpu_to_le32(count * 512); + writecmd->sg.count = cpu_to_le32(1); + /* ->stable is not used - it did mean which type of write */ + + aac_build_sg(cmd, &writecmd->sg); + fibsize = sizeof(struct aac_write) + + ((le32_to_cpu(writecmd->sg.count) - 1) * + sizeof (struct sgentry)); + BUG_ON (fibsize > (fib->dev->max_fib_size - + sizeof(struct aac_fibhdr))); + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ContainerCommand, + fib, + fibsize, + FsaNormal, + 0, 1, + (fib_callback) io_callback, + (void *) cmd); +} + +static struct aac_srb * aac_scsi_common(struct fib * fib, struct scsi_cmnd * cmd) +{ + struct aac_srb * srbcmd; + u32 flag; + u32 timeout; + + aac_fib_init(fib); + switch(cmd->sc_data_direction){ + case DMA_TO_DEVICE: + flag = SRB_DataOut; + break; + case DMA_BIDIRECTIONAL: + flag = SRB_DataIn | SRB_DataOut; + break; + case DMA_FROM_DEVICE: + flag = SRB_DataIn; + break; + case DMA_NONE: + default: /* shuts up some versions of gcc */ + flag = SRB_NoDataXfer; + break; + } + + srbcmd = (struct aac_srb*) fib_data(fib); + srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); + srbcmd->channel = cpu_to_le32(aac_logical_to_phys(scmd_channel(cmd))); + srbcmd->id = cpu_to_le32(scmd_id(cmd)); + srbcmd->lun = cpu_to_le32(cmd->device->lun); + srbcmd->flags = cpu_to_le32(flag); + timeout = cmd->timeout_per_command/HZ; + if (timeout == 0) + timeout = 1; + srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds + srbcmd->retry_limit = 0; /* Obsolete parameter */ + srbcmd->cdb_size = cpu_to_le32(cmd->cmd_len); + return srbcmd; +} + +static void aac_srb_callback(void *context, struct fib * fibptr); + +static int aac_scsi_64(struct fib * fib, struct scsi_cmnd * cmd) +{ + u16 fibsize; + struct aac_srb * srbcmd = aac_scsi_common(fib, cmd); + + aac_build_sg64(cmd, (struct sgmap64*) &srbcmd->sg); + srbcmd->count = cpu_to_le32(cmd->request_bufflen); + + memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); + memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len); + /* + * Build Scatter/Gather list + */ + fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) + + ((le32_to_cpu(srbcmd->sg.count) & 0xff) * + sizeof (struct sgentry64)); + BUG_ON (fibsize > (fib->dev->max_fib_size - + sizeof(struct aac_fibhdr))); + + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ScsiPortCommand64, fib, + fibsize, FsaNormal, 0, 1, + (fib_callback) aac_srb_callback, + (void *) cmd); +} + +static int aac_scsi_32(struct fib * fib, struct scsi_cmnd * cmd) +{ + u16 fibsize; + struct aac_srb * srbcmd = aac_scsi_common(fib, cmd); + + aac_build_sg(cmd, (struct sgmap*)&srbcmd->sg); + srbcmd->count = cpu_to_le32(cmd->request_bufflen); + + memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); + memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len); + /* + * Build Scatter/Gather list + */ + fibsize = sizeof (struct aac_srb) + + (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * + sizeof (struct sgentry)); + BUG_ON (fibsize > (fib->dev->max_fib_size - + sizeof(struct aac_fibhdr))); + + /* + * Now send the Fib to the adapter + */ + return aac_fib_send(ScsiPortCommand, fib, fibsize, FsaNormal, 0, 1, + (fib_callback) aac_srb_callback, (void *) cmd); +} + int aac_get_adapter_info(struct aac_dev* dev) { struct fib* fibptr; @@ -874,14 +1177,27 @@ int aac_get_adapter_info(struct aac_dev* dev) } } /* - * 57 scatter gather elements + * Deal with configuring for the individualized limits of each packet + * interface. */ - if (!(dev->raw_io_interface)) { + dev->a_ops.adapter_scsi = (dev->dac_support) + ? aac_scsi_64 + : aac_scsi_32; + if (dev->raw_io_interface) { + dev->a_ops.adapter_bounds = (dev->raw_io_64) + ? aac_bounds_64 + : aac_bounds_32; + dev->a_ops.adapter_read = aac_read_raw_io; + dev->a_ops.adapter_write = aac_write_raw_io; + } else { + dev->a_ops.adapter_bounds = aac_bounds_32; dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size - sizeof(struct aac_fibhdr) - sizeof(struct aac_write) + sizeof(struct sgentry)) / sizeof(struct sgentry); if (dev->dac_support) { + dev->a_ops.adapter_read = aac_read_block64; + dev->a_ops.adapter_write = aac_write_block64; /* * 38 scatter gather elements */ @@ -891,6 +1207,9 @@ int aac_get_adapter_info(struct aac_dev* dev) sizeof(struct aac_write64) + sizeof(struct sgentry64)) / sizeof(struct sgentry64); + } else { + dev->a_ops.adapter_read = aac_read_block; + dev->a_ops.adapter_write = aac_write_block; } dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT; if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) { @@ -1004,8 +1323,6 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) u64 lba; u32 count; int status; - - u16 fibsize; struct aac_dev *dev; struct fib * cmd_fibcontext; @@ -1059,23 +1376,8 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) } dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n", smp_processor_id(), (unsigned long long)lba, jiffies)); - if ((!(dev->raw_io_interface) || !(dev->raw_io_64)) && - (lba & 0xffffffff00000000LL)) { - dprintk((KERN_DEBUG "aac_read: Illegal lba\n")); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | - SAM_STAT_CHECK_CONDITION; - set_sense((u8 *) &dev->fsa_dev[cid].sense_data, - HARDWARE_ERROR, - SENCODE_INTERNAL_TARGET_FAILURE, - ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, - 0, 0); - memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, - (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer)) - ? sizeof(scsicmd->sense_buffer) - : sizeof(dev->fsa_dev[cid].sense_data)); - scsicmd->scsi_done(scsicmd); + if (aac_adapter_bounds(dev,scsicmd,lba)) return 0; - } /* * Alocate and initialize a Fib */ @@ -1083,85 +1385,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) return -1; } - aac_fib_init(cmd_fibcontext); - - if (dev->raw_io_interface) { - struct aac_raw_io *readcmd; - readcmd = (struct aac_raw_io *) fib_data(cmd_fibcontext); - readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); - readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); - readcmd->count = cpu_to_le32(count<<9); - readcmd->cid = cpu_to_le16(cid); - readcmd->flags = cpu_to_le16(1); - readcmd->bpTotal = 0; - readcmd->bpComplete = 0; - - aac_build_sgraw(scsicmd, &readcmd->sg); - fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw)); - BUG_ON(fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))); - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ContainerRawIo, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) io_callback, - (void *) scsicmd); - } else if (dev->dac_support == 1) { - struct aac_read64 *readcmd; - readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext); - readcmd->command = cpu_to_le32(VM_CtHostRead64); - readcmd->cid = cpu_to_le16(cid); - readcmd->sector_count = cpu_to_le16(count); - readcmd->block = cpu_to_le32((u32)(lba&0xffffffff)); - readcmd->pad = 0; - readcmd->flags = 0; - - aac_build_sg64(scsicmd, &readcmd->sg); - fibsize = sizeof(struct aac_read64) + - ((le32_to_cpu(readcmd->sg.count) - 1) * - sizeof (struct sgentry64)); - BUG_ON (fibsize > (dev->max_fib_size - - sizeof(struct aac_fibhdr))); - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ContainerCommand64, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) io_callback, - (void *) scsicmd); - } else { - struct aac_read *readcmd; - readcmd = (struct aac_read *) fib_data(cmd_fibcontext); - readcmd->command = cpu_to_le32(VM_CtBlockRead); - readcmd->cid = cpu_to_le32(cid); - readcmd->block = cpu_to_le32((u32)(lba&0xffffffff)); - readcmd->count = cpu_to_le32(count * 512); - - aac_build_sg(scsicmd, &readcmd->sg); - fibsize = sizeof(struct aac_read) + - ((le32_to_cpu(readcmd->sg.count) - 1) * - sizeof (struct sgentry)); - BUG_ON (fibsize > (dev->max_fib_size - - sizeof(struct aac_fibhdr))); - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ContainerCommand, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) io_callback, - (void *) scsicmd); - } - - + status = aac_adapter_read(cmd_fibcontext, scsicmd, lba, count); /* * Check that the command queued to the controller @@ -1187,7 +1411,6 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) u64 lba; u32 count; int status; - u16 fibsize; struct aac_dev *dev; struct fib * cmd_fibcontext; @@ -1227,22 +1450,8 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) } dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n", smp_processor_id(), (unsigned long long)lba, jiffies)); - if ((!(dev->raw_io_interface) || !(dev->raw_io_64)) - && (lba & 0xffffffff00000000LL)) { - dprintk((KERN_DEBUG "aac_write: Illegal lba\n")); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; - set_sense((u8 *) &dev->fsa_dev[cid].sense_data, - HARDWARE_ERROR, - SENCODE_INTERNAL_TARGET_FAILURE, - ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, - 0, 0); - memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, - (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer)) - ? sizeof(scsicmd->sense_buffer) - : sizeof(dev->fsa_dev[cid].sense_data)); - scsicmd->scsi_done(scsicmd); + if (aac_adapter_bounds(dev,scsicmd,lba)) return 0; - } /* * Allocate and initialize a Fib then setup a BlockWrite command */ @@ -1251,85 +1460,8 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) scsicmd->scsi_done(scsicmd); return 0; } - aac_fib_init(cmd_fibcontext); - if (dev->raw_io_interface) { - struct aac_raw_io *writecmd; - writecmd = (struct aac_raw_io *) fib_data(cmd_fibcontext); - writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); - writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); - writecmd->count = cpu_to_le32(count<<9); - writecmd->cid = cpu_to_le16(cid); - writecmd->flags = 0; - writecmd->bpTotal = 0; - writecmd->bpComplete = 0; - - aac_build_sgraw(scsicmd, &writecmd->sg); - fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw)); - BUG_ON(fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))); - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ContainerRawIo, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) io_callback, - (void *) scsicmd); - } else if (dev->dac_support == 1) { - struct aac_write64 *writecmd; - writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext); - writecmd->command = cpu_to_le32(VM_CtHostWrite64); - writecmd->cid = cpu_to_le16(cid); - writecmd->sector_count = cpu_to_le16(count); - writecmd->block = cpu_to_le32((u32)(lba&0xffffffff)); - writecmd->pad = 0; - writecmd->flags = 0; - - aac_build_sg64(scsicmd, &writecmd->sg); - fibsize = sizeof(struct aac_write64) + - ((le32_to_cpu(writecmd->sg.count) - 1) * - sizeof (struct sgentry64)); - BUG_ON (fibsize > (dev->max_fib_size - - sizeof(struct aac_fibhdr))); - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ContainerCommand64, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) io_callback, - (void *) scsicmd); - } else { - struct aac_write *writecmd; - writecmd = (struct aac_write *) fib_data(cmd_fibcontext); - writecmd->command = cpu_to_le32(VM_CtBlockWrite); - writecmd->cid = cpu_to_le32(cid); - writecmd->block = cpu_to_le32((u32)(lba&0xffffffff)); - writecmd->count = cpu_to_le32(count * 512); - writecmd->sg.count = cpu_to_le32(1); - /* ->stable is not used - it did mean which type of write */ - - aac_build_sg(scsicmd, &writecmd->sg); - fibsize = sizeof(struct aac_write) + - ((le32_to_cpu(writecmd->sg.count) - 1) * - sizeof (struct sgentry)); - BUG_ON (fibsize > (dev->max_fib_size - - sizeof(struct aac_fibhdr))); - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ContainerCommand, - cmd_fibcontext, - fibsize, - FsaNormal, - 0, 1, - (fib_callback) io_callback, - (void *) scsicmd); - } + status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count); /* * Check that the command queued to the controller @@ -2099,10 +2231,6 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) struct fib* cmd_fibcontext; struct aac_dev* dev; int status; - struct aac_srb *srbcmd; - u16 fibsize; - u32 flag; - u32 timeout; dev = (struct aac_dev *)scsicmd->device->host->hostdata; if (scmd_id(scsicmd) >= dev->maximum_num_physicals || @@ -2112,88 +2240,14 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd) return 0; } - switch(scsicmd->sc_data_direction){ - case DMA_TO_DEVICE: - flag = SRB_DataOut; - break; - case DMA_BIDIRECTIONAL: - flag = SRB_DataIn | SRB_DataOut; - break; - case DMA_FROM_DEVICE: - flag = SRB_DataIn; - break; - case DMA_NONE: - default: /* shuts up some versions of gcc */ - flag = SRB_NoDataXfer; - break; - } - - /* * Allocate and initialize a Fib then setup a BlockWrite command */ if (!(cmd_fibcontext = aac_fib_alloc(dev))) { return -1; } - aac_fib_init(cmd_fibcontext); - - srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext); - srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); - srbcmd->channel = cpu_to_le32(aac_logical_to_phys(scmd_channel(scsicmd))); - srbcmd->id = cpu_to_le32(scmd_id(scsicmd)); - srbcmd->lun = cpu_to_le32(scsicmd->device->lun); - srbcmd->flags = cpu_to_le32(flag); - timeout = scsicmd->timeout_per_command/HZ; - if(timeout == 0){ - timeout = 1; - } - srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds - srbcmd->retry_limit = 0; /* Obsolete parameter */ - srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len); - - if( dev->dac_support == 1 ) { - aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg); - srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); - - memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); - memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len); - /* - * Build Scatter/Gather list - */ - fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) + - ((le32_to_cpu(srbcmd->sg.count) & 0xff) * - sizeof (struct sgentry64)); - BUG_ON (fibsize > (dev->max_fib_size - - sizeof(struct aac_fibhdr))); + status = aac_adapter_scsi(cmd_fibcontext, scsicmd); - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ScsiPortCommand64, cmd_fibcontext, - fibsize, FsaNormal, 0, 1, - (fib_callback) aac_srb_callback, - (void *) scsicmd); - } else { - aac_build_sg(scsicmd, (struct sgmap*)&srbcmd->sg); - srbcmd->count = cpu_to_le32(scsicmd->request_bufflen); - - memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); - memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len); - /* - * Build Scatter/Gather list - */ - fibsize = sizeof (struct aac_srb) + - (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * - sizeof (struct sgentry)); - BUG_ON (fibsize > (dev->max_fib_size - - sizeof(struct aac_fibhdr))); - - /* - * Now send the Fib to the adapter - */ - status = aac_fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1, - (fib_callback) aac_srb_callback, (void *) scsicmd); - } /* * Check that the command queued to the controller */ diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index bdbd81e73f18..39ecd0d22eb0 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -486,6 +486,7 @@ enum aac_log_level { struct aac_dev; struct fib; +struct scsi_cmnd; struct adapter_ops { @@ -501,6 +502,10 @@ struct adapter_ops irqreturn_t (*adapter_intr)(int irq, void *dev_id); /* Packet operations */ int (*adapter_deliver)(struct fib * fib); + int (*adapter_bounds)(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba); + int (*adapter_read)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count); + int (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count); + int (*adapter_scsi)(struct fib * fib, struct scsi_cmnd * cmd); /* Administrative operations */ int (*adapter_comm)(struct aac_dev * dev, int comm); }; @@ -1061,6 +1066,18 @@ struct aac_dev #define aac_adapter_deliver(fib) \ ((fib)->dev)->a_ops.adapter_deliver(fib) +#define aac_adapter_bounds(dev,cmd,lba) \ + dev->a_ops.adapter_bounds(dev,cmd,lba) + +#define aac_adapter_read(fib,cmd,lba,count) \ + ((fib)->dev)->a_ops.adapter_read(fib,cmd,lba,count) + +#define aac_adapter_write(fib,cmd,lba,count) \ + ((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count) + +#define aac_adapter_scsi(fib,cmd) \ + ((fib)->dev)->a_ops.adapter_scsi(fib,cmd) + #define aac_adapter_comm(dev,comm) \ (dev)->a_ops.adapter_comm(dev, comm) @@ -1783,7 +1800,6 @@ static inline u32 cap_to_cyls(sector_t capacity, u32 divisor) return (u32)capacity; } -struct scsi_cmnd; /* SCp.phase values */ #define AAC_OWNER_MIDLEVEL 0x101 #define AAC_OWNER_LOWLEVEL 0x102 -- cgit v1.2.3 From e37ee4bec6c6d6d67aebafeecbbb32aa33d502bc Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Fri, 26 Jan 2007 09:23:32 -0800 Subject: [SCSI] aacraid: expanded expose physical device code (new) Received from Mark Salyzyn, Take the expose_physicals flag and allow the user to select default (physicals available via /dev/sg), exposed (physicals available via /dev/sd for experimental reasons) and hidden (physicals blocked from all access). This expands the functionality of the previous expose_physicals insmod parameter which was added to support some experimental configurations. Signed-off-by Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 4 ++-- drivers/scsi/aacraid/linit.c | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 971425557f74..ddb33b06e0ef 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -170,9 +170,9 @@ int acbsize = -1; module_param(acbsize, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512, 2048, 4096 and 8192. Default is to use suggestion from Firmware."); -int expose_physicals = 0; +int expose_physicals = -1; module_param(expose_physicals, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. 0=off, 1=on"); +MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on"); /** * aac_get_config_status - check the adapter configuration * @common: adapter to query diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 1326c0a1bdae..1feda449aedc 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -398,11 +398,15 @@ static int aac_slave_configure(struct scsi_device *sdev) sdev->skip_ms_page_3f = 1; } if ((sdev->type == TYPE_DISK) && - !expose_physicals && (sdev_channel(sdev) != CONTAINER_CHANNEL)) { - struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata; - if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2)) - sdev->no_uld_attach = 1; + if (expose_physicals == 0) + return -ENXIO; + if (expose_physicals < 0) { + struct aac_dev *aac = + (struct aac_dev *)sdev->host->hostdata; + if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2)) + sdev->no_uld_attach = 1; + } } if (sdev->tagged_supported && (sdev->type == TYPE_DISK) && (sdev_channel(sdev) == CONTAINER_CHANNEL)) { -- cgit v1.2.3 From a5364c5a311f73eade88f37bf5b614797ce30ec9 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Wed, 24 Jan 2007 09:31:30 -0800 Subject: [SCSI] NCR_D700: fix compile error Fix a typo in NCR_D700 Signed-off-by Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/NCR_D700.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c index 01967a59479d..f12864abed2f 100644 --- a/drivers/scsi/NCR_D700.c +++ b/drivers/scsi/NCR_D700.c @@ -200,7 +200,7 @@ NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq, hostdata->base = ioport_map(region, 64); hostdata->differential = (((1<clock = NCR_D700_CLOCK_MHZ; - hostdata->busrt_length = 8; + hostdata->burst_length = 8; /* and register the siop */ host = NCR_700_detect(&NCR_D700_driver_template, hostdata, p->dev); -- cgit v1.2.3 From 3b6e9fafc40e36f50f0bd0f1ee758eecd79f1098 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 26 Jan 2007 14:08:41 -0800 Subject: [SCSI] libsas: Fix incorrect sas_port deformation in sas_form_port Currently, sas_form_port checks the given asd_sas_phy's sas_phy to see if there's already a port attached. If so, the SAS addresses of the port and the phy are compared to determine if we need to detach from the port because the addresses don't match or if we can stop; the SAS address stored in the sas_port reflects whatever device _was_ attached to the port/phy, and the SAS address stored in the sas_port reflects whatever device we just discovered. As written, the code detaches from the port if the addresses _do_ match, and prints an error if they do _not_ match. I believe this to be incorrect, as it seems more logical to keep the port if the addresses match (i.e. the phy was reset but the device didn't change), and detach it they do not (i.e. the device changed). Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index a796ae31430e..e1e2d085c920 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c @@ -46,7 +46,7 @@ static void sas_form_port(struct asd_sas_phy *phy) if (port) { if (memcmp(port->attached_sas_addr, phy->attached_sas_addr, - SAS_ADDR_SIZE) == 0) + SAS_ADDR_SIZE) != 0) sas_deform_port(phy); else { SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n", -- cgit v1.2.3 From 6f63caae2172e97e528b58319480217b0b36542e Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 26 Jan 2007 14:08:43 -0800 Subject: [SCSI] libsas: Clean up discovery failure handler code sas_rphy_delete does two things: it removes the sas_rphy from the transport layer and frees the sas_rphy. This can be broken down into two functions, sas_rphy_remove and sas_rphy_free; sas_rphy_remove is of interest to sas_discover_root_expander because it calls functions that require sas_rphy_add as a prerequisite and can fail (namely sas_discover_expander). In that case, sas_discover_root_expander needs to be able to undo the effects of sas_rphy_add yet leave the job of freeing the sas_rphy to the caller of sas_discover_root_expander. This patch also removes some unnecessary code from sas_discover_end_dev to eliminate an unnecessary cycle of sas_notify_lldd_gone/found for SAS devices, thus eliminating a sas_rphy_remove call (and fixing a race condition where a SCSI target scan can come in between the gone and found call). It also moves the sas_rphy_free calls into sas_discover_domain and sas_ex_discover_end_dev to complement the sas_rphy_allocation via sas_get_port_device. This patch does not change the semantics of sas_rphy_delete. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_discover.c | 45 ++++++++++++++------------------------ drivers/scsi/libsas/sas_expander.c | 8 +++---- drivers/scsi/scsi_transport_sas.c | 33 ++++++++++++++++------------ include/scsi/scsi_transport_sas.h | 1 + 4 files changed, 40 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index b6ba0e053d1a..a65598b1e536 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -577,8 +577,6 @@ int sas_discover_sata(struct domain_device *dev) out_err: sas_notify_lldd_dev_gone(dev); out_err2: - sas_rphy_free(dev->rphy); - dev->rphy = NULL; return res; } @@ -600,24 +598,11 @@ int sas_discover_end_dev(struct domain_device *dev) if (res) goto out_err; - /* do this to get the end device port attributes which will have - * been scanned in sas_rphy_add */ - sas_notify_lldd_dev_gone(dev); - res = sas_notify_lldd_dev_found(dev); - if (res) - goto out_err3; - return 0; out_err: sas_notify_lldd_dev_gone(dev); out_err2: - sas_rphy_free(dev->rphy); - dev->rphy = NULL; - return res; -out_err3: - sas_rphy_delete(dev->rphy); - dev->rphy = NULL; return res; } @@ -672,6 +657,7 @@ void sas_unregister_domain_devices(struct asd_sas_port *port) */ static void sas_discover_domain(struct work_struct *work) { + struct domain_device *dev; int error = 0; struct sas_discovery_event *ev = container_of(work, struct sas_discovery_event, work); @@ -681,39 +667,42 @@ static void sas_discover_domain(struct work_struct *work) &port->disc.pending); if (port->port_dev) - return ; - else { - error = sas_get_port_device(port); - if (error) - return; - } + return; + + error = sas_get_port_device(port); + if (error) + return; + dev = port->port_dev; SAS_DPRINTK("DOING DISCOVERY on port %d, pid:%d\n", port->id, current->pid); - switch (port->port_dev->dev_type) { + switch (dev->dev_type) { case SAS_END_DEV: - error = sas_discover_end_dev(port->port_dev); + error = sas_discover_end_dev(dev); break; case EDGE_DEV: case FANOUT_DEV: - error = sas_discover_root_expander(port->port_dev); + error = sas_discover_root_expander(dev); break; case SATA_DEV: case SATA_PM: - error = sas_discover_sata(port->port_dev); + error = sas_discover_sata(dev); break; default: - SAS_DPRINTK("unhandled device %d\n", port->port_dev->dev_type); + SAS_DPRINTK("unhandled device %d\n", dev->dev_type); break; } if (error) { + sas_rphy_free(dev->rphy); + dev->rphy = NULL; + spin_lock(&port->dev_list_lock); - list_del_init(&port->port_dev->dev_list_node); + list_del_init(&dev->dev_list_node); spin_unlock(&port->dev_list_lock); - kfree(port->port_dev); /* not kobject_register-ed yet */ + kfree(dev); /* not kobject_register-ed yet */ port->port_dev = NULL; } diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 0dfd97e7e96c..d9b9a008d36d 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -667,6 +667,8 @@ static struct domain_device *sas_ex_discover_end_dev( return child; out_list_del: + sas_rphy_free(child->rphy); + child->rphy = NULL; list_del(&child->dev_list_node); out_free: sas_port_delete(phy->port); @@ -1444,12 +1446,8 @@ int sas_discover_root_expander(struct domain_device *dev) return res; out_err2: - sas_rphy_delete(dev->rphy); - dev->rphy = NULL; - return res; + sas_rphy_remove(dev->rphy); out_err: - sas_rphy_free(dev->rphy); - dev->rphy = NULL; return res; } diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index ce232803f433..010845fd2b85 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1299,7 +1299,7 @@ EXPORT_SYMBOL(sas_rphy_add); * Note: * This function must only be called on a remote * PHY that has not sucessfully been added using - * sas_rphy_add(). + * sas_rphy_add() (or has been sas_rphy_remove()'d) */ void sas_rphy_free(struct sas_rphy *rphy) { @@ -1318,18 +1318,30 @@ void sas_rphy_free(struct sas_rphy *rphy) EXPORT_SYMBOL(sas_rphy_free); /** - * sas_rphy_delete -- remove SAS remote PHY - * @rphy: SAS remote PHY to remove + * sas_rphy_delete -- remove and free SAS remote PHY + * @rphy: SAS remote PHY to remove and free * - * Removes the specified SAS remote PHY. + * Removes the specified SAS remote PHY and frees it. */ void sas_rphy_delete(struct sas_rphy *rphy) +{ + sas_rphy_remove(rphy); + sas_rphy_free(rphy); +} +EXPORT_SYMBOL(sas_rphy_delete); + +/** + * sas_rphy_remove -- remove SAS remote PHY + * @rphy: SAS remote phy to remove + * + * Removes the specified SAS remote PHY. + */ +void +sas_rphy_remove(struct sas_rphy *rphy) { struct device *dev = &rphy->dev; struct sas_port *parent = dev_to_sas_port(dev->parent); - struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); - struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); switch (rphy->identify.device_type) { case SAS_END_DEVICE: @@ -1345,17 +1357,10 @@ sas_rphy_delete(struct sas_rphy *rphy) transport_remove_device(dev); device_del(dev); - transport_destroy_device(dev); - - mutex_lock(&sas_host->lock); - list_del(&rphy->list); - mutex_unlock(&sas_host->lock); parent->rphy = NULL; - - put_device(dev); } -EXPORT_SYMBOL(sas_rphy_delete); +EXPORT_SYMBOL(sas_rphy_remove); /** * scsi_is_sas_rphy -- check if a struct device represents a SAS remote PHY diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 45d58598c3ee..9aedc19820b0 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h @@ -182,6 +182,7 @@ extern struct sas_rphy *sas_end_device_alloc(struct sas_port *); extern struct sas_rphy *sas_expander_alloc(struct sas_port *, enum sas_device_type); void sas_rphy_free(struct sas_rphy *); extern int sas_rphy_add(struct sas_rphy *); +extern void sas_rphy_remove(struct sas_rphy *); extern void sas_rphy_delete(struct sas_rphy *); extern int scsi_is_sas_rphy(const struct device *); -- cgit v1.2.3 From 21434966462d57145c861b43f6206d945ac57630 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 26 Jan 2007 14:08:46 -0800 Subject: [SCSI] libsas: Check return values of sysfs_create_link Get rid of: "warning: ignoring return value of sysfs_create_link..." Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 010845fd2b85..6d39150e205b 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -625,8 +625,19 @@ static void sas_port_release(struct device *dev) static void sas_port_create_link(struct sas_port *port, struct sas_phy *phy) { - sysfs_create_link(&port->dev.kobj, &phy->dev.kobj, phy->dev.bus_id); - sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port"); + int res; + + res = sysfs_create_link(&port->dev.kobj, &phy->dev.kobj, + phy->dev.bus_id); + if (res) + goto err; + res = sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port"); + if (res) + goto err; + return; +err: + printk(KERN_ERR "%s: Cannot create port links, err=%d\n", + __FUNCTION__, res); } static void sas_port_delete_link(struct sas_port *port, @@ -864,13 +875,20 @@ EXPORT_SYMBOL(sas_port_delete_phy); void sas_port_mark_backlink(struct sas_port *port) { + int res; struct device *parent = port->dev.parent->parent->parent; if (port->is_backlink) return; port->is_backlink = 1; - sysfs_create_link(&port->dev.kobj, &parent->kobj, - parent->bus_id); + res = sysfs_create_link(&port->dev.kobj, &parent->kobj, + parent->bus_id); + if (res) + goto err; + return; +err: + printk(KERN_ERR "%s: Cannot create port backlink, err=%d\n", + __FUNCTION__, res); } EXPORT_SYMBOL(sas_port_mark_backlink); -- cgit v1.2.3 From dca84e4694419adf61ad052b1e5a50ac82726597 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 26 Jan 2007 14:08:49 -0800 Subject: [SCSI] scsi_error.c: Export some scsi_eh_* functions Export a couple of functions from scsi_error that are needed to handle failed SCSI commands from the SAS EH. Signed-off-by: Darrick J. Wong make exports GPL and Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 12 +++++++----- drivers/scsi/scsi_priv.h | 5 +++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 2ecb6ff42444..8e5011d13a18 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -672,8 +672,8 @@ EXPORT_SYMBOL(scsi_eh_finish_cmd); * XXX: Long term this code should go away, but that needs an audit of * all LLDDs first. **/ -static int scsi_eh_get_sense(struct list_head *work_q, - struct list_head *done_q) +int scsi_eh_get_sense(struct list_head *work_q, + struct list_head *done_q) { struct scsi_cmnd *scmd, *next; int rtn; @@ -715,6 +715,7 @@ static int scsi_eh_get_sense(struct list_head *work_q, return list_empty(work_q); } +EXPORT_SYMBOL_GPL(scsi_eh_get_sense); /** * scsi_try_to_abort_cmd - Ask host to abort a running command. @@ -1411,9 +1412,9 @@ static void scsi_restart_operations(struct Scsi_Host *shost) * @eh_done_q: list_head for processed commands. * **/ -static void scsi_eh_ready_devs(struct Scsi_Host *shost, - struct list_head *work_q, - struct list_head *done_q) +void scsi_eh_ready_devs(struct Scsi_Host *shost, + struct list_head *work_q, + struct list_head *done_q) { if (!scsi_eh_stu(shost, work_q, done_q)) if (!scsi_eh_bus_device_reset(shost, work_q, done_q)) @@ -1421,6 +1422,7 @@ static void scsi_eh_ready_devs(struct Scsi_Host *shost, if (!scsi_eh_host_reset(work_q, done_q)) scsi_eh_offline_sdevs(work_q, done_q); } +EXPORT_SYMBOL_GPL(scsi_eh_ready_devs); /** * scsi_eh_flush_done_q - finish processed commands or retry them. diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index d4faa19609d9..ee8efe849bf4 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -57,6 +57,11 @@ extern int scsi_error_handler(void *host); extern int scsi_decide_disposition(struct scsi_cmnd *cmd); extern void scsi_eh_wakeup(struct Scsi_Host *shost); extern int scsi_eh_scmd_add(struct scsi_cmnd *, int); +void scsi_eh_ready_devs(struct Scsi_Host *shost, + struct list_head *work_q, + struct list_head *done_q); +int scsi_eh_get_sense(struct list_head *work_q, + struct list_head *done_q); /* scsi_lib.c */ extern int scsi_maybe_unblock_host(struct scsi_device *sdev); -- cgit v1.2.3 From ad689233bee854dced741c91aff12a8771a22f6f Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 26 Jan 2007 14:08:52 -0800 Subject: [SCSI] libsas: Handle SCSI commands that complete with failure codes This patch moves the code that handles SAS failures out of the main EH function and into a separate function. It also detects commands that have no sas_task (i.e. they completed, but with error data) and sends them into scsi_error for processing. This allows us to handle SCSI errors (and enables auto-spinup as a side effect) instead of dropping them on the floor and falling into an infinite loop. It also requires the implementation of a device reset function, which the SAS failure code has been modified to employ for REQ_DEVICE_RESET. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_scsi_host.c | 148 +++++++++++++++++++++++++----------- include/scsi/libsas.h | 1 + 2 files changed, 105 insertions(+), 44 deletions(-) diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 9ffe7605fb9d..eac1d2dde743 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -34,6 +34,7 @@ #include #include "../scsi_sas_internal.h" #include "../scsi_transport_api.h" +#include "../scsi_priv.h" #include #include @@ -396,54 +397,80 @@ static int sas_recover_I_T(struct domain_device *dev) return res; } -static int eh_reset_phy_helper(struct sas_phy *phy) +/* Find the sas_phy that's attached to this device */ +struct sas_phy *find_local_sas_phy(struct domain_device *dev) { - int tmf_resp; + struct domain_device *pdev = dev->parent; + struct ex_phy *exphy = NULL; + int i; + + /* Directly attached device */ + if (!pdev) + return dev->port->phy; - tmf_resp = sas_phy_reset(phy, 1); - if (tmf_resp) - SAS_DPRINTK("Hard reset of phy %d failed 0x%x\n", - phy->identify.phy_identifier, - tmf_resp); + /* Otherwise look in the expander */ + for (i = 0; i < pdev->ex_dev.num_phys; i++) + if (!memcmp(dev->sas_addr, + pdev->ex_dev.ex_phy[i].attached_sas_addr, + SAS_ADDR_SIZE)) { + exphy = &pdev->ex_dev.ex_phy[i]; + break; + } - return tmf_resp; + BUG_ON(!exphy); + return exphy->phy; } -void sas_scsi_recover_host(struct Scsi_Host *shost) +/* Attempt to send a target reset message to a device */ +int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) +{ + struct domain_device *dev = cmd_to_domain_dev(cmd); + struct sas_phy *phy = find_local_sas_phy(dev); + int res; + + res = sas_phy_reset(phy, 1); + if (res) + SAS_DPRINTK("Device reset of %s failed 0x%x\n", + phy->dev.kobj.k_name, + res); + if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE) + return SUCCESS; + + return FAILED; +} + +/* Try to reset a device */ +static int try_to_reset_cmd_device(struct Scsi_Host *shost, + struct scsi_cmnd *cmd) +{ + if (!shost->hostt->eh_device_reset_handler) + return FAILED; + + return shost->hostt->eh_device_reset_handler(cmd); +} + +static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, + struct list_head *work_q, + struct list_head *done_q) { - struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); - unsigned long flags; - LIST_HEAD(error_q); struct scsi_cmnd *cmd, *n; enum task_disposition res = TASK_IS_DONE; int tmf_resp, need_reset; struct sas_internal *i = to_sas_internal(shost->transportt); - struct sas_phy *task_sas_phy = NULL; - - spin_lock_irqsave(shost->host_lock, flags); - list_splice_init(&shost->eh_cmd_q, &error_q); - spin_unlock_irqrestore(shost->host_lock, flags); - - SAS_DPRINTK("Enter %s\n", __FUNCTION__); + unsigned long flags; + struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); - /* All tasks on this list were marked SAS_TASK_STATE_ABORTED - * by sas_scsi_timed_out() callback. - */ Again: - SAS_DPRINTK("going over list...\n"); - list_for_each_entry_safe(cmd, n, &error_q, eh_entry) { + list_for_each_entry_safe(cmd, n, work_q, eh_entry) { struct sas_task *task = TO_SAS_TASK(cmd); - list_del_init(&cmd->eh_entry); - if (!task) { - SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__); + if (!task) continue; - } + + list_del_init(&cmd->eh_entry); spin_lock_irqsave(&task->task_state_lock, flags); need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; - if (need_reset) - task_sas_phy = task->dev->port->phy; spin_unlock_irqrestore(&task->task_state_lock, flags); SAS_DPRINTK("trying to find task 0x%p\n", task); @@ -457,14 +484,14 @@ Again: task); task->task_done(task); if (need_reset) - eh_reset_phy_helper(task_sas_phy); + try_to_reset_cmd_device(shost, cmd); continue; case TASK_IS_ABORTED: SAS_DPRINTK("%s: task 0x%p is aborted\n", __FUNCTION__, task); task->task_done(task); if (need_reset) - eh_reset_phy_helper(task_sas_phy); + try_to_reset_cmd_device(shost, cmd); continue; case TASK_IS_AT_LU: SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); @@ -476,8 +503,8 @@ Again: cmd->device->lun); task->task_done(task); if (need_reset) - eh_reset_phy_helper(task_sas_phy); - sas_scsi_clear_queue_lu(&error_q, cmd); + try_to_reset_cmd_device(shost, cmd); + sas_scsi_clear_queue_lu(work_q, cmd); goto Again; } /* fallthrough */ @@ -491,8 +518,8 @@ Again: SAS_ADDR(task->dev->sas_addr)); task->task_done(task); if (need_reset) - eh_reset_phy_helper(task_sas_phy); - sas_scsi_clear_queue_I_T(&error_q, task->dev); + try_to_reset_cmd_device(shost, cmd); + sas_scsi_clear_queue_I_T(work_q, task->dev); goto Again; } /* Hammer time :-) */ @@ -506,8 +533,8 @@ Again: "succeeded\n", port->id); task->task_done(task); if (need_reset) - eh_reset_phy_helper(task_sas_phy); - sas_scsi_clear_queue_port(&error_q, + try_to_reset_cmd_device(shost, cmd); + sas_scsi_clear_queue_port(work_q, port); goto Again; } @@ -520,7 +547,7 @@ Again: "succeeded\n"); task->task_done(task); if (need_reset) - eh_reset_phy_helper(task_sas_phy); + try_to_reset_cmd_device(shost, cmd); goto out; } } @@ -535,21 +562,53 @@ Again: task->task_done(task); if (need_reset) - eh_reset_phy_helper(task_sas_phy); + try_to_reset_cmd_device(shost, cmd); goto clear_q; } } out: - scsi_eh_flush_done_q(&ha->eh_done_q); - SAS_DPRINTK("--- Exit %s\n", __FUNCTION__); - return; + return list_empty(work_q); clear_q: SAS_DPRINTK("--- Exit %s -- clear_q\n", __FUNCTION__); - list_for_each_entry_safe(cmd, n, &error_q, eh_entry) { + list_for_each_entry_safe(cmd, n, work_q, eh_entry) { struct sas_task *task = TO_SAS_TASK(cmd); list_del_init(&cmd->eh_entry); task->task_done(task); } + return list_empty(work_q); +} + +void sas_scsi_recover_host(struct Scsi_Host *shost) +{ + struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); + unsigned long flags; + LIST_HEAD(eh_work_q); + + spin_lock_irqsave(shost->host_lock, flags); + list_splice_init(&shost->eh_cmd_q, &eh_work_q); + spin_unlock_irqrestore(shost->host_lock, flags); + + SAS_DPRINTK("Enter %s\n", __FUNCTION__); + /* + * Deal with commands that still have SAS tasks (i.e. they didn't + * complete via the normal sas_task completion mechanism) + */ + if (sas_eh_handle_sas_errors(shost, &eh_work_q, &ha->eh_done_q)) + goto out; + + /* + * Now deal with SCSI commands that completed ok but have a an error + * code (and hopefully sense data) attached. This is roughly what + * scsi_unjam_host does, but we skip scsi_eh_abort_cmds because any + * command we see here has no sas_task and is thus unknown to the HA. + */ + if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q)) + scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q); + +out: + scsi_eh_flush_done_q(&ha->eh_done_q); + SAS_DPRINTK("--- Exit %s\n", __FUNCTION__); + return; } enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) @@ -914,3 +973,4 @@ EXPORT_SYMBOL_GPL(__sas_task_abort); EXPORT_SYMBOL_GPL(sas_task_abort); EXPORT_SYMBOL_GPL(sas_phy_reset); EXPORT_SYMBOL_GPL(sas_phy_enable); +EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index ca393929c10b..b200233cc6f4 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -660,5 +660,6 @@ void sas_init_dev(struct domain_device *); void sas_task_abort(struct sas_task *); int __sas_task_abort(struct sas_task *); +int sas_eh_device_reset_handler(struct scsi_cmnd *cmd); #endif /* _SASLIB_H_ */ -- cgit v1.2.3 From 111367f5c9a0af0f3a42c39dee7360ca217cba1d Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 26 Jan 2007 14:08:55 -0800 Subject: [SCSI] aic94xx: Register eh_device_reset_handler Register libsas's default device reset code with the scsi. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 421e98e1d522..3aa568fbdbf7 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -79,6 +79,7 @@ static struct scsi_host_template aic94xx_sht = { .sg_tablesize = SG_ALL, .max_sectors = SCSI_DEFAULT_MAX_SECTORS, .use_clustering = ENABLE_CLUSTERING, + .eh_device_reset_handler = sas_eh_device_reset_handler, }; static int __devinit asd_map_memio(struct asd_ha_struct *asd_ha) -- cgit v1.2.3 From f27708fc7523a87e3e69cae5628015961f0d3061 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 26 Jan 2007 14:08:58 -0800 Subject: [SCSI] libsas: Enable automatic spin-up of SAS disks Set allow_restart=1 for all SAS disks so that they are spun up when needed. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_scsi_host.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index eac1d2dde743..04eace9020ba 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -723,6 +723,8 @@ int sas_slave_configure(struct scsi_device *scsi_dev) scsi_deactivate_tcq(scsi_dev, 1); } + scsi_dev->allow_restart = 1; + return 0; } -- cgit v1.2.3 From 20ce791a0e684dceea2b6804a7c7aaa22e8bfa5c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 25 Jan 2007 18:15:03 -0800 Subject: [SCSI] ipr: remove duplicate device id This patch removes a duplicate device id from the IPR driver. Based on the ipr.h file, I'm not so sure this was intended to be a duplicate, and if so, the .h file should be modified to use the proper sub-device id instead. This was pointed out to me by Kay Sievers Signed-off-by: Greg Kroah-Hartman Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 4f5273ea2772..95045e33710d 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -7552,8 +7552,6 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, - PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B8, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, 0 }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, -- cgit v1.2.3 From 63bb1bf0400414c0bc51cf276daa0fb5168d1e61 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sun, 28 Jan 2007 01:19:41 +0900 Subject: [SCSI] libsas: fix task attribute Why TASK_ATTR_HOQ? Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_scsi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 04eace9020ba..cd2378010c7e 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -131,7 +131,7 @@ static enum task_attribute sas_scsi_get_task_attr(struct scsi_cmnd *cmd) if (cmd->request && blk_rq_tagged(cmd->request)) { if (cmd->device->ordered_tags && (cmd->request->cmd_flags & REQ_HARDBARRIER)) - ta = TASK_ATTR_HOQ; + ta = TASK_ATTR_ORDERED; } return ta; } -- cgit v1.2.3 From 3c6061236801a376d86ca75fd56d61f964611dd5 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 29 Jan 2007 10:22:18 -0800 Subject: [SCSI] qla2xxx: Correct sector-erase issues while writing flash. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_sup.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 15390ad87456..7bbe751a7334 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -611,7 +611,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, flash_conf_to_access_addr(0x0339), (fdata & 0xff00) | ((fdata << 16) & 0xff0000) | ((fdata >> 16) & 0xff)); - fdata = (faddr & sec_mask) << 2; ret = qla24xx_write_flash_dword(ha, conf_addr, (fdata & 0xff00) |((fdata << 16) & 0xff0000) | ((fdata >> 16) & 0xff)); -- cgit v1.2.3 From a8488abefaa863a0c3a19888f03395adb3f1c6d2 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 29 Jan 2007 10:22:19 -0800 Subject: [SCSI] qla2xxx: Add MSI-X support. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 24 +++++ drivers/scsi/qla2xxx/qla_gbl.h | 3 + drivers/scsi/qla2xxx/qla_init.c | 2 + drivers/scsi/qla2xxx/qla_isr.c | 215 ++++++++++++++++++++++++++++++++++++++++ drivers/scsi/qla2xxx/qla_os.c | 14 +-- 5 files changed, 247 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index c4fc40f8e8ca..8d7e8cb1e703 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2046,6 +2046,27 @@ struct isp_operations { uint32_t); }; +/* MSI-X Support *************************************************************/ + +#define QLA_MSIX_CHIP_REV_24XX 3 +#define QLA_MSIX_FW_MODE(m) (((m) & (BIT_7|BIT_8|BIT_9)) >> 7) +#define QLA_MSIX_FW_MODE_1(m) (QLA_MSIX_FW_MODE(m) == 1) + +#define QLA_MSIX_DEFAULT 0x00 +#define QLA_MSIX_RSP_Q 0x01 + +#define QLA_MSIX_ENTRIES 2 +#define QLA_MIDX_DEFAULT 0 +#define QLA_MIDX_RSP_Q 1 + +struct scsi_qla_host; + +struct qla_msix_entry { + int have_irq; + uint16_t msix_vector; + uint16_t msix_entry; +}; + /* * Linux Host Adapter structure */ @@ -2356,6 +2377,7 @@ typedef struct scsi_qla_host { uint8_t host_str[16]; uint32_t pci_attr; + uint16_t chip_revision; uint16_t product_id[4]; @@ -2389,6 +2411,8 @@ typedef struct scsi_qla_host { uint16_t zio_mode; uint16_t zio_timer; struct fc_host_statistics fc_host_stat; + + struct qla_msix_entry msix_entries[QLA_MSIX_ENTRIES]; } scsi_qla_host_t; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 32ebeec45ff0..e6ca2bc9a28d 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -225,6 +225,9 @@ extern irqreturn_t qla24xx_intr_handler(int, void *); extern void qla2x00_process_response_queue(struct scsi_qla_host *); extern void qla24xx_process_response_queue(struct scsi_qla_host *); +extern int qla2x00_request_irqs(scsi_qla_host_t *); +extern void qla2x00_free_irqs(scsi_qla_host_t *); + /* * Global Function Prototypes in qla_sup.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index a823f0bc519d..b6f0494e034c 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -293,6 +293,8 @@ qla24xx_pci_config(scsi_qla_host_t *ha) d &= ~PCI_ROM_ADDRESS_ENABLE; pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); + pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->chip_revision); + /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); ha->pci_attr = RD_REG_DWORD(®->ctrl_status); diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index b95fcb2c065e..e883b5fc3b08 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1529,3 +1529,218 @@ qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt) qla2x00_sp_compl(ha, sp); } +static irqreturn_t +qla24xx_msix_rsp_q(int irq, void *dev_id) +{ + scsi_qla_host_t *ha; + struct device_reg_24xx __iomem *reg; + unsigned long flags; + + ha = dev_id; + reg = &ha->iobase->isp24; + + spin_lock_irqsave(&ha->hardware_lock, flags); + + qla24xx_process_response_queue(ha); + + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); + RD_REG_DWORD_RELAXED(®->hccr); + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return IRQ_HANDLED; +} + +static irqreturn_t +qla24xx_msix_default(int irq, void *dev_id) +{ + scsi_qla_host_t *ha; + struct device_reg_24xx __iomem *reg; + int status; + unsigned long flags; + unsigned long iter; + uint32_t stat; + uint32_t hccr; + uint16_t mb[4]; + + ha = dev_id; + reg = &ha->iobase->isp24; + status = 0; + + spin_lock_irqsave(&ha->hardware_lock, flags); + for (iter = 50; iter--; ) { + stat = RD_REG_DWORD(®->host_status); + if (stat & HSRX_RISC_PAUSED) { + hccr = RD_REG_DWORD(®->hccr); + + qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " + "Dumping firmware!\n", hccr); + ha->isp_ops.fw_dump(ha, 1); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + break; + } else if ((stat & HSRX_RISC_INT) == 0) + break; + + switch (stat & 0xff) { + case 0x1: + case 0x2: + case 0x10: + case 0x11: + qla24xx_mbx_completion(ha, MSW(stat)); + status |= MBX_INTERRUPT; + + break; + case 0x12: + mb[0] = MSW(stat); + mb[1] = RD_REG_WORD(®->mailbox1); + mb[2] = RD_REG_WORD(®->mailbox2); + mb[3] = RD_REG_WORD(®->mailbox3); + qla2x00_async_event(ha, mb); + break; + case 0x13: + qla24xx_process_response_queue(ha); + break; + default: + DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " + "(%d).\n", + ha->host_no, stat & 0xff)); + break; + } + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); + RD_REG_DWORD_RELAXED(®->hccr); + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && + (status & MBX_INTERRUPT) && ha->flags.mbox_int) { + spin_lock_irqsave(&ha->mbx_reg_lock, flags); + + set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + up(&ha->mbx_intr_sem); + + spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); + } + + return IRQ_HANDLED; +} + +/* Interrupt handling helpers. */ + +struct qla_init_msix_entry { + uint16_t entry; + uint16_t index; + const char *name; + irqreturn_t (*handler)(int, void *); +}; + +static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = { + { QLA_MSIX_DEFAULT, QLA_MIDX_DEFAULT, + "qla2xxx (default)", qla24xx_msix_default }, + + { QLA_MSIX_RSP_Q, QLA_MIDX_RSP_Q, + "qla2xxx (rsp_q)", qla24xx_msix_rsp_q }, +}; + +static void +qla24xx_disable_msix(scsi_qla_host_t *ha) +{ + int i; + struct qla_msix_entry *qentry; + + for (i = 0; i < QLA_MSIX_ENTRIES; i++) { + qentry = &ha->msix_entries[imsix_entries[i].index]; + if (qentry->have_irq) + free_irq(qentry->msix_vector, ha); + } + pci_disable_msix(ha->pdev); +} + +static int +qla24xx_enable_msix(scsi_qla_host_t *ha) +{ + int i, ret; + struct msix_entry entries[QLA_MSIX_ENTRIES]; + struct qla_msix_entry *qentry; + + for (i = 0; i < QLA_MSIX_ENTRIES; i++) + entries[i].entry = imsix_entries[i].entry; + + ret = pci_enable_msix(ha->pdev, entries, ARRAY_SIZE(entries)); + if (ret) { + qla_printk(KERN_WARNING, ha, + "MSI-X: Failed to enable support -- %d/%d\n", + QLA_MSIX_ENTRIES, ret); + goto msix_out; + } + ha->flags.msix_enabled = 1; + + for (i = 0; i < QLA_MSIX_ENTRIES; i++) { + qentry = &ha->msix_entries[imsix_entries[i].index]; + qentry->msix_vector = entries[i].vector; + qentry->msix_entry = entries[i].entry; + qentry->have_irq = 0; + ret = request_irq(qentry->msix_vector, + imsix_entries[i].handler, 0, imsix_entries[i].name, ha); + if (ret) { + qla_printk(KERN_WARNING, ha, + "MSI-X: Unable to register handler -- %x/%d.\n", + imsix_entries[i].index, ret); + qla24xx_disable_msix(ha); + goto msix_out; + } + qentry->have_irq = 1; + } + +msix_out: + return ret; +} + +int +qla2x00_request_irqs(scsi_qla_host_t *ha) +{ + int ret; + + /* If possible, enable MSI-X. */ + if (!IS_QLA2432(ha)) + goto skip_msix; + + if (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX || + !QLA_MSIX_FW_MODE_1(ha->fw_attributes)) { + DEBUG2(qla_printk(KERN_WARNING, ha, + "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n", + ha->chip_revision, ha->fw_attributes)); + + goto skip_msix; + } + + ret = qla24xx_enable_msix(ha); + if (!ret) { + DEBUG2(qla_printk(KERN_INFO, ha, + "MSI-X: Enabled (0x%X, 0x%X).\n", ha->chip_revision, + ha->fw_attributes)); + return ret; + } + qla_printk(KERN_WARNING, ha, + "MSI-X: Falling back-to INTa mode -- %d.\n", ret); +skip_msix: + ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler, + IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha); + if (ret) { + qla_printk(KERN_WARNING, ha, + "Failed to reserve interrupt %d already in use.\n", + ha->pdev->irq); + } + ha->host->irq = ha->pdev->irq; + + return ret; +} + +void +qla2x00_free_irqs(scsi_qla_host_t *ha) +{ + + if (ha->flags.msix_enabled) + qla24xx_disable_msix(ha); + else if (ha->host->irq) + free_irq(ha->host->irq, ha); +} diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index d03523d3bf38..2bd70bb82aab 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1612,15 +1612,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) host->max_lun = MAX_LUNS; host->transportt = qla2xxx_transport_template; - ret = request_irq(pdev->irq, ha->isp_ops.intr_handler, - IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha); - if (ret) { - qla_printk(KERN_WARNING, ha, - "Failed to reserve interrupt %d already in use.\n", - pdev->irq); + ret = qla2x00_request_irqs(ha); + if (ret) goto probe_failed; - } - host->irq = pdev->irq; /* Initialized the timer */ qla2x00_start_timer(ha, qla2x00_timer, WATCH_INTERVAL); @@ -1750,9 +1744,7 @@ qla2x00_free_device(scsi_qla_host_t *ha) qla2x00_mem_free(ha); - /* Detach interrupts */ - if (ha->host->irq) - free_irq(ha->host->irq, ha); + qla2x00_free_irqs(ha); /* release io space registers */ if (ha->iobase) -- cgit v1.2.3 From d88021a6710e6ed5d1899ba2e54d4638026e277d Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 29 Jan 2007 10:22:20 -0800 Subject: [SCSI] qla2xxx: Handle IRQ-0 assignments by the system. No restriction should be placed on the IRQ number assigned to a given ISP. Original code incorrectly assumed a non-zero IRQ number assignment by the system. In these circumstances the proper freeing of the IRQ (via free_irq()) would not take place. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_isr.c | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 8d7e8cb1e703..3b26f8e00ace 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2097,6 +2097,7 @@ typedef struct scsi_qla_host { uint32_t enable_lip_full_login :1; uint32_t enable_target_reset :1; uint32_t enable_led_scheme :1; + uint32_t inta_enabled :1; uint32_t msi_enabled :1; uint32_t msix_enabled :1; uint32_t disable_serdes :1; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index e883b5fc3b08..6e19769b46d2 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1725,12 +1725,14 @@ qla2x00_request_irqs(scsi_qla_host_t *ha) skip_msix: ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler, IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha); - if (ret) { + if (!ret) { + ha->flags.inta_enabled = 1; + ha->host->irq = ha->pdev->irq; + } else { qla_printk(KERN_WARNING, ha, "Failed to reserve interrupt %d already in use.\n", ha->pdev->irq); } - ha->host->irq = ha->pdev->irq; return ret; } @@ -1741,6 +1743,6 @@ qla2x00_free_irqs(scsi_qla_host_t *ha) if (ha->flags.msix_enabled) qla24xx_disable_msix(ha); - else if (ha->host->irq) + else if (ha->flags.inta_enabled) free_irq(ha->host->irq, ha); } -- cgit v1.2.3 From 30c4766213aeb684ee477ac7f36703f9134ac7ad Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 29 Jan 2007 10:22:21 -0800 Subject: [SCSI] qla2xxx: Export OptionROM boot-codes version information. This includes BIOS, EFI, FCODE and firmware versions. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 49 ++++++ drivers/scsi/qla2xxx/qla_def.h | 11 ++ drivers/scsi/qla2xxx/qla_gbl.h | 3 + drivers/scsi/qla2xxx/qla_init.c | 4 + drivers/scsi/qla2xxx/qla_os.c | 2 + drivers/scsi/qla2xxx/qla_sup.c | 347 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 416 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 7b18a6c7b7eb..78a5867bf515 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -653,6 +653,43 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf, return count; } +static ssize_t +qla2x00_optrom_bios_version_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + + return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1], + ha->bios_revision[0]); +} + +static ssize_t +qla2x00_optrom_efi_version_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + + return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1], + ha->efi_revision[0]); +} + +static ssize_t +qla2x00_optrom_fcode_version_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + + return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1], + ha->fcode_revision[0]); +} + +static ssize_t +qla2x00_optrom_fw_version_show(struct class_device *cdev, char *buf) +{ + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + + return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n", + ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2], + ha->fw_revision[3]); +} + static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL); static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); @@ -669,6 +706,14 @@ static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show, qla2x00_zio_timer_store); static CLASS_DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show, qla2x00_beacon_store); +static CLASS_DEVICE_ATTR(optrom_bios_version, S_IRUGO, + qla2x00_optrom_bios_version_show, NULL); +static CLASS_DEVICE_ATTR(optrom_efi_version, S_IRUGO, + qla2x00_optrom_efi_version_show, NULL); +static CLASS_DEVICE_ATTR(optrom_fcode_version, S_IRUGO, + qla2x00_optrom_fcode_version_show, NULL); +static CLASS_DEVICE_ATTR(optrom_fw_version, S_IRUGO, + qla2x00_optrom_fw_version_show, NULL); struct class_device_attribute *qla2x00_host_attrs[] = { &class_device_attr_driver_version, @@ -683,6 +728,10 @@ struct class_device_attribute *qla2x00_host_attrs[] = { &class_device_attr_zio, &class_device_attr_zio_timer, &class_device_attr_beacon, + &class_device_attr_optrom_bios_version, + &class_device_attr_optrom_efi_version, + &class_device_attr_optrom_fcode_version, + &class_device_attr_optrom_fw_version, NULL, }; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 3b26f8e00ace..2a59faa632df 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2044,6 +2044,8 @@ struct isp_operations { uint32_t, uint32_t); int (*write_optrom) (struct scsi_qla_host *, uint8_t *, uint32_t, uint32_t); + + int (*get_flash_version) (struct scsi_qla_host *, void *); }; /* MSI-X Support *************************************************************/ @@ -2400,6 +2402,15 @@ typedef struct scsi_qla_host { #define QLA_SREADING 1 #define QLA_SWRITING 2 + /* PCI expansion ROM image information. */ +#define ROM_CODE_TYPE_BIOS 0 +#define ROM_CODE_TYPE_FCODE 1 +#define ROM_CODE_TYPE_EFI 3 + uint8_t bios_revision[2]; + uint8_t efi_revision[2]; + uint8_t fcode_revision[16]; + uint32_t fw_revision[4]; + /* Needed for BEACON */ uint16_t beacon_blink_led; uint8_t beacon_color_state; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index e6ca2bc9a28d..f8bddec4fe85 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -263,6 +263,9 @@ extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *, uint32_t, uint32_t); +extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *); +extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *); + /* * Global Function Prototypes in qla_dbg.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index b6f0494e034c..570f5f8e6c28 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -84,6 +84,8 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) ha->isp_ops.reset_chip(ha); + ha->isp_ops.get_flash_version(ha, ha->request_ring); + qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); ha->isp_ops.nvram_config(ha); @@ -3109,6 +3111,8 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) } spin_unlock_irqrestore(&ha->hardware_lock, flags); + ha->isp_ops.get_flash_version(ha, ha->request_ring); + ha->isp_ops.nvram_config(ha); if (!qla2x00_restart_isp(ha)) { diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2bd70bb82aab..d35ff4a2a764 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1482,6 +1482,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->isp_ops.fw_dump = qla2100_fw_dump; ha->isp_ops.read_optrom = qla2x00_read_optrom_data; ha->isp_ops.write_optrom = qla2x00_write_optrom_data; + ha->isp_ops.get_flash_version = qla2x00_get_flash_version; if (IS_QLA2100(ha)) { host->max_id = MAX_TARGETS_2100; ha->mbx_count = MAILBOX_REGISTER_COUNT_2100; @@ -1547,6 +1548,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->isp_ops.beacon_on = qla24xx_beacon_on; ha->isp_ops.beacon_off = qla24xx_beacon_off; ha->isp_ops.beacon_blink = qla24xx_beacon_blink; + ha->isp_ops.get_flash_version = qla24xx_get_flash_version; ha->gid_list_info_size = 8; ha->optrom_size = OPTROM_SIZE_24XX; } diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 7bbe751a7334..ff1dd4175a7f 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -1382,6 +1382,29 @@ qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, qla2x00_write_flash_byte(ha, 0x5555, 0xf0); } +static void +qla2x00_read_flash_data(scsi_qla_host_t *ha, uint8_t *tmp_buf, uint32_t saddr, + uint32_t length) +{ + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + uint32_t midpoint, ilength; + uint8_t data; + + midpoint = length / 2; + + WRT_REG_WORD(®->nvram, 0); + RD_REG_WORD(®->nvram); + for (ilength = 0; ilength < length; saddr++, ilength++, tmp_buf++) { + if (ilength == midpoint) { + WRT_REG_WORD(®->nvram, NVR_SELECT); + RD_REG_WORD(®->nvram); + } + data = qla2x00_read_flash_byte(ha, saddr); + if (saddr % 100) + udelay(10); + *tmp_buf = data; + } +} static inline void qla2x00_suspend_hba(struct scsi_qla_host *ha) @@ -1721,3 +1744,327 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, return rval; } + +/** + * qla2x00_get_fcode_version() - Determine an FCODE image's version. + * @ha: HA context + * @pcids: Pointer to the FCODE PCI data structure + * + * The process of retrieving the FCODE version information is at best + * described as interesting. + * + * Within the first 100h bytes of the image an ASCII string is present + * which contains several pieces of information including the FCODE + * version. Unfortunately it seems the only reliable way to retrieve + * the version is by scanning for another sentinel within the string, + * the FCODE build date: + * + * ... 2.00.02 10/17/02 ... + * + * Returns QLA_SUCCESS on successful retrieval of version. + */ +static void +qla2x00_get_fcode_version(scsi_qla_host_t *ha, uint32_t pcids) +{ + int ret = QLA_FUNCTION_FAILED; + uint32_t istart, iend, iter, vend; + uint8_t do_next, rbyte, *vbyte; + + memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); + + /* Skip the PCI data structure. */ + istart = pcids + + ((qla2x00_read_flash_byte(ha, pcids + 0x0B) << 8) | + qla2x00_read_flash_byte(ha, pcids + 0x0A)); + iend = istart + 0x100; + do { + /* Scan for the sentinel date string...eeewww. */ + do_next = 0; + iter = istart; + while ((iter < iend) && !do_next) { + iter++; + if (qla2x00_read_flash_byte(ha, iter) == '/') { + if (qla2x00_read_flash_byte(ha, iter + 2) == + '/') + do_next++; + else if (qla2x00_read_flash_byte(ha, + iter + 3) == '/') + do_next++; + } + } + if (!do_next) + break; + + /* Backtrack to previous ' ' (space). */ + do_next = 0; + while ((iter > istart) && !do_next) { + iter--; + if (qla2x00_read_flash_byte(ha, iter) == ' ') + do_next++; + } + if (!do_next) + break; + + /* + * Mark end of version tag, and find previous ' ' (space) or + * string length (recent FCODE images -- major hack ahead!!!). + */ + vend = iter - 1; + do_next = 0; + while ((iter > istart) && !do_next) { + iter--; + rbyte = qla2x00_read_flash_byte(ha, iter); + if (rbyte == ' ' || rbyte == 0xd || rbyte == 0x10) + do_next++; + } + if (!do_next) + break; + + /* Mark beginning of version tag, and copy data. */ + iter++; + if ((vend - iter) && + ((vend - iter) < sizeof(ha->fcode_revision))) { + vbyte = ha->fcode_revision; + while (iter <= vend) { + *vbyte++ = qla2x00_read_flash_byte(ha, iter); + iter++; + } + ret = QLA_SUCCESS; + } + } while (0); + + if (ret != QLA_SUCCESS) + memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); +} + +int +qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf) +{ + int ret = QLA_SUCCESS; + uint8_t code_type, last_image; + uint32_t pcihdr, pcids; + uint8_t *dbyte; + uint16_t *dcode; + + if (!ha->pio_address || !mbuf) + return QLA_FUNCTION_FAILED; + + memset(ha->bios_revision, 0, sizeof(ha->bios_revision)); + memset(ha->efi_revision, 0, sizeof(ha->efi_revision)); + memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); + memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); + + qla2x00_flash_enable(ha); + + /* Begin with first PCI expansion ROM header. */ + pcihdr = 0; + last_image = 1; + do { + /* Verify PCI expansion ROM header. */ + if (qla2x00_read_flash_byte(ha, pcihdr) != 0x55 || + qla2x00_read_flash_byte(ha, pcihdr + 0x01) != 0xaa) { + /* No signature */ + DEBUG2(printk("scsi(%ld): No matching ROM " + "signature.\n", ha->host_no)); + ret = QLA_FUNCTION_FAILED; + break; + } + + /* Locate PCI data structure. */ + pcids = pcihdr + + ((qla2x00_read_flash_byte(ha, pcihdr + 0x19) << 8) | + qla2x00_read_flash_byte(ha, pcihdr + 0x18)); + + /* Validate signature of PCI data structure. */ + if (qla2x00_read_flash_byte(ha, pcids) != 'P' || + qla2x00_read_flash_byte(ha, pcids + 0x1) != 'C' || + qla2x00_read_flash_byte(ha, pcids + 0x2) != 'I' || + qla2x00_read_flash_byte(ha, pcids + 0x3) != 'R') { + /* Incorrect header. */ + DEBUG2(printk("%s(): PCI data struct not found " + "pcir_adr=%x.\n", __func__, pcids)); + ret = QLA_FUNCTION_FAILED; + break; + } + + /* Read version */ + code_type = qla2x00_read_flash_byte(ha, pcids + 0x14); + switch (code_type) { + case ROM_CODE_TYPE_BIOS: + /* Intel x86, PC-AT compatible. */ + ha->bios_revision[0] = + qla2x00_read_flash_byte(ha, pcids + 0x12); + ha->bios_revision[1] = + qla2x00_read_flash_byte(ha, pcids + 0x13); + DEBUG3(printk("%s(): read BIOS %d.%d.\n", __func__, + ha->bios_revision[1], ha->bios_revision[0])); + break; + case ROM_CODE_TYPE_FCODE: + /* Open Firmware standard for PCI (FCode). */ + /* Eeeewww... */ + qla2x00_get_fcode_version(ha, pcids); + break; + case ROM_CODE_TYPE_EFI: + /* Extensible Firmware Interface (EFI). */ + ha->efi_revision[0] = + qla2x00_read_flash_byte(ha, pcids + 0x12); + ha->efi_revision[1] = + qla2x00_read_flash_byte(ha, pcids + 0x13); + DEBUG3(printk("%s(): read EFI %d.%d.\n", __func__, + ha->efi_revision[1], ha->efi_revision[0])); + break; + default: + DEBUG2(printk("%s(): Unrecognized code type %x at " + "pcids %x.\n", __func__, code_type, pcids)); + break; + } + + last_image = qla2x00_read_flash_byte(ha, pcids + 0x15) & BIT_7; + + /* Locate next PCI expansion ROM. */ + pcihdr += ((qla2x00_read_flash_byte(ha, pcids + 0x11) << 8) | + qla2x00_read_flash_byte(ha, pcids + 0x10)) * 512; + } while (!last_image); + + if (IS_QLA2322(ha)) { + /* Read firmware image information. */ + memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); + dbyte = mbuf; + memset(dbyte, 0, 8); + dcode = (uint16_t *)dbyte; + + qla2x00_read_flash_data(ha, dbyte, FA_RISC_CODE_ADDR * 4 + 10, + 8); + DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n", + __func__, ha->host_no)); + DEBUG3(qla2x00_dump_buffer((uint8_t *)dbyte, 8)); + + if ((dcode[0] == 0xffff && dcode[1] == 0xffff && + dcode[2] == 0xffff && dcode[3] == 0xffff) || + (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && + dcode[3] == 0)) { + DEBUG2(printk("%s(): Unrecognized fw revision at " + "%x.\n", __func__, FA_RISC_CODE_ADDR * 4)); + } else { + /* values are in big endian */ + ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1]; + ha->fw_revision[1] = dbyte[2] << 16 | dbyte[3]; + ha->fw_revision[2] = dbyte[4] << 16 | dbyte[5]; + } + } + + qla2x00_flash_disable(ha); + + return ret; +} + +int +qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) +{ + int ret = QLA_SUCCESS; + uint32_t pcihdr, pcids; + uint32_t *dcode; + uint8_t *bcode; + uint8_t code_type, last_image; + int i; + + if (!mbuf) + return QLA_FUNCTION_FAILED; + + memset(ha->bios_revision, 0, sizeof(ha->bios_revision)); + memset(ha->efi_revision, 0, sizeof(ha->efi_revision)); + memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); + memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); + + dcode = mbuf; + + /* Begin with first PCI expansion ROM header. */ + pcihdr = 0; + last_image = 1; + do { + /* Verify PCI expansion ROM header. */ + qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, 0x20); + bcode = mbuf + (pcihdr % 4); + if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) { + /* No signature */ + DEBUG2(printk("scsi(%ld): No matching ROM " + "signature.\n", ha->host_no)); + ret = QLA_FUNCTION_FAILED; + break; + } + + /* Locate PCI data structure. */ + pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]); + + qla24xx_read_flash_data(ha, dcode, pcids >> 2, 0x20); + bcode = mbuf + (pcihdr % 4); + + /* Validate signature of PCI data structure. */ + if (bcode[0x0] != 'P' || bcode[0x1] != 'C' || + bcode[0x2] != 'I' || bcode[0x3] != 'R') { + /* Incorrect header. */ + DEBUG2(printk("%s(): PCI data struct not found " + "pcir_adr=%x.\n", __func__, pcids)); + ret = QLA_FUNCTION_FAILED; + break; + } + + /* Read version */ + code_type = bcode[0x14]; + switch (code_type) { + case ROM_CODE_TYPE_BIOS: + /* Intel x86, PC-AT compatible. */ + ha->bios_revision[0] = bcode[0x12]; + ha->bios_revision[1] = bcode[0x13]; + DEBUG3(printk("%s(): read BIOS %d.%d.\n", __func__, + ha->bios_revision[1], ha->bios_revision[0])); + break; + case ROM_CODE_TYPE_FCODE: + /* Open Firmware standard for PCI (FCode). */ + ha->fcode_revision[0] = bcode[0x12]; + ha->fcode_revision[1] = bcode[0x13]; + DEBUG3(printk("%s(): read FCODE %d.%d.\n", __func__, + ha->fcode_revision[1], ha->fcode_revision[0])); + break; + case ROM_CODE_TYPE_EFI: + /* Extensible Firmware Interface (EFI). */ + ha->efi_revision[0] = bcode[0x12]; + ha->efi_revision[1] = bcode[0x13]; + DEBUG3(printk("%s(): read EFI %d.%d.\n", __func__, + ha->efi_revision[1], ha->efi_revision[0])); + break; + default: + DEBUG2(printk("%s(): Unrecognized code type %x at " + "pcids %x.\n", __func__, code_type, pcids)); + break; + } + + last_image = bcode[0x15] & BIT_7; + + /* Locate next PCI expansion ROM. */ + pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512; + } while (!last_image); + + /* Read firmware image information. */ + memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); + dcode = mbuf; + + qla24xx_read_flash_data(ha, dcode, FA_RISC_CODE_ADDR + 4, 4); + for (i = 0; i < 4; i++) + dcode[i] = be32_to_cpu(dcode[i]); + + if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && + dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || + (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && + dcode[3] == 0)) { + DEBUG2(printk("%s(): Unrecognized fw version at %x.\n", + __func__, FA_RISC_CODE_ADDR)); + } else { + ha->fw_revision[0] = dcode[0]; + ha->fw_revision[1] = dcode[1]; + ha->fw_revision[2] = dcode[2]; + ha->fw_revision[3] = dcode[3]; + } + + return ret; +} -- cgit v1.2.3 From b1372bc90ffd5e2d2543e10924c1971a86e25310 Mon Sep 17 00:00:00 2001 From: Lalit Chandivade Date: Mon, 29 Jan 2007 10:22:22 -0800 Subject: [SCSI] qla2xxx: Perform implicit LOGO during fabric logout request. Similarly to previous LOGO requests on non-24xx hardware, perform an implicit-LOGO as to avoid the potential 2 * R_A_TOV delay which can result during an explicit-LOGO request. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mbx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 4cde76c85cb3..c52bd9ca8d7a 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1713,7 +1713,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, lg->entry_count = 1; lg->nport_handle = cpu_to_le16(loop_id); lg->control_flags = - __constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_EXPL_LOGO); + __constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO); lg->port_id[0] = al_pa; lg->port_id[1] = area; lg->port_id[2] = domain; -- cgit v1.2.3 From 2603221a285e32a1033dcefa8de38a989a7633e0 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 29 Jan 2007 10:22:23 -0800 Subject: [SCSI] qla2xxx: Set correct cabling state during initialization. Previous work to add asynchronous-scsi-scanning support (d19044c32baadeb80e135027124a9e845c6f057c) caused peculiar semantic changes when no cabling was attached to the HBA whereby unneeded and intrusive 'error-handling' would take place due to the initial link state being unset. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 570f5f8e6c28..3757d7479586 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -65,7 +65,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) ha->flags.reset_active = 0; atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); atomic_set(&ha->loop_state, LOOP_DOWN); - ha->device_flags = 0; + ha->device_flags = DFLG_NO_CABLE; ha->dpc_flags = 0; ha->flags.management_server_logged_in = 0; ha->marker_needed = 0; -- cgit v1.2.3 From 9bb9fcf2f2b4deeb3ae8a44ed4b8686302297030 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 29 Jan 2007 10:22:24 -0800 Subject: [SCSI] qla2xxx: Refactor set-HBA-model/description code. Limit assignments via qla2x00_model_name[] array to HBA subsystem vendor IDs equal to QLogic. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 83 ++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 46 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 3757d7479586..ee4b79eb59ce 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1355,6 +1355,39 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) return(rval); } +static inline void +qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *def) +{ + char *st, *en; + uint16_t index; + + if (memcmp(model, BINZERO, len) != 0) { + strncpy(ha->model_number, model, len); + st = en = ha->model_number; + en += len - 1; + while (en > st) { + if (*en != 0x20 && *en != 0x00) + break; + *en-- = '\0'; + } + + index = (ha->pdev->subsystem_device & 0xff); + if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && + index < QLA_MODEL_NAMES) + ha->model_desc = qla2x00_model_name[index * 2 + 1]; + } else { + index = (ha->pdev->subsystem_device & 0xff); + if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && + index < QLA_MODEL_NAMES) { + strcpy(ha->model_number, + qla2x00_model_name[index * 2]); + ha->model_desc = qla2x00_model_name[index * 2 + 1]; + } else { + strcpy(ha->model_number, def); + } + } +} + /* * NVRAM configuration for ISP 2xxx * @@ -1493,33 +1526,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) strcpy(ha->model_number, "QLA2300"); } } else { - if (rval == 0 && - memcmp(nv->model_number, BINZERO, - sizeof(nv->model_number)) != 0) { - char *st, *en; - - strncpy(ha->model_number, nv->model_number, - sizeof(nv->model_number)); - st = en = ha->model_number; - en += sizeof(nv->model_number) - 1; - while (en > st) { - if (*en != 0x20 && *en != 0x00) - break; - *en-- = '\0'; - } - } else { - uint16_t index; - - index = (ha->pdev->subsystem_device & 0xff); - if (index < QLA_MODEL_NAMES) { - strcpy(ha->model_number, - qla2x00_model_name[index * 2]); - ha->model_desc = - qla2x00_model_name[index * 2 + 1]; - } else { - strcpy(ha->model_number, "QLA23xx"); - } - } + qla2x00_set_model_info(ha, nv->model_number, + sizeof(nv->model_number), "QLA23xx"); } } else if (IS_QLA2200(ha)) { nv->firmware_options[0] |= BIT_2; @@ -3444,25 +3452,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) /* * Setup driver NVRAM options. */ - if (memcmp(nv->model_name, BINZERO, sizeof(nv->model_name)) != 0) { - char *st, *en; - uint16_t index; - - strncpy(ha->model_number, nv->model_name, - sizeof(nv->model_name)); - st = en = ha->model_number; - en += sizeof(nv->model_name) - 1; - while (en > st) { - if (*en != 0x20 && *en != 0x00) - break; - *en-- = '\0'; - } - - index = (ha->pdev->subsystem_device & 0xff); - if (index < QLA_MODEL_NAMES) - ha->model_desc = qla2x00_model_name[index * 2 + 1]; - } else - strcpy(ha->model_number, "QLA2462"); + qla2x00_set_model_info(ha, nv->model_name, sizeof(nv->model_name), + "QLA2462"); /* Use alternate WWN? */ if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { -- cgit v1.2.3 From 178779a6ca7c23b52d5537b972f2b54c830b4480 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 29 Jan 2007 10:22:25 -0800 Subject: [SCSI] qla2xxx: Check loop-state before reading host statistics. Non-ISP24xx cards must have a loop-id in order to query host statistics. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 78a5867bf515..834c404973b6 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -885,21 +885,24 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) link_stat_t stat_buf; struct fc_host_statistics *pfc_host_stat; + rval = QLA_FUNCTION_FAILED; pfc_host_stat = &ha->fc_host_stat; memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, sizeof(stat_buf) / 4, mb_stat); - } else { + } else if (atomic_read(&ha->loop_state) == LOOP_READY && + !test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) && + !test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) && + !ha->dpc_active) { + /* Must be in a 'READY' state for statistics retrieval. */ rval = qla2x00_get_link_status(ha, ha->loop_id, &stat_buf, mb_stat); } - if (rval != 0) { - qla_printk(KERN_WARNING, ha, - "Unable to retrieve host statistics (%d).\n", mb_stat[0]); - return pfc_host_stat; - } + + if (rval != QLA_SUCCESS) + goto done; pfc_host_stat->link_failure_count = stat_buf.link_fail_cnt; pfc_host_stat->loss_of_sync_count = stat_buf.loss_sync_cnt; @@ -907,7 +910,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) pfc_host_stat->prim_seq_protocol_err_count = stat_buf.prim_seq_err_cnt; pfc_host_stat->invalid_tx_word_count = stat_buf.inval_xmit_word_cnt; pfc_host_stat->invalid_crc_count = stat_buf.inval_crc_cnt; - +done: return pfc_host_stat; } -- cgit v1.2.3 From 7aef45ac92f49e76d990b51b7ecd714b9a608be1 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 29 Jan 2007 10:22:26 -0800 Subject: [SCSI] qla2xxx: Fail initialization when inconsistent NVRAM detected. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 125 +++++----------------------------------- 1 file changed, 14 insertions(+), 111 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index ee4b79eb59ce..b247bc22704e 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -88,7 +88,12 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); - ha->isp_ops.nvram_config(ha); + rval = ha->isp_ops.nvram_config(ha); + if (rval) { + DEBUG2(printk("scsi(%ld): Unable to verify NVRAM data.\n", + ha->host_no)); + return rval; + } if (ha->flags.disable_serdes) { /* Mask HBA via NVRAM settings? */ @@ -1404,7 +1409,6 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de int qla2x00_nvram_config(scsi_qla_host_t *ha) { - int rval; uint8_t chksum = 0; uint16_t cnt; uint8_t *dptr1, *dptr2; @@ -1413,8 +1417,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) uint8_t *ptr = (uint8_t *)ha->request_ring; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - rval = QLA_SUCCESS; - /* Determine NVRAM starting address. */ ha->nvram_size = sizeof(nvram_t); ha->nvram_base = 0; @@ -1438,55 +1440,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], nv->nvram_version); - qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " - "invalid -- WWPN) defaults.\n"); - - /* - * Set default initialization control block. - */ - memset(nv, 0, ha->nvram_size); - nv->parameter_block_version = ICB_VERSION; - - if (IS_QLA23XX(ha)) { - nv->firmware_options[0] = BIT_2 | BIT_1; - nv->firmware_options[1] = BIT_7 | BIT_5; - nv->add_firmware_options[0] = BIT_5; - nv->add_firmware_options[1] = BIT_5 | BIT_4; - nv->frame_payload_size = __constant_cpu_to_le16(2048); - nv->special_options[1] = BIT_7; - } else if (IS_QLA2200(ha)) { - nv->firmware_options[0] = BIT_2 | BIT_1; - nv->firmware_options[1] = BIT_7 | BIT_5; - nv->add_firmware_options[0] = BIT_5; - nv->add_firmware_options[1] = BIT_5 | BIT_4; - nv->frame_payload_size = __constant_cpu_to_le16(1024); - } else if (IS_QLA2100(ha)) { - nv->firmware_options[0] = BIT_3 | BIT_1; - nv->firmware_options[1] = BIT_5; - nv->frame_payload_size = __constant_cpu_to_le16(1024); - } - - nv->max_iocb_allocation = __constant_cpu_to_le16(256); - nv->execution_throttle = __constant_cpu_to_le16(16); - nv->retry_count = 8; - nv->retry_delay = 1; - - nv->port_name[0] = 33; - nv->port_name[3] = 224; - nv->port_name[4] = 139; - - nv->login_timeout = 4; - - /* - * Set default host adapter parameters - */ - nv->host_p[1] = BIT_2; - nv->reset_delay = 5; - nv->port_down_retry_count = 8; - nv->max_luns_per_target = __constant_cpu_to_le16(8); - nv->link_down_timeout = 60; - - rval = 1; + return QLA_FUNCTION_FAILED; } #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) @@ -1699,11 +1653,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) } } - if (rval) { - DEBUG2_3(printk(KERN_WARNING - "scsi(%ld): NVRAM configuration failed!\n", ha->host_no)); - } - return (rval); + return QLA_SUCCESS; } static void @@ -3121,7 +3071,9 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) ha->isp_ops.get_flash_version(ha, ha->request_ring); - ha->isp_ops.nvram_config(ha); + rval = ha->isp_ops.nvram_config(ha); + if (rval) + goto isp_abort_retry; if (!qla2x00_restart_isp(ha)) { clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); @@ -3151,6 +3103,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) } } } else { /* failed the ISP abort */ +isp_abort_retry: ha->flags.online = 1; if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) { if (ha->isp_abort_cnt == 0) { @@ -3340,7 +3293,6 @@ qla24xx_reset_adapter(scsi_qla_host_t *ha) int qla24xx_nvram_config(scsi_qla_host_t *ha) { - int rval; struct init_cb_24xx *icb; struct nvram_24xx *nv; uint32_t *dptr; @@ -3348,7 +3300,6 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) uint32_t chksum; uint16_t cnt; - rval = QLA_SUCCESS; icb = (struct init_cb_24xx *)ha->init_cb; nv = (struct nvram_24xx *)ha->request_ring; @@ -3381,51 +3332,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], le16_to_cpu(nv->nvram_version)); - qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " - "invalid -- WWPN) defaults.\n"); - - /* - * Set default initialization control block. - */ - memset(nv, 0, ha->nvram_size); - nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION); - nv->version = __constant_cpu_to_le16(ICB_VERSION); - nv->frame_payload_size = __constant_cpu_to_le16(2048); - nv->execution_throttle = __constant_cpu_to_le16(0xFFFF); - nv->exchange_count = __constant_cpu_to_le16(0); - nv->hard_address = __constant_cpu_to_le16(124); - nv->port_name[0] = 0x21; - nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn); - nv->port_name[2] = 0x00; - nv->port_name[3] = 0xe0; - nv->port_name[4] = 0x8b; - nv->port_name[5] = 0x1c; - nv->port_name[6] = 0x55; - nv->port_name[7] = 0x86; - nv->node_name[0] = 0x20; - nv->node_name[1] = 0x00; - nv->node_name[2] = 0x00; - nv->node_name[3] = 0xe0; - nv->node_name[4] = 0x8b; - nv->node_name[5] = 0x1c; - nv->node_name[6] = 0x55; - nv->node_name[7] = 0x86; - nv->login_retry_count = __constant_cpu_to_le16(8); - nv->interrupt_delay_timer = __constant_cpu_to_le16(0); - nv->login_timeout = __constant_cpu_to_le16(0); - nv->firmware_options_1 = - __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1); - nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4); - nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12); - nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13); - nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10); - nv->efi_parameters = __constant_cpu_to_le32(0); - nv->reset_delay = 5; - nv->max_luns_per_target = __constant_cpu_to_le16(128); - nv->port_down_retry_count = __constant_cpu_to_le16(30); - nv->link_down_timeout = __constant_cpu_to_le16(30); - - rval = 1; + return QLA_FUNCTION_FAILED; } /* Reset Initialization control block */ @@ -3570,11 +3477,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ha->flags.process_response_queue = 1; } - if (rval) { - DEBUG2_3(printk(KERN_WARNING - "scsi(%ld): NVRAM configuration failed!\n", ha->host_no)); - } - return (rval); + return QLA_SUCCESS; } static int -- cgit v1.2.3 From ffec28a3e959b156ea5906838a8897e27c8bbf22 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 29 Jan 2007 10:22:27 -0800 Subject: [SCSI] qla2xxx: Enable queue-full throttling when UNDERRUN detected. As ISP24xx firmware can return a CS_DATA_UNDERRUN completion status when the storage has returned a SAM_STAT_TASK_SET_FULL scsi-status. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 6e19769b46d2..df69dc016a53 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -987,6 +987,22 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) if (lscsi_status != 0) { cp->result = DID_OK << 16 | lscsi_status; + if (lscsi_status == SAM_STAT_TASK_SET_FULL) { + DEBUG2(printk(KERN_INFO + "scsi(%ld): QUEUE FULL status detected " + "0x%x-0x%x.\n", ha->host_no, comp_status, + scsi_status)); + + /* + * Adjust queue depth for all luns on the + * port. + */ + fcport->last_queue_full = jiffies; + starget_for_each_device( + cp->device->sdev_target, fcport, + qla2x00_adjust_sdev_qdepth_down); + break; + } if (lscsi_status != SS_CHECK_CONDITION) break; -- cgit v1.2.3 From 26b8d34808598aae760091ae551182de91f3e0ae Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 29 Jan 2007 10:22:28 -0800 Subject: [SCSI] qla2xxx: Allow NVRAM updates to immediately go into effect. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 834c404973b6..8081b637d97e 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -140,6 +140,8 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off, ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); spin_unlock_irqrestore(&ha->hardware_lock, flags); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + return (count); } -- cgit v1.2.3 From 7c98a046b76a3a858c21b75235bf146493b76e11 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 29 Jan 2007 10:22:29 -0800 Subject: [SCSI] qla2xxx: Fixup printk() with proper new-line character. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index b247bc22704e..ef87d81935d2 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -77,7 +77,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); rval = ha->isp_ops.pci_config(ha); if (rval) { - DEBUG2(printk("scsi(%ld): Unable to configure PCI space=n", + DEBUG2(printk("scsi(%ld): Unable to configure PCI space.\n", ha->host_no)); return (rval); } -- cgit v1.2.3 From 03c79cc56e4497cbd09d74a73c1bd0d1d9a8a16c Mon Sep 17 00:00:00 2001 From: Seokmann Ju Date: Mon, 29 Jan 2007 10:22:30 -0800 Subject: [SCSI] qla2xxx: Remove unnecessary spinlock primitive - mbx_reg_lock. Since, mailbox commands are executed in a synchronous manner, there is no need to have a separate spinlock primitive to protect data/register access shared by callers. Signed-off-by: Seokmann Ju Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 2 -- drivers/scsi/qla2xxx/qla_isr.c | 16 ---------------- drivers/scsi/qla2xxx/qla_mbx.c | 16 ---------------- drivers/scsi/qla2xxx/qla_os.c | 8 -------- 4 files changed, 42 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 2a59faa632df..e83e4a34725a 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2338,8 +2338,6 @@ typedef struct scsi_qla_host { #define MBX_INTR_WAIT 2 #define MBX_UPDATE_FLASH_ACTIVE 3 - spinlock_t mbx_reg_lock; /* Mbx Cmd Register Lock */ - struct semaphore mbx_cmd_sem; /* Serialialize mbx access */ struct semaphore mbx_intr_sem; /* Used for completion notification */ diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index df69dc016a53..c948a8ce7232 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -86,12 +86,8 @@ qla2100_intr_handler(int irq, void *dev_id) if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { - spin_lock_irqsave(&ha->mbx_reg_lock, flags); - set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); up(&ha->mbx_intr_sem); - - spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); } return (IRQ_HANDLED); @@ -197,12 +193,8 @@ qla2300_intr_handler(int irq, void *dev_id) if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { - spin_lock_irqsave(&ha->mbx_reg_lock, flags); - set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); up(&ha->mbx_intr_sem); - - spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); } return (IRQ_HANDLED); @@ -1491,12 +1483,8 @@ qla24xx_intr_handler(int irq, void *dev_id) if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { - spin_lock_irqsave(&ha->mbx_reg_lock, flags); - set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); up(&ha->mbx_intr_sem); - - spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); } return IRQ_HANDLED; @@ -1629,12 +1617,8 @@ qla24xx_msix_default(int irq, void *dev_id) if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { - spin_lock_irqsave(&ha->mbx_reg_lock, flags); - set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); up(&ha->mbx_intr_sem); - - spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); } return IRQ_HANDLED; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index c52bd9ca8d7a..c6f0cdf4cdc4 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -55,7 +55,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) uint16_t __iomem *optr; uint32_t cnt; uint32_t mboxes; - unsigned long mbx_flags = 0; unsigned long wait_time; rval = QLA_SUCCESS; @@ -81,10 +80,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) /* Save mailbox command for debug */ ha->mcp = mcp; - /* Try to get mailbox register access */ - if (!abort_active) - spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); - DEBUG11(printk("scsi(%ld): prepare to issue mbox cmd=0x%x.\n", ha->host_no, mcp->mb[0])); @@ -161,9 +156,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); spin_unlock_irqrestore(&ha->hardware_lock, flags); - if (!abort_active) - spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags); - /* Wait for either the timer to expire * or the mbox completion interrupt */ @@ -184,8 +176,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) else WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); spin_unlock_irqrestore(&ha->hardware_lock, flags); - if (!abort_active) - spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags); wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */ while (!ha->flags.mbox_int) { @@ -201,9 +191,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) } /* while */ } - if (!abort_active) - spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); - /* Check whether we timed out */ if (ha->flags.mbox_int) { uint16_t *iptr2; @@ -256,9 +243,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) rval = QLA_FUNCTION_TIMEOUT; } - if (!abort_active) - spin_unlock_irqrestore(&ha->mbx_reg_lock, mbx_flags); - ha->flags.mbox_busy = 0; /* Clean up */ diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index d35ff4a2a764..6f161d3f661b 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1563,14 +1563,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) INIT_LIST_HEAD(&ha->list); INIT_LIST_HEAD(&ha->fcports); - /* - * These locks are used to prevent more than one CPU - * from modifying the queue at the same time. The - * higher level "host_lock" will reduce most - * contention for these locks. - */ - spin_lock_init(&ha->mbx_reg_lock); - qla2x00_config_dma_addressing(ha); if (qla2x00_mem_alloc(ha)) { qla_printk(KERN_WARNING, ha, -- cgit v1.2.3 From 7b3b92116387fbea7b3b42553180984a544206d9 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Mon, 29 Jan 2007 10:22:31 -0800 Subject: [SCSI] qla2xxx: Update version number to 8.01.07-k5. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 459e0d6bd2b4..61347aee55ce 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.01.07-k4" +#define QLA2XXX_VERSION "8.01.07-k5" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 1 -- cgit v1.2.3 From fd1b494d4a8147da4517fef72d15116bbb1a2dc7 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Wed, 29 Nov 2006 19:45:23 -0800 Subject: [SCSI] Fix sense key MEDIUM ERROR processing and retry 1) If the device reports an uncorrectable MEDIUM ERROR, such as SK MEDIUM ERROR, ASC UNRECOVERED READ ERR, AMNF DATA FIELD or RECORD NOT FOUND, then: In scsi_check_sense() return SUCCESS so as to not retry -- the error is uncorrectable -- this speeds up total processing time. Signed-off-by: Luben Tuikov Extracted the MEDIUM ERROR piece and Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 8e5011d13a18..2dce06a58c08 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -359,6 +359,11 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) return SUCCESS; case MEDIUM_ERROR: + if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */ + sshdr.asc == 0x13 || /* AMNF DATA FIELD */ + sshdr.asc == 0x14) { /* RECORD NOT FOUND */ + return SUCCESS; + } return NEEDS_RETRY; case HARDWARE_ERROR: -- cgit v1.2.3 From 502c62f17aa7daa78d5da963305251b872885ff9 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Mon, 29 Jan 2007 09:41:12 -0700 Subject: [SCSI] spi transport class: export spi_dv_pending Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_spi.c | 1 - include/scsi/scsi_transport_spi.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 014d7fea1ff3..6f56f8750635 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -46,7 +46,6 @@ * two cc/ua clears */ /* Private data accessors (keep these out of the header file) */ -#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) #define spi_dv_in_progress(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_in_progress) #define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex) diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h index da180f738477..286e9628ed8b 100644 --- a/include/scsi/scsi_transport_spi.h +++ b/include/scsi/scsi_transport_spi.h @@ -85,6 +85,7 @@ struct spi_host_attrs { #define spi_pcomp_en(x) (((struct spi_transport_attrs *)&(x)->starget_data)->pcomp_en) #define spi_hold_mcs(x) (((struct spi_transport_attrs *)&(x)->starget_data)->hold_mcs) #define spi_initial_dv(x) (((struct spi_transport_attrs *)&(x)->starget_data)->initial_dv) +#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) #define spi_support_sync(x) (((struct spi_transport_attrs *)&(x)->starget_data)->support_sync) #define spi_support_wide(x) (((struct spi_transport_attrs *)&(x)->starget_data)->support_wide) -- cgit v1.2.3 From 793955f549c710a1b0c18f823d5d710840747b15 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Mon, 29 Jan 2007 09:42:20 -0700 Subject: [SCSI] fusion - Greater than 255 target and lun support Add support for greater than 255 target and luns. Kill the hd->Target[] field, and change all references of bus_id/target_id, to channel/id. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/Makefile | 2 +- drivers/message/fusion/mptbase.c | 29 +++- drivers/message/fusion/mptbase.h | 12 +- drivers/message/fusion/mptctl.c | 159 +++++++------------- drivers/message/fusion/mptfc.c | 51 +++---- drivers/message/fusion/mptsas.c | 73 +++++---- drivers/message/fusion/mptscsih.c | 301 +++++++++++--------------------------- drivers/message/fusion/mptscsih.h | 42 +++++- drivers/message/fusion/mptspi.c | 188 ++++++++++++++++-------- 9 files changed, 380 insertions(+), 477 deletions(-) diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 341691390e86..3217076b40f4 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile @@ -8,6 +8,7 @@ #EXTRA_CFLAGS += -DMPT_DEBUG_INIT #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL +#EXTRA_CFLAGS += -DMPT_DEBUG_TM # # driver/module specifics... @@ -22,7 +23,6 @@ # For mptscsih: #CFLAGS_mptscsih.o += -DMPT_DEBUG_DV #CFLAGS_mptscsih.o += -DMPT_DEBUG_NEGO -#CFLAGS_mptscsih.o += -DMPT_DEBUG_TM #CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI #CFLAGS_mptscsih.o += -DMPT_DEBUG_REPLY # diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index b3f28a03b6a9..a07f0f81f96b 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -82,6 +82,10 @@ static int mpt_msi_enable; module_param(mpt_msi_enable, int, 0); MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)"); +static int mpt_channel_mapping; +module_param(mpt_channel_mapping, int, 0); +MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)"); + #ifdef MFCNT static int mfcounter = 0; #define PRINT_MF_COUNT 20000 @@ -2505,6 +2509,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag) int ii; int req_sz; int reply_sz; + int max_id; /* IOC *must* NOT be in RESET state! */ if (ioc->last_state == MPI_IOC_STATE_RESET) { @@ -2552,6 +2557,21 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag) pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs); pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets); + max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID : + pfacts->MaxDevices; + ioc->devices_per_bus = (max_id > 255) ? 256 : max_id; + ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256; + + /* + * Place all the devices on channels + * + * (for debuging) + */ + if (mpt_channel_mapping) { + ioc->devices_per_bus = 1; + ioc->number_of_buses = (max_id > 255) ? 255 : max_id; + } + return 0; } @@ -2592,13 +2612,8 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n", ioc->name, ioc->upload_fw, ioc->facts.Flags)); - if(ioc->bus_type == SAS) - ioc_init.MaxDevices = ioc->facts.MaxDevices; - else if(ioc->bus_type == FC) - ioc_init.MaxDevices = MPT_MAX_FC_DEVICES; - else - ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES; - ioc_init.MaxBuses = MPT_MAX_BUS; + ioc_init.MaxDevices = (U8)ioc->devices_per_bus; + ioc_init.MaxBuses = (U8)ioc->number_of_buses; dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n", ioc->name, ioc->facts.MsgVersion)); if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) { diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index e316708f76bd..f82a817de81f 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -334,8 +334,8 @@ typedef struct _VirtTarget { struct scsi_target *starget; u8 tflags; u8 ioc_id; - u8 target_id; - u8 bus_id; + u8 id; + u8 channel; u8 minSyncFactor; /* 0xFF is async */ u8 maxOffset; /* 0 if async */ u8 maxWidth; /* 0 if narrow, 1 if wide */ @@ -344,13 +344,12 @@ typedef struct _VirtTarget { u8 type; /* byte 0 of Inquiry data */ u8 deleted; /* target in process of being removed */ u32 num_luns; - u32 luns[8]; /* Max LUNs is 256 */ } VirtTarget; typedef struct _VirtDevice { VirtTarget *vtarget; u8 configured_lun; - u32 lun; + int lun; } VirtDevice; /* @@ -412,7 +411,7 @@ typedef struct _MPT_IOCTL { u8 rsvd; u8 status; /* current command status */ u8 reset; /* 1 if bus reset allowed */ - u8 target; /* target for reset */ + u8 id; /* target for reset */ struct mutex ioctl_mutex; } MPT_IOCTL; @@ -528,6 +527,8 @@ typedef struct _MPT_ADAPTER u32 mem_phys; /* == f4020000 (mmap) */ u32 pio_mem_phys; /* Programmed IO (downloadboot) */ int mem_size; /* mmap memory size */ + int number_of_buses; + int devices_per_bus; int alloc_total; u32 last_state; int active; @@ -957,7 +958,6 @@ typedef struct _MPT_SCSI_HOST { int port; u32 pad0; struct scsi_cmnd **ScsiLookup; - VirtTarget **Targets; MPT_LOCAL_REPLY *pLocal; /* used for internal commands */ struct timer_list timer; /* Pool of memory for holding SCpnts before doing diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 504632da4347..922d0c879f06 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -361,7 +361,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl) ioctl->ioc->name, mf)); pScsiTm = (SCSITaskMgmt_t *) mf; - pScsiTm->TargetID = ioctl->target; + pScsiTm->TargetID = ioctl->id; pScsiTm->Bus = hd->port; /* 0 */ pScsiTm->ChainOffset = 0; pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; @@ -1159,15 +1159,12 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) struct mpt_ioctl_iocinfo *karg; MPT_ADAPTER *ioc; struct pci_dev *pdev; - struct Scsi_Host *sh; - MPT_SCSI_HOST *hd; int iocnum; - int numDevices = 0; - unsigned int max_id; - int ii; unsigned int port; int cim_rev; u8 revision; + struct scsi_device *sdev; + VirtDevice *vdev; dctlprintk((": mptctl_getiocinfo called.\n")); /* Add of PCI INFO results in unaligned access for @@ -1257,23 +1254,16 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) /* Get number of devices */ - if ((sh = ioc->sh) != NULL) { - /* sh->max_id = maximum target ID + 1 - */ - max_id = sh->max_id - 1; - hd = (MPT_SCSI_HOST *) sh->hostdata; - - /* Check all of the target structures and - * keep a counter. - */ - if (hd && hd->Targets) { - for (ii = 0; ii <= max_id; ii++) { - if (hd->Targets[ii]) - numDevices++; - } + karg->numDevices = 0; + if (ioc->sh) { + shost_for_each_device(sdev, ioc->sh) { + vdev = sdev->hostdata; + if (vdev->vtarget->tflags & + MPT_TARGET_FLAGS_RAID_COMPONENT) + continue; + karg->numDevices++; } } - karg->numDevices = numDevices; /* Set the BIOS and FW Version */ @@ -1319,21 +1309,16 @@ mptctl_gettargetinfo (unsigned long arg) struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg; struct mpt_ioctl_targetinfo karg; MPT_ADAPTER *ioc; - struct Scsi_Host *sh; - MPT_SCSI_HOST *hd; - VirtTarget *vdev; + VirtDevice *vdev; char *pmem; int *pdata; - IOCPage2_t *pIoc2; - IOCPage3_t *pIoc3; int iocnum; int numDevices = 0; - unsigned int max_id; - int id, jj, indexed_lun, lun_index; - u32 lun; + int lun; int maxWordsLeft; int numBytes; - u8 port, devType, bus_id; + u8 port; + struct scsi_device *sdev; dctlprintk(("mptctl_gettargetinfo called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) { @@ -1389,74 +1374,22 @@ mptctl_gettargetinfo (unsigned long arg) /* Get number of devices */ - if ((sh = ioc->sh) != NULL) { - - max_id = sh->max_id - 1; - hd = (MPT_SCSI_HOST *) sh->hostdata; - - /* Check all of the target structures. - * Save the Id and increment the counter, - * if ptr non-null. - * sh->max_id = maximum target ID + 1 - */ - if (hd && hd->Targets) { - mpt_findImVolumes(ioc); - pIoc2 = ioc->raid_data.pIocPg2; - for ( id = 0; id <= max_id; ) { - if ( pIoc2 && pIoc2->NumActiveVolumes ) { - if ( id == pIoc2->RaidVolume[0].VolumeID ) { - if (maxWordsLeft <= 0) { - printk(KERN_ERR "mptctl_gettargetinfo - " - "buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices); - goto data_space_full; - } - if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 ) - devType = 0x80; - else - devType = 0xC0; - bus_id = pIoc2->RaidVolume[0].VolumeBus; - numDevices++; - *pdata = ( (devType << 24) | (bus_id << 8) | id ); - dctlprintk((KERN_ERR "mptctl_gettargetinfo - " - "volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata)); - pdata++; - --maxWordsLeft; - goto next_id; - } else { - pIoc3 = ioc->raid_data.pIocPg3; - for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) { - if ( pIoc3->PhysDisk[jj].PhysDiskID == id ) - goto next_id; - } - } - } - if ( (vdev = hd->Targets[id]) ) { - for (jj = 0; jj <= MPT_LAST_LUN; jj++) { - lun_index = (jj >> 5); - indexed_lun = (jj % 32); - lun = (1 << indexed_lun); - if (vdev->luns[lun_index] & lun) { - if (maxWordsLeft <= 0) { - printk(KERN_ERR "mptctl_gettargetinfo - " - "buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices); - goto data_space_full; - } - bus_id = vdev->bus_id; - numDevices++; - *pdata = ( (jj << 16) | (bus_id << 8) | id ); - dctlprintk((KERN_ERR "mptctl_gettargetinfo - " - "target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata)); - pdata++; - --maxWordsLeft; - } - } - } -next_id: - id++; - } + if (ioc->sh){ + shost_for_each_device(sdev, ioc->sh) { + if (!maxWordsLeft) + continue; + vdev = sdev->hostdata; + if (vdev->vtarget->tflags & + MPT_TARGET_FLAGS_RAID_COMPONENT) + continue; + lun = (vdev->vtarget->raidVolume) ? 0x80 : vdev->lun; + *pdata = (((u8)lun << 16) + (vdev->vtarget->channel << 8) + + (vdev->vtarget->id )); + pdata++; + numDevices++; + --maxWordsLeft; } } -data_space_full: karg.numDevices = numDevices; /* Copy part of the data from kernel memory to user memory @@ -1821,6 +1754,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) int msgContext; u16 req_idx; ulong timeout; + struct scsi_device *sdev; dctlprintk(("mptctl_do_mpt_command called.\n")); bufIn.kptr = bufOut.kptr = NULL; @@ -1902,14 +1836,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) case MPI_FUNCTION_SCSI_IO_REQUEST: if (ioc->sh) { SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf; - VirtTarget *pTarget = NULL; - MPT_SCSI_HOST *hd = NULL; int qtag = MPI_SCSIIO_CONTROL_UNTAGGED; int scsidir = 0; - int target = (int) pScsiReq->TargetID; int dataSize; + u32 id; - if ((target < 0) || (target >= ioc->sh->max_id)) { + id = (ioc->devices_per_bus == 0) ? 256 : ioc->devices_per_bus; + if (pScsiReq->TargetID > id) { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Target ID out of bounds. \n", __FILE__, __LINE__); @@ -1917,6 +1850,14 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) goto done_free_mem; } + if (pScsiReq->Bus >= ioc->number_of_buses) { + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "Target Bus out of bounds. \n", + __FILE__, __LINE__); + rc = -ENODEV; + goto done_free_mem; + } + pScsiReq->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH; pScsiReq->MsgFlags |= mpt_msg_flags(); @@ -1936,13 +1877,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) cpu_to_le32(ioc->sense_buf_low_dma + (req_idx * MPT_SENSE_BUFFER_ALLOC)); - if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) { - if (hd->Targets) - pTarget = hd->Targets[target]; - } + shost_for_each_device(sdev, ioc->sh) { + struct scsi_target *starget = scsi_target(sdev); + VirtTarget *vtarget = starget->hostdata; - if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) - qtag = MPI_SCSIIO_CONTROL_SIMPLEQ; + if ((pScsiReq->TargetID == vtarget->id) && + (pScsiReq->Bus == vtarget->channel) && + (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) + qtag = MPI_SCSIIO_CONTROL_SIMPLEQ; + } /* Have the IOCTL driver set the direction based * on the dataOutSize (ordering issue with Sparc). @@ -1959,7 +1902,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) pScsiReq->DataLength = cpu_to_le32(dataSize); ioc->ioctl->reset = MPTCTL_RESET_OK; - ioc->ioctl->target = target; + ioc->ioctl->id = pScsiReq->TargetID; } else { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " @@ -2038,7 +1981,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) pScsiReq->DataLength = cpu_to_le32(dataSize); ioc->ioctl->reset = MPTCTL_RESET_OK; - ioc->ioctl->target = pScsiReq->TargetID; + ioc->ioctl->id = pScsiReq->TargetID; } else { printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "SCSI driver is not loaded. \n", diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index c819c23b55b1..cd8fa39ec270 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -86,6 +86,12 @@ MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the " " return following a device loss event." " Default=60."); +/* scsi-mid layer global parmeter is max_report_luns, which is 511 */ +#define MPTFC_MAX_LUN (16895) +static int max_lun = MPTFC_MAX_LUN; +module_param(max_lun, int, 0); +MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); + static int mptfcDoneCtx = -1; static int mptfcTaskCtx = -1; static int mptfcInternalCtx = -1; /* Used only for internal commands */ @@ -292,10 +298,9 @@ mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port, U32 port_id = 0xffffff; int num_targ = 0; int max_bus = ioc->facts.MaxBuses; - int max_targ = ioc->facts.MaxDevices; + int max_targ; - if (max_bus == 0 || max_targ == 0) - goto out; + max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices; data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ; p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL); @@ -467,8 +472,8 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) if (ri->starget) { vtarget = ri->starget->hostdata; if (vtarget) { - vtarget->target_id = pg0->CurrentTargetID; - vtarget->bus_id = pg0->CurrentBus; + vtarget->id = pg0->CurrentTargetID; + vtarget->channel = pg0->CurrentBus; } } *((struct mptfc_rport_info **)rport->dd_data) = ri; @@ -540,8 +545,8 @@ mptfc_target_alloc(struct scsi_target *starget) if (rport) { ri = *((struct mptfc_rport_info **)rport->dd_data); if (ri) { /* better be! */ - vtarget->target_id = ri->pg0.CurrentTargetID; - vtarget->bus_id = ri->pg0.CurrentBus; + vtarget->id = ri->pg0.CurrentTargetID; + vtarget->channel = ri->pg0.CurrentBus; ri->starget = starget; rc = 0; } @@ -592,7 +597,6 @@ mptfc_slave_alloc(struct scsi_device *sdev) if (vtarget->num_luns == 0) { vtarget->ioc_id = hd->ioc->id; vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; - hd->Targets[sdev->id] = vtarget; } vdev->vtarget = vtarget; @@ -630,16 +634,17 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) struct mptfc_rport_info *ri; struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device)); int err; + VirtDevice *vdev = SCpnt->device->hostdata; - err = fc_remote_port_chkready(rport); - if (unlikely(err)) { - SCpnt->result = err; + if (!vdev || !vdev->vtarget) { + SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; } - if (!SCpnt->device->hostdata) { /* vdev */ - SCpnt->result = DID_NO_CONNECT << 16; + err = fc_remote_port_chkready(rport); + if (unlikely(err)) { + SCpnt->result = err; done(SCpnt); return 0; } @@ -1143,7 +1148,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) printk(MYIOC_s_WARN_FMT "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", ioc->name, ioc); - return -ENODEV; + return 0; } sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST)); @@ -1173,10 +1178,9 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* set 16 byte cdb's */ sh->max_cmd_len = 16; - sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255; + sh->max_id = ioc->pfacts->MaxDevices; + sh->max_lun = max_lun; - sh->max_lun = MPT_LAST_LUN + 1; - sh->max_channel = 0; sh->this_id = ioc->pfacts[0].PortSCSIID; /* Required entry. @@ -1230,19 +1234,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", ioc->name, hd->ScsiLookup)); - /* Allocate memory for the device structures. - * A non-Null pointer at an offset - * indicates a device exists. - * max_id = 1 + maximum id (hosts.h) - */ - hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); - if (!hd->Targets) { - error = -ENOMEM; - goto out_mptfc_probe; - } - - dprintk((KERN_INFO " vdev @ %p\n", hd->Targets)); - /* Clear the TM flags */ hd->tmPending = 0; diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 09e9a9d96410..f7c5e0d97890 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -83,6 +83,12 @@ MODULE_PARM_DESC(mpt_pt_clear, " Clear persistency table: enable=1 " "(default=MPTSCSIH_PT_CLEAR=0)"); +/* scsi-mid layer global parmeter is max_report_luns, which is 511 */ +#define MPTSAS_MAX_LUN (16895) +static int max_lun = MPTSAS_MAX_LUN; +module_param(max_lun, int, 0); +MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); + static int mptsasDoneCtx = -1; static int mptsasTaskCtx = -1; static int mptsasInternalCtx = -1; /* Used only for internal commands */ @@ -568,12 +574,12 @@ mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget) if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) { + vtarget->channel, vtarget->id, 0, 0, 5) < 0) { hd->tmPending = 0; hd->tmState = TM_STATE_NONE; printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt id=%d TARGET_RESET\n", - ioc->name, vtarget->target_id); + ioc->name, vtarget->id); } } @@ -661,8 +667,7 @@ mptsas_target_alloc(struct scsi_target *starget) struct Scsi_Host *host = dev_to_shost(&starget->dev); MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; VirtTarget *vtarget; - u32 target_id; - u32 channel; + u8 id, channel; struct sas_rphy *rphy; struct mptsas_portinfo *p; int i; @@ -673,15 +678,19 @@ mptsas_target_alloc(struct scsi_target *starget) vtarget->starget = starget; vtarget->ioc_id = hd->ioc->id; - vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY; - - target_id = starget->id; + vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; + id = starget->id; channel = 0; - hd->Targets[target_id] = vtarget; - - if (starget->channel == MPTSAS_RAID_CHANNEL) + /* + * RAID volumes placed beyond the last expected port. + */ + if (starget->channel == MPTSAS_RAID_CHANNEL) { + for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) + if (id == hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) + channel = hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus; goto out; + } rphy = dev_to_rphy(starget->dev.parent); mutex_lock(&hd->ioc->sas_topology_mutex); @@ -690,16 +699,16 @@ mptsas_target_alloc(struct scsi_target *starget) if (p->phy_info[i].attached.sas_address != rphy->identify.sas_address) continue; - target_id = p->phy_info[i].attached.id; + id = p->phy_info[i].attached.id; channel = p->phy_info[i].attached.channel; mptsas_set_starget(&p->phy_info[i], starget); /* * Exposing hidden raid components */ - if (mptscsih_is_phys_disk(hd->ioc, target_id)) { - target_id = mptscsih_raid_id_to_num(hd, - target_id); + if (mptscsih_is_phys_disk(hd->ioc, channel, id)) { + id = mptscsih_raid_id_to_num(hd->ioc, + channel, id); vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; } @@ -713,8 +722,8 @@ mptsas_target_alloc(struct scsi_target *starget) return -ENXIO; out: - vtarget->target_id = target_id; - vtarget->bus_id = channel; + vtarget->id = id; + vtarget->channel = channel; starget->hostdata = vtarget; return 0; } @@ -786,7 +795,8 @@ mptsas_slave_alloc(struct scsi_device *sdev) * Exposing hidden raid components */ if (mptscsih_is_phys_disk(hd->ioc, - p->phy_info[i].attached.id)) + p->phy_info[i].attached.channel, + p->phy_info[i].attached.id)) sdev->no_uld_attach = 1; mutex_unlock(&hd->ioc->sas_topology_mutex); goto out; @@ -808,13 +818,14 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { VirtDevice *vdev = SCpnt->device->hostdata; -// scsi_print_command(SCpnt); - if (vdev->vtarget->deleted) { + if (!vdev || !vdev->vtarget || vdev->vtarget->deleted) { SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; } +// scsi_print_command(SCpnt); + return mptscsih_qcmd(SCpnt,done); } @@ -1976,7 +1987,7 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) goto out; if (!ioc->raid_data.pIocPg2->NumActiveVolumes) goto out; - for (i=0; iraid_data.pIocPg2->NumActiveVolumes; i++) { + for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); } @@ -2160,7 +2171,7 @@ mptsas_hotplug_work(struct work_struct *work) * Handling RAID components */ if (ev->phys_disk_num_valid) { - vtarget->target_id = ev->phys_disk_num; + vtarget->id = ev->phys_disk_num; vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; mptsas_reprobe_target(starget, 1); break; @@ -2233,7 +2244,7 @@ mptsas_hotplug_work(struct work_struct *work) */ if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT; - vtarget->target_id = ev->id; + vtarget->id = ev->id; mptsas_reprobe_target(starget, 0); } break; @@ -2611,12 +2622,11 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* set 16 byte cdb's */ sh->max_cmd_len = 16; - sh->max_id = ioc->pfacts->MaxDevices + 1; + sh->max_id = ioc->pfacts[0].PortSCSIID; + sh->max_lun = max_lun; sh->transportt = mptsas_transport_template; - sh->max_lun = MPT_LAST_LUN + 1; - sh->max_channel = 0; sh->this_id = ioc->pfacts[0].PortSCSIID; /* Required entry. @@ -2676,19 +2686,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", ioc->name, hd->ScsiLookup)); - /* Allocate memory for the device structures. - * A non-Null pointer at an offset - * indicates a device exists. - * max_id = 1 + maximum id (hosts.h) - */ - hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); - if (!hd->Targets) { - error = -ENOMEM; - goto out_mptsas_probe; - } - - dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets)); - /* Clear the TM flags */ hd->tmPending = 0; diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index f0cca3ea93b2..ce58431bee8e 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -79,43 +79,6 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(my_VERSION); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -typedef struct _BIG_SENSE_BUF { - u8 data[MPT_SENSE_BUFFER_ALLOC]; -} BIG_SENSE_BUF; - -#define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */ -#define MPT_SCANDV_DID_RESET (0x00000001) -#define MPT_SCANDV_SENSE (0x00000002) -#define MPT_SCANDV_SOME_ERROR (0x00000004) -#define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008) -#define MPT_SCANDV_ISSUE_SENSE (0x00000010) -#define MPT_SCANDV_FALLBACK (0x00000020) - -#define MPT_SCANDV_MAX_RETRIES (10) - -#define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */ -#define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */ -#define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */ -#define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */ -#define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */ -#define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */ -#define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */ - -typedef struct _internal_cmd { - char *data; /* data pointer */ - dma_addr_t data_dma; /* data dma address */ - int size; /* transfer size */ - u8 cmd; /* SCSI Op Code */ - u8 bus; /* bus number */ - u8 id; /* SCSI ID (virtual) */ - u8 lun; - u8 flags; /* Bit Field - See above */ - u8 physDiskNum; /* Phys disk number, -1 else */ - u8 rsvd2; - u8 rsvd; -} INTERNAL_CMD; - /* * Other private/forward protos... */ @@ -131,14 +94,14 @@ static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); -static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); +static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev); static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev); -static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus); +static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int channel, int id); int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); @@ -517,13 +480,13 @@ mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget, SEPMsg = (SEPRequest_t *)mf; SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; - SEPMsg->Bus = vtarget->bus_id; - SEPMsg->TargetID = vtarget->target_id; + SEPMsg->Bus = vtarget->channel; + SEPMsg->TargetID = vtarget->id; SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS; SEPMsg->SlotStatus = SlotStatus; devtverboseprintk((MYIOC_s_WARN_FMT - "Sending SEP cmd=%x id=%d bus=%d\n", - ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus)); + "Sending SEP cmd=%x channel=%d id=%d\n", + ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID)); mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); } @@ -955,9 +918,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) int ii; int max = hd->ioc->req_depth; struct scsi_cmnd *sc; + struct scsi_lun lun; - dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n", - vdevice->vtarget->target_id, vdevice->lun, max)); + dsprintk((KERN_INFO MYNAM ": search_running channel %d id %d lun %d max %d\n", + vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max)); for (ii=0; ii < max; ii++) { if ((sc = hd->ScsiLookup[ii]) != NULL) { @@ -965,10 +929,14 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); if (mf == NULL) continue; - dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n", - hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1])); - if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun))) + int_to_scsilun(vdevice->lun, &lun); + if ((mf->Bus != vdevice->vtarget->channel) || + (mf->TargetID != vdevice->vtarget->id) || + memcmp(lun.scsi_lun, mf->LUN, 8)) continue; + dsprintk(( "search_running: found (sc=%p, mf = %p) " + "channel %d id %d, lun %d \n", hd->ScsiLookup[ii], + mf, mf->Bus, mf->TargetID, vdevice->lun)); /* Cleanup */ @@ -1065,12 +1033,6 @@ mptscsih_remove(struct pci_dev *pdev) hd->ScsiLookup = NULL; } - /* - * Free pointer array. - */ - kfree(hd->Targets); - hd->Targets = NULL; - dprintk((MYIOC_s_INFO_FMT "Free'd ScsiLookup (%d) memory\n", hd->ioc->name, sz1)); @@ -1317,14 +1279,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return SCSI_MLQUEUE_HOST_BUSY; } - if ((hd->ioc->bus_type == SPI) && - vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT && - mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) { - SCpnt->result = DID_NO_CONNECT << 16; - done(SCpnt); - return 0; - } - /* * Put together a MPT SCSI request... */ @@ -1368,8 +1322,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* Use the above information to set up the message frame */ - pScsiReq->TargetID = (u8) vdev->vtarget->target_id; - pScsiReq->Bus = vdev->vtarget->bus_id; + pScsiReq->TargetID = (u8) vdev->vtarget->id; + pScsiReq->Bus = vdev->vtarget->channel; pScsiReq->ChainOffset = 0; if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; @@ -1379,14 +1333,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; pScsiReq->Reserved = 0; pScsiReq->MsgFlags = mpt_msg_flags(); - pScsiReq->LUN[0] = 0; - pScsiReq->LUN[1] = lun; - pScsiReq->LUN[2] = 0; - pScsiReq->LUN[3] = 0; - pScsiReq->LUN[4] = 0; - pScsiReq->LUN[5] = 0; - pScsiReq->LUN[6] = 0; - pScsiReq->LUN[7] = 0; + int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN); pScsiReq->Control = cpu_to_le32(scsictl); /* @@ -1498,7 +1445,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) * * @ioc: Pointer to MPT_ADAPTER structure * @type: Task Management type - * @target: Logical Target ID for reset (if appropriate) + * @id: Logical Target ID for reset (if appropriate) * @lun: Logical Unit for reset (if appropriate) * @ctx2abort: Context for the task to be aborted (if appropriate) * @@ -1510,7 +1457,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) * Returns 0 for SUCCESS or -1 if FAILED. */ int -mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout) +mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) { MPT_ADAPTER *ioc; int rc = -1; @@ -1590,7 +1537,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in */ if (hd->hard_resets < -1) hd->hard_resets++; - rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout); + rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun, ctx2abort, timeout); if (rc) { printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name); } else { @@ -1624,7 +1571,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in * mptscsih_IssueTaskMgmt - Generic send Task Management function. * @hd: Pointer to MPT_SCSI_HOST structure * @type: Task Management type - * @target: Logical Target ID for reset (if appropriate) + * @id: Logical Target ID for reset (if appropriate) * @lun: Logical Unit for reset (if appropriate) * @ctx2abort: Context for the task to be aborted (if appropriate) * @@ -1637,7 +1584,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in * else other non-zero value returned. */ static int -mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout) +mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) { MPT_FRAME_HDR *mf; SCSITaskMgmt_t *pScsiTm; @@ -1657,7 +1604,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun /* Format the Request */ pScsiTm = (SCSITaskMgmt_t *) mf; - pScsiTm->TargetID = target; + pScsiTm->TargetID = id; pScsiTm->Bus = channel; pScsiTm->ChainOffset = 0; pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; @@ -1668,10 +1615,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0; - for (ii= 0; ii < 8; ii++) { - pScsiTm->LUN[ii] = 0; - } - pScsiTm->LUN[1] = lun; + int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN); for (ii=0; ii < 7; ii++) pScsiTm->Reserved2[ii] = 0; @@ -1789,7 +1733,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, - vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun, + vdev->vtarget->channel, vdev->vtarget->id, vdev->lun, ctx2abort, mptscsih_get_tm_timeout(hd->ioc)); if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx && @@ -1845,7 +1789,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - vdev->vtarget->bus_id, vdev->vtarget->target_id, + vdev->vtarget->channel, vdev->vtarget->id, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", @@ -1896,7 +1840,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); + vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", hd->ioc->name, @@ -2191,7 +2135,7 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, dprintk((KERN_NOTICE ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n", - sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors)); + sdev->id, sdev->lun, sdev->channel, (int)cylinders, heads, sectors)); return 0; } @@ -2200,115 +2144,46 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, * */ int -mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) +mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) { int i; + int rc = 0; - if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) - return 0; + if (!ioc->raid_data.pIocPg3) + goto out; for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { - if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) - return 1; - } - return 0; -} -EXPORT_SYMBOL(mptscsih_is_phys_disk); - -int -mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid) -{ - int i; - - if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3) - return -ENXIO; - - for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) { - if (physdiskid == - hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) - return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum; + if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) && + (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) { + rc = 1; + goto out; + } } - return -ENXIO; -} -EXPORT_SYMBOL(mptscsih_raid_id_to_num); - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * OS entry point to allow host driver to alloc memory - * for each scsi target. Called once per device the bus scan. - * Return non-zero if allocation fails. - */ -int -mptscsih_target_alloc(struct scsi_target *starget) -{ - VirtTarget *vtarget; - - vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); - if (!vtarget) - return -ENOMEM; - starget->hostdata = vtarget; - vtarget->starget = starget; - return 0; + out: + return rc; } +EXPORT_SYMBOL(mptscsih_is_phys_disk); -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * OS entry point to allow host driver to alloc memory - * for each scsi device. Called once per device the bus scan. - * Return non-zero if allocation fails. - */ -int -mptscsih_slave_alloc(struct scsi_device *sdev) +u8 +mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) { - struct Scsi_Host *host = sdev->host; - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; - VirtTarget *vtarget; - VirtDevice *vdev; - struct scsi_target *starget; - - vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); - if (!vdev) { - printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", - hd->ioc->name, sizeof(VirtDevice)); - return -ENOMEM; - } - - vdev->lun = sdev->lun; - sdev->hostdata = vdev; - - starget = scsi_target(sdev); - vtarget = starget->hostdata; + int i; + int rc = -ENXIO; - vdev->vtarget = vtarget; - - if (vtarget->num_luns == 0) { - hd->Targets[sdev->id] = vtarget; - vtarget->ioc_id = hd->ioc->id; - vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; - vtarget->target_id = sdev->id; - vtarget->bus_id = sdev->channel; - if (hd->ioc->bus_type == SPI && sdev->channel == 0 && - hd->ioc->raid_data.isRaid & (1 << sdev->id)) { - vtarget->raidVolume = 1; - ddvtprintk((KERN_INFO - "RAID Volume @ id %d\n", sdev->id)); + if (!ioc->raid_data.pIocPg3) + goto out; + for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { + if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) && + (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) { + rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum; + goto out; } } - vtarget->num_luns++; - return 0; -} -/* - * OS entry point to allow for host driver to free allocated memory - * Called if no device present or device being unloaded - */ -void -mptscsih_target_destroy(struct scsi_target *starget) -{ - if (starget->hostdata) - kfree(starget->hostdata); - starget->hostdata = NULL; + out: + return rc; } +EXPORT_SYMBOL(mptscsih_raid_id_to_num); /* * OS entry point to allow for host driver to free allocated memory @@ -2328,11 +2203,7 @@ mptscsih_slave_destroy(struct scsi_device *sdev) vdevice = sdev->hostdata; mptscsih_search_running_cmds(hd, vdevice); - vtarget->luns[0] &= ~(1 << vdevice->lun); vtarget->num_luns--; - if (vtarget->num_luns == 0) { - hd->Targets[sdev->id] = NULL; - } mptscsih_synchronize_cache(hd, vdevice); kfree(vdevice); sdev->hostdata = NULL; @@ -2394,15 +2265,14 @@ mptscsih_slave_configure(struct scsi_device *sdev) VirtDevice *vdevice; struct scsi_target *starget; MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata; - int indexed_lun, lun_index; starget = scsi_target(sdev); vtarget = starget->hostdata; vdevice = sdev->hostdata; dsprintk((MYIOC_s_INFO_FMT - "device @ %p, id=%d, LUN=%d, channel=%d\n", - hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel)); + "device @ %p, channel=%d, id=%d, lun=%d\n", + hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun)); if (hd->ioc->bus_type == SPI) dsprintk((MYIOC_s_INFO_FMT "sdtr %d wdtr %d ppr %d inq length=%d\n", @@ -2415,10 +2285,7 @@ mptscsih_slave_configure(struct scsi_device *sdev) goto slave_configure_exit; } - vdevice->configured_lun=1; - lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */ - indexed_lun = (vdevice->lun % 32); - vtarget->luns[lun_index] |= (1 << indexed_lun); + vdevice->configured_lun = 1; mptscsih_initTarget(hd, vtarget, sdev); mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); @@ -2699,8 +2566,8 @@ static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev) { - dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", - hd->ioc->name, vtarget->bus_id, vtarget->target_id, + dinitprintk((MYIOC_s_INFO_FMT "initTarget channel=%d id=%d lun=%d hd=%p\n", + hd->ioc->name, vtarget->channel, vtarget->id, sdev->lun, hd)); /* Is LUN supported? If so, upper 2 bits will be 0 @@ -2721,7 +2588,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, /* Treat all Processors as SAF-TE if * command line option is set */ vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; - mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); + mptscsih_writeIOCPage4(hd, vtarget->channel, vtarget->id); }else if ((sdev->type == TYPE_PROCESSOR) && !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { if (sdev->inquiry_len > 49 ) { @@ -2732,7 +2599,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, sdev->inquiry[48] == 'T' && sdev->inquiry[49] == 'E' ) { vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; - mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); + mptscsih_writeIOCPage4(hd, vtarget->channel, vtarget->id); } } } @@ -2750,7 +2617,7 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, struct scsi_device *sdev) { SpiCfgData *pspi_data = &hd->ioc->spi_data; - int id = (int) target->target_id; + int id = (int) target->id; int nvram; u8 width = MPT_NARROW; u8 factor = MPT_ASYNC; @@ -2887,7 +2754,8 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* mptscsih_writeIOCPage4 - write IOC Page 4 * @hd: Pointer to a SCSI Host Structure - * @target_id: write IOC Page4 for this ID & Bus + * @channel: write IOC Page4 for this Bus + * @id: write IOC Page4 for this ID * * Return: -EAGAIN if unable to obtain a Message Frame * or 0 if success. @@ -2895,7 +2763,7 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, * Remark: We do not wait for a return, write pages sequentially. */ static int -mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus) +mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int channel, int id) { MPT_ADAPTER *ioc = hd->ioc; Config_t *pReq; @@ -2936,13 +2804,13 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus) pReq->Reserved2[ii] = 0; } - IOCPage4Ptr = ioc->spi_data.pIocPg4; - dataDma = ioc->spi_data.IocPg4_dma; - ii = IOCPage4Ptr->ActiveSEP++; - IOCPage4Ptr->SEP[ii].SEPTargetID = target_id; - IOCPage4Ptr->SEP[ii].SEPBus = bus; - pReq->Header = IOCPage4Ptr->Header; - pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 )); + IOCPage4Ptr = ioc->spi_data.pIocPg4; + dataDma = ioc->spi_data.IocPg4_dma; + ii = IOCPage4Ptr->ActiveSEP++; + IOCPage4Ptr->SEP[ii].SEPTargetID = id; + IOCPage4Ptr->SEP[ii].SEPBus = channel; + pReq->Header = IOCPage4Ptr->Header; + pReq->PageAddress = cpu_to_le32(id | (channel << 8 )); /* Add a SGE to the config request. */ @@ -2952,8 +2820,8 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus) mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); dinitprintk((MYIOC_s_INFO_FMT - "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n", - ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus)); + "writeIOCPage4: MaxSEP=%d ActiveSEP=%d channel=%d id=%d \n", + ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, channel, id)); mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); @@ -3343,7 +3211,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; } else { pScsiReq->TargetID = io->id; - pScsiReq->Bus = io->bus; + pScsiReq->Bus = io->channel; pScsiReq->ChainOffset = 0; pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; } @@ -3356,9 +3224,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) pScsiReq->MsgFlags = mpt_msg_flags(); /* MsgContext set in mpt_get_msg_fram call */ - for (ii=0; ii < 8; ii++) - pScsiReq->LUN[ii] = 0; - pScsiReq->LUN[1] = io->lun; + int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN); if (io->flags & MPT_ICFLAG_TAGGED_CMD) pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ); @@ -3379,7 +3245,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) + (my_idx * MPT_SENSE_BUFFER_ALLOC)); ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n", - hd->ioc->name, cmd, io->bus, io->id, io->lun)); + hd->ioc->name, cmd, io->channel, io->id, io->lun)); if (dir == MPI_SCSIIO_CONTROL_READ) { mpt_add_sge((char *) &pScsiReq->SGL, @@ -3462,9 +3328,9 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) iocmd.data_dma = -1; iocmd.size = 0; iocmd.rsvd = iocmd.rsvd2 = 0; - iocmd.bus = vdevice->vtarget->bus_id; - iocmd.id = vdevice->vtarget->target_id; - iocmd.lun = (u8)vdevice->lun; + iocmd.channel = vdevice->vtarget->channel; + iocmd.id = vdevice->vtarget->id; + iocmd.lun = vdevice->lun; if ((vdevice->vtarget->type == TYPE_DISK) && (vdevice->configured_lun)) @@ -3480,9 +3346,6 @@ EXPORT_SYMBOL(mptscsih_resume); EXPORT_SYMBOL(mptscsih_proc_info); EXPORT_SYMBOL(mptscsih_info); EXPORT_SYMBOL(mptscsih_qcmd); -EXPORT_SYMBOL(mptscsih_target_alloc); -EXPORT_SYMBOL(mptscsih_slave_alloc); -EXPORT_SYMBOL(mptscsih_target_destroy); EXPORT_SYMBOL(mptscsih_slave_destroy); EXPORT_SYMBOL(mptscsih_slave_configure); EXPORT_SYMBOL(mptscsih_abort); diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 187c8af0890b..43b4f236adf9 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -53,6 +53,24 @@ * SCSI Public stuff... */ +#define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */ +#define MPT_SCANDV_DID_RESET (0x00000001) +#define MPT_SCANDV_SENSE (0x00000002) +#define MPT_SCANDV_SOME_ERROR (0x00000004) +#define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008) +#define MPT_SCANDV_ISSUE_SENSE (0x00000010) +#define MPT_SCANDV_FALLBACK (0x00000020) + +#define MPT_SCANDV_MAX_RETRIES (10) + +#define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */ +#define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */ +#define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */ +#define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */ +#define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */ +#define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */ +#define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */ + #define MPT_SCSI_CMD_PER_DEV_HIGH 64 #define MPT_SCSI_CMD_PER_DEV_LOW 32 @@ -69,9 +87,22 @@ #define MPTSCSIH_SAF_TE 0 #define MPTSCSIH_PT_CLEAR 0 - #endif +typedef struct _internal_cmd { + char *data; /* data pointer */ + dma_addr_t data_dma; /* data dma address */ + int size; /* transfer size */ + u8 cmd; /* SCSI Op Code */ + u8 channel; /* bus number */ + u8 id; /* SCSI ID (virtual) */ + int lun; + u8 flags; /* Bit Field - See above */ + u8 physDiskNum; /* Phys disk number, -1 else */ + u8 rsvd2; + u8 rsvd; +} INTERNAL_CMD; + extern void mptscsih_remove(struct pci_dev *); extern void mptscsih_shutdown(struct pci_dev *); #ifdef CONFIG_PM @@ -81,9 +112,6 @@ extern int mptscsih_resume(struct pci_dev *pdev); extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func); extern const char * mptscsih_info(struct Scsi_Host *SChost); extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)); -extern int mptscsih_target_alloc(struct scsi_target *starget); -extern int mptscsih_slave_alloc(struct scsi_device *device); -extern void mptscsih_target_destroy(struct scsi_target *starget); extern void mptscsih_slave_destroy(struct scsi_device *device); extern int mptscsih_slave_configure(struct scsi_device *device); extern int mptscsih_abort(struct scsi_cmnd * SCpnt); @@ -98,6 +126,6 @@ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pE extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); extern void mptscsih_timer_expired(unsigned long data); -extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); -extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid); -extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); +extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); +extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id); +extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id); diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 203c661d2c79..aec0c2fe221f 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -95,25 +95,76 @@ static int mptspiDoneCtx = -1; static int mptspiTaskCtx = -1; static int mptspiInternalCtx = -1; /* Used only for internal commands */ + +/** + * mptspi_is_raid - Determines whether target is belonging to volume + * @hd: Pointer to a SCSI HOST structure + * @id: target device id + * + * Return: + * non-zero = true + * zero = false + * + */ +static int +mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id) +{ + int i, rc = 0; + + if (!hd->ioc->raid_data.pIocPg2) + goto out; + + if (!hd->ioc->raid_data.pIocPg2->NumActiveVolumes) + goto out; + for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { + if (hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) { + rc = 1; + goto out; + } + } + + out: + return rc; +} + static int mptspi_target_alloc(struct scsi_target *starget) { struct Scsi_Host *shost = dev_to_shost(&starget->dev); struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; - int ret; + VirtTarget *vtarget; if (hd == NULL) return -ENODEV; - ret = mptscsih_target_alloc(starget); - if (ret) - return ret; + vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); + if (!vtarget) + return -ENOMEM; + + vtarget->ioc_id = hd->ioc->id; + vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; + vtarget->id = (u8)starget->id; + vtarget->channel = (u8)starget->channel; + vtarget->starget = starget; + starget->hostdata = vtarget; + + if (starget->channel == 1) { + if (mptscsih_is_phys_disk(hd->ioc, 0, starget->id) == 0) + return 0; + vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; + /* The real channel for this device is zero */ + vtarget->channel = 0; + /* The actual physdisknum (for RAID passthrough) */ + vtarget->id = mptscsih_raid_id_to_num(hd->ioc, 0, + starget->id); + } - /* if we're a device on virtual channel 1 and we're not part - * of an array, just return here (otherwise the setup below - * may actually affect a real physical device on channel 0 */ - if (starget->channel == 1 && - mptscsih_raid_id_to_num(hd, starget->id) < 0) - return 0; + if (starget->channel == 0 && + mptspi_is_raid(hd, starget->id)) { + vtarget->raidVolume = 1; + ddvprintk((KERN_INFO + "RAID Volume @ channel=%d id=%d\n", starget->channel, + starget->id)); + } if (hd->ioc->spi_data.nvram && hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) { @@ -132,6 +183,14 @@ static int mptspi_target_alloc(struct scsi_target *starget) return 0; } +void +mptspi_target_destroy(struct scsi_target *starget) +{ + if (starget->hostdata) + kfree(starget->hostdata); + starget->hostdata = NULL; +} + static int mptspi_read_spi_device_pg0(struct scsi_target *starget, struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0) { @@ -147,7 +206,7 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget, /* No SPI parameters for RAID devices */ if (starget->channel == 0 && - (hd->ioc->raid_data.isRaid & (1 << starget->id))) + mptspi_is_raid(hd, starget->id)) return -1; size = ioc->spi_data.sdp0length * 4; @@ -233,7 +292,7 @@ static void mptspi_read_parameters(struct scsi_target *starget) } static int -mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk) +mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) { MpiRaidActionRequest_t *pReq; MPT_FRAME_HDR *mf; @@ -253,8 +312,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk) pReq->Reserved1 = 0; pReq->ChainOffset = 0; pReq->Function = MPI_FUNCTION_RAID_ACTION; - pReq->VolumeID = disk; - pReq->VolumeBus = 0; + pReq->VolumeID = id; + pReq->VolumeBus = channel; pReq->PhysDiskNum = 0; pReq->MsgFlags = 0; pReq->Reserved2 = 0; @@ -263,8 +322,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk) mpt_add_sge((char *)&pReq->ActionDataSGE, MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); - ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n", - hd->ioc->name, action, io->id)); + ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action=%x channel=%d id=%d\n", + hd->ioc->name, pReq->Action, channel, id)); hd->pLocal = NULL; hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ @@ -292,12 +351,12 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, /* no DV on RAID devices */ if (sdev->channel == 0 && - (hd->ioc->raid_data.isRaid & (1 << sdev->id))) + mptspi_is_raid(hd, sdev->id)) return; /* If this is a piece of a RAID, then quiesce first */ if (sdev->channel == 1 && - mptscsih_quiesce_raid(hd, 1, vtarget->target_id) < 0) { + mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) { starget_printk(KERN_ERR, scsi_target(sdev), "Integrated RAID quiesce failed\n"); return; @@ -306,7 +365,7 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, spi_dv_device(sdev); if (sdev->channel == 1 && - mptscsih_quiesce_raid(hd, 0, vtarget->target_id) < 0) + mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0) starget_printk(KERN_ERR, scsi_target(sdev), "Integrated RAID resume failed\n"); @@ -317,33 +376,32 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, static int mptspi_slave_alloc(struct scsi_device *sdev) { - int ret; MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata; - /* gcc doesn't see that all uses of this variable occur within - * the if() statements, so stop it from whining */ - int physdisknum = 0; - - if (sdev->channel == 1) { - physdisknum = mptscsih_raid_id_to_num(hd, sdev->id); + VirtTarget *vtarget; + VirtDevice *vdev; + struct scsi_target *starget; - if (physdisknum < 0) - return physdisknum; + if (sdev->channel == 1 && + mptscsih_is_phys_disk(hd->ioc, 0, sdev->id) == 0) + return -ENXIO; + + vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); + if (!vdev) { + printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", + hd->ioc->name, sizeof(VirtDevice)); + return -ENOMEM; } - ret = mptscsih_slave_alloc(sdev); + vdev->lun = sdev->lun; + sdev->hostdata = vdev; - if (ret) - return ret; + starget = scsi_target(sdev); + vtarget = starget->hostdata; + vdev->vtarget = vtarget; + vtarget->num_luns++; - if (sdev->channel == 1) { - VirtDevice *vdev = sdev->hostdata; + if (sdev->channel == 1) sdev->no_uld_attach = 1; - vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; - /* The real channel for this device is zero */ - vdev->vtarget->bus_id = 0; - /* The actual physdisknum (for RAID passthrough) */ - vdev->vtarget->target_id = physdisknum; - } return 0; } @@ -358,13 +416,35 @@ static int mptspi_slave_configure(struct scsi_device *sdev) return ret; if ((sdev->channel == 1 || - !(hd->ioc->raid_data.isRaid & (1 << sdev->id))) && + !(mptspi_is_raid(hd, sdev->id))) && !spi_initial_dv(sdev->sdev_target)) mptspi_dv_device(hd, sdev); return 0; } +static int +mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) +{ + struct _MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; + VirtDevice *vdev = SCpnt->device->hostdata; + + if (!vdev || !vdev->vtarget) { + SCpnt->result = DID_NO_CONNECT << 16; + done(SCpnt); + return 0; + } + + if (SCpnt->device->channel == 1 && + mptscsih_is_phys_disk(hd->ioc, 0, SCpnt->device->id) == 0) { + SCpnt->result = DID_NO_CONNECT << 16; + done(SCpnt); + return 0; + } + + return mptscsih_qcmd(SCpnt,done); +} + static void mptspi_slave_destroy(struct scsi_device *sdev) { struct scsi_target *starget = scsi_target(sdev); @@ -392,11 +472,11 @@ static struct scsi_host_template mptspi_driver_template = { .proc_info = mptscsih_proc_info, .name = "MPT SPI Host", .info = mptscsih_info, - .queuecommand = mptscsih_qcmd, + .queuecommand = mptspi_qcmd, .target_alloc = mptspi_target_alloc, .slave_alloc = mptspi_slave_alloc, .slave_configure = mptspi_slave_configure, - .target_destroy = mptscsih_target_destroy, + .target_destroy = mptspi_target_destroy, .slave_destroy = mptspi_slave_destroy, .change_queue_depth = mptscsih_change_queue_depth, .eh_abort_handler = mptscsih_abort, @@ -427,7 +507,7 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget, /* don't allow updating nego parameters on RAID devices */ if (starget->channel == 0 && - (hd->ioc->raid_data.isRaid & (1 << starget->id))) + mptspi_is_raid(hd, starget->id)) return -1; size = ioc->spi_data.sdp1length * 4; @@ -672,9 +752,9 @@ static void mpt_work_wrapper(struct work_struct *work) if (sdev->channel != 1) continue; - /* The target_id is the raid PhysDiskNum, even if + /* The id is the raid PhysDiskNum, even if * starget->id is the actual target address */ - if(vtarget->target_id != disk) + if(vtarget->id != disk) continue; starget_printk(KERN_INFO, vtarget->starget, @@ -727,7 +807,7 @@ mptspi_deny_binding(struct scsi_target *starget) { struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata; - return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) && + return ((mptspi_is_raid(hd, starget->id)) && starget->channel == 0) ? 1 : 0; } @@ -945,7 +1025,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) * max_lun = 1 + actual last lun, * see hosts.h :o( */ - sh->max_id = MPT_MAX_SCSI_DEVICES; + sh->max_id = ioc->devices_per_bus; sh->max_lun = MPT_LAST_LUN + 1; /* @@ -1009,20 +1089,6 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", ioc->name, hd->ScsiLookup)); - /* Allocate memory for the device structures. - * A non-Null pointer at an offset - * indicates a device exists. - * max_id = 1 + maximum id (hosts.h) - */ - hd->Targets = kcalloc(sh->max_id * (sh->max_channel + 1), - sizeof(void *), GFP_ATOMIC); - if (!hd->Targets) { - error = -ENOMEM; - goto out_mptspi_probe; - } - - dprintk((KERN_INFO " vdev @ %p\n", hd->Targets)); - /* Clear the TM flags */ hd->tmPending = 0; -- cgit v1.2.3 From 5a9c47b1344b514758d5d7f193c672850390cc36 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Mon, 29 Jan 2007 09:43:17 -0700 Subject: [SCSI] fusion - move SPI API over to mptspi.c Move some functions that only apply to the mptspi module over from mptscsih.c Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptscsih.c | 284 -------------------------------------- drivers/message/fusion/mptspi.c | 268 ++++++++++++++++++++++++++++++++++- 2 files changed, 267 insertions(+), 285 deletions(-) diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index ce58431bee8e..d5877316cbea 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -99,9 +99,6 @@ static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); -static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev); -static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev); -static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int channel, int id); int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); @@ -2286,7 +2283,6 @@ mptscsih_slave_configure(struct scsi_device *sdev) } vdevice->configured_lun = 1; - mptscsih_initTarget(hd, vtarget, sdev); mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); dsprintk((MYIOC_s_INFO_FMT @@ -2548,286 +2544,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) return 1; /* currently means nothing really */ } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_initTarget - Target, LUN alloc/free functionality. - * @hd: Pointer to MPT_SCSI_HOST structure - * @vtarget: per target private data - * @sdev: SCSI device - * - * NOTE: It's only SAFE to call this routine if data points to - * sane & valid STANDARD INQUIRY data! - * - * Allocate and initialize memory for this target. - * Save inquiry data. - * - */ -static void -mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, - struct scsi_device *sdev) -{ - dinitprintk((MYIOC_s_INFO_FMT "initTarget channel=%d id=%d lun=%d hd=%p\n", - hd->ioc->name, vtarget->channel, vtarget->id, - sdev->lun, hd)); - - /* Is LUN supported? If so, upper 2 bits will be 0 - * in first byte of inquiry data. - */ - if (sdev->inq_periph_qual != 0) - return; - - if (vtarget == NULL) - return; - - vtarget->type = sdev->type; - - if (hd->ioc->bus_type != SPI) - return; - - if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { - /* Treat all Processors as SAF-TE if - * command line option is set */ - vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; - mptscsih_writeIOCPage4(hd, vtarget->channel, vtarget->id); - }else if ((sdev->type == TYPE_PROCESSOR) && - !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { - if (sdev->inquiry_len > 49 ) { - if (sdev->inquiry[44] == 'S' && - sdev->inquiry[45] == 'A' && - sdev->inquiry[46] == 'F' && - sdev->inquiry[47] == '-' && - sdev->inquiry[48] == 'T' && - sdev->inquiry[49] == 'E' ) { - vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; - mptscsih_writeIOCPage4(hd, vtarget->channel, vtarget->id); - } - } - } - mptscsih_setTargetNegoParms(hd, vtarget, sdev); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Update the target negotiation parameters based on the - * the Inquiry data, adapter capabilities, and NVRAM settings. - * - */ -static void -mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, - struct scsi_device *sdev) -{ - SpiCfgData *pspi_data = &hd->ioc->spi_data; - int id = (int) target->id; - int nvram; - u8 width = MPT_NARROW; - u8 factor = MPT_ASYNC; - u8 offset = 0; - u8 nfactor; - u8 noQas = 1; - - target->negoFlags = pspi_data->noQas; - - /* noQas == 0 => device supports QAS. */ - - if (sdev->scsi_level < SCSI_2) { - width = 0; - factor = MPT_ULTRA2; - offset = pspi_data->maxSyncOffset; - target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; - } else { - if (scsi_device_wide(sdev)) { - width = 1; - } - - if (scsi_device_sync(sdev)) { - factor = pspi_data->minSyncFactor; - if (!scsi_device_dt(sdev)) - factor = MPT_ULTRA2; - else { - if (!scsi_device_ius(sdev) && - !scsi_device_qas(sdev)) - factor = MPT_ULTRA160; - else { - factor = MPT_ULTRA320; - if (scsi_device_qas(sdev)) { - ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id)); - noQas = 0; - } - if (sdev->type == TYPE_TAPE && - scsi_device_ius(sdev)) - target->negoFlags |= MPT_TAPE_NEGO_IDP; - } - } - offset = pspi_data->maxSyncOffset; - - /* If RAID, never disable QAS - * else if non RAID, do not disable - * QAS if bit 1 is set - * bit 1 QAS support, non-raid only - * bit 0 IU support - */ - if (target->raidVolume == 1) { - noQas = 0; - } - } else { - factor = MPT_ASYNC; - offset = 0; - } - } - - if (!sdev->tagged_supported) { - target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; - } - - /* Update tflags based on NVRAM settings. (SCSI only) - */ - if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { - nvram = pspi_data->nvram[id]; - nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; - - if (width) - width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; - - if (offset > 0) { - /* Ensure factor is set to the - * maximum of: adapter, nvram, inquiry - */ - if (nfactor) { - if (nfactor < pspi_data->minSyncFactor ) - nfactor = pspi_data->minSyncFactor; - - factor = max(factor, nfactor); - if (factor == MPT_ASYNC) - offset = 0; - } else { - offset = 0; - factor = MPT_ASYNC; - } - } else { - factor = MPT_ASYNC; - } - } - - /* Make sure data is consistent - */ - if ((!width) && (factor < MPT_ULTRA2)) { - factor = MPT_ULTRA2; - } - - /* Save the data to the target structure. - */ - target->minSyncFactor = factor; - target->maxOffset = offset; - target->maxWidth = width; - - target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO; - - /* Disable unused features. - */ - if (!width) - target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE; - - if (!offset) - target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC; - - if ( factor > MPT_ULTRA320 ) - noQas = 0; - - if (noQas && (pspi_data->noQas == 0)) { - pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; - target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; - - /* Disable QAS in a mixed configuration case - */ - - ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * SCSI Config Page functionality ... - */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptscsih_writeIOCPage4 - write IOC Page 4 - * @hd: Pointer to a SCSI Host Structure - * @channel: write IOC Page4 for this Bus - * @id: write IOC Page4 for this ID - * - * Return: -EAGAIN if unable to obtain a Message Frame - * or 0 if success. - * - * Remark: We do not wait for a return, write pages sequentially. - */ -static int -mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int channel, int id) -{ - MPT_ADAPTER *ioc = hd->ioc; - Config_t *pReq; - IOCPage4_t *IOCPage4Ptr; - MPT_FRAME_HDR *mf; - dma_addr_t dataDma; - u16 req_idx; - u32 frameOffset; - u32 flagsLength; - int ii; - - /* Get a MF for this command. - */ - if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { - dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n", - ioc->name)); - return -EAGAIN; - } - - /* Set the request and the data pointers. - * Place data at end of MF. - */ - pReq = (Config_t *)mf; - - req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); - frameOffset = ioc->req_sz - sizeof(IOCPage4_t); - - /* Complete the request frame (same for all requests). - */ - pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - pReq->Reserved = 0; - pReq->ChainOffset = 0; - pReq->Function = MPI_FUNCTION_CONFIG; - pReq->ExtPageLength = 0; - pReq->ExtPageType = 0; - pReq->MsgFlags = 0; - for (ii=0; ii < 8; ii++) { - pReq->Reserved2[ii] = 0; - } - - IOCPage4Ptr = ioc->spi_data.pIocPg4; - dataDma = ioc->spi_data.IocPg4_dma; - ii = IOCPage4Ptr->ActiveSEP++; - IOCPage4Ptr->SEP[ii].SEPTargetID = id; - IOCPage4Ptr->SEP[ii].SEPBus = channel; - pReq->Header = IOCPage4Ptr->Header; - pReq->PageAddress = cpu_to_le32(id | (channel << 8 )); - - /* Add a SGE to the config request. - */ - flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | - (IOCPage4Ptr->Header.PageLength + ii) * 4; - - mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); - - dinitprintk((MYIOC_s_INFO_FMT - "writeIOCPage4: MaxSEP=%d ActiveSEP=%d channel=%d id=%d \n", - ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, channel, id)); - - mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); - - return 0; -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Bus Scan and Domain Validation functionality ... diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index aec0c2fe221f..4896d7cc681a 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -95,6 +95,269 @@ static int mptspiDoneCtx = -1; static int mptspiTaskCtx = -1; static int mptspiInternalCtx = -1; /* Used only for internal commands */ +/** + * mptspi_setTargetNegoParms - Update the target negotiation + * parameters based on the the Inquiry data, adapter capabilities, + * and NVRAM settings + * + * @hd: Pointer to a SCSI Host Structure + * @vtarget: per target private data + * @sdev: SCSI device + * + **/ +static void +mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, + struct scsi_device *sdev) +{ + SpiCfgData *pspi_data = &hd->ioc->spi_data; + int id = (int) target->id; + int nvram; + u8 width = MPT_NARROW; + u8 factor = MPT_ASYNC; + u8 offset = 0; + u8 nfactor; + u8 noQas = 1; + + target->negoFlags = pspi_data->noQas; + + if (sdev->scsi_level < SCSI_2) { + width = 0; + factor = MPT_ULTRA2; + offset = pspi_data->maxSyncOffset; + target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; + } else { + if (scsi_device_wide(sdev)) + width = 1; + + if (scsi_device_sync(sdev)) { + factor = pspi_data->minSyncFactor; + if (!scsi_device_dt(sdev)) + factor = MPT_ULTRA2; + else { + if (!scsi_device_ius(sdev) && + !scsi_device_qas(sdev)) + factor = MPT_ULTRA160; + else { + factor = MPT_ULTRA320; + if (scsi_device_qas(sdev)) { + ddvprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id)); + noQas = 0; + } + if (sdev->type == TYPE_TAPE && + scsi_device_ius(sdev)) + target->negoFlags |= MPT_TAPE_NEGO_IDP; + } + } + offset = pspi_data->maxSyncOffset; + + /* If RAID, never disable QAS + * else if non RAID, do not disable + * QAS if bit 1 is set + * bit 1 QAS support, non-raid only + * bit 0 IU support + */ + if (target->raidVolume == 1) + noQas = 0; + } else { + factor = MPT_ASYNC; + offset = 0; + } + } + + if (!sdev->tagged_supported) + target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; + + /* Update tflags based on NVRAM settings. (SCSI only) + */ + if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { + nvram = pspi_data->nvram[id]; + nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; + + if (width) + width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; + + if (offset > 0) { + /* Ensure factor is set to the + * maximum of: adapter, nvram, inquiry + */ + if (nfactor) { + if (nfactor < pspi_data->minSyncFactor ) + nfactor = pspi_data->minSyncFactor; + + factor = max(factor, nfactor); + if (factor == MPT_ASYNC) + offset = 0; + } else { + offset = 0; + factor = MPT_ASYNC; + } + } else { + factor = MPT_ASYNC; + } + } + + /* Make sure data is consistent + */ + if ((!width) && (factor < MPT_ULTRA2)) + factor = MPT_ULTRA2; + + /* Save the data to the target structure. + */ + target->minSyncFactor = factor; + target->maxOffset = offset; + target->maxWidth = width; + + target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO; + + /* Disable unused features. + */ + if (!width) + target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE; + + if (!offset) + target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC; + + if ( factor > MPT_ULTRA320 ) + noQas = 0; + + if (noQas && (pspi_data->noQas == 0)) { + pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; + target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; + + /* Disable QAS in a mixed configuration case + */ + + ddvprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); + } +} + +/** + * mptspi_writeIOCPage4 - write IOC Page 4 + * @hd: Pointer to a SCSI Host Structure + * @channel: + * @id: write IOC Page4 for this ID & Bus + * + * Return: -EAGAIN if unable to obtain a Message Frame + * or 0 if success. + * + * Remark: We do not wait for a return, write pages sequentially. + **/ +static int +mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id) +{ + MPT_ADAPTER *ioc = hd->ioc; + Config_t *pReq; + IOCPage4_t *IOCPage4Ptr; + MPT_FRAME_HDR *mf; + dma_addr_t dataDma; + u16 req_idx; + u32 frameOffset; + u32 flagsLength; + int ii; + + /* Get a MF for this command. + */ + if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { + dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n", + ioc->name)); + return -EAGAIN; + } + + /* Set the request and the data pointers. + * Place data at end of MF. + */ + pReq = (Config_t *)mf; + + req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); + frameOffset = ioc->req_sz - sizeof(IOCPage4_t); + + /* Complete the request frame (same for all requests). + */ + pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; + pReq->Reserved = 0; + pReq->ChainOffset = 0; + pReq->Function = MPI_FUNCTION_CONFIG; + pReq->ExtPageLength = 0; + pReq->ExtPageType = 0; + pReq->MsgFlags = 0; + for (ii=0; ii < 8; ii++) { + pReq->Reserved2[ii] = 0; + } + + IOCPage4Ptr = ioc->spi_data.pIocPg4; + dataDma = ioc->spi_data.IocPg4_dma; + ii = IOCPage4Ptr->ActiveSEP++; + IOCPage4Ptr->SEP[ii].SEPTargetID = id; + IOCPage4Ptr->SEP[ii].SEPBus = channel; + pReq->Header = IOCPage4Ptr->Header; + pReq->PageAddress = cpu_to_le32(id | (channel << 8 )); + + /* Add a SGE to the config request. + */ + flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | + (IOCPage4Ptr->Header.PageLength + ii) * 4; + + mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); + + ddvprintk((MYIOC_s_INFO_FMT + "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n", + ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel)); + + mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); + + return 0; +} + +/** + * mptspi_initTarget - Target, LUN alloc/free functionality. + * @hd: Pointer to MPT_SCSI_HOST structure + * @vtarget: per target private data + * @sdev: SCSI device + * + * NOTE: It's only SAFE to call this routine if data points to + * sane & valid STANDARD INQUIRY data! + * + * Allocate and initialize memory for this target. + * Save inquiry data. + * + **/ +static void +mptspi_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, + struct scsi_device *sdev) +{ + + /* Is LUN supported? If so, upper 2 bits will be 0 + * in first byte of inquiry data. + */ + if (sdev->inq_periph_qual != 0) + return; + + if (vtarget == NULL) + return; + + vtarget->type = sdev->type; + + if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { + /* Treat all Processors as SAF-TE if + * command line option is set */ + vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; + mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id); + }else if ((sdev->type == TYPE_PROCESSOR) && + !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { + if (sdev->inquiry_len > 49 ) { + if (sdev->inquiry[44] == 'S' && + sdev->inquiry[45] == 'A' && + sdev->inquiry[46] == 'F' && + sdev->inquiry[47] == '-' && + sdev->inquiry[48] == 'T' && + sdev->inquiry[49] == 'E' ) { + vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; + mptspi_writeIOCPage4(hd, vtarget->channel, vtarget->id); + } + } + } + mptspi_setTargetNegoParms(hd, vtarget, sdev); +} /** * mptspi_is_raid - Determines whether target is belonging to volume @@ -408,13 +671,16 @@ static int mptspi_slave_alloc(struct scsi_device *sdev) static int mptspi_slave_configure(struct scsi_device *sdev) { - int ret = mptscsih_slave_configure(sdev); struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)sdev->host->hostdata; + VirtTarget *vtarget = scsi_target(sdev)->hostdata; + int ret = mptscsih_slave_configure(sdev); if (ret) return ret; + mptspi_initTarget(hd, vtarget, sdev); + if ((sdev->channel == 1 || !(mptspi_is_raid(hd, sdev->id))) && !spi_initial_dv(sdev->sdev_target)) -- cgit v1.2.3 From 873c82ed165a345fa381415b9734d26e9af4ec96 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Mon, 29 Jan 2007 09:44:06 -0700 Subject: [SCSI] fusion - added mptspi debug helpful debug for mptspi module Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/Makefile | 3 +- drivers/message/fusion/mptbase.h | 6 ---- drivers/message/fusion/mptspi.c | 66 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 3217076b40f4..6171783f0007 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile @@ -8,6 +8,7 @@ #EXTRA_CFLAGS += -DMPT_DEBUG_INIT #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL +#EXTRA_CFLAGS += -DMPT_DEBUG_DV #EXTRA_CFLAGS += -DMPT_DEBUG_TM # @@ -21,8 +22,6 @@ #CFLAGS_mptbase.o += -DMPT_DEBUG_RESET # # For mptscsih: -#CFLAGS_mptscsih.o += -DMPT_DEBUG_DV -#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEGO #CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI #CFLAGS_mptscsih.o += -DMPT_DEBUG_REPLY # diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index f82a817de81f..a0ce2f4e33f9 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -791,12 +791,6 @@ typedef struct _mpt_sge { #define ddvprintk(x) #endif -#ifdef MPT_DEBUG_NEGO -#define dnegoprintk(x) printk x -#else -#define dnegoprintk(x) -#endif - #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) #define ddvtprintk(x) printk x #else diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 4896d7cc681a..06a7b86f5f23 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -65,6 +65,7 @@ #include #include #include +#include #include "mptbase.h" #include "mptscsih.h" @@ -454,6 +455,56 @@ mptspi_target_destroy(struct scsi_target *starget) starget->hostdata = NULL; } +/** + * mptspi_print_write_nego - negotiation parameters debug info that is being sent + * @hd: Pointer to a SCSI HOST structure + * @starget: SCSI target + * @ii: negotiation parameters + * + */ +static void +mptspi_print_write_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii) +{ + ddvprintk((MYIOC_s_INFO_FMT "id=%d Requested = 0x%08x" + " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n", + hd->ioc->name, starget->id, ii, + ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "", + ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF), + ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "", + ii & MPI_SCSIDEVPAGE0_NP_DT ? "DT ": "", + ii & MPI_SCSIDEVPAGE0_NP_QAS ? "QAS ": "", + ii & MPI_SCSIDEVPAGE0_NP_HOLD_MCS ? "HOLDMCS ": "", + ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "", + ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "", + ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "", + ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": "")); +} + +/** + * mptspi_print_read_nego - negotiation parameters debug info that is being read + * @hd: Pointer to a SCSI HOST structure + * @starget: SCSI target + * @ii: negotiation parameters + * + */ +static void +mptspi_print_read_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii) +{ + ddvprintk((MYIOC_s_INFO_FMT "id=%d Read = 0x%08x" + " ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n", + hd->ioc->name, starget->id, ii, + ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "", + ((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF), + ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "", + ii & MPI_SCSIDEVPAGE0_NP_DT ? "DT ": "", + ii & MPI_SCSIDEVPAGE0_NP_QAS ? "QAS ": "", + ii & MPI_SCSIDEVPAGE0_NP_HOLD_MCS ? "HOLDMCS ": "", + ii & MPI_SCSIDEVPAGE0_NP_WR_FLOW ? "WRFLOW ": "", + ii & MPI_SCSIDEVPAGE0_NP_RD_STRM ? "RDSTRM ": "", + ii & MPI_SCSIDEVPAGE0_NP_RTI ? "RTI ": "", + ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": "")); +} + static int mptspi_read_spi_device_pg0(struct scsi_target *starget, struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0) { @@ -507,6 +558,8 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget, err = 0; memcpy(pass_pg0, pg0, size); + mptspi_print_read_nego(hd, starget, le32_to_cpu(pg0->NegotiatedParameters)); + out_free: dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma); return err; @@ -681,6 +734,12 @@ static int mptspi_slave_configure(struct scsi_device *sdev) mptspi_initTarget(hd, vtarget, sdev); + ddvprintk((MYIOC_s_INFO_FMT "id=%d min_period=0x%02x" + " max_offset=0x%02x max_width=%d\n", hd->ioc->name, + sdev->id, spi_min_period(scsi_target(sdev)), + spi_max_offset(scsi_target(sdev)), + spi_max_width(scsi_target(sdev)))); + if ((sdev->channel == 1 || !(mptspi_is_raid(hd, sdev->id))) && !spi_initial_dv(sdev->sdev_target)) @@ -708,6 +767,11 @@ mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return 0; } +#ifdef MPT_DEBUG_DV + if (spi_dv_pending(scsi_target(SCpnt->device))) + scsi_print_command(SCpnt); +#endif + return mptscsih_qcmd(SCpnt,done); } @@ -806,6 +870,8 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget, pg1->Header.PageNumber = hdr.PageNumber; pg1->Header.PageType = hdr.PageType; + mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters)); + if (mpt_config(ioc, &cfg)) { starget_printk(KERN_ERR, starget, "mpt_config failed\n"); goto out_free; -- cgit v1.2.3 From c6c727a1a0ff90c80425b7226557b2354e00cf7b Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Mon, 29 Jan 2007 09:44:54 -0700 Subject: [SCSI] fusion - iocstatus, loginfo, and event debug updates various string updates for iocstatus, logingo, and fw asyn events. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/Makefile | 2 +- drivers/message/fusion/mptbase.c | 552 ++++++++++++++++++++++++++++++++------ drivers/message/fusion/mptbase.h | 3 + drivers/message/fusion/mptscsih.c | 129 ++++++++- 4 files changed, 587 insertions(+), 99 deletions(-) diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 6171783f0007..6003b46c8438 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile @@ -10,6 +10,7 @@ #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL #EXTRA_CFLAGS += -DMPT_DEBUG_DV #EXTRA_CFLAGS += -DMPT_DEBUG_TM +#EXTRA_CFLAGS += -DMPT_DEBUG_REPLY # # driver/module specifics... @@ -23,7 +24,6 @@ # # For mptscsih: #CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI -#CFLAGS_mptscsih.o += -DMPT_DEBUG_REPLY # # For mptctl: #CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index a07f0f81f96b..5d4faa4dd4ea 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -177,7 +177,9 @@ static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc); //int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers); -static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); +#ifdef MPT_DEBUG_REPLY +static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); +#endif static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); @@ -323,13 +325,11 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) else if (ioc->bus_type == SAS) mpt_sas_log_info(ioc, log_info); } - if (ioc_stat & MPI_IOCSTATUS_MASK) { - if (ioc->bus_type == SPI && - cb_idx != mpt_stm_index && - cb_idx != mpt_lan_index) - mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf); - } +#ifdef MPT_DEBUG_REPLY + if (ioc_stat & MPI_IOCSTATUS_MASK) + mpt_iocstatus_info(ioc, (u32)ioc_stat, mf); +#endif /* Check for (valid) IO callback! */ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || @@ -5694,8 +5694,6 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) return rc; } -# define EVENT_DESCR_STR_SZ 100 - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static void EventDescriptionStr(u8 event, u32 evData0, char *evStr) @@ -5723,9 +5721,6 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) break; case MPI_EVENT_RESCAN: ds = "Bus Rescan Event"; - /* Ok, do we need to do anything here? As far as - I can tell, this is when a new device gets added - to the loop. */ break; case MPI_EVENT_LINK_STATUS_CHANGE: if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE) @@ -5802,48 +5797,63 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: { u8 id = (u8)(evData0); + u8 channel = (u8)(evData0 >> 8); u8 ReasonCode = (u8)(evData0 >> 16); switch (ReasonCode) { case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Added: id=%d", id); + "SAS Device Status Change: Added: " + "id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Deleted: id=%d", id); + "SAS Device Status Change: Deleted: " + "id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: SMART Data: id=%d", - id); + "SAS Device Status Change: SMART Data: " + "id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: No Persistancy: id=%d", id); + "SAS Device Status Change: No Persistancy: " + "id=%d channel=%d", id, channel); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Device Status Change: Unsupported Device " + "Discovered : id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Internal Device Reset : id=%d", id); + "SAS Device Status Change: Internal Device " + "Reset : id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Internal Task Abort : id=%d", id); + "SAS Device Status Change: Internal Task " + "Abort : id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Internal Abort Task Set : id=%d", id); + "SAS Device Status Change: Internal Abort " + "Task Set : id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Internal Clear Task Set : id=%d", id); + "SAS Device Status Change: Internal Clear " + "Task Set : id=%d channel=%d", id, channel); break; case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Internal Query Task : id=%d", id); + "SAS Device Status Change: Internal Query " + "Task : id=%d channel=%d", id, channel); break; default: snprintf(evStr, EVENT_DESCR_STR_SZ, - "SAS Device Status Change: Unknown: id=%d", id); + "SAS Device Status Change: Unknown: " + "id=%d channel=%d", id, channel); break; } break; @@ -5852,8 +5862,16 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) ds = "Bus Timer Expired"; break; case MPI_EVENT_QUEUE_FULL: - ds = "Queue Full"; + { + u16 curr_depth = (u16)(evData0 >> 16); + u8 channel = (u8)(evData0 >> 8); + u8 id = (u8)(evData0); + + snprintf(evStr, EVENT_DESCR_STR_SZ, + "Queue Full: channel=%d id=%d depth=%d", + channel, id, curr_depth); break; + } case MPI_EVENT_SAS_SES: ds = "SAS SES Event"; break; @@ -5957,6 +5975,76 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) ds = "SAS Log Entry Added"; break; + case MPI_EVENT_SAS_BROADCAST_PRIMITIVE: + { + u8 phy_num = (u8)(evData0); + u8 port_num = (u8)(evData0 >> 8); + u8 port_width = (u8)(evData0 >> 16); + u8 primative = (u8)(evData0 >> 24); + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Broadcase Primative: phy=%d port=%d " + "width=%d primative=0x%02x", + phy_num, port_num, port_width, primative); + break; + } + + case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: + { + u8 reason = (u8)(evData0); + u8 port_num = (u8)(evData0 >> 8); + u16 handle = le16_to_cpu(evData0 >> 16); + + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Initiator Device Status Change: reason=0x%02x " + "port=%d handle=0x%04x", + reason, port_num, handle); + break; + } + + case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW: + { + u8 max_init = (u8)(evData0); + u8 current_init = (u8)(evData0 >> 8); + + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS Initiator Device Table Overflow: max initiators=%02d " + "current initators=%02d", + max_init, current_init); + break; + } + case MPI_EVENT_SAS_SMP_ERROR: + { + u8 status = (u8)(evData0); + u8 port_num = (u8)(evData0 >> 8); + u8 result = (u8)(evData0 >> 16); + + if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID) + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS SMP Error: port=%d result=0x%02x", + port_num, result); + else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR) + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS SMP Error: port=%d : CRC Error", + port_num); + else if (status == MPI_EVENT_SAS_SMP_TIMEOUT) + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS SMP Error: port=%d : Timeout", + port_num); + else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION) + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS SMP Error: port=%d : No Destination", + port_num); + else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION) + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS SMP Error: port=%d : Bad Destination", + port_num); + else + snprintf(evStr, EVENT_DESCR_STR_SZ, + "SAS SMP Error: port=%d : status=0x%02x", + port_num, status); + break; + } + /* * MPT base "custom" events may be added here... */ @@ -6220,10 +6308,11 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) "Abort", /* 12h */ "IO Not Yet Executed", /* 13h */ "IO Executed", /* 14h */ - "Persistent Reservation Out Not Affiliation Owner", /* 15h */ + "Persistent Reservation Out Not Affiliation " + "Owner", /* 15h */ "Open Transmit DMA Abort", /* 16h */ "IO Device Missing Delay Retry", /* 17h */ - NULL, /* 18h */ + "IO Cancelled Due to Recieve Error", /* 18h */ NULL, /* 19h */ NULL, /* 1Ah */ NULL, /* 1Bh */ @@ -6233,6 +6322,96 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) NULL, /* 1Fh */ "Enclosure Management" /* 20h */ }; + static char *ir_code_str[] = { + "Raid Action Error", /* 00h */ + NULL, /* 00h */ + NULL, /* 01h */ + NULL, /* 02h */ + NULL, /* 03h */ + NULL, /* 04h */ + NULL, /* 05h */ + NULL, /* 06h */ + NULL /* 07h */ + }; + static char *raid_sub_code_str[] = { + NULL, /* 00h */ + "Volume Creation Failed: Data Passed too " + "Large", /* 01h */ + "Volume Creation Failed: Duplicate Volumes " + "Attempted", /* 02h */ + "Volume Creation Failed: Max Number " + "Supported Volumes Exceeded", /* 03h */ + "Volume Creation Failed: DMA Error", /* 04h */ + "Volume Creation Failed: Invalid Volume Type", /* 05h */ + "Volume Creation Failed: Error Reading " + "MFG Page 4", /* 06h */ + "Volume Creation Failed: Creating Internal " + "Structures", /* 07h */ + NULL, /* 08h */ + NULL, /* 09h */ + NULL, /* 0Ah */ + NULL, /* 0Bh */ + NULL, /* 0Ch */ + NULL, /* 0Dh */ + NULL, /* 0Eh */ + NULL, /* 0Fh */ + "Activation failed: Already Active Volume", /* 10h */ + "Activation failed: Unsupported Volume Type", /* 11h */ + "Activation failed: Too Many Active Volumes", /* 12h */ + "Activation failed: Volume ID in Use", /* 13h */ + "Activation failed: Reported Failure", /* 14h */ + "Activation failed: Importing a Volume", /* 15h */ + NULL, /* 16h */ + NULL, /* 17h */ + NULL, /* 18h */ + NULL, /* 19h */ + NULL, /* 1Ah */ + NULL, /* 1Bh */ + NULL, /* 1Ch */ + NULL, /* 1Dh */ + NULL, /* 1Eh */ + NULL, /* 1Fh */ + "Phys Disk failed: Too Many Phys Disks", /* 20h */ + "Phys Disk failed: Data Passed too Large", /* 21h */ + "Phys Disk failed: DMA Error", /* 22h */ + "Phys Disk failed: Invalid ", /* 23h */ + "Phys Disk failed: Creating Phys Disk Config " + "Page", /* 24h */ + NULL, /* 25h */ + NULL, /* 26h */ + NULL, /* 27h */ + NULL, /* 28h */ + NULL, /* 29h */ + NULL, /* 2Ah */ + NULL, /* 2Bh */ + NULL, /* 2Ch */ + NULL, /* 2Dh */ + NULL, /* 2Eh */ + NULL, /* 2Fh */ + "Compatibility Error: IR Disabled", /* 30h */ + "Compatibility Error: Inquiry Comand Failed", /* 31h */ + "Compatibility Error: Device not Direct Access " + "Device ", /* 32h */ + "Compatibility Error: Removable Device Found", /* 33h */ + "Compatibility Error: Device SCSI Version not " + "2 or Higher", /* 34h */ + "Compatibility Error: SATA Device, 48 BIT LBA " + "not Supported", /* 35h */ + "Compatibility Error: Device doesn't have " + "512 Byte Block Sizes", /* 36h */ + "Compatibility Error: Volume Type Check Failed", /* 37h */ + "Compatibility Error: Volume Type is " + "Unsupported by FW", /* 38h */ + "Compatibility Error: Disk Drive too Small for " + "use in Volume", /* 39h */ + "Compatibility Error: Phys Disk for Create " + "Volume not Found", /* 3Ah */ + "Compatibility Error: Too Many or too Few " + "Disks for Volume Type", /* 3Bh */ + "Compatibility Error: Disk stripe Sizes " + "Must be 64KB", /* 3Ch */ + "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */ + }; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** @@ -6241,7 +6420,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) * @log_info: U32 LogInfo reply word from the IOC * * Refer to lsi/mpi_log_sas.h. - */ + **/ static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info) { @@ -6255,56 +6434,165 @@ union loginfo_type { }dw; }; union loginfo_type sas_loginfo; + char *originator_desc = NULL; char *code_desc = NULL; + char *sub_code_desc = NULL; sas_loginfo.loginfo = log_info; if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) && (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*))) return; - if ((sas_loginfo.dw.originator == 0 /*IOP*/) && - (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) { - code_desc = iop_code_str[sas_loginfo.dw.code]; - }else if ((sas_loginfo.dw.originator == 1 /*PL*/) && - (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) { - code_desc = pl_code_str[sas_loginfo.dw.code]; + + originator_desc = originator_str[sas_loginfo.dw.originator]; + + switch (sas_loginfo.dw.originator) { + + case 0: /* IOP */ + if (sas_loginfo.dw.code < + sizeof(iop_code_str)/sizeof(char*)) + code_desc = iop_code_str[sas_loginfo.dw.code]; + break; + case 1: /* PL */ + if (sas_loginfo.dw.code < + sizeof(pl_code_str)/sizeof(char*)) + code_desc = pl_code_str[sas_loginfo.dw.code]; + break; + case 2: /* IR */ + if (sas_loginfo.dw.code >= + sizeof(ir_code_str)/sizeof(char*)) + break; + code_desc = ir_code_str[sas_loginfo.dw.code]; + if (sas_loginfo.dw.subcode >= + sizeof(raid_sub_code_str)/sizeof(char*)) + break; + if (sas_loginfo.dw.code == 0) + sub_code_desc = + raid_sub_code_str[sas_loginfo.dw.subcode]; + break; + default: + return; } - if (code_desc != NULL) + if (sub_code_desc != NULL) + printk(MYIOC_s_INFO_FMT + "LogInfo(0x%08x): Originator={%s}, Code={%s}," + " SubCode={%s}\n", + ioc->name, log_info, originator_desc, code_desc, + sub_code_desc); + else if (code_desc != NULL) printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): Originator={%s}, Code={%s}," " SubCode(0x%04x)\n", - ioc->name, - log_info, - originator_str[sas_loginfo.dw.originator], - code_desc, + ioc->name, log_info, originator_desc, code_desc, sas_loginfo.dw.subcode); else printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x)," " SubCode(0x%04x)\n", - ioc->name, - log_info, - originator_str[sas_loginfo.dw.originator], - sas_loginfo.dw.code, - sas_loginfo.dw.subcode); + ioc->name, log_info, originator_desc, + sas_loginfo.dw.code, sas_loginfo.dw.subcode); } +#ifdef MPT_DEBUG_REPLY /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC. + * mpt_iocstatus_info_config - IOCSTATUS information for config pages + * @ioc: Pointer to MPT_ADAPTER structure + * ioc_status: U32 IOCStatus word from IOC + * @mf: Pointer to MPT request frame + * + * Refer to lsi/mpi.h. + **/ +static void +mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) +{ + Config_t *pReq = (Config_t *)mf; + char extend_desc[EVENT_DESCR_STR_SZ]; + char *desc = NULL; + u32 form; + u8 page_type; + + if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED) + page_type = pReq->ExtPageType; + else + page_type = pReq->Header.PageType; + + /* + * ignore invalid page messages for GET_NEXT_HANDLE + */ + form = le32_to_cpu(pReq->PageAddress); + if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) { + if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE || + page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER || + page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) { + if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) == + MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE) + return; + } + if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE) + if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) == + MPI_FC_DEVICE_PGAD_FORM_NEXT_DID) + return; + } + + snprintf(extend_desc, EVENT_DESCR_STR_SZ, + "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh", + page_type, pReq->Header.PageNumber, pReq->Action, form); + + switch (ioc_status) { + + case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */ + desc = "Config Page Invalid Action"; + break; + + case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */ + desc = "Config Page Invalid Type"; + break; + + case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */ + desc = "Config Page Invalid Page"; + break; + + case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */ + desc = "Config Page Invalid Data"; + break; + + case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */ + desc = "Config Page No Defaults"; + break; + + case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */ + desc = "Config Page Can't Commit"; + break; + } + + if (!desc) + return; + + printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n", + ioc->name, ioc_status, desc, extend_desc); +} + +/** + * mpt_iocstatus_info - IOCSTATUS information returned from IOC. * @ioc: Pointer to MPT_ADAPTER structure * @ioc_status: U32 IOCStatus word from IOC * @mf: Pointer to MPT request frame * * Refer to lsi/mpi.h. - */ + **/ static void -mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) +mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) { u32 status = ioc_status & MPI_IOCSTATUS_MASK; char *desc = NULL; switch (status) { + +/****************************************************************************/ +/* Common IOCStatus values for all replies */ +/****************************************************************************/ + case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */ desc = "Invalid Function"; break; @@ -6337,84 +6625,180 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) desc = "Invalid State"; break; +/****************************************************************************/ +/* Config IOCStatus values */ +/****************************************************************************/ + case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */ case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */ case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */ case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */ case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */ case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */ - /* No message for Config IOCStatus values */ + mpt_iocstatus_info_config(ioc, status, mf); break; +/****************************************************************************/ +/* SCSIIO Reply (SPI, FCP, SAS) initiator values */ +/* */ +/* Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */ +/* */ +/****************************************************************************/ + case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ - /* No message for recovered error - desc = "SCSI Recovered Error"; - */ + case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ + case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ + case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */ + case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ + case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ + case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ + case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ + case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ + case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ + case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ + case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ + case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ break; - case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ - desc = "SCSI Invalid Bus"; +/****************************************************************************/ +/* SCSI Target values */ +/****************************************************************************/ + + case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */ + desc = "Target: Priority IO"; break; - case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */ - desc = "SCSI Invalid TargetID"; + case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */ + desc = "Target: Invalid Port"; break; - case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ - { - SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf; - U8 cdb = pScsiReq->CDB[0]; - if (cdb != 0x12) { /* Inquiry is issued for device scanning */ - desc = "SCSI Device Not There"; - } + case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */ + desc = "Target Invalid IO Index:"; break; - } - case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ - desc = "SCSI Data Overrun"; + case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */ + desc = "Target: Aborted"; break; - case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ - /* This error is checked in scsi_io_done(). Skip. - desc = "SCSI Data Underrun"; - */ + case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */ + desc = "Target: No Conn Retryable"; break; - case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ - desc = "SCSI I/O Data Error"; + case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */ + desc = "Target: No Connection"; break; - case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ - desc = "SCSI Protocol Error"; + case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */ + desc = "Target: Transfer Count Mismatch"; break; - case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ - desc = "SCSI Task Terminated"; + case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */ + desc = "Target: STS Data not Sent"; break; - case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ - desc = "SCSI Residual Mismatch"; + case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */ + desc = "Target: Data Offset Error"; break; - case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ - desc = "SCSI Task Management Failed"; + case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */ + desc = "Target: Too Much Write Data"; break; - case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ - desc = "SCSI IOC Terminated"; + case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */ + desc = "Target: IU Too Short"; break; - case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ - desc = "SCSI Ext Terminated"; + case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */ + desc = "Target: ACK NAK Timeout"; + break; + + case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */ + desc = "Target: Nak Received"; + break; + +/****************************************************************************/ +/* Fibre Channel Direct Access values */ +/****************************************************************************/ + + case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */ + desc = "FC: Aborted"; + break; + + case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */ + desc = "FC: RX ID Invalid"; + break; + + case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */ + desc = "FC: DID Invalid"; + break; + + case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */ + desc = "FC: Node Logged Out"; + break; + + case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */ + desc = "FC: Exchange Canceled"; + break; + +/****************************************************************************/ +/* LAN values */ +/****************************************************************************/ + + case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */ + desc = "LAN: Device not Found"; + break; + + case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */ + desc = "LAN: Device Failure"; + break; + + case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */ + desc = "LAN: Transmit Error"; + break; + + case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */ + desc = "LAN: Transmit Aborted"; + break; + + case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */ + desc = "LAN: Receive Error"; + break; + + case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */ + desc = "LAN: Receive Aborted"; + break; + + case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */ + desc = "LAN: Partial Packet"; + break; + + case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */ + desc = "LAN: Canceled"; + break; + +/****************************************************************************/ +/* Serial Attached SCSI values */ +/****************************************************************************/ + + case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */ + desc = "SAS: SMP Request Failed"; + break; + + case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */ + desc = "SAS: SMP Data Overrun"; break; default: desc = "Others"; break; } - if (desc != NULL) - printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc); + + if (!desc) + return; + + printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s\n", ioc->name, status, desc); } +#endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ EXPORT_SYMBOL(mpt_attach); diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index a0ce2f4e33f9..3d613c4f93d9 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -172,6 +172,9 @@ #define MPT_SCSI_SG_DEPTH 40 #endif +/* debug print string length used for events and iocstatus */ +# define EVENT_DESCR_STR_SZ 100 + #ifdef __KERNEL__ /* { */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index d5877316cbea..507aa08611d5 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -487,6 +487,90 @@ mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget, mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); } +#ifdef MPT_DEBUG_REPLY +/** + * mptscsih_iocstatus_info_scsiio - IOCSTATUS information for SCSIIO + * @ioc: Pointer to MPT_ADAPTER structure + * @ioc_status: U32 IOCStatus word from IOC + * @scsi_status: U8 sam status from target + * @scsi_state: U8 scsi state + * @sc: original scsi cmnd pointer + * @mf: Pointer to MPT request frame + * + * Refer to lsi/mpi.h. + **/ +static void +mptscsih_iocstatus_info_scsiio(MPT_ADAPTER *ioc, u32 ioc_status, + u8 scsi_status, u8 scsi_state, struct scsi_cmnd *sc) +{ + char extend_desc[EVENT_DESCR_STR_SZ]; + char *desc = NULL; + + switch (ioc_status) { + + case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ + desc = "SCSI Invalid Bus"; + break; + + case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */ + desc = "SCSI Invalid TargetID"; + break; + + case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ + /* + * Inquiry is issued for device scanning + */ + if (sc->cmnd[0] != 0x12) + desc = "SCSI Device Not There"; + break; + + case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ + desc = "SCSI Data Overrun"; + break; + + case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ + desc = "SCSI I/O Data Error"; + break; + + case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ + desc = "SCSI Protocol Error"; + break; + + case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ + desc = "SCSI Task Terminated"; + break; + + case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ + desc = "SCSI Residual Mismatch"; + break; + + case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ + desc = "SCSI Task Management Failed"; + break; + + case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ + desc = "SCSI IOC Terminated"; + break; + + case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ + desc = "SCSI Ext Terminated"; + break; + } + + if (!desc) + return; + + snprintf(extend_desc, EVENT_DESCR_STR_SZ, + "[%d:%d:%d:%d] cmd=%02Xh, sam_status=%02Xh state=%02Xh", + sc->device->host->host_no, + sc->device->channel, sc->device->id, sc->device->lun, + sc->cmnd[0], scsi_status, scsi_state); + + printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n", + ioc->name, ioc_status, desc, extend_desc); +} +#endif + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mptscsih_io_done - Main SCSI IO callback routine registered to @@ -573,12 +657,14 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) u32 xfer_cnt; u16 status; u8 scsi_state, scsi_status; + u32 log_info; status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; scsi_state = pScsiReply->SCSIState; scsi_status = pScsiReply->SCSIStatus; xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); sc->resid = sc->request_bufflen - xfer_cnt; + log_info = le32_to_cpu(pScsiReply->IOCLogInfo); /* * if we get a data underrun indication, yet no data was @@ -593,13 +679,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) status = MPI_IOCSTATUS_SUCCESS; } - dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n" - "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n" - "resid=%d bufflen=%d xfer_cnt=%d\n", - ioc->id, sc->device->id, sc->device->lun, - status, scsi_state, scsi_status, sc->resid, - sc->request_bufflen, xfer_cnt)); - if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) mptscsih_copy_sense_data(sc, hd, mf, pScsiReply); @@ -608,9 +687,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) */ if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID && pScsiReply->ResponseInfo) { - printk(KERN_NOTICE "ha=%d id=%d lun=%d: " + printk(KERN_NOTICE "[%d:%d:%d:%d] " "FCP_ResponseInfo=%08xh\n", - ioc->id, sc->device->id, sc->device->lun, + sc->device->host->host_no, sc->device->channel, + sc->device->id, sc->device->lun, le32_to_cpu(pScsiReply->ResponseInfo)); } @@ -655,9 +735,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) if ( ioc->bus_type == SAS ) { u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus); if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { - u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); - log_info &=SAS_LOGINFO_MASK; - if (log_info == SAS_LOGINFO_NEXUS_LOSS) { + if ((log_info & SAS_LOGINFO_MASK) + == SAS_LOGINFO_NEXUS_LOSS) { sc->result = (DID_BUS_BUSY << 16); break; } @@ -695,7 +774,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) else /* Sufficient data transfer occurred */ sc->result = (DID_OK << 16) | scsi_status; dreplyprintk((KERN_NOTICE - "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id)); + "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n", + sc->result, sc->device->channel, sc->device->id)); break; case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ @@ -808,7 +888,28 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) } /* switch(status) */ - dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result)); +#ifdef MPT_DEBUG_REPLY + if (sc->result) { + + mptscsih_iocstatus_info_scsiio(ioc, status, + scsi_status, scsi_state, sc); + + dreplyprintk(("%s: [%d:%d:%d:%d] cmd=0x%02x " + "result=0x%08x\n\tiocstatus=0x%04X " + "scsi_state=0x%02X scsi_status=0x%02X " + "loginfo=0x%08X\n", __FUNCTION__, + sc->device->host->host_no, sc->device->channel, sc->device->id, + sc->device->lun, sc->cmnd[0], sc->result, status, + scsi_state, scsi_status, log_info)); + + dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d " + "bufflen=%d xfer_cnt=%d\n", __FUNCTION__, + sc->device->host->host_no, sc->device->channel, sc->device->id, + sc->device->lun, sc->resid, sc->request_bufflen, + xfer_cnt)); + } +#endif + } /* end of address reply case */ /* Unmap the DMA buffers, if any. */ -- cgit v1.2.3 From b506ade9f3c309ac2ce3ffc4039f731097506038 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Mon, 29 Jan 2007 09:45:37 -0700 Subject: [SCSI] fusion - inactive raid support, and raid event bug fix's inactive raid support, e.g. exposing hidden raid components belonging to a volume that are inactive. Also misc bug fix's for various raid asyn events. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 278 ++++++++++++++++++++++++++++++-------- drivers/message/fusion/mptbase.h | 19 ++- drivers/message/fusion/mptsas.c | 272 ++++++++++++++++++++++++++++++++----- drivers/message/fusion/mptscsih.c | 32 +++++ drivers/message/fusion/mptspi.c | 3 +- 5 files changed, 510 insertions(+), 94 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 5d4faa4dd4ea..e7aec3478a30 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -184,6 +184,7 @@ static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); +static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc); /* module entry point */ static int __init fusion_init (void); @@ -1815,6 +1816,13 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) * and we try GetLanConfigPages again... */ if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { + + /* + * Initalize link list for inactive raid volumes. + */ + init_MUTEX(&ioc->raid_data.inactive_list_mutex); + INIT_LIST_HEAD(&ioc->raid_data.inactive_list); + if (ioc->bus_type == SAS) { /* clear persistency table */ @@ -2021,6 +2029,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) } kfree(ioc->spi_data.nvram); + mpt_inactive_raid_list_free(ioc); + kfree(ioc->raid_data.pIocPg2); kfree(ioc->raid_data.pIocPg3); ioc->spi_data.nvram = NULL; ioc->raid_data.pIocPg3 = NULL; @@ -2417,6 +2427,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word); facts->ProductID = le16_to_cpu(facts->ProductID); + if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) + > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) + ioc->ir_firmware = 1; facts->CurrentHostMfaHighAddr = le32_to_cpu(facts->CurrentHostMfaHighAddr); facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits); @@ -2735,9 +2748,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) /* RAID FW may take a long time to enable */ - if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) - > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) || - (ioc->bus_type == SAS)) { + if (ioc->ir_firmware || ioc->bus_type == SAS) { rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag); @@ -4325,8 +4336,8 @@ mptbase_raid_process_event_data(MPT_ADAPTER *ioc, if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED && reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) || (reason == MPI_EVENT_RAID_RC_SMART_DATA)) { - printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n", - ioc->name, disk); + printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n", + ioc->name, disk, volume); } else { printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n", ioc->name, volume); @@ -4727,7 +4738,187 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) return 0; } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** + * mpt_inactive_raid_list_free + * + * This clears this link list. + * + * @ioc - pointer to per adapter structure + * + **/ +static void +mpt_inactive_raid_list_free(MPT_ADAPTER *ioc) +{ + struct inactive_raid_component_info *component_info, *pNext; + + if (list_empty(&ioc->raid_data.inactive_list)) + return; + + down(&ioc->raid_data.inactive_list_mutex); + list_for_each_entry_safe(component_info, pNext, + &ioc->raid_data.inactive_list, list) { + list_del(&component_info->list); + kfree(component_info); + } + up(&ioc->raid_data.inactive_list_mutex); +} + +/** + * mpt_inactive_raid_volumes + * + * This sets up link list of phy_disk_nums for devices belonging in an inactive volume + * + * @ioc - pointer to per adapter structure + * @channel - volume channel + * @id - volume target id + * + * + **/ +static void +mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id) +{ + CONFIGPARMS cfg; + ConfigPageHeader_t hdr; + dma_addr_t dma_handle; + pRaidVolumePage0_t buffer = NULL; + int i; + RaidPhysDiskPage0_t phys_disk; + struct inactive_raid_component_info *component_info; + int handle_inactive_volumes; + + memset(&cfg, 0 , sizeof(CONFIGPARMS)); + memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); + hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; + cfg.pageAddr = (channel << 8) + id; + cfg.cfghdr.hdr = &hdr; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + + if (mpt_config(ioc, &cfg) != 0) + goto out; + + if (!hdr.PageLength) + goto out; + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, + &dma_handle); + + if (!buffer) + goto out; + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + if (mpt_config(ioc, &cfg) != 0) + goto out; + + if (!buffer->NumPhysDisks) + goto out; + + handle_inactive_volumes = + (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE || + (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 || + buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED || + buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0; + + if (!handle_inactive_volumes) + goto out; + + down(&ioc->raid_data.inactive_list_mutex); + for (i = 0; i < buffer->NumPhysDisks; i++) { + if(mpt_raid_phys_disk_pg0(ioc, + buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) + continue; + + if ((component_info = kmalloc(sizeof (*component_info), + GFP_KERNEL)) == NULL) + continue; + + component_info->volumeID = id; + component_info->volumeBus = channel; + component_info->d.PhysDiskNum = phys_disk.PhysDiskNum; + component_info->d.PhysDiskBus = phys_disk.PhysDiskBus; + component_info->d.PhysDiskID = phys_disk.PhysDiskID; + component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC; + + list_add_tail(&component_info->list, + &ioc->raid_data.inactive_list); + } + up(&ioc->raid_data.inactive_list_mutex); + + out: + if (buffer) + pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, + dma_handle); +} + +/** + * mpt_raid_phys_disk_pg0 - returns phys disk page zero + * @ioc: Pointer to a Adapter Structure + * @phys_disk_num: io unit unique phys disk num generated by the ioc + * @phys_disk: requested payload data returned + * + * Return: + * 0 on success + * -EFAULT if read of config page header fails or data pointer not NULL + * -ENOMEM if pci_alloc failed + **/ +int +mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk) +{ + CONFIGPARMS cfg; + ConfigPageHeader_t hdr; + dma_addr_t dma_handle; + pRaidPhysDiskPage0_t buffer = NULL; + int rc; + + memset(&cfg, 0 , sizeof(CONFIGPARMS)); + memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); + + hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + + if (mpt_config(ioc, &cfg) != 0) { + rc = -EFAULT; + goto out; + } + + if (!hdr.PageLength) { + rc = -EFAULT; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, + &dma_handle); + + if (!buffer) { + rc = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + cfg.pageAddr = phys_disk_num; + + if (mpt_config(ioc, &cfg) != 0) { + rc = -EFAULT; + goto out; + } + + rc = 0; + memcpy(phys_disk, buffer, sizeof(*buffer)); + phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA); + + out: + + if (buffer) + pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, + dma_handle); + + return rc; +} + /** * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes * @ioc: Pointer to a Adapter Strucutre @@ -4737,21 +4928,27 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) * 0 on success * -EFAULT if read of config page header fails or data pointer not NULL * -ENOMEM if pci_alloc failed - */ + **/ int mpt_findImVolumes(MPT_ADAPTER *ioc) { IOCPage2_t *pIoc2; u8 *mem; - ConfigPageIoc2RaidVol_t *pIocRv; dma_addr_t ioc2_dma; CONFIGPARMS cfg; ConfigPageHeader_t header; - int jj; int rc = 0; int iocpage2sz; - u8 nVols, nPhys; - u8 vid, vbus, vioc; + int i; + + if (!ioc->ir_firmware) + return 0; + + /* Free the old page + */ + kfree(ioc->raid_data.pIocPg2); + ioc->raid_data.pIocPg2 = NULL; + mpt_inactive_raid_list_free(ioc); /* Read IOCP2 header then the page. */ @@ -4779,55 +4976,23 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; cfg.physAddr = ioc2_dma; if (mpt_config(ioc, &cfg) != 0) - goto done_and_free; + goto out; + + mem = kmalloc(iocpage2sz, GFP_KERNEL); + if (!mem) + goto out; - if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) { - mem = kmalloc(iocpage2sz, GFP_ATOMIC); - if (mem) { - ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem; - } else { - goto done_and_free; - } - } memcpy(mem, (u8 *)pIoc2, iocpage2sz); + ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem; - /* Identify RAID Volume Id's */ - nVols = pIoc2->NumActiveVolumes; - if ( nVols == 0) { - /* No RAID Volume. - */ - goto done_and_free; - } else { - /* At least 1 RAID Volume - */ - pIocRv = pIoc2->RaidVolume; - ioc->raid_data.isRaid = 0; - for (jj = 0; jj < nVols; jj++, pIocRv++) { - vid = pIocRv->VolumeID; - vbus = pIocRv->VolumeBus; - vioc = pIocRv->VolumeIOC; - - /* find the match - */ - if (vbus == 0) { - ioc->raid_data.isRaid |= (1 << vid); - } else { - /* Error! Always bus 0 - */ - } - } - } + mpt_read_ioc_pg_3(ioc); - /* Identify Hidden Physical Disk Id's */ - nPhys = pIoc2->NumActivePhysDisks; - if (nPhys == 0) { - /* No physical disks. - */ - } else { - mpt_read_ioc_pg_3(ioc); - } + for (i = 0; i < pIoc2->NumActiveVolumes ; i++) + mpt_inactive_raid_volumes(ioc, + pIoc2->RaidVolume[i].VolumeBus, + pIoc2->RaidVolume[i].VolumeID); -done_and_free: + out: pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma); return rc; @@ -4880,7 +5045,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) cfg.physAddr = ioc3_dma; cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; if (mpt_config(ioc, &cfg) == 0) { - mem = kmalloc(iocpage3sz, GFP_ATOMIC); + mem = kmalloc(iocpage3sz, GFP_KERNEL); if (mem) { memcpy(mem, (u8 *)pIoc3, iocpage3sz); ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem; @@ -6833,6 +6998,7 @@ EXPORT_SYMBOL(mpt_findImVolumes); EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory); EXPORT_SYMBOL(mptbase_sas_persist_operation); +EXPORT_SYMBOL(mpt_raid_phys_disk_pg0); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 3d613c4f93d9..07830d28e58d 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -485,10 +485,24 @@ typedef struct _SasCfgData { */ }SasCfgData; +/* + * Inactive volume link list of raid component data + * @inactive_list + */ +struct inactive_raid_component_info { + struct list_head list; + u8 volumeID; /* volume target id */ + u8 volumeBus; /* volume channel */ + IOC_3_PHYS_DISK d; /* phys disk info */ +}; + typedef struct _RaidCfgData { IOCPage2_t *pIocPg2; /* table of Raid Volumes */ IOCPage3_t *pIocPg3; /* table of physical disks */ - int isRaid; /* bit field, 1 if RAID */ + struct semaphore inactive_list_mutex; + struct list_head inactive_list; /* link list for physical + disk that belong in + inactive volumes */ }RaidCfgData; typedef struct _FcCfgData { @@ -611,6 +625,8 @@ typedef struct _MPT_ADAPTER u8 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */ LANPage0_t lan_cnfg_page0; LANPage1_t lan_cnfg_page1; + + u8 ir_firmware; /* =1 if IR firmware detected */ /* * Description: errata_flag_1064 * If a PCIX read occurs within 1 or 2 cycles after the chip receives @@ -1043,6 +1059,7 @@ extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); extern int mpt_findImVolumes(MPT_ADAPTER *ioc); extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); +extern int mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk); /* * Public data decl's... diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index f7c5e0d97890..a8df06c422bd 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -94,12 +94,14 @@ static int mptsasTaskCtx = -1; static int mptsasInternalCtx = -1; /* Used only for internal commands */ static int mptsasMgmtCtx = -1; +static void mptsas_hotplug_work(struct work_struct *work); enum mptsas_hotplug_action { MPTSAS_ADD_DEVICE, MPTSAS_DEL_DEVICE, MPTSAS_ADD_RAID, MPTSAS_DEL_RAID, + MPTSAS_ADD_INACTIVE_VOLUME, MPTSAS_IGNORE_EVENT, }; @@ -108,14 +110,15 @@ struct mptsas_hotplug_event { MPT_ADAPTER *ioc; enum mptsas_hotplug_action event_type; u64 sas_address; - u32 channel; - u32 id; + u8 channel; + u8 id; u32 device_info; u16 handle; u16 parent_handle; u8 phy_id; - u8 phys_disk_num; - u8 phys_disk_num_valid; + u8 phys_disk_num_valid; /* hrc (hidden raid component) */ + u8 phys_disk_num; /* hrc - unique index*/ + u8 hidden_raid_component; /* hrc - don't expose*/ }; struct mptsas_discovery_event { @@ -140,6 +143,7 @@ struct mptsas_devinfo { u8 port_id; /* sas physical port this device is assoc'd with */ u8 id; /* logical target id of this device */ + u32 phys_disk_num; /* phys disk id, for csmi-ioctls */ u8 channel; /* logical bus number of this device */ u64 sas_address; /* WWN of this device, SATA is assigned by HBA,expander */ @@ -711,6 +715,7 @@ mptsas_target_alloc(struct scsi_target *starget) channel, id); vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; + p->phy_info[i].attached.phys_disk_num = id; } mutex_unlock(&hd->ioc->sas_topology_mutex); goto out; @@ -1272,6 +1277,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, device_info->phy_id = buffer->PhyNum; device_info->port_id = buffer->PhysicalPort; device_info->id = buffer->TargetID; + device_info->phys_disk_num = ~0; device_info->channel = buffer->Bus; memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); device_info->sas_address = le64_to_cpu(sas_address); @@ -1983,6 +1989,8 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) /* Reporting RAID volumes. */ + if (!ioc->ir_firmware) + goto out; if (!ioc->raid_data.pIocPg2) goto out; if (!ioc->raid_data.pIocPg2->NumActiveVolumes) @@ -2041,12 +2049,37 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) mutex_lock(&ioc->sas_topology_mutex); list_for_each_entry(port_info, &ioc->sas_topology, list) { for (i = 0; i < port_info->num_phys; i++) { + if (!mptsas_is_end_device( + &port_info->phy_info[i].attached)) + continue; if (port_info->phy_info[i].attached.sas_address != sas_address) continue; + phy_info = &port_info->phy_info[i]; + break; + } + } + mutex_unlock(&ioc->sas_topology_mutex); + return phy_info; +} + +static struct mptsas_phyinfo * +mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id) +{ + struct mptsas_portinfo *port_info; + struct mptsas_phyinfo *phy_info = NULL; + int i; + + mutex_lock(&ioc->sas_topology_mutex); + list_for_each_entry(port_info, &ioc->sas_topology, list) { + for (i = 0; i < port_info->num_phys; i++) { if (!mptsas_is_end_device( &port_info->phy_info[i].attached)) continue; + if (port_info->phy_info[i].attached.id != id) + continue; + if (port_info->phy_info[i].attached.channel != channel) + continue; phy_info = &port_info->phy_info[i]; break; } @@ -2056,7 +2089,7 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) } static struct mptsas_phyinfo * -mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) +mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id) { struct mptsas_portinfo *port_info; struct mptsas_phyinfo *phy_info = NULL; @@ -2065,11 +2098,15 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) mutex_lock(&ioc->sas_topology_mutex); list_for_each_entry(port_info, &ioc->sas_topology, list) { for (i = 0; i < port_info->num_phys; i++) { - if (port_info->phy_info[i].attached.id != id) - continue; if (!mptsas_is_end_device( &port_info->phy_info[i].attached)) continue; + if (port_info->phy_info[i].attached.phys_disk_num == ~0) + continue; + if (port_info->phy_info[i].attached.phys_disk_num != id) + continue; + if (port_info->phy_info[i].attached.channel != channel) + continue; phy_info = &port_info->phy_info[i]; break; } @@ -2105,6 +2142,76 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach) mptsas_reprobe_lun); } +static void +mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id) +{ + CONFIGPARMS cfg; + ConfigPageHeader_t hdr; + dma_addr_t dma_handle; + pRaidVolumePage0_t buffer = NULL; + RaidPhysDiskPage0_t phys_disk; + int i; + struct mptsas_hotplug_event *ev; + + memset(&cfg, 0 , sizeof(CONFIGPARMS)); + memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); + hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; + cfg.pageAddr = (channel << 8) + id; + cfg.cfghdr.hdr = &hdr; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + + if (mpt_config(ioc, &cfg) != 0) + goto out; + + if (!hdr.PageLength) + goto out; + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, + &dma_handle); + + if (!buffer) + goto out; + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + if (mpt_config(ioc, &cfg) != 0) + goto out; + + if (!(buffer->VolumeStatus.Flags & + MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE)) + goto out; + + if (!buffer->NumPhysDisks) + goto out; + + for (i = 0; i < buffer->NumPhysDisks; i++) { + + if (mpt_raid_phys_disk_pg0(ioc, + buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) + continue; + + ev = kzalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) { + printk(KERN_WARNING "mptsas: lost hotplug event\n"); + goto out; + } + + INIT_WORK(&ev->work, mptsas_hotplug_work); + ev->ioc = ioc; + ev->id = phys_disk.PhysDiskID; + ev->channel = phys_disk.PhysDiskBus; + ev->phys_disk_num_valid = 1; + ev->phys_disk_num = phys_disk.PhysDiskNum; + ev->event_type = MPTSAS_ADD_DEVICE; + schedule_work(&ev->work); + } + + out: + if (buffer) + pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, + dma_handle); +} /* * Work queue thread to handle SAS hotplug events */ @@ -2113,6 +2220,7 @@ mptsas_hotplug_work(struct work_struct *work) { struct mptsas_hotplug_event *ev = container_of(work, struct mptsas_hotplug_event, work); + MPT_ADAPTER *ioc = ev->ioc; struct mptsas_phyinfo *phy_info; struct sas_rphy *rphy; @@ -2125,17 +2233,43 @@ mptsas_hotplug_work(struct work_struct *work) VirtTarget *vtarget; VirtDevice *vdevice; - mutex_lock(&ioc->sas_discovery_mutex); switch (ev->event_type) { case MPTSAS_DEL_DEVICE: - phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id); + phy_info = NULL; + if (ev->phys_disk_num_valid) { + if (ev->hidden_raid_component){ + if (mptsas_sas_device_pg0(ioc, &sas_device, + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), + (ev->channel << 8) + ev->id)) { + dfailprintk((MYIOC_s_ERR_FMT + "%s: exit at line=%d\n", ioc->name, + __FUNCTION__, __LINE__)); + break; + } + phy_info = mptsas_find_phyinfo_by_sas_address( + ioc, sas_device.sas_address); + }else + phy_info = mptsas_find_phyinfo_by_phys_disk_num( + ioc, ev->channel, ev->phys_disk_num); + } + + if (!phy_info) + phy_info = mptsas_find_phyinfo_by_target(ioc, + ev->channel, ev->id); /* * Sanity checks, for non-existing phys and remote rphys. */ - if (!phy_info || !phy_info->port_details) { + if (!phy_info){ + dfailprintk((MYIOC_s_ERR_FMT + "%s: exit at line=%d\n", ioc->name, + __FUNCTION__, __LINE__)); + break; + } + if (!phy_info->port_details) { dfailprintk((MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); @@ -2148,6 +2282,7 @@ mptsas_hotplug_work(struct work_struct *work) __FUNCTION__, __LINE__)); break; } + port = mptsas_get_port(phy_info); if (!port) { dfailprintk((MYIOC_s_ERR_FMT @@ -2170,28 +2305,38 @@ mptsas_hotplug_work(struct work_struct *work) /* * Handling RAID components */ - if (ev->phys_disk_num_valid) { + if (ev->phys_disk_num_valid && + ev->hidden_raid_component) { + printk(MYIOC_s_INFO_FMT + "RAID Hidding: channel=%d, id=%d, " + "physdsk %d \n", ioc->name, ev->channel, + ev->id, ev->phys_disk_num); vtarget->id = ev->phys_disk_num; - vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; + vtarget->tflags |= + MPT_TARGET_FLAGS_RAID_COMPONENT; mptsas_reprobe_target(starget, 1); - break; + phy_info->attached.phys_disk_num = + ev->phys_disk_num; + break; } vtarget->deleted = 1; mptsas_target_reset(ioc, vtarget); } - if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) + if (phy_info->attached.device_info & + MPI_SAS_DEVICE_INFO_SSP_TARGET) ds = "ssp"; - if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) + if (phy_info->attached.device_info & + MPI_SAS_DEVICE_INFO_STP_TARGET) ds = "stp"; - if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) + if (phy_info->attached.device_info & + MPI_SAS_DEVICE_INFO_SATA_DEVICE) ds = "sata"; printk(MYIOC_s_INFO_FMT "removing %s device, channel %d, id %d, phy %d\n", ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); - #ifdef MPT_DEBUG_SAS_WIDE dev_printk(KERN_DEBUG, &port->dev, "delete port (%d)\n", port->port_identifier); @@ -2209,14 +2354,14 @@ mptsas_hotplug_work(struct work_struct *work) */ if (mptsas_sas_device_pg0(ioc, &sas_device, (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << - MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) { + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), + (ev->channel << 8) + ev->id)) { dfailprintk((MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); break; } - ssleep(2); __mptsas_discovery_work(ioc); phy_info = mptsas_find_phyinfo_by_sas_address(ioc, @@ -2230,7 +2375,8 @@ mptsas_hotplug_work(struct work_struct *work) } starget = mptsas_get_starget(phy_info); - if (starget) { + if (starget && (!ev->hidden_raid_component)){ + vtarget = starget->hostdata; if (!vtarget) { @@ -2243,9 +2389,15 @@ mptsas_hotplug_work(struct work_struct *work) * Handling RAID components */ if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { - vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT; + printk(MYIOC_s_INFO_FMT + "RAID Exposing: channel=%d, id=%d, " + "physdsk %d \n", ioc->name, ev->channel, + ev->id, ev->phys_disk_num); + vtarget->tflags &= + ~MPT_TARGET_FLAGS_RAID_COMPONENT; vtarget->id = ev->id; mptsas_reprobe_target(starget, 0); + phy_info->attached.phys_disk_num = ~0; } break; } @@ -2254,8 +2406,10 @@ mptsas_hotplug_work(struct work_struct *work) dfailprintk((MYIOC_s_ERR_FMT "%s: exit at line=%d\n", ioc->name, __FUNCTION__, __LINE__)); + if (ev->channel) printk("%d\n", __LINE__); break; } + port = mptsas_get_port(phy_info); if (!port) { dfailprintk((MYIOC_s_ERR_FMT @@ -2263,15 +2417,17 @@ mptsas_hotplug_work(struct work_struct *work) __FUNCTION__, __LINE__)); break; } - memcpy(&phy_info->attached, &sas_device, sizeof(struct mptsas_devinfo)); - if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) + if (phy_info->attached.device_info & + MPI_SAS_DEVICE_INFO_SSP_TARGET) ds = "ssp"; - if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) + if (phy_info->attached.device_info & + MPI_SAS_DEVICE_INFO_STP_TARGET) ds = "stp"; - if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) + if (phy_info->attached.device_info & + MPI_SAS_DEVICE_INFO_SATA_DEVICE) ds = "sata"; printk(MYIOC_s_INFO_FMT @@ -2312,19 +2468,23 @@ mptsas_hotplug_work(struct work_struct *work) break; case MPTSAS_DEL_RAID: sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, - ev->id, 0); + ev->id, 0); if (!sdev) break; printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, ev->id); - vdevice = sdev->hostdata; vdevice->vtarget->deleted = 1; mptsas_target_reset(ioc, vdevice->vtarget); + vdevice = sdev->hostdata; scsi_remove_device(sdev); scsi_device_put(sdev); mpt_findImVolumes(ioc); break; + case MPTSAS_ADD_INACTIVE_VOLUME: + mptsas_adding_inactive_raid_components(ioc, + ev->channel, ev->id); + break; case MPTSAS_IGNORE_EVENT: default: break; @@ -2332,7 +2492,6 @@ mptsas_hotplug_work(struct work_struct *work) mutex_unlock(&ioc->sas_discovery_mutex); kfree(ev); - } static void @@ -2386,15 +2545,20 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, mptsas_persist_clear_table); schedule_work(&ioc->sas_persist_task); break; + /* + * TODO, handle other events + */ case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: - /* TODO */ + case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: - /* TODO */ + case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: + case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: + case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: + case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: default: break; } } - static void mptsas_send_raid_event(MPT_ADAPTER *ioc, EVENT_DATA_RAID *raid_event_data) @@ -2415,31 +2579,36 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, INIT_WORK(&ev->work, mptsas_hotplug_work); ev->ioc = ioc; ev->id = raid_event_data->VolumeID; + ev->channel = raid_event_data->VolumeBus; ev->event_type = MPTSAS_IGNORE_EVENT; switch (raid_event_data->ReasonCode) { case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: + ev->phys_disk_num_valid = 1; + ev->phys_disk_num = raid_event_data->PhysDiskNum; ev->event_type = MPTSAS_ADD_DEVICE; break; case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: - ioc->raid_data.isRaid = 1; ev->phys_disk_num_valid = 1; ev->phys_disk_num = raid_event_data->PhysDiskNum; + ev->hidden_raid_component = 1; ev->event_type = MPTSAS_DEL_DEVICE; break; case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: switch (state) { case MPI_PD_STATE_ONLINE: - ioc->raid_data.isRaid = 1; + case MPI_PD_STATE_NOT_COMPATIBLE: ev->phys_disk_num_valid = 1; ev->phys_disk_num = raid_event_data->PhysDiskNum; + ev->hidden_raid_component = 1; ev->event_type = MPTSAS_ADD_DEVICE; break; case MPI_PD_STATE_MISSING: - case MPI_PD_STATE_NOT_COMPATIBLE: case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST: case MPI_PD_STATE_FAILED_AT_HOST_REQUEST: case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON: + ev->phys_disk_num_valid = 1; + ev->phys_disk_num = raid_event_data->PhysDiskNum; ev->event_type = MPTSAS_DEL_DEVICE; break; default: @@ -2496,6 +2665,35 @@ mptsas_send_discovery_event(MPT_ADAPTER *ioc, schedule_work(&ev->work); }; +/* + * mptsas_send_ir2_event - handle exposing hidden disk when + * an inactive raid volume is added + * + * @ioc: Pointer to MPT_ADAPTER structure + * @ir2_data + * + */ +static void +mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data) +{ + struct mptsas_hotplug_event *ev; + + if (ir2_data->ReasonCode != + MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED) + return; + + ev = kzalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) + return; + + INIT_WORK(&ev->work, mptsas_hotplug_work); + ev->ioc = ioc; + ev->id = ir2_data->TargetID; + ev->channel = ir2_data->Bus; + ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME; + + schedule_work(&ev->work); +}; static int mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) @@ -2535,6 +2733,10 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) mptsas_send_discovery_event(ioc, (EVENT_DATA_SAS_DISCOVERY *)reply->Data); break; + case MPI_EVENT_IR2: + mptsas_send_ir2_event(ioc, + (PTR_MPI_EVENT_DATA_IR2)reply->Data); + break; default: rc = mptscsih_event_process(ioc, reply); break; @@ -2742,7 +2944,7 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) struct mptsas_portinfo *p, *n; int i; - ioc->sas_discovery_ignore_events=1; + ioc->sas_discovery_ignore_events = 1; sas_remove_host(ioc->sh); mutex_lock(&ioc->sas_topology_mutex); diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 507aa08611d5..f9e11c8db462 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -2244,6 +2244,7 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) { + struct inactive_raid_component_info *component_info; int i; int rc = 0; @@ -2257,6 +2258,21 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) } } + /* + * Check inactive list for matching phys disks + */ + if (list_empty(&ioc->raid_data.inactive_list)) + goto out; + + down(&ioc->raid_data.inactive_list_mutex); + list_for_each_entry(component_info, &ioc->raid_data.inactive_list, + list) { + if ((component_info->d.PhysDiskID == id) && + (component_info->d.PhysDiskBus == channel)) + rc = 1; + } + up(&ioc->raid_data.inactive_list_mutex); + out: return rc; } @@ -2265,6 +2281,7 @@ EXPORT_SYMBOL(mptscsih_is_phys_disk); u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) { + struct inactive_raid_component_info *component_info; int i; int rc = -ENXIO; @@ -2278,6 +2295,21 @@ mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) } } + /* + * Check inactive list for matching phys disks + */ + if (list_empty(&ioc->raid_data.inactive_list)) + goto out; + + down(&ioc->raid_data.inactive_list_mutex); + list_for_each_entry(component_info, &ioc->raid_data.inactive_list, + list) { + if ((component_info->d.PhysDiskID == id) && + (component_info->d.PhysDiskBus == channel)) + rc = component_info->d.PhysDiskNum; + } + up(&ioc->raid_data.inactive_list_mutex); + out: return rc; } diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 06a7b86f5f23..5398aeab191d 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -1363,8 +1363,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* * If RAID Firmware Detected, setup virtual channel */ - if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) - > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) + if (ioc->ir_firmware) sh->max_channel = 1; else sh->max_channel = 0; -- cgit v1.2.3 From df9e062ad994c4db683377b108c0dbed4690e4b0 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Mon, 29 Jan 2007 09:46:21 -0700 Subject: [SCSI] fusion - serialize target resets in mptsas.c Fusion firmware requires target reset following hotplug removal event, with purpose to flush target outstanding request in fw. Current implementation does the target resets from delayed work tasks, that in heavy load conditions, take too long to be invoked, resulting in command time outs This patch will issue target reset immediately from ISR context, and will queue remaining target resets to be issued after the previous one completes. The delayed work tasks are spawned during the target reset completion. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 1 + drivers/message/fusion/mptsas.c | 325 +++++++++++++++++++++++++++++++++------ 2 files changed, 281 insertions(+), 45 deletions(-) diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 07830d28e58d..7176944e201c 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -994,6 +994,7 @@ typedef struct _MPT_SCSI_HOST { int scandv_wait_done; long last_queue_full; u16 tm_iocstatus; + struct list_head target_reset_list; } MPT_SCSI_HOST; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index a8df06c422bd..3dbb5659f615 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -96,6 +96,12 @@ static int mptsasMgmtCtx = -1; static void mptsas_hotplug_work(struct work_struct *work); +struct mptsas_target_reset_event { + struct list_head list; + EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data; + u8 target_reset_issued; +}; + enum mptsas_hotplug_action { MPTSAS_ADD_DEVICE, MPTSAS_DEL_DEVICE, @@ -571,20 +577,271 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) mutex_unlock(&ioc->sas_topology_mutex); } +/** + * csmisas_find_vtarget + * + * @ioc + * @volume_id + * @volume_bus + * + **/ +static VirtTarget * +mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id) +{ + struct scsi_device *sdev; + VirtDevice *vdev; + VirtTarget *vtarget = NULL; + + shost_for_each_device(sdev, ioc->sh) { + if ((vdev = sdev->hostdata) == NULL) + continue; + if (vdev->vtarget->id == id && + vdev->vtarget->channel == channel) + vtarget = vdev->vtarget; + } + return vtarget; +} + +/** + * mptsas_target_reset + * + * Issues TARGET_RESET to end device using handshaking method + * + * @ioc + * @channel + * @id + * + * Returns (1) success + * (0) failure + * + **/ +static int +mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id) +{ + MPT_FRAME_HDR *mf; + SCSITaskMgmt_t *pScsiTm; + + if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { + dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n", + ioc->name,__FUNCTION__, __LINE__)); + return 0; + } + + /* Format the Request + */ + pScsiTm = (SCSITaskMgmt_t *) mf; + memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t)); + pScsiTm->TargetID = id; + pScsiTm->Bus = channel; + pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; + pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET; + pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; + + DBG_DUMP_TM_REQUEST_FRAME(mf); + + if (mpt_send_handshake_request(ioc->TaskCtx, ioc, + sizeof(SCSITaskMgmt_t), (u32 *)mf, NO_SLEEP)) { + mpt_free_msg_frame(ioc, mf); + dfailprintk((MYIOC_s_WARN_FMT "%s, tm handshake failed @%d!!\n", + ioc->name,__FUNCTION__, __LINE__)); + return 0; + } + + return 1; +} + +/** + * mptsas_target_reset_queue + * + * Receive request for TARGET_RESET after recieving an firmware + * event NOT_RESPONDING_EVENT, then put command in link list + * and queue if task_queue already in use. + * + * @ioc + * @sas_event_data + * + **/ static void -mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget) +mptsas_target_reset_queue(MPT_ADAPTER *ioc, + EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data) { - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + VirtTarget *vtarget = NULL; + struct mptsas_target_reset_event *target_reset_list; + u8 id, channel; - if (mptscsih_TMHandler(hd, - MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - vtarget->channel, vtarget->id, 0, 0, 5) < 0) { - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - printk(MYIOC_s_WARN_FMT - "Error processing TaskMgmt id=%d TARGET_RESET\n", - ioc->name, vtarget->id); + id = sas_event_data->TargetID; + channel = sas_event_data->Bus; + + if (!(vtarget = mptsas_find_vtarget(ioc, channel, id))) + return; + + vtarget->deleted = 1; /* block IO */ + + target_reset_list = kzalloc(sizeof(*target_reset_list), + GFP_ATOMIC); + if (!target_reset_list) { + dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", + ioc->name,__FUNCTION__, __LINE__)); + return; + } + + memcpy(&target_reset_list->sas_event_data, sas_event_data, + sizeof(*sas_event_data)); + list_add_tail(&target_reset_list->list, &hd->target_reset_list); + + if (hd->resetPending) + return; + + if (mptsas_target_reset(ioc, channel, id)) { + target_reset_list->target_reset_issued = 1; + hd->resetPending = 1; + } +} + +/** + * mptsas_dev_reset_complete + * + * Completion for TARGET_RESET after NOT_RESPONDING_EVENT, + * enable work queue to finish off removing device from upper layers. + * then send next TARGET_RESET in the queue. + * + * @ioc + * + **/ +static void +mptsas_dev_reset_complete(MPT_ADAPTER *ioc) +{ + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + struct list_head *head = &hd->target_reset_list; + struct mptsas_target_reset_event *target_reset_list; + struct mptsas_hotplug_event *ev; + EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data; + u8 id, channel; + __le64 sas_address; + + if (list_empty(head)) + return; + + target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list); + + sas_event_data = &target_reset_list->sas_event_data; + id = sas_event_data->TargetID; + channel = sas_event_data->Bus; + hd->resetPending = 0; + + /* + * retry target reset + */ + if (!target_reset_list->target_reset_issued) { + if (mptsas_target_reset(ioc, channel, id)) { + target_reset_list->target_reset_issued = 1; + hd->resetPending = 1; + } + return; + } + + /* + * enable work queue to remove device from upper layers + */ + list_del(&target_reset_list->list); + + ev = kzalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) { + dfailprintk((MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", + ioc->name,__FUNCTION__, __LINE__)); + return; + } + + INIT_WORK(&ev->work, mptsas_hotplug_work); + ev->ioc = ioc; + ev->handle = le16_to_cpu(sas_event_data->DevHandle); + ev->parent_handle = + le16_to_cpu(sas_event_data->ParentDevHandle); + ev->channel = channel; + ev->id =id; + ev->phy_id = sas_event_data->PhyNum; + memcpy(&sas_address, &sas_event_data->SASAddress, + sizeof(__le64)); + ev->sas_address = le64_to_cpu(sas_address); + ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo); + ev->event_type = MPTSAS_DEL_DEVICE; + schedule_work(&ev->work); + kfree(target_reset_list); + + /* + * issue target reset to next device in the queue + */ + + head = &hd->target_reset_list; + if (list_empty(head)) + return; + + target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, + list); + + sas_event_data = &target_reset_list->sas_event_data; + id = sas_event_data->TargetID; + channel = sas_event_data->Bus; + + if (mptsas_target_reset(ioc, channel, id)) { + target_reset_list->target_reset_issued = 1; + hd->resetPending = 1; + } +} + +/** + * mptsas_taskmgmt_complete + * + * @ioc + * @mf + * @mr + * + **/ +static int +mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) +{ + mptsas_dev_reset_complete(ioc); + return mptscsih_taskmgmt_complete(ioc, mf, mr); +} + +/** + * mptscsih_ioc_reset + * + * @ioc + * @reset_phase + * + **/ +static int +mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) +{ + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + struct mptsas_target_reset_event *target_reset_list, *n; + int rc; + + rc = mptscsih_ioc_reset(ioc, reset_phase); + + if (ioc->bus_type != SAS) + goto out; + + if (reset_phase != MPT_IOC_POST_RESET) + goto out; + + if (!hd || !hd->ioc) + goto out; + + if (list_empty(&hd->target_reset_list)) + goto out; + + /* flush the target_reset_list */ + list_for_each_entry_safe(target_reset_list, n, + &hd->target_reset_list, list) { + list_del(&target_reset_list->list); + kfree(target_reset_list); } + + out: + return rc; } static int @@ -1885,8 +2142,6 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc) struct mptsas_portinfo buffer; struct mptsas_portinfo *port_info, *n, *parent; struct mptsas_phyinfo *phy_info; - struct scsi_target * starget; - VirtTarget * vtarget; struct sas_port * port; int i; u64 expander_sas_address; @@ -1903,25 +2158,6 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc) (MPI_SAS_EXPAND_PGAD_FORM_HANDLE << MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) { - /* - * Issue target reset to all child end devices - * then mark them deleted to prevent further - * IO going to them. - */ - phy_info = port_info->phy_info; - for (i = 0; i < port_info->num_phys; i++, phy_info++) { - starget = mptsas_get_starget(phy_info); - if (!starget) - continue; - vtarget = starget->hostdata; - if(vtarget->deleted) - continue; - vtarget->deleted = 1; - mptsas_target_reset(ioc, vtarget); - sas_port_delete(mptsas_get_port(phy_info)); - mptsas_port_delete(phy_info->port_details); - } - /* * Obtain the port_info instance to the parent port */ @@ -2319,9 +2555,6 @@ mptsas_hotplug_work(struct work_struct *work) ev->phys_disk_num; break; } - - vtarget->deleted = 1; - mptsas_target_reset(ioc, vtarget); } if (phy_info->attached.device_info & @@ -2474,8 +2707,6 @@ mptsas_hotplug_work(struct work_struct *work) printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, ev->id); - vdevice->vtarget->deleted = 1; - mptsas_target_reset(ioc, vdevice->vtarget); vdevice = sdev->hostdata; scsi_remove_device(sdev); scsi_device_put(sdev); @@ -2509,8 +2740,12 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, return; switch (sas_event_data->ReasonCode) { - case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: + + mptsas_target_reset_queue(ioc, sas_event_data); + break; + + case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: ev = kzalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) { printk(KERN_WARNING "mptsas: lost hotplug event\n"); @@ -2871,8 +3106,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) sh->sg_tablesize = numSGE; } - spin_unlock_irqrestore(&ioc->FreeQlock, flags); - hd = (MPT_SCSI_HOST *) sh->hostdata; hd->ioc = ioc; @@ -2912,15 +3145,17 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->sas_data.ptClear = mpt_pt_clear; + init_waitqueue_head(&hd->scandv_waitq); + hd->scandv_wait_done = 0; + hd->last_queue_full = 0; + INIT_LIST_HEAD(&hd->target_reset_list); + spin_unlock_irqrestore(&ioc->FreeQlock, flags); + if (ioc->sas_data.ptClear==1) { mptbase_sas_persist_operation( ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT); } - init_waitqueue_head(&hd->scandv_waitq); - hd->scandv_wait_done = 0; - hd->last_queue_full = 0; - error = scsi_add_host(sh, &ioc->pcidev->dev); if (error) { dprintk((KERN_ERR MYNAM @@ -2999,7 +3234,7 @@ mptsas_init(void) return -ENODEV; mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); - mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER); + mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER); mptsasInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); @@ -3009,7 +3244,7 @@ mptsas_init(void) ": Registered for IOC event notifications\n")); } - if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) { + if (mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset) == 0) { dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); } -- cgit v1.2.3 From 2ecce492290bf0d5eedc76cf0f4bf45f8c3f42bc Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Mon, 29 Jan 2007 09:47:08 -0700 Subject: [SCSI] fusion - report wide port sas address's for hba phys Return proper sas address to sas transport layer for parent phys that form a wide port. Current implementation returns a different address for each phy, incremented by one from the base address. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 52 ++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 3dbb5659f615..9d0f87f4c5e5 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -169,6 +169,7 @@ struct mptsas_portinfo_details{ }; struct mptsas_phyinfo { + u16 handle; /* unique id to address this */ u8 phy_id; /* phy index */ u8 port_id; /* firmware port identifier */ u8 negotiated_link_rate; /* nego'd link rate for this phy */ @@ -184,7 +185,6 @@ struct mptsas_phyinfo { struct mptsas_portinfo { struct list_head list; - u16 handle; /* unique id to address this */ u16 num_phys; /* number of phys */ struct mptsas_phyinfo *phy_info; }; @@ -1387,9 +1387,6 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) goto out_free_consistent; } - if (port_info->num_phys) - port_info->handle = - le16_to_cpu(buffer->PhyData[0].ControllerDevHandle); for (i = 0; i < port_info->num_phys; i++) { mptsas_print_phy_data(&buffer->PhyData[i]); port_info->phy_info[i].phy_id = i; @@ -1398,6 +1395,8 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) port_info->phy_info[i].negotiated_link_rate = buffer->PhyData[i].NegotiatedLinkRate; port_info->phy_info[i].portinfo = port_info; + port_info->phy_info[i].handle = + le16_to_cpu(buffer->PhyData[i].ControllerDevHandle); } out_free_consistent: @@ -1599,7 +1598,6 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, /* save config data */ port_info->num_phys = buffer->NumPhys; - port_info->handle = le16_to_cpu(buffer->DevHandle); port_info->phy_info = kcalloc(port_info->num_phys, sizeof(*port_info->phy_info),GFP_KERNEL); if (!port_info->phy_info) { @@ -1607,8 +1605,11 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, goto out_free_consistent; } - for (i = 0; i < port_info->num_phys; i++) + for (i = 0; i < port_info->num_phys; i++) { port_info->phy_info[i].portinfo = port_info; + port_info->phy_info[i].handle = + le16_to_cpu(buffer->DevHandle); + } out_free_consistent: pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, @@ -1976,7 +1977,6 @@ static int mptsas_probe_hba_phys(MPT_ADAPTER *ioc) { struct mptsas_portinfo *port_info, *hba; - u32 handle = 0xFFFF; int error = -ENOMEM, i; hba = kzalloc(sizeof(*port_info), GFP_KERNEL); @@ -1988,34 +1988,36 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) goto out_free_port_info; mutex_lock(&ioc->sas_topology_mutex); - ioc->handle = hba->handle; - port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle); + ioc->handle = hba->phy_info[0].handle; + port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle); if (!port_info) { port_info = hba; list_add_tail(&port_info->list, &ioc->sas_topology); } else { - port_info->handle = hba->handle; - for (i = 0; i < hba->num_phys; i++) + for (i = 0; i < hba->num_phys; i++) { port_info->phy_info[i].negotiated_link_rate = hba->phy_info[i].negotiated_link_rate; + port_info->phy_info[i].handle = + hba->phy_info[i].handle; + port_info->phy_info[i].port_id = + hba->phy_info[i].port_id; + } kfree(hba->phy_info); kfree(hba); hba = NULL; } mutex_unlock(&ioc->sas_topology_mutex); - for (i = 0; i < port_info->num_phys; i++) { mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER << MPI_SAS_PHY_PGAD_FORM_SHIFT), i); mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify, - (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE << - MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle); + (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), + port_info->phy_info[i].handle); port_info->phy_info[i].identify.phy_id = - port_info->phy_info[i].phy_id; - handle = port_info->phy_info[i].identify.handle; - + port_info->phy_info[i].phy_id = i; if (port_info->phy_info[i].attached.handle) mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].attached, @@ -2051,12 +2053,12 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle) goto out; error = mptsas_sas_expander_pg0(ioc, ex, - (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << - MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle); + (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << + MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle); if (error) goto out_free_port_info; - *handle = ex->handle; + *handle = ex->phy_info[0].handle; mutex_lock(&ioc->sas_topology_mutex); port_info = mptsas_find_portinfo_by_handle(ioc, *handle); @@ -2064,7 +2066,12 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle) port_info = ex; list_add_tail(&port_info->list, &ioc->sas_topology); } else { - port_info->handle = ex->handle; + for (i = 0; i < ex->num_phys; i++) { + port_info->phy_info[i].handle = + ex->phy_info[i].handle; + port_info->phy_info[i].port_id = + ex->phy_info[i].port_id; + } kfree(ex->phy_info); kfree(ex); ex = NULL; @@ -2156,7 +2163,8 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc) if (mptsas_sas_expander_pg0(ioc, &buffer, (MPI_SAS_EXPAND_PGAD_FORM_HANDLE << - MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) { + MPI_SAS_EXPAND_PGAD_FORM_SHIFT), + port_info->phy_info[0].handle)) { /* * Obtain the port_info instance to the parent port -- cgit v1.2.3 From cd2c61911dfe0d87cb872571739d5838cc233747 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Mon, 29 Jan 2007 09:47:47 -0700 Subject: [SCSI] fusion - error handling bug fix's misc error handling bug fix's - properly interpret iocstatus returned after task management request - clear tmState after a failed doorbell - cleanup mptscsih_taskmgmt_complete Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 14 +- drivers/message/fusion/mptctl.c | 2 +- drivers/message/fusion/mptscsih.c | 295 +++++++++++++++++++------------------- 3 files changed, 153 insertions(+), 158 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index e7aec3478a30..fcbce1c31d04 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -916,7 +916,7 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) int mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag) { - int r = 0; + int r = 0; u8 *req_as_bytes; int ii; @@ -3219,6 +3219,9 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) u32 diag1val = 0; #endif + /* Clear any existing interrupts */ + CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset " "address=%p\n", ioc->name, __FUNCTION__, @@ -3238,7 +3241,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) " count=%d\n", ioc->name, doorbell, count)); if (doorbell == MPI_IOC_STATE_READY) { - return 0; + return 1; } /* wait 1 sec */ @@ -3250,9 +3253,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) return -1; } - /* Clear any existing interrupts */ - CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - /* Use "Diagnostic reset" method! (only thing available!) */ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); @@ -3968,7 +3968,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } } else { while (--cntdn) { - mdelay (1); + udelay (1000); intstat = CHIPREG_READ32(&ioc->chip->IntStatus); if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) break; @@ -4020,7 +4020,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) intstat = CHIPREG_READ32(&ioc->chip->IntStatus); if (intstat & MPI_HIS_DOORBELL_INTERRUPT) break; - mdelay(1); + udelay (1000); count++; } } diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 922d0c879f06..4779ff502e53 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -313,7 +313,7 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl) */ dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", ioctl->ioc->name)); - mpt_HardResetHandler(ioctl->ioc, NO_SLEEP); + mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP); } return; diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index f9e11c8db462..3bc9446ec42d 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1536,7 +1536,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mptscsih_TMHandler - Generic handler for SCSI Task Management. * Fall through to mpt_HardResetHandler if: not operational, too many * failed TM requests or handshake failure. @@ -1552,28 +1552,17 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC * will be active. * - * Returns 0 for SUCCESS or -1 if FAILED. - */ + * Returns 0 for SUCCESS, or FAILED. + **/ int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) { MPT_ADAPTER *ioc; int rc = -1; - int doTask = 1; u32 ioc_raw_state; unsigned long flags; - /* If FW is being reloaded currently, return success to - * the calling function. - */ - if (hd == NULL) - return 0; - ioc = hd->ioc; - if (ioc == NULL) { - printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n"); - return FAILED; - } dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name)); // SJR - CHECKME - Can we avoid this here? @@ -1586,8 +1575,10 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c spin_unlock_irqrestore(&ioc->diagLock, flags); /* Wait a fixed amount of time for the TM pending flag to be cleared. - * If we time out and not bus reset, then we return a FAILED status to the caller. - * The call to mptscsih_tm_pending_wait() will set the pending flag if we are + * If we time out and not bus reset, then we return a FAILED status + * to the caller. + * The call to mptscsih_tm_pending_wait() will set the pending flag + * if we are * successful. Otherwise, reload the FW. */ if (mptscsih_tm_pending_wait(hd) == FAILED) { @@ -1597,18 +1588,16 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c hd->ioc->name, hd->tmPending)); return FAILED; } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { - dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: " - "Timed out waiting for last TM (%d) to complete! \n", - hd->ioc->name, hd->tmPending)); + dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target " + "reset: Timed out waiting for last TM (%d) " + "to complete! \n", hd->ioc->name, + hd->tmPending)); return FAILED; } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: " "Timed out waiting for last TM (%d) to complete! \n", hd->ioc->name, hd->tmPending)); - if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)) - return FAILED; - - doTask = 0; + return FAILED; } } else { spin_lock_irqsave(&hd->ioc->FreeQlock, flags); @@ -1616,47 +1605,40 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); } - /* Is operational? - */ ioc_raw_state = mpt_GetIocState(hd->ioc, 0); -#ifdef MPT_DEBUG_RESET if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { printk(MYIOC_s_WARN_FMT - "TM Handler: IOC Not operational(0x%x)!\n", - hd->ioc->name, ioc_raw_state); - } -#endif - - if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) - && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) { - - /* Isse the Task Mgmt request. - */ - if (hd->hard_resets < -1) - hd->hard_resets++; - rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun, ctx2abort, timeout); - if (rc) { - printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name); - } else { - dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name)); - } + "TM Handler for type=%x: IOC Not operational (0x%x)!\n", + ioc->name, type, ioc_raw_state); + printk(KERN_WARNING " Issuing HardReset!!\n"); + if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) + printk((KERN_WARNING "TMHandler: HardReset " + "FAILED!!\n")); + return FAILED; } - /* Only fall through to the HRH if this is a bus reset - */ - if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc || - ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) { - dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", - hd->ioc->name)); - rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); + if (ioc_raw_state & MPI_DOORBELL_ACTIVE) { + printk(MYIOC_s_WARN_FMT + "TM Handler for type=%x: ioc_state: " + "DOORBELL_ACTIVE (0x%x)!\n", + ioc->name, type, ioc_raw_state); + return FAILED; } - /* - * Check IOCStatus from TM reply message + /* Isse the Task Mgmt request. */ - if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS) - rc = FAILED; + if (hd->hard_resets < -1) + hd->hard_resets++; + + rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun, + ctx2abort, timeout); + if (rc) + printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", + hd->ioc->name); + else + dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", + hd->ioc->name)); dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc)); @@ -1665,7 +1647,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mptscsih_IssueTaskMgmt - Generic send Task Management function. * @hd: Pointer to MPT_SCSI_HOST structure * @type: Task Management type @@ -1678,9 +1660,9 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c * * Not all fields are meaningfull for all task types. * - * Returns 0 for SUCCESS, -999 for "no msg frames", - * else other non-zero value returned. - */ + * Returns 0 for SUCCESS, or FAILED. + * + **/ static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) { @@ -1720,32 +1702,52 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i pScsiTm->TaskMsgContext = ctx2abort; - dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n", - hd->ioc->name, ctx2abort, type)); + dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) " + "type=%d\n", hd->ioc->name, ctx2abort, type)); DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm); if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc, - sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, - CAN_SLEEP)) != 0) { - dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" - " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, - hd->ioc, mf)); - mpt_free_msg_frame(hd->ioc, mf); - return retval; + sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) { + dfailprintk((MYIOC_s_ERR_FMT "send_handshake FAILED!" + " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd, + hd->ioc, mf, retval)); + goto fail_out; } if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) { - dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!" + dfailprintk((MYIOC_s_ERR_FMT "task management request TIMED OUT!" " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf)); - mpt_free_msg_frame(hd->ioc, mf); dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", hd->ioc->name)); retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); + dtmprintk((MYIOC_s_INFO_FMT "rc=%d \n", + hd->ioc->name, retval)); + goto fail_out; } + /* + * Handle success case, see if theres a non-zero ioc_status. + */ + if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS || + hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED || + hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED) + retval = 0; + else + retval = FAILED; + return retval; + + fail_out: + + /* + * Free task managment mf, and corresponding tm flags + */ + mpt_free_msg_frame(hd->ioc, mf); + hd->tmPending = 0; + hd->tmState = TM_STATE_NONE; + return FAILED; } static int @@ -1770,7 +1772,7 @@ mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) * (linux scsi_host_template.eh_abort_handler routine) * * Returns SUCCESS or FAILED. - */ + **/ int mptscsih_abort(struct scsi_cmnd * SCpnt) { @@ -1806,9 +1808,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) return SUCCESS; } - if (hd->resetPending) { + if (hd->resetPending) return FAILED; - } if (hd->timeouts < -1) hd->timeouts++; @@ -1835,9 +1836,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) ctx2abort, mptscsih_get_tm_timeout(hd->ioc)); if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx && - SCpnt->serial_number == sn) { + SCpnt->serial_number == sn) retval = FAILED; - } printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", hd->ioc->name, @@ -1845,12 +1845,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) if (retval == 0) return SUCCESS; - - if(retval != FAILED ) { - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - } - return FAILED; + else + return FAILED; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1861,7 +1857,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) * (linux scsi_host_template.eh_dev_reset_handler routine) * * Returns SUCCESS or FAILED. - */ + **/ int mptscsih_dev_reset(struct scsi_cmnd * SCpnt) { @@ -1896,14 +1892,11 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) if (retval == 0) return SUCCESS; - - if(retval != FAILED ) { - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - } - return FAILED; + else + return FAILED; } + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant @@ -1912,7 +1905,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) * (linux scsi_host_template.eh_bus_reset_handler routine) * * Returns SUCCESS or FAILED. - */ + **/ int mptscsih_bus_reset(struct scsi_cmnd * SCpnt) { @@ -1946,12 +1939,8 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) if (retval == 0) return SUCCESS; - - if(retval != FAILED ) { - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - } - return FAILED; + else + return FAILED; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2034,7 +2023,6 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) /** * mptscsih_tm_wait_for_completion - wait for completion of TM task * @hd: Pointer to MPT host structure. - * @timeout: timeout in seconds * * Returns {SUCCESS,FAILED}. */ @@ -2108,7 +2096,7 @@ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) * load/init time via the mpt_register() API call. * * Returns 1 indicating alloc'd request frame ptr should be freed. - */ + **/ int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) { @@ -2118,78 +2106,85 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m unsigned long flags; u16 iocstatus; u8 tmType; + u32 termination_count; dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n", - ioc->name, mf, mr)); - if (ioc->sh) { - /* Depending on the thread, a timer is activated for - * the TM request. Delete this timer on completion of TM. - * Decrement count of outstanding TM requests. - */ - hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; - } else { - dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n", - ioc->name)); + ioc->name, mf, mr)); + if (!ioc->sh) { + dtmprintk((MYIOC_s_WARN_FMT + "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name)); return 1; } if (mr == NULL) { - dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n", - ioc->name, mf)); + dtmprintk((MYIOC_s_WARN_FMT + "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf)); return 1; - } else { - pScsiTmReply = (SCSITaskMgmtReply_t*)mr; - pScsiTmReq = (SCSITaskMgmt_t*)mf; + } - /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */ - tmType = pScsiTmReq->TaskType; + hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + pScsiTmReply = (SCSITaskMgmtReply_t*)mr; + pScsiTmReq = (SCSITaskMgmt_t*)mf; + tmType = pScsiTmReq->TaskType; + iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; + termination_count = le32_to_cpu(pScsiTmReply->TerminationCount); + + if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && + pScsiTmReply->ResponseCode) + mptscsih_taskmgmt_response_code(ioc, + pScsiTmReply->ResponseCode); + DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); + +#if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_TM) + printk("%s: ha=%d [%d:%d:0] task_type=0x%02X " + "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X " + "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus, + pScsiTmReply->TargetID, pScsiTmReq->TaskType, + le16_to_cpu(pScsiTmReply->IOCStatus), + le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode, + le32_to_cpu(pScsiTmReply->TerminationCount)); +#endif + if (!iocstatus) { + dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name)); + hd->abortSCpnt = NULL; + goto out; + } - if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && - pScsiTmReply->ResponseCode) - mptscsih_taskmgmt_response_code(ioc, - pScsiTmReply->ResponseCode); + /* Error? (anything non-zero?) */ - dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n", - ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount))); - DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); + /* clear flags and continue. + */ + switch (tmType) { - iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; - hd->tm_iocstatus = iocstatus; - dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n", - ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo))); - /* Error? (anything non-zero?) */ - if (iocstatus) { + case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK: + if (termination_count == 1) + iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED; + hd->abortSCpnt = NULL; + break; - /* clear flags and continue. - */ - if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) - hd->abortSCpnt = NULL; + case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS: - /* If an internal command is present - * or the TM failed - reload the FW. - * FC FW may respond FAILED to an ABORT - */ - if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { - if ((hd->cmdPtr) || - (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) { - if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) { - printk((KERN_WARNING - " Firmware Reload FAILED!!\n")); - } - } - } - } else { - dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name)); - - hd->abortSCpnt = NULL; + /* If an internal command is present + * or the TM failed - reload the FW. + * FC FW may respond FAILED to an ABORT + */ + if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED || + hd->cmdPtr) + if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) + printk((KERN_WARNING " Firmware Reload FAILED!!\n")); + break; - } + case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET: + default: + break; } + out: spin_lock_irqsave(&ioc->FreeQlock, flags); hd->tmPending = 0; - spin_unlock_irqrestore(&ioc->FreeQlock, flags); hd->tmState = TM_STATE_NONE; + hd->tm_iocstatus = iocstatus; + spin_unlock_irqrestore(&ioc->FreeQlock, flags); return 1; } -- cgit v1.2.3 From 07c861d6d9ca3dc58e225bcfe2da0f378af6fa6c Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Mon, 29 Jan 2007 09:48:50 -0700 Subject: [SCSI] fusion - bump version - 3.04.04 bump version, and fix email addr for lsi support Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 2 +- drivers/message/fusion/mptbase.h | 6 +++--- drivers/message/fusion/mptctl.c | 2 +- drivers/message/fusion/mptctl.h | 2 +- drivers/message/fusion/mptfc.c | 2 +- drivers/message/fusion/mptlan.c | 1 + drivers/message/fusion/mptlan.h | 1 + drivers/message/fusion/mptsas.c | 2 +- drivers/message/fusion/mptscsih.c | 2 +- drivers/message/fusion/mptscsih.h | 2 +- drivers/message/fusion/mptspi.c | 2 +- 11 files changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index fcbce1c31d04..083acfd91d8b 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -6,7 +6,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 7176944e201c..e3a39272aad6 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -6,7 +6,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -75,8 +75,8 @@ #define COPYRIGHT "Copyright (c) 1999-2007 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.04.03" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.03" +#define MPT_LINUX_VERSION_COMMON "3.04.04" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.04" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 4779ff502e53..b0b80428d110 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -5,7 +5,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h index e65a1cf5eb0b..f7e72c5e47de 100644 --- a/drivers/message/fusion/mptctl.h +++ b/drivers/message/fusion/mptctl.h @@ -6,7 +6,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index cd8fa39ec270..b7d4c7265ec6 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -4,7 +4,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 2936204d8ad6..b691292ff599 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -5,6 +5,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 2000-2007 LSI Logic Corporation + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h index 70ab75e7c263..fe438bf119f6 100644 --- a/drivers/message/fusion/mptlan.h +++ b/drivers/message/fusion/mptlan.h @@ -5,6 +5,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 2000-2007 LSI Logic Corporation + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 9d0f87f4c5e5..84b8b485e95b 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -4,7 +4,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * Copyright (c) 2005-2007 Dell */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 3bc9446ec42d..c417ae0b5fe6 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -4,7 +4,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 43b4f236adf9..843c01a6aa0e 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -6,7 +6,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 5398aeab191d..c31a9e3c8a26 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -4,7 +4,7 @@ * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2007 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -- cgit v1.2.3 From 9abe16c670bd3d4ab5519257514f9f291383d104 Mon Sep 17 00:00:00 2001 From: Kai Makisara Date: Sat, 3 Feb 2007 13:21:29 +0200 Subject: [SCSI] st: fix Tape dies if wrong block size used, bug 7919 On Thu, 1 Feb 2007, Andrew Morton wrote: > On Thu, 1 Feb 2007 15:34:29 -0800 > bugme-daemon@bugzilla.kernel.org wrote: > > > http://bugzilla.kernel.org/show_bug.cgi?id=7919 > > > > Summary: Tape dies if wrong block size used > > Kernel Version: 2.6.20-rc5 > > Status: NEW > > Severity: normal > > Owner: scsi_drivers-other@kernel-bugs.osdl.org > > Submitter: dmartin@sccd.ctc.edu > > > > > > Most recent kernel where this bug did *NOT* occur: 2.6.17.14 > > > > Other Kernels Tested and Results: > > > > OK 2.6.15.7 > > OK 2.6.16.37 > > OK 2.6.17.14 > > BAD 2.6.18.6 > > BAD 2.6.18-1.2869.fc6 > > BAD 2.6.19.2 + > > BAD 2.6.20-rc5 > > > > NOTE: 2.6.18-1.2869.fc6 is a Fedora modified kernel, all others are from kernel.org > > ... > > Steps to reproduce: > > Get a Adaptec AHA-2940U/UW/D / AIC-7881U card and a tape drive, > > install a recent kernel > > set the tape block size - mt setblk 4096 > > read from or write to tape using wrong block size - tar -b 7 -cvf /dev/tape foo > > Write does not trigger this bug because the driver refuses in fixed block mode writes that are not a multiple of the block size. Read does trigger it in my system. The bug is not associated with any specific HBA. st tries to do direct i/o in fixed block mode with reads that are not a multiple of tape block size. The patch in this message fixes the st problem by switching to using the driver buffer up to the next close of the device file in fixed block mode if the user asks for a read like this. I don't know why the bug has surfaced only after 2.6.17 although the st problem is old. There may be another bug in the block subsystem and this patch works around it. However, the patch fixes a problem in st and in this way it is a valid fix. This patch may also fix the bug 7900. The patch compiles and is lightly tested. Signed-off-by: Kai Makisara Signed-off-by: James Bottomley --- drivers/scsi/st.c | 23 +++++++++++++---------- drivers/scsi/st.h | 3 ++- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index e016e0906e1a..fba8b204e310 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -9,7 +9,7 @@ Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky, Michael Schaefer, J"org Weule, and Eric Youngdale. - Copyright 1992 - 2006 Kai Makisara + Copyright 1992 - 2007 Kai Makisara email Kai.Makisara@kolumbus.fi Some small formal changes - aeb, 950809 @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static const char *verstr = "20061107"; +static const char *verstr = "20070203"; #include @@ -1168,6 +1168,7 @@ static int st_open(struct inode *inode, struct file *filp) STps = &(STp->ps[i]); STps->rw = ST_IDLE; } + STp->try_dio_now = STp->try_dio; STp->recover_count = 0; DEB( STp->nbr_waits = STp->nbr_finished = 0; STp->nbr_requests = STp->nbr_dio = STp->nbr_pages = STp->nbr_combinable = 0; ) @@ -1400,9 +1401,9 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf, struct st_buffer *STbp = STp->buffer; if (is_read) - i = STp->try_dio && try_rdio; + i = STp->try_dio_now && try_rdio; else - i = STp->try_dio && try_wdio; + i = STp->try_dio_now && try_wdio; if (i && ((unsigned long)buf & queue_dma_alignment( STp->device->request_queue)) == 0) { @@ -1599,7 +1600,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) STm->do_async_writes && STps->eof < ST_EOM_OK; if (STp->block_size != 0 && STm->do_buffer_writes && - !(STp->try_dio && try_wdio) && STps->eof < ST_EOM_OK && + !(STp->try_dio_now && try_wdio) && STps->eof < ST_EOM_OK && STbp->buffer_bytes < STbp->buffer_size) { STp->dirty = 1; /* Don't write a buffer that is not full enough. */ @@ -1769,7 +1770,7 @@ static long read_tape(struct scsi_tape *STp, long count, if (STp->block_size == 0) blks = bytes = count; else { - if (!(STp->try_dio && try_rdio) && STm->do_read_ahead) { + if (!(STp->try_dio_now && try_rdio) && STm->do_read_ahead) { blks = (STp->buffer)->buffer_blocks; bytes = blks * STp->block_size; } else { @@ -1948,10 +1949,12 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) goto out; STm = &(STp->modes[STp->current_mode]); - if (!(STm->do_read_ahead) && STp->block_size != 0 && - (count % STp->block_size) != 0) { - retval = (-EINVAL); /* Read must be integral number of blocks */ - goto out; + if (STp->block_size != 0 && (count % STp->block_size) != 0) { + if (!STm->do_read_ahead) { + retval = (-EINVAL); /* Read must be integral number of blocks */ + goto out; + } + STp->try_dio_now = 0; /* Direct i/o can't handle split blocks */ } STps = &(STp->ps[STp->partition]); diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h index 05a5cae126ec..50f3deb1f9ed 100644 --- a/drivers/scsi/st.h +++ b/drivers/scsi/st.h @@ -117,7 +117,8 @@ struct scsi_tape { unsigned char cln_sense_value; unsigned char cln_sense_mask; unsigned char use_pf; /* Set Page Format bit in all mode selects? */ - unsigned char try_dio; /* try direct i/o? */ + unsigned char try_dio; /* try direct i/o in general? */ + unsigned char try_dio_now; /* try direct i/o before next close? */ unsigned char c_algo; /* compression algorithm */ unsigned char pos_unknown; /* after reset position unknown */ int tape_type; -- cgit v1.2.3 From 423f7cf467045eab616f97309aed87a54b5e351d Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 30 Jan 2007 12:07:27 -0800 Subject: [SCSI] libsas: Don't BUG when connecting two expanders via wide port libsas: Don't BUG when connecting two expanders via wide port When a device is connected to an expander, the discovery process goes through sas_ex_discover_dev to figure out what's attached to the phy. If it is the case that the phy being discovered happens to be the second phy of a wide link to an expander, that discover_dev function will incorrectly call sas_ex_discover_expander, which creates another sas_port and tries to attach the other sas_phys to the new port, thus triggering a BUG. The correct thing to do is to check the other ex_phys of the expander to see if there's a sas_port for this sas_phy, and attach the sas_phy to the existing sas_port. This is easily triggered if one enables the phys of a wide port between expanders one by one. This second version of the patch fixes a small regression in the case where all the phys show up at once and we accidentally try to attach to a port that hasn't been created yet. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_expander.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index d9b9a008d36d..dc70c180e115 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -678,6 +678,29 @@ static struct domain_device *sas_ex_discover_end_dev( return NULL; } +/* See if this phy is part of a wide port */ +static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id) +{ + struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id]; + int i; + + for (i = 0; i < parent->ex_dev.num_phys; i++) { + struct ex_phy *ephy = &parent->ex_dev.ex_phy[i]; + + if (ephy == phy) + continue; + + if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr, + SAS_ADDR_SIZE) && ephy->port) { + sas_port_add_phy(ephy->port, phy->phy); + phy->phy_state = PHY_DEVICE_DISCOVERED; + return 0; + } + } + + return -ENODEV; +} + static struct domain_device *sas_ex_discover_expander( struct domain_device *parent, int phy_id) { @@ -810,6 +833,13 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) return res; } + res = sas_ex_join_wide_port(dev, phy_id); + if (!res) { + SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", + phy_id, SAS_ADDR(ex_phy->attached_sas_addr)); + return res; + } + switch (ex_phy->attached_dev_type) { case SAS_END_DEV: child = sas_ex_discover_end_dev(dev, phy_id); -- cgit v1.2.3 From a9344e68ac0a656475006737dbc258d69fe4f7b0 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 29 Jan 2007 23:48:19 -0800 Subject: [SCSI] libsas: Add an LU reset mechanism to the error handler After discussion with andmike and dougg, it seems that the purpose of eh_device_reset_handler is to issue LU resets, and that eh_bus_reset_handler would be a more appropriate place for a phy reset. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_scsi_host.c | 40 +++++++++++++++++++++++++++++++++---- include/scsi/libsas.h | 1 + 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index cd2378010c7e..897a5e2c55e4 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -421,8 +421,29 @@ struct sas_phy *find_local_sas_phy(struct domain_device *dev) return exphy->phy; } -/* Attempt to send a target reset message to a device */ +/* Attempt to send a LUN reset message to a device */ int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) +{ + struct domain_device *dev = cmd_to_domain_dev(cmd); + struct sas_internal *i = + to_sas_internal(dev->port->ha->core.shost->transportt); + struct scsi_lun lun; + int res; + + int_to_scsilun(cmd->device->lun, &lun); + + if (!i->dft->lldd_lu_reset) + return FAILED; + + res = i->dft->lldd_lu_reset(dev, lun.scsi_lun); + if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE) + return SUCCESS; + + return FAILED; +} + +/* Attempt to send a phy (bus) reset */ +int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) { struct domain_device *dev = cmd_to_domain_dev(cmd); struct sas_phy *phy = find_local_sas_phy(dev); @@ -430,7 +451,7 @@ int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) res = sas_phy_reset(phy, 1); if (res) - SAS_DPRINTK("Device reset of %s failed 0x%x\n", + SAS_DPRINTK("Bus reset of %s failed 0x%x\n", phy->dev.kobj.k_name, res); if (res == TMF_RESP_FUNC_SUCC || res == TMF_RESP_FUNC_COMPLETE) @@ -443,10 +464,20 @@ int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) static int try_to_reset_cmd_device(struct Scsi_Host *shost, struct scsi_cmnd *cmd) { + int res; + if (!shost->hostt->eh_device_reset_handler) - return FAILED; + goto try_bus_reset; + + res = shost->hostt->eh_device_reset_handler(cmd); + if (res == SUCCESS) + return res; - return shost->hostt->eh_device_reset_handler(cmd); +try_bus_reset: + if (shost->hostt->eh_bus_reset_handler) + return shost->hostt->eh_bus_reset_handler(cmd); + + return FAILED; } static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, @@ -976,3 +1007,4 @@ EXPORT_SYMBOL_GPL(sas_task_abort); EXPORT_SYMBOL_GPL(sas_phy_reset); EXPORT_SYMBOL_GPL(sas_phy_enable); EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); +EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index b200233cc6f4..8516ba68cc95 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -661,5 +661,6 @@ void sas_init_dev(struct domain_device *); void sas_task_abort(struct sas_task *); int __sas_task_abort(struct sas_task *); int sas_eh_device_reset_handler(struct scsi_cmnd *cmd); +int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd); #endif /* _SASLIB_H_ */ -- cgit v1.2.3 From 058e2c474897dc53c88ac9162f9a9b16a879b8cd Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 29 Jan 2007 23:48:22 -0800 Subject: [SCSI] aic94xx: Remove TMF result code munging In asd_initiate_ssp_tmf, the TMF result code is replaced with TMF_RESP_FUNC_FAILED except when the TMF returns a result code immediately. However, TMFs can return result codes via an ESCB... yet these codes are also replaced with "FAILED". The only values that can fall into that case are TMF_* codes anyway, so get rid of this code where COMPLETE and SUCCESS are turned into FAILED. This also lets us propagate those TMF_* codes up to the caller. Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_tmf.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c index fd5269e086a6..9a14a6d97275 100644 --- a/drivers/scsi/aic94xx/aic94xx_tmf.c +++ b/drivers/scsi/aic94xx/aic94xx_tmf.c @@ -566,14 +566,7 @@ static int asd_initiate_ssp_tmf(struct domain_device *dev, u8 *lun, res = TMF_RESP_FUNC_ESUPP; break; default: - if (tmf == TMF_QUERY_TASK) { - ASD_DPRINTK("%s: QUERY_SSP_TASK response: 0x%x\n", - __FUNCTION__, res); - break; - } - ASD_DPRINTK("%s: converting result 0x%x to TMF_RESP_FUNC_FAILED\n", - __FUNCTION__, res); - res = TMF_RESP_FUNC_FAILED; + /* Allow TMF response codes to propagate upwards */ break; } out_err: -- cgit v1.2.3 From 214fbb75075efa677b614be79a2d62dd79785b4f Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 29 Jan 2007 23:48:25 -0800 Subject: [SCSI] aic94xx: Add default bus reset handler Signed-off-by: Darrick J. Wong Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 3aa568fbdbf7..bc7744e35ad0 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -80,6 +80,7 @@ static struct scsi_host_template aic94xx_sht = { .max_sectors = SCSI_DEFAULT_MAX_SECTORS, .use_clustering = ENABLE_CLUSTERING, .eh_device_reset_handler = sas_eh_device_reset_handler, + .eh_bus_reset_handler = sas_eh_bus_reset_handler, }; static int __devinit asd_map_memio(struct asd_ha_struct *asd_ha) -- cgit v1.2.3 From 292148f8bb2b5d120440e046d24de07a739461aa Mon Sep 17 00:00:00 2001 From: Brian King Date: Tue, 30 Jan 2007 17:51:17 -0600 Subject: [SCSI] scsi_error: Fix lost EH commands If an EH command times out today, the LLDD's abort handler will be called to abort the command. It is assumed that this completes successfully, which can result in the command getting completed later resulting in an oops. Improve the current implementation by escalating all the way to host reset if necessary in order to clean up the EH command. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 239 ++++++++++++++++++++++++---------------------- 1 file changed, 123 insertions(+), 116 deletions(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 2dce06a58c08..b8edcf5b5451 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -457,6 +457,128 @@ static void scsi_eh_done(struct scsi_cmnd *scmd) complete(eh_action); } +/** + * scsi_try_host_reset - ask host adapter to reset itself + * @scmd: SCSI cmd to send hsot reset. + **/ +static int scsi_try_host_reset(struct scsi_cmnd *scmd) +{ + unsigned long flags; + int rtn; + + SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n", + __FUNCTION__)); + + if (!scmd->device->host->hostt->eh_host_reset_handler) + return FAILED; + + rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd); + + if (rtn == SUCCESS) { + if (!scmd->device->host->hostt->skip_settle_delay) + ssleep(HOST_RESET_SETTLE_TIME); + spin_lock_irqsave(scmd->device->host->host_lock, flags); + scsi_report_bus_reset(scmd->device->host, + scmd_channel(scmd)); + spin_unlock_irqrestore(scmd->device->host->host_lock, flags); + } + + return rtn; +} + +/** + * scsi_try_bus_reset - ask host to perform a bus reset + * @scmd: SCSI cmd to send bus reset. + **/ +static int scsi_try_bus_reset(struct scsi_cmnd *scmd) +{ + unsigned long flags; + int rtn; + + SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n", + __FUNCTION__)); + + if (!scmd->device->host->hostt->eh_bus_reset_handler) + return FAILED; + + rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd); + + if (rtn == SUCCESS) { + if (!scmd->device->host->hostt->skip_settle_delay) + ssleep(BUS_RESET_SETTLE_TIME); + spin_lock_irqsave(scmd->device->host->host_lock, flags); + scsi_report_bus_reset(scmd->device->host, + scmd_channel(scmd)); + spin_unlock_irqrestore(scmd->device->host->host_lock, flags); + } + + return rtn; +} + +/** + * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev + * @scmd: SCSI cmd used to send BDR + * + * Notes: + * There is no timeout for this operation. if this operation is + * unreliable for a given host, then the host itself needs to put a + * timer on it, and set the host back to a consistent state prior to + * returning. + **/ +static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd) +{ + int rtn; + + if (!scmd->device->host->hostt->eh_device_reset_handler) + return FAILED; + + rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd); + if (rtn == SUCCESS) { + scmd->device->was_reset = 1; + scmd->device->expecting_cc_ua = 1; + } + + return rtn; +} + +static int __scsi_try_to_abort_cmd(struct scsi_cmnd *scmd) +{ + if (!scmd->device->host->hostt->eh_abort_handler) + return FAILED; + + return scmd->device->host->hostt->eh_abort_handler(scmd); +} + +/** + * scsi_try_to_abort_cmd - Ask host to abort a running command. + * @scmd: SCSI cmd to abort from Lower Level. + * + * Notes: + * This function will not return until the user's completion function + * has been called. there is no timeout on this operation. if the + * author of the low-level driver wishes this operation to be timed, + * they can provide this facility themselves. helper functions in + * scsi_error.c can be supplied to make this easier to do. + **/ +static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd) +{ + /* + * scsi_done was called just after the command timed out and before + * we had a chance to process it. (db) + */ + if (scmd->serial_number == 0) + return SUCCESS; + return __scsi_try_to_abort_cmd(scmd); +} + +static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) +{ + if (__scsi_try_to_abort_cmd(scmd) != SUCCESS) + if (scsi_try_bus_device_reset(scmd) != SUCCESS) + if (scsi_try_bus_reset(scmd) != SUCCESS) + scsi_try_host_reset(scmd); +} + /** * scsi_send_eh_cmnd - submit a scsi command as part of error recory * @scmd: SCSI command structure to hijack @@ -584,13 +706,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, break; } } else { - /* - * FIXME(eric) - we are not tracking whether we could - * abort a timed out command or not. not sure how - * we should treat them differently anyways. - */ - if (shost->hostt->eh_abort_handler) - shost->hostt->eh_abort_handler(scmd); + scsi_abort_eh_cmnd(scmd); rtn = FAILED; } @@ -722,31 +838,6 @@ int scsi_eh_get_sense(struct list_head *work_q, } EXPORT_SYMBOL_GPL(scsi_eh_get_sense); -/** - * scsi_try_to_abort_cmd - Ask host to abort a running command. - * @scmd: SCSI cmd to abort from Lower Level. - * - * Notes: - * This function will not return until the user's completion function - * has been called. there is no timeout on this operation. if the - * author of the low-level driver wishes this operation to be timed, - * they can provide this facility themselves. helper functions in - * scsi_error.c can be supplied to make this easier to do. - **/ -static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd) -{ - if (!scmd->device->host->hostt->eh_abort_handler) - return FAILED; - - /* - * scsi_done was called just after the command timed out and before - * we had a chance to process it. (db) - */ - if (scmd->serial_number == 0) - return SUCCESS; - return scmd->device->host->hostt->eh_abort_handler(scmd); -} - /** * scsi_eh_tur - Send TUR to device. * @scmd: Scsi cmd to send TUR @@ -820,32 +911,6 @@ static int scsi_eh_abort_cmds(struct list_head *work_q, return list_empty(work_q); } -/** - * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev - * @scmd: SCSI cmd used to send BDR - * - * Notes: - * There is no timeout for this operation. if this operation is - * unreliable for a given host, then the host itself needs to put a - * timer on it, and set the host back to a consistent state prior to - * returning. - **/ -static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd) -{ - int rtn; - - if (!scmd->device->host->hostt->eh_device_reset_handler) - return FAILED; - - rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd); - if (rtn == SUCCESS) { - scmd->device->was_reset = 1; - scmd->device->expecting_cc_ua = 1; - } - - return rtn; -} - /** * scsi_eh_try_stu - Send START_UNIT to device. * @scmd: Scsi cmd to send START_UNIT @@ -976,64 +1041,6 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost, return list_empty(work_q); } -/** - * scsi_try_bus_reset - ask host to perform a bus reset - * @scmd: SCSI cmd to send bus reset. - **/ -static int scsi_try_bus_reset(struct scsi_cmnd *scmd) -{ - unsigned long flags; - int rtn; - - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n", - __FUNCTION__)); - - if (!scmd->device->host->hostt->eh_bus_reset_handler) - return FAILED; - - rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd); - - if (rtn == SUCCESS) { - if (!scmd->device->host->hostt->skip_settle_delay) - ssleep(BUS_RESET_SETTLE_TIME); - spin_lock_irqsave(scmd->device->host->host_lock, flags); - scsi_report_bus_reset(scmd->device->host, - scmd_channel(scmd)); - spin_unlock_irqrestore(scmd->device->host->host_lock, flags); - } - - return rtn; -} - -/** - * scsi_try_host_reset - ask host adapter to reset itself - * @scmd: SCSI cmd to send hsot reset. - **/ -static int scsi_try_host_reset(struct scsi_cmnd *scmd) -{ - unsigned long flags; - int rtn; - - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n", - __FUNCTION__)); - - if (!scmd->device->host->hostt->eh_host_reset_handler) - return FAILED; - - rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd); - - if (rtn == SUCCESS) { - if (!scmd->device->host->hostt->skip_settle_delay) - ssleep(HOST_RESET_SETTLE_TIME); - spin_lock_irqsave(scmd->device->host->host_lock, flags); - scsi_report_bus_reset(scmd->device->host, - scmd_channel(scmd)); - spin_unlock_irqrestore(scmd->device->host->host_lock, flags); - } - - return rtn; -} - /** * scsi_eh_bus_reset - send a bus reset * @shost: scsi host being recovered. -- cgit v1.2.3 From 083d1631be7c36309359792ecf61aaf88559043f Mon Sep 17 00:00:00 2001 From: "Wu, Gilbert" Date: Tue, 30 Jan 2007 15:31:25 -0800 Subject: [SCSI] aic94xx: update for v28 firmware These changes work compatibly with the old V17 firmware Contribution: Ed Chim Gilbert Wu Change Log: 1. Use dword instead of qword to display the value of Connection State register for debug purpose. 2. There are some registers location of AIC94xx chip has been changed according to the new V28 firmware. The patch has redefined the register location and provided initialization. 3. The new sequencer firmware v28 for Aic94xx SAS/SATA Linux open source device driver can be downloaded from http://www.adaptec.com/NR/exeres/35B611BC-9789-4B5B-82C6-85A2CCA8A46A.htm Signed-off-by: Gilbert Wu Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_dump.c | 2 +- drivers/scsi/aic94xx/aic94xx_reg_def.h | 5 +++-- drivers/scsi/aic94xx/aic94xx_seq.c | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/aic94xx/aic94xx_dump.c b/drivers/scsi/aic94xx/aic94xx_dump.c index e6ade5996d95..6bd8e3059d27 100644 --- a/drivers/scsi/aic94xx/aic94xx_dump.c +++ b/drivers/scsi/aic94xx/aic94xx_dump.c @@ -556,7 +556,7 @@ static void asd_dump_lseq_state(struct asd_ha_struct *asd_ha, int lseq) PRINT_LMIP_word(asd_ha, lseq, Q_TGTXFR_TAIL); PRINT_LMIP_byte(asd_ha, lseq, LINK_NUMBER); PRINT_LMIP_byte(asd_ha, lseq, SCRATCH_FLAGS); - PRINT_LMIP_qword(asd_ha, lseq, CONNECTION_STATE); + PRINT_LMIP_dword(asd_ha, lseq, CONNECTION_STATE); PRINT_LMIP_word(asd_ha, lseq, CONCTL); PRINT_LMIP_byte(asd_ha, lseq, CONSTAT); PRINT_LMIP_byte(asd_ha, lseq, CONNECTION_MODES); diff --git a/drivers/scsi/aic94xx/aic94xx_reg_def.h b/drivers/scsi/aic94xx/aic94xx_reg_def.h index a11f4e6d8bd9..a43e8cdf4ee4 100644 --- a/drivers/scsi/aic94xx/aic94xx_reg_def.h +++ b/drivers/scsi/aic94xx/aic94xx_reg_def.h @@ -2226,9 +2226,10 @@ #define LmSEQ_SAS_RESET_MODE(LinkNum) (LmSCRATCH(LinkNum) + 0x0074) #define LmSEQ_LINK_RESET_RETRY_COUNT(LinkNum) (LmSCRATCH(LinkNum) + 0x0075) #define LmSEQ_NUM_LINK_RESET_RETRIES(LinkNum) (LmSCRATCH(LinkNum) + 0x0076) -#define LmSEQ_OOB_INT_ENABLES(LinkNum) (LmSCRATCH(LinkNum) + 0x007A) +#define LmSEQ_OOB_INT_ENABLES(LinkNum) (LmSCRATCH(LinkNum) + 0x0078) +#define LmSEQ_NOTIFY_TIMER_DOWN_COUNT(LinkNum) (LmSCRATCH(LinkNum) + 0x007A) #define LmSEQ_NOTIFY_TIMER_TIMEOUT(LinkNum) (LmSCRATCH(LinkNum) + 0x007C) -#define LmSEQ_NOTIFY_TIMER_DOWN_COUNT(LinkNum) (LmSCRATCH(LinkNum) + 0x007E) +#define LmSEQ_NOTIFY_TIMER_INITIAL_COUNT(LinkNum) (LmSCRATCH(LinkNum) + 0x007E) /* Mode dependent scratch page 1, mode 0 and mode 1 */ #define LmSEQ_SG_LIST_PTR_ADDR0(LinkNum) (LmSCRATCH(LinkNum) + 0x0020) diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c index 2768fe4d66ba..eae7a247bece 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.c +++ b/drivers/scsi/aic94xx/aic94xx_seq.c @@ -810,6 +810,8 @@ static void asd_init_lseq_mdp(struct asd_ha_struct *asd_ha, int lseq) /* No delay for the first NOTIFY to be sent to the attached target. */ asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_DOWN_COUNT(lseq), ASD_NOTIFY_DOWN_COUNT); + asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_INITIAL_COUNT(lseq), + ASD_NOTIFY_DOWN_COUNT); /* LSEQ Mode dependent, mode 0 and 1, page 1 setup. */ for (i = 0; i < 2; i++) { -- cgit v1.2.3 From 44746438973e4f9ed9bdf3347e75f60f105b325a Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 1 Feb 2007 16:43:07 -0800 Subject: [SCSI] Buslogic: local_irq_disable() is redundant after local_irq_save() drivers/scsi/BusLogic.c::BusLogic_Command() contains local_irq_disable() call after local_irq_save(). This looks redundant. Signed-off-by: Jiri Kosina Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/BusLogic.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 3075204915c8..6272ec2125ec 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -362,10 +362,8 @@ static int BusLogic_Command(struct BusLogic_HostAdapter *HostAdapter, enum BusLo interrupt could occur if the IRQ Channel was previously enabled by another BusLogic Host Adapter or another driver sharing the same IRQ Channel. */ - if (!HostAdapter->IRQ_ChannelAcquired) { + if (!HostAdapter->IRQ_ChannelAcquired) local_irq_save(ProcessorFlags); - local_irq_disable(); - } /* Wait for the Host Adapter Ready bit to be set and the Command/Parameter Register Busy bit to be reset in the Status Register. -- cgit v1.2.3 From 22cfefb56b53103a99908ec63311e61c217eaffe Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 5 Feb 2007 16:39:03 -0800 Subject: [SCSI] scsi_kmap_atomic_sg(): check that local irqs are disabled The KM_BIO_SRC_IRQ kmap slot must be taken with local irqs disabled. Add a check into scsi for this. Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 503f09c2f05f..0f9b6c275417 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2250,6 +2250,8 @@ void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, size_t sg_len = 0, len_complete = 0; struct page *page; + WARN_ON(!irqs_disabled()); + for (i = 0; i < sg_count; i++) { len_complete = sg_len; /* Complete sg-entries */ sg_len += sg[i].length; -- cgit v1.2.3 From 0a361e31864f0822671703963f52957b3f275b93 Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Mon, 5 Feb 2007 16:38:55 -0800 Subject: [SCSI] DAC960: kmalloc->kzalloc/Casting cleanups A patch to switch kmalloc->kzalloc and to clean unneeded kammloc, pci_alloc_consistent casts Signed-off-by: Ahmed Darwish Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/block/DAC960.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 8d81a3a64c07..7c72f104567e 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -1373,8 +1373,7 @@ static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T Controller->BounceBufferLimit = DAC690_V2_PciDmaMask; /* This is a temporary dma mapping, used only in the scope of this function */ - CommandMailbox = - (DAC960_V2_CommandMailbox_T *)pci_alloc_consistent( PCI_Device, + CommandMailbox = pci_alloc_consistent(PCI_Device, sizeof(DAC960_V2_CommandMailbox_T), &CommandMailboxDMA); if (CommandMailbox == NULL) return false; @@ -1879,8 +1878,8 @@ static boolean DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T if (NewLogicalDeviceInfo->LogicalDeviceState != DAC960_V2_LogicalDevice_Offline) Controller->LogicalDriveInitiallyAccessible[LogicalDeviceNumber] = true; - LogicalDeviceInfo = (DAC960_V2_LogicalDeviceInfo_T *) - kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), GFP_ATOMIC); + LogicalDeviceInfo = kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), + GFP_ATOMIC); if (LogicalDeviceInfo == NULL) return DAC960_Failure(Controller, "LOGICAL DEVICE ALLOCATION"); Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber] = @@ -2113,8 +2112,8 @@ static boolean DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T if (!DAC960_V2_NewPhysicalDeviceInfo(Controller, Channel, TargetID, LogicalUnit)) break; - PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *) - kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC); + PhysicalDeviceInfo = kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), + GFP_ATOMIC); if (PhysicalDeviceInfo == NULL) return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION"); Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex] = @@ -2122,8 +2121,8 @@ static boolean DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T memcpy(PhysicalDeviceInfo, NewPhysicalDeviceInfo, sizeof(DAC960_V2_PhysicalDeviceInfo_T)); - InquiryUnitSerialNumber = (DAC960_SCSI_Inquiry_UnitSerialNumber_T *) - kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC); + InquiryUnitSerialNumber = kmalloc( + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC); if (InquiryUnitSerialNumber == NULL) { kfree(PhysicalDeviceInfo); return DAC960_Failure(Controller, "SERIAL NUMBER ALLOCATION"); @@ -4949,8 +4948,8 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command) PhysicalDevice.LogicalUnit = NewLogicalDeviceInfo->LogicalUnit; Controller->V2.LogicalDriveToVirtualDevice[LogicalDeviceNumber] = PhysicalDevice; - LogicalDeviceInfo = (DAC960_V2_LogicalDeviceInfo_T *) - kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), GFP_ATOMIC); + LogicalDeviceInfo = kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), + GFP_ATOMIC); Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber] = LogicalDeviceInfo; DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " @@ -5709,14 +5708,14 @@ static boolean DAC960_CheckStatusBuffer(DAC960_Controller_T *Controller, unsigned int NewStatusBufferLength = DAC960_InitialStatusBufferSize; while (NewStatusBufferLength < ByteCount) NewStatusBufferLength *= 2; - Controller->CombinedStatusBuffer = - (unsigned char *) kmalloc(NewStatusBufferLength, GFP_ATOMIC); + Controller->CombinedStatusBuffer = kmalloc(NewStatusBufferLength, + GFP_ATOMIC); if (Controller->CombinedStatusBuffer == NULL) return false; Controller->CombinedStatusBufferLength = NewStatusBufferLength; return true; } - NewStatusBuffer = (unsigned char *) - kmalloc(2 * Controller->CombinedStatusBufferLength, GFP_ATOMIC); + NewStatusBuffer = kmalloc(2 * Controller->CombinedStatusBufferLength, + GFP_ATOMIC); if (NewStatusBuffer == NULL) { DAC960_Warning("Unable to expand Combined Status Buffer - Truncating\n", -- cgit v1.2.3 From a76106afbeb0c7d50762e7e5239496e5f7a0a074 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 5 Feb 2007 16:38:27 -0800 Subject: [SCSI] aic79xx: make ahd_match_scb() static Signed-off-by: Adrian Bunk Acked-by: Hannes Reinecke Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx.h | 3 --- drivers/scsi/aic7xxx/aic79xx_core.c | 5 ++++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 170a4344cbb2..27adbb294ac1 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -1337,9 +1337,6 @@ int ahd_pci_test_register_access(struct ahd_softc *); /************************** SCB and SCB queue management **********************/ void ahd_qinfifo_requeue_tail(struct ahd_softc *ahd, struct scb *scb); -int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, - int target, char channel, int lun, - u_int tag, role_t role); /****************************** Initialization ********************************/ struct ahd_softc *ahd_alloc(void *platform_arg, char *name); diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 07a86a30f676..9ddc6e4a74b0 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -262,6 +262,9 @@ static void ahd_update_coalescing_values(struct ahd_softc *ahd, u_int mincmds); static int ahd_verify_vpd_cksum(struct vpd_config *vpd); static int ahd_wait_seeprom(struct ahd_softc *ahd); +static int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, + int target, char channel, int lun, + u_int tag, role_t role); /******************************** Private Inlines *****************************/ @@ -7256,7 +7259,7 @@ ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, u_int scbid) } /************************** SCB and SCB queue management **********************/ -int +static int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target, char channel, int lun, u_int tag, role_t role) { -- cgit v1.2.3 From af0db3a8ab9917e9a0184470a2995dd8fe66c6e2 Mon Sep 17 00:00:00 2001 From: Michal Piotrowski Date: Mon, 5 Feb 2007 16:38:36 -0800 Subject: [SCSI] nsp_cs: remove old scsi code Signed-off-by: Michal Piotrowski Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/pcmcia/nsp_cs.h | 66 -------------------------------------------- 1 file changed, 66 deletions(-) diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h index 625ca97da52d..9102cbdf1359 100644 --- a/drivers/scsi/pcmcia/nsp_cs.h +++ b/drivers/scsi/pcmcia/nsp_cs.h @@ -290,7 +290,6 @@ typedef struct _nsp_hw_data { #endif } nsp_hw_data; - /**************************************************************************** * */ @@ -302,22 +301,13 @@ static int nsp_cs_config (struct pcmcia_device *link); /* Linux SCSI subsystem specific functions */ static struct Scsi_Host *nsp_detect (struct scsi_host_template *sht); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -static int nsp_detect_old (struct scsi_host_template *sht); -static int nsp_release_old(struct Scsi_Host *shpnt); -#endif static const char *nsp_info (struct Scsi_Host *shpnt); static int nsp_proc_info ( -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) struct Scsi_Host *host, -#endif char *buffer, char **start, off_t offset, int length, -#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) - int hostno, -#endif int inout); static int nsp_queuecommand(struct scsi_cmnd *SCpnt, void (* done)(struct scsi_cmnd *SCpnt)); @@ -356,7 +346,6 @@ static struct Scsi_Host *nsp_detect(struct scsi_host_template *sht); static int __init nsp_cs_init(void); static void __exit nsp_cs_exit(void); - /* Debug */ #ifdef NSP_DEBUG static void show_command (struct scsi_cmnd *SCpnt); @@ -401,7 +390,6 @@ enum _burst_mode { BURST_MEM32 = 2, }; - /************************************************************************** * SCSI messaage */ @@ -413,62 +401,8 @@ enum _burst_mode { #define MSG_EXT_SDTR 0x01 - -/************************************************************************** - * Compatibility functions - */ - -/* for Kernel 2.4 */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) -# define scsi_register_host(template) scsi_register_module(MODULE_SCSI_HA, template) -# define scsi_unregister_host(template) scsi_unregister_module(MODULE_SCSI_HA, template) -# define scsi_host_put(host) scsi_unregister(host) - -typedef void irqreturn_t; -# define IRQ_NONE /* */ -# define IRQ_HANDLED /* */ -# define IRQ_RETVAL(x) /* */ - -/* This is ad-hoc version of scsi_host_get_next() */ -static inline struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *host) -{ - if (host == NULL) { - return scsi_hostlist; - } else { - return host->next; - } -} - -/* This is ad-hoc version of scsi_host_hn_get() */ -static inline struct Scsi_Host *scsi_host_hn_get(unsigned short hostno) -{ - struct Scsi_Host *host; - - for (host = scsi_host_get_next(NULL); host != NULL; - host = scsi_host_get_next(host)) { - if (host->host_no == hostno) { - break; - } - } - - return host; -} - -static void cs_error(struct pcmcia_device *handle, int func, int ret) -{ - error_info_t err = { func, ret }; - pcmcia_report_error(handle, &err); -} - -/* scatter-gather table */ -# define BUFFER_ADDR (SCpnt->SCp.buffer->address) -#endif - -/* for Kernel 2.6 */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) /* scatter-gather table */ # define BUFFER_ADDR ((char *)((unsigned int)(SCpnt->SCp.buffer->page) + SCpnt->SCp.buffer->offset)) -#endif #endif /*__nsp_cs__*/ /* end */ -- cgit v1.2.3 From a84cb1e82dc4ada9f93e708fa606fa918710a338 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Mon, 5 Feb 2007 16:38:53 -0800 Subject: [SCSI] 53c7xx: brackets fix in uncompiled code Signed-off-by: Mariusz Kozlowski Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/53c7xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c index 640536ef77dc..b432fd20dad2 100644 --- a/drivers/scsi/53c7xx.c +++ b/drivers/scsi/53c7xx.c @@ -4400,7 +4400,7 @@ abort_connected (struct Scsi_Host *host) { * account the current synchronous offset) */ - sstat = (NCR53c8x0_read8 (SSTAT2_REG); + sstat = NCR53c8x0_read8 (SSTAT2_REG); offset = OFFSET (sstat & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT; phase = sstat & SSTAT2_PHASE_MASK; @@ -5423,7 +5423,7 @@ insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) { --buffers, offset += segment->length, ++segment) #if 0 printk("scsi%d: comparing 0x%p to 0x%p\n", - cmd->device->host->host_no, saved, page_address(segment->page+segment->offset); + cmd->device->host->host_no, saved, page_address(segment->page+segment->offset)); #else ; #endif -- cgit v1.2.3 From 35d6848322364b396484b5fcc450f6b009a3dac4 Mon Sep 17 00:00:00 2001 From: Ken Witherow Date: Mon, 5 Feb 2007 16:38:28 -0800 Subject: [SCSI] advansys: clean up warnings Fix typecast warnings and switch from check_region to request_region (akpm: Ken and Jeffrey Phillips Freeman are possible advansys testers) Signed-off-by: Ken Witherow Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/advansys.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 306bec355e45..9b3303b64113 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -4403,7 +4403,7 @@ advansys_detect(struct scsi_host_template *tpnt) ASC_DBG1(1, "advansys_detect: probing I/O port 0x%x...\n", iop); - if (check_region(iop, ASC_IOADR_GAP) != 0) { + if (!request_region(iop, ASC_IOADR_GAP, "advansys")){ printk( "AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop); /* Don't try this I/O port twice. */ @@ -4413,6 +4413,7 @@ advansys_detect(struct scsi_host_template *tpnt) printk( "AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop); /* Don't try this I/O port twice. */ + release_region(iop, ASC_IOADR_GAP); asc_ioport[ioport] = 0; goto ioport_try_again; } else { @@ -4431,6 +4432,7 @@ advansys_detect(struct scsi_host_template *tpnt) * 'ioport' past this board. */ ioport++; + release_region(iop, ASC_IOADR_GAP); goto ioport_try_again; } } @@ -9740,13 +9742,14 @@ AscSearchIOPortAddr11( } for (; i < ASC_IOADR_TABLE_MAX_IX; i++) { iop_base = _asc_def_iop_base[i]; - if (check_region(iop_base, ASC_IOADR_GAP) != 0) { + if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")){ ASC_DBG1(1, "AscSearchIOPortAddr11: check_region() failed I/O port 0x%x\n", iop_base); continue; } ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port 0x%x\n", iop_base); + release_region(iop_base, ASC_IOADR_GAP); if (AscFindSignature(iop_base)) { return (iop_base); } -- cgit v1.2.3 From 2065e310cc116e4b2b0f42faaf27f0c9baaca9cd Mon Sep 17 00:00:00 2001 From: Richard Knutsson Date: Mon, 5 Feb 2007 16:39:01 -0800 Subject: [SCSI] BusLogic: Replace 'boolean' by 'bool' Signed-off-by: Richard Knutsson Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/BusLogic.c | 42 +++---- drivers/scsi/BusLogic.h | 300 +++++++++++++++++++++++----------------------- drivers/scsi/FlashPoint.c | 4 +- 3 files changed, 170 insertions(+), 176 deletions(-) diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 6272ec2125ec..e874b8944875 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -192,7 +192,7 @@ static void BusLogic_InitializeCCBs(struct BusLogic_HostAdapter *HostAdapter, vo BusLogic_CreateInitialCCBs allocates the initial CCBs for Host Adapter. */ -static boolean __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *HostAdapter) +static bool __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *HostAdapter) { int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB); void *BlockPointer; @@ -238,7 +238,7 @@ static void BusLogic_DestroyCCBs(struct BusLogic_HostAdapter *HostAdapter) multiple host adapters share the same IRQ Channel. */ -static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, int AdditionalCCBs, boolean SuccessMessageP) +static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, int AdditionalCCBs, bool SuccessMessageP) { int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB); int PreviouslyAllocated = HostAdapter->AllocatedCCBs; @@ -637,9 +637,9 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd struct BusLogic_ProbeInfo *PrimaryProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount]; int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1; int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0; - boolean ForceBusDeviceScanningOrder = false; - boolean ForceBusDeviceScanningOrderChecked = false; - boolean StandardAddressSeen[6]; + bool ForceBusDeviceScanningOrder = false; + bool ForceBusDeviceScanningOrderChecked = false; + bool StandardAddressSeen[6]; struct pci_dev *PCI_Device = NULL; int i; if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) @@ -1009,7 +1009,7 @@ static void __init BusLogic_InitializeProbeInfoList(struct BusLogic_HostAdapter BusLogic_Failure prints a standardized error message, and then returns false. */ -static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char *ErrorMessage) +static bool BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char *ErrorMessage) { BusLogic_AnnounceDriver(HostAdapter); if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus) { @@ -1028,7 +1028,7 @@ static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char * BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter. */ -static boolean __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAdapter) +static bool __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAdapter) { union BusLogic_StatusRegister StatusRegister; union BusLogic_InterruptRegister InterruptRegister; @@ -1099,8 +1099,8 @@ static boolean __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *Hos SCSI Bus Reset. */ -static boolean BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter - *HostAdapter, boolean HardReset) +static bool BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter + *HostAdapter, bool HardReset) { union BusLogic_StatusRegister StatusRegister; int TimeoutCounter; @@ -1203,11 +1203,11 @@ static boolean BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter Host Adapter. */ -static boolean __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *HostAdapter) +static bool __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *HostAdapter) { struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation; unsigned char RequestedReplyLength; - boolean Result = true; + bool Result = true; /* FlashPoint Host Adapters do not require this protection. */ @@ -1237,7 +1237,7 @@ static boolean __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *Hos from Host Adapter and initializes the Host Adapter structure. */ -static boolean __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_HostAdapter +static bool __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_HostAdapter *HostAdapter) { struct BusLogic_BoardID BoardID; @@ -1684,14 +1684,14 @@ static boolean __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_Host Host Adapter. */ -static boolean __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_HostAdapter +static bool __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_HostAdapter *HostAdapter) { unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1; unsigned short SynchronousPermitted, FastPermitted; unsigned short UltraPermitted, WidePermitted; unsigned short DisconnectPermitted, TaggedQueuingPermitted; - boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth; + bool CommonSynchronousNegotiation, CommonTaggedQueueDepth; char SynchronousString[BusLogic_MaxTargetDevices + 1]; char WideString[BusLogic_MaxTargetDevices + 1]; char DisconnectString[BusLogic_MaxTargetDevices + 1]; @@ -1833,7 +1833,7 @@ static boolean __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_Ho Host Adapter. */ -static boolean __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *HostAdapter) +static bool __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *HostAdapter) { if (HostAdapter->IRQ_Channel == 0) { BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n", HostAdapter); @@ -1901,7 +1901,7 @@ static void BusLogic_ReleaseResources(struct BusLogic_HostAdapter *HostAdapter) of the Host Adapter from its initial power on or hard reset state. */ -static boolean BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter +static bool BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter *HostAdapter) { struct BusLogic_ExtendedMailboxRequest ExtendedMailboxRequest; @@ -2000,7 +2000,7 @@ static boolean BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter through Host Adapter. */ -static boolean __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter +static bool __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter *HostAdapter) { u16 InstalledDevices; @@ -2737,7 +2737,7 @@ static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, void *DeviceIdenti already have been acquired by the caller. */ -static boolean BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter +static bool BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter *HostAdapter, enum BusLogic_ActionCode ActionCode, struct BusLogic_CCB *CCB) { struct BusLogic_OutgoingMailbox *NextOutgoingMailbox; @@ -3056,7 +3056,7 @@ static int BusLogic_AbortCommand(struct scsi_cmnd *Command) currently executing SCSI Commands as having been Reset. */ -static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, boolean HardReset) +static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, bool HardReset) { struct BusLogic_CCB *CCB; int TargetID; @@ -3307,7 +3307,7 @@ Target Requested Completed Requested Completed Requested Completed\n\ static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel, char *Format, struct BusLogic_HostAdapter *HostAdapter, ...) { static char Buffer[BusLogic_LineBufferSize]; - static boolean BeginningOfLine = true; + static bool BeginningOfLine = true; va_list Arguments; int Length = 0; va_start(Arguments, HostAdapter); @@ -3345,7 +3345,7 @@ static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel, char *Form and updates the pointer if the keyword is recognized and false otherwise. */ -static boolean __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword) +static bool __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword) { char *Pointer = *StringPointer; while (*Keyword != '\0') { diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h index cca6d45eee4d..bfbfb5c3a8f6 100644 --- a/drivers/scsi/BusLogic.h +++ b/drivers/scsi/BusLogic.h @@ -233,12 +233,6 @@ enum BusLogic_BIOS_DiskGeometryTranslation { } PACKED; -/* - Define a Boolean data type. -*/ - -typedef bool boolean; - /* Define a 10^18 Statistics Byte Counter data type. */ @@ -269,19 +263,19 @@ struct BusLogic_ProbeInfo { */ struct BusLogic_ProbeOptions { - boolean NoProbe:1; /* Bit 0 */ - boolean NoProbeISA:1; /* Bit 1 */ - boolean NoProbePCI:1; /* Bit 2 */ - boolean NoSortPCI:1; /* Bit 3 */ - boolean MultiMasterFirst:1; /* Bit 4 */ - boolean FlashPointFirst:1; /* Bit 5 */ - boolean LimitedProbeISA:1; /* Bit 6 */ - boolean Probe330:1; /* Bit 7 */ - boolean Probe334:1; /* Bit 8 */ - boolean Probe230:1; /* Bit 9 */ - boolean Probe234:1; /* Bit 10 */ - boolean Probe130:1; /* Bit 11 */ - boolean Probe134:1; /* Bit 12 */ + bool NoProbe:1; /* Bit 0 */ + bool NoProbeISA:1; /* Bit 1 */ + bool NoProbePCI:1; /* Bit 2 */ + bool NoSortPCI:1; /* Bit 3 */ + bool MultiMasterFirst:1;/* Bit 4 */ + bool FlashPointFirst:1; /* Bit 5 */ + bool LimitedProbeISA:1; /* Bit 6 */ + bool Probe330:1; /* Bit 7 */ + bool Probe334:1; /* Bit 8 */ + bool Probe230:1; /* Bit 9 */ + bool Probe234:1; /* Bit 10 */ + bool Probe130:1; /* Bit 11 */ + bool Probe134:1; /* Bit 12 */ }; /* @@ -289,10 +283,10 @@ struct BusLogic_ProbeOptions { */ struct BusLogic_GlobalOptions { - boolean TraceProbe:1; /* Bit 0 */ - boolean TraceHardwareReset:1; /* Bit 1 */ - boolean TraceConfiguration:1; /* Bit 2 */ - boolean TraceErrors:1; /* Bit 3 */ + bool TraceProbe:1; /* Bit 0 */ + bool TraceHardwareReset:1; /* Bit 1 */ + bool TraceConfiguration:1; /* Bit 2 */ + bool TraceErrors:1; /* Bit 3 */ }; /* @@ -300,7 +294,7 @@ struct BusLogic_GlobalOptions { */ struct BusLogic_LocalOptions { - boolean InhibitTargetInquiry:1; /* Bit 0 */ + bool InhibitTargetInquiry:1; /* Bit 0 */ }; /* @@ -322,10 +316,10 @@ union BusLogic_ControlRegister { unsigned char All; struct { unsigned char:4; /* Bits 0-3 */ - boolean SCSIBusReset:1; /* Bit 4 */ - boolean InterruptReset:1; /* Bit 5 */ - boolean SoftReset:1; /* Bit 6 */ - boolean HardReset:1; /* Bit 7 */ + bool SCSIBusReset:1; /* Bit 4 */ + bool InterruptReset:1; /* Bit 5 */ + bool SoftReset:1; /* Bit 6 */ + bool HardReset:1; /* Bit 7 */ } cr; }; @@ -336,14 +330,14 @@ union BusLogic_ControlRegister { union BusLogic_StatusRegister { unsigned char All; struct { - boolean CommandInvalid:1; /* Bit 0 */ - boolean Reserved:1; /* Bit 1 */ - boolean DataInRegisterReady:1; /* Bit 2 */ - boolean CommandParameterRegisterBusy:1; /* Bit 3 */ - boolean HostAdapterReady:1; /* Bit 4 */ - boolean InitializationRequired:1; /* Bit 5 */ - boolean DiagnosticFailure:1; /* Bit 6 */ - boolean DiagnosticActive:1; /* Bit 7 */ + bool CommandInvalid:1; /* Bit 0 */ + bool Reserved:1; /* Bit 1 */ + bool DataInRegisterReady:1; /* Bit 2 */ + bool CommandParameterRegisterBusy:1; /* Bit 3 */ + bool HostAdapterReady:1; /* Bit 4 */ + bool InitializationRequired:1; /* Bit 5 */ + bool DiagnosticFailure:1; /* Bit 6 */ + bool DiagnosticActive:1; /* Bit 7 */ } sr; }; @@ -354,12 +348,12 @@ union BusLogic_StatusRegister { union BusLogic_InterruptRegister { unsigned char All; struct { - boolean IncomingMailboxLoaded:1; /* Bit 0 */ - boolean OutgoingMailboxAvailable:1; /* Bit 1 */ - boolean CommandComplete:1; /* Bit 2 */ - boolean ExternalBusReset:1; /* Bit 3 */ + bool IncomingMailboxLoaded:1; /* Bit 0 */ + bool OutgoingMailboxAvailable:1;/* Bit 1 */ + bool CommandComplete:1; /* Bit 2 */ + bool ExternalBusReset:1; /* Bit 3 */ unsigned char Reserved:3; /* Bits 4-6 */ - boolean InterruptValid:1; /* Bit 7 */ + bool InterruptValid:1; /* Bit 7 */ } ir; }; @@ -373,7 +367,7 @@ union BusLogic_GeometryRegister { enum BusLogic_BIOS_DiskGeometryTranslation Drive0Geometry:2; /* Bits 0-1 */ enum BusLogic_BIOS_DiskGeometryTranslation Drive1Geometry:2; /* Bits 2-3 */ unsigned char:3; /* Bits 4-6 */ - boolean ExtendedTranslationEnabled:1; /* Bit 7 */ + bool ExtendedTranslationEnabled:1; /* Bit 7 */ } gr; }; @@ -445,16 +439,16 @@ struct BusLogic_BoardID { struct BusLogic_Configuration { unsigned char:5; /* Byte 0 Bits 0-4 */ - boolean DMA_Channel5:1; /* Byte 0 Bit 5 */ - boolean DMA_Channel6:1; /* Byte 0 Bit 6 */ - boolean DMA_Channel7:1; /* Byte 0 Bit 7 */ - boolean IRQ_Channel9:1; /* Byte 1 Bit 0 */ - boolean IRQ_Channel10:1; /* Byte 1 Bit 1 */ - boolean IRQ_Channel11:1; /* Byte 1 Bit 2 */ - boolean IRQ_Channel12:1; /* Byte 1 Bit 3 */ + bool DMA_Channel5:1; /* Byte 0 Bit 5 */ + bool DMA_Channel6:1; /* Byte 0 Bit 6 */ + bool DMA_Channel7:1; /* Byte 0 Bit 7 */ + bool IRQ_Channel9:1; /* Byte 1 Bit 0 */ + bool IRQ_Channel10:1; /* Byte 1 Bit 1 */ + bool IRQ_Channel11:1; /* Byte 1 Bit 2 */ + bool IRQ_Channel12:1; /* Byte 1 Bit 3 */ unsigned char:1; /* Byte 1 Bit 4 */ - boolean IRQ_Channel14:1; /* Byte 1 Bit 5 */ - boolean IRQ_Channel15:1; /* Byte 1 Bit 6 */ + bool IRQ_Channel14:1; /* Byte 1 Bit 5 */ + bool IRQ_Channel15:1; /* Byte 1 Bit 6 */ unsigned char:1; /* Byte 1 Bit 7 */ unsigned char HostAdapterID:4; /* Byte 2 Bits 0-3 */ unsigned char:4; /* Byte 2 Bits 4-7 */ @@ -467,12 +461,12 @@ struct BusLogic_Configuration { struct BusLogic_SynchronousValue { unsigned char Offset:4; /* Bits 0-3 */ unsigned char TransferPeriod:3; /* Bits 4-6 */ - boolean Synchronous:1; /* Bit 7 */ + bool Synchronous:1; /* Bit 7 */ }; struct BusLogic_SetupInformation { - boolean SynchronousInitiationEnabled:1; /* Byte 0 Bit 0 */ - boolean ParityCheckingEnabled:1; /* Byte 0 Bit 1 */ + bool SynchronousInitiationEnabled:1; /* Byte 0 Bit 0 */ + bool ParityCheckingEnabled:1; /* Byte 0 Bit 1 */ unsigned char:6; /* Byte 0 Bits 2-7 */ unsigned char BusTransferRate; /* Byte 1 */ unsigned char PreemptTimeOnBus; /* Byte 2 */ @@ -523,13 +517,13 @@ enum BusLogic_ISACompatibleIOPort { struct BusLogic_PCIHostAdapterInformation { enum BusLogic_ISACompatibleIOPort ISACompatibleIOPort; /* Byte 0 */ unsigned char PCIAssignedIRQChannel; /* Byte 1 */ - boolean LowByteTerminated:1; /* Byte 2 Bit 0 */ - boolean HighByteTerminated:1; /* Byte 2 Bit 1 */ + bool LowByteTerminated:1; /* Byte 2 Bit 0 */ + bool HighByteTerminated:1; /* Byte 2 Bit 1 */ unsigned char:2; /* Byte 2 Bits 2-3 */ - boolean JP1:1; /* Byte 2 Bit 4 */ - boolean JP2:1; /* Byte 2 Bit 5 */ - boolean JP3:1; /* Byte 2 Bit 6 */ - boolean GenericInfoValid:1; /* Byte 2 Bit 7 */ + bool JP1:1; /* Byte 2 Bit 4 */ + bool JP2:1; /* Byte 2 Bit 5 */ + bool JP3:1; /* Byte 2 Bit 6 */ + bool GenericInfoValid:1;/* Byte 2 Bit 7 */ unsigned char:8; /* Byte 3 */ }; @@ -545,17 +539,17 @@ struct BusLogic_ExtendedSetupInformation { u32 BaseMailboxAddress; /* Bytes 5-8 */ struct { unsigned char:2; /* Byte 9 Bits 0-1 */ - boolean FastOnEISA:1; /* Byte 9 Bit 2 */ + bool FastOnEISA:1; /* Byte 9 Bit 2 */ unsigned char:3; /* Byte 9 Bits 3-5 */ - boolean LevelSensitiveInterrupt:1; /* Byte 9 Bit 6 */ + bool LevelSensitiveInterrupt:1; /* Byte 9 Bit 6 */ unsigned char:1; /* Byte 9 Bit 7 */ } Misc; unsigned char FirmwareRevision[3]; /* Bytes 10-12 */ - boolean HostWideSCSI:1; /* Byte 13 Bit 0 */ - boolean HostDifferentialSCSI:1; /* Byte 13 Bit 1 */ - boolean HostSupportsSCAM:1; /* Byte 13 Bit 2 */ - boolean HostUltraSCSI:1; /* Byte 13 Bit 3 */ - boolean HostSmartTermination:1; /* Byte 13 Bit 4 */ + bool HostWideSCSI:1; /* Byte 13 Bit 0 */ + bool HostDifferentialSCSI:1; /* Byte 13 Bit 1 */ + bool HostSupportsSCAM:1; /* Byte 13 Bit 2 */ + bool HostUltraSCSI:1; /* Byte 13 Bit 3 */ + bool HostSmartTermination:1; /* Byte 13 Bit 4 */ unsigned char:3; /* Byte 13 Bits 5-7 */ } PACKED; @@ -590,35 +584,35 @@ struct BusLogic_AutoSCSIData { unsigned char InformationByteCount; /* Byte 2 */ unsigned char HostAdapterType[6]; /* Bytes 3-8 */ unsigned char:8; /* Byte 9 */ - boolean FloppyEnabled:1; /* Byte 10 Bit 0 */ - boolean FloppySecondary:1; /* Byte 10 Bit 1 */ - boolean LevelSensitiveInterrupt:1; /* Byte 10 Bit 2 */ + bool FloppyEnabled:1; /* Byte 10 Bit 0 */ + bool FloppySecondary:1; /* Byte 10 Bit 1 */ + bool LevelSensitiveInterrupt:1; /* Byte 10 Bit 2 */ unsigned char:2; /* Byte 10 Bits 3-4 */ unsigned char SystemRAMAreaForBIOS:3; /* Byte 10 Bits 5-7 */ unsigned char DMA_Channel:7; /* Byte 11 Bits 0-6 */ - boolean DMA_AutoConfiguration:1; /* Byte 11 Bit 7 */ + bool DMA_AutoConfiguration:1; /* Byte 11 Bit 7 */ unsigned char IRQ_Channel:7; /* Byte 12 Bits 0-6 */ - boolean IRQ_AutoConfiguration:1; /* Byte 12 Bit 7 */ + bool IRQ_AutoConfiguration:1; /* Byte 12 Bit 7 */ unsigned char DMA_TransferRate; /* Byte 13 */ unsigned char SCSI_ID; /* Byte 14 */ - boolean LowByteTerminated:1; /* Byte 15 Bit 0 */ - boolean ParityCheckingEnabled:1; /* Byte 15 Bit 1 */ - boolean HighByteTerminated:1; /* Byte 15 Bit 2 */ - boolean NoisyCablingEnvironment:1; /* Byte 15 Bit 3 */ - boolean FastSynchronousNegotiation:1; /* Byte 15 Bit 4 */ - boolean BusResetEnabled:1; /* Byte 15 Bit 5 */ - boolean:1; /* Byte 15 Bit 6 */ - boolean ActiveNegationEnabled:1; /* Byte 15 Bit 7 */ + bool LowByteTerminated:1; /* Byte 15 Bit 0 */ + bool ParityCheckingEnabled:1; /* Byte 15 Bit 1 */ + bool HighByteTerminated:1; /* Byte 15 Bit 2 */ + bool NoisyCablingEnvironment:1; /* Byte 15 Bit 3 */ + bool FastSynchronousNegotiation:1; /* Byte 15 Bit 4 */ + bool BusResetEnabled:1; /* Byte 15 Bit 5 */ + bool:1; /* Byte 15 Bit 6 */ + bool ActiveNegationEnabled:1; /* Byte 15 Bit 7 */ unsigned char BusOnDelay; /* Byte 16 */ unsigned char BusOffDelay; /* Byte 17 */ - boolean HostAdapterBIOSEnabled:1; /* Byte 18 Bit 0 */ - boolean BIOSRedirectionOfINT19Enabled:1; /* Byte 18 Bit 1 */ - boolean ExtendedTranslationEnabled:1; /* Byte 18 Bit 2 */ - boolean MapRemovableAsFixedEnabled:1; /* Byte 18 Bit 3 */ - boolean:1; /* Byte 18 Bit 4 */ - boolean BIOSSupportsMoreThan2DrivesEnabled:1; /* Byte 18 Bit 5 */ - boolean BIOSInterruptModeEnabled:1; /* Byte 18 Bit 6 */ - boolean FlopticalSupportEnabled:1; /* Byte 19 Bit 7 */ + bool HostAdapterBIOSEnabled:1; /* Byte 18 Bit 0 */ + bool BIOSRedirectionOfINT19Enabled:1; /* Byte 18 Bit 1 */ + bool ExtendedTranslationEnabled:1; /* Byte 18 Bit 2 */ + bool MapRemovableAsFixedEnabled:1; /* Byte 18 Bit 3 */ + bool:1; /* Byte 18 Bit 4 */ + bool BIOSSupportsMoreThan2DrivesEnabled:1; /* Byte 18 Bit 5 */ + bool BIOSInterruptModeEnabled:1; /* Byte 18 Bit 6 */ + bool FlopticalSupportEnabled:1; /* Byte 19 Bit 7 */ unsigned short DeviceEnabled; /* Bytes 19-20 */ unsigned short WidePermitted; /* Bytes 21-22 */ unsigned short FastPermitted; /* Bytes 23-24 */ @@ -628,22 +622,22 @@ struct BusLogic_AutoSCSIData { unsigned short IgnoreInBIOSScan; /* Bytes 31-32 */ unsigned char PCIInterruptPin:2; /* Byte 33 Bits 0-1 */ unsigned char HostAdapterIOPortAddress:2; /* Byte 33 Bits 2-3 */ - boolean StrictRoundRobinModeEnabled:1; /* Byte 33 Bit 4 */ - boolean VESABusSpeedGreaterThan33MHz:1; /* Byte 33 Bit 5 */ - boolean VESABurstWriteEnabled:1; /* Byte 33 Bit 6 */ - boolean VESABurstReadEnabled:1; /* Byte 33 Bit 7 */ + bool StrictRoundRobinModeEnabled:1; /* Byte 33 Bit 4 */ + bool VESABusSpeedGreaterThan33MHz:1; /* Byte 33 Bit 5 */ + bool VESABurstWriteEnabled:1; /* Byte 33 Bit 6 */ + bool VESABurstReadEnabled:1; /* Byte 33 Bit 7 */ unsigned short UltraPermitted; /* Bytes 34-35 */ unsigned int:32; /* Bytes 36-39 */ unsigned char:8; /* Byte 40 */ unsigned char AutoSCSIMaximumLUN; /* Byte 41 */ - boolean:1; /* Byte 42 Bit 0 */ - boolean SCAM_Dominant:1; /* Byte 42 Bit 1 */ - boolean SCAM_Enabled:1; /* Byte 42 Bit 2 */ - boolean SCAM_Level2:1; /* Byte 42 Bit 3 */ + bool:1; /* Byte 42 Bit 0 */ + bool SCAM_Dominant:1; /* Byte 42 Bit 1 */ + bool SCAM_Enabled:1; /* Byte 42 Bit 2 */ + bool SCAM_Level2:1; /* Byte 42 Bit 3 */ unsigned char:4; /* Byte 42 Bits 4-7 */ - boolean INT13ExtensionEnabled:1; /* Byte 43 Bit 0 */ - boolean:1; /* Byte 43 Bit 1 */ - boolean CDROMBootEnabled:1; /* Byte 43 Bit 2 */ + bool INT13ExtensionEnabled:1; /* Byte 43 Bit 0 */ + bool:1; /* Byte 43 Bit 1 */ + bool CDROMBootEnabled:1; /* Byte 43 Bit 2 */ unsigned char:5; /* Byte 43 Bits 3-7 */ unsigned char BootTargetID:4; /* Byte 44 Bits 0-3 */ unsigned char BootChannel:4; /* Byte 44 Bits 4-7 */ @@ -852,7 +846,7 @@ struct BusLogic_CCB { enum BusLogic_CCB_Opcode Opcode; /* Byte 0 */ unsigned char:3; /* Byte 1 Bits 0-2 */ enum BusLogic_DataDirection DataDirection:2; /* Byte 1 Bits 3-4 */ - boolean TagEnable:1; /* Byte 1 Bit 5 */ + bool TagEnable:1; /* Byte 1 Bit 5 */ enum BusLogic_QueueTag QueueTag:2; /* Byte 1 Bits 6-7 */ unsigned char CDB_Length; /* Byte 2 */ unsigned char SenseDataLength; /* Byte 3 */ @@ -864,7 +858,7 @@ struct BusLogic_CCB { enum BusLogic_TargetDeviceStatus TargetDeviceStatus; /* Byte 15 */ unsigned char TargetID; /* Byte 16 */ unsigned char LogicalUnit:5; /* Byte 17 Bits 0-4 */ - boolean LegacyTagEnable:1; /* Byte 17 Bit 5 */ + bool LegacyTagEnable:1; /* Byte 17 Bit 5 */ enum BusLogic_QueueTag LegacyQueueTag:2; /* Byte 17 Bits 6-7 */ SCSI_CDB_T CDB; /* Bytes 18-29 */ unsigned char:8; /* Byte 30 */ @@ -939,13 +933,13 @@ struct BusLogic_DriverOptions { */ struct BusLogic_TargetFlags { - boolean TargetExists:1; - boolean TaggedQueuingSupported:1; - boolean WideTransfersSupported:1; - boolean TaggedQueuingActive:1; - boolean WideTransfersActive:1; - boolean CommandSuccessfulFlag:1; - boolean TargetInfoReported:1; + bool TargetExists:1; + bool TaggedQueuingSupported:1; + bool WideTransfersSupported:1; + bool TaggedQueuingActive:1; + bool WideTransfersActive:1; + bool CommandSuccessfulFlag:1; + bool TargetInfoReported:1; }; /* @@ -992,7 +986,7 @@ typedef unsigned int FlashPoint_CardHandle_T; struct FlashPoint_Info { u32 BaseAddress; /* Bytes 0-3 */ - boolean Present; /* Byte 4 */ + bool Present; /* Byte 4 */ unsigned char IRQ_Channel; /* Byte 5 */ unsigned char SCSI_ID; /* Byte 6 */ unsigned char SCSI_LUN; /* Byte 7 */ @@ -1002,15 +996,15 @@ struct FlashPoint_Info { unsigned short UltraPermitted; /* Bytes 14-15 */ unsigned short DisconnectPermitted; /* Bytes 16-17 */ unsigned short WidePermitted; /* Bytes 18-19 */ - boolean ParityCheckingEnabled:1; /* Byte 20 Bit 0 */ - boolean HostWideSCSI:1; /* Byte 20 Bit 1 */ - boolean HostSoftReset:1; /* Byte 20 Bit 2 */ - boolean ExtendedTranslationEnabled:1; /* Byte 20 Bit 3 */ - boolean LowByteTerminated:1; /* Byte 20 Bit 4 */ - boolean HighByteTerminated:1; /* Byte 20 Bit 5 */ - boolean ReportDataUnderrun:1; /* Byte 20 Bit 6 */ - boolean SCAM_Enabled:1; /* Byte 20 Bit 7 */ - boolean SCAM_Level2:1; /* Byte 21 Bit 0 */ + bool ParityCheckingEnabled:1; /* Byte 20 Bit 0 */ + bool HostWideSCSI:1; /* Byte 20 Bit 1 */ + bool HostSoftReset:1; /* Byte 20 Bit 2 */ + bool ExtendedTranslationEnabled:1; /* Byte 20 Bit 3 */ + bool LowByteTerminated:1; /* Byte 20 Bit 4 */ + bool HighByteTerminated:1; /* Byte 20 Bit 5 */ + bool ReportDataUnderrun:1; /* Byte 20 Bit 6 */ + bool SCAM_Enabled:1; /* Byte 20 Bit 7 */ + bool SCAM_Level2:1; /* Byte 21 Bit 0 */ unsigned char:7; /* Byte 21 Bits 1-7 */ unsigned char Family; /* Byte 22 */ unsigned char BusType; /* Byte 23 */ @@ -1044,29 +1038,29 @@ struct BusLogic_HostAdapter { unsigned char IRQ_Channel; unsigned char DMA_Channel; unsigned char SCSI_ID; - boolean IRQ_ChannelAcquired:1; - boolean DMA_ChannelAcquired:1; - boolean ExtendedTranslationEnabled:1; - boolean ParityCheckingEnabled:1; - boolean BusResetEnabled:1; - boolean LevelSensitiveInterrupt:1; - boolean HostWideSCSI:1; - boolean HostDifferentialSCSI:1; - boolean HostSupportsSCAM:1; - boolean HostUltraSCSI:1; - boolean ExtendedLUNSupport:1; - boolean TerminationInfoValid:1; - boolean LowByteTerminated:1; - boolean HighByteTerminated:1; - boolean BounceBuffersRequired:1; - boolean StrictRoundRobinModeSupport:1; - boolean SCAM_Enabled:1; - boolean SCAM_Level2:1; - boolean HostAdapterInitialized:1; - boolean HostAdapterExternalReset:1; - boolean HostAdapterInternalError:1; - boolean ProcessCompletedCCBsActive; - volatile boolean HostAdapterCommandCompleted; + bool IRQ_ChannelAcquired:1; + bool DMA_ChannelAcquired:1; + bool ExtendedTranslationEnabled:1; + bool ParityCheckingEnabled:1; + bool BusResetEnabled:1; + bool LevelSensitiveInterrupt:1; + bool HostWideSCSI:1; + bool HostDifferentialSCSI:1; + bool HostSupportsSCAM:1; + bool HostUltraSCSI:1; + bool ExtendedLUNSupport:1; + bool TerminationInfoValid:1; + bool LowByteTerminated:1; + bool HighByteTerminated:1; + bool BounceBuffersRequired:1; + bool StrictRoundRobinModeSupport:1; + bool SCAM_Enabled:1; + bool SCAM_Level2:1; + bool HostAdapterInitialized:1; + bool HostAdapterExternalReset:1; + bool HostAdapterInternalError:1; + bool ProcessCompletedCCBsActive; + volatile bool HostAdapterCommandCompleted; unsigned short HostAdapterScatterGatherLimit; unsigned short DriverScatterGatherLimit; unsigned short MaxTargetDevices; @@ -1141,25 +1135,25 @@ struct SCSI_Inquiry { unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */ - boolean RMB:1; /* Byte 1 Bit 7 */ + bool RMB:1; /* Byte 1 Bit 7 */ unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */ unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */ unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */ unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */ unsigned char:2; /* Byte 3 Bits 4-5 */ - boolean TrmIOP:1; /* Byte 3 Bit 6 */ - boolean AENC:1; /* Byte 3 Bit 7 */ + bool TrmIOP:1; /* Byte 3 Bit 6 */ + bool AENC:1; /* Byte 3 Bit 7 */ unsigned char AdditionalLength; /* Byte 4 */ unsigned char:8; /* Byte 5 */ unsigned char:8; /* Byte 6 */ - boolean SftRe:1; /* Byte 7 Bit 0 */ - boolean CmdQue:1; /* Byte 7 Bit 1 */ - boolean:1; /* Byte 7 Bit 2 */ - boolean Linked:1; /* Byte 7 Bit 3 */ - boolean Sync:1; /* Byte 7 Bit 4 */ - boolean WBus16:1; /* Byte 7 Bit 5 */ - boolean WBus32:1; /* Byte 7 Bit 6 */ - boolean RelAdr:1; /* Byte 7 Bit 7 */ + bool SftRe:1; /* Byte 7 Bit 0 */ + bool CmdQue:1; /* Byte 7 Bit 1 */ + bool:1; /* Byte 7 Bit 2 */ + bool Linked:1; /* Byte 7 Bit 3 */ + bool Sync:1; /* Byte 7 Bit 4 */ + bool WBus16:1; /* Byte 7 Bit 5 */ + bool WBus32:1; /* Byte 7 Bit 6 */ + bool RelAdr:1; /* Byte 7 Bit 7 */ unsigned char VendorIdentification[8]; /* Bytes 8-15 */ unsigned char ProductIdentification[16]; /* Bytes 16-31 */ unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */ @@ -1348,7 +1342,7 @@ static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *, char **, off_t static int BusLogic_SlaveConfigure(struct scsi_device *); static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *); static irqreturn_t BusLogic_InterruptHandler(int, void *); -static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, boolean HardReset); +static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, bool HardReset); static void BusLogic_Message(enum BusLogic_MessageLevel, char *, struct BusLogic_HostAdapter *, ...); static int __init BusLogic_Setup(char *); diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 7c0068049586..a7f916c0c9cd 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -7609,7 +7609,7 @@ FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle, FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB); } -static inline boolean +static inline bool FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle) { return FlashPoint_InterruptPending(CardHandle); @@ -7640,7 +7640,7 @@ extern FlashPoint_CardHandle_T FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *); extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *); extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *); -extern boolean FlashPoint_InterruptPending(FlashPoint_CardHandle_T); +extern bool FlashPoint_InterruptPending(FlashPoint_CardHandle_T); extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T); extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T); -- cgit v1.2.3 From 55048021177eee956af88333ec4565919c8567e4 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Mon, 5 Feb 2007 16:38:53 -0800 Subject: [SCSI] aic79xx: fix bracket mismatch in unused macro Signed-off-by: Mariusz Kozlowski Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 2cf7bb3123f0..8d72bbae96ad 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -88,7 +88,7 @@ ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) #define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20) -#define SUBID_9005_SEEPTYPE(id) ((id) & 0x0C0) >> 6) +#define SUBID_9005_SEEPTYPE(id) (((id) & 0x0C0) >> 6) #define SUBID_9005_SEEPTYPE_NONE 0x0 #define SUBID_9005_SEEPTYPE_4K 0x1 -- cgit v1.2.3 From 19966769f9fc1968dcf5bffec2e53f7f40100872 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 7 Feb 2007 09:47:44 +0100 Subject: [SCSI] aic79xx: use dma_get_required_mask() As originally noted by Frederic Temporelli, the aic79xx supports 64 bit addressing, but the initialization code of the driver is wrong: it tests the available memory size instead of testing the maximum available memory address. This patch uses the correct dma_get_required_mask() macros to determine the correct addressing method. Signed-off-by: Hannes Reinecke Cc: Xavier Bru CC: Frederic Temporelli cosmetic fixes Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_osm.c | 9 --------- drivers/scsi/aic7xxx/aic79xx_osm.h | 2 -- drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 19 +++++++++---------- 3 files changed, 9 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 9bfcca5ede08..c7fe478f4813 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -1126,15 +1126,6 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa return 0; } -uint64_t -ahd_linux_get_memsize(void) -{ - struct sysinfo si; - - si_meminfo(&si); - return ((uint64_t)si.totalram << PAGE_SHIFT); -} - /* * Place the SCSI bus into a known state by either resetting it, * or forcing transfer negotiations on the next command to any diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index 3a67fc578d78..147c83c456a5 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -496,8 +496,6 @@ ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count) int ahd_linux_register_host(struct ahd_softc *, struct scsi_host_template *); -uint64_t ahd_linux_get_memsize(void); - /*************************** Pretty Printing **********************************/ struct info_str { char *buffer; diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index 1a3ab6aa856b..c62ce41f2793 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -132,6 +132,7 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct ahd_pci_identity *entry; char *name; int error; + struct device *dev = &pdev->dev; pci = pdev; entry = ahd_find_pci_device(pci); @@ -161,20 +162,18 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_master(pdev); if (sizeof(dma_addr_t) > 4) { - uint64_t memsize; - const uint64_t mask_39bit = 0x7FFFFFFFFFULL; + const u64 required_mask = dma_get_required_mask(dev); - memsize = ahd_linux_get_memsize(); - - if (memsize >= 0x8000000000ULL - && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) { + if (required_mask > DMA_39BIT_MASK && + dma_set_mask(dev, DMA_64BIT_MASK) == 0) ahd->flags |= AHD_64BIT_ADDRESSING; - } else if (memsize > 0x80000000 - && pci_set_dma_mask(pdev, mask_39bit) == 0) { + else if (required_mask > DMA_32BIT_MASK && + dma_set_mask(dev, DMA_39BIT_MASK) == 0) ahd->flags |= AHD_39BIT_ADDRESSING; - } + else + dma_set_mask(dev, DMA_32BIT_MASK); } else { - pci_set_dma_mask(pdev, DMA_32BIT_MASK); + dma_set_mask(dev, DMA_32BIT_MASK); } ahd->dev_softc = pci; error = ahd_pci_config(ahd, entry); -- cgit v1.2.3 From 6fcc47111ae14f284007e1b9a5002babb01d913c Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Wed, 7 Feb 2007 13:17:57 +0100 Subject: [SCSI] zfcp: Invalid locking order Invalid locking order. Kernel hangs after trying to take two locks which are dependend on each other. Introducing temporary variable to free requests. Free lock after requests are copied. Signed-off-by: Swen Schillig Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_ext.h | 2 +- drivers/s390/scsi/zfcp_fsf.c | 23 ++++++++++------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index b8794d77285d..7ec8e352b1fe 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -89,7 +89,7 @@ extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **, u32, u32, struct zfcp_sg_list *); extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long); extern void zfcp_erp_start_timer(struct zfcp_fsf_req *); -extern int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); +extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); extern int zfcp_fsf_status_read(struct zfcp_adapter *, int); extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *, unsigned long *, struct zfcp_fsf_req **); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 067f1519eb04..eabf86bb13f5 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -176,28 +176,25 @@ static void zfcp_fsf_req_dismiss(struct zfcp_adapter *adapter, /** * zfcp_fsf_req_dismiss_all - dismiss all remaining fsf requests */ -int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) +void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) { struct zfcp_fsf_req *request, *tmp; unsigned long flags; + LIST_HEAD(remove_queue); unsigned int i, counter; spin_lock_irqsave(&adapter->req_list_lock, flags); atomic_set(&adapter->reqs_active, 0); - for (i=0; ireq_list[i])) - continue; - - counter = 0; - list_for_each_entry_safe(request, tmp, - &adapter->req_list[i], list) { - zfcp_fsf_req_dismiss(adapter, request, counter); - counter++; - } - } + for (i=0; ireq_list[i], &remove_queue); + spin_unlock_irqrestore(&adapter->req_list_lock, flags); - return 0; + counter = 0; + list_for_each_entry_safe(request, tmp, &remove_queue, list) { + zfcp_fsf_req_dismiss(adapter, request, counter); + counter++; + } } /* -- cgit v1.2.3 From ca880cf93361e752d2e0bf6bf73657e2c56a0822 Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Fri, 9 Feb 2007 10:00:14 +0100 Subject: [SCSI] zfcp: use of uninitialized variable commit 988d955c3314336d716a9208f3d565b06f262e07 Author: Swen Schillig Date: Fri Feb 9 09:40:11 2007 +0100 Use of uninitialized variable. ERP action might not be finished accordingly. Signed-off-by: Swen Schillig Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_erp.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index c88babce9bca..9d3c4a9ba90c 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -841,29 +841,27 @@ zfcp_erp_action_exists(struct zfcp_erp_action *erp_action) * * returns: 0 */ -static int +static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) { - int retval = 0; - struct zfcp_fsf_req *fsf_req = NULL; struct zfcp_adapter *adapter = erp_action->adapter; if (erp_action->fsf_req) { /* take lock to ensure that request is not deleted meanwhile */ spin_lock(&adapter->req_list_lock); - if ((!zfcp_reqlist_ismember(adapter, - erp_action->fsf_req->req_id)) && - (fsf_req->erp_action == erp_action)) { + if (zfcp_reqlist_ismember(adapter, + erp_action->fsf_req->req_id)) { /* fsf_req still exists */ debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); - debug_event(adapter->erp_dbf, 3, &fsf_req, + debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req, sizeof (unsigned long)); /* dismiss fsf_req of timed out/dismissed erp_action */ if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED | ZFCP_STATUS_ERP_TIMEDOUT)) { debug_text_event(adapter->erp_dbf, 3, "a_ca_disreq"); - fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; + erp_action->fsf_req->status |= + ZFCP_STATUS_FSFREQ_DISMISSED; } if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { ZFCP_LOG_NORMAL("error: erp step timed out " @@ -876,11 +874,11 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) * then keep it running asynchronously and don't mess * with the association of erp_action and fsf_req. */ - if (fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED | + if (erp_action->fsf_req->status & + (ZFCP_STATUS_FSFREQ_COMPLETED | ZFCP_STATUS_FSFREQ_DISMISSED)) { /* forget about association between fsf_req and erp_action */ - fsf_req->erp_action = NULL; erp_action->fsf_req = NULL; } } else { @@ -894,8 +892,6 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) spin_unlock(&adapter->req_list_lock); } else debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq"); - - return retval; } /** -- cgit v1.2.3 From 98051995ab44b993f992946055edc6115351f725 Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Fri, 9 Feb 2007 10:01:40 +0100 Subject: [SCSI] zfcp: removed wrong comment commit 07a105136f07f0cf1b476383e43033b8a65e13ff Author: Swen Schillig Date: Fri Feb 9 09:58:09 2007 +0100 removed wrong comment Signed-off-by: Swen Schillig Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_erp.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 9d3c4a9ba90c..755b754dec60 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -838,8 +838,6 @@ zfcp_erp_action_exists(struct zfcp_erp_action *erp_action) * and does appropriate preparations (dismiss fsf request, ...) * * locks: called under erp_lock (disabled interrupts) - * - * returns: 0 */ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) -- cgit v1.2.3