提交 c8b6de16 编写于 作者: L Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (48 commits)
  [SCSI] aacraid: do not set valid bit in sense information
  [SCSI] ses: add new Enclosure ULD
  [SCSI] enclosure: add support for enclosure services
  [SCSI] sr: fix test unit ready responses
  [SCSI] u14-34f: fix data direction bug
  [SCSI] aacraid: pci_set_dma_max_seg_size opened up for late model controllers
  [SCSI] fix BUG when sum(scatterlist) > bufflen
  [SCSI] arcmsr: updates (1.20.00.15)
  [SCSI] advansys: make 3 functions static
  [SCSI] Small cleanups for scsi_host.h
  [SCSI] dc395x: fix uninitialized var warning
  [SCSI] NCR53C9x: remove driver
  [SCSI] remove m68k NCR53C9x based drivers
  [SCSI] dec_esp: Remove driver
  [SCSI] kernel-doc: fix scsi docbook
  [SCSI] update my email address
  [SCSI] add protocol definitions
  [SCSI] sd: handle bad lba in sense information
  [SCSI] qla2xxx: Update version number to 8.02.00-k8.
  [SCSI] qla2xxx: Correct issue where incorrect init-fw mailbox command was used on non-NPIV capable ISPs.
  ...
......@@ -12,7 +12,7 @@
<surname>Bottomley</surname>
<affiliation>
<address>
<email>James.Bottomley@steeleye.com</email>
<email>James.Bottomley@hansenpartnership.com</email>
</address>
</affiliation>
</author>
......
......@@ -68,4 +68,45 @@
** 2. modify the arcmsr_pci_slot_reset function
** 3. modify the arcmsr_pci_ers_disconnect_forepart function
** 4. modify the arcmsr_pci_ers_need_reset_forepart function
** 1.20.00.15 09/27/2007 Erich Chen & Nick Cheng
** 1. add arcmsr_enable_eoi_mode() on adapter Type B
** 2. add readl(reg->iop2drv_doorbell_reg) in arcmsr_handle_hbb_isr()
** in case of the doorbell interrupt clearance is cached
** 1.20.00.15 10/01/2007 Erich Chen & Nick Cheng
** 1. modify acb->devstate[i][j]
** as ARECA_RAID_GOOD instead of
** ARECA_RAID_GONE in arcmsr_alloc_ccb_pool
** 1.20.00.15 11/06/2007 Erich Chen & Nick Cheng
** 1. add conditional declaration for
** arcmsr_pci_error_detected() and
** arcmsr_pci_slot_reset
** 1.20.00.15 11/23/2007 Erich Chen & Nick Cheng
** 1.check if the sg list member number
** exceeds arcmsr default limit in arcmsr_build_ccb()
** 2.change the returned value type of arcmsr_build_ccb()
** from "void" to "int"
** 3.add the conditional check if arcmsr_build_ccb()
** returns FAILED
** 1.20.00.15 12/04/2007 Erich Chen & Nick Cheng
** 1. modify arcmsr_drain_donequeue() to ignore unknown
** command and let kernel process command timeout.
** This could handle IO request violating max. segments
** while Linux XFS over DM-CRYPT.
** Thanks to Milan Broz's comments <mbroz@redhat.com>
** 1.20.00.15 12/24/2007 Erich Chen & Nick Cheng
** 1.fix the portability problems
** 2.fix type B where we should _not_ iounmap() acb->pmu;
** it's not ioremapped.
** 3.add return -ENOMEM if ioremap() fails
** 4.transfer IS_SG64_ADDR w/ cpu_to_le32()
** in arcmsr_build_ccb
** 5. modify acb->devstate[i][j] as ARECA_RAID_GONE instead of
** ARECA_RAID_GOOD in arcmsr_alloc_ccb_pool()
** 6.fix arcmsr_cdb->Context as (unsigned long)arcmsr_cdb
** 7.add the checking state of
** (outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT) == 0
** in arcmsr_handle_hba_isr
** 8.replace pci_alloc_consistent()/pci_free_consistent() with kmalloc()/kfree() in arcmsr_iop_message_xfer()
** 9. fix the release of dma memory for type B in arcmsr_free_ccb_pool()
** 10.fix the arcmsr_polling_hbb_ccbdone()
**************************************************************************
......@@ -1407,7 +1407,7 @@ Credits
=======
The following people have contributed to this document:
Mike Anderson <andmike at us dot ibm dot com>
James Bottomley <James dot Bottomley at steeleye dot com>
James Bottomley <James dot Bottomley at hansenpartnership dot com>
Patrick Mansfield <patmans at us dot ibm dot com>
Christoph Hellwig <hch at infradead dot org>
Doug Ledford <dledford at redhat dot com>
......
......@@ -285,4 +285,13 @@ config INTEL_MENLOW
If unsure, say N.
config ENCLOSURE_SERVICES
tristate "Enclosure Services"
default n
help
Provides support for intelligent enclosures (bays which
contain storage devices). You also need either a host
driver (SCSI/ATA) which supports enclosures
or a SCSI enclosure device (SES) to use these services.
endif # MISC_DEVICES
......@@ -20,3 +20,4 @@ obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
/*
* Enclosure Services
*
* Copyright (C) 2008 James Bottomley <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
** version 2 as published by the Free Software Foundation.
**
** 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.
**
**-----------------------------------------------------------------------------
*/
#include <linux/device.h>
#include <linux/enclosure.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
static LIST_HEAD(container_list);
static DEFINE_MUTEX(container_list_lock);
static struct class enclosure_class;
static struct class enclosure_component_class;
/**
* enclosure_find - find an enclosure given a device
* @dev: the device to find for
*
* Looks through the list of registered enclosures to see
* if it can find a match for a device. Returns NULL if no
* enclosure is found. Obtains a reference to the enclosure class
* device which must be released with class_device_put().
*/
struct enclosure_device *enclosure_find(struct device *dev)
{
struct enclosure_device *edev = NULL;
mutex_lock(&container_list_lock);
list_for_each_entry(edev, &container_list, node) {
if (edev->cdev.dev == dev) {
class_device_get(&edev->cdev);
mutex_unlock(&container_list_lock);
return edev;
}
}
mutex_unlock(&container_list_lock);
return NULL;
}
EXPORT_SYMBOL_GPL(enclosure_find);
/**
* enclosure_for_each_device - calls a function for each enclosure
* @fn: the function to call
* @data: the data to pass to each call
*
* Loops over all the enclosures calling the function.
*
* Note, this function uses a mutex which will be held across calls to
* @fn, so it must have non atomic context, and @fn may (although it
* should not) sleep or otherwise cause the mutex to be held for
* indefinite periods
*/
int enclosure_for_each_device(int (*fn)(struct enclosure_device *, void *),
void *data)
{
int error = 0;
struct enclosure_device *edev;
mutex_lock(&container_list_lock);
list_for_each_entry(edev, &container_list, node) {
error = fn(edev, data);
if (error)
break;
}
mutex_unlock(&container_list_lock);
return error;
}
EXPORT_SYMBOL_GPL(enclosure_for_each_device);
/**
* enclosure_register - register device as an enclosure
*
* @dev: device containing the enclosure
* @components: number of components in the enclosure
*
* This sets up the device for being an enclosure. Note that @dev does
* not have to be a dedicated enclosure device. It may be some other type
* of device that additionally responds to enclosure services
*/
struct enclosure_device *
enclosure_register(struct device *dev, const char *name, int components,
struct enclosure_component_callbacks *cb)
{
struct enclosure_device *edev =
kzalloc(sizeof(struct enclosure_device) +
sizeof(struct enclosure_component)*components,
GFP_KERNEL);
int err, i;
BUG_ON(!cb);
if (!edev)
return ERR_PTR(-ENOMEM);
edev->components = components;
edev->cdev.class = &enclosure_class;
edev->cdev.dev = get_device(dev);
edev->cb = cb;
snprintf(edev->cdev.class_id, BUS_ID_SIZE, "%s", name);
err = class_device_register(&edev->cdev);
if (err)
goto err;
for (i = 0; i < components; i++)
edev->component[i].number = -1;
mutex_lock(&container_list_lock);
list_add_tail(&edev->node, &container_list);
mutex_unlock(&container_list_lock);
return edev;
err:
put_device(edev->cdev.dev);
kfree(edev);
return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(enclosure_register);
static struct enclosure_component_callbacks enclosure_null_callbacks;
/**
* enclosure_unregister - remove an enclosure
*
* @edev: the registered enclosure to remove;
*/
void enclosure_unregister(struct enclosure_device *edev)
{
int i;
mutex_lock(&container_list_lock);
list_del(&edev->node);
mutex_unlock(&container_list_lock);
for (i = 0; i < edev->components; i++)
if (edev->component[i].number != -1)
class_device_unregister(&edev->component[i].cdev);
/* prevent any callbacks into service user */
edev->cb = &enclosure_null_callbacks;
class_device_unregister(&edev->cdev);
}
EXPORT_SYMBOL_GPL(enclosure_unregister);
static void enclosure_release(struct class_device *cdev)
{
struct enclosure_device *edev = to_enclosure_device(cdev);
put_device(cdev->dev);
kfree(edev);
}
static void enclosure_component_release(struct class_device *cdev)
{
if (cdev->dev)
put_device(cdev->dev);
class_device_put(cdev->parent);
}
/**
* enclosure_component_register - add a particular component to an enclosure
* @edev: the enclosure to add the component
* @num: the device number
* @type: the type of component being added
* @name: an optional name to appear in sysfs (leave NULL if none)
*
* Registers the component. The name is optional for enclosures that
* give their components a unique name. If not, leave the field NULL
* and a name will be assigned.
*
* Returns a pointer to the enclosure component or an error.
*/
struct enclosure_component *
enclosure_component_register(struct enclosure_device *edev,
unsigned int number,
enum enclosure_component_type type,
const char *name)
{
struct enclosure_component *ecomp;
struct class_device *cdev;
int err;
if (number >= edev->components)
return ERR_PTR(-EINVAL);
ecomp = &edev->component[number];
if (ecomp->number != -1)
return ERR_PTR(-EINVAL);
ecomp->type = type;
ecomp->number = number;
cdev = &ecomp->cdev;
cdev->parent = class_device_get(&edev->cdev);
cdev->class = &enclosure_component_class;
if (name)
snprintf(cdev->class_id, BUS_ID_SIZE, "%s", name);
else
snprintf(cdev->class_id, BUS_ID_SIZE, "%u", number);
err = class_device_register(cdev);
if (err)
ERR_PTR(err);
return ecomp;
}
EXPORT_SYMBOL_GPL(enclosure_component_register);
/**
* enclosure_add_device - add a device as being part of an enclosure
* @edev: the enclosure device being added to.
* @num: the number of the component
* @dev: the device being added
*
* Declares a real device to reside in slot (or identifier) @num of an
* enclosure. This will cause the relevant sysfs links to appear.
* This function may also be used to change a device associated with
* an enclosure without having to call enclosure_remove_device() in
* between.
*
* Returns zero on success or an error.
*/
int enclosure_add_device(struct enclosure_device *edev, int component,
struct device *dev)
{
struct class_device *cdev;
if (!edev || component >= edev->components)
return -EINVAL;
cdev = &edev->component[component].cdev;
class_device_del(cdev);
if (cdev->dev)
put_device(cdev->dev);
cdev->dev = get_device(dev);
return class_device_add(cdev);
}
EXPORT_SYMBOL_GPL(enclosure_add_device);
/**
* enclosure_remove_device - remove a device from an enclosure
* @edev: the enclosure device
* @num: the number of the component to remove
*
* Returns zero on success or an error.
*
*/
int enclosure_remove_device(struct enclosure_device *edev, int component)
{
struct class_device *cdev;
if (!edev || component >= edev->components)
return -EINVAL;
cdev = &edev->component[component].cdev;
class_device_del(cdev);
if (cdev->dev)
put_device(cdev->dev);
cdev->dev = NULL;
return class_device_add(cdev);
}
EXPORT_SYMBOL_GPL(enclosure_remove_device);
/*
* sysfs pieces below
*/
static ssize_t enclosure_show_components(struct class_device *cdev, char *buf)
{
struct enclosure_device *edev = to_enclosure_device(cdev);
return snprintf(buf, 40, "%d\n", edev->components);
}
static struct class_device_attribute enclosure_attrs[] = {
__ATTR(components, S_IRUGO, enclosure_show_components, NULL),
__ATTR_NULL
};
static struct class enclosure_class = {
.name = "enclosure",
.owner = THIS_MODULE,
.release = enclosure_release,
.class_dev_attrs = enclosure_attrs,
};
static const char *const enclosure_status [] = {
[ENCLOSURE_STATUS_UNSUPPORTED] = "unsupported",
[ENCLOSURE_STATUS_OK] = "OK",
[ENCLOSURE_STATUS_CRITICAL] = "critical",
[ENCLOSURE_STATUS_NON_CRITICAL] = "non-critical",
[ENCLOSURE_STATUS_UNRECOVERABLE] = "unrecoverable",
[ENCLOSURE_STATUS_NOT_INSTALLED] = "not installed",
[ENCLOSURE_STATUS_UNKNOWN] = "unknown",
[ENCLOSURE_STATUS_UNAVAILABLE] = "unavailable",
};
static const char *const enclosure_type [] = {
[ENCLOSURE_COMPONENT_DEVICE] = "device",
[ENCLOSURE_COMPONENT_ARRAY_DEVICE] = "array device",
};
static ssize_t get_component_fault(struct class_device *cdev, char *buf)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
if (edev->cb->get_fault)
edev->cb->get_fault(edev, ecomp);
return snprintf(buf, 40, "%d\n", ecomp->fault);
}
static ssize_t set_component_fault(struct class_device *cdev, const char *buf,
size_t count)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
int val = simple_strtoul(buf, NULL, 0);
if (edev->cb->set_fault)
edev->cb->set_fault(edev, ecomp, val);
return count;
}
static ssize_t get_component_status(struct class_device *cdev, char *buf)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
if (edev->cb->get_status)
edev->cb->get_status(edev, ecomp);
return snprintf(buf, 40, "%s\n", enclosure_status[ecomp->status]);
}
static ssize_t set_component_status(struct class_device *cdev, const char *buf,
size_t count)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
int i;
for (i = 0; enclosure_status[i]; i++) {
if (strncmp(buf, enclosure_status[i],
strlen(enclosure_status[i])) == 0 &&
(buf[strlen(enclosure_status[i])] == '\n' ||
buf[strlen(enclosure_status[i])] == '\0'))
break;
}
if (enclosure_status[i] && edev->cb->set_status) {
edev->cb->set_status(edev, ecomp, i);
return count;
} else
return -EINVAL;
}
static ssize_t get_component_active(struct class_device *cdev, char *buf)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
if (edev->cb->get_active)
edev->cb->get_active(edev, ecomp);
return snprintf(buf, 40, "%d\n", ecomp->active);
}
static ssize_t set_component_active(struct class_device *cdev, const char *buf,
size_t count)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
int val = simple_strtoul(buf, NULL, 0);
if (edev->cb->set_active)
edev->cb->set_active(edev, ecomp, val);
return count;
}
static ssize_t get_component_locate(struct class_device *cdev, char *buf)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
if (edev->cb->get_locate)
edev->cb->get_locate(edev, ecomp);
return snprintf(buf, 40, "%d\n", ecomp->locate);
}
static ssize_t set_component_locate(struct class_device *cdev, const char *buf,
size_t count)
{
struct enclosure_device *edev = to_enclosure_device(cdev->parent);
struct enclosure_component *ecomp = to_enclosure_component(cdev);
int val = simple_strtoul(buf, NULL, 0);
if (edev->cb->set_locate)
edev->cb->set_locate(edev, ecomp, val);
return count;
}
static ssize_t get_component_type(struct class_device *cdev, char *buf)
{
struct enclosure_component *ecomp = to_enclosure_component(cdev);
return snprintf(buf, 40, "%s\n", enclosure_type[ecomp->type]);
}
static struct class_device_attribute enclosure_component_attrs[] = {
__ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
set_component_fault),
__ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
set_component_status),
__ATTR(active, S_IRUGO | S_IWUSR, get_component_active,
set_component_active),
__ATTR(locate, S_IRUGO | S_IWUSR, get_component_locate,
set_component_locate),
__ATTR(type, S_IRUGO, get_component_type, NULL),
__ATTR_NULL
};
static struct class enclosure_component_class = {
.name = "enclosure_component",
.owner = THIS_MODULE,
.class_dev_attrs = enclosure_component_attrs,
.release = enclosure_component_release,
};
static int __init enclosure_init(void)
{
int err;
err = class_register(&enclosure_class);
if (err)
return err;
err = class_register(&enclosure_component_class);
if (err)
goto err_out;
return 0;
err_out:
class_unregister(&enclosure_class);
return err;
}
static void __exit enclosure_exit(void)
{
class_unregister(&enclosure_component_class);
class_unregister(&enclosure_class);
}
module_init(enclosure_init);
module_exit(enclosure_exit);
MODULE_AUTHOR("James Bottomley");
MODULE_DESCRIPTION("Enclosure Services");
MODULE_LICENSE("GPL v2");
......@@ -179,7 +179,15 @@ config CHR_DEV_SCH
say M here and read <file:Documentation/kbuild/modules.txt> and
<file:Documentation/scsi/scsi.txt>. The module will be called ch.o.
If unsure, say N.
config SCSI_ENCLOSURE
tristate "SCSI Enclosure Support"
depends on SCSI && ENCLOSURE_SERVICES
help
Enclosures are devices sitting on or in SCSI backplanes that
manage devices. If you have a disk cage, the chances are that
it has an enclosure device. Selecting this option will just allow
certain enclosure conditions to be reported and is not required.
comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs"
depends on SCSI
......@@ -350,17 +358,6 @@ config SGIWD93_SCSI
If you have a Western Digital WD93 SCSI controller on
an SGI MIPS system, say Y. Otherwise, say N.
config SCSI_DECNCR
tristate "DEC NCR53C94 Scsi Driver"
depends on MACH_DECSTATION && SCSI && TC
help
Say Y here to support the NCR53C94 SCSI controller chips on IOASIC
based TURBOchannel DECstations and TURBOchannel PMAZ-A cards.
config SCSI_DECSII
tristate "DEC SII Scsi Driver"
depends on MACH_DECSTATION && SCSI && 32BIT
config BLK_DEV_3W_XXXX_RAID
tristate "3ware 5/6/7/8xxx ATA-RAID support"
depends on PCI && SCSI
......@@ -1263,17 +1260,6 @@ config SCSI_NCR53C8XX_NO_DISCONNECT
not allow targets to disconnect is not reasonable if there is more
than 1 device on a SCSI bus. The normal answer therefore is N.
config SCSI_MCA_53C9X
tristate "NCR MCA 53C9x SCSI support"
depends on MCA_LEGACY && SCSI && BROKEN_ON_SMP
help
Some MicroChannel machines, notably the NCR 35xx line, use a SCSI
controller based on the NCR 53C94. This driver will allow use of
the controller on the 3550, and very possibly others.
To compile this driver as a module, choose M here: the
module will be called mca_53c9x.
config SCSI_PAS16
tristate "PAS16 SCSI support"
depends on ISA && SCSI
......@@ -1600,45 +1586,6 @@ config GVP11_SCSI
To compile this driver as a module, choose M here: the
module will be called gvp11.
config CYBERSTORM_SCSI
tristate "CyberStorm SCSI support"
depends on ZORRO && SCSI
help
If you have an Amiga with an original (MkI) Phase5 Cyberstorm
accelerator board and the optional Cyberstorm SCSI controller,
answer Y. Otherwise, say N.
config CYBERSTORMII_SCSI
tristate "CyberStorm Mk II SCSI support"
depends on ZORRO && SCSI
help
If you have an Amiga with a Phase5 Cyberstorm MkII accelerator board
and the optional Cyberstorm SCSI controller, say Y. Otherwise,
answer N.
config BLZ2060_SCSI
tristate "Blizzard 2060 SCSI support"
depends on ZORRO && SCSI
help
If you have an Amiga with a Phase5 Blizzard 2060 accelerator board
and want to use the onboard SCSI controller, say Y. Otherwise,
answer N.
config BLZ1230_SCSI
tristate "Blizzard 1230IV/1260 SCSI support"
depends on ZORRO && SCSI
help
If you have an Amiga 1200 with a Phase5 Blizzard 1230IV or Blizzard
1260 accelerator, and the optional SCSI module, say Y. Otherwise,
say N.
config FASTLANE_SCSI
tristate "Fastlane SCSI support"
depends on ZORRO && SCSI
help
If you have the Phase5 Fastlane Z3 SCSI controller, or plan to use
one in the near future, say Y to this question. Otherwise, say N.
config SCSI_A4000T
tristate "A4000T NCR53c710 SCSI support (EXPERIMENTAL)"
depends on AMIGA && SCSI && EXPERIMENTAL
......@@ -1666,15 +1613,6 @@ config SCSI_ZORRO7XX
accelerator card for the Amiga 1200,
- the SCSI controller on the GVP Turbo 040/060 accelerator.
config OKTAGON_SCSI
tristate "BSC Oktagon SCSI support (EXPERIMENTAL)"
depends on ZORRO && SCSI && EXPERIMENTAL
help
If you have the BSC Oktagon SCSI disk controller for the Amiga, say
Y to this question. If you're in doubt about whether you have one,
see the picture at
<http://amiga.resource.cx/exp/search.pl?product=oktagon>.
config ATARI_SCSI
tristate "Atari native SCSI support"
depends on ATARI && SCSI
......@@ -1727,18 +1665,6 @@ config MAC_SCSI
SCSI-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
config SCSI_MAC_ESP
tristate "Macintosh NCR53c9[46] SCSI"
depends on MAC && SCSI
help
This is the NCR 53c9x SCSI controller found on most of the 68040
based Macintoshes. If you have one of these say Y and read the
SCSI-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
To compile this driver as a module, choose M here: the
module will be called mac_esp.
config MVME147_SCSI
bool "WD33C93 SCSI driver for MVME147"
depends on MVME147 && SCSI=y
......@@ -1779,6 +1705,7 @@ config SUN3_SCSI
config SUN3X_ESP
bool "Sun3x ESP SCSI"
depends on SUN3X && SCSI=y
select SCSI_SPI_ATTRS
help
The ESP was an on-board SCSI controller used on Sun 3/80
machines. Say Y here to compile in support for it.
......
......@@ -44,15 +44,8 @@ obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o
obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o
obj-$(CONFIG_MVME147_SCSI) += mvme147.o wd33c93.o
obj-$(CONFIG_SGIWD93_SCSI) += sgiwd93.o wd33c93.o
obj-$(CONFIG_CYBERSTORM_SCSI) += NCR53C9x.o cyberstorm.o
obj-$(CONFIG_CYBERSTORMII_SCSI) += NCR53C9x.o cyberstormII.o
obj-$(CONFIG_BLZ2060_SCSI) += NCR53C9x.o blz2060.o
obj-$(CONFIG_BLZ1230_SCSI) += NCR53C9x.o blz1230.o
obj-$(CONFIG_FASTLANE_SCSI) += NCR53C9x.o fastlane.o
obj-$(CONFIG_OKTAGON_SCSI) += NCR53C9x.o oktagon_esp_mod.o
obj-$(CONFIG_ATARI_SCSI) += atari_scsi.o
obj-$(CONFIG_MAC_SCSI) += mac_scsi.o
obj-$(CONFIG_SCSI_MAC_ESP) += mac_esp.o NCR53C9x.o
obj-$(CONFIG_SUN3_SCSI) += sun3_scsi.o sun3_scsi_vme.o
obj-$(CONFIG_MVME16x_SCSI) += 53c700.o mvme16x_scsi.o
obj-$(CONFIG_BVME6000_SCSI) += 53c700.o bvme6000_scsi.o
......@@ -95,7 +88,6 @@ obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/
obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o
obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o
obj-$(CONFIG_SCSI_7000FASST) += wd7000.o
obj-$(CONFIG_SCSI_MCA_53C9X) += NCR53C9x.o mca_53c9x.o
obj-$(CONFIG_SCSI_IBMMCA) += ibmmca.o
obj-$(CONFIG_SCSI_EATA) += eata.o
obj-$(CONFIG_SCSI_DC395x) += dc395x.o
......@@ -112,13 +104,12 @@ obj-$(CONFIG_SCSI_QLOGICPTI) += qlogicpti.o
obj-$(CONFIG_BLK_DEV_IDESCSI) += ide-scsi.o
obj-$(CONFIG_SCSI_MESH) += mesh.o
obj-$(CONFIG_SCSI_MAC53C94) += mac53c94.o
obj-$(CONFIG_SCSI_DECNCR) += NCR53C9x.o dec_esp.o
obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o
obj-$(CONFIG_SCSI_3W_9XXX) += 3w-9xxx.o
obj-$(CONFIG_SCSI_PPA) += ppa.o
obj-$(CONFIG_SCSI_IMM) += imm.o
obj-$(CONFIG_JAZZ_ESP) += esp_scsi.o jazz_esp.o
obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o
obj-$(CONFIG_SUN3X_ESP) += esp_scsi.o sun3x_esp.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
......@@ -138,6 +129,7 @@ obj-$(CONFIG_BLK_DEV_SD) += sd_mod.o
obj-$(CONFIG_BLK_DEV_SR) += sr_mod.o
obj-$(CONFIG_CHR_DEV_SG) += sg.o
obj-$(CONFIG_CHR_DEV_SCH) += ch.o
obj-$(CONFIG_SCSI_ENCLOSURE) += ses.o
# This goes last, so that "real" scsi devices probe earlier
obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o
......
此差异已折叠。
此差异已折叠。
......@@ -859,44 +859,31 @@ static int setinqserial(struct aac_dev *dev, void *data, int cid)
le32_to_cpu(dev->adapter_info.serial[0]), cid);
}
static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
u8 a_sense_code, u8 incorrect_length,
u8 bit_pointer, u16 field_pointer,
u32 residue)
static inline void set_sense(struct sense_data *sense_data, u8 sense_key,
u8 sense_code, u8 a_sense_code, u8 bit_pointer, u16 field_pointer)
{
sense_buf[0] = 0xF0; /* Sense data valid, err code 70h (current error) */
u8 *sense_buf = (u8 *)sense_data;
/* Sense data valid, err code 70h */
sense_buf[0] = 0x70; /* No info field */
sense_buf[1] = 0; /* Segment number, always zero */
if (incorrect_length) {
sense_buf[2] = sense_key | 0x20;/* Set ILI bit | sense key */
sense_buf[3] = BYTE3(residue);
sense_buf[4] = BYTE2(residue);
sense_buf[5] = BYTE1(residue);
sense_buf[6] = BYTE0(residue);
} else
sense_buf[2] = sense_key; /* Sense key */
if (sense_key == ILLEGAL_REQUEST)
sense_buf[7] = 10; /* Additional sense length */
else
sense_buf[7] = 6; /* Additional sense length */
sense_buf[2] = sense_key; /* Sense key */
sense_buf[12] = sense_code; /* Additional sense code */
sense_buf[13] = a_sense_code; /* Additional sense code qualifier */
if (sense_key == ILLEGAL_REQUEST) {
sense_buf[15] = 0;
sense_buf[7] = 10; /* Additional sense length */
if (sense_code == SENCODE_INVALID_PARAM_FIELD)
sense_buf[15] = 0x80;/* Std sense key specific field */
sense_buf[15] = bit_pointer;
/* Illegal parameter is in the parameter block */
if (sense_code == SENCODE_INVALID_CDB_FIELD)
sense_buf[15] = 0xc0;/* Std sense key specific field */
sense_buf[15] |= 0xc0;/* Std sense key specific field */
/* Illegal parameter is in the CDB block */
sense_buf[15] |= bit_pointer;
sense_buf[16] = field_pointer >> 8; /* MSB */
sense_buf[17] = field_pointer; /* LSB */
}
} else
sense_buf[7] = 6; /* Additional sense length */
}
static int aac_bounds_32(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba)
......@@ -906,11 +893,9 @@ static int aac_bounds_32(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba)
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);
set_sense(&dev->fsa_dev[cid].sense_data,
HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
SCSI_SENSE_BUFFERSIZE));
......@@ -1520,11 +1505,9 @@ static void io_callback(void *context, struct fib * fibptr)
le32_to_cpu(readreply->status));
#endif
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);
set_sense(&dev->fsa_dev[cid].sense_data,
HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
SCSI_SENSE_BUFFERSIZE));
......@@ -1733,11 +1716,9 @@ static void synchronize_callback(void *context, struct fib *fibptr)
le32_to_cpu(synchronizereply->status));
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);
set_sense(&dev->fsa_dev[cid].sense_data,
HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
SCSI_SENSE_BUFFERSIZE));
......@@ -1945,10 +1926,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
{
dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for controller, rcvd = 0x%x.\n", scsicmd->cmnd[0]));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
ILLEGAL_REQUEST,
SENCODE_INVALID_COMMAND,
ASENCODE_INVALID_COMMAND, 0, 0, 0, 0);
set_sense(&dev->fsa_dev[cid].sense_data,
ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
ASENCODE_INVALID_COMMAND, 0, 0);
memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
SCSI_SENSE_BUFFERSIZE));
......@@ -1995,10 +1975,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
scsicmd->result = DID_OK << 16 |
COMMAND_COMPLETE << 8 |
SAM_STAT_CHECK_CONDITION;
set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
ILLEGAL_REQUEST,
SENCODE_INVALID_CDB_FIELD,
ASENCODE_NO_SENSE, 0, 7, 2, 0);
set_sense(&dev->fsa_dev[cid].sense_data,
ILLEGAL_REQUEST, SENCODE_INVALID_CDB_FIELD,
ASENCODE_NO_SENSE, 7, 2);
memcpy(scsicmd->sense_buffer,
&dev->fsa_dev[cid].sense_data,
min_t(size_t,
......@@ -2254,9 +2233,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
*/
dprintk((KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
ASENCODE_INVALID_COMMAND, 0, 0, 0, 0);
set_sense(&dev->fsa_dev[cid].sense_data,
ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
ASENCODE_INVALID_COMMAND, 0, 0);
memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
min_t(size_t,
sizeof(dev->fsa_dev[cid].sense_data),
......
......@@ -243,6 +243,7 @@ static int next_getadapter_fib(struct aac_dev * dev, void __user *arg)
* Search the list of AdapterFibContext addresses on the adapter
* to be sure this is a valid address
*/
spin_lock_irqsave(&dev->fib_lock, flags);
entry = dev->fib_list.next;
fibctx = NULL;
......@@ -251,24 +252,25 @@ static int next_getadapter_fib(struct aac_dev * dev, void __user *arg)
/*
* Extract the AdapterFibContext from the Input parameters.
*/
if (fibctx->unique == f.fibctx) { /* We found a winner */
if (fibctx->unique == f.fibctx) { /* We found a winner */
break;
}
entry = entry->next;
fibctx = NULL;
}
if (!fibctx) {
spin_unlock_irqrestore(&dev->fib_lock, flags);
dprintk ((KERN_INFO "Fib Context not found\n"));
return -EINVAL;
}
if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||
(fibctx->size != sizeof(struct aac_fib_context))) {
spin_unlock_irqrestore(&dev->fib_lock, flags);
dprintk ((KERN_INFO "Fib Context corrupt?\n"));
return -EINVAL;
}
status = 0;
spin_lock_irqsave(&dev->fib_lock, flags);
/*
* If there are no fibs to send back, then either wait or return
* -EAGAIN
......@@ -414,8 +416,8 @@ static int close_getadapter_fib(struct aac_dev * dev, void __user *arg)
* @arg: ioctl arguments
*
* This routine returns the driver version.
* Under Linux, there have been no version incompatibilities, so this is
* simple!
* Under Linux, there have been no version incompatibilities, so this is
* simple!
*/
static int check_revision(struct aac_dev *dev, void __user *arg)
......@@ -463,7 +465,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
u32 data_dir;
void __user *sg_user[32];
void *sg_list[32];
u32 sg_indx = 0;
u32 sg_indx = 0;
u32 byte_count = 0;
u32 actual_fibsize64, actual_fibsize = 0;
int i;
......@@ -517,11 +519,11 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
// Fix up srb for endian and force some values
srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this
srbcmd->channel = cpu_to_le32(user_srbcmd->channel);
srbcmd->channel = cpu_to_le32(user_srbcmd->channel);
srbcmd->id = cpu_to_le32(user_srbcmd->id);
srbcmd->lun = cpu_to_le32(user_srbcmd->lun);
srbcmd->timeout = cpu_to_le32(user_srbcmd->timeout);
srbcmd->flags = cpu_to_le32(flags);
srbcmd->lun = cpu_to_le32(user_srbcmd->lun);
srbcmd->timeout = cpu_to_le32(user_srbcmd->timeout);
srbcmd->flags = cpu_to_le32(flags);
srbcmd->retry_limit = 0; // Obsolete parameter
srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);
memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb));
......@@ -786,9 +788,9 @@ static int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
pci_info.bus = dev->pdev->bus->number;
pci_info.slot = PCI_SLOT(dev->pdev->devfn);
if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) {
dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n"));
return -EFAULT;
if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) {
dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n"));
return -EFAULT;
}
return 0;
}
......
......@@ -1130,31 +1130,29 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
if (error < 0)
goto out_deinit;
if (!(aac->adapter_info.options & AAC_OPT_NEW_COMM)) {
error = pci_set_dma_max_seg_size(pdev, 65536);
if (error)
goto out_deinit;
}
/*
* Lets override negotiations and drop the maximum SG limit to 34
*/
if ((aac_drivers[index].quirks & AAC_QUIRK_34SG) &&
(aac->scsi_host_ptr->sg_tablesize > 34)) {
aac->scsi_host_ptr->sg_tablesize = 34;
aac->scsi_host_ptr->max_sectors
= (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
(shost->sg_tablesize > 34)) {
shost->sg_tablesize = 34;
shost->max_sectors = (shost->sg_tablesize * 8) + 112;
}
if ((aac_drivers[index].quirks & AAC_QUIRK_17SG) &&
(aac->scsi_host_ptr->sg_tablesize > 17)) {
aac->scsi_host_ptr->sg_tablesize = 17;
aac->scsi_host_ptr->max_sectors
= (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
(shost->sg_tablesize > 17)) {
shost->sg_tablesize = 17;
shost->max_sectors = (shost->sg_tablesize * 8) + 112;
}
error = pci_set_dma_max_seg_size(pdev,
(aac->adapter_info.options & AAC_OPT_NEW_COMM) ?
(shost->max_sectors << 9) : 65536);
if (error)
goto out_deinit;
/*
* Firware printf works only with older firmware.
* Firmware printf works only with older firmware.
*/
if (aac_drivers[index].quirks & AAC_QUIRK_34SG)
aac->printf_enabled = 1;
......
......@@ -12261,7 +12261,7 @@ static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
/*
* Write the EEPROM from 'cfg_buf'.
*/
void __devinit
static void __devinit
AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
{
ushort *wbuf;
......@@ -12328,7 +12328,7 @@ AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
/*
* Write the EEPROM from 'cfg_buf'.
*/
void __devinit
static void __devinit
AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
{
ushort *wbuf;
......@@ -12395,7 +12395,7 @@ AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
/*
* Write the EEPROM from 'cfg_buf'.
*/
void __devinit
static void __devinit
AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
{
ushort *wbuf;
......
......@@ -48,7 +48,7 @@ struct class_device_attribute;
/*The limit of outstanding scsi command that firmware can handle*/
#define ARCMSR_MAX_OUTSTANDING_CMD 256
#define ARCMSR_MAX_FREECCB_NUM 320
#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2007/08/30"
#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2007/12/24"
#define ARCMSR_SCSI_INITIATOR_ID 255
#define ARCMSR_MAX_XFER_SECTORS 512
#define ARCMSR_MAX_XFER_SECTORS_B 4096
......@@ -248,6 +248,7 @@ struct FIRMWARE_INFO
#define ARCMSR_MESSAGE_START_BGRB 0x00060008
#define ARCMSR_MESSAGE_START_DRIVER_MODE 0x000E0008
#define ARCMSR_MESSAGE_SET_POST_WINDOW 0x000F0008
#define ARCMSR_MESSAGE_ACTIVE_EOI_MODE 0x00100008
/* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */
#define ARCMSR_MESSAGE_FIRMWARE_OK 0x80000000
/* ioctl transfer */
......@@ -256,6 +257,7 @@ struct FIRMWARE_INFO
#define ARCMSR_DRV2IOP_DATA_READ_OK 0x00000002
#define ARCMSR_DRV2IOP_CDB_POSTED 0x00000004
#define ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED 0x00000008
#define ARCMSR_DRV2IOP_END_OF_INTERRUPT 0x00000010
/* data tunnel buffer between user space program and its firmware */
/* user space data to iop 128bytes */
......
......@@ -315,9 +315,6 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
(0x20 - ((unsigned long)dma_coherent_handle & 0x1F));
}
reg = (struct MessageUnit_B *)(dma_coherent +
ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock));
dma_addr = dma_coherent_handle;
ccb_tmp = (struct CommandControlBlock *)dma_coherent;
for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
......@@ -371,8 +368,8 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
out:
dma_free_coherent(&acb->pdev->dev,
ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20,
acb->dma_coherent, acb->dma_coherent_handle);
(ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 +
sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle);
return -ENOMEM;
}
......@@ -509,6 +506,7 @@ static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
& ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN
, reg->iop2drv_doorbell_reg);
writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg);
return 0x00;
}
msleep(10);
......@@ -748,6 +746,7 @@ static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, uint32_t fla
, ccb->startdone
, atomic_read(&acb->ccboutstandingcount));
}
else
arcmsr_report_ccb_state(acb, ccb, flag_ccb);
}
......@@ -886,7 +885,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \
}
}
static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
static int arcmsr_build_ccb(struct AdapterControlBlock *acb,
struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd)
{
struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb;
......@@ -906,6 +905,8 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len);
nseg = scsi_dma_map(pcmd);
if (nseg > ARCMSR_MAX_SG_ENTRIES)
return FAILED;
BUG_ON(nseg < 0);
if (nseg) {
......@@ -946,6 +947,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
ccb->ccb_flags |= CCB_FLAG_WRITE;
}
return SUCCESS;
}
static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb)
......@@ -1036,18 +1038,22 @@ static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb)
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
iounmap(acb->pmuA);
dma_free_coherent(&acb->pdev->dev,
ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20,
acb->dma_coherent,
acb->dma_coherent_handle);
break;
}
case ACB_ADAPTER_TYPE_B: {
struct MessageUnit_B *reg = acb->pmuB;
iounmap(reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL);
iounmap(reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER);
dma_free_coherent(&acb->pdev->dev,
(ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 +
sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle);
}
}
dma_free_coherent(&acb->pdev->dev,
ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20,
acb->dma_coherent,
acb->dma_coherent_handle);
}
void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
......@@ -1273,7 +1279,9 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb)
return 1;
writel(~outbound_doorbell, reg->iop2drv_doorbell_reg);
/*in case the last action of doorbell interrupt clearance is cached, this action can push HW to write down the clear bit*/
readl(reg->iop2drv_doorbell_reg);
writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg);
if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) {
arcmsr_iop2drv_data_wrote_handle(acb);
}
......@@ -1380,12 +1388,13 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
case ARCMSR_MESSAGE_READ_RQBUFFER: {
unsigned long *ver_addr;
dma_addr_t buf_handle;
uint8_t *pQbuffer, *ptmpQbuffer;
int32_t allxfer_len = 0;
void *tmp;
ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle);
if (!ver_addr) {
tmp = kmalloc(1032, GFP_KERNEL|GFP_DMA);
ver_addr = (unsigned long *)tmp;
if (!tmp) {
retvalue = ARCMSR_MESSAGE_FAIL;
goto message_out;
}
......@@ -1421,18 +1430,19 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
memcpy(pcmdmessagefld->messagedatabuffer, (uint8_t *)ver_addr, allxfer_len);
pcmdmessagefld->cmdmessage.Length = allxfer_len;
pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle);
kfree(tmp);
}
break;
case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
unsigned long *ver_addr;
dma_addr_t buf_handle;
int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
uint8_t *pQbuffer, *ptmpuserbuffer;
void *tmp;
ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle);
if (!ver_addr) {
tmp = kmalloc(1032, GFP_KERNEL|GFP_DMA);
ver_addr = (unsigned long *)tmp;
if (!tmp) {
retvalue = ARCMSR_MESSAGE_FAIL;
goto message_out;
}
......@@ -1482,7 +1492,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
retvalue = ARCMSR_MESSAGE_FAIL;
}
}
pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle);
kfree(tmp);
}
break;
......@@ -1682,8 +1692,11 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
ccb = arcmsr_get_freeccb(acb);
if (!ccb)
return SCSI_MLQUEUE_HOST_BUSY;
arcmsr_build_ccb(acb, ccb, cmd);
if ( arcmsr_build_ccb( acb, ccb, cmd ) == FAILED ) {
cmd->result = (DID_ERROR << 16) | (RESERVATION_CONFLICT << 1);
cmd->scsi_done(cmd);
return 0;
}
arcmsr_post_ccb(acb, ccb);
return 0;
}
......@@ -1844,7 +1857,7 @@ static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb,
}
}
static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \
static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb,
struct CommandControlBlock *poll_ccb)
{
struct MessageUnit_B *reg = acb->pmuB;
......@@ -1878,7 +1891,7 @@ static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \
(acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/
poll_ccb_done = (ccb == poll_ccb) ? 1:0;
if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) {
if (ccb->startdone == ARCMSR_CCB_ABORTED) {
if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) {
printk(KERN_NOTICE "arcmsr%d: \
scsi id = %d lun = %d ccb = '0x%p' poll command abort successfully \n"
,acb->host->host_no
......@@ -1901,7 +1914,7 @@ static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \
} /*drain reply FIFO*/
}
static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, \
static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
struct CommandControlBlock *poll_ccb)
{
switch (acb->adapter_type) {
......@@ -2026,6 +2039,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
do {
firmware_state = readl(reg->iop2drv_doorbell_reg);
} while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0);
writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg);
}
break;
}
......@@ -2090,19 +2104,39 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb)
}
}
static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A:
return;
case ACB_ADAPTER_TYPE_B:
{
struct MessageUnit_B *reg = acb->pmuB;
writel(ARCMSR_MESSAGE_ACTIVE_EOI_MODE, reg->drv2iop_doorbell_reg);
if(arcmsr_hbb_wait_msgint_ready(acb)) {
printk(KERN_NOTICE "ARCMSR IOP enables EOI_MODE TIMEOUT");
return;
}
}
break;
}
return;
}
static void arcmsr_iop_init(struct AdapterControlBlock *acb)
{
uint32_t intmask_org;
arcmsr_wait_firmware_ready(acb);
arcmsr_iop_confirm(acb);
/* disable all outbound interrupt */
intmask_org = arcmsr_disable_outbound_ints(acb);
arcmsr_wait_firmware_ready(acb);
arcmsr_iop_confirm(acb);
arcmsr_get_firmware_spec(acb);
/*start background rebuild*/
arcmsr_start_adapter_bgrb(acb);
/* empty doorbell Qbuffer if door bell ringed */
arcmsr_clear_doorbell_queue_buffer(acb);
arcmsr_enable_eoi_mode(acb);
/* enable outbound Post Queue,outbound doorbell Interrupt */
arcmsr_enable_outbound_ints(acb, intmask_org);
acb->acb_flags |= ACB_F_IOP_INITED;
......@@ -2275,6 +2309,7 @@ static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev)
arcmsr_start_adapter_bgrb(acb);
/* empty doorbell Qbuffer if door bell ringed */
arcmsr_clear_doorbell_queue_buffer(acb);
arcmsr_enable_eoi_mode(acb);
/* enable outbound Post Queue,outbound doorbell Interrupt */
arcmsr_enable_outbound_ints(acb, intmask_org);
acb->acb_flags |= ACB_F_IOP_INITED;
......
......@@ -1790,7 +1790,7 @@ int acornscsi_starttransfer(AS_Host *host)
return 0;
}
residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred;
residual = scsi_bufflen(host->SCpnt) - host->scsi.SCp.scsi_xferred;
sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer);
sbic_arm_writenext(host->scsi.io_port, residual >> 16);
......@@ -2270,7 +2270,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq)
case 0x4b: /* -> PHASE_STATUSIN */
case 0x8b: /* -> PHASE_STATUSIN */
/* DATA IN -> STATUS */
host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
acornscsi_sbic_xfcount(host);
acornscsi_dma_stop(host);
acornscsi_readstatusbyte(host);
......@@ -2281,7 +2281,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq)
case 0x4e: /* -> PHASE_MSGOUT */
case 0x8e: /* -> PHASE_MSGOUT */
/* DATA IN -> MESSAGE OUT */
host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
acornscsi_sbic_xfcount(host);
acornscsi_dma_stop(host);
acornscsi_sendmessage(host);
......@@ -2291,7 +2291,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq)
case 0x4f: /* message in */
case 0x8f: /* message in */
/* DATA IN -> MESSAGE IN */
host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
acornscsi_sbic_xfcount(host);
acornscsi_dma_stop(host);
acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
......@@ -2319,7 +2319,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq)
case 0x4b: /* -> PHASE_STATUSIN */
case 0x8b: /* -> PHASE_STATUSIN */
/* DATA OUT -> STATUS */
host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
acornscsi_sbic_xfcount(host);
acornscsi_dma_stop(host);
acornscsi_dma_adjust(host);
......@@ -2331,7 +2331,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq)
case 0x4e: /* -> PHASE_MSGOUT */
case 0x8e: /* -> PHASE_MSGOUT */
/* DATA OUT -> MESSAGE OUT */
host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
acornscsi_sbic_xfcount(host);
acornscsi_dma_stop(host);
acornscsi_dma_adjust(host);
......@@ -2342,7 +2342,7 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq)
case 0x4f: /* message in */
case 0x8f: /* message in */
/* DATA OUT -> MESSAGE IN */
host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) -
acornscsi_sbic_xfcount(host);
acornscsi_dma_stop(host);
acornscsi_dma_adjust(host);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -4267,7 +4267,7 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
int srb_idx = 0;
unsigned i = 0;
struct SGentry *ptr;
struct SGentry *uninitialized_var(ptr);
for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
acb->srb_array[i].segment_x = NULL;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册