18611 lines
579 KiB
Plaintext
18611 lines
579 KiB
Plaintext
From: Hannes Reinecke <hare@suse.de>
|
|
Date: Tue, 24 Nov 2009 14:40:54 +0100
|
|
Subject: Update MPT Fusion driver to 4.22.00.00-suse
|
|
References: bnc#556587
|
|
Patch-Mainline: No
|
|
|
|
This patch updates the MPT Fusion driver to version 4.22.00.00-suse.
|
|
|
|
Signed-off-by: Hannes Reinecke <hare@suse.de>
|
|
|
|
---
|
|
drivers/message/fusion/Kconfig | 16
|
|
drivers/message/fusion/Makefile | 13
|
|
drivers/message/fusion/csmi/csmisas.c | 5805 +++++++++++++++++++
|
|
drivers/message/fusion/csmi/csmisas.h | 1854 ++++++
|
|
drivers/message/fusion/lsi/mpi.h | 5
|
|
drivers/message/fusion/lsi/mpi_cnfg.h | 21
|
|
drivers/message/fusion/lsi/mpi_history.txt | 55
|
|
drivers/message/fusion/lsi/mpi_log_sas.h | 14
|
|
drivers/message/fusion/lsi/mpi_type.h | 15
|
|
drivers/message/fusion/mptbase.c | 802 +-
|
|
drivers/message/fusion/mptbase.h | 250
|
|
drivers/message/fusion/mptctl.c | 648 +-
|
|
drivers/message/fusion/mptctl.h | 5
|
|
drivers/message/fusion/mptdebug.h | 11
|
|
drivers/message/fusion/mptfc.c | 173
|
|
drivers/message/fusion/mptlan.c | 222
|
|
drivers/message/fusion/mptlan.h | 2
|
|
drivers/message/fusion/mptsas.c | 1359 +++-
|
|
drivers/message/fusion/mptsas.h | 60
|
|
drivers/message/fusion/mptscsih.c | 1043 ++-
|
|
drivers/message/fusion/mptscsih.h | 13
|
|
drivers/message/fusion/mptspi.c | 262
|
|
drivers/message/fusion/rejected_ioctls/diag_buffer.c | 671 ++
|
|
drivers/message/fusion/rejected_ioctls/diag_buffer.h | 101
|
|
24 files changed, 12081 insertions(+), 1339 deletions(-)
|
|
|
|
--- a/drivers/message/fusion/Kconfig
|
|
+++ b/drivers/message/fusion/Kconfig
|
|
@@ -61,13 +61,25 @@ config FUSION_SAS
|
|
LSISAS1078
|
|
|
|
config FUSION_MAX_SGE
|
|
- int "Maximum number of scatter gather entries (16 - 128)"
|
|
+ int "Maximum number of scatter gather entries for SAS and SPI (16 - 128)"
|
|
default "128"
|
|
range 16 128
|
|
help
|
|
This option allows you to specify the maximum number of scatter-
|
|
gather entries per I/O. The driver default is 128, which matches
|
|
- SCSI_MAX_PHYS_SEGMENTS. However, it may decreased down to 16.
|
|
+ SAFE_PHYS_SEGMENTS. However, it may decreased down to 16.
|
|
+ Decreasing this parameter will reduce memory requirements
|
|
+ on a per controller instance.
|
|
+
|
|
+config FUSION_MAX_FC_SGE
|
|
+ int "Maximum number of scatter gather entries for FC (16 - 256)"
|
|
+ depends on FUSION_FC
|
|
+ default "256"
|
|
+ range 16 256
|
|
+ help
|
|
+ This option allows you to specify the maximum number of scatter-
|
|
+ gather entries per I/O. The driver default is 256, which matches
|
|
+ MAX_PHYS_SEGMENTS. However, it may decreased down to 16.
|
|
Decreasing this parameter will reduce memory requirements
|
|
on a per controller instance.
|
|
|
|
--- a/drivers/message/fusion/Makefile
|
|
+++ b/drivers/message/fusion/Makefile
|
|
@@ -1,12 +1,17 @@
|
|
-# Fusion MPT drivers; recognized debug defines...
|
|
+#
|
|
+# LSI mpt fusion
|
|
+#
|
|
+
|
|
+# csmi ioctls enable
|
|
+EXTRA_CFLAGS += -DCPQ_CIM
|
|
+EXTRA_CFLAGS += -DDIAG_BUFFER_SUPPORT
|
|
+
|
|
+EXTRA_CFLAGS += -DCONFIG_FUSION_LOGGING
|
|
|
|
# enable verbose logging
|
|
# CONFIG_FUSION_LOGGING needs to be enabled in Kconfig
|
|
#EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE
|
|
|
|
-
|
|
-#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
|
|
-
|
|
obj-$(CONFIG_FUSION_SPI) += mptbase.o mptscsih.o mptspi.o
|
|
obj-$(CONFIG_FUSION_FC) += mptbase.o mptscsih.o mptfc.o
|
|
obj-$(CONFIG_FUSION_SAS) += mptbase.o mptscsih.o mptsas.o
|
|
--- /dev/null
|
|
+++ b/drivers/message/fusion/csmi/csmisas.c
|
|
@@ -0,0 +1,5805 @@
|
|
+/*
|
|
+ * linux/drivers/message/fusion/csmi/csmisas.c
|
|
+ * For use with LSI PCI chip/adapter(s)
|
|
+ * running LSI Fusion MPT (Message Passing Technology) firmware.
|
|
+ *
|
|
+ * Copyright (c) 1999-2008 LSI Corporation
|
|
+ * (mailto:DL-MPTFusionLinux@lsi.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; version 2 of the License.
|
|
+
|
|
+ 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.
|
|
+
|
|
+ NO WARRANTY
|
|
+ THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
+ CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
|
|
+ LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
|
|
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
|
|
+ solely responsible for determining the appropriateness of using and
|
|
+ distributing the Program and assumes all risks associated with its
|
|
+ exercise of rights under this Agreement, including but not limited to
|
|
+ the risks and costs of program errors, damage to or loss of data,
|
|
+ programs or equipment, and unavailability or interruption of operations.
|
|
+
|
|
+ DISCLAIMER OF LIABILITY
|
|
+ NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
|
|
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
+ DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
|
|
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
|
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
|
+ USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
|
|
+ HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
|
|
+
|
|
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
+*/
|
|
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
+
|
|
+#define MPT_CSMI_DESCRIPTION "LSI Corporation: Fusion MPT Driver "MPT_LINUX_VERSION_COMMON
|
|
+#define csmisas_is_this_sas_cntr(ioc) (ioc->bus_type == SAS) ? 1 : 0
|
|
+
|
|
+static int csmisas_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus,
|
|
+ u8 VolumeId, pMpiRaidActionReply_t reply);
|
|
+static u8 map_sas_status_to_csmi(u8 mpi_sas_status);
|
|
+
|
|
+/**
|
|
+ * reverse_byte_order64
|
|
+ *
|
|
+ * @data64
|
|
+ *
|
|
+ **/
|
|
+static u64
|
|
+reverse_byte_order64(u64 data64)
|
|
+{
|
|
+ int i;
|
|
+ u64 rc;
|
|
+ u8 *inWord = (u8*)&data64, *outWord = (u8*)&rc;
|
|
+
|
|
+ for (i = 0 ; i < 8 ; i++)
|
|
+ outWord[i] = inWord[7-i];
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_is_sata
|
|
+ *
|
|
+ * @phys_disk
|
|
+ *
|
|
+ **/
|
|
+static int
|
|
+csmisas_is_sata(RaidPhysDiskPage0_t *phys_disk)
|
|
+{
|
|
+ if ((phys_disk->ExtDiskIdentifier[0] == 'A') &&
|
|
+ (phys_disk->ExtDiskIdentifier[1] == 'T') &&
|
|
+ (phys_disk->ExtDiskIdentifier[2] == 'A'))
|
|
+ return 1;
|
|
+ else
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_is_end_device
|
|
+ *
|
|
+ * @attached
|
|
+ *
|
|
+ **/
|
|
+static inline int
|
|
+csmisas_is_end_device(struct mptsas_devinfo * attached)
|
|
+{
|
|
+ if ((attached->sas_address) &&
|
|
+ (attached->device_info &
|
|
+ MPI_SAS_DEVICE_INFO_END_DEVICE) &&
|
|
+ ((attached->device_info &
|
|
+ MPI_SAS_DEVICE_INFO_SSP_TARGET) |
|
|
+ (attached->device_info &
|
|
+ MPI_SAS_DEVICE_INFO_STP_TARGET) |
|
|
+ (attached->device_info &
|
|
+ MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
|
|
+ return 1;
|
|
+ else
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_is_phys_disk
|
|
+ *
|
|
+ * returns (1) success (0) fail - not a phys disk
|
|
+ **/
|
|
+static int
|
|
+csmisas_is_phys_disk(MPT_ADAPTER *ioc, int channel, int id)
|
|
+{
|
|
+ struct inactive_raid_component_info *component_info;
|
|
+ int i;
|
|
+ int rc = 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) &&
|
|
+ (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
|
|
+ rc = 1;
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * 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;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_raid_id_to_num
|
|
+ *
|
|
+ * Obtains the phys disk num for given H:C:T nexus
|
|
+ *
|
|
+ * input (channel/id)
|
|
+ * output (phys disk number - used by SCSI_IO_PASSTHRU to access hidden component)
|
|
+ *
|
|
+ * returns - signed return means failure
|
|
+ **/
|
|
+static s8
|
|
+csmisas_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
|
|
+{
|
|
+ struct inactive_raid_component_info *component_info;
|
|
+ int i;
|
|
+ s8 rc = -ENXIO;
|
|
+
|
|
+ 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;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * 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;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_get_device_component_by_os
|
|
+ *
|
|
+ * Obtain device component object by operating system mapping
|
|
+ *
|
|
+ * @ioc
|
|
+ * @channel
|
|
+ * @id
|
|
+ *
|
|
+ **/
|
|
+static struct sas_device_info *
|
|
+csmisas_get_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id)
|
|
+{
|
|
+ struct sas_device_info *sas_info, *p;
|
|
+
|
|
+ sas_info = NULL;
|
|
+
|
|
+ down(&ioc->sas_device_info_mutex);
|
|
+ list_for_each_entry(p, &ioc->sas_device_info_list, list) {
|
|
+ if (p->os.channel == channel && p->os.id == id) {
|
|
+ sas_info = p;
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ out:
|
|
+ up(&ioc->sas_device_info_mutex);
|
|
+ return sas_info;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_get_device_component
|
|
+ *
|
|
+ * Obtain device component object by firmware system mapping
|
|
+ *
|
|
+ * @ioc
|
|
+ * @channel
|
|
+ * @id
|
|
+ *
|
|
+ **/
|
|
+static struct sas_device_info *
|
|
+csmisas_get_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
|
|
+{
|
|
+ struct sas_device_info *sas_info, *p;
|
|
+
|
|
+ sas_info = NULL;
|
|
+
|
|
+ down(&ioc->sas_device_info_mutex);
|
|
+ list_for_each_entry(p, &ioc->sas_device_info_list, list) {
|
|
+ if (p->fw.channel == channel && p->fw.id == id) {
|
|
+ sas_info = p;
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ out:
|
|
+ up(&ioc->sas_device_info_mutex);
|
|
+ return sas_info;
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * csmisas_get_device_component_by_sas_addr
|
|
+ *
|
|
+ * Obtain device component object by sas address
|
|
+ *
|
|
+ * @ioc
|
|
+ * @channel
|
|
+ * @id
|
|
+ *
|
|
+ **/
|
|
+static struct sas_device_info *
|
|
+csmisas_get_device_component_by_sas_addr(MPT_ADAPTER *ioc, u64 sas_address)
|
|
+{
|
|
+ struct sas_device_info *sas_info, *p;
|
|
+
|
|
+ sas_info = NULL;
|
|
+
|
|
+ down(&ioc->sas_device_info_mutex);
|
|
+ list_for_each_entry(p, &ioc->sas_device_info_list, list) {
|
|
+ if (p->sas_address == sas_address) {
|
|
+ sas_info = p;
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ out:
|
|
+ up(&ioc->sas_device_info_mutex);
|
|
+ return sas_info;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_send_command_wait
|
|
+ *
|
|
+ * Send mf to firmware
|
|
+ *
|
|
+ * @ioc
|
|
+ * @mf
|
|
+ * @timeout - timeout
|
|
+ *
|
|
+ * Return: 0 for success
|
|
+ * non-zero, failure
|
|
+ **/
|
|
+static int
|
|
+csmisas_send_command_wait(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, unsigned long timeout)
|
|
+{
|
|
+ int rc;
|
|
+ unsigned long timeleft;
|
|
+
|
|
+ timeout = max_t(unsigned long, MPT_IOCTL_DEFAULT_TIMEOUT, timeout);
|
|
+ rc = 0;
|
|
+ timeleft = 0;
|
|
+
|
|
+ SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context,
|
|
+ mf->u.hdr.MsgContext);
|
|
+ INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
|
|
+ mpt_put_msg_frame(mptctl_id, ioc, mf);
|
|
+ timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done, timeout*HZ);
|
|
+ if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
+ rc = -1;
|
|
+ printk("%s: failed\n", __FUNCTION__);
|
|
+ if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
|
|
+ return rc;
|
|
+ }
|
|
+ if (!timeleft)
|
|
+ mptctl_timeout_expired(ioc, mf);
|
|
+ }
|
|
+ SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_send_handshake_wait
|
|
+ *
|
|
+ * Handshake a mf to firmware
|
|
+ *
|
|
+ * @ioc
|
|
+ * @mf
|
|
+ * @mf_size
|
|
+ * @timeout - timeout
|
|
+ *
|
|
+ * Return: 0 for success
|
|
+ * non-zero, failure
|
|
+ **/
|
|
+static int
|
|
+csmisas_send_handshake_wait(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, unsigned long timeout)
|
|
+{
|
|
+ int rc;
|
|
+ unsigned long timeleft;
|
|
+
|
|
+ timeout = max_t(unsigned long, MPT_IOCTL_DEFAULT_TIMEOUT, timeout);
|
|
+ rc = 0;
|
|
+ timeleft = 0;
|
|
+
|
|
+ INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
|
|
+ mpt_put_msg_frame_hi_pri(mptctl_taskmgmt_id, ioc, mf);
|
|
+ timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ);
|
|
+ if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
+ rc = -1;
|
|
+ printk("%s: failed\n", __FUNCTION__);
|
|
+ mpt_clear_taskmgmt_in_progress_flag(ioc);
|
|
+ if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
|
|
+ return rc;
|
|
+ }
|
|
+ if (!timeleft)
|
|
+ mptctl_timeout_expired(ioc, mf);
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_get_number_hotspares - returns num hot spares in this ioc
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ *
|
|
+ * Return: number of hotspares
|
|
+ *
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_number_hotspares(MPT_ADAPTER *ioc)
|
|
+{
|
|
+ ConfigPageHeader_t hdr;
|
|
+ CONFIGPARMS cfg;
|
|
+ IOCPage5_t *buffer = NULL;
|
|
+ dma_addr_t dma_handle;
|
|
+ int data_sz;
|
|
+ int rc;
|
|
+
|
|
+ memset(&hdr, 0, sizeof(ConfigPageHeader_t));
|
|
+ memset(&cfg, 0, sizeof(CONFIGPARMS));
|
|
+
|
|
+ rc = 0;
|
|
+ data_sz = 0;
|
|
+ hdr.PageNumber = 5;
|
|
+ hdr.PageType = MPI_CONFIG_PAGETYPE_IOC;
|
|
+ cfg.cfghdr.hdr = &hdr;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+
|
|
+ if (mpt_config(ioc, &cfg) != 0)
|
|
+ goto get_ioc_pg5;
|
|
+
|
|
+ if (hdr.PageLength == 0)
|
|
+ goto get_ioc_pg5;
|
|
+
|
|
+ data_sz = hdr.PageLength * 4;
|
|
+ buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev,
|
|
+ data_sz, &dma_handle);
|
|
+ if (!buffer)
|
|
+ goto get_ioc_pg5;
|
|
+
|
|
+ memset((u8 *)buffer, 0, data_sz);
|
|
+ cfg.physAddr = dma_handle;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+
|
|
+ if (mpt_config(ioc, &cfg) != 0)
|
|
+ goto get_ioc_pg5;
|
|
+
|
|
+ rc = buffer->NumHotSpares;
|
|
+
|
|
+ get_ioc_pg5:
|
|
+
|
|
+ if (buffer)
|
|
+ pci_free_consistent(ioc->pcidev, data_sz,
|
|
+ (u8 *) buffer, dma_handle);
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * csmisas_get_ioc_pg5 - ioc Page 5 hot spares
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @pIocPage5: ioc page 5
|
|
+ * @data_size: expected data size(units=bytes)
|
|
+ *
|
|
+ * Return: 0 for success
|
|
+ * -ENOMEM if no memory available
|
|
+ * -EPERM if not allowed due to ISR context
|
|
+ * -EAGAIN if no msg frames currently available
|
|
+ * -EFAULT for non-successful reply or no reply (timeout)
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_ioc_pg5(MPT_ADAPTER *ioc, IOCPage5_t *iocPage5, int data_size)
|
|
+{
|
|
+ ConfigPageHeader_t hdr;
|
|
+ CONFIGPARMS cfg;
|
|
+ IOCPage5_t *buffer = NULL;
|
|
+ dma_addr_t dma_handle;
|
|
+ int data_sz;
|
|
+ int rc;
|
|
+
|
|
+ memset(&hdr, 0, sizeof(ConfigPageHeader_t));
|
|
+ memset(&cfg, 0, sizeof(CONFIGPARMS));
|
|
+
|
|
+ rc = 0;
|
|
+ data_sz = 0;
|
|
+ hdr.PageNumber = 5;
|
|
+ hdr.PageType = MPI_CONFIG_PAGETYPE_IOC;
|
|
+ cfg.cfghdr.hdr = &hdr;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0)
|
|
+ goto get_ioc_pg5;
|
|
+
|
|
+ if (hdr.PageLength == 0) {
|
|
+ rc = -EFAULT;
|
|
+ goto get_ioc_pg5;
|
|
+ }
|
|
+
|
|
+ data_sz = hdr.PageLength * 4;
|
|
+ buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev,
|
|
+ data_sz, &dma_handle);
|
|
+ if (!buffer) {
|
|
+ rc = -ENOMEM;
|
|
+ goto get_ioc_pg5;
|
|
+ }
|
|
+
|
|
+ memset((u8 *)buffer, 0, data_sz);
|
|
+ cfg.physAddr = dma_handle;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0)
|
|
+ goto get_ioc_pg5;
|
|
+
|
|
+ memcpy(iocPage5, buffer, data_size);
|
|
+
|
|
+ get_ioc_pg5:
|
|
+
|
|
+ if (buffer)
|
|
+ pci_free_consistent(ioc->pcidev, data_sz,
|
|
+ (u8 *) buffer, dma_handle);
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_sas_device_pg0 - sas device page 0
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @mptsas_devinfo: structure found in mptsas.h
|
|
+ * @form, @form_specific - defines the Page Address field in the config page
|
|
+ * (pls refer to chapter 5.1 in the mpi spec)
|
|
+ *
|
|
+ * Return: 0 for success
|
|
+ * -ENOMEM if no memory available
|
|
+ * -EPERM if not allowed due to ISR context
|
|
+ * -EAGAIN if no msg frames currently available
|
|
+ * -EFAULT for non-successful reply or no reply (timeout)
|
|
+ **/
|
|
+static int
|
|
+csmisas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
|
|
+ u32 form, u32 form_specific)
|
|
+{
|
|
+ ConfigExtendedPageHeader_t hdr;
|
|
+ CONFIGPARMS cfg;
|
|
+ SasDevicePage0_t *buffer;
|
|
+ dma_addr_t dma_handle;
|
|
+ u64 sas_address;
|
|
+ int rc;
|
|
+
|
|
+ rc = 0;
|
|
+ hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
|
|
+ hdr.ExtPageLength = 0;
|
|
+ hdr.PageNumber = 0;
|
|
+ hdr.Reserved1 = 0;
|
|
+ hdr.Reserved2 = 0;
|
|
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
|
|
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
|
|
+
|
|
+ cfg.cfghdr.ehdr = &hdr;
|
|
+ cfg.pageAddr = form + form_specific;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0; /* read */
|
|
+ cfg.timeout = 10;
|
|
+
|
|
+ memset(device_info, 0, sizeof(struct mptsas_devinfo));
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0)
|
|
+ goto out;
|
|
+
|
|
+ if (!hdr.ExtPageLength) {
|
|
+ rc = -ENXIO;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ buffer = pci_alloc_consistent(ioc->pcidev,
|
|
+ hdr.ExtPageLength * 4, &dma_handle);
|
|
+ if (!buffer) {
|
|
+ rc = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ cfg.physAddr = dma_handle;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0)
|
|
+ goto out_free_consistent;
|
|
+
|
|
+ device_info->handle = le16_to_cpu(buffer->DevHandle);
|
|
+ device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
|
|
+ device_info->handle_enclosure =
|
|
+ le16_to_cpu(buffer->EnclosureHandle);
|
|
+ device_info->slot = le16_to_cpu(buffer->Slot);
|
|
+ device_info->phy_id = buffer->PhyNum;
|
|
+ device_info->port_id = buffer->PhysicalPort;
|
|
+ device_info->id = buffer->TargetID;
|
|
+ device_info->channel = buffer->Bus;
|
|
+ memcpy(&sas_address, &buffer->SASAddress, sizeof(u64));
|
|
+ device_info->sas_address = le64_to_cpu(sas_address);
|
|
+ device_info->device_info =
|
|
+ le32_to_cpu(buffer->DeviceInfo);
|
|
+
|
|
+ out_free_consistent:
|
|
+ pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
|
|
+ buffer, dma_handle);
|
|
+ out:
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Routine for the CSMI Sas Get Driver Info command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_driver_info(unsigned long arg)
|
|
+{
|
|
+
|
|
+ CSMI_SAS_DRIVER_INFO_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_DRIVER_INFO_BUFFER karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ int iocnum;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Unable to read in csmi_sas_get_driver_info_buffer struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ /* Fill in the data and return the structure to the calling
|
|
+ * program
|
|
+ */
|
|
+ memcpy( karg.Information.szName, MPT_MISCDEV_BASENAME,
|
|
+ sizeof(MPT_MISCDEV_BASENAME));
|
|
+ memcpy( karg.Information.szDescription, MPT_CSMI_DESCRIPTION,
|
|
+ sizeof(MPT_CSMI_DESCRIPTION));
|
|
+
|
|
+ karg.Information.usMajorRevision = MPT_LINUX_MAJOR_VERSION;
|
|
+ karg.Information.usMinorRevision = MPT_LINUX_MINOR_VERSION;
|
|
+ karg.Information.usBuildRevision = MPT_LINUX_BUILD_VERSION;
|
|
+ karg.Information.usReleaseRevision = MPT_LINUX_RELEASE_VERSION;
|
|
+
|
|
+ karg.Information.usCSMIMajorRevision = CSMI_MAJOR_REVISION;
|
|
+ karg.Information.usCSMIMinorRevision = CSMI_MINOR_REVISION;
|
|
+
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, &karg,
|
|
+ sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Unable to write out csmi_sas_get_driver_info_buffer @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI_SAS_GET_CNTLR_CONFIG command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_cntlr_config(unsigned long arg)
|
|
+{
|
|
+
|
|
+ CSMI_SAS_CNTLR_CONFIG_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_CNTLR_CONFIG_BUFFER karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ int iocnum;
|
|
+ u64 mem_phys;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_CONFIG_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Unable to read in csmi_sas_get_cntlr_config_buffer struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ /* Clear the struct before filling in data. */
|
|
+ memset( &karg.Configuration, 0, sizeof(CSMI_SAS_CNTLR_CONFIG));
|
|
+
|
|
+ /* Fill in the data and return the structure to the calling
|
|
+ * program
|
|
+ */
|
|
+
|
|
+ karg.Configuration.uBaseIoAddress = ioc->pio_mem_phys;
|
|
+ karg.Configuration.BaseMemoryAddress.uLowPart = ioc->mem_phys;
|
|
+ if (sizeof(ioc->mem_phys) == sizeof(u64)) {
|
|
+ mem_phys = ioc->mem_phys;
|
|
+ karg.Configuration.BaseMemoryAddress.uHighPart =
|
|
+ (u32)(mem_phys >> 32);
|
|
+ }
|
|
+
|
|
+ karg.Configuration.uBoardID = (ioc->pcidev->subsystem_device << 16) |
|
|
+ (ioc->pcidev->subsystem_vendor);
|
|
+
|
|
+ karg.Configuration.usSlotNumber =
|
|
+ (ioc->pci_slot_number = 0xff) ?
|
|
+ SLOT_NUMBER_UNKNOWN : ioc->pci_slot_number;
|
|
+ karg.Configuration.bControllerClass = CSMI_SAS_CNTLR_CLASS_HBA;
|
|
+ karg.Configuration.bIoBusType = CSMI_SAS_BUS_TYPE_PCI;
|
|
+ karg.Configuration.BusAddress.PciAddress.bBusNumber =
|
|
+ ioc->pcidev->bus->number;
|
|
+ karg.Configuration.BusAddress.PciAddress.bDeviceNumber =
|
|
+ PCI_SLOT(ioc->pcidev->devfn);
|
|
+ karg.Configuration.BusAddress.PciAddress.bFunctionNumber =
|
|
+ PCI_FUNC(ioc->pcidev->devfn);
|
|
+ karg.Configuration.BusAddress.PciAddress.bReserved = 0;
|
|
+ memcpy( &karg.Configuration.szSerialNumber, ioc->board_tracer, 16 );
|
|
+ karg.Configuration.usMajorRevision = ioc->facts.FWVersion.Struct.Major;
|
|
+ karg.Configuration.usMinorRevision = ioc->facts.FWVersion.Struct.Minor;
|
|
+ karg.Configuration.usBuildRevision = ioc->facts.FWVersion.Struct.Unit;
|
|
+ karg.Configuration.usReleaseRevision = ioc->facts.FWVersion.Struct.Dev;
|
|
+ karg.Configuration.usBIOSMajorRevision =
|
|
+ (ioc->biosVersion & 0xFF000000) >> 24;
|
|
+ karg.Configuration.usBIOSMinorRevision =
|
|
+ (ioc->biosVersion & 0x00FF0000) >> 16;
|
|
+ karg.Configuration.usBIOSBuildRevision =
|
|
+ (ioc->biosVersion & 0x0000FF00) >> 8;
|
|
+ karg.Configuration.usBIOSReleaseRevision =
|
|
+ (ioc->biosVersion & 0x000000FF);
|
|
+ karg.Configuration.uControllerFlags = CSMI_SAS_CNTLR_SAS_HBA |
|
|
+ CSMI_SAS_CNTLR_FWD_SUPPORT | CSMI_SAS_CNTLR_FWD_ONLINE |
|
|
+ CSMI_SAS_CNTLR_FWD_SRESET ;
|
|
+
|
|
+ /*
|
|
+ * Enabling CSMI_SAS_CNTLR_SAS_RAID bit when IR fw detected
|
|
+ */
|
|
+ if (ioc->ir_firmware)
|
|
+ karg.Configuration.uControllerFlags |= CSMI_SAS_CNTLR_SAS_RAID;
|
|
+
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+
|
|
+ /* All Rrom entries will be zero. Skip them. */
|
|
+ /* bReserved will also be zeros. */
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, &karg,
|
|
+ sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Unable to write out csmi_sas_get_driver_info_buffer @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI Sas Get Controller Status command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_cntlr_status(unsigned long arg)
|
|
+{
|
|
+
|
|
+ CSMI_SAS_CNTLR_STATUS_BUFFER __user *uarg = (void __user *) arg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ CSMI_SAS_CNTLR_STATUS_BUFFER karg;
|
|
+ int iocnum;
|
|
+ int rc;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Unable to read in csmi_sas_get_cntlr_status_buffer struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ /* Fill in the data and return the structure to the calling
|
|
+ * program
|
|
+ */
|
|
+
|
|
+ rc = mpt_GetIocState(ioc, 1);
|
|
+ switch (rc) {
|
|
+ case MPI_IOC_STATE_OPERATIONAL:
|
|
+ karg.Status.uStatus = CSMI_SAS_CNTLR_STATUS_GOOD;
|
|
+ karg.Status.uOfflineReason = 0;
|
|
+ break;
|
|
+
|
|
+ case MPI_IOC_STATE_FAULT:
|
|
+ karg.Status.uStatus = CSMI_SAS_CNTLR_STATUS_FAILED;
|
|
+ karg.Status.uOfflineReason = 0;
|
|
+ break;
|
|
+
|
|
+ case MPI_IOC_STATE_RESET:
|
|
+ case MPI_IOC_STATE_READY:
|
|
+ default:
|
|
+ karg.Status.uStatus = CSMI_SAS_CNTLR_STATUS_OFFLINE;
|
|
+ karg.Status.uOfflineReason =
|
|
+ CSMI_SAS_OFFLINE_REASON_INITIALIZING;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ memset(&karg.Status.bReserved, 0, 28);
|
|
+
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, &karg,
|
|
+ sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Unable to write out csmi_sas_get_cntlr_status @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI Sas Get Phy Info command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_phy_info(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_PHY_INFO_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_PHY_INFO_BUFFER *karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ ConfigExtendedPageHeader_t hdr;
|
|
+ CONFIGPARMS cfg;
|
|
+ SasIOUnitPage0_t *sasIoUnitPg0;
|
|
+ dma_addr_t sasIoUnitPg0_dma;
|
|
+ int sasIoUnitPg0_data_sz;
|
|
+ SasPhyPage0_t *sasPhyPg0;
|
|
+ dma_addr_t sasPhyPg0_dma;
|
|
+ int sasPhyPg0_data_sz;
|
|
+ u16 protocol;
|
|
+ int iocnum;
|
|
+ int rc;
|
|
+ int ii;
|
|
+ u64 sas_address;
|
|
+ struct mptsas_devinfo device_info;
|
|
+ int memory_pages;
|
|
+
|
|
+ sasIoUnitPg0=NULL;
|
|
+ sasPhyPg0=NULL;
|
|
+ sasIoUnitPg0_data_sz=0;
|
|
+ sasPhyPg0_data_sz=0;
|
|
+
|
|
+ memory_pages = get_order(sizeof(CSMI_SAS_PHY_INFO_BUFFER));
|
|
+ karg = (CSMI_SAS_PHY_INFO_BUFFER *)__get_free_pages(
|
|
+ GFP_KERNEL, memory_pages);
|
|
+ if (!karg){
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to malloc CSMI_SAS_PHY_INFO_BUFFER "
|
|
+ "malloc_data_sz=%d memory_pages=%d\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__,
|
|
+ (int)sizeof(CSMI_SAS_PHY_INFO_BUFFER), memory_pages);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ memset(karg, 0, sizeof(*karg));
|
|
+
|
|
+ if (copy_from_user(karg, uarg, sizeof(CSMI_SAS_PHY_INFO_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Unable to read in csmisas_get_phy_info_buffer struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ /* Fill in the data and return the structure to the calling
|
|
+ * program
|
|
+ */
|
|
+
|
|
+ /* Issue a config request to get the number of phys
|
|
+ */
|
|
+ hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
|
|
+ hdr.ExtPageLength = 0;
|
|
+ hdr.PageNumber = 0;
|
|
+ hdr.Reserved1 = 0;
|
|
+ hdr.Reserved2 = 0;
|
|
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
|
|
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
|
|
+
|
|
+ cfg.cfghdr.ehdr = &hdr;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.pageAddr = 0;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0; /* read */
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0) {
|
|
+ /* Don't check if this failed. Already in a
|
|
+ * failure case.
|
|
+ */
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: HEADER\n"));
|
|
+ dcsmisasprintk(ioc, printk(": rc=%x\n",rc));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto sas_get_phy_info_exit;
|
|
+ }
|
|
+
|
|
+ if (hdr.ExtPageLength == 0) {
|
|
+ /* Don't check if this failed. Already in a
|
|
+ * failure case.
|
|
+ */
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": hdr.ExtPageLength == 0\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto sas_get_phy_info_exit;
|
|
+ }
|
|
+
|
|
+ sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4;
|
|
+ rc = -ENOMEM;
|
|
+
|
|
+ sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev,
|
|
+ sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma);
|
|
+
|
|
+ if (!sasIoUnitPg0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto sas_get_phy_info_exit;
|
|
+ }
|
|
+
|
|
+ memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz);
|
|
+ cfg.physAddr = sasIoUnitPg0_dma;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0) {
|
|
+
|
|
+ /* Don't check if this failed. Already in a
|
|
+ * failure case.
|
|
+ */
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: PAGE\n"));
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto sas_get_phy_info_exit;
|
|
+ }
|
|
+
|
|
+ /* Number of Phys. */
|
|
+ karg->Information.bNumberOfPhys = sasIoUnitPg0->NumPhys;
|
|
+
|
|
+ /* Fill in information for each phy. */
|
|
+ for (ii = 0; ii < karg->Information.bNumberOfPhys; ii++) {
|
|
+
|
|
+/* EDM : dump IO Unit Page 0 data*/
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "---- IO UNIT PAGE 0 ------------\n"));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Handle=0x%X\n",
|
|
+ le16_to_cpu(sasIoUnitPg0->PhyData[ii].AttachedDeviceHandle)));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Controller Handle=0x%X\n",
|
|
+ le16_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerDevHandle)));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Port=0x%X\n",
|
|
+ sasIoUnitPg0->PhyData[ii].Port));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Port Flags=0x%X\n",
|
|
+ sasIoUnitPg0->PhyData[ii].PortFlags));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "PHY Flags=0x%X\n",
|
|
+ sasIoUnitPg0->PhyData[ii].PhyFlags));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Negotiated Link Rate=0x%X\n",
|
|
+ sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Controller PHY Device Info=0x%X\n",
|
|
+ le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo)));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "DiscoveryStatus=0x%X\n",
|
|
+ le32_to_cpu(sasIoUnitPg0->PhyData[ii].DiscoveryStatus)));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "\n"));
|
|
+/* EDM : debug data */
|
|
+
|
|
+ /* PHY stuff. */
|
|
+ karg->Information.Phy[ii].bPortIdentifier =
|
|
+ sasIoUnitPg0->PhyData[ii].Port;
|
|
+
|
|
+ /* Get the negotiated link rate for the phy. */
|
|
+ switch (sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate) {
|
|
+
|
|
+ case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
|
|
+ karg->Information.Phy[ii].bNegotiatedLinkRate =
|
|
+ CSMI_SAS_PHY_DISABLED;
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
|
|
+ karg->Information.Phy[ii].bNegotiatedLinkRate =
|
|
+ CSMI_SAS_LINK_RATE_FAILED;
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_IOUNIT0_RATE_1_5:
|
|
+ karg->Information.Phy[ii].bNegotiatedLinkRate =
|
|
+ CSMI_SAS_LINK_RATE_1_5_GBPS;
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_IOUNIT0_RATE_3_0:
|
|
+ karg->Information.Phy[ii].bNegotiatedLinkRate =
|
|
+ CSMI_SAS_LINK_RATE_3_0_GBPS;
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
|
|
+ default:
|
|
+ karg->Information.Phy[ii].bNegotiatedLinkRate =
|
|
+ CSMI_SAS_LINK_RATE_UNKNOWN;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (sasIoUnitPg0->PhyData[ii].PortFlags &
|
|
+ MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS) {
|
|
+ karg->Information.Phy[ii].bAutoDiscover =
|
|
+ CSMI_SAS_DISCOVER_IN_PROGRESS;
|
|
+ } else {
|
|
+ karg->Information.Phy[ii].bAutoDiscover =
|
|
+ CSMI_SAS_DISCOVER_COMPLETE;
|
|
+ }
|
|
+
|
|
+ /* Issue a config request to get
|
|
+ * phy information.
|
|
+ */
|
|
+ hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
|
|
+ hdr.ExtPageLength = 0;
|
|
+ hdr.PageNumber = 0;
|
|
+ hdr.Reserved1 = 0;
|
|
+ hdr.Reserved2 = 0;
|
|
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
|
|
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
|
|
+
|
|
+ cfg.cfghdr.ehdr = &hdr;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.pageAddr = ii;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0; /* read */
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n"));
|
|
+ dcsmisasprintk(ioc, printk(": rc=%x\n",rc));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto sas_get_phy_info_exit;
|
|
+ }
|
|
+
|
|
+ if (hdr.ExtPageLength == 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto sas_get_phy_info_exit;
|
|
+ }
|
|
+
|
|
+ sasPhyPg0_data_sz = hdr.ExtPageLength * 4;
|
|
+ rc = -ENOMEM;
|
|
+
|
|
+ sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(
|
|
+ ioc->pcidev, sasPhyPg0_data_sz, &sasPhyPg0_dma);
|
|
+
|
|
+ if (! sasPhyPg0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto sas_get_phy_info_exit;
|
|
+ }
|
|
+
|
|
+ memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz);
|
|
+ cfg.physAddr = sasPhyPg0_dma;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n"));
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
|
|
+ (u8 *) sasPhyPg0, sasPhyPg0_dma);
|
|
+ goto sas_get_phy_info_exit;
|
|
+ }
|
|
+
|
|
+/* EDM : dump PHY Page 0 data*/
|
|
+ memcpy(&sas_address, &sasPhyPg0->SASAddress, sizeof(u64));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "---- SAS PHY PAGE 0 ------------\n"));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Handle=0x%X\n",
|
|
+ le16_to_cpu(sasPhyPg0->AttachedDevHandle)));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "SAS Address=0x%llX\n",
|
|
+ (unsigned long long)sas_address));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Attached PHY Identifier=0x%X\n",
|
|
+ sasPhyPg0->AttachedPhyIdentifier));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Attached Device Info=0x%X\n",
|
|
+ le32_to_cpu(sasPhyPg0->AttachedDeviceInfo)));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Programmed Link Rate=0x%X\n",
|
|
+ sasPhyPg0->ProgrammedLinkRate));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Hardware Link Rate=0x%X\n",
|
|
+ sasPhyPg0->HwLinkRate));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Change Count=0x%X\n",
|
|
+ sasPhyPg0->ChangeCount));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "PHY Info=0x%X\n",
|
|
+ le32_to_cpu(sasPhyPg0->PhyInfo)));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "\n"));
|
|
+/* EDM : debug data */
|
|
+
|
|
+ /* save the data */
|
|
+
|
|
+ /* Set Max hardware link rate.
|
|
+ * This value is hard coded
|
|
+ * because the HW link rate
|
|
+ * is currently being
|
|
+ * overwritten in FW.
|
|
+ */
|
|
+
|
|
+ /* Set Max hardware link rate. */
|
|
+ switch (sasPhyPg0->HwLinkRate &
|
|
+ MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
|
|
+
|
|
+ case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
|
|
+ karg->Information.Phy[ii].bMaximumLinkRate =
|
|
+ CSMI_SAS_LINK_RATE_1_5_GBPS;
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
|
|
+ karg->Information.Phy[ii].bMaximumLinkRate =
|
|
+ CSMI_SAS_LINK_RATE_3_0_GBPS;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* Set Max programmed link rate. */
|
|
+ switch (sasPhyPg0->ProgrammedLinkRate &
|
|
+ MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
|
|
+
|
|
+ case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
|
|
+ karg->Information.Phy[ii].bMaximumLinkRate |=
|
|
+ (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4);
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
|
|
+ karg->Information.Phy[ii].bMaximumLinkRate |=
|
|
+ (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* Set Min hardware link rate. */
|
|
+ switch (sasPhyPg0->HwLinkRate &
|
|
+ MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
|
|
+
|
|
+ case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
|
|
+ karg->Information.Phy[ii].bMinimumLinkRate =
|
|
+ CSMI_SAS_LINK_RATE_1_5_GBPS;
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
|
|
+ karg->Information.Phy[ii].bMinimumLinkRate =
|
|
+ CSMI_SAS_LINK_RATE_3_0_GBPS;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* Set Min programmed link rate. */
|
|
+ switch (sasPhyPg0->ProgrammedLinkRate &
|
|
+ MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
|
|
+
|
|
+ case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
|
|
+ karg->Information.Phy[ii].bMinimumLinkRate |=
|
|
+ (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4);
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
|
|
+ karg->Information.Phy[ii].bMinimumLinkRate |=
|
|
+ (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ karg->Information.Phy[ii].bPhyChangeCount = sasPhyPg0->ChangeCount;
|
|
+ if( sasPhyPg0->PhyInfo & MPI_SAS_PHY0_PHYINFO_VIRTUAL_PHY )
|
|
+ karg->Information.Phy[ii].bPhyFeatures = CSMI_SAS_PHY_VIRTUAL_SMP;
|
|
+
|
|
+ /* Fill in Attached Device
|
|
+ * Initiator Port Protocol.
|
|
+ * Bits 6:3
|
|
+ * More than one bit can be set.
|
|
+ */
|
|
+ protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x78;
|
|
+ karg->Information.Phy[ii].Attached.bInitiatorPortProtocol = 0;
|
|
+ if (protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
|
|
+ karg->Information.Phy[ii].Attached.bInitiatorPortProtocol =
|
|
+ CSMI_SAS_PROTOCOL_SSP;
|
|
+ if (protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
|
|
+ karg->Information.Phy[ii].Attached.bInitiatorPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_STP;
|
|
+ if (protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
|
|
+ karg->Information.Phy[ii].Attached.bInitiatorPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_SMP;
|
|
+ if (protocol & MPI_SAS_DEVICE_INFO_SATA_HOST)
|
|
+ karg->Information.Phy[ii].Attached.bInitiatorPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_SATA;
|
|
+
|
|
+ /* Fill in Phy Target Port
|
|
+ * Protocol. Bits 10:7
|
|
+ * More than one bit can be set.
|
|
+ */
|
|
+ protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x780;
|
|
+ karg->Information.Phy[ii].Attached.bTargetPortProtocol = 0;
|
|
+ if (protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET)
|
|
+ karg->Information.Phy[ii].Attached.bTargetPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_SSP;
|
|
+ if (protocol & MPI_SAS_DEVICE_INFO_STP_TARGET)
|
|
+ karg->Information.Phy[ii].Attached.bTargetPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_STP;
|
|
+ if (protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET)
|
|
+ karg->Information.Phy[ii].Attached.bTargetPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_SMP;
|
|
+ if (protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
|
|
+ karg->Information.Phy[ii].Attached.bTargetPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_SATA;
|
|
+
|
|
+
|
|
+ /* Fill in Attached device type */
|
|
+ switch (le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) &
|
|
+ MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
|
|
+
|
|
+ case MPI_SAS_DEVICE_INFO_NO_DEVICE:
|
|
+ karg->Information.Phy[ii].Attached.bDeviceType =
|
|
+ CSMI_SAS_NO_DEVICE_ATTACHED;
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_DEVICE_INFO_END_DEVICE:
|
|
+ karg->Information.Phy[ii].Attached.bDeviceType =
|
|
+ CSMI_SAS_END_DEVICE;
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
|
|
+ karg->Information.Phy[ii].Attached.bDeviceType =
|
|
+ CSMI_SAS_EDGE_EXPANDER_DEVICE;
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
|
|
+ karg->Information.Phy[ii].Attached.bDeviceType =
|
|
+ CSMI_SAS_FANOUT_EXPANDER_DEVICE;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* Identify Info. */
|
|
+ switch (le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) &
|
|
+ MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
|
|
+
|
|
+ case MPI_SAS_DEVICE_INFO_NO_DEVICE:
|
|
+ karg->Information.Phy[ii].Identify.bDeviceType =
|
|
+ CSMI_SAS_NO_DEVICE_ATTACHED;
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_DEVICE_INFO_END_DEVICE:
|
|
+ karg->Information.Phy[ii].Identify.bDeviceType =
|
|
+ CSMI_SAS_END_DEVICE;
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
|
|
+ karg->Information.Phy[ii].Identify.bDeviceType =
|
|
+ CSMI_SAS_EDGE_EXPANDER_DEVICE;
|
|
+ break;
|
|
+
|
|
+ case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
|
|
+ karg->Information.Phy[ii].Identify.bDeviceType =
|
|
+ CSMI_SAS_FANOUT_EXPANDER_DEVICE;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* Fill in Phy Initiator Port Protocol. Bits 6:3
|
|
+ * More than one bit can be set, fall through cases.
|
|
+ */
|
|
+ protocol = le32_to_cpu(
|
|
+ sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) & 0x78;
|
|
+ karg->Information.Phy[ii].Identify.bInitiatorPortProtocol = 0;
|
|
+ if( protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR )
|
|
+ karg->Information.Phy[ii].Identify.bInitiatorPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_SSP;
|
|
+ if( protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR )
|
|
+ karg->Information.Phy[ii].Identify.bInitiatorPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_STP;
|
|
+ if( protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR )
|
|
+ karg->Information.Phy[ii].Identify.bInitiatorPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_SMP;
|
|
+ if( protocol & MPI_SAS_DEVICE_INFO_SATA_HOST )
|
|
+ karg->Information.Phy[ii].Identify.bInitiatorPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_SATA;
|
|
+
|
|
+ /* Fill in Phy Target Port Protocol. Bits 10:7
|
|
+ * More than one bit can be set, fall through cases.
|
|
+ */
|
|
+ protocol = le32_to_cpu(
|
|
+ sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) & 0x780;
|
|
+ karg->Information.Phy[ii].Identify.bTargetPortProtocol = 0;
|
|
+ if( protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET )
|
|
+ karg->Information.Phy[ii].Identify.bTargetPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_SSP;
|
|
+ if( protocol & MPI_SAS_DEVICE_INFO_STP_TARGET )
|
|
+ karg->Information.Phy[ii].Identify.bTargetPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_STP;
|
|
+ if( protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET )
|
|
+ karg->Information.Phy[ii].Identify.bTargetPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_SMP;
|
|
+ if( protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE )
|
|
+ karg->Information.Phy[ii].Identify.bTargetPortProtocol |=
|
|
+ CSMI_SAS_PROTOCOL_SATA;
|
|
+
|
|
+ /* Setup SAS Address for the attached device */
|
|
+ if (sasPhyPg0->AttachedDevHandle) {
|
|
+ sas_address = reverse_byte_order64(sas_address);
|
|
+ memcpy(karg->Information.Phy[ii].Attached.bSASAddress,
|
|
+ &sas_address, sizeof(u64));
|
|
+ karg->Information.Phy[ii].Attached.bPhyIdentifier =
|
|
+ sasPhyPg0->AttachedPhyIdentifier;
|
|
+ }
|
|
+
|
|
+ /* Setup SAS Address for the parent device */
|
|
+ csmisas_sas_device_pg0(ioc, &device_info,
|
|
+ (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
|
|
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
|
|
+ sasIoUnitPg0->PhyData[ii].ControllerDevHandle);
|
|
+ sas_address = reverse_byte_order64(device_info.sas_address);
|
|
+ memcpy(karg->Information.Phy[ii].Identify.bSASAddress,
|
|
+ &sas_address, sizeof(u64));
|
|
+ karg->Information.Phy[ii].Identify.bPhyIdentifier = ii;
|
|
+
|
|
+ pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
|
|
+ (u8 *) sasPhyPg0, sasPhyPg0_dma);
|
|
+ }
|
|
+
|
|
+sas_get_phy_info_exit:
|
|
+
|
|
+ if (sasIoUnitPg0)
|
|
+ pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz,
|
|
+ (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma);
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, karg,
|
|
+ sizeof(CSMI_SAS_PHY_INFO_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Unable to write out csmisas_get_phy_info_buffer @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI SAS Set PHY Info command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_set_phy_info(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_SET_PHY_INFO_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_SET_PHY_INFO_BUFFER karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ int iocnum;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_set_phy_info struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+/* TODO - implement IOCTL here */
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE;
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG ": not implemented\n"));
|
|
+
|
|
+// cim_set_phy_info_exit:
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, &karg,
|
|
+ sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_set_phy_info @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI Sas Get SCSI Address command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_scsi_address(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_GET_SCSI_ADDRESS_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_GET_SCSI_ADDRESS_BUFFER karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ int iocnum;
|
|
+ u64 sas_address;
|
|
+ struct sas_device_info *sas_info;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg,
|
|
+ sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_get_scsi_address struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ /* reverse byte order the sas address */
|
|
+ memcpy(&sas_address, karg.bSASAddress, sizeof(u64));
|
|
+ sas_address = reverse_byte_order64(sas_address);
|
|
+
|
|
+ /* Search the list for the matching SAS address. */
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SCSI_ADDRESS;
|
|
+ karg.bPathId = 0;
|
|
+ karg.bTargetId = 0;
|
|
+ karg.bLun = 0;
|
|
+
|
|
+ sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address);
|
|
+ if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume)
|
|
+ goto csmisas_get_scsi_address_exit;
|
|
+
|
|
+ karg.bPathId = sas_info->os.channel;
|
|
+ karg.bTargetId = sas_info->os.id;
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+
|
|
+ csmisas_get_scsi_address_exit:
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, &karg,
|
|
+ sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_get_scsi_address @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI Sas Get SCSI Address command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_sata_signature(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_SATA_SIGNATURE_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_SATA_SIGNATURE_BUFFER karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ int iocnum;
|
|
+ int rc, jj;
|
|
+ ConfigExtendedPageHeader_t hdr;
|
|
+ CONFIGPARMS cfg;
|
|
+ SasPhyPage0_t *sasPhyPg0;
|
|
+ dma_addr_t sasPhyPg0_dma;
|
|
+ int sasPhyPg0_data_sz;
|
|
+ SasDevicePage1_t *sasDevicePg1;
|
|
+ dma_addr_t sasDevicePg1_dma;
|
|
+ int sasDevicePg1_data_sz;
|
|
+ u8 phyId;
|
|
+ u64 sas_address;
|
|
+
|
|
+ sasPhyPg0=NULL;
|
|
+ sasPhyPg0_data_sz=0;
|
|
+ sasDevicePg1=NULL;
|
|
+ sasDevicePg1_data_sz=0;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg,
|
|
+ sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_sata_signature struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+ phyId = karg.Signature.bPhyIdentifier;
|
|
+ if (phyId >= ioc->num_ports) {
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST;
|
|
+ dcsmisasprintk(ioc, printk(KERN_WARNING ": phyId >= ioc->num_ports\n"));
|
|
+ goto cim_sata_signature_exit;
|
|
+ }
|
|
+
|
|
+ /* Default to success.*/
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+
|
|
+ /* Issue a config request to get the devHandle of the attached device
|
|
+ */
|
|
+
|
|
+ /* Issue a config request to get phy information. */
|
|
+ hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
|
|
+ hdr.ExtPageLength = 0;
|
|
+ hdr.PageNumber = 0;
|
|
+ hdr.Reserved1 = 0;
|
|
+ hdr.Reserved2 = 0;
|
|
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
|
|
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
|
|
+
|
|
+ cfg.cfghdr.ehdr = &hdr;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.pageAddr = phyId;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0; /* read */
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0) {
|
|
+ /* Don't check if this failed. Already in a
|
|
+ * failure case.
|
|
+ */
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n"));
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sata_signature_exit;
|
|
+ }
|
|
+
|
|
+ if (hdr.ExtPageLength == 0) {
|
|
+ /* Don't check if this failed. Already in a
|
|
+ * failure case.
|
|
+ */
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": hdr.ExtPageLength == 0\n"));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sata_signature_exit;
|
|
+ }
|
|
+
|
|
+
|
|
+ sasPhyPg0_data_sz = hdr.ExtPageLength * 4;
|
|
+ rc = -ENOMEM;
|
|
+
|
|
+ sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(ioc->pcidev,
|
|
+ sasPhyPg0_data_sz, &sasPhyPg0_dma);
|
|
+
|
|
+ if (! sasPhyPg0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sata_signature_exit;
|
|
+ }
|
|
+
|
|
+ memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz);
|
|
+ cfg.physAddr = sasPhyPg0_dma;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0) {
|
|
+ /* Don't check if this failed. Already in a
|
|
+ * failure case.
|
|
+ */
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n"));
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sata_signature_exit;
|
|
+ }
|
|
+
|
|
+ /* Make sure a SATA device is attached. */
|
|
+ if ((le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) &
|
|
+ MPI_SAS_DEVICE_INFO_SATA_DEVICE) == 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_WARNING ": NOT A SATA DEVICE\n"));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SATA_DEVICE;
|
|
+ goto cim_sata_signature_exit;
|
|
+ }
|
|
+
|
|
+ /* Get device page 1 for FIS signature. */
|
|
+ hdr.PageVersion = MPI_SASDEVICE1_PAGEVERSION;
|
|
+ hdr.ExtPageLength = 0;
|
|
+ hdr.PageNumber = 1 /* page number 1 */;
|
|
+ hdr.Reserved1 = 0;
|
|
+ hdr.Reserved2 = 0;
|
|
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
|
|
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
|
|
+
|
|
+ cfg.cfghdr.ehdr = &hdr;
|
|
+ cfg.physAddr = -1;
|
|
+
|
|
+ cfg.pageAddr = ((MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
|
|
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT) |
|
|
+ le16_to_cpu(sasPhyPg0->AttachedDevHandle));
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0; /* read */
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: MPI_SASDEVICE1_PAGEVERSION: HEADER\n"));
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sata_signature_exit;
|
|
+ }
|
|
+
|
|
+ if (hdr.ExtPageLength == 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": hdr.ExtPageLength == 0\n"));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sata_signature_exit;
|
|
+ }
|
|
+
|
|
+ sasDevicePg1_data_sz = hdr.ExtPageLength * 4;
|
|
+ rc = -ENOMEM;
|
|
+
|
|
+ sasDevicePg1 = (SasDevicePage1_t *) pci_alloc_consistent
|
|
+ (ioc->pcidev, sasDevicePg1_data_sz, &sasDevicePg1_dma);
|
|
+
|
|
+ if (! sasDevicePg1) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sata_signature_exit;
|
|
+ }
|
|
+
|
|
+ memset((u8 *)sasDevicePg1, 0, sasDevicePg1_data_sz);
|
|
+ cfg.physAddr = sasDevicePg1_dma;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: MPI_SASDEVICE1_PAGEVERSION: PAGE\n"));
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sata_signature_exit;
|
|
+ }
|
|
+
|
|
+/* EDM : dump Device Page 1 data*/
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "---- SAS DEVICE PAGE 1 ---------\n"));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Handle=0x%x\n",sasDevicePg1->DevHandle));
|
|
+ memcpy(&sas_address, &sasDevicePg1->SASAddress, sizeof(u64));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "SAS Address=0x%llX\n",
|
|
+ (unsigned long long)sas_address));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "\n"));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Target ID=0x%x\n",sasDevicePg1->TargetID));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Bus=0x%x\n",sasDevicePg1->Bus));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Initial Reg Device FIS="));
|
|
+ for(jj=0;jj<20;jj++)
|
|
+ dcsmisasprintk(ioc, printk("%02x ",
|
|
+ ((u8 *)&sasDevicePg1->InitialRegDeviceFIS)[jj]));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "\n\n"));
|
|
+/* EDM : debug data */
|
|
+
|
|
+ memcpy(karg.Signature.bSignatureFIS,
|
|
+ sasDevicePg1->InitialRegDeviceFIS,20);
|
|
+
|
|
+ cim_sata_signature_exit:
|
|
+
|
|
+ if (sasPhyPg0)
|
|
+ pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz,
|
|
+ (u8 *) sasPhyPg0, sasPhyPg0_dma);
|
|
+
|
|
+ if (sasDevicePg1)
|
|
+ pci_free_consistent(ioc->pcidev, sasDevicePg1_data_sz,
|
|
+ (u8 *) sasDevicePg1, sasDevicePg1_dma);
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, &karg,
|
|
+ sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_sata_signature @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI Sas Get SCSI Address command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_device_address(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ int iocnum;
|
|
+ struct sas_device_info *sas_info;
|
|
+ u64 sas_address;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg,
|
|
+ sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_get_device_address_buffer struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_DEVICE_ADDRESS;
|
|
+ memset(karg.bSASAddress, 0, sizeof(u64));
|
|
+ memset(karg.bSASLun, 0, sizeof(karg.bSASLun));
|
|
+
|
|
+ /* Search the list for the matching SAS address. */
|
|
+ sas_info = csmisas_get_device_component_by_os(ioc, karg.bPathId,
|
|
+ karg.bTargetId);
|
|
+ if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume)
|
|
+ goto csmisas_get_device_address_exit;
|
|
+
|
|
+ sas_address = reverse_byte_order64(sas_info->sas_address);
|
|
+ memcpy(karg.bSASAddress, &sas_address, sizeof(u64));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+
|
|
+ csmisas_get_device_address_exit:
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, &karg,
|
|
+ sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_get_device_address_buffer @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI Sas Get Link Errors command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_link_errors(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_LINK_ERRORS_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_LINK_ERRORS_BUFFER karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ MPT_FRAME_HDR *mf = NULL;
|
|
+ MPIHeader_t *mpi_hdr;
|
|
+ int iocnum;
|
|
+ int rc;
|
|
+ ConfigExtendedPageHeader_t hdr;
|
|
+ CONFIGPARMS cfg;
|
|
+ SasPhyPage1_t *sasPhyPage1;
|
|
+ dma_addr_t sasPhyPage1_dma;
|
|
+ int sasPhyPage1_data_sz;
|
|
+ SasIoUnitControlRequest_t *sasIoUnitCntrReq;
|
|
+ SasIoUnitControlReply_t *sasIoUnitCntrReply;
|
|
+ u8 phyId;
|
|
+ u16 ioc_status;
|
|
+ u32 MsgContext;
|
|
+
|
|
+ sasPhyPage1=NULL;
|
|
+ sasPhyPage1_data_sz=0;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg,
|
|
+ sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmisas_get_link_errors struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+ phyId = karg.Information.bPhyIdentifier;
|
|
+ if (phyId >= ioc->num_ports) {
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST;
|
|
+ dcsmisasprintk(ioc, printk(KERN_WARNING ": phyId >= ioc->num_ports\n"));
|
|
+ goto cim_get_link_errors_exit;
|
|
+ }
|
|
+
|
|
+ /* Default to success.*/
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+
|
|
+ /* Issue a config request to get the devHandle of the attached device
|
|
+ */
|
|
+
|
|
+ /* Issue a config request to get phy information. */
|
|
+ hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
|
|
+ hdr.ExtPageLength = 0;
|
|
+ hdr.PageNumber = 1 /* page number 1*/;
|
|
+ hdr.Reserved1 = 0;
|
|
+ hdr.Reserved2 = 0;
|
|
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
|
|
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
|
|
+
|
|
+ cfg.cfghdr.ehdr = &hdr;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.pageAddr = phyId;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0; /* read */
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0) {
|
|
+ /* Don't check if this failed. Already in a
|
|
+ * failure case.
|
|
+ */
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: MPI_SASPHY1_PAGEVERSION: HEADER\n"));
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_link_errors_exit;
|
|
+ }
|
|
+
|
|
+ if (hdr.ExtPageLength == 0) {
|
|
+ /* Don't check if this failed. Already in a
|
|
+ * failure case.
|
|
+ */
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": hdr.ExtPageLength == 0\n"));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_link_errors_exit;
|
|
+ }
|
|
+
|
|
+
|
|
+ sasPhyPage1_data_sz = hdr.ExtPageLength * 4;
|
|
+ rc = -ENOMEM;
|
|
+
|
|
+ sasPhyPage1 = (SasPhyPage1_t *) pci_alloc_consistent(ioc->pcidev,
|
|
+ sasPhyPage1_data_sz, &sasPhyPage1_dma);
|
|
+
|
|
+ if (! sasPhyPage1) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_link_errors_exit;
|
|
+ }
|
|
+
|
|
+ memset((u8 *)sasPhyPage1, 0, sasPhyPage1_data_sz);
|
|
+ cfg.physAddr = sasPhyPage1_dma;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0) {
|
|
+ /* Don't check if this failed. Already in a
|
|
+ * failure case.
|
|
+ */
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": FAILED: MPI_SASPHY1_PAGEVERSION: PAGE\n"));
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": rc=%x\n",rc));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_link_errors_exit;
|
|
+ }
|
|
+
|
|
+/* EDM : dump PHY Page 1 data*/
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "---- SAS PHY PAGE 1 ------------\n"));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Invalid Dword Count=0x%x\n",
|
|
+ sasPhyPage1->InvalidDwordCount));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Running Disparity Error Count=0x%x\n",
|
|
+ sasPhyPage1->RunningDisparityErrorCount));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "Loss Dword Synch Count=0x%x\n",
|
|
+ sasPhyPage1->LossDwordSynchCount));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "PHY Reset Problem Count=0x%x\n",
|
|
+ sasPhyPage1->PhyResetProblemCount));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "\n\n"));
|
|
+/* EDM : debug data */
|
|
+
|
|
+ karg.Information.uInvalidDwordCount =
|
|
+ le32_to_cpu(sasPhyPage1->InvalidDwordCount);
|
|
+ karg.Information.uRunningDisparityErrorCount =
|
|
+ le32_to_cpu(sasPhyPage1->RunningDisparityErrorCount);
|
|
+ karg.Information.uLossOfDwordSyncCount =
|
|
+ le32_to_cpu(sasPhyPage1->LossDwordSynchCount);
|
|
+ karg.Information.uPhyResetProblemCount =
|
|
+ le32_to_cpu(sasPhyPage1->PhyResetProblemCount);
|
|
+
|
|
+ if (karg.Information.bResetCounts ==
|
|
+ CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS ) {
|
|
+ goto cim_get_link_errors_exit;
|
|
+ }
|
|
+
|
|
+ /* Clear Error log
|
|
+ *
|
|
+ * Issue IOUNIT Control Reqeust Message
|
|
+ */
|
|
+
|
|
+ /* Get a MF for this command.
|
|
+ */
|
|
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_link_errors_exit;
|
|
+ }
|
|
+
|
|
+ mpi_hdr = (MPIHeader_t *) mf;
|
|
+ MsgContext = mpi_hdr->MsgContext;
|
|
+ sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
|
|
+ memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
|
|
+ sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
|
|
+ sasIoUnitCntrReq->MsgContext = MsgContext;
|
|
+ sasIoUnitCntrReq->PhyNum = phyId;
|
|
+ sasIoUnitCntrReq->Operation = MPI_SAS_OP_PHY_CLEAR_ERROR_LOG;
|
|
+
|
|
+ if (csmisas_send_command_wait(ioc, mf, karg.IoctlHeader.Timeout) != 0) {
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_link_errors_exit;
|
|
+ }
|
|
+
|
|
+ /* process the completed Reply Message Frame */
|
|
+ if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) {
|
|
+
|
|
+ sasIoUnitCntrReply =
|
|
+ (SasIoUnitControlReply_t *)ioc->ioctl_cmds.reply;
|
|
+ ioc_status = le16_to_cpu(sasIoUnitCntrReply->IOCStatus)
|
|
+ & MPI_IOCSTATUS_MASK;
|
|
+
|
|
+ if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG ": SAS IO Unit Control: "));
|
|
+ dcsmisasprintk(ioc, printk("IOCStatus=0x%X IOCLogInfo=0x%X\n",
|
|
+ sasIoUnitCntrReply->IOCStatus,
|
|
+ sasIoUnitCntrReply->IOCLogInfo));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ cim_get_link_errors_exit:
|
|
+
|
|
+ if (sasPhyPage1)
|
|
+ pci_free_consistent(ioc->pcidev, sasPhyPage1_data_sz,
|
|
+ (u8 *) sasPhyPage1, sasPhyPage1_dma);
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, &karg,
|
|
+ sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmisas_get_link_errors @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI SAS SMP Passthru command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_smp_passthru(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_SMP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
|
|
+ MPT_ADAPTER *ioc;
|
|
+ CSMI_SAS_SMP_PASSTHRU_BUFFER *karg;
|
|
+ pSmpPassthroughRequest_t smpReq;
|
|
+ pSmpPassthroughReply_t smpReply;
|
|
+ MPT_FRAME_HDR *mf = NULL;
|
|
+ MPIHeader_t *mpi_hdr;
|
|
+ char *psge;
|
|
+ int iocnum, flagsLength;
|
|
+ void * request_data;
|
|
+ dma_addr_t request_data_dma;
|
|
+ u32 request_data_sz;
|
|
+ void * response_data;
|
|
+ dma_addr_t response_data_dma;
|
|
+ u32 response_data_sz;
|
|
+ u16 ioc_status;
|
|
+ u64 sas_address;
|
|
+ u32 MsgContext;
|
|
+ int malloc_data_sz;
|
|
+ int memory_pages;
|
|
+
|
|
+ malloc_data_sz = sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER);
|
|
+ memory_pages = get_order(malloc_data_sz);
|
|
+ karg = (CSMI_SAS_SMP_PASSTHRU_BUFFER *)__get_free_pages(
|
|
+ GFP_KERNEL, memory_pages);
|
|
+ if (!karg){
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to malloc CSMI_SAS_SMP_PASSTHRU_BUFFER "
|
|
+ "malloc_data_sz=%d memory_pages=%d\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__,
|
|
+ malloc_data_sz, memory_pages);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ if (copy_from_user(karg, uarg, sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_smp_passthru struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ request_data = NULL;
|
|
+ response_data = NULL;
|
|
+ response_data_sz = sizeof(CSMI_SAS_SMP_RESPONSE);
|
|
+ request_data_sz = karg->Parameters.uRequestLength;
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (ioc->ioc_reset_in_progress) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Busy with IOC Reset \n",
|
|
+ __FILE__, __LINE__,__FUNCTION__);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -EBUSY;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ /* Default to success.*/
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+
|
|
+ /* Do some error checking on the request. */
|
|
+ if (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
|
|
+ goto cim_smp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ if ((request_data_sz > 0xFFFF) || (!request_data_sz)) {
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_smp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ /* Get a free request frame and save the message context.
|
|
+ */
|
|
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_smp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ mpi_hdr = (MPIHeader_t *) mf;
|
|
+ MsgContext = mpi_hdr->MsgContext;
|
|
+ smpReq = (pSmpPassthroughRequest_t ) mf;
|
|
+
|
|
+ memset(smpReq,0,ioc->req_sz);
|
|
+
|
|
+ memcpy(&sas_address, karg->Parameters.bDestinationSASAddress,
|
|
+ sizeof(u64));
|
|
+ sas_address = cpu_to_le64(reverse_byte_order64(sas_address));
|
|
+ memcpy(&smpReq->SASAddress, &sas_address, sizeof(u64));
|
|
+
|
|
+ /* Fill in smp request. */
|
|
+ smpReq->PhysicalPort = karg->Parameters.bPortIdentifier;
|
|
+ smpReq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
|
|
+ smpReq->RequestDataLength = cpu_to_le16(request_data_sz);
|
|
+ smpReq->ConnectionRate = karg->Parameters.bConnectionRate;
|
|
+ smpReq->MsgContext = MsgContext;
|
|
+ smpReq->Reserved2 = 0;
|
|
+ smpReq->Reserved3 = 0;
|
|
+
|
|
+ /*
|
|
+ * Prepare the necessary pointers to run
|
|
+ * through the SGL generation
|
|
+ */
|
|
+
|
|
+ psge = (char *)&smpReq->SGL;
|
|
+
|
|
+ /* setup the *Request* payload SGE */
|
|
+ flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
|
|
+ MPI_SGE_FLAGS_SYSTEM_ADDRESS |
|
|
+ MPI_SGE_FLAGS_HOST_TO_IOC |
|
|
+ MPI_SGE_FLAGS_END_OF_BUFFER;
|
|
+
|
|
+ flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
|
|
+ flagsLength |= request_data_sz;
|
|
+
|
|
+ request_data = pci_alloc_consistent(
|
|
+ ioc->pcidev, request_data_sz, &request_data_dma);
|
|
+
|
|
+ if (!request_data) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ goto cim_smp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ ioc->add_sge(psge, flagsLength, request_data_dma);
|
|
+ psge += ioc->SGE_size;
|
|
+
|
|
+ memcpy(request_data, &karg->Parameters.Request, request_data_sz);
|
|
+
|
|
+ /* setup the *Response* payload SGE */
|
|
+ response_data = pci_alloc_consistent(
|
|
+ ioc->pcidev, response_data_sz, &response_data_dma);
|
|
+
|
|
+ if (!response_data) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ goto cim_smp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
|
|
+ MPI_SGE_FLAGS_SYSTEM_ADDRESS |
|
|
+ MPI_SGE_FLAGS_IOC_TO_HOST |
|
|
+ MPI_SGE_FLAGS_END_OF_BUFFER;
|
|
+
|
|
+ flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
|
|
+ flagsLength |= response_data_sz;
|
|
+
|
|
+ ioc->add_sge(psge, flagsLength, response_data_dma);
|
|
+
|
|
+ if (csmisas_send_command_wait(ioc, mf, karg->IoctlHeader.Timeout) != 0) {
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_smp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) == 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG ": SMP Passthru: oh no, there is no reply!!"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_smp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ /* process the completed Reply Message Frame */
|
|
+ smpReply = (pSmpPassthroughReply_t )ioc->ioctl_cmds.reply;
|
|
+ ioc_status = le16_to_cpu(smpReply->IOCStatus) & MPI_IOCSTATUS_MASK;
|
|
+
|
|
+ if ((ioc_status != MPI_IOCSTATUS_SUCCESS) &&
|
|
+ (ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) {
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG ": SMP Passthru: "));
|
|
+ dcsmisasprintk(ioc, printk("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n",
|
|
+ le16_to_cpu(smpReply->IOCStatus),
|
|
+ le32_to_cpu(smpReply->IOCLogInfo),
|
|
+ smpReply->SASStatus));
|
|
+ goto cim_smp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ karg->Parameters.bConnectionStatus =
|
|
+ map_sas_status_to_csmi(smpReply->SASStatus);
|
|
+
|
|
+
|
|
+ if (le16_to_cpu(smpReply->ResponseDataLength)) {
|
|
+ karg->Parameters.uResponseBytes = le16_to_cpu(smpReply->ResponseDataLength);
|
|
+ memcpy(&karg->Parameters.Response,
|
|
+ response_data, le16_to_cpu(smpReply->ResponseDataLength));
|
|
+ }
|
|
+
|
|
+ cim_smp_passthru_exit:
|
|
+
|
|
+ if (request_data)
|
|
+ pci_free_consistent(ioc->pcidev, request_data_sz,
|
|
+ (u8 *)request_data, request_data_dma);
|
|
+
|
|
+ if (response_data)
|
|
+ pci_free_consistent(ioc->pcidev, response_data_sz,
|
|
+ (u8 *)response_data, response_data_dma);
|
|
+
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, karg,
|
|
+ sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_smp_passthru @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG ": %s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI SAS SSP Passthru command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int csmisas_ssp_passthru(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_SSP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_SSP_PASSTHRU_BUFFER karg_hdr, * karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ pSCSIIORequest_t pScsiRequest;
|
|
+ pSCSIIOReply_t pScsiReply;
|
|
+ MPT_FRAME_HDR *mf = NULL;
|
|
+ MPIHeader_t *mpi_hdr;
|
|
+ int iocnum,ii;
|
|
+ u64 sas_address;
|
|
+ u16 req_idx;
|
|
+ char *psge;
|
|
+ int flagsLength;
|
|
+ void * request_data;
|
|
+ dma_addr_t request_data_dma;
|
|
+ u32 request_data_sz;
|
|
+ int malloc_data_sz;
|
|
+ int memory_pages;
|
|
+ u16 ioc_status;
|
|
+ u8 volume_id;
|
|
+ u8 volume_bus;
|
|
+ u8 is_hidden_raid_component;
|
|
+ u8 channel;
|
|
+ u8 id;
|
|
+ struct sas_device_info *sas_info;
|
|
+ u8 skey, asc, ascq;
|
|
+ u32 MsgContext;
|
|
+
|
|
+ if (copy_from_user(&karg_hdr, uarg, sizeof(CSMI_SAS_SSP_PASSTHRU_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_ssp_passthru struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ request_data = NULL;
|
|
+ request_data_sz = karg_hdr.Parameters.uDataLength;
|
|
+ channel = 0;
|
|
+ id = 0;
|
|
+ volume_id = 0;
|
|
+ volume_bus = 0;
|
|
+ is_hidden_raid_component = 0;
|
|
+
|
|
+ malloc_data_sz = (request_data_sz +
|
|
+ offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER, bDataBuffer));
|
|
+ memory_pages = get_order(malloc_data_sz);
|
|
+ karg = (CSMI_SAS_SSP_PASSTHRU_BUFFER *)__get_free_pages(
|
|
+ GFP_KERNEL, memory_pages);
|
|
+ if (!karg){
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to malloc SAS_SSP_PASSTHRU_BUFFER "
|
|
+ "malloc_data_sz=%d memory_pages=%d\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__,
|
|
+ malloc_data_sz, memory_pages);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ memset(karg, 0, sizeof(*karg));
|
|
+
|
|
+ if (copy_from_user(karg, uarg, request_data_sz +
|
|
+ offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_ssp_passthru struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * some checks of the incoming frame
|
|
+ */
|
|
+ if ( offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer) +
|
|
+ request_data_sz - sizeof(IOCTL_HEADER) >
|
|
+ karg->IoctlHeader.Length ) {
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ "%s::%s()"
|
|
+ " @%d - expected datalen incorrect!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__));
|
|
+ goto cim_ssp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ goto cim_ssp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ if (ioc->ioc_reset_in_progress) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Busy with IOC Reset \n",
|
|
+ __FILE__, __LINE__,__FUNCTION__);
|
|
+ return -EBUSY;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ printk(KERN_ERR "%s::%s()@%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ goto cim_ssp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ /* Default to success.
|
|
+ */
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+
|
|
+ /* Neither a phy nor a port has been selected.
|
|
+ */
|
|
+ if ((karg->Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) &&
|
|
+ (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) {
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ "%s::%s()"
|
|
+ " @%d - incorrect bPhyIdentifier and bPortIdentifier!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__));
|
|
+ goto cim_ssp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ /* A phy has been selected. Verify that it's valid.
|
|
+ */
|
|
+ if (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
|
|
+
|
|
+ /* Is the phy in range? */
|
|
+ if (karg->Parameters.bPhyIdentifier >= ioc->num_ports) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_WARNING ": phyId >= ioc->num_ports (%d %d)\n",
|
|
+ karg->Parameters.bPhyIdentifier,
|
|
+ ioc->num_ports));
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_PHY_DOES_NOT_EXIST;
|
|
+ goto cim_ssp_passthru_exit;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if(karg->Parameters.bAdditionalCDBLength) {
|
|
+ /* TODO - SCSI IO (32) Request Message support
|
|
+ */
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG ": greater than 16-byte cdb "
|
|
+ "is not supported!\n"));
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ goto cim_ssp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ /* we will use SAS address to resolve the scsi adddressing
|
|
+ */
|
|
+ memcpy(&sas_address, karg->Parameters.bDestinationSASAddress,
|
|
+ sizeof(u64));
|
|
+ sas_address = reverse_byte_order64(sas_address);
|
|
+
|
|
+ /* Search the list for the matching SAS address.
|
|
+ */
|
|
+ sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address);
|
|
+ if (!sas_info || sas_info->is_cached) {
|
|
+ /*
|
|
+ *Invalid SAS address
|
|
+ */
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ "%s::%s() @%d - couldn't find associated "
|
|
+ "SASAddress=%llX!\n", __FILE__, __FUNCTION__, __LINE__,
|
|
+ (unsigned long long)sas_address));
|
|
+ goto cim_ssp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ id = sas_info->fw.id;
|
|
+ channel = sas_info->fw.channel;
|
|
+
|
|
+ if (csmisas_is_phys_disk(ioc, channel, id)) {
|
|
+ id = csmisas_raid_id_to_num(ioc, channel, id);
|
|
+ channel = 0;
|
|
+ is_hidden_raid_component = 1;
|
|
+ }
|
|
+
|
|
+ /* Get a free request frame and save the message context.
|
|
+ */
|
|
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_ssp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ mpi_hdr = (MPIHeader_t *) mf;
|
|
+ MsgContext = mpi_hdr->MsgContext;
|
|
+ pScsiRequest = (pSCSIIORequest_t) mf;
|
|
+ req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
|
|
+
|
|
+ memset(pScsiRequest,0,sizeof(SCSIIORequest_t));
|
|
+
|
|
+ /* Fill in SCSI IO (16) request.
|
|
+ */
|
|
+
|
|
+ pScsiRequest->Function = (is_hidden_raid_component == 1) ?
|
|
+ MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH : MPI_FUNCTION_SCSI_IO_REQUEST;
|
|
+ pScsiRequest->TargetID = id;
|
|
+ pScsiRequest->Bus = channel;
|
|
+ memcpy(pScsiRequest->LUN, &karg->Parameters.bLun, 8);
|
|
+ pScsiRequest->CDBLength = karg->Parameters.bCDBLength;
|
|
+ pScsiRequest->DataLength = cpu_to_le32(request_data_sz);
|
|
+ pScsiRequest->MsgContext = MsgContext;
|
|
+ memcpy(pScsiRequest->CDB, karg->Parameters.bCDB,
|
|
+ pScsiRequest->CDBLength);
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "\tchannel = %d id = %d ",
|
|
+ sas_info->fw.channel, sas_info->fw.id));
|
|
+ dcsmisasprintk(ioc, if(is_hidden_raid_component)
|
|
+ printk(KERN_DEBUG "num_id = %d ", id));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "\n"));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "\tcdb_len = %d request_len = %d\n",
|
|
+ pScsiRequest->CDBLength, request_data_sz));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "\t"));
|
|
+ dcsmisasprintk(ioc, for (ii = 0; ii < pScsiRequest->CDBLength; ++ii)
|
|
+ printk(" %02x", pScsiRequest->CDB[ii]));
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "\n"));
|
|
+
|
|
+ /* direction
|
|
+ */
|
|
+ if (karg->Parameters.uFlags & CSMI_SAS_SSP_READ) {
|
|
+ pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
|
|
+ } else if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE) {
|
|
+ pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_WRITE);
|
|
+ } else if ((karg->Parameters.uFlags & CSMI_SAS_SSP_UNSPECIFIED) &&
|
|
+ (!karg->Parameters.uDataLength)) {
|
|
+ /* no data transfer
|
|
+ */
|
|
+ pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_NODATATRANSFER);
|
|
+ } else {
|
|
+ /* no direction specified
|
|
+ */
|
|
+ pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
|
|
+ pScsiRequest->MsgFlags =
|
|
+ MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR;
|
|
+ }
|
|
+
|
|
+ pScsiRequest->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
|
|
+ if (ioc->sg_addr_size == sizeof(u64))
|
|
+ pScsiRequest->MsgFlags |= MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64;
|
|
+
|
|
+ /* task attributes
|
|
+ */
|
|
+ if((karg->Parameters.uFlags && 0xFF) == 0) {
|
|
+ pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ);
|
|
+ } else if (karg->Parameters.uFlags &
|
|
+ CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE) {
|
|
+ pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_HEADOFQ);
|
|
+ } else if (karg->Parameters.uFlags &
|
|
+ CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED) {
|
|
+ pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ORDEREDQ);
|
|
+ } else if (karg->Parameters.uFlags &
|
|
+ CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA) {
|
|
+ pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ACAQ);
|
|
+ } else {
|
|
+ pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_UNTAGGED);
|
|
+ }
|
|
+
|
|
+ /* setup sense
|
|
+ */
|
|
+ pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
|
|
+ pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma +
|
|
+ (req_idx * MPT_SENSE_BUFFER_ALLOC));
|
|
+
|
|
+ /* setup databuffer sg, assuming we fit everything one contiguous buffer
|
|
+ */
|
|
+ psge = (char *)&pScsiRequest->SGL;
|
|
+
|
|
+ if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE) {
|
|
+ flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
|
|
+ } else if (karg->Parameters.uFlags & CSMI_SAS_SSP_READ) {
|
|
+ flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
|
|
+ }else {
|
|
+ flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
|
|
+ MPI_SGE_FLAGS_DIRECTION )
|
|
+ << MPI_SGE_FLAGS_SHIFT;
|
|
+ }
|
|
+ flagsLength |= request_data_sz;
|
|
+
|
|
+ if ( request_data_sz > 0) {
|
|
+ request_data = pci_alloc_consistent(
|
|
+ ioc->pcidev, request_data_sz, &request_data_dma);
|
|
+
|
|
+ if (request_data == NULL) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED "
|
|
+ "request_data_sz=%d\n", request_data_sz));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ goto cim_ssp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ ioc->add_sge(psge, flagsLength, request_data_dma);
|
|
+ if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE)
|
|
+ memcpy(request_data, karg->bDataBuffer, request_data_sz);
|
|
+ } else {
|
|
+ ioc->add_sge(psge, flagsLength, (dma_addr_t) -1);
|
|
+ }
|
|
+
|
|
+ if (csmisas_send_command_wait(ioc, mf, karg->IoctlHeader.Timeout) != 0) {
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_ssp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ memset(&karg->Status,0,sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS));
|
|
+ karg->Status.bConnectionStatus = CSMI_SAS_OPEN_ACCEPT;
|
|
+ karg->Status.bDataPresent = CSMI_SAS_SSP_NO_DATA_PRESENT;
|
|
+ karg->Status.bStatus = GOOD;
|
|
+ karg->Status.bResponseLength[0] = 0;
|
|
+ karg->Status.bResponseLength[1] = 0;
|
|
+ karg->Status.uDataBytes = request_data_sz;
|
|
+
|
|
+ /* process the completed Reply Message Frame */
|
|
+ if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) {
|
|
+
|
|
+ pScsiReply = (pSCSIIOReply_t ) ioc->ioctl_cmds.reply;
|
|
+ karg->Status.bStatus = pScsiReply->SCSIStatus;
|
|
+ karg->Status.uDataBytes = min(le32_to_cpu(pScsiReply->TransferCount),
|
|
+ request_data_sz);
|
|
+ ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
|
|
+
|
|
+ if (pScsiReply->SCSIState ==
|
|
+ MPI_SCSI_STATE_AUTOSENSE_VALID) {
|
|
+ karg->Status.bConnectionStatus =
|
|
+ CSMI_SAS_SSP_SENSE_DATA_PRESENT;
|
|
+ karg->Status.bResponseLength[0] =
|
|
+ (u8)le32_to_cpu(pScsiReply->SenseCount) & 0xFF;
|
|
+ memcpy(karg->Status.bResponse,
|
|
+ ioc->ioctl_cmds.sense, le32_to_cpu(pScsiReply->SenseCount));
|
|
+
|
|
+ skey = ioc->ioctl_cmds.sense[2] & 0x0F;
|
|
+ asc = ioc->ioctl_cmds.sense[12];
|
|
+ ascq = ioc->ioctl_cmds.sense[13];
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "\t [sense_key,asc,ascq]: "
|
|
+ "[0x%02x,0x%02x,0x%02x]\n",
|
|
+ skey, asc, ascq));
|
|
+
|
|
+ } else if(pScsiReply->SCSIState ==
|
|
+ MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
|
|
+ karg->Status.bDataPresent =
|
|
+ CSMI_SAS_SSP_RESPONSE_DATA_PRESENT;
|
|
+ karg->Status.bResponseLength[0] =
|
|
+ sizeof(pScsiReply->ResponseInfo);
|
|
+ for (ii=0;ii<sizeof(pScsiReply->ResponseInfo);ii++) {
|
|
+ karg->Status.bResponse[ii] =
|
|
+ ((u8*)&pScsiReply->ResponseInfo)[
|
|
+ (sizeof(pScsiReply->ResponseInfo)-1)-ii];
|
|
+ }
|
|
+ } else if ((ioc_status != MPI_IOCSTATUS_SUCCESS) &&
|
|
+ (ioc_status != MPI_IOCSTATUS_SCSI_RECOVERED_ERROR) &&
|
|
+ (ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) {
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG ": SCSI IO : "));
|
|
+ dcsmisasprintk(ioc, printk("IOCStatus=0x%X IOCLogInfo=0x%X\n",
|
|
+ pScsiReply->IOCStatus,
|
|
+ pScsiReply->IOCLogInfo));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if ((karg->Status.uDataBytes) && (request_data) &&
|
|
+ (karg->Parameters.uFlags & CSMI_SAS_SSP_READ)) {
|
|
+ if (copy_to_user((void __user *)uarg->bDataBuffer,
|
|
+ request_data, karg->Status.uDataBytes)) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Unable to write data to user %p\n",
|
|
+ __FILE__, __LINE__,__FUNCTION__,
|
|
+ (void*)karg->bDataBuffer);
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ cim_ssp_passthru_exit:
|
|
+
|
|
+
|
|
+ if (request_data)
|
|
+ pci_free_consistent(ioc->pcidev, request_data_sz,
|
|
+ (u8 *)request_data, request_data_dma);
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, karg,
|
|
+ offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER, bDataBuffer))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_ssp_passthru @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI SAS STP Passthru command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_stp_passthru(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_STP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_STP_PASSTHRU_BUFFER karg_hdr, *karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ pSataPassthroughRequest_t pSataRequest;
|
|
+ pSataPassthroughReply_t pSataReply;
|
|
+ MPT_FRAME_HDR *mf = NULL;
|
|
+ MPIHeader_t *mpi_hdr;
|
|
+ int iocnum;
|
|
+ u32 data_sz;
|
|
+ u64 sas_address;
|
|
+ u16 req_idx;
|
|
+ char *psge;
|
|
+ int flagsLength;
|
|
+ void * request_data;
|
|
+ dma_addr_t request_data_dma;
|
|
+ u32 request_data_sz;
|
|
+ int malloc_data_sz;
|
|
+ int memory_pages;
|
|
+ u8 channel;
|
|
+ u8 id;
|
|
+ u8 volume_id;
|
|
+ u8 volume_bus;
|
|
+ struct sas_device_info *sas_info;
|
|
+ u16 ioc_status;
|
|
+ u32 MsgContext;
|
|
+
|
|
+ if (copy_from_user(&karg_hdr, uarg, sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ request_data=NULL;
|
|
+ request_data_sz = karg_hdr.Parameters.uDataLength;
|
|
+ volume_id = 0;
|
|
+ volume_bus = 0;
|
|
+ channel = 0;
|
|
+ id = 0;
|
|
+
|
|
+ malloc_data_sz = (request_data_sz +
|
|
+ offsetof(CSMI_SAS_STP_PASSTHRU_BUFFER, bDataBuffer));
|
|
+ memory_pages = get_order(malloc_data_sz);
|
|
+ karg = (CSMI_SAS_STP_PASSTHRU_BUFFER *)__get_free_pages(
|
|
+ GFP_KERNEL, memory_pages);
|
|
+ if (!karg){
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to malloc CSMI_SAS_STP_PASSTHRU_BUFFER "
|
|
+ "malloc_data_sz=%d memory_pages=%d\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__,
|
|
+ malloc_data_sz, memory_pages);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ memset(karg, 0, sizeof(*karg));
|
|
+
|
|
+ if (copy_from_user(karg, uarg, malloc_data_sz)) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_ssp_passthru struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (ioc->ioc_reset_in_progress) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Busy with IOC Reset \n",
|
|
+ __FILE__, __LINE__,__FUNCTION__);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -EBUSY;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ /* Default to success.
|
|
+ */
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+
|
|
+ /* Neither a phy nor a port has been selected.
|
|
+ */
|
|
+ if ((karg->Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) &&
|
|
+ (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) {
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT;
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ "%s::%s() @%d - incorrect bPhyIdentifier and bPortIdentifier!\n",
|
|
+ __FILE__,__FUNCTION__, __LINE__));
|
|
+ goto cim_stp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ /* A phy has been selected. Verify that it's valid.
|
|
+ */
|
|
+ if (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) {
|
|
+
|
|
+ /* Is the phy in range? */
|
|
+ if (karg->Parameters.bPhyIdentifier >= ioc->num_ports) {
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_PHY_DOES_NOT_EXIST;
|
|
+ goto cim_stp_passthru_exit;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ data_sz = sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER) -
|
|
+ sizeof(IOCTL_HEADER) - sizeof(u8*) +
|
|
+ request_data_sz;
|
|
+
|
|
+ if ( data_sz > karg->IoctlHeader.Length ) {
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ "%s::%s() @%d - expected datalen incorrect!\n",
|
|
+ __FILE__, __FUNCTION__,__LINE__));
|
|
+ goto cim_stp_passthru_exit;
|
|
+ }
|
|
+
|
|
+
|
|
+ /* we will use SAS address to resolve the scsi adddressing
|
|
+ */
|
|
+ memcpy(&sas_address, karg->Parameters.bDestinationSASAddress,
|
|
+ sizeof(u64));
|
|
+ sas_address = reverse_byte_order64(sas_address);
|
|
+
|
|
+ /* Search the list for the matching SAS address.
|
|
+ */
|
|
+ sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address);
|
|
+ if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume) {
|
|
+ /*
|
|
+ *Invalid SAS address
|
|
+ */
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ "%s::%s() @%d - couldn't find associated "
|
|
+ "SASAddress=%llX!\n", __FILE__, __FUNCTION__, __LINE__,
|
|
+ (unsigned long long)sas_address));
|
|
+ goto cim_stp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ id = sas_info->fw.id;
|
|
+ channel = sas_info->fw.channel;
|
|
+
|
|
+ /* check that this is an STP or SATA target device
|
|
+ */
|
|
+ if ( !(sas_info->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET ) &&
|
|
+ !(sas_info->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE )) {
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ goto cim_stp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ /* Get a free request frame and save the message context.
|
|
+ */
|
|
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_stp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ mpi_hdr = (MPIHeader_t *) mf;
|
|
+ MsgContext = mpi_hdr->MsgContext;
|
|
+ pSataRequest = (pSataPassthroughRequest_t) mf;
|
|
+ req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
|
|
+
|
|
+ memset(pSataRequest,0,sizeof(pSataPassthroughRequest_t));
|
|
+
|
|
+ pSataRequest->TargetID = id;
|
|
+ pSataRequest->Bus = channel;
|
|
+ pSataRequest->Function = MPI_FUNCTION_SATA_PASSTHROUGH;
|
|
+ pSataRequest->PassthroughFlags = cpu_to_le16(karg->Parameters.uFlags);
|
|
+ pSataRequest->ConnectionRate = karg->Parameters.bConnectionRate;
|
|
+ pSataRequest->MsgContext = MsgContext;
|
|
+ pSataRequest->DataLength = cpu_to_le32(request_data_sz);
|
|
+ pSataRequest->MsgFlags = 0;
|
|
+ memcpy( pSataRequest->CommandFIS,karg->Parameters.bCommandFIS, 20);
|
|
+
|
|
+ psge = (char *)&pSataRequest->SGL;
|
|
+ if (karg->Parameters.uFlags & CSMI_SAS_STP_WRITE) {
|
|
+ flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
|
|
+ } else if (karg->Parameters.uFlags & CSMI_SAS_STP_READ) {
|
|
+ flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
|
|
+ }else {
|
|
+ flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
|
|
+ MPI_SGE_FLAGS_DIRECTION )
|
|
+ << MPI_SGE_FLAGS_SHIFT;
|
|
+ }
|
|
+
|
|
+ flagsLength |= request_data_sz;
|
|
+ if (request_data_sz > 0) {
|
|
+ request_data = pci_alloc_consistent(
|
|
+ ioc->pcidev, request_data_sz, &request_data_dma);
|
|
+
|
|
+ if (request_data == NULL) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ goto cim_stp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ ioc->add_sge(psge, flagsLength, request_data_dma);
|
|
+ if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE)
|
|
+ memcpy(request_data, karg->bDataBuffer, request_data_sz);
|
|
+ } else {
|
|
+ ioc->add_sge(psge, flagsLength, (dma_addr_t) -1);
|
|
+ }
|
|
+
|
|
+ if (csmisas_send_command_wait(ioc, mf, karg->IoctlHeader.Timeout) != 0) {
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_stp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ memset(&karg->Status,0,sizeof(CSMI_SAS_STP_PASSTHRU_STATUS));
|
|
+
|
|
+ if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) == 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG ": STP Passthru: oh no, there is no reply!!"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_stp_passthru_exit;
|
|
+ }
|
|
+
|
|
+ /* process the completed Reply Message Frame */
|
|
+ pSataReply = (pSataPassthroughReply_t ) ioc->ioctl_cmds.reply;
|
|
+ ioc_status = le16_to_cpu(pSataReply->IOCStatus) & MPI_IOCSTATUS_MASK;
|
|
+
|
|
+ if (ioc_status != MPI_IOCSTATUS_SUCCESS &&
|
|
+ ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) {
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG ": STP Passthru: "));
|
|
+ dcsmisasprintk(ioc, printk("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n",
|
|
+ le16_to_cpu(pSataReply->IOCStatus),
|
|
+ le32_to_cpu(pSataReply->IOCLogInfo),
|
|
+ pSataReply->SASStatus));
|
|
+ }
|
|
+
|
|
+ karg->Status.bConnectionStatus =
|
|
+ map_sas_status_to_csmi(pSataReply->SASStatus);
|
|
+
|
|
+ memcpy(karg->Status.bStatusFIS,pSataReply->StatusFIS, 20);
|
|
+
|
|
+ /*
|
|
+ * for now, just zero out uSCR array,
|
|
+ * then copy the one dword returned
|
|
+ * in the reply frame into uSCR[0]
|
|
+ */
|
|
+ memset( karg->Status.uSCR, 0, 64);
|
|
+ karg->Status.uSCR[0] = le32_to_cpu(pSataReply->StatusControlRegisters);
|
|
+
|
|
+ if((le32_to_cpu(pSataReply->TransferCount)) && (request_data) &&
|
|
+ (karg->Parameters.uFlags & CSMI_SAS_STP_READ)) {
|
|
+ karg->Status.uDataBytes =
|
|
+ min(le32_to_cpu(pSataReply->TransferCount),request_data_sz);
|
|
+ if (copy_to_user((void __user *)uarg->bDataBuffer,
|
|
+ request_data, karg->Status.uDataBytes)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - "
|
|
+ "Unable to write data to user %p\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__,
|
|
+ (void*)karg->bDataBuffer);
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ cim_stp_passthru_exit:
|
|
+
|
|
+ if (request_data)
|
|
+ pci_free_consistent(ioc->pcidev, request_data_sz,
|
|
+ (u8 *)request_data, request_data_dma);
|
|
+
|
|
+ /* Copy th data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, karg,
|
|
+ offsetof(CSMI_SAS_STP_PASSTHRU_BUFFER, bDataBuffer))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_ssp_passthru @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG ": %s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI SAS Firmware Download command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_firmware_download(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ int iocnum;
|
|
+ pMpiFwHeader_t pFwHeader=NULL;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg,
|
|
+ sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_firmware_download struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ /* Default to success.*/
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+ karg.Information.usStatus = CSMI_SAS_FWD_SUCCESS;
|
|
+ karg.Information.usSeverity = CSMI_SAS_FWD_INFORMATION;
|
|
+
|
|
+ /* some checks of the incoming frame */
|
|
+ if ((karg.Information.uBufferLength +
|
|
+ sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD)) >
|
|
+ karg.IoctlHeader.Length) {
|
|
+ karg.IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
|
|
+ goto cim_firmware_download_exit;
|
|
+ }
|
|
+
|
|
+ if ( karg.Information.uDownloadFlags &
|
|
+ (CSMI_SAS_FWD_SOFT_RESET | CSMI_SAS_FWD_VALIDATE)) {
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
|
|
+ karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
|
|
+ goto cim_firmware_download_exit;
|
|
+ }
|
|
+
|
|
+ /* now we need to alloc memory so we can pull in the
|
|
+ * fw image attached to end of incoming packet.
|
|
+ */
|
|
+ pFwHeader = kmalloc(karg.Information.uBufferLength, GFP_KERNEL);
|
|
+ if (!pFwHeader){
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
|
|
+ karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
|
|
+ goto cim_firmware_download_exit;
|
|
+ }
|
|
+ memset(pFwHeader, 0, sizeof(*pFwHeader));
|
|
+
|
|
+ if (copy_from_user(pFwHeader, uarg->bDataBuffer,
|
|
+ karg.Information.uBufferLength)) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in pFwHeader @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if ( !((pFwHeader->Signature0 == MPI_FW_HEADER_SIGNATURE_0) &&
|
|
+ (pFwHeader->Signature1 == MPI_FW_HEADER_SIGNATURE_1) &&
|
|
+ (pFwHeader->Signature2 == MPI_FW_HEADER_SIGNATURE_2))) {
|
|
+ // the signature check failed
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ karg.Information.usStatus = CSMI_SAS_FWD_REJECT;
|
|
+ karg.Information.usSeverity = CSMI_SAS_FWD_ERROR;
|
|
+ goto cim_firmware_download_exit;
|
|
+ }
|
|
+
|
|
+ if ( mptctl_do_fw_download(karg.IoctlHeader.IOControllerNumber,
|
|
+ uarg->bDataBuffer, karg.Information.uBufferLength)
|
|
+ != 0) {
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
|
|
+ karg.Information.usSeverity = CSMI_SAS_FWD_FATAL;
|
|
+ goto cim_firmware_download_exit;
|
|
+ }
|
|
+
|
|
+ if((karg.Information.uDownloadFlags & CSMI_SAS_FWD_SOFT_RESET) ||
|
|
+ (karg.Information.uDownloadFlags & CSMI_SAS_FWD_HARD_RESET)) {
|
|
+ if (mpt_HardResetHandler(ioc, CAN_SLEEP) != 0) {
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ karg.Information.usStatus = CSMI_SAS_FWD_FAILED;
|
|
+ karg.Information.usSeverity = CSMI_SAS_FWD_FATAL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ cim_firmware_download_exit:
|
|
+
|
|
+ if(pFwHeader)
|
|
+ kfree(pFwHeader);
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, &karg,
|
|
+ sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_firmware_download @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI SAS Get RAID Info command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_raid_info(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_RAID_INFO_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_RAID_INFO_BUFFER karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ int iocnum;
|
|
+ u32 raidFlags;
|
|
+ u8 maxRaidTypes;
|
|
+ u8 maxDrivesPerSet;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_INFO_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_get_raid_info struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ if (!ioc->raid_data.pIocPg2)
|
|
+ goto csmisas_get_raid_info_out;
|
|
+ karg.Information.uNumRaidSets =
|
|
+ ioc->raid_data.pIocPg2->NumActiveVolumes;
|
|
+ karg.Information.uMaxRaidSets = ioc->raid_data.pIocPg2->MaxVolumes;
|
|
+ if( ioc->raid_data.pIocPg6 ) {
|
|
+ // get absolute maximum for all RAID sets
|
|
+ maxDrivesPerSet = ioc->raid_data.pIocPg6->MaxDrivesIS;
|
|
+ maxDrivesPerSet = max(ioc->raid_data.pIocPg6->MaxDrivesIM,
|
|
+ maxDrivesPerSet);
|
|
+ maxDrivesPerSet = max(ioc->raid_data.pIocPg6->MaxDrivesIME,
|
|
+ maxDrivesPerSet);
|
|
+ karg.Information.uMaxDrivesPerSet = maxDrivesPerSet;
|
|
+ }
|
|
+ else
|
|
+ karg.Information.uMaxDrivesPerSet = 8;
|
|
+ // For bMaxRaidSets, count bits set in bits 0-6 of CapabilitiesFlags
|
|
+ raidFlags = ioc->raid_data.pIocPg2->CapabilitiesFlags & 0x0000007F;
|
|
+ for( maxRaidTypes=0; raidFlags; maxRaidTypes++ )
|
|
+ raidFlags &= raidFlags - 1;
|
|
+ karg.Information.bMaxRaidTypes = maxRaidTypes;
|
|
+ // ulMinRaidSetBlocks hard coded to 1MB until available from config page
|
|
+ karg.Information.ulMinRaidSetBlocks.uLowPart = 2048;
|
|
+ karg.Information.ulMinRaidSetBlocks.uHighPart = 0;
|
|
+ karg.Information.ulMaxRaidSetBlocks.uLowPart = 0xffffffff;
|
|
+ if( ioc->raid_data.pIocPg2->CapabilitiesFlags &
|
|
+ MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING )
|
|
+ karg.Information.ulMaxRaidSetBlocks.uHighPart = 0xffffffff;
|
|
+ else
|
|
+ karg.Information.ulMaxRaidSetBlocks.uHighPart = 0;
|
|
+ karg.Information.uMaxPhysicalDrives =
|
|
+ ioc->raid_data.pIocPg2->MaxPhysDisks;
|
|
+ karg.Information.uMaxExtents = 1;
|
|
+ karg.Information.uMaxModules = 0;
|
|
+ karg.Information.uMaxTransformationMemory = 0;
|
|
+ karg.Information.uChangeCount = ioc->csmi_change_count;
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+
|
|
+csmisas_get_raid_info_out:
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, &karg,
|
|
+ sizeof(CSMI_SAS_RAID_INFO_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_get_raid_info @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_do_raid - Format and Issue a RAID volume request message.
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @action: What do be done.
|
|
+ * @PhysDiskNum: Logical target id.
|
|
+ * @VolumeBus: Target locations bus.
|
|
+ * @VolumeId: Volume id
|
|
+ *
|
|
+ * Returns: < 0 on a fatal error
|
|
+ * 0 on success
|
|
+ *
|
|
+ * Remark: Wait to return until reply processed by the ISR.
|
|
+ **/
|
|
+static int
|
|
+csmisas_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus, u8 VolumeId, pMpiRaidActionReply_t reply)
|
|
+{
|
|
+ MpiRaidActionRequest_t *pReq;
|
|
+ MpiRaidActionReply_t *pReply;
|
|
+ MPT_FRAME_HDR *mf;
|
|
+
|
|
+ /* Get and Populate a free Frame
|
|
+ */
|
|
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
|
|
+ return -EAGAIN;
|
|
+ }
|
|
+ pReq = (MpiRaidActionRequest_t *)mf;
|
|
+ pReq->Action = action;
|
|
+ pReq->Reserved1 = 0;
|
|
+ pReq->ChainOffset = 0;
|
|
+ pReq->Function = MPI_FUNCTION_RAID_ACTION;
|
|
+ pReq->VolumeID = VolumeId;
|
|
+ pReq->VolumeBus = VolumeBus;
|
|
+ pReq->PhysDiskNum = PhysDiskNum;
|
|
+ pReq->MsgFlags = 0;
|
|
+ pReq->Reserved2 = 0;
|
|
+ pReq->ActionDataWord = 0; /* Reserved for this action */
|
|
+ //pReq->ActionDataSGE = 0;
|
|
+
|
|
+ ioc->add_sge((char *)&pReq->ActionDataSGE,
|
|
+ MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
|
|
+
|
|
+ if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0)
|
|
+ return -ENODATA;
|
|
+
|
|
+ if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) &&
|
|
+ (reply != NULL)){
|
|
+ pReply = (MpiRaidActionReply_t *)&(ioc->ioctl_cmds.reply);
|
|
+ memcpy(reply, pReply,
|
|
+ min(ioc->reply_sz,
|
|
+ 4*pReply->MsgLength));
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_raid_inq
|
|
+ * @ioc = per host instance
|
|
+ * @opcode = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH or
|
|
+ * MPI_FUNCTION_SCSI_IO_REQUEST
|
|
+ * @id = target id
|
|
+ * @bus = target bus
|
|
+ * @inq_vpd = inquiry data, returned
|
|
+ * @inq_vpd_sz = maximum size of inquiry data
|
|
+ *
|
|
+ * Return = 0(sucess), non-zero(failure)
|
|
+ **/
|
|
+static int
|
|
+csmisas_raid_inq(MPT_ADAPTER *ioc, u8 opcode, u8 bus, u8 id, u8 inq_vpd_page,
|
|
+ u8 * inq_vpd, u32 inq_vpd_sz)
|
|
+{
|
|
+ MPT_FRAME_HDR *mf = NULL;
|
|
+ MPIHeader_t *mpi_hdr;
|
|
+ pSCSIIORequest_t pScsiRequest;
|
|
+ u16 req_idx;
|
|
+ char *psge;
|
|
+ u8 inq_vpd_cdb[6];
|
|
+ u8 *request_data=NULL;
|
|
+ dma_addr_t request_data_dma;
|
|
+ u32 request_data_sz;
|
|
+ int rc = 0;
|
|
+ u32 MsgContext;
|
|
+
|
|
+ request_data_sz = inq_vpd_sz;
|
|
+
|
|
+ /* fill-in cdb */
|
|
+ memset(inq_vpd_cdb, 0, sizeof(inq_vpd_cdb));
|
|
+ inq_vpd_cdb[0] = 0x12;
|
|
+ if (inq_vpd_page) {
|
|
+ inq_vpd_cdb[1] = 0x01; /* evpd bit */
|
|
+ inq_vpd_cdb[2] = inq_vpd_page;
|
|
+ }
|
|
+ inq_vpd_cdb[3] = (u8)(request_data_sz >> 8);
|
|
+ inq_vpd_cdb[4] = (u8)request_data_sz;
|
|
+
|
|
+ /* Get a free request frame and save the message context.
|
|
+ */
|
|
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
|
|
+ goto csmisas_raid_inq_exit;
|
|
+ }
|
|
+
|
|
+ mpi_hdr = (MPIHeader_t *) mf;
|
|
+ MsgContext = mpi_hdr->MsgContext;
|
|
+ pScsiRequest = (pSCSIIORequest_t) mf;
|
|
+ req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
|
|
+
|
|
+ memset(pScsiRequest,0,sizeof(SCSIIORequest_t));
|
|
+ pScsiRequest->Function = opcode;
|
|
+ pScsiRequest->TargetID = id;
|
|
+ pScsiRequest->Bus = bus;
|
|
+ pScsiRequest->CDBLength = 6;
|
|
+ pScsiRequest->DataLength = cpu_to_le32(request_data_sz);
|
|
+ pScsiRequest->MsgContext = MsgContext;
|
|
+ memcpy(pScsiRequest->CDB,inq_vpd_cdb,pScsiRequest->CDBLength);
|
|
+ pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ);
|
|
+ pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ);
|
|
+ pScsiRequest->MsgFlags &= ~MPI_SCSIIO_MSGFLGS_SENSE_WIDTH;
|
|
+ if (ioc->sg_addr_size == sizeof(u64))
|
|
+ pScsiRequest->MsgFlags |= MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64;
|
|
+
|
|
+ /* setup sense
|
|
+ */
|
|
+ pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
|
|
+ pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma +
|
|
+ (req_idx * MPT_SENSE_BUFFER_ALLOC));
|
|
+
|
|
+ request_data = pci_alloc_consistent(
|
|
+ ioc->pcidev, request_data_sz, &request_data_dma);
|
|
+
|
|
+ if (request_data == NULL) {
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ rc=-1;
|
|
+ goto csmisas_raid_inq_exit;
|
|
+ }
|
|
+
|
|
+ memset(request_data,0,request_data_sz);
|
|
+ psge = (char *)&pScsiRequest->SGL;
|
|
+ ioc->add_sge(psge, (MPT_SGE_FLAGS_SSIMPLE_READ | 0xFC) ,
|
|
+ request_data_dma);
|
|
+
|
|
+ if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0) {
|
|
+ rc=-1;
|
|
+ goto csmisas_raid_inq_exit;
|
|
+ }
|
|
+
|
|
+ /* copy the request_data */
|
|
+ memcpy(inq_vpd, request_data, request_data_sz);
|
|
+
|
|
+ csmisas_raid_inq_exit:
|
|
+
|
|
+ if (request_data)
|
|
+ pci_free_consistent(ioc->pcidev, request_data_sz,
|
|
+ request_data, request_data_dma);
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI SAS Get RAID Config command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_raid_config(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_RAID_CONFIG_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_RAID_CONFIG_BUFFER karg,*pKarg=NULL;
|
|
+ CONFIGPARMS cfg;
|
|
+ ConfigPageHeader_t header;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ int iocnum;
|
|
+ u8 volumeID, VolumeBus;
|
|
+ u8 physDiskNum, physDiskNumMax;
|
|
+ int volumepage0sz = 0;
|
|
+ int physdiskpage0sz = 0, ioc_page5_sz = 0;
|
|
+ dma_addr_t volume0_dma, physdisk0_dma;
|
|
+ dma_addr_t ioc_page5_dma = 0;
|
|
+ pRaidVolumePage0_t pVolume0 = NULL;
|
|
+ pRaidPhysDiskPage0_t pPhysDisk0 = NULL;
|
|
+ pMpiRaidActionReply_t pRaidActionReply = NULL;
|
|
+ u32 device_info = 0;
|
|
+ pIOCPage5_t pIocPage5 = NULL;
|
|
+ int i, idx, csmi_sas_raid_config_buffer_sz;
|
|
+ int memory_pages;
|
|
+ int copy_buffer_sz = 0;
|
|
+ u64 totalMaxLBA, tmpTotalMaxLBA;
|
|
+ u64 sas_address;
|
|
+ struct sas_device_info *sas_info;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmisas_get_raid_config struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ csmi_sas_raid_config_buffer_sz = karg.IoctlHeader.Length;
|
|
+ memory_pages = get_order(csmi_sas_raid_config_buffer_sz);
|
|
+ pKarg = (CSMI_SAS_RAID_CONFIG_BUFFER *)__get_free_pages(
|
|
+ GFP_KERNEL, memory_pages);
|
|
+ if (!pKarg){
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to malloc RAID_CONFIG_BUFFER "
|
|
+ "csmi_sas_raid_config_buffer_sz=%d memory_pages=%d\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__,
|
|
+ csmi_sas_raid_config_buffer_sz, memory_pages);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+ memset(pKarg, 0, sizeof(*pKarg));
|
|
+
|
|
+ if (copy_from_user(pKarg, uarg, csmi_sas_raid_config_buffer_sz)) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmisas_get_raid_config struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ if (pKarg->Configuration.uChangeCount != 0 &&
|
|
+ pKarg->Configuration.uChangeCount != ioc->csmi_change_count ) {
|
|
+ pKarg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ pKarg->Configuration.uFailureCode =
|
|
+ CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
|
|
+ goto cim_get_raid_config_exit;
|
|
+ }
|
|
+
|
|
+ if (!ioc->raid_data.pIocPg2) {
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_raid_config_exit;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Check to see if the input uRaidSetIndex is
|
|
+ * greater than the number of RAID sets
|
|
+ */
|
|
+ if (pKarg->Configuration.uRaidSetIndex >=
|
|
+ ioc->raid_data.pIocPg2->NumActiveVolumes) {
|
|
+ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_RAID_SET_OUT_OF_RANGE;
|
|
+ goto cim_get_raid_config_exit;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * get RAID Volume Page 0
|
|
+ */
|
|
+ volumeID = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeID;
|
|
+ VolumeBus = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeBus;
|
|
+
|
|
+ header.PageVersion = 0;
|
|
+ header.PageLength = 0;
|
|
+ header.PageNumber = 0;
|
|
+ header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
|
|
+ cfg.cfghdr.hdr = &header;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.pageAddr = (VolumeBus << 8) + volumeID;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0;
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+ if (mpt_config(ioc, &cfg) != 0) {
|
|
+ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_raid_config_exit;
|
|
+ }
|
|
+
|
|
+ if (header.PageLength == 0) {
|
|
+ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_raid_config_exit;
|
|
+ }
|
|
+
|
|
+ volumepage0sz = header.PageLength * 4;
|
|
+ pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz,
|
|
+ &volume0_dma);
|
|
+ if (!pVolume0) {
|
|
+ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_raid_config_exit;
|
|
+ }
|
|
+
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+ cfg.physAddr = volume0_dma;
|
|
+ if (mpt_config(ioc, &cfg) != 0) {
|
|
+ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_raid_config_exit;
|
|
+ }
|
|
+
|
|
+ totalMaxLBA = (u64)le32_to_cpu(pVolume0->MaxLBA) |
|
|
+ ((u64)le32_to_cpu(pVolume0->MaxLBAHigh)) << 32;
|
|
+ tmpTotalMaxLBA = totalMaxLBA + 1;
|
|
+ do_div(tmpTotalMaxLBA, 2048);
|
|
+ pKarg->Configuration.bDriveCount = 0;
|
|
+ pKarg->Configuration.uCapacity = tmpTotalMaxLBA;
|
|
+ pKarg->Configuration.uStripeSize =
|
|
+ le32_to_cpu(pVolume0->StripeSize)/2;
|
|
+
|
|
+ switch(pVolume0->VolumeType) {
|
|
+ case MPI_RAID_VOL_TYPE_IS:
|
|
+ pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_0;
|
|
+ break;
|
|
+ case MPI_RAID_VOL_TYPE_IME:
|
|
+ pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_10;
|
|
+ break;
|
|
+ case MPI_RAID_VOL_TYPE_IM:
|
|
+ pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_1;
|
|
+ break;
|
|
+ default:
|
|
+ pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_OTHER;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch (pVolume0->VolumeStatus.State) {
|
|
+ case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
|
|
+ pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OK;
|
|
+ break;
|
|
+ case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
|
|
+ /* Volume is degraded, check if Resyncing or Inactive */
|
|
+ pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_DEGRADED;
|
|
+ break;
|
|
+ case MPI_RAIDVOL0_STATUS_STATE_FAILED:
|
|
+ pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_FAILED;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* check flags */
|
|
+ if (pVolume0->VolumeStatus.Flags &
|
|
+ MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE)
|
|
+ pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OFFLINE;
|
|
+ else if (pVolume0->VolumeStatus.Flags &
|
|
+ MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS)
|
|
+ pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_REBUILDING;
|
|
+
|
|
+ pKarg->Configuration.bInformation = 0; /* default */
|
|
+ if(pVolume0->VolumeStatus.Flags &
|
|
+ MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS ) {
|
|
+
|
|
+ uint64_t * ptrUint64;
|
|
+ uint64_t totalBlocks64, blocksRemaining64;
|
|
+ uint32_t totalBlocks32, blocksRemaining32;
|
|
+
|
|
+ /* get percentage complete */
|
|
+ pRaidActionReply = kmalloc( sizeof(MPI_RAID_VOL_INDICATOR) +
|
|
+ offsetof(MSG_RAID_ACTION_REPLY,ActionData),
|
|
+ GFP_KERNEL);
|
|
+
|
|
+ if (!pRaidActionReply){
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to malloc @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__,pKarg);
|
|
+ goto cim_get_raid_config_exit;
|
|
+ }
|
|
+ memset(pRaidActionReply, 0, sizeof(*pRaidActionReply));
|
|
+
|
|
+ csmisas_do_raid(ioc,
|
|
+ MPI_RAID_ACTION_INDICATOR_STRUCT,
|
|
+ 0, VolumeBus, volumeID, pRaidActionReply);
|
|
+
|
|
+ ptrUint64 = (uint64_t *)&pRaidActionReply->ActionData;
|
|
+ totalBlocks64 = *ptrUint64;
|
|
+ ptrUint64++;
|
|
+ blocksRemaining64 = *ptrUint64;
|
|
+ while(totalBlocks64 > 0xFFFFFFFFUL){
|
|
+ totalBlocks64 = totalBlocks64 >> 1;
|
|
+ blocksRemaining64 = blocksRemaining64 >> 1;
|
|
+ }
|
|
+ totalBlocks32 = (uint32_t)totalBlocks64;
|
|
+ blocksRemaining32 = (uint32_t)blocksRemaining64;
|
|
+
|
|
+ if(totalBlocks32)
|
|
+ pKarg->Configuration.bInformation =
|
|
+ (totalBlocks32 - blocksRemaining32) /
|
|
+ (totalBlocks32 / 100);
|
|
+
|
|
+ kfree(pRaidActionReply);
|
|
+ }
|
|
+
|
|
+ /* fill-in more information depending on data type */
|
|
+ if (pKarg->Configuration.bDataType ==
|
|
+ CSMI_SAS_RAID_DATA_ADDITIONAL_DATA) {
|
|
+ pKarg->Configuration.Data->bLabel[0] = '\0';
|
|
+ pKarg->Configuration.Data->bRaidSetLun[1] = 0;
|
|
+ pKarg->Configuration.Data->bWriteProtection =
|
|
+ CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN;
|
|
+ pKarg->Configuration.Data->bCacheSetting =
|
|
+ CSMI_SAS_RAID_SET_CACHE_UNKNOWN;
|
|
+ pKarg->Configuration.Data->bCacheRatio = 0;
|
|
+ pKarg->Configuration.Data->usBlockSize = 512;
|
|
+ pKarg->Configuration.Data->ulRaidSetExtentOffset.uLowPart = 0;
|
|
+ pKarg->Configuration.Data->ulRaidSetExtentOffset.uHighPart = 0;
|
|
+ pKarg->Configuration.Data->ulRaidSetBlocks.uLowPart =
|
|
+ le32_to_cpu(pVolume0->MaxLBA);
|
|
+ pKarg->Configuration.Data->ulRaidSetBlocks.uHighPart =
|
|
+ le32_to_cpu(pVolume0->MaxLBAHigh);
|
|
+ if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS ||
|
|
+ pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME ) {
|
|
+ pKarg->Configuration.Data->uStripeSizeInBlocks =
|
|
+ le32_to_cpu(pVolume0->StripeSize);
|
|
+ } else {
|
|
+ pKarg->Configuration.Data->uStripeSizeInBlocks = 0;
|
|
+ }
|
|
+ pKarg->Configuration.Data->uSectorsPerTrack = 128;
|
|
+ for (i=0; i<16; i++) {
|
|
+ // unsupported
|
|
+ pKarg->Configuration.Data->bApplicationScratchPad[i] =
|
|
+ 0xFF;
|
|
+ }
|
|
+ pKarg->Configuration.Data->uNumberOfHeads = 16;
|
|
+
|
|
+ tmpTotalMaxLBA = totalMaxLBA;
|
|
+ do_div(tmpTotalMaxLBA,
|
|
+ (pKarg->Configuration.Data->uNumberOfHeads *
|
|
+ pKarg->Configuration.Data->uSectorsPerTrack));
|
|
+ pKarg->Configuration.Data->uNumberOfTracks = tmpTotalMaxLBA;
|
|
+ } else if ( pKarg->Configuration.bDataType ==
|
|
+ CSMI_SAS_RAID_DATA_DEVICE_ID ) {
|
|
+ /* Send inquiry to get VPD Page 0x83 */
|
|
+ u32 vpd_page_sz;
|
|
+ vpd_page_sz = csmi_sas_raid_config_buffer_sz -
|
|
+ offsetof(CSMI_SAS_RAID_CONFIG,DeviceId);
|
|
+ if (csmisas_raid_inq(ioc, MPI_FUNCTION_SCSI_IO_REQUEST,
|
|
+ VolumeBus, volumeID, 0x83,
|
|
+ (u8*)&pKarg->Configuration.DeviceId->bDeviceIdentificationVPDPage,
|
|
+ vpd_page_sz) != 0) {
|
|
+ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_raid_config_exit;
|
|
+ }
|
|
+ } else {
|
|
+ /* suppress drive information */
|
|
+ if (pKarg->Configuration.bDriveCount ==
|
|
+ CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED) {
|
|
+ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+ goto cim_get_raid_config_exit;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* get hotspare info, used later in this function */
|
|
+ if (pVolume0->VolumeSettings.HotSparePool) {
|
|
+ /* Read and save IOC Page 5
|
|
+ */
|
|
+ header.PageVersion = 0;
|
|
+ header.PageLength = 0;
|
|
+ header.PageNumber = 5;
|
|
+ header.PageType = MPI_CONFIG_PAGETYPE_IOC;
|
|
+ cfg.cfghdr.hdr = &header;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.pageAddr = 0;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0;
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+ if ((mpt_config(ioc, &cfg) == 0) && (header.PageLength)) {
|
|
+ ioc_page5_sz = header.PageLength * 4;
|
|
+ pIocPage5 = pci_alloc_consistent(ioc->pcidev,
|
|
+ ioc_page5_sz,
|
|
+ &ioc_page5_dma);
|
|
+ memset(pIocPage5,0,ioc_page5_sz);
|
|
+ if (ioc_page5_dma) {
|
|
+ cfg.physAddr = ioc_page5_dma;
|
|
+ cfg.action =
|
|
+ MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+ mpt_config(ioc, &cfg);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * get RAID Physical Disk Page 0
|
|
+ */
|
|
+ header.PageVersion = 0;
|
|
+ header.PageLength = 0;
|
|
+ header.PageNumber = 0;
|
|
+ header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
|
|
+ cfg.cfghdr.hdr = &header;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.pageAddr = 0;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0;
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+ if (mpt_config(ioc, &cfg) != 0) {
|
|
+ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_raid_config_exit;
|
|
+ }
|
|
+
|
|
+ if (header.PageLength == 0) {
|
|
+ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_raid_config_exit;
|
|
+ }
|
|
+
|
|
+ physdiskpage0sz = header.PageLength * 4;
|
|
+ pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz,
|
|
+ &physdisk0_dma);
|
|
+ if (!pPhysDisk0) {
|
|
+ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_raid_config_exit;
|
|
+ }
|
|
+ cfg.physAddr = physdisk0_dma;
|
|
+
|
|
+ physDiskNumMax = (csmi_sas_raid_config_buffer_sz -
|
|
+ offsetof(CSMI_SAS_RAID_CONFIG,Drives))
|
|
+ / sizeof(CSMI_SAS_RAID_DRIVES);
|
|
+
|
|
+ tmpTotalMaxLBA = totalMaxLBA;
|
|
+ if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS) {
|
|
+ do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks);
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "IS Volume tmpTotalMaxLBA=%llX\n",
|
|
+ (unsigned long long)tmpTotalMaxLBA));
|
|
+ }
|
|
+ else if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME) {
|
|
+ do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks * 2);
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "IME Volume tmpTotalMaxLBA=%llX\n",
|
|
+ (unsigned long long)tmpTotalMaxLBA));
|
|
+ } else {
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "IM Volume tmpTotalMaxLBA=%llX\n",
|
|
+ (unsigned long long)tmpTotalMaxLBA));
|
|
+ }
|
|
+
|
|
+ for (i=0; i< min(pVolume0->NumPhysDisks, physDiskNumMax); i++) {
|
|
+
|
|
+ physDiskNum = pVolume0->PhysDisk[i].PhysDiskNum;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+ cfg.pageAddr = physDiskNum;
|
|
+ if (mpt_config(ioc, &cfg) != 0){
|
|
+ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_raid_config_exit;
|
|
+ }
|
|
+
|
|
+ pKarg->Configuration.bDriveCount++;
|
|
+ if (pKarg->Configuration.bDataType != CSMI_SAS_RAID_DATA_DRIVES)
|
|
+ continue;
|
|
+
|
|
+ /* Search the list for the matching SAS address. */
|
|
+ sas_info = csmisas_get_device_component_by_fw(ioc, pPhysDisk0->PhysDiskBus,
|
|
+ pPhysDisk0->PhysDiskID);
|
|
+ if (sas_info) {
|
|
+ sas_address = reverse_byte_order64(sas_info->sas_address);
|
|
+ memcpy(pKarg->Configuration.Drives[i].bSASAddress,
|
|
+ &sas_address,sizeof(u64));
|
|
+ if (!device_info)
|
|
+ device_info = sas_info->device_info;
|
|
+ }
|
|
+
|
|
+ memcpy(pKarg->Configuration.Drives[i].bModel,
|
|
+ pPhysDisk0->InquiryData.VendorID,
|
|
+ offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel));
|
|
+ memcpy(pKarg->Configuration.Drives[i].bFirmware,
|
|
+ pPhysDisk0->InquiryData.ProductRevLevel,
|
|
+ sizeof(pPhysDisk0->InquiryData.ProductRevLevel));
|
|
+ if (csmisas_is_sata(pPhysDisk0)) {
|
|
+ memcpy(&pKarg->Configuration.Drives[i].bSerialNumber,
|
|
+ &pPhysDisk0->ExtDiskIdentifier[4],
|
|
+ 4);
|
|
+ memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4],
|
|
+ &pPhysDisk0->DiskIdentifier,
|
|
+ sizeof(pPhysDisk0->DiskIdentifier));
|
|
+ } else {
|
|
+ memcpy(pKarg->Configuration.Drives[i].bSerialNumber,
|
|
+ pPhysDisk0->DiskIdentifier,
|
|
+ sizeof(pPhysDisk0->DiskIdentifier));
|
|
+ }
|
|
+
|
|
+ pKarg->Configuration.Drives[i].bDriveUsage =
|
|
+ (pPhysDisk0->PhysDiskStatus.Flags &
|
|
+ MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME) ?
|
|
+ CSMI_SAS_DRIVE_CONFIG_NOT_USED :
|
|
+ CSMI_SAS_DRIVE_CONFIG_MEMBER;
|
|
+
|
|
+ pKarg->Configuration.Drives[i].bDriveStatus =
|
|
+ CSMI_SAS_DRIVE_STATUS_OK;
|
|
+ if (pPhysDisk0->PhysDiskStatus.State ==
|
|
+ MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED) {
|
|
+ pKarg->Configuration.Drives[i].bDriveStatus =
|
|
+ CSMI_SAS_DRIVE_STATUS_OFFLINE;
|
|
+ } else if(pPhysDisk0->PhysDiskStatus.State) {
|
|
+ pKarg->Configuration.Drives[i].bDriveStatus =
|
|
+ CSMI_SAS_DRIVE_STATUS_FAILED;
|
|
+ if(pKarg->Configuration.bStatus ==
|
|
+ CSMI_SAS_RAID_SET_STATUS_DEGRADED)
|
|
+ pKarg->Configuration.bInformation = i;
|
|
+ } else if((pVolume0->VolumeStatus.Flags &
|
|
+ MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) &&
|
|
+ (pPhysDisk0->PhysDiskStatus.Flags &
|
|
+ MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC))
|
|
+ pKarg->Configuration.Drives[i].bDriveStatus =
|
|
+ CSMI_SAS_DRIVE_STATUS_REBUILDING;
|
|
+ else if(pPhysDisk0->ErrorData.SmartCount ||
|
|
+ (pPhysDisk0->PhysDiskStatus.Flags &
|
|
+ MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC))
|
|
+ pKarg->Configuration.Drives[i].bDriveStatus =
|
|
+ CSMI_SAS_DRIVE_STATUS_DEGRADED;
|
|
+
|
|
+ memset(pKarg->Configuration.Drives[i].bSASLun,
|
|
+ 0, sizeof(pKarg->Configuration.Drives[i].bSASLun));
|
|
+ if (csmisas_is_sata(pPhysDisk0)) {
|
|
+ pKarg->Configuration.Drives[i].bDriveType =
|
|
+ CSMI_SAS_DRIVE_TYPE_SATA;
|
|
+ } else { /* drive in a volume can only be SAS/SATA */
|
|
+ pKarg->Configuration.Drives[i].bDriveType =
|
|
+ CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS;
|
|
+ if (mpt_raid_phys_disk_get_num_paths(ioc,
|
|
+ pVolume0->PhysDisk[i].PhysDiskNum) > 1)
|
|
+ pKarg->Configuration.Drives[i].bDriveType =
|
|
+ CSMI_SAS_DRIVE_TYPE_DUAL_PORT_SAS;
|
|
+ }
|
|
+
|
|
+ pKarg->Configuration.Drives[i].usBlockSize = 512;
|
|
+ pKarg->Configuration.Drives[i].uDriveIndex =
|
|
+ pPhysDisk0->PhysDiskNum;
|
|
+ pKarg->Configuration.Drives[i].ulTotalUserBlocks.uLowPart =
|
|
+ (u32)tmpTotalMaxLBA;
|
|
+ pKarg->Configuration.Drives[i].ulTotalUserBlocks.uHighPart =
|
|
+ (u32)(tmpTotalMaxLBA >> 32);
|
|
+ }
|
|
+
|
|
+ /* adding hot spare info at the end */
|
|
+ if ((pVolume0->VolumeSettings.HotSparePool) && (pIocPage5) &&
|
|
+ (pVolume0->VolumeType != MPI_RAID_VOL_TYPE_IS)) {
|
|
+ for (idx = 0, i = pVolume0->NumPhysDisks ;
|
|
+ idx < pIocPage5->NumHotSpares ; idx++) {
|
|
+ if (i >= physDiskNumMax)
|
|
+ break;
|
|
+ if ((pVolume0->VolumeSettings.HotSparePool &
|
|
+ pIocPage5->HotSpare[idx].HotSparePool) == 0)
|
|
+ continue;
|
|
+ if(pIocPage5->HotSpare[idx].Flags !=
|
|
+ MPI_IOC_PAGE_5_HOT_SPARE_ACTIVE)
|
|
+ continue;
|
|
+ physDiskNum = pIocPage5->HotSpare[idx].PhysDiskNum;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+ cfg.pageAddr = physDiskNum;
|
|
+ if (mpt_config(ioc, &cfg) != 0)
|
|
+ continue;
|
|
+
|
|
+ /* don't mix SSP hot spare
|
|
+ * in SATA volume
|
|
+ */
|
|
+ if (!csmisas_is_sata(pPhysDisk0) &&
|
|
+ (device_info &
|
|
+ MPI_SAS_DEVICE_INFO_SATA_DEVICE))
|
|
+ continue;
|
|
+
|
|
+ /* don't mix SATA hot spare
|
|
+ * in SSP volume
|
|
+ */
|
|
+ if (csmisas_is_sata(pPhysDisk0) &&
|
|
+ (device_info &
|
|
+ MPI_SAS_DEVICE_INFO_SSP_TARGET))
|
|
+ continue;
|
|
+
|
|
+ /* capacity check for IM volumes*/
|
|
+ if ((pVolume0->VolumeType ==
|
|
+ MPI_RAID_VOL_TYPE_IM) &&
|
|
+ (totalMaxLBA +
|
|
+ (64*2*1024) /* metadata = 64MB*/ >
|
|
+ le32_to_cpu(pPhysDisk0->MaxLBA)))
|
|
+ continue;
|
|
+
|
|
+ tmpTotalMaxLBA = totalMaxLBA;
|
|
+ do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks);
|
|
+ /* capacity check for IME volumes*/
|
|
+ if ((pVolume0->VolumeType ==
|
|
+ MPI_RAID_VOL_TYPE_IME) &&
|
|
+ (((totalMaxLBA +
|
|
+ pVolume0->NumPhysDisks) * 2) +
|
|
+ (64*2*1024 ) /*metadata = 64MB*/ >
|
|
+ le32_to_cpu(pPhysDisk0->MaxLBA)))
|
|
+ continue;
|
|
+
|
|
+ pKarg->Configuration.bDriveCount++;
|
|
+ if (pKarg->Configuration.bDataType !=
|
|
+ CSMI_SAS_RAID_DATA_DRIVES) {
|
|
+ i++;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ /* Search the list for the matching SAS address. */
|
|
+ sas_info = csmisas_get_device_component_by_fw(ioc,
|
|
+ pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID);
|
|
+ if (sas_info) {
|
|
+ sas_address = reverse_byte_order64(sas_info->sas_address);
|
|
+ memcpy(pKarg->Configuration.Drives[i].bSASAddress,
|
|
+ &sas_address,sizeof(u64));
|
|
+ }
|
|
+
|
|
+ memcpy(pKarg->Configuration.Drives[i].bModel,
|
|
+ pPhysDisk0->InquiryData.VendorID,
|
|
+ offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel));
|
|
+ memcpy(pKarg->Configuration.Drives[i].bFirmware,
|
|
+ pPhysDisk0->InquiryData.ProductRevLevel,
|
|
+ sizeof(pPhysDisk0->InquiryData.ProductRevLevel));
|
|
+ if (csmisas_is_sata(pPhysDisk0)) {
|
|
+ memcpy(&pKarg->Configuration.Drives[i].bSerialNumber,
|
|
+ &pPhysDisk0->ExtDiskIdentifier[4],
|
|
+ 4);
|
|
+ memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4],
|
|
+ &pPhysDisk0->DiskIdentifier,
|
|
+ sizeof(pPhysDisk0->DiskIdentifier));
|
|
+ } else {
|
|
+ memcpy(pKarg->Configuration.Drives[i].bSerialNumber,
|
|
+ pPhysDisk0->DiskIdentifier,
|
|
+ sizeof(pPhysDisk0->DiskIdentifier));
|
|
+ }
|
|
+ pKarg->Configuration.Drives[i].bDriveStatus =
|
|
+ CSMI_SAS_DRIVE_STATUS_OK;
|
|
+ if(pPhysDisk0->PhysDiskStatus.State)
|
|
+ pKarg->Configuration.Drives[i].bDriveStatus =
|
|
+ CSMI_SAS_DRIVE_STATUS_FAILED;
|
|
+ else if(pPhysDisk0->ErrorData.SmartCount)
|
|
+ pKarg->Configuration.Drives[i].bDriveStatus =
|
|
+ CSMI_SAS_DRIVE_STATUS_DEGRADED;
|
|
+ pKarg->Configuration.Drives[i].bDriveUsage =
|
|
+ CSMI_SAS_DRIVE_CONFIG_SPARE;
|
|
+ pKarg->Configuration.Drives[i].usBlockSize = 512;
|
|
+ pKarg->Configuration.Drives[i].uDriveIndex =
|
|
+ pPhysDisk0->PhysDiskNum;
|
|
+ if (csmisas_is_sata(pPhysDisk0)) {
|
|
+ pKarg->Configuration.Drives[i].bDriveType =
|
|
+ CSMI_SAS_DRIVE_TYPE_SATA;
|
|
+ } else { /* drive in a volume can only be SAS/SATA */
|
|
+ pKarg->Configuration.Drives[i].bDriveType =
|
|
+ CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS;
|
|
+ if (mpt_raid_phys_disk_get_num_paths(ioc,
|
|
+ pVolume0->PhysDisk[i].PhysDiskNum) > 1)
|
|
+ pKarg->Configuration.Drives[i].bDriveType =
|
|
+ CSMI_SAS_DRIVE_TYPE_DUAL_PORT_SAS;
|
|
+ }
|
|
+ i++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Only return data on the first 240 drives
|
|
+ if( pKarg->Configuration.bDriveCount > 0xF0 )
|
|
+ pKarg->Configuration.bDriveCount =
|
|
+ CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG;
|
|
+
|
|
+ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+
|
|
+ cim_get_raid_config_exit:
|
|
+
|
|
+ if (pVolume0 != NULL)
|
|
+ pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0,
|
|
+ volume0_dma);
|
|
+
|
|
+ if(pPhysDisk0 != NULL)
|
|
+ pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0,
|
|
+ physdisk0_dma);
|
|
+
|
|
+ if(pIocPage5 != NULL)
|
|
+ pci_free_consistent(ioc->pcidev, ioc_page5_sz, pIocPage5,
|
|
+ ioc_page5_dma);
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+
|
|
+ /* find the buffer size to copy depending on how much is filled-in */
|
|
+ switch (pKarg->Configuration.bDataType) {
|
|
+ case CSMI_SAS_RAID_DATA_ADDITIONAL_DATA:
|
|
+ copy_buffer_sz = sizeof(IOCTL_HEADER) +
|
|
+ offsetof(CSMI_SAS_RAID_CONFIG,Data) +
|
|
+ sizeof(CSMI_SAS_RAID_SET_ADDITIONAL_DATA);
|
|
+ break;
|
|
+ case CSMI_SAS_RAID_DATA_DRIVES:
|
|
+ if (pKarg->Configuration.bDriveCount ==
|
|
+ CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED)
|
|
+ copy_buffer_sz = sizeof(IOCTL_HEADER) +
|
|
+ offsetof(CSMI_SAS_RAID_CONFIG,Drives);
|
|
+ else
|
|
+ copy_buffer_sz = sizeof(IOCTL_HEADER) +
|
|
+ offsetof(CSMI_SAS_RAID_CONFIG,Drives) +
|
|
+ (pKarg->Configuration.bDriveCount *
|
|
+ sizeof(CSMI_SAS_RAID_DRIVES));
|
|
+ break;
|
|
+ case CSMI_SAS_RAID_DATA_DEVICE_ID:
|
|
+ copy_buffer_sz = csmi_sas_raid_config_buffer_sz;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (copy_to_user(uarg, pKarg, copy_buffer_sz)) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_get_raid_config @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI SAS Get RAID Features command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_raid_features(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_RAID_FEATURES_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_RAID_FEATURES_BUFFER karg, *pKarg=NULL;
|
|
+ int csmi_sas_raid_features_buffer_sz, iocnum;
|
|
+ int memory_pages;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_get_raid_features struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ csmi_sas_raid_features_buffer_sz = karg.IoctlHeader.Length;
|
|
+ memory_pages = get_order(csmi_sas_raid_features_buffer_sz);
|
|
+ pKarg = (CSMI_SAS_RAID_FEATURES_BUFFER *)__get_free_pages(
|
|
+ GFP_KERNEL, memory_pages);
|
|
+ if (!pKarg){
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to malloc RAID_FEATURES_BUFFER "
|
|
+ "csmi_sas_raid_features_buffer_sz=%d memory_pages=%d\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__,
|
|
+ csmi_sas_raid_features_buffer_sz, memory_pages);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+ memset(pKarg, 0, sizeof(*pKarg));
|
|
+
|
|
+ if (copy_from_user(pKarg, uarg, csmi_sas_raid_features_buffer_sz)) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_get_raid_features struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ if (pKarg->Information.uChangeCount != 0 &&
|
|
+ pKarg->Information.uChangeCount != ioc->csmi_change_count ) {
|
|
+ pKarg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ pKarg->Information.uFailureCode =
|
|
+ CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
|
|
+ goto cim_get_raid_features_exit;
|
|
+ }
|
|
+
|
|
+ pKarg->Information.uFeatures = CSMI_SAS_RAID_FEATURE_REBUILD |
|
|
+ CSMI_SAS_RAID_FEATURE_SURFACE_SCAN |
|
|
+ CSMI_SAS_RAID_FEATURE_SPARES_SHARED;
|
|
+ pKarg->Information.bDefaultTransformPriority =
|
|
+ CSMI_SAS_PRIORITY_UNKNOWN;
|
|
+ pKarg->Information.bTransformPriority = CSMI_SAS_PRIORITY_UNKNOWN;
|
|
+ pKarg->Information.bDefaultRebuildPriority = CSMI_SAS_PRIORITY_UNKNOWN;
|
|
+ pKarg->Information.bRebuildPriority =
|
|
+ pKarg->Information.bDefaultRebuildPriority;
|
|
+ pKarg->Information.bDefaultSurfaceScanPriority =
|
|
+ CSMI_SAS_PRIORITY_UNKNOWN;
|
|
+ pKarg->Information.bSurfaceScanPriority = CSMI_SAS_PRIORITY_UNKNOWN;
|
|
+ pKarg->Information.uRaidSetTransformationRules = 0;
|
|
+
|
|
+ /* IS */
|
|
+ pKarg->Information.RaidType[0].bRaidType = CSMI_SAS_RAID_TYPE_0;
|
|
+ pKarg->Information.RaidType[0].uSupportedStripeSizeMap = 0x80;
|
|
+
|
|
+ /* IM */
|
|
+ pKarg->Information.RaidType[1].bRaidType = CSMI_SAS_RAID_TYPE_1;
|
|
+ pKarg->Information.RaidType[1].uSupportedStripeSizeMap = 0;
|
|
+
|
|
+ /* IME */
|
|
+ pKarg->Information.RaidType[2].bRaidType = CSMI_SAS_RAID_TYPE_1E;
|
|
+ pKarg->Information.RaidType[2].uSupportedStripeSizeMap = 0x80;
|
|
+
|
|
+ pKarg->Information.RaidType[3].bRaidType = CSMI_SAS_RAID_TYPE_END;
|
|
+ pKarg->Information.bCacheRatiosSupported[0] =
|
|
+ CSMI_SAS_RAID_CACHE_RATIO_END;
|
|
+
|
|
+ cim_get_raid_features_exit:
|
|
+
|
|
+ /*
|
|
+ * Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, pKarg,
|
|
+ sizeof(CSMI_SAS_RAID_FEATURES_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_get_raid_features @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI SAS Set RAID Control command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_set_raid_control(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_RAID_CONTROL_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_RAID_CONTROL_BUFFER karg, *pKarg=NULL;
|
|
+ int csmi_sas_raid_control_buffer_sz, iocnum;
|
|
+ int memory_pages;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_set_raid_control struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ csmi_sas_raid_control_buffer_sz = karg.IoctlHeader.Length;
|
|
+ memory_pages = get_order(csmi_sas_raid_control_buffer_sz);
|
|
+ pKarg = (CSMI_SAS_RAID_CONTROL_BUFFER *)__get_free_pages(
|
|
+ GFP_KERNEL, memory_pages);
|
|
+ if (!pKarg){
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to malloc RAID_CONTROL_BUFFER "
|
|
+ "csmi_sas_raid_control_buffer_sz=%d memory_pages=%d\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__,
|
|
+ csmi_sas_raid_control_buffer_sz, memory_pages);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+ memset(pKarg, 0, sizeof(*pKarg));
|
|
+
|
|
+ if (copy_from_user(pKarg, uarg, csmi_sas_raid_control_buffer_sz)) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_set_raid_control struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ if (pKarg->Information.uChangeCount != 0 &&
|
|
+ pKarg->Information.uChangeCount != ioc->csmi_change_count ) {
|
|
+ pKarg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ pKarg->Information.uFailureCode =
|
|
+ CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID;
|
|
+ goto cim_set_raid_control_exit;
|
|
+ }
|
|
+
|
|
+ if (pKarg->Information.bTransformPriority !=
|
|
+ CSMI_SAS_PRIORITY_UNCHANGED) {
|
|
+ pKarg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ pKarg->Information.uFailureCode =
|
|
+ CSMI_SAS_FAIL_CODE_TRANSFORM_PRIORITY_INVALID;
|
|
+ goto cim_set_raid_control_exit;
|
|
+ }
|
|
+
|
|
+ if (pKarg->Information.bRebuildPriority !=
|
|
+ CSMI_SAS_PRIORITY_AUTO &&
|
|
+ pKarg->Information.bRebuildPriority !=
|
|
+ CSMI_SAS_PRIORITY_UNCHANGED) {
|
|
+ pKarg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ pKarg->Information.uFailureCode =
|
|
+ CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID;
|
|
+ goto cim_set_raid_control_exit;
|
|
+ }
|
|
+
|
|
+ if (pKarg->Information.bCacheRatioFlag ==
|
|
+ CSMI_SAS_RAID_CACHE_RATIO_DISABLE) {
|
|
+ pKarg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ pKarg->Information.uFailureCode =
|
|
+ CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID;
|
|
+ goto cim_set_raid_control_exit;
|
|
+ }
|
|
+
|
|
+ if( !strcmp(pKarg->Information.bClearConfiguration,
|
|
+ CSMI_SAS_RAID_CLEAR_CONFIGURATION_SIGNATURE) ) {
|
|
+ pKarg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ pKarg->Information.uFailureCode =
|
|
+ CSMI_SAS_FAIL_CODE_CLEAR_CONFIGURATION_INVALID;
|
|
+ goto cim_set_raid_control_exit;
|
|
+ }
|
|
+
|
|
+ pKarg->Information.bFailureDescription[0] = '\0';
|
|
+
|
|
+ cim_set_raid_control_exit:
|
|
+
|
|
+ /*
|
|
+ * Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, pKarg,
|
|
+ sizeof(CSMI_SAS_RAID_CONTROL_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_set_raid_control @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ free_pages((unsigned long)pKarg, memory_pages);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI SAS Get Raid Element.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_raid_element(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_RAID_ELEMENT_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_RAID_ELEMENT_BUFFER karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ int iocnum;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_ELEMENT_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmisas_get_raid_element struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+/* TODO - implement IOCTL here */
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE;
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG ": not implemented\n"));
|
|
+
|
|
+// csmisas_get_raid_element_exit:
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, &karg,
|
|
+ sizeof(CSMI_SAS_RAID_ELEMENT_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmisas_get_raid_element @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI SAS Set Raid Operation
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_set_raid_operation(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_RAID_SET_OPERATION_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_RAID_SET_OPERATION_BUFFER karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ int iocnum;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_SET_OPERATION_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_set_raid_operation struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+/* TODO - implement IOCTL here */
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE;
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG ": not implemented\n"));
|
|
+
|
|
+// cim_set_raid_operation:
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, &karg,
|
|
+ sizeof(CSMI_SAS_RAID_SET_OPERATION_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_set_raid_operation @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI SAS Task Managment Config command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_task_managment(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_SSP_TASK_IU_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_SSP_TASK_IU_BUFFER karg;
|
|
+ pSCSITaskMgmt_t pScsiTm;
|
|
+ pSCSITaskMgmtReply_t pScsiTmReply;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ MPT_SCSI_HOST *hd;
|
|
+ MPT_FRAME_HDR *mf = NULL;
|
|
+ MPIHeader_t *mpi_hdr;
|
|
+ int iocnum;
|
|
+ u8 taskType;
|
|
+ u8 channel;
|
|
+ u8 id;
|
|
+ u8 queueTag;
|
|
+ u32 TaskMsgContext = 0;
|
|
+ int i;
|
|
+ u8 found_qtag;
|
|
+ struct sas_device_info *sas_info;
|
|
+ u16 ioc_status;
|
|
+ u32 MsgContext;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_task_managment struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+
|
|
+ sas_info = csmisas_get_device_component_by_os(ioc,
|
|
+ karg.Parameters.bPathId, karg.Parameters.bTargetId);
|
|
+ if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume)
|
|
+ goto cim_get_task_managment_exit;
|
|
+
|
|
+ channel = sas_info->fw.channel;
|
|
+ id = sas_info->fw.id;
|
|
+ queueTag = (u8)karg.Parameters.uQueueTag & 0xFF;
|
|
+ hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
|
|
+
|
|
+ /* try to catch an error
|
|
+ */
|
|
+ if ((karg.Parameters.uFlags & CSMI_SAS_TASK_IU) &&
|
|
+ (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE))
|
|
+ goto cim_get_task_managment_exit;
|
|
+
|
|
+ if (karg.Parameters.uFlags & CSMI_SAS_TASK_IU) {
|
|
+ switch (karg.Parameters.bTaskManagementFunction) {
|
|
+
|
|
+ case CSMI_SAS_SSP_ABORT_TASK:
|
|
+ taskType = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
|
|
+ break;
|
|
+ case CSMI_SAS_SSP_ABORT_TASK_SET:
|
|
+ taskType = MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET;
|
|
+ break;
|
|
+ case CSMI_SAS_SSP_CLEAR_TASK_SET:
|
|
+ taskType = MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET;
|
|
+ break;
|
|
+ case CSMI_SAS_SSP_LOGICAL_UNIT_RESET:
|
|
+ taskType = MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET;
|
|
+ break;
|
|
+ case CSMI_SAS_SSP_CLEAR_ACA:
|
|
+ case CSMI_SAS_SSP_QUERY_TASK:
|
|
+ default:
|
|
+ goto cim_get_task_managment_exit;
|
|
+ }
|
|
+ } else if (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE)
|
|
+ taskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
|
|
+ else
|
|
+ goto cim_get_task_managment_exit;
|
|
+
|
|
+ switch (karg.Parameters.uInformation) {
|
|
+ case CSMI_SAS_SSP_TEST:
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "TM request for test purposes\n"));
|
|
+ break;
|
|
+ case CSMI_SAS_SSP_EXCEEDED:
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "TM request due to timeout\n"));
|
|
+ break;
|
|
+ case CSMI_SAS_SSP_DEMAND:
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "TM request demanded by app\n"));
|
|
+ break;
|
|
+ case CSMI_SAS_SSP_TRIGGER:
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "TM request sent to trigger event\n"));
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch (taskType) {
|
|
+
|
|
+ case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
|
|
+ /*
|
|
+ * look up qtag in the ScsiLookup[] table
|
|
+ */
|
|
+ for (i = 0, found_qtag = 0; i < hd->ioc->req_depth; i++) {
|
|
+ if ((ioc->ScsiLookup[i]) &&
|
|
+ (ioc->ScsiLookup[i]->tag == queueTag)) {
|
|
+ mf = MPT_INDEX_2_MFPTR(hd->ioc, i);
|
|
+ TaskMsgContext =
|
|
+ mf->u.frame.hwhdr.msgctxu.MsgContext;
|
|
+ found_qtag=1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if(!found_qtag)
|
|
+ goto cim_get_task_managment_exit;
|
|
+
|
|
+ case MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
|
|
+ case MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
|
|
+ case MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:
|
|
+ /* for now, this should work
|
|
+ */
|
|
+ case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
|
|
+
|
|
+ /* Single threading ....
|
|
+ */
|
|
+ mutex_lock(&ioc->taskmgmt_cmds.mutex);
|
|
+ if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
|
|
+ mutex_unlock(&ioc->taskmgmt_cmds.mutex);
|
|
+ karg.IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_task_managment_exit;
|
|
+ }
|
|
+ /* Send request
|
|
+ */
|
|
+ if ((mf = mpt_get_msg_frame(mptctl_taskmgmt_id, ioc)) == NULL) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
|
|
+ mutex_unlock(&ioc->taskmgmt_cmds.mutex);
|
|
+ mpt_clear_taskmgmt_in_progress_flag(ioc);
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_task_managment_exit;
|
|
+ }
|
|
+
|
|
+ mpi_hdr = (MPIHeader_t *) mf;
|
|
+ MsgContext = mpi_hdr->MsgContext;
|
|
+ pScsiTm = (pSCSITaskMgmt_t ) mf;
|
|
+
|
|
+ memset(pScsiTm,0,sizeof(SCSITaskMgmt_t));
|
|
+ pScsiTm->TaskType = taskType;
|
|
+ pScsiTm->Bus = channel;
|
|
+ pScsiTm->TargetID = id;
|
|
+ int_to_scsilun(karg.Parameters.bLun,
|
|
+ (struct scsi_lun *)pScsiTm->LUN);
|
|
+ pScsiTm->MsgContext = MsgContext;
|
|
+ pScsiTm->TaskMsgContext = TaskMsgContext;
|
|
+ pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
|
|
+
|
|
+ if (csmisas_send_handshake_wait(ioc, mf,
|
|
+ karg.IoctlHeader.Timeout) != 0) {
|
|
+ mutex_unlock(&ioc->taskmgmt_cmds.mutex);
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_get_task_managment_exit;
|
|
+ }
|
|
+
|
|
+ if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) {
|
|
+
|
|
+ pScsiTmReply =
|
|
+ (pSCSITaskMgmtReply_t ) ioc->ioctl_cmds.reply;
|
|
+
|
|
+ ioc_status = le16_to_cpu(pScsiTmReply->IOCStatus)
|
|
+ & MPI_IOCSTATUS_MASK;
|
|
+
|
|
+ memset(&karg.Status,0,
|
|
+ sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS));
|
|
+
|
|
+ if(ioc_status == MPI_IOCSTATUS_SUCCESS) {
|
|
+ karg.IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_SUCCESS;
|
|
+ karg.Status.bSSPStatus =
|
|
+ CSMI_SAS_SSP_STATUS_COMPLETED;
|
|
+ }else if(ioc_status == MPI_IOCSTATUS_INSUFFICIENT_RESOURCES) {
|
|
+ karg.IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_SUCCESS;
|
|
+ karg.Status.bSSPStatus =
|
|
+ CSMI_SAS_SSP_STATUS_RETRY;
|
|
+ }else {
|
|
+ karg.IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_FAILED;
|
|
+ karg.Status.bSSPStatus =
|
|
+ CSMI_SAS_SSP_STATUS_FATAL_ERROR;
|
|
+ }
|
|
+ } else
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ mutex_unlock(&ioc->taskmgmt_cmds.mutex);
|
|
+
|
|
+ cim_get_task_managment_exit:
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, &karg,
|
|
+ sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_task_managment @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * map_sas_status_to_csmi - Conversion for Connection Status
|
|
+ * @mpi_sas_status: Sas status returned by the firmware
|
|
+ *
|
|
+ * Returns converted connection status
|
|
+ *
|
|
+ **/
|
|
+static u8
|
|
+map_sas_status_to_csmi(u8 mpi_sas_status)
|
|
+{
|
|
+ u8 csmi_connect_status;
|
|
+
|
|
+ switch (mpi_sas_status) {
|
|
+
|
|
+ case MPI_SASSTATUS_SUCCESS:
|
|
+ csmi_connect_status = CSMI_SAS_OPEN_ACCEPT;
|
|
+ break;
|
|
+
|
|
+ case MPI_SASSTATUS_UTC_BAD_DEST:
|
|
+ csmi_connect_status = CSMI_SAS_OPEN_REJECT_BAD_DESTINATION;
|
|
+ break;
|
|
+
|
|
+ case MPI_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED:
|
|
+ csmi_connect_status = CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED;
|
|
+ break;
|
|
+
|
|
+ case MPI_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED:
|
|
+ csmi_connect_status =
|
|
+ CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED;
|
|
+ break;
|
|
+
|
|
+ case MPI_SASSTATUS_UTC_STP_RESOURCES_BUSY:
|
|
+ csmi_connect_status = CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY;
|
|
+ break;
|
|
+
|
|
+ case MPI_SASSTATUS_UTC_WRONG_DESTINATION:
|
|
+ csmi_connect_status = CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION;
|
|
+ break;
|
|
+
|
|
+ case MPI_SASSTATUS_SDSF_NAK_RECEIVED:
|
|
+ csmi_connect_status = CSMI_SAS_OPEN_REJECT_RETRY;
|
|
+ break;
|
|
+
|
|
+ case MPI_SASSTATUS_SDSF_CONNECTION_FAILED:
|
|
+ csmi_connect_status = CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED;
|
|
+ break;
|
|
+
|
|
+ case MPI_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT:
|
|
+ csmi_connect_status = CSMI_SAS_OPEN_REJECT_NO_DESTINATION;
|
|
+ break;
|
|
+
|
|
+ case MPI_SASSTATUS_UNKNOWN_ERROR:
|
|
+ case MPI_SASSTATUS_INVALID_FRAME:
|
|
+ case MPI_SASSTATUS_UTC_BREAK_RECEIVED:
|
|
+ case MPI_SASSTATUS_UTC_PORT_LAYER_REQUEST:
|
|
+ case MPI_SASSTATUS_SHORT_INFORMATION_UNIT:
|
|
+ case MPI_SASSTATUS_LONG_INFORMATION_UNIT:
|
|
+ case MPI_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA:
|
|
+ case MPI_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR:
|
|
+ case MPI_SASSTATUS_XFER_RDY_NOT_EXPECTED:
|
|
+ case MPI_SASSTATUS_DATA_INCORRECT_DATA_LENGTH:
|
|
+ case MPI_SASSTATUS_DATA_TOO_MUCH_READ_DATA:
|
|
+ case MPI_SASSTATUS_DATA_OFFSET_ERROR:
|
|
+ csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return csmi_connect_status;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_phy_reset
|
|
+ * Issues a phy link reset or phy hard reset
|
|
+ *
|
|
+ * @ioc - Pointer to MPT_ADAPTER structure
|
|
+ * @PhyNum - phy number
|
|
+ * @opcode - {MPI_SAS_OP_PHY_LINK_RESET,MPI_SAS_OP_PHY_HARD_RESET}
|
|
+ *
|
|
+ * Returns: 0 for success, non-zero error
|
|
+ **/
|
|
+static int
|
|
+csmisas_phy_reset(MPT_ADAPTER *ioc, u8 PhyNum, u8 opcode)
|
|
+{
|
|
+ SasIoUnitControlRequest_t *sasIoUnitCntrReq;
|
|
+ SasIoUnitControlReply_t *sasIoUnitCntrReply;
|
|
+ MPT_FRAME_HDR *mf = NULL;
|
|
+ MPIHeader_t *mpi_hdr;
|
|
+ u16 ioc_status;
|
|
+ u32 MsgContext;
|
|
+
|
|
+ if ((opcode != MPI_SAS_OP_PHY_LINK_RESET) &&
|
|
+ (opcode != MPI_SAS_OP_PHY_HARD_RESET))
|
|
+ return -1;
|
|
+
|
|
+ /* Get a MF for this command.
|
|
+ */
|
|
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": no msg frames!\n"));
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ mpi_hdr = (MPIHeader_t *) mf;
|
|
+ MsgContext = mpi_hdr->MsgContext;
|
|
+ sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
|
|
+ memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
|
|
+ sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
|
|
+ sasIoUnitCntrReq->MsgContext = MsgContext;
|
|
+ sasIoUnitCntrReq->Operation = opcode;
|
|
+ sasIoUnitCntrReq->PhyNum = PhyNum;
|
|
+
|
|
+ if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0)
|
|
+ return -1;
|
|
+
|
|
+ if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) == 0)
|
|
+ return -1;
|
|
+
|
|
+ /* process the completed Reply Message Frame */
|
|
+ sasIoUnitCntrReply = (SasIoUnitControlReply_t *)ioc->ioctl_cmds.reply;
|
|
+ ioc_status = le16_to_cpu(sasIoUnitCntrReply->IOCStatus)
|
|
+ & MPI_IOCSTATUS_MASK;
|
|
+ if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
|
|
+ printk(KERN_DEBUG "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
|
|
+ __FUNCTION__,
|
|
+ sasIoUnitCntrReply->IOCStatus,
|
|
+ sasIoUnitCntrReply->IOCLogInfo);
|
|
+ return -1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/** Prototype Routine for the CSMI SAS Phy Control command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_phy_control(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_PHY_CONTROL_BUFFER __user *uarg = (void __user *) arg;
|
|
+ IOCTL_HEADER ioctl_header;
|
|
+ PCSMI_SAS_PHY_CONTROL_BUFFER karg;
|
|
+ SasIOUnitPage0_t *sasIoUnitPg0=NULL;
|
|
+ dma_addr_t sasIoUnitPg0_dma;
|
|
+ int sasIoUnitPg0_data_sz=0;
|
|
+ SasIOUnitPage1_t *sasIoUnitPg1=NULL;
|
|
+ dma_addr_t sasIoUnitPg1_dma;
|
|
+ int sasIoUnitPg1_data_sz=0;
|
|
+ ConfigExtendedPageHeader_t hdr;
|
|
+ CONFIGPARMS cfg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ int iocnum;
|
|
+ int csmi_sas_phy_control_buffer_sz;
|
|
+ int memory_pages;
|
|
+
|
|
+ if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in IOCTL_HEADER"
|
|
+ "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ csmi_sas_phy_control_buffer_sz = ioctl_header.Length;
|
|
+ memory_pages = get_order(csmi_sas_phy_control_buffer_sz);
|
|
+ karg = (PCSMI_SAS_PHY_CONTROL_BUFFER)__get_free_pages(
|
|
+ GFP_KERNEL, memory_pages);
|
|
+ if (!karg){
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to malloc SAS_PHY_CONTROL_BUFFER "
|
|
+ "csmi_sas_phy_control_buffer_sz=%d memory_pages=%d\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__,
|
|
+ csmi_sas_phy_control_buffer_sz, memory_pages);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+ memset(karg, 0, sizeof(*karg));
|
|
+
|
|
+ if (copy_from_user(karg, uarg, csmi_sas_phy_control_buffer_sz)) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_phy_control_buffer "
|
|
+ "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(ioctl_header.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ if (karg->bPhyIdentifier >= ioc->num_ports) {
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Retreive SAS IOUNIT PAGE 0
|
|
+ */
|
|
+
|
|
+ hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
|
|
+ hdr.ExtPageLength = 0;
|
|
+ hdr.PageNumber = 0;
|
|
+ hdr.Reserved1 = 0;
|
|
+ hdr.Reserved2 = 0;
|
|
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
|
|
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
|
|
+
|
|
+ cfg.cfghdr.ehdr = &hdr;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.pageAddr = 0;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0; /* read */
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+
|
|
+ if (mpt_config(ioc, &cfg) != 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: READ MPI_SASIOUNITPAGE0: HEADER\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+
|
|
+ if (hdr.ExtPageLength == 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": hdr.ExtPageLength == 0\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+
|
|
+ sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4;
|
|
+ sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev,
|
|
+ sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma);
|
|
+
|
|
+ if (!sasIoUnitPg0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+
|
|
+ memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz);
|
|
+ cfg.physAddr = sasIoUnitPg0_dma;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+
|
|
+ if (mpt_config(ioc, &cfg) != 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: READ MPI_SASIOUNITPAGE0: CURRENT\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Retreive SAS IOUNIT PAGE 1
|
|
+ */
|
|
+
|
|
+ hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
|
|
+ hdr.ExtPageLength = 0;
|
|
+ hdr.PageNumber = 1;
|
|
+ hdr.Reserved1 = 0;
|
|
+ hdr.Reserved2 = 0;
|
|
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
|
|
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
|
|
+
|
|
+ cfg.cfghdr.ehdr = &hdr;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.pageAddr = 0;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0; /* read */
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+
|
|
+ if (mpt_config(ioc, &cfg) != 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: READ MPI_SASIOUNITPAGE1: HEADER\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+
|
|
+ if (hdr.ExtPageLength == 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": hdr.ExtPageLength == 0\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+
|
|
+ sasIoUnitPg1_data_sz = hdr.ExtPageLength * 4;
|
|
+ sasIoUnitPg1 = (SasIOUnitPage1_t *) pci_alloc_consistent(ioc->pcidev,
|
|
+ sasIoUnitPg1_data_sz, &sasIoUnitPg1_dma);
|
|
+
|
|
+ if (!sasIoUnitPg1) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR ": pci_alloc_consistent: FAILED\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+
|
|
+ memset((u8 *)sasIoUnitPg1, 0, sasIoUnitPg1_data_sz);
|
|
+ cfg.physAddr = sasIoUnitPg1_dma;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+
|
|
+ if (mpt_config(ioc, &cfg) != 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: READ MPI_SASIOUNITPAGE1: CURRENT\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+
|
|
+ switch (karg->uFunction) {
|
|
+
|
|
+ case CSMI_SAS_PC_LINK_RESET:
|
|
+ case CSMI_SAS_PC_HARD_RESET:
|
|
+ {
|
|
+ u8 opcode = (karg->uFunction==CSMI_SAS_PC_LINK_RESET) ?
|
|
+ MPI_SAS_OP_PHY_LINK_RESET : MPI_SAS_OP_PHY_HARD_RESET;
|
|
+
|
|
+ if((karg->uLinkFlags & CSMI_SAS_PHY_ACTIVATE_CONTROL) &&
|
|
+ (karg->usLengthOfControl >= sizeof(CSMI_SAS_PHY_CONTROL)) &&
|
|
+ (karg->bNumberOfControls > 0)){
|
|
+ if(karg->Control[0].bRate ==
|
|
+ CSMI_SAS_LINK_RATE_1_5_GBPS) {
|
|
+ sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate =
|
|
+ MPI_SAS_IOUNIT1_MAX_RATE_1_5 |
|
|
+ MPI_SAS_IOUNIT1_MIN_RATE_1_5;
|
|
+ }
|
|
+ else if(karg->Control[0].bRate ==
|
|
+ CSMI_SAS_LINK_RATE_3_0_GBPS) {
|
|
+ sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate =
|
|
+ MPI_SAS_IOUNIT1_MAX_RATE_3_0 |
|
|
+ MPI_SAS_IOUNIT1_MIN_RATE_3_0;
|
|
+ }
|
|
+ sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags &=
|
|
+ ~MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE;
|
|
+ cfg.dir = 1;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
|
|
+ if (mpt_config(ioc, &cfg) != 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n"));
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
|
|
+ if (mpt_config(ioc, &cfg) != 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n"));
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+ }
|
|
+ if (csmisas_phy_reset(ioc,
|
|
+ karg->bPhyIdentifier, opcode) != 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: csmisas_phy_reset\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ }
|
|
+ case CSMI_SAS_PC_PHY_DISABLE:
|
|
+ if(karg->usLengthOfControl || karg->bNumberOfControls) {
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ break;
|
|
+ }
|
|
+ sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags |=
|
|
+ MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE;
|
|
+ cfg.dir = 1;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
|
|
+ if (mpt_config(ioc, &cfg) != 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
|
|
+ if (mpt_config(ioc, &cfg) != 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+ if (csmisas_phy_reset(ioc,
|
|
+ karg->bPhyIdentifier, MPI_SAS_OP_PHY_HARD_RESET) != 0) {
|
|
+ dcsmisasprintk(ioc, printk(KERN_ERR
|
|
+ ": FAILED: csmisas_phy_reset\n"));
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_phy_control_exit;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case CSMI_SAS_PC_GET_PHY_SETTINGS:
|
|
+ if(karg->usLengthOfControl || karg->bNumberOfControls) {
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ break;
|
|
+ }
|
|
+ if(csmi_sas_phy_control_buffer_sz <
|
|
+ offsetof(CSMI_SAS_PHY_CONTROL_BUFFER,Control) +
|
|
+ (4* sizeof(CSMI_SAS_PHY_CONTROL))) {
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ break;
|
|
+ }
|
|
+ karg->usLengthOfControl = sizeof(CSMI_SAS_PHY_CONTROL);
|
|
+ karg->bNumberOfControls = 4;
|
|
+ karg->Control[0].bType = CSMI_SAS_SAS;
|
|
+ karg->Control[0].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS;
|
|
+ karg->Control[1].bType = CSMI_SAS_SAS;
|
|
+ karg->Control[1].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS;
|
|
+ karg->Control[2].bType = CSMI_SAS_SATA;
|
|
+ karg->Control[2].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS;
|
|
+ karg->Control[3].bType = CSMI_SAS_SATA;
|
|
+ karg->Control[3].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS;
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ cim_sas_phy_control_exit:
|
|
+
|
|
+ if (sasIoUnitPg0)
|
|
+ pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz,
|
|
+ (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma);
|
|
+
|
|
+ if (sasIoUnitPg1)
|
|
+ pci_free_consistent(ioc->pcidev, sasIoUnitPg1_data_sz,
|
|
+ (u8 *) sasIoUnitPg1, sasIoUnitPg1_dma);
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, karg,csmi_sas_phy_control_buffer_sz)) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_phy_control_buffer @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_get_manuf_pg_7 - Fetch Manufacturing config Page7.
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @mfgpage7_buffer: pointer to ManufacturingPage7_t that returns config
|
|
+ * page data
|
|
+ * @mfg_size - max size of buffer
|
|
+ *
|
|
+ * Return: 0 for success
|
|
+ * -ENOMEM if no memory available
|
|
+ * -EPERM if not allowed due to ISR context
|
|
+ * -EAGAIN if no msg frames currently available
|
|
+ * -EFAULT for non-successful reply or no reply (timeout)
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_manuf_pg_7(MPT_ADAPTER *ioc, ManufacturingPage7_t *mfgpage7_buffer, int mfg_size)
|
|
+{
|
|
+ ConfigPageHeader_t hdr;
|
|
+ CONFIGPARMS cfg;
|
|
+ ManufacturingPage7_t *mfgPage7 = NULL;
|
|
+ dma_addr_t mfgPage7_dma;
|
|
+ int data_sz = 0;
|
|
+ int rc;
|
|
+
|
|
+ /* Get Manufacturing Page 7 header */
|
|
+ hdr.PageVersion = MPI_MANUFACTURING0_PAGEVERSION;
|
|
+ hdr.PageLength = 0;
|
|
+ hdr.PageNumber = 7;
|
|
+ hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
|
|
+ cfg.cfghdr.hdr = &hdr;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0;
|
|
+ cfg.pageAddr = 0;
|
|
+ cfg.timeout = 0;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0)
|
|
+ goto csmisas_get_manuf_pg_7_exit;
|
|
+
|
|
+ if (hdr.PageLength == 0) {
|
|
+ rc = -EFAULT;
|
|
+ goto csmisas_get_manuf_pg_7_exit;
|
|
+ }
|
|
+
|
|
+ data_sz = hdr.PageLength * 4;
|
|
+ mfgPage7 = pci_alloc_consistent(ioc->pcidev, data_sz, &mfgPage7_dma);
|
|
+ if (!mfgPage7) {
|
|
+ rc = -ENOMEM;
|
|
+ goto csmisas_get_manuf_pg_7_exit;
|
|
+ }
|
|
+
|
|
+ memset((u8 *)mfgPage7, 0, data_sz);
|
|
+ cfg.physAddr = mfgPage7_dma;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0)
|
|
+ goto csmisas_get_manuf_pg_7_exit;
|
|
+
|
|
+ /* copy buffer back to user */
|
|
+ memcpy(mfgpage7_buffer, mfgPage7, min(data_sz, mfg_size));
|
|
+
|
|
+ csmisas_get_manuf_pg_7_exit:
|
|
+
|
|
+ if (mfgPage7)
|
|
+ pci_free_consistent(ioc->pcidev, data_sz, (u8 *)mfgPage7,
|
|
+ mfgPage7_dma);
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI SAS Get Connector info command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ **/
|
|
+static int
|
|
+csmisas_get_connector_info(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_CONNECTOR_INFO_BUFFER __user *uarg = (void __user *) arg;
|
|
+ CSMI_SAS_CONNECTOR_INFO_BUFFER karg;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ ManufacturingPage7_t *mfgPg7 = NULL;
|
|
+ int mfgPg7_sz;
|
|
+ int iocnum;
|
|
+ int i;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg,
|
|
+ sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_connector_info_buffer"
|
|
+ " struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+
|
|
+ /* `32` is the sizeof MPI_MANPAGE7_CONNECTOR_INFO */
|
|
+ for (i = 0; i < 32; i++) {
|
|
+ karg.Reference[i].uPinout = CSMI_SAS_CON_UNKNOWN;
|
|
+ strcpy(karg.Reference[i].bConnector,"");
|
|
+ karg.Reference[i].bLocation = CSMI_SAS_CON_UNKNOWN;
|
|
+ }
|
|
+
|
|
+ mfgPg7_sz = offsetof(CONFIG_PAGE_MANUFACTURING_7,ConnectorInfo) +
|
|
+ (ioc->num_ports * sizeof(MPI_MANPAGE7_CONNECTOR_INFO));
|
|
+ mfgPg7 = kmalloc(mfgPg7_sz, GFP_KERNEL);
|
|
+ if (!mfgPg7){
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to malloc @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, mfgPg7);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ memset(mfgPg7, 0, mfgPg7_sz);
|
|
+
|
|
+ if (!csmisas_get_manuf_pg_7(ioc, mfgPg7, mfgPg7_sz)) {
|
|
+ for (i = 0; i < ioc->num_ports; i++) {
|
|
+ karg.Reference[i].uPinout =
|
|
+ le32_to_cpu(mfgPg7->ConnectorInfo[i].Pinout);
|
|
+ /*endian conversion , this is u8 * 16 ?? */
|
|
+ strncpy(karg.Reference[i].bConnector,
|
|
+ mfgPg7->ConnectorInfo[i].Connector, 16);
|
|
+ karg.Reference[i].bLocation =
|
|
+ mfgPg7->ConnectorInfo[i].Location;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ kfree(mfgPg7);
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, &karg,
|
|
+ sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_connector_info_buffer @"
|
|
+ "%p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * csmisas_fill_location_data
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ **/
|
|
+static int
|
|
+csmisas_fill_location_data(MPT_ADAPTER *ioc, u8 bus, u8 id, u8 opcode,
|
|
+ CSMI_SAS_LOCATION_IDENTIFIER * location_ident)
|
|
+{
|
|
+
|
|
+ ConfigExtendedPageHeader_t hdr;
|
|
+ CONFIGPARMS cfg;
|
|
+ int rc;
|
|
+ SasDevicePage0_t *sasDevicePg0=NULL;
|
|
+ SasEnclosurePage0_t *sasEnclosurePg0=NULL;
|
|
+ dma_addr_t sasDevicePg0_dma,sasEnclosurePg0_dma;
|
|
+ int sasDevicePg0_data_sz=0;
|
|
+ int sasEnclosurePg0_data_sz=0;
|
|
+ u64 sas_address;
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+ memset (location_ident, 0, sizeof(*location_ident));
|
|
+
|
|
+ /* SAS Device Page 0 */
|
|
+ hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
|
|
+ hdr.ExtPageLength = 0;
|
|
+ hdr.PageNumber = 0;
|
|
+ hdr.Reserved1 = 0;
|
|
+ hdr.Reserved2 = 0;
|
|
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
|
|
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
|
|
+
|
|
+ cfg.cfghdr.ehdr = &hdr;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0; /* read */
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0) {
|
|
+ rc=-1;
|
|
+ goto fill_location_data_exit;
|
|
+ }
|
|
+
|
|
+ if (hdr.ExtPageLength == 0) {
|
|
+ rc=-1;
|
|
+ goto fill_location_data_exit;
|
|
+ }
|
|
+
|
|
+ sasDevicePg0_data_sz = hdr.ExtPageLength * 4;
|
|
+ sasDevicePg0 = (SasDevicePage0_t *) pci_alloc_consistent(
|
|
+ ioc->pcidev, sasDevicePg0_data_sz, &sasDevicePg0_dma);
|
|
+ if (!sasDevicePg0) {
|
|
+ rc=-1;
|
|
+ goto fill_location_data_exit;
|
|
+ }
|
|
+
|
|
+ memset((u8 *)sasDevicePg0, 0, sasDevicePg0_data_sz);
|
|
+ cfg.physAddr = sasDevicePg0_dma;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+ cfg.pageAddr = (bus << 8) + id
|
|
+ + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
|
|
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT);
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0) {
|
|
+ rc=-1;
|
|
+ goto fill_location_data_exit;
|
|
+ }
|
|
+
|
|
+ location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_ADDRESS_VALID;
|
|
+ memcpy(&sas_address, &sasDevicePg0->SASAddress, sizeof(u64));
|
|
+ sas_address = reverse_byte_order64(sas_address);
|
|
+ memcpy(location_ident->bSASAddress, &sas_address, sizeof(u64));
|
|
+
|
|
+ location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_LUN_VALID;
|
|
+ memset(location_ident->bSASLun, 0, sizeof(location_ident->bSASLun));
|
|
+
|
|
+ /* SAS Enclosure Page 0 */
|
|
+ hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
|
|
+ hdr.ExtPageLength = 0;
|
|
+ hdr.PageNumber = 0;
|
|
+ hdr.Reserved1 = 0;
|
|
+ hdr.Reserved2 = 0;
|
|
+ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
|
|
+ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
|
|
+
|
|
+ cfg.cfghdr.ehdr = &hdr;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0; /* read */
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0) {
|
|
+ rc=0;
|
|
+ goto fill_location_data_exit;
|
|
+ }
|
|
+
|
|
+ if (hdr.ExtPageLength == 0) {
|
|
+ rc=0;
|
|
+ goto fill_location_data_exit;
|
|
+ }
|
|
+
|
|
+ sasEnclosurePg0_data_sz = hdr.ExtPageLength * 4;
|
|
+ sasEnclosurePg0 = (SasEnclosurePage0_t *) pci_alloc_consistent(
|
|
+ ioc->pcidev, sasEnclosurePg0_data_sz, &sasEnclosurePg0_dma);
|
|
+ if (!sasEnclosurePg0) {
|
|
+ rc=0;
|
|
+ goto fill_location_data_exit;
|
|
+ }
|
|
+ cfg.physAddr = sasEnclosurePg0_dma;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+ cfg.pageAddr = sasDevicePg0->EnclosureHandle
|
|
+ + (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE << MPI_SAS_ENCLOS_PGAD_FORM_SHIFT);
|
|
+
|
|
+ if ((rc = mpt_config(ioc, &cfg)) != 0) {
|
|
+ rc=0;
|
|
+ goto fill_location_data_exit;
|
|
+ }
|
|
+
|
|
+ location_ident->bLocationFlags |= CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID;
|
|
+ memcpy(&sas_address, &sasEnclosurePg0->EnclosureLogicalID, sizeof(u64));
|
|
+ sas_address = reverse_byte_order64(sas_address);
|
|
+ if (sas_address)
|
|
+ memcpy(location_ident->bEnclosureIdentifier, &sas_address, sizeof(u64));
|
|
+ else
|
|
+ strcpy(location_ident->bEnclosureIdentifier,"Internal");
|
|
+
|
|
+// bBayPrefix - not supported
|
|
+
|
|
+// TODO - We need to look at sasEnclosurePg0-.Flags , to determine
|
|
+// whether SEP BUS/TargetID is valid. Ifs its a SES device, then
|
|
+// issue internal inquiry to (bus/id) to gather the Enclosure name.
|
|
+// If the device is SMP, then issue SMP_MANUFACTURING to get enclosure name
|
|
+// If its direct attached, there is no enclosure name
|
|
+ location_ident->bLocationFlags |= CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID;
|
|
+ strcpy(location_ident->bEnclosureName,"Not Supported");
|
|
+
|
|
+ location_ident->bLocationFlags |= CSMI_SAS_LOCATE_LOCATION_STATE_VALID;
|
|
+ location_ident->bLocationState = CSMI_SAS_LOCATE_UNKNOWN;
|
|
+
|
|
+ location_ident->bLocationFlags |= CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID;
|
|
+ location_ident->bBayIdentifier = le16_to_cpu(sasDevicePg0->Slot);
|
|
+
|
|
+
|
|
+// TODO - illuminating LEDs,
|
|
+// karg->bIdentify = CSMI_SAS_LOCATE_FORCE_OFF, CSMI_SAS_LOCATE_FORCE_ON
|
|
+// We can enable/disable LEDs by SCSI Enclosure Processor MPI request message
|
|
+// printk("Flags=0x%x\n",sasEnclosurePg0->Flags);
|
|
+
|
|
+/* check sasEnclosurePg0->Flags -
|
|
+ * to validate whether we need to send the SEPRequest
|
|
+ * bit:5 should be set
|
|
+ * bit:3-0 any bit should be set. If zero, then SEPRequest will fail
|
|
+*/
|
|
+
|
|
+/* MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR
|
|
+ * Look in mpi_init.h
|
|
+ * SEPRequest_t = structure
|
|
+ *
|
|
+ * SEPRequest_t->Action should be set to MPI_SEP_REQ_ACTION_WRITE_STATUS
|
|
+ *
|
|
+ * SEPRequest_t->Flags should be set to
|
|
+ * MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS, to pass along enclosure/slot ids
|
|
+ *
|
|
+ * SEPRequest_t->SlotStatus |= MPI_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST - this
|
|
+ * will illuminate the LEDs
|
|
+ */
|
|
+
|
|
+fill_location_data_exit:
|
|
+
|
|
+ if (sasDevicePg0 != NULL)
|
|
+ pci_free_consistent(ioc->pcidev, sasDevicePg0_data_sz,
|
|
+ sasDevicePg0, sasDevicePg0_dma);
|
|
+
|
|
+ if (sasEnclosurePg0 != NULL)
|
|
+ pci_free_consistent(ioc->pcidev, sasEnclosurePg0_data_sz,
|
|
+ sasEnclosurePg0, sasEnclosurePg0_dma);
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+static int
|
|
+csmisas_fill_location_data_raid(MPT_ADAPTER *ioc, PCSMI_SAS_GET_LOCATION_BUFFER karg, u8 VolumeBus,
|
|
+ u8 volumeID)
|
|
+{
|
|
+ pRaidVolumePage0_t pVolume0 = NULL;
|
|
+ pRaidPhysDiskPage0_t pPhysDisk0 = NULL;
|
|
+ CONFIGPARMS cfg;
|
|
+ ConfigPageHeader_t header;
|
|
+ u8 physDiskNumMax;
|
|
+ int volumepage0sz = 0, physdiskpage0sz = 0;
|
|
+ dma_addr_t volume0_dma, physdisk0_dma;
|
|
+ int csmi_sas_get_location_sz;
|
|
+ int rc = 0, i, idx;
|
|
+ int num_hotpares;
|
|
+ u64 totalMaxLBA, tmpTotalMaxLBA;
|
|
+ IOCPage5_t *iocPage5 = NULL;
|
|
+ u32 device_info = 0;
|
|
+ struct sas_device_info *sas_info;
|
|
+ int sz;
|
|
+
|
|
+ csmi_sas_get_location_sz = karg->IoctlHeader.Length;
|
|
+ physDiskNumMax = (csmi_sas_get_location_sz -
|
|
+ offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location))
|
|
+ / sizeof(CSMI_SAS_LOCATION_IDENTIFIER);
|
|
+ karg->bNumberOfLocationIdentifiers=0;
|
|
+
|
|
+ /*
|
|
+ * get RAID Volume Page 0
|
|
+ */
|
|
+
|
|
+ header.PageVersion = 0;
|
|
+ header.PageLength = 0;
|
|
+ header.PageNumber = 0;
|
|
+ header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
|
|
+ cfg.cfghdr.hdr = &header;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.pageAddr = (VolumeBus << 8) + volumeID;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0;
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+ if (mpt_config(ioc, &cfg) != 0) {
|
|
+ rc = -1;
|
|
+ goto sas_fill_location_data_raid_exit;
|
|
+ }
|
|
+
|
|
+ if (header.PageLength == 0) {
|
|
+ rc = -1;
|
|
+ goto sas_fill_location_data_raid_exit;
|
|
+ }
|
|
+
|
|
+ volumepage0sz = header.PageLength * 4;
|
|
+ pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz,
|
|
+ &volume0_dma);
|
|
+ if (!pVolume0) {
|
|
+ rc = -1;
|
|
+ goto sas_fill_location_data_raid_exit;
|
|
+ }
|
|
+
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+ cfg.physAddr = volume0_dma;
|
|
+ if (mpt_config(ioc, &cfg) != 0){
|
|
+ rc = -1;
|
|
+ goto sas_fill_location_data_raid_exit;
|
|
+ }
|
|
+
|
|
+ totalMaxLBA = (u64)le32_to_cpu(pVolume0->MaxLBA) |
|
|
+ ((u64)le32_to_cpu(pVolume0->MaxLBAHigh)) << 32;
|
|
+
|
|
+ /*
|
|
+ * get RAID Physical Disk Page 0
|
|
+ */
|
|
+ header.PageVersion = 0;
|
|
+ header.PageLength = 0;
|
|
+ header.PageNumber = 0;
|
|
+ header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
|
|
+ cfg.cfghdr.hdr = &header;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.pageAddr = 0;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0;
|
|
+ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
+ if (mpt_config(ioc, &cfg) != 0) {
|
|
+ rc = -1;
|
|
+ goto sas_fill_location_data_raid_exit;
|
|
+ }
|
|
+
|
|
+ if (header.PageLength == 0) {
|
|
+ rc = -1;
|
|
+ goto sas_fill_location_data_raid_exit;
|
|
+ }
|
|
+
|
|
+ physdiskpage0sz = header.PageLength * 4;
|
|
+ pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz,
|
|
+ &physdisk0_dma);
|
|
+ if (!pPhysDisk0) {
|
|
+ rc = -1;
|
|
+ goto sas_fill_location_data_raid_exit;
|
|
+ }
|
|
+ cfg.physAddr = physdisk0_dma;
|
|
+
|
|
+ for (i=0; i < min(pVolume0->NumPhysDisks, physDiskNumMax); i++) {
|
|
+
|
|
+ /* obtain a refresh of pPhysDisk0 */
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+ cfg.pageAddr = pVolume0->PhysDisk[i].PhysDiskNum;
|
|
+ if (mpt_config(ioc, &cfg) != 0){
|
|
+ rc = -1;
|
|
+ goto sas_fill_location_data_raid_exit;
|
|
+ }
|
|
+
|
|
+ if((csmisas_fill_location_data(ioc, pPhysDisk0->PhysDiskBus,
|
|
+ pPhysDisk0->PhysDiskID, karg->bIdentify,
|
|
+ &karg->Location[karg->bNumberOfLocationIdentifiers])) == 0)
|
|
+ karg->bNumberOfLocationIdentifiers++;
|
|
+
|
|
+ if (device_info)
|
|
+ continue;
|
|
+ sas_info = csmisas_get_device_component_by_fw(ioc,
|
|
+ pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID);
|
|
+ if (!sas_info || sas_info->is_cached)
|
|
+ continue;
|
|
+ device_info = sas_info->device_info;
|
|
+ }
|
|
+
|
|
+ if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS)
|
|
+ goto sas_fill_location_data_raid_exit;
|
|
+
|
|
+ /*
|
|
+ * hot spare support
|
|
+ *
|
|
+ */
|
|
+
|
|
+ num_hotpares = csmisas_get_number_hotspares(ioc);
|
|
+
|
|
+ if (num_hotpares) {
|
|
+
|
|
+ sz = offsetof(IOCPage5_t, HotSpare) +
|
|
+ num_hotpares * sizeof(IOC_5_HOT_SPARE);
|
|
+ iocPage5 = kmalloc(sz, GFP_KERNEL);
|
|
+
|
|
+ if (!iocPage5)
|
|
+ goto sas_fill_location_data_raid_exit;
|
|
+ memset(iocPage5, 0, sizeof(*iocPage5));
|
|
+
|
|
+ if (csmisas_get_ioc_pg5(ioc, iocPage5, sz) != 0)
|
|
+ goto sas_fill_location_data_raid_exit;
|
|
+
|
|
+ for(i = 0, idx = pVolume0->NumPhysDisks ; i < num_hotpares;
|
|
+ i++, idx++) {
|
|
+
|
|
+ if (idx >= physDiskNumMax)
|
|
+ break;
|
|
+
|
|
+ /* obtain a refresh of pPhysDisk0 */
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+ cfg.pageAddr = iocPage5->HotSpare[i].PhysDiskNum;
|
|
+ if (mpt_config(ioc, &cfg) != 0)
|
|
+ goto sas_fill_location_data_raid_exit;
|
|
+
|
|
+ /* Search the list for the matching SAS address. */
|
|
+ sas_info = csmisas_get_device_component_by_fw(ioc,
|
|
+ pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID);
|
|
+
|
|
+ if (!sas_info || sas_info->is_cached)
|
|
+ continue;
|
|
+
|
|
+ /* don't mix SSP hot spare
|
|
+ * in SATA volume
|
|
+ */
|
|
+ if (!csmisas_is_sata(pPhysDisk0) &&
|
|
+ (device_info &
|
|
+ MPI_SAS_DEVICE_INFO_SATA_DEVICE))
|
|
+ continue;
|
|
+
|
|
+ /* don't mix SATA hot spare
|
|
+ * in SSP volume
|
|
+ */
|
|
+ if (csmisas_is_sata(pPhysDisk0) &&
|
|
+ (device_info &
|
|
+ MPI_SAS_DEVICE_INFO_SSP_TARGET))
|
|
+ continue;
|
|
+
|
|
+ /* capacity check for IM volumes*/
|
|
+ if ((pVolume0->VolumeType ==
|
|
+ MPI_RAID_VOL_TYPE_IM) &&
|
|
+ (totalMaxLBA +
|
|
+ (64*2*1024) /* metadata = 64MB*/ >
|
|
+ le32_to_cpu(pPhysDisk0->MaxLBA)))
|
|
+ continue;
|
|
+
|
|
+ tmpTotalMaxLBA = totalMaxLBA;
|
|
+ do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks);
|
|
+ /* capacity check for IME volumes*/
|
|
+ if ((pVolume0->VolumeType ==
|
|
+ MPI_RAID_VOL_TYPE_IME) &&
|
|
+ ((tmpTotalMaxLBA * 2) +
|
|
+ (64*2*1024 ) /*metadata = 64MB*/ >
|
|
+ le32_to_cpu(pPhysDisk0->MaxLBA)))
|
|
+ continue;
|
|
+
|
|
+ if((csmisas_fill_location_data(ioc,
|
|
+ pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID,
|
|
+ karg->bIdentify,
|
|
+ &karg->Location[karg->bNumberOfLocationIdentifiers])) == 0)
|
|
+ karg->bNumberOfLocationIdentifiers++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+
|
|
+ sas_fill_location_data_raid_exit:
|
|
+
|
|
+ kfree(iocPage5);
|
|
+
|
|
+ if (pVolume0)
|
|
+ pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0,
|
|
+ volume0_dma);
|
|
+
|
|
+ if(pPhysDisk0)
|
|
+ pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0,
|
|
+ physdisk0_dma);
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Prototype Routine for the CSMI SAS Get location command.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -ENODEV if no such device/adapter
|
|
+ */
|
|
+static int
|
|
+csmisas_get_location(unsigned long arg)
|
|
+{
|
|
+ CSMI_SAS_GET_LOCATION_BUFFER __user *uarg = (void __user *) arg;
|
|
+ PCSMI_SAS_GET_LOCATION_BUFFER karg;
|
|
+ IOCTL_HEADER ioctl_header;
|
|
+ MPT_ADAPTER *ioc = NULL;
|
|
+ int iocnum,i;
|
|
+ int csmi_sas_get_location_sz;
|
|
+ int memory_pages;
|
|
+ struct sas_device_info *sas_info;
|
|
+
|
|
+ if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in IOCTL_HEADER"
|
|
+ "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ csmi_sas_get_location_sz = ioctl_header.Length;
|
|
+ memory_pages = get_order(csmi_sas_get_location_sz);
|
|
+ karg = (PCSMI_SAS_GET_LOCATION_BUFFER)__get_free_pages(
|
|
+ GFP_KERNEL, memory_pages);
|
|
+ if (!karg){
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to malloc GET_LOCATION_BUFFER "
|
|
+ "csmi_sas_get_location_sz=%d memory_pages=%d\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__,
|
|
+ csmi_sas_get_location_sz, memory_pages);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+ memset(karg, 0, sizeof(*karg));
|
|
+
|
|
+ if (copy_from_user(karg, uarg, csmi_sas_get_location_sz)) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to read in csmi_sas_phy_control_buffer "
|
|
+ "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber,
|
|
+ &ioc)) < 0) || (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (!csmisas_is_this_sas_cntr(ioc)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not SAS controller!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s enter.\n",__FUNCTION__));
|
|
+
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER;
|
|
+ if(karg->bLengthOfLocationIdentifier !=
|
|
+ sizeof(CSMI_SAS_LOCATION_IDENTIFIER))
|
|
+ goto cim_sas_get_location_exit;
|
|
+
|
|
+ sas_info = csmisas_get_device_component_by_os(ioc, karg->bPathId,
|
|
+ karg->bTargetId);
|
|
+ if (!sas_info)
|
|
+ goto cim_sas_get_location_exit;
|
|
+
|
|
+ /* RAID SUPPORT */
|
|
+ if (ioc->raid_data.pIocPg2 && sas_info->is_logical_volume) {
|
|
+ for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++){
|
|
+ if (sas_info->fw.id ==
|
|
+ ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID &&
|
|
+ sas_info->fw.channel ==
|
|
+ ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus) {
|
|
+ if(csmisas_fill_location_data_raid(ioc, karg,
|
|
+ ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus,
|
|
+ ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) == 0)
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_SUCCESS;
|
|
+ else
|
|
+ karg->IoctlHeader.ReturnCode =
|
|
+ CSMI_SAS_STATUS_FAILED;
|
|
+ goto cim_sas_get_location_exit;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* NON-RAID SUPPORT */
|
|
+ if (sas_info->is_cached || sas_info->is_logical_volume)
|
|
+ goto cim_sas_get_location_exit;
|
|
+
|
|
+ /* make sure there's enough room to populate the Location[] struct */
|
|
+ if ((csmi_sas_get_location_sz -
|
|
+ offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location)) <
|
|
+ sizeof(CSMI_SAS_LOCATION_IDENTIFIER))
|
|
+ goto cim_sas_get_location_exit;
|
|
+
|
|
+ karg->bNumberOfLocationIdentifiers=1;
|
|
+ karg->Location[0].bLocationFlags=0;
|
|
+ if((csmisas_fill_location_data(ioc, sas_info->fw.channel,
|
|
+ sas_info->fw.id, karg->bIdentify, &karg->Location[0])) == 0)
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS;
|
|
+ else
|
|
+ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED;
|
|
+
|
|
+ cim_sas_get_location_exit:
|
|
+
|
|
+ /* Copy the data from kernel memory to user memory
|
|
+ */
|
|
+ if (copy_to_user(uarg, karg, csmi_sas_get_location_sz)) {
|
|
+ printk(KERN_ERR "%s@%d::%s() - "
|
|
+ "Unable to write out csmi_sas_get_location_buffer "
|
|
+ "@ %p\n",__FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ dcsmisasprintk(ioc, printk(KERN_DEBUG "%s exit.\n",__FUNCTION__));
|
|
+ free_pages((unsigned long)karg, memory_pages);
|
|
+ return 0;
|
|
+}
|
|
--- /dev/null
|
|
+++ b/drivers/message/fusion/csmi/csmisas.h
|
|
@@ -0,0 +1,1854 @@
|
|
+/**************************************************************************
|
|
+
|
|
+Module Name:
|
|
+
|
|
+ CSMISAS.H
|
|
+
|
|
+
|
|
+Abstract:
|
|
+
|
|
+ This file contains constants and data structure definitions used by drivers
|
|
+ that support the Common Storage Management Interface specification for
|
|
+ SAS or SATA in either the Windows or Linux.
|
|
+
|
|
+ This should be considered as a reference implementation only. Changes may
|
|
+ be necessary to accommodate a specific build environment or target OS.
|
|
+
|
|
+Revision History:
|
|
+
|
|
+ 001 SEF 8/12/03 Initial release.
|
|
+ 002 SEF 8/20/03 Cleanup to match documentation.
|
|
+ 003 SEF 9/12/03 Additional cleanup, created combined header
|
|
+ 004 SEF 9/23/03 Changed base types to match linux defaults
|
|
+ Added RAID signature
|
|
+ Added bControllerFlags to CSMI_SAS_CNTLR_CONFIG
|
|
+ Changed CSMI_SAS_BEGIN_PACK to 8 for common structures
|
|
+ Fixed other typos identified in first compilation test
|
|
+ 005 SEF 10/03/03 Additions to match first version of CSMI document
|
|
+ 006 SEF 10/14/03 Fixed typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER
|
|
+ Added defines for bConnectionRate
|
|
+ 007 SEF 10/15/03 Added Firmware Download Control Code and support
|
|
+ Added CSMI revision support
|
|
+ 008 SEF 10/30/03 No functional change, just updated version to track
|
|
+ spec changes
|
|
+ 009 SEF 12/09/03 No functional change, just updated version to track
|
|
+ spec changes
|
|
+ 010 SEF 3/11/04 Fixed typedef struct CSMI_SAS_RAID_DRIVES to include the
|
|
+ bFirmware member that is defined in the spec, but
|
|
+ was missing in this file,
|
|
+ added CC_CSMI_SAS_TASK_MANAGEMENT
|
|
+ 011 SEF 4/02/04 No functional change, added comment line before
|
|
+ CC_CSMI_SAS_TASK_MANAGEMENT
|
|
+ 012 SEF 4/16/04 Added IOControllerNumber to linux header,
|
|
+ Modified linux control codes to have upper word of
|
|
+ 0xCC77.... to indicate CSMI version 77
|
|
+ Added bSignalClass to CC_CSMI_SET_PHY_INFO
|
|
+ Added CC_CSMI_SAS_PHY_CONTROL support
|
|
+ 013 SEF 5/14/04 Added CC_CSMI_SAS_GET_CONNECTOR_INFO support
|
|
+ 014 SEF 5/24/04 No functional change, just updated version to track spec
|
|
+ changes
|
|
+ 015 SEF 6/16/04 changed bPinout to uPinout to reflect proper size,
|
|
+ changed width of bLocation defines to reflect size
|
|
+ 016 SEF 6/17/04 changed bLengthOfControls in CSMI_SAS_PHY_CONTROL
|
|
+ to be proper size
|
|
+ 017 SEF 9/17/04 added CSMI_SAS_SATA_PORT_SELECTOR,
|
|
+ CSMI_SAS_LINK_VIRTUAL, CSMI_SAS_CON_NOT_PRESENT, and
|
|
+ CSMI_SAS_CON_NOT_CONNECTED
|
|
+ 018 SEF 9/20/04 added CSMI_SAS_PHY_USER_PATTERN,
|
|
+ changed definition of CSMI_SAS_PHY_FIXED_PATTERN to not
|
|
+ conflict with activate definition
|
|
+ 019 SEF 12/06/04 added CSMI_SAS_GET_LOCATION
|
|
+ added bSSPStatus to CSMI_SAS_SSP_PASSTHRU_STATUS
|
|
+ structure
|
|
+ 020 SEF 5/25/05 added CSMI_SAS_PHY_VIRTUAL_SMP, and changes to
|
|
+ CSMI_SAS_GET_LOCATION
|
|
+ 021 SEF 11/03/05 added new RAID creation functionality
|
|
+ 022 SEF 2/01/06 corrected typo bNegotitiatedLInkRate
|
|
+ Added two more RAID_TYPES, 7 and 8
|
|
+ 023 SEF 4/04/06 added CSMI_RAID_TYPE_1E
|
|
+ changed structures that contained surface scan
|
|
+ to priority approach rather than time, causes
|
|
+ 0.89 to incompatible with 0.87, so a version
|
|
+ check is necessary when interpreting the
|
|
+ raid structures
|
|
+ Added netware section
|
|
+ 024 DRG 5/22/06 Added uFailureCode to CSMI_SAS_RAID_CONFIG and
|
|
+ CSMI_SAS_RAID_FEATURES
|
|
+ Changed __u64 fields to high and low __u32 fields in
|
|
+ order to avoid backward compatibility issues with
|
|
+ packing and alignment.
|
|
+ Fixed alignment problem in CSMI_SAS_RAID_DRIVES.
|
|
+ Added CSMI_SAS_CNTLR_SMART_ARRAY to uControllerFlags
|
|
+ Reassigned the value of CSMI_SAS_CNTLR_RAID_CFG_SUPPORT
|
|
+ to avoid a conflict.
|
|
+
|
|
+**************************************************************************/
|
|
+
|
|
+#ifndef _CSMI_SAS_H_
|
|
+#define _CSMI_SAS_H_
|
|
+
|
|
+// CSMI Specification Revision, the intent is that all versions of the
|
|
+// specification will be backward compatible after the 1.00 release.
|
|
+// Major revision number, corresponds to xxxx. of CSMI specification
|
|
+// Minor revision number, corresponds to .xxxx of CSMI specification
|
|
+#define CSMI_MAJOR_REVISION 0
|
|
+#define CSMI_MINOR_REVISION 90
|
|
+
|
|
+/*************************************************************************/
|
|
+/* PATCHES FOR TYPOS */
|
|
+/*************************************************************************/
|
|
+
|
|
+#define bNegotitiatedLInkRate bNegotiatedLinkRate
|
|
+
|
|
+/*************************************************************************/
|
|
+/* TARGET OS LINUX SPECIFIC CODE */
|
|
+/*************************************************************************/
|
|
+
|
|
+// EDM #ifdef _linux
|
|
+#ifdef __KERNEL__
|
|
+
|
|
+// Linux base types
|
|
+
|
|
+#include <linux/types.h>
|
|
+
|
|
+#define __i8 char
|
|
+
|
|
+// pack definition
|
|
+
|
|
+// EDM #define CSMI_SAS_BEGIN_PACK(x) pack(x)
|
|
+// EDM #define CSMI_SAS_END_PACK pack()
|
|
+
|
|
+// IOCTL Control Codes
|
|
+// (IoctlHeader.ControlCode)
|
|
+
|
|
+// Control Codes prior to 0.77
|
|
+
|
|
+// Control Codes requiring CSMI_ALL_SIGNATURE
|
|
+
|
|
+// #define CC_CSMI_SAS_GET_DRIVER_INFO 0x12345678
|
|
+// #define CC_CSMI_SAS_GET_CNTLR_CONFIG 0x23456781
|
|
+// #define CC_CSMI_SAS_GET_CNTLR_STATUS 0x34567812
|
|
+// #define CC_CSMI_SAS_FIRMWARE_DOWNLOAD 0x92345678
|
|
+
|
|
+// Control Codes requiring CSMI_RAID_SIGNATURE
|
|
+
|
|
+// #define CC_CSMI_SAS_GET_RAID_INFO 0x45678123
|
|
+// #define CC_CSMI_SAS_GET_RAID_CONFIG 0x56781234
|
|
+
|
|
+// Control Codes requiring CSMI_SAS_SIGNATURE
|
|
+
|
|
+// #define CC_CSMI_SAS_GET_PHY_INFO 0x67812345
|
|
+// #define CC_CSMI_SAS_SET_PHY_INFO 0x78123456
|
|
+// #define CC_CSMI_SAS_GET_LINK_ERRORS 0x81234567
|
|
+// #define CC_CSMI_SAS_SMP_PASSTHRU 0xA1234567
|
|
+// #define CC_CSMI_SAS_SSP_PASSTHRU 0xB1234567
|
|
+// #define CC_CSMI_SAS_STP_PASSTHRU 0xC1234567
|
|
+// #define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xD1234567
|
|
+// #define CC_CSMI_SAS_GET_SCSI_ADDRESS 0xE1234567
|
|
+// #define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xF1234567
|
|
+// #define CC_CSMI_SAS_TASK_MANAGEMENT 0xA2345678
|
|
+
|
|
+// Control Codes for 0.77 and later
|
|
+
|
|
+// Control Codes requiring CSMI_ALL_SIGNATURE
|
|
+
|
|
+#define CC_CSMI_SAS_GET_DRIVER_INFO 0xCC770001
|
|
+#define CC_CSMI_SAS_GET_CNTLR_CONFIG 0xCC770002
|
|
+#define CC_CSMI_SAS_GET_CNTLR_STATUS 0xCC770003
|
|
+#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD 0xCC770004
|
|
+
|
|
+// Control Codes requiring CSMI_RAID_SIGNATURE
|
|
+
|
|
+#define CC_CSMI_SAS_GET_RAID_INFO 0xCC77000A
|
|
+#define CC_CSMI_SAS_GET_RAID_CONFIG 0xCC77000B
|
|
+#define CC_CSMI_SAS_GET_RAID_FEATURES 0xCC77000C
|
|
+#define CC_CSMI_SAS_SET_RAID_CONTROL 0xCC77000D
|
|
+#define CC_CSMI_SAS_GET_RAID_ELEMENT 0xCC77000E
|
|
+#define CC_CSMI_SAS_SET_RAID_OPERATION 0xCC77000F
|
|
+
|
|
+// Control Codes requiring CSMI_SAS_SIGNATURE
|
|
+
|
|
+#define CC_CSMI_SAS_GET_PHY_INFO 0xCC770014
|
|
+#define CC_CSMI_SAS_SET_PHY_INFO 0xCC770015
|
|
+#define CC_CSMI_SAS_GET_LINK_ERRORS 0xCC770016
|
|
+#define CC_CSMI_SAS_SMP_PASSTHRU 0xCC770017
|
|
+#define CC_CSMI_SAS_SSP_PASSTHRU 0xCC770018
|
|
+#define CC_CSMI_SAS_STP_PASSTHRU 0xCC770019
|
|
+#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xCC770020
|
|
+#define CC_CSMI_SAS_GET_SCSI_ADDRESS 0xCC770021
|
|
+#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xCC770022
|
|
+#define CC_CSMI_SAS_TASK_MANAGEMENT 0xCC770023
|
|
+#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0xCC770024
|
|
+#define CC_CSMI_SAS_GET_LOCATION 0xCC770025
|
|
+
|
|
+
|
|
+// Control Codes requiring CSMI_PHY_SIGNATURE
|
|
+
|
|
+#define CC_CSMI_SAS_PHY_CONTROL 0xCC77003C
|
|
+
|
|
+// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
|
|
+#pragma pack(8)
|
|
+
|
|
+// IOCTL_HEADER
|
|
+typedef struct _IOCTL_HEADER {
|
|
+ __u32 IOControllerNumber;
|
|
+ __u32 Length;
|
|
+ __u32 ReturnCode;
|
|
+ __u32 Timeout;
|
|
+ __u16 Direction;
|
|
+} IOCTL_HEADER,
|
|
+ *PIOCTL_HEADER;
|
|
+
|
|
+// EDM #pragma CSMI_SAS_END_PACK
|
|
+#pragma pack()
|
|
+
|
|
+#endif
|
|
+
|
|
+/*************************************************************************/
|
|
+/* TARGET OS WINDOWS SPECIFIC CODE */
|
|
+/*************************************************************************/
|
|
+
|
|
+#ifdef _WIN32
|
|
+
|
|
+// windows IOCTL definitions
|
|
+
|
|
+#ifndef _NTDDSCSIH_
|
|
+#include <ntddscsi.h>
|
|
+#endif
|
|
+
|
|
+// pack definition
|
|
+
|
|
+#if defined _MSC_VER
|
|
+ #define CSMI_SAS_BEGIN_PACK(x) pack(push,x)
|
|
+ #define CSMI_SAS_END_PACK pack(pop)
|
|
+#elif defined __BORLANDC__
|
|
+ #define CSMI_SAS_BEGIN_PACK(x) option -a##x
|
|
+ #define CSMI_SAS_END_PACK option -a.
|
|
+#else
|
|
+ #error "CSMISAS.H - Must externally define a pack compiler designator."
|
|
+#endif
|
|
+
|
|
+// base types
|
|
+
|
|
+#define __u8 unsigned char
|
|
+#define __u16 unsigned short
|
|
+#define __u32 unsigned long
|
|
+#define __u64 unsigned __int64
|
|
+
|
|
+#define __i8 char
|
|
+
|
|
+// IOCTL Control Codes
|
|
+// (IoctlHeader.ControlCode)
|
|
+
|
|
+// Control Codes requiring CSMI_ALL_SIGNATURE
|
|
+
|
|
+#define CC_CSMI_SAS_GET_DRIVER_INFO 1
|
|
+#define CC_CSMI_SAS_GET_CNTLR_CONFIG 2
|
|
+#define CC_CSMI_SAS_GET_CNTLR_STATUS 3
|
|
+#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD 4
|
|
+
|
|
+// Control Codes requiring CSMI_RAID_SIGNATURE
|
|
+
|
|
+#define CC_CSMI_SAS_GET_RAID_INFO 10
|
|
+#define CC_CSMI_SAS_GET_RAID_CONFIG 11
|
|
+#define CC_CSMI_SAS_GET_RAID_FEATURES 12
|
|
+#define CC_CSMI_SAS_SET_RAID_CONTROL 13
|
|
+#define CC_CSMI_SAS_GET_RAID_ELEMENT 14
|
|
+#define CC_CSMI_SAS_SET_RAID_OPERATION 15
|
|
+
|
|
+// Control Codes requiring CSMI_SAS_SIGNATURE
|
|
+
|
|
+#define CC_CSMI_SAS_GET_PHY_INFO 20
|
|
+#define CC_CSMI_SAS_SET_PHY_INFO 21
|
|
+#define CC_CSMI_SAS_GET_LINK_ERRORS 22
|
|
+#define CC_CSMI_SAS_SMP_PASSTHRU 23
|
|
+#define CC_CSMI_SAS_SSP_PASSTHRU 24
|
|
+#define CC_CSMI_SAS_STP_PASSTHRU 25
|
|
+#define CC_CSMI_SAS_GET_SATA_SIGNATURE 26
|
|
+#define CC_CSMI_SAS_GET_SCSI_ADDRESS 27
|
|
+#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 28
|
|
+#define CC_CSMI_SAS_TASK_MANAGEMENT 29
|
|
+#define CC_CSMI_SAS_GET_CONNECTOR_INFO 30
|
|
+#define CC_CSMI_SAS_GET_LOCATION 31
|
|
+
|
|
+// Control Codes requiring CSMI_PHY_SIGNATURE
|
|
+
|
|
+#define CC_CSMI_SAS_PHY_CONTROL 60
|
|
+
|
|
+#define IOCTL_HEADER SRB_IO_CONTROL
|
|
+#define PIOCTL_HEADER PSRB_IO_CONTROL
|
|
+
|
|
+#endif
|
|
+
|
|
+/*************************************************************************/
|
|
+/* TARGET OS NETWARE SPECIFIC CODE */
|
|
+/*************************************************************************/
|
|
+
|
|
+#ifdef _NETWARE
|
|
+
|
|
+// NetWare IOCTL definitions
|
|
+
|
|
+#define CSMI_SAS_BEGIN_PACK(x) pack(x)
|
|
+#define CSMI_SAS_END_PACK pack()
|
|
+
|
|
+#ifndef LONG
|
|
+typedef unsigned long LONG;
|
|
+#endif
|
|
+
|
|
+#ifndef WORD
|
|
+typedef unsigned short WORD;
|
|
+#endif
|
|
+
|
|
+#ifndef BYTE
|
|
+typedef unsigned char BYTE;
|
|
+#endif
|
|
+
|
|
+/* Need to have these definitions for Netware */
|
|
+#define __u8 unsigned char
|
|
+#define __u16 unsigned short
|
|
+#define __u32 unsigned long
|
|
+#define __u64 unsigned __int64
|
|
+
|
|
+#define __i8 char
|
|
+
|
|
+
|
|
+// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
|
|
+#pragma pack(8)
|
|
+
|
|
+// IOCTL_HEADER
|
|
+typedef struct _IOCTL_HEADER {
|
|
+ __u32 Length;
|
|
+ __u32 ReturnCode;
|
|
+} IOCTL_HEADER,
|
|
+ *PIOCTL_HEADER;
|
|
+
|
|
+// EDM #pragma CSMI_SAS_END_PACK
|
|
+#pragma pack()
|
|
+
|
|
+// IOCTL Control Codes
|
|
+// (IoctlHeader.ControlCode)
|
|
+
|
|
+// Control Codes requiring CSMI_ALL_SIGNATURE
|
|
+
|
|
+#define CC_CSMI_SAS_GET_DRIVER_INFO 0x01FF0001
|
|
+#define CC_CSMI_SAS_GET_CNTLR_CONFIG 0x01FF0002
|
|
+#define CC_CSMI_SAS_GET_CNTLR_STATUS 0x01FF0003
|
|
+#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD 0x01FF0004
|
|
+
|
|
+// Control Codes requiring CSMI_RAID_SIGNATURE
|
|
+
|
|
+#define CC_CSMI_SAS_GET_RAID_INFO 0x01FF000A
|
|
+#define CC_CSMI_SAS_GET_RAID_CONFIG 0x01FF000B
|
|
+#define CC_CSMI_SAS_GET_RAID_FEATURES 0x01FF000C
|
|
+#define CC_CSMI_SAS_SET_RAID_CONTROL 0x01FF000D
|
|
+#define CC_CSMI_SAS_GET_RAID_ELEMENT 0x01FF000E
|
|
+#define CC_CSMI_SAS_SET_RAID_OPERATION 0x01FF000F
|
|
+
|
|
+// Control Codes requiring CSMI_SAS_SIGNATURE
|
|
+
|
|
+#define CC_CSMI_SAS_GET_PHY_INFO 0x01FF0014
|
|
+#define CC_CSMI_SAS_SET_PHY_INFO 0x01FF0015
|
|
+#define CC_CSMI_SAS_GET_LINK_ERRORS 0x01FF0016
|
|
+#define CC_CSMI_SAS_SMP_PASSTHRU 0x01FF0017
|
|
+#define CC_CSMI_SAS_SSP_PASSTHRU 0x01FF0018
|
|
+#define CC_CSMI_SAS_STP_PASSTHRU 0x01FF0019
|
|
+#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0x01FF001A
|
|
+#define CC_CSMI_SAS_GET_SCSI_ADDRESS 0x01FF001B
|
|
+#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0x01FF001C
|
|
+#define CC_CSMI_SAS_TASK_MANAGEMENT 0x01FF001D
|
|
+#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0x01FF001E
|
|
+#define CC_CSMI_SAS_GET_LOCATION 0x01FF001F
|
|
+
|
|
+// Control Codes requiring CSMI_PHY_SIGNATURE
|
|
+
|
|
+#define CC_CSMI_SAS_PHY_CONTROL 60
|
|
+
|
|
+#endif
|
|
+
|
|
+/*************************************************************************/
|
|
+/* TARGET OS NOT DEFINED ERROR */
|
|
+/*************************************************************************/
|
|
+
|
|
+// EDM
|
|
+//#if (!_WIN32 && !_linux && !_NETWARE)
|
|
+// #error "Unknown target OS."
|
|
+//#endif
|
|
+
|
|
+/*************************************************************************/
|
|
+/* OS INDEPENDENT CODE */
|
|
+/*************************************************************************/
|
|
+
|
|
+/* * * * * * * * * * Class Independent IOCTL Constants * * * * * * * * * */
|
|
+
|
|
+// Return codes for all IOCTL's regardless of class
|
|
+// (IoctlHeader.ReturnCode)
|
|
+
|
|
+#define CSMI_SAS_STATUS_SUCCESS 0
|
|
+#define CSMI_SAS_STATUS_FAILED 1
|
|
+#define CSMI_SAS_STATUS_BAD_CNTL_CODE 2
|
|
+#define CSMI_SAS_STATUS_INVALID_PARAMETER 3
|
|
+#define CSMI_SAS_STATUS_WRITE_ATTEMPTED 4
|
|
+
|
|
+// Signature value
|
|
+// (IoctlHeader.Signature)
|
|
+
|
|
+#define CSMI_ALL_SIGNATURE "CSMIALL"
|
|
+
|
|
+// Timeout value default of 60 seconds
|
|
+// (IoctlHeader.Timeout)
|
|
+
|
|
+#define CSMI_ALL_TIMEOUT 60
|
|
+
|
|
+// Direction values for data flow on this IOCTL
|
|
+// (IoctlHeader.Direction, Linux only)
|
|
+#define CSMI_SAS_DATA_READ 0
|
|
+#define CSMI_SAS_DATA_WRITE 1
|
|
+
|
|
+// I/O Bus Types
|
|
+// ISA and EISA bus types are not supported
|
|
+// (bIoBusType)
|
|
+
|
|
+#define CSMI_SAS_BUS_TYPE_PCI 3
|
|
+#define CSMI_SAS_BUS_TYPE_PCMCIA 4
|
|
+
|
|
+// Controller Status
|
|
+// (uStatus)
|
|
+
|
|
+#define CSMI_SAS_CNTLR_STATUS_GOOD 1
|
|
+#define CSMI_SAS_CNTLR_STATUS_FAILED 2
|
|
+#define CSMI_SAS_CNTLR_STATUS_OFFLINE 3
|
|
+#define CSMI_SAS_CNTLR_STATUS_POWEROFF 4
|
|
+
|
|
+// Offline Status Reason
|
|
+// (uOfflineReason)
|
|
+
|
|
+#define CSMI_SAS_OFFLINE_REASON_NO_REASON 0
|
|
+#define CSMI_SAS_OFFLINE_REASON_INITIALIZING 1
|
|
+#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_DEGRADED 2
|
|
+#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_FAILURE 3
|
|
+
|
|
+// Controller Class
|
|
+// (bControllerClass)
|
|
+
|
|
+#define CSMI_SAS_CNTLR_CLASS_HBA 5
|
|
+
|
|
+// Controller Flag bits
|
|
+// (uControllerFlags)
|
|
+
|
|
+#define CSMI_SAS_CNTLR_SAS_HBA 0x00000001
|
|
+#define CSMI_SAS_CNTLR_SAS_RAID 0x00000002
|
|
+#define CSMI_SAS_CNTLR_SATA_HBA 0x00000004
|
|
+#define CSMI_SAS_CNTLR_SATA_RAID 0x00000008
|
|
+#define CSMI_SAS_CNTLR_SMART_ARRAY 0x00000010
|
|
+
|
|
+// for firmware download
|
|
+#define CSMI_SAS_CNTLR_FWD_SUPPORT 0x00010000
|
|
+#define CSMI_SAS_CNTLR_FWD_ONLINE 0x00020000
|
|
+#define CSMI_SAS_CNTLR_FWD_SRESET 0x00040000
|
|
+#define CSMI_SAS_CNTLR_FWD_HRESET 0x00080000
|
|
+#define CSMI_SAS_CNTLR_FWD_RROM 0x00100000
|
|
+
|
|
+// for RAID configuration supported
|
|
+#define CSMI_SAS_CNTLR_RAID_CFG_SUPPORT 0x01000000
|
|
+
|
|
+// Download Flag bits
|
|
+// (uDownloadFlags)
|
|
+#define CSMI_SAS_FWD_VALIDATE 0x00000001
|
|
+#define CSMI_SAS_FWD_SOFT_RESET 0x00000002
|
|
+#define CSMI_SAS_FWD_HARD_RESET 0x00000004
|
|
+
|
|
+// Firmware Download Status
|
|
+// (usStatus)
|
|
+#define CSMI_SAS_FWD_SUCCESS 0
|
|
+#define CSMI_SAS_FWD_FAILED 1
|
|
+#define CSMI_SAS_FWD_USING_RROM 2
|
|
+#define CSMI_SAS_FWD_REJECT 3
|
|
+#define CSMI_SAS_FWD_DOWNREV 4
|
|
+
|
|
+// Firmware Download Severity
|
|
+// (usSeverity>
|
|
+#define CSMI_SAS_FWD_INFORMATION 0
|
|
+#define CSMI_SAS_FWD_WARNING 1
|
|
+#define CSMI_SAS_FWD_ERROR 2
|
|
+#define CSMI_SAS_FWD_FATAL 3
|
|
+
|
|
+/* * * * * * * * * * SAS RAID Class IOCTL Constants * * * * * * * * */
|
|
+
|
|
+// Return codes for the RAID IOCTL's regardless of class
|
|
+// (IoctlHeader.ReturnCode)
|
|
+
|
|
+#define CSMI_SAS_RAID_SET_OUT_OF_RANGE 1000
|
|
+#define CSMI_SAS_RAID_SET_BUFFER_TOO_SMALL 1001
|
|
+#define CSMI_SAS_RAID_SET_DATA_CHANGED 1002
|
|
+
|
|
+// Signature value
|
|
+// (IoctlHeader.Signature)
|
|
+
|
|
+#define CSMI_RAID_SIGNATURE "CSMIARY"
|
|
+
|
|
+// Timeout value default of 60 seconds
|
|
+// (IoctlHeader.Timeout)
|
|
+
|
|
+#define CSMI_RAID_TIMEOUT 60
|
|
+
|
|
+// RAID Types
|
|
+// (bRaidType)
|
|
+#define CSMI_SAS_RAID_TYPE_NONE 0
|
|
+#define CSMI_SAS_RAID_TYPE_0 1
|
|
+#define CSMI_SAS_RAID_TYPE_1 2
|
|
+#define CSMI_SAS_RAID_TYPE_10 3
|
|
+#define CSMI_SAS_RAID_TYPE_5 4
|
|
+#define CSMI_SAS_RAID_TYPE_15 5
|
|
+#define CSMI_SAS_RAID_TYPE_6 6
|
|
+#define CSMI_SAS_RAID_TYPE_50 7
|
|
+#define CSMI_SAS_RAID_TYPE_VOLUME 8
|
|
+#define CSMI_SAS_RAID_TYPE_1E 9
|
|
+#define CSMI_SAS_RAID_TYPE_OTHER 255
|
|
+// the last value 255 was already defined for other
|
|
+// so end is defined as 254
|
|
+#define CSMI_SAS_RAID_TYPE_END 254
|
|
+
|
|
+// RAID Status
|
|
+// (bStatus)
|
|
+#define CSMI_SAS_RAID_SET_STATUS_OK 0
|
|
+#define CSMI_SAS_RAID_SET_STATUS_DEGRADED 1
|
|
+#define CSMI_SAS_RAID_SET_STATUS_REBUILDING 2
|
|
+#define CSMI_SAS_RAID_SET_STATUS_FAILED 3
|
|
+#define CSMI_SAS_RAID_SET_STATUS_OFFLINE 4
|
|
+#define CSMI_SAS_RAID_SET_STATUS_TRANSFORMING 5
|
|
+#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_REBUILD 6
|
|
+#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_TRANSFORMATION 7
|
|
+
|
|
+// RAID Drive Count
|
|
+// (bDriveCount, 0xF1 to 0xFF are reserved)
|
|
+#define CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG 0xF1
|
|
+#define CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED 0xF2
|
|
+
|
|
+// RAID Data Type
|
|
+// (bDataType)
|
|
+#define CSMI_SAS_RAID_DATA_DRIVES 0
|
|
+#define CSMI_SAS_RAID_DATA_DEVICE_ID 1
|
|
+#define CSMI_SAS_RAID_DATA_ADDITIONAL_DATA 2
|
|
+
|
|
+// RAID Drive Status
|
|
+// (bDriveStatus)
|
|
+#define CSMI_SAS_DRIVE_STATUS_OK 0
|
|
+#define CSMI_SAS_DRIVE_STATUS_REBUILDING 1
|
|
+#define CSMI_SAS_DRIVE_STATUS_FAILED 2
|
|
+#define CSMI_SAS_DRIVE_STATUS_DEGRADED 3
|
|
+#define CSMI_SAS_DRIVE_STATUS_OFFLINE 4
|
|
+#define CSMI_SAS_DRIVE_STATUS_QUEUED_FOR_REBUILD 5
|
|
+
|
|
+// RAID Drive Usage
|
|
+// (bDriveUsage)
|
|
+#define CSMI_SAS_DRIVE_CONFIG_NOT_USED 0
|
|
+#define CSMI_SAS_DRIVE_CONFIG_MEMBER 1
|
|
+#define CSMI_SAS_DRIVE_CONFIG_SPARE 2
|
|
+#define CSMI_SAS_DRIVE_CONFIG_SPARE_ACTIVE 3
|
|
+
|
|
+// RAID Drive Type
|
|
+// (bDriveType)
|
|
+#define CSMI_SAS_DRIVE_TYPE_UNKNOWN 0
|
|
+#define CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS 1
|
|
+#define CSMI_SAS_DRIVE_TYPE_DUAL_PORT_SAS 2
|
|
+#define CSMI_SAS_DRIVE_TYPE_SATA 3
|
|
+#define CSMI_SAS_DRIVE_TYPE_SATA_PS 4
|
|
+#define CSMI_SAS_DRIVE_TYPE_OTHER 255
|
|
+
|
|
+// RAID Write Protect
|
|
+// (bWriteProtect)
|
|
+#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN 0
|
|
+#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNCHANGED 0
|
|
+#define CSMI_SAS_RAID_SET_WRITE_PROTECT_ENABLED 1
|
|
+#define CSMI_SAS_RAID_SET_WRITE_PROTECT_DISABLED 2
|
|
+
|
|
+// RAID Cache Setting
|
|
+// (bCacheSetting)
|
|
+#define CSMI_SAS_RAID_SET_CACHE_UNKNOWN 0
|
|
+#define CSMI_SAS_RAID_SET_CACHE_UNCHANGED 0
|
|
+#define CSMI_SAS_RAID_SET_CACHE_ENABLED 1
|
|
+#define CSMI_SAS_RAID_SET_CACHE_DISABLED 2
|
|
+#define CSMI_SAS_RAID_SET_CACHE_CORRUPT 3
|
|
+
|
|
+// RAID Features
|
|
+// (uFeatures)
|
|
+#define CSMI_SAS_RAID_FEATURE_TRANSFORMATION 0x00000001
|
|
+#define CSMI_SAS_RAID_FEATURE_REBUILD 0x00000002
|
|
+#define CSMI_SAS_RAID_FEATURE_SPLIT_MIRROR 0x00000004
|
|
+#define CSMI_SAS_RAID_FEATURE_MERGE_MIRROR 0x00000008
|
|
+#define CSMI_SAS_RAID_FEATURE_LUN_RENUMBER 0x00000010
|
|
+#define CSMI_SAS_RAID_FEATURE_SURFACE_SCAN 0x00000020
|
|
+#define CSMI_SAS_RAID_FEATURE_SPARES_SHARED 0x00000040
|
|
+
|
|
+// RAID Priority
|
|
+// (bDefaultTransformPriority, etc.)
|
|
+#define CSMI_SAS_PRIORITY_UNKNOWN 0
|
|
+#define CSMI_SAS_PRIORITY_UNCHANGED 0
|
|
+#define CSMI_SAS_PRIORITY_AUTO 1
|
|
+#define CSMI_SAS_PRIORITY_OFF 2
|
|
+#define CSMI_SAS_PRIORITY_LOW 3
|
|
+#define CSMI_SAS_PRIORITY_MEDIUM 4
|
|
+#define CSMI_SAS_PRIORITY_HIGH 5
|
|
+
|
|
+// RAID Transformation Rules
|
|
+// (uRaidSetTransformationRules)
|
|
+#define CSMI_SAS_RAID_RULE_AVAILABLE_MEMORY 0x00000001
|
|
+#define CSMI_SAS_RAID_RULE_OVERLAPPED_EXTENTS 0x00000002
|
|
+
|
|
+// RAID Cache Ratios Supported
|
|
+// (bCacheRatiosSupported)
|
|
+// from 0 to 100 defines the write to read ratio, 0 is 100% write
|
|
+#define CSMI_SAS_RAID_CACHE_RATIO_RANGE 101
|
|
+#define CSMI_SAS_RAID_CACHE_RATIO_FIXED 102
|
|
+#define CSMI_SAS_RAID_CACHE_RATIO_AUTO 103
|
|
+#define CSMI_SAS_RAID_CACHE_RATIO_END 255
|
|
+
|
|
+// RAID Cache Ratio Flag
|
|
+// (bCacheRatioFlag)
|
|
+#define CSMI_SAS_RAID_CACHE_RATIO_DISABLE 0
|
|
+#define CSMI_SAS_RAID_CACHE_RATIO_ENABLE 1
|
|
+
|
|
+// RAID Clear Configuration Signature
|
|
+// (bClearConfiguration)
|
|
+#define CSMI_SAS_RAID_CLEAR_CONFIGURATION_SIGNATURE "RAIDCLR"
|
|
+
|
|
+// RAID Failure Codes
|
|
+// (uFailureCode)
|
|
+#define CSMI_SAS_FAIL_CODE_OK 0
|
|
+#define CSMI_SAS_FAIL_CODE_PARAMETER_INVALID 1000
|
|
+#define CSMI_SAS_FAIL_CODE_TRANSFORM_PRIORITY_INVALID 1001
|
|
+#define CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID 1002
|
|
+#define CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID 1003
|
|
+#define CSMI_SAS_FAIL_CODE_SURFACE_SCAN_INVALID 1004
|
|
+#define CSMI_SAS_FAIL_CODE_CLEAR_CONFIGURATION_INVALID 1005
|
|
+#define CSMI_SAS_FAIL_CODE_ELEMENT_INDEX_INVALID 1006
|
|
+#define CSMI_SAS_FAIL_CODE_SUBELEMENT_INDEX_INVALID 1007
|
|
+#define CSMI_SAS_FAIL_CODE_EXTENT_INVALID 1008
|
|
+#define CSMI_SAS_FAIL_CODE_BLOCK_COUNT_INVALID 1009
|
|
+#define CSMI_SAS_FAIL_CODE_DRIVE_INDEX_INVALID 1010
|
|
+#define CSMI_SAS_FAIL_CODE_EXISTING_LUN_INVALID 1011
|
|
+#define CSMI_SAS_FAIL_CODE_RAID_TYPE_INVALID 1012
|
|
+#define CSMI_SAS_FAIL_CODE_STRIPE_SIZE_INVALID 1013
|
|
+#define CSMI_SAS_FAIL_CODE_TRANSFORMATION_INVALID 1014
|
|
+#define CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID 1015
|
|
+#define CSMI_SAS_FAIL_CODE_ENUMERATION_TYPE_INVALID 1016
|
|
+
|
|
+#define CSMI_SAS_FAIL_CODE_EXCEEDED_RAID_SET_COUNT 2000
|
|
+#define CSMI_SAS_FAIL_CODE_DUPLICATE_LUN 2001
|
|
+
|
|
+#define CSMI_SAS_FAIL_CODE_WAIT_FOR_OPERATION 3000
|
|
+
|
|
+// RAID Enumeration Types
|
|
+// (uEnumerationType)
|
|
+#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE 0
|
|
+#define CSMI_SAS_RAID_ELEMENT_TYPE_MODULE 1
|
|
+#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE_RAID_SET 2
|
|
+#define CSMI_SAS_RAID_ELEMENT_TYPE_EXTENT_DRIVE 3
|
|
+
|
|
+// RAID Extent Types
|
|
+// (bExtentType)
|
|
+#define CSMI_SAS_RAID_EXTENT_RESERVED 0
|
|
+#define CSMI_SAS_RAID_EXTENT_METADATA 1
|
|
+#define CSMI_SAS_RAID_EXTENT_ALLOCATED 2
|
|
+#define CSMI_SAS_RAID_EXTENT_UNALLOCATED 3
|
|
+
|
|
+// RAID Operation Types
|
|
+// (uOperationType)
|
|
+#define CSMI_SAS_RAID_SET_CREATE 0
|
|
+#define CSMI_SAS_RAID_SET_LABEL 1
|
|
+#define CSMI_SAS_RAID_SET_TRANSFORM 2
|
|
+#define CSMI_SAS_RAID_SET_DELETE 3
|
|
+#define CSMI_SAS_RAID_SET_WRITE_PROTECT 4
|
|
+#define CSMI_SAS_RAID_SET_CACHE 5
|
|
+#define CSMI_SAS_RAID_SET_ONLINE_STATE 6
|
|
+#define CSMI_SAS_RAID_SET_SPARE 7
|
|
+
|
|
+// RAID Transform Types
|
|
+// (bTransformType)
|
|
+#define CSMI_SAS_RAID_SET_TRANSFORM_SPLIT_MIRROR 0
|
|
+#define CSMI_SAS_RAID_SET_TRANSFORM_MERGE_RAID_0 1
|
|
+#define CSMI_SAS_RAID_SET_TRANSFORM_LUN_RENUMBER 2
|
|
+#define CSMI_SAS_RAID_SET_TRANSFORM_RAID_SET 3
|
|
+
|
|
+// RAID Online State
|
|
+// (bOnlineState)
|
|
+#define CSMI_SAS_RAID_SET_STATE_UNKNOWN 0
|
|
+#define CSMI_SAS_RAID_SET_STATE_ONLINE 1
|
|
+#define CSMI_SAS_RAID_SET_STATE_OFFLINE 2
|
|
+
|
|
+/* * * * * * * * * * SAS HBA Class IOCTL Constants * * * * * * * * * */
|
|
+
|
|
+// Return codes for SAS IOCTL's
|
|
+// (IoctlHeader.ReturnCode)
|
|
+
|
|
+#define CSMI_SAS_PHY_INFO_CHANGED CSMI_SAS_STATUS_SUCCESS
|
|
+#define CSMI_SAS_PHY_INFO_NOT_CHANGEABLE 2000
|
|
+#define CSMI_SAS_LINK_RATE_OUT_OF_RANGE 2001
|
|
+
|
|
+#define CSMI_SAS_PHY_DOES_NOT_EXIST 2002
|
|
+#define CSMI_SAS_PHY_DOES_NOT_MATCH_PORT 2003
|
|
+#define CSMI_SAS_PHY_CANNOT_BE_SELECTED 2004
|
|
+#define CSMI_SAS_SELECT_PHY_OR_PORT 2005
|
|
+#define CSMI_SAS_PORT_DOES_NOT_EXIST 2006
|
|
+#define CSMI_SAS_PORT_CANNOT_BE_SELECTED 2007
|
|
+#define CSMI_SAS_CONNECTION_FAILED 2008
|
|
+
|
|
+#define CSMI_SAS_NO_SATA_DEVICE 2009
|
|
+#define CSMI_SAS_NO_SATA_SIGNATURE 2010
|
|
+#define CSMI_SAS_SCSI_EMULATION 2011
|
|
+#define CSMI_SAS_NOT_AN_END_DEVICE 2012
|
|
+#define CSMI_SAS_NO_SCSI_ADDRESS 2013
|
|
+#define CSMI_SAS_NO_DEVICE_ADDRESS 2014
|
|
+
|
|
+// Signature value
|
|
+// (IoctlHeader.Signature)
|
|
+
|
|
+#define CSMI_SAS_SIGNATURE "CSMISAS"
|
|
+
|
|
+// Timeout value default of 60 seconds
|
|
+// (IoctlHeader.Timeout)
|
|
+
|
|
+#define CSMI_SAS_TIMEOUT 60
|
|
+
|
|
+// Device types
|
|
+// (bDeviceType)
|
|
+
|
|
+#define CSMI_SAS_PHY_UNUSED 0x00
|
|
+#define CSMI_SAS_NO_DEVICE_ATTACHED 0x00
|
|
+#define CSMI_SAS_END_DEVICE 0x10
|
|
+#define CSMI_SAS_EDGE_EXPANDER_DEVICE 0x20
|
|
+#define CSMI_SAS_FANOUT_EXPANDER_DEVICE 0x30
|
|
+
|
|
+// Protocol options
|
|
+// (bInitiatorPortProtocol, bTargetPortProtocol)
|
|
+
|
|
+#define CSMI_SAS_PROTOCOL_SATA 0x01
|
|
+#define CSMI_SAS_PROTOCOL_SMP 0x02
|
|
+#define CSMI_SAS_PROTOCOL_STP 0x04
|
|
+#define CSMI_SAS_PROTOCOL_SSP 0x08
|
|
+
|
|
+// Negotiated and hardware link rates
|
|
+// (bNegotiatedLinkRate, bMinimumLinkRate, bMaximumLinkRate)
|
|
+
|
|
+#define CSMI_SAS_LINK_RATE_UNKNOWN 0x00
|
|
+#define CSMI_SAS_PHY_DISABLED 0x01
|
|
+#define CSMI_SAS_LINK_RATE_FAILED 0x02
|
|
+#define CSMI_SAS_SATA_SPINUP_HOLD 0x03
|
|
+#define CSMI_SAS_SATA_PORT_SELECTOR 0x04
|
|
+#define CSMI_SAS_LINK_RATE_1_5_GBPS 0x08
|
|
+#define CSMI_SAS_LINK_RATE_3_0_GBPS 0x09
|
|
+#define CSMI_SAS_LINK_VIRTUAL 0x10
|
|
+
|
|
+// Discover state
|
|
+// (bAutoDiscover)
|
|
+
|
|
+#define CSMI_SAS_DISCOVER_NOT_SUPPORTED 0x00
|
|
+#define CSMI_SAS_DISCOVER_NOT_STARTED 0x01
|
|
+#define CSMI_SAS_DISCOVER_IN_PROGRESS 0x02
|
|
+#define CSMI_SAS_DISCOVER_COMPLETE 0x03
|
|
+#define CSMI_SAS_DISCOVER_ERROR 0x04
|
|
+
|
|
+// Phy features
|
|
+
|
|
+#define CSMI_SAS_PHY_VIRTUAL_SMP 0x01
|
|
+
|
|
+// Programmed link rates
|
|
+// (bMinimumLinkRate, bMaximumLinkRate)
|
|
+// (bProgrammedMinimumLinkRate, bProgrammedMaximumLinkRate)
|
|
+
|
|
+#define CSMI_SAS_PROGRAMMED_LINK_RATE_UNCHANGED 0x00
|
|
+#define CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS 0x08
|
|
+#define CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS 0x09
|
|
+
|
|
+// Link rate
|
|
+// (bNegotiatedLinkRate in CSMI_SAS_SET_PHY_INFO)
|
|
+
|
|
+#define CSMI_SAS_LINK_RATE_NEGOTIATE 0x00
|
|
+#define CSMI_SAS_LINK_RATE_PHY_DISABLED 0x01
|
|
+
|
|
+// Signal class
|
|
+// (bSignalClass in CSMI_SAS_SET_PHY_INFO)
|
|
+
|
|
+#define CSMI_SAS_SIGNAL_CLASS_UNKNOWN 0x00
|
|
+#define CSMI_SAS_SIGNAL_CLASS_DIRECT 0x01
|
|
+#define CSMI_SAS_SIGNAL_CLASS_SERVER 0x02
|
|
+#define CSMI_SAS_SIGNAL_CLASS_ENCLOSURE 0x03
|
|
+
|
|
+// Link error reset
|
|
+// (bResetCounts)
|
|
+
|
|
+#define CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS 0x00
|
|
+#define CSMI_SAS_LINK_ERROR_RESET_COUNTS 0x01
|
|
+
|
|
+// Phy identifier
|
|
+// (bPhyIdentifier)
|
|
+
|
|
+#define CSMI_SAS_USE_PORT_IDENTIFIER 0xFF
|
|
+
|
|
+// Port identifier
|
|
+// (bPortIdentifier)
|
|
+
|
|
+#define CSMI_SAS_IGNORE_PORT 0xFF
|
|
+
|
|
+// Programmed link rates
|
|
+// (bConnectionRate)
|
|
+
|
|
+#define CSMI_SAS_LINK_RATE_NEGOTIATED 0x00
|
|
+#define CSMI_SAS_LINK_RATE_1_5_GBPS 0x08
|
|
+#define CSMI_SAS_LINK_RATE_3_0_GBPS 0x09
|
|
+
|
|
+// Connection status
|
|
+// (bConnectionStatus)
|
|
+
|
|
+#define CSMI_SAS_OPEN_ACCEPT 0
|
|
+#define CSMI_SAS_OPEN_REJECT_BAD_DESTINATION 1
|
|
+#define CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED 2
|
|
+#define CSMI_SAS_OPEN_REJECT_NO_DESTINATION 3
|
|
+#define CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED 4
|
|
+#define CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED 5
|
|
+#define CSMI_SAS_OPEN_REJECT_RESERVE_ABANDON 6
|
|
+#define CSMI_SAS_OPEN_REJECT_RESERVE_CONTINUE 7
|
|
+#define CSMI_SAS_OPEN_REJECT_RESERVE_INITIALIZE 8
|
|
+#define CSMI_SAS_OPEN_REJECT_RESERVE_STOP 9
|
|
+#define CSMI_SAS_OPEN_REJECT_RETRY 10
|
|
+#define CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY 11
|
|
+#define CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION 12
|
|
+
|
|
+// SSP Status
|
|
+// (bSSPStatus)
|
|
+
|
|
+#define CSMI_SAS_SSP_STATUS_UNKNOWN 0x00
|
|
+#define CSMI_SAS_SSP_STATUS_WAITING 0x01
|
|
+#define CSMI_SAS_SSP_STATUS_COMPLETED 0x02
|
|
+#define CSMI_SAS_SSP_STATUS_FATAL_ERROR 0x03
|
|
+#define CSMI_SAS_SSP_STATUS_RETRY 0x04
|
|
+#define CSMI_SAS_SSP_STATUS_NO_TAG 0x05
|
|
+
|
|
+// SSP Flags
|
|
+// (uFlags)
|
|
+
|
|
+#define CSMI_SAS_SSP_READ 0x00000001
|
|
+#define CSMI_SAS_SSP_WRITE 0x00000002
|
|
+#define CSMI_SAS_SSP_UNSPECIFIED 0x00000004
|
|
+
|
|
+#define CSMI_SAS_SSP_TASK_ATTRIBUTE_SIMPLE 0x00000000
|
|
+#define CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE 0x00000010
|
|
+#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED 0x00000020
|
|
+#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA 0x00000040
|
|
+
|
|
+// SSP Data present
|
|
+// (bDataPresent)
|
|
+
|
|
+#define CSMI_SAS_SSP_NO_DATA_PRESENT 0x00
|
|
+#define CSMI_SAS_SSP_RESPONSE_DATA_PRESENT 0x01
|
|
+#define CSMI_SAS_SSP_SENSE_DATA_PRESENT 0x02
|
|
+
|
|
+// STP Flags
|
|
+// (uFlags)
|
|
+
|
|
+#define CSMI_SAS_STP_READ 0x00000001
|
|
+#define CSMI_SAS_STP_WRITE 0x00000002
|
|
+#define CSMI_SAS_STP_UNSPECIFIED 0x00000004
|
|
+#define CSMI_SAS_STP_PIO 0x00000010
|
|
+#define CSMI_SAS_STP_DMA 0x00000020
|
|
+#define CSMI_SAS_STP_PACKET 0x00000040
|
|
+#define CSMI_SAS_STP_DMA_QUEUED 0x00000080
|
|
+#define CSMI_SAS_STP_EXECUTE_DIAG 0x00000100
|
|
+#define CSMI_SAS_STP_RESET_DEVICE 0x00000200
|
|
+
|
|
+// Task Management Flags
|
|
+// (uFlags)
|
|
+
|
|
+#define CSMI_SAS_TASK_IU 0x00000001
|
|
+#define CSMI_SAS_HARD_RESET_SEQUENCE 0x00000002
|
|
+#define CSMI_SAS_SUPPRESS_RESULT 0x00000004
|
|
+
|
|
+// Task Management Functions
|
|
+// (bTaskManagement)
|
|
+
|
|
+#define CSMI_SAS_SSP_ABORT_TASK 0x01
|
|
+#define CSMI_SAS_SSP_ABORT_TASK_SET 0x02
|
|
+#define CSMI_SAS_SSP_CLEAR_TASK_SET 0x04
|
|
+#define CSMI_SAS_SSP_LOGICAL_UNIT_RESET 0x08
|
|
+#define CSMI_SAS_SSP_CLEAR_ACA 0x40
|
|
+#define CSMI_SAS_SSP_QUERY_TASK 0x80
|
|
+
|
|
+// Task Management Information
|
|
+// (uInformation)
|
|
+
|
|
+#define CSMI_SAS_SSP_TEST 1
|
|
+#define CSMI_SAS_SSP_EXCEEDED 2
|
|
+#define CSMI_SAS_SSP_DEMAND 3
|
|
+#define CSMI_SAS_SSP_TRIGGER 4
|
|
+
|
|
+// Connector Pinout Information
|
|
+// (uPinout)
|
|
+
|
|
+#define CSMI_SAS_CON_UNKNOWN 0x00000001
|
|
+#define CSMI_SAS_CON_SFF_8482 0x00000002
|
|
+#define CSMI_SAS_CON_SFF_8470_LANE_1 0x00000100
|
|
+#define CSMI_SAS_CON_SFF_8470_LANE_2 0x00000200
|
|
+#define CSMI_SAS_CON_SFF_8470_LANE_3 0x00000400
|
|
+#define CSMI_SAS_CON_SFF_8470_LANE_4 0x00000800
|
|
+#define CSMI_SAS_CON_SFF_8484_LANE_1 0x00010000
|
|
+#define CSMI_SAS_CON_SFF_8484_LANE_2 0x00020000
|
|
+#define CSMI_SAS_CON_SFF_8484_LANE_3 0x00040000
|
|
+#define CSMI_SAS_CON_SFF_8484_LANE_4 0x00080000
|
|
+
|
|
+// Connector Location Information
|
|
+// (bLocation)
|
|
+
|
|
+// same as uPinout above...
|
|
+// #define CSMI_SAS_CON_UNKNOWN 0x01
|
|
+#define CSMI_SAS_CON_INTERNAL 0x02
|
|
+#define CSMI_SAS_CON_EXTERNAL 0x04
|
|
+#define CSMI_SAS_CON_SWITCHABLE 0x08
|
|
+#define CSMI_SAS_CON_AUTO 0x10
|
|
+#define CSMI_SAS_CON_NOT_PRESENT 0x20
|
|
+#define CSMI_SAS_CON_NOT_CONNECTED 0x80
|
|
+
|
|
+// Device location identification
|
|
+// (bIdentify)
|
|
+
|
|
+#define CSMI_SAS_LOCATE_UNKNOWN 0x00
|
|
+#define CSMI_SAS_LOCATE_FORCE_OFF 0x01
|
|
+#define CSMI_SAS_LOCATE_FORCE_ON 0x02
|
|
+
|
|
+// Location Valid flags
|
|
+// (uLocationFlags)
|
|
+
|
|
+#define CSMI_SAS_LOCATE_SAS_ADDRESS_VALID 0x00000001
|
|
+#define CSMI_SAS_LOCATE_SAS_LUN_VALID 0x00000002
|
|
+#define CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID 0x00000004
|
|
+#define CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID 0x00000008
|
|
+#define CSMI_SAS_LOCATE_BAY_PREFIX_VALID 0x00000010
|
|
+#define CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID 0x00000020
|
|
+#define CSMI_SAS_LOCATE_LOCATION_STATE_VALID 0x00000040
|
|
+
|
|
+/* * * * * * * * SAS Phy Control Class IOCTL Constants * * * * * * * * */
|
|
+
|
|
+// Return codes for SAS Phy Control IOCTL's
|
|
+// (IoctlHeader.ReturnCode)
|
|
+
|
|
+// Signature value
|
|
+// (IoctlHeader.Signature)
|
|
+
|
|
+#define CSMI_PHY_SIGNATURE "CSMIPHY"
|
|
+
|
|
+// Phy Control Functions
|
|
+// (bFunction)
|
|
+
|
|
+// values 0x00 to 0xFF are consistent in definition with the SMP PHY CONTROL
|
|
+// function defined in the SAS spec
|
|
+#define CSMI_SAS_PC_NOP 0x00000000
|
|
+#define CSMI_SAS_PC_LINK_RESET 0x00000001
|
|
+#define CSMI_SAS_PC_HARD_RESET 0x00000002
|
|
+#define CSMI_SAS_PC_PHY_DISABLE 0x00000003
|
|
+// 0x04 to 0xFF reserved...
|
|
+#define CSMI_SAS_PC_GET_PHY_SETTINGS 0x00000100
|
|
+
|
|
+// Link Flags
|
|
+#define CSMI_SAS_PHY_ACTIVATE_CONTROL 0x00000001
|
|
+#define CSMI_SAS_PHY_UPDATE_SPINUP_RATE 0x00000002
|
|
+#define CSMI_SAS_PHY_AUTO_COMWAKE 0x00000004
|
|
+
|
|
+// Device Types for Phy Settings
|
|
+// (bType)
|
|
+#define CSMI_SAS_UNDEFINED 0x00
|
|
+#define CSMI_SAS_SATA 0x01
|
|
+#define CSMI_SAS_SAS 0x02
|
|
+
|
|
+// Transmitter Flags
|
|
+// (uTransmitterFlags)
|
|
+#define CSMI_SAS_PHY_PREEMPHASIS_DISABLED 0x00000001
|
|
+
|
|
+// Receiver Flags
|
|
+// (uReceiverFlags)
|
|
+#define CSMI_SAS_PHY_EQUALIZATION_DISABLED 0x00000001
|
|
+
|
|
+// Pattern Flags
|
|
+// (uPatternFlags)
|
|
+// #define CSMI_SAS_PHY_ACTIVATE_CONTROL 0x00000001
|
|
+#define CSMI_SAS_PHY_DISABLE_SCRAMBLING 0x00000002
|
|
+#define CSMI_SAS_PHY_DISABLE_ALIGN 0x00000004
|
|
+#define CSMI_SAS_PHY_DISABLE_SSC 0x00000008
|
|
+
|
|
+#define CSMI_SAS_PHY_FIXED_PATTERN 0x00000010
|
|
+#define CSMI_SAS_PHY_USER_PATTERN 0x00000020
|
|
+
|
|
+// Fixed Patterns
|
|
+// (bFixedPattern)
|
|
+#define CSMI_SAS_PHY_CJPAT 0x00000001
|
|
+#define CSMI_SAS_PHY_ALIGN 0x00000002
|
|
+
|
|
+// Type Flags
|
|
+// (bTypeFlags)
|
|
+#define CSMI_SAS_PHY_POSITIVE_DISPARITY 0x01
|
|
+#define CSMI_SAS_PHY_NEGATIVE_DISPARITY 0x02
|
|
+#define CSMI_SAS_PHY_CONTROL_CHARACTER 0x04
|
|
+
|
|
+// Miscellaneous
|
|
+#define SLOT_NUMBER_UNKNOWN 0xFFFF
|
|
+
|
|
+/*************************************************************************/
|
|
+/* DATA STRUCTURES */
|
|
+/*************************************************************************/
|
|
+
|
|
+/* * * * * * * * * * Class Independent Structures * * * * * * * * * */
|
|
+
|
|
+// EDM #pragma CSMI_SAS_BEGIN_PACK(8)
|
|
+#pragma pack(8)
|
|
+
|
|
+// CC_CSMI_SAS_DRIVER_INFO
|
|
+
|
|
+typedef struct _CSMI_SAS_DRIVER_INFO {
|
|
+ __u8 szName[81];
|
|
+ __u8 szDescription[81];
|
|
+ __u16 usMajorRevision;
|
|
+ __u16 usMinorRevision;
|
|
+ __u16 usBuildRevision;
|
|
+ __u16 usReleaseRevision;
|
|
+ __u16 usCSMIMajorRevision;
|
|
+ __u16 usCSMIMinorRevision;
|
|
+} CSMI_SAS_DRIVER_INFO,
|
|
+ *PCSMI_SAS_DRIVER_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_DRIVER_INFO_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_DRIVER_INFO Information;
|
|
+} CSMI_SAS_DRIVER_INFO_BUFFER,
|
|
+ *PCSMI_SAS_DRIVER_INFO_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_CNTLR_CONFIGURATION
|
|
+
|
|
+typedef struct _CSMI_SAS_PCI_BUS_ADDRESS {
|
|
+ __u8 bBusNumber;
|
|
+ __u8 bDeviceNumber;
|
|
+ __u8 bFunctionNumber;
|
|
+ __u8 bReserved;
|
|
+} CSMI_SAS_PCI_BUS_ADDRESS,
|
|
+ *PCSMI_SAS_PCI_BUS_ADDRESS;
|
|
+
|
|
+typedef union _CSMI_SAS_IO_BUS_ADDRESS {
|
|
+ CSMI_SAS_PCI_BUS_ADDRESS PciAddress;
|
|
+ __u8 bReserved[32];
|
|
+} CSMI_SAS_IO_BUS_ADDRESS,
|
|
+ *PCSMI_SAS_IO_BUS_ADDRESS;
|
|
+
|
|
+typedef struct _CSMI_SAS_CNTLR_CONFIG {
|
|
+ __u32 uBaseIoAddress;
|
|
+ struct {
|
|
+ __u32 uLowPart;
|
|
+ __u32 uHighPart;
|
|
+ } BaseMemoryAddress;
|
|
+ __u32 uBoardID;
|
|
+ __u16 usSlotNumber;
|
|
+ __u8 bControllerClass;
|
|
+ __u8 bIoBusType;
|
|
+ CSMI_SAS_IO_BUS_ADDRESS BusAddress;
|
|
+ __u8 szSerialNumber[81];
|
|
+ __u16 usMajorRevision;
|
|
+ __u16 usMinorRevision;
|
|
+ __u16 usBuildRevision;
|
|
+ __u16 usReleaseRevision;
|
|
+ __u16 usBIOSMajorRevision;
|
|
+ __u16 usBIOSMinorRevision;
|
|
+ __u16 usBIOSBuildRevision;
|
|
+ __u16 usBIOSReleaseRevision;
|
|
+ __u32 uControllerFlags;
|
|
+ __u16 usRromMajorRevision;
|
|
+ __u16 usRromMinorRevision;
|
|
+ __u16 usRromBuildRevision;
|
|
+ __u16 usRromReleaseRevision;
|
|
+ __u16 usRromBIOSMajorRevision;
|
|
+ __u16 usRromBIOSMinorRevision;
|
|
+ __u16 usRromBIOSBuildRevision;
|
|
+ __u16 usRromBIOSReleaseRevision;
|
|
+ __u8 bReserved[7];
|
|
+} CSMI_SAS_CNTLR_CONFIG,
|
|
+ *PCSMI_SAS_CNTLR_CONFIG;
|
|
+
|
|
+typedef struct _CSMI_SAS_CNTLR_CONFIG_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_CNTLR_CONFIG Configuration;
|
|
+} CSMI_SAS_CNTLR_CONFIG_BUFFER,
|
|
+ *PCSMI_SAS_CNTLR_CONFIG_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_CNTLR_STATUS
|
|
+
|
|
+typedef struct _CSMI_SAS_CNTLR_STATUS {
|
|
+ __u32 uStatus;
|
|
+ __u32 uOfflineReason;
|
|
+ __u8 bReserved[28];
|
|
+} CSMI_SAS_CNTLR_STATUS,
|
|
+ *PCSMI_SAS_CNTLR_STATUS;
|
|
+
|
|
+typedef struct _CSMI_SAS_CNTLR_STATUS_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_CNTLR_STATUS Status;
|
|
+} CSMI_SAS_CNTLR_STATUS_BUFFER,
|
|
+ *PCSMI_SAS_CNTLR_STATUS_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_FIRMWARE_DOWNLOAD
|
|
+
|
|
+typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD {
|
|
+ __u32 uBufferLength;
|
|
+ __u32 uDownloadFlags;
|
|
+ __u8 bReserved[32];
|
|
+ __u16 usStatus;
|
|
+ __u16 usSeverity;
|
|
+} CSMI_SAS_FIRMWARE_DOWNLOAD,
|
|
+ *PCSMI_SAS_FIRMWARE_DOWNLOAD;
|
|
+
|
|
+typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_FIRMWARE_DOWNLOAD Information;
|
|
+ __u8 bDataBuffer[1];
|
|
+} CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER,
|
|
+ *PCSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_RAID_INFO
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_INFO {
|
|
+ __u32 uNumRaidSets;
|
|
+ __u32 uMaxDrivesPerSet;
|
|
+ __u32 uMaxRaidSets;
|
|
+ __u8 bMaxRaidTypes;
|
|
+ __u8 bReservedByteFields[7];
|
|
+ struct
|
|
+ {
|
|
+ __u32 uLowPart;
|
|
+ __u32 uHighPart;
|
|
+ } ulMinRaidSetBlocks;
|
|
+ struct
|
|
+ {
|
|
+ __u32 uLowPart;
|
|
+ __u32 uHighPart;
|
|
+ } ulMaxRaidSetBlocks;
|
|
+ __u32 uMaxPhysicalDrives;
|
|
+ __u32 uMaxExtents;
|
|
+ __u32 uMaxModules;
|
|
+ __u32 uMaxTransformationMemory;
|
|
+ __u32 uChangeCount;
|
|
+ __u8 bReserved[44];
|
|
+} CSMI_SAS_RAID_INFO,
|
|
+ *PCSMI_SAS_RAID_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_INFO_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_RAID_INFO Information;
|
|
+} CSMI_SAS_RAID_INFO_BUFFER,
|
|
+ *PCSMI_SAS_RAID_INFO_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_GET_RAID_CONFIG
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_DRIVES {
|
|
+ __u8 bModel[40];
|
|
+ __u8 bFirmware[8];
|
|
+ __u8 bSerialNumber[40];
|
|
+ __u8 bSASAddress[8];
|
|
+ __u8 bSASLun[8];
|
|
+ __u8 bDriveStatus;
|
|
+ __u8 bDriveUsage;
|
|
+ __u16 usBlockSize;
|
|
+ __u8 bDriveType;
|
|
+ __u8 bReserved[15];
|
|
+ __u32 uDriveIndex;
|
|
+ struct
|
|
+ {
|
|
+ __u32 uLowPart;
|
|
+ __u32 uHighPart;
|
|
+ } ulTotalUserBlocks;
|
|
+} CSMI_SAS_RAID_DRIVES,
|
|
+ *PCSMI_SAS_RAID_DRIVES;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_DEVICE_ID {
|
|
+ __u8 bDeviceIdentificationVPDPage[1];
|
|
+} CSMI_SAS_RAID_DEVICE_ID,
|
|
+ *PCSMI_SAS_RAID_DEVICE_ID;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_SET_ADDITIONAL_DATA {
|
|
+ __u8 bLabel[16];
|
|
+ __u8 bRaidSetLun[8];
|
|
+ __u8 bWriteProtection;
|
|
+ __u8 bCacheSetting;
|
|
+ __u8 bCacheRatio;
|
|
+ __u16 usBlockSize;
|
|
+ __u8 bReservedBytes[11];
|
|
+ struct
|
|
+ {
|
|
+ __u32 uLowPart;
|
|
+ __u32 uHighPart;
|
|
+ } ulRaidSetExtentOffset;
|
|
+ struct
|
|
+ {
|
|
+ __u32 uLowPart;
|
|
+ __u32 uHighPart;
|
|
+ } ulRaidSetBlocks;
|
|
+ __u32 uStripeSizeInBlocks;
|
|
+ __u32 uSectorsPerTrack;
|
|
+ __u8 bApplicationScratchPad[16];
|
|
+ __u32 uNumberOfHeads;
|
|
+ __u32 uNumberOfTracks;
|
|
+ __u8 bReserved[24];
|
|
+} CSMI_SAS_RAID_SET_ADDITIONAL_DATA,
|
|
+ *PCSMI_SAS_RAID_SET_ADDITIONAL_DATA;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_CONFIG {
|
|
+ __u32 uRaidSetIndex;
|
|
+ __u32 uCapacity;
|
|
+ __u32 uStripeSize;
|
|
+ __u8 bRaidType;
|
|
+ __u8 bStatus;
|
|
+ __u8 bInformation;
|
|
+ __u8 bDriveCount;
|
|
+ __u8 bDataType;
|
|
+ __u8 bReserved[11];
|
|
+ __u32 uFailureCode;
|
|
+ __u32 uChangeCount;
|
|
+ union {
|
|
+ CSMI_SAS_RAID_DRIVES Drives[1];
|
|
+ CSMI_SAS_RAID_DEVICE_ID DeviceId[1];
|
|
+ CSMI_SAS_RAID_SET_ADDITIONAL_DATA Data[1];
|
|
+ };
|
|
+} CSMI_SAS_RAID_CONFIG,
|
|
+ *PCSMI_SAS_RAID_CONFIG;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_CONFIG_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_RAID_CONFIG Configuration;
|
|
+} CSMI_SAS_RAID_CONFIG_BUFFER,
|
|
+ *PCSMI_SAS_RAID_CONFIG_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_GET_RAID_FEATURES
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_TYPE_DESCRIPTION {
|
|
+ __u8 bRaidType;
|
|
+ __u8 bReservedBytes[7];
|
|
+ __u32 uSupportedStripeSizeMap;
|
|
+ __u8 bReserved[24];
|
|
+} CSMI_SAS_RAID_TYPE_DESCRIPTION,
|
|
+ *PCSMI_SAS_RAID_TYPE_DESCRIPTION;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_FEATURES {
|
|
+ __u32 uFeatures;
|
|
+ __u8 bReservedFeatures[32];
|
|
+ __u8 bDefaultTransformPriority;
|
|
+ __u8 bTransformPriority;
|
|
+ __u8 bDefaultRebuildPriority;
|
|
+ __u8 bRebuildPriority;
|
|
+ __u8 bDefaultSurfaceScanPriority;
|
|
+ __u8 bSurfaceScanPriority;
|
|
+ __u16 usReserved;
|
|
+ __u32 uRaidSetTransformationRules;
|
|
+ __u32 uReserved[11];
|
|
+ CSMI_SAS_RAID_TYPE_DESCRIPTION RaidType[24];
|
|
+ __u8 bCacheRatiosSupported[104];
|
|
+ __u32 uChangeCount;
|
|
+ __u32 uFailureCode;
|
|
+ __u8 bReserved[120];
|
|
+} CSMI_SAS_RAID_FEATURES,
|
|
+ *PCSMI_SAS_RAID_FEATURES;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_FEATURES_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_RAID_FEATURES Information;
|
|
+} CSMI_SAS_RAID_FEATURES_BUFFER,
|
|
+ *PCSMI_SAS_RAID_FEATURES_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_SET_RAID_CONTROL
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_CONTROL {
|
|
+ __u8 bTransformPriority;
|
|
+ __u8 bRebuildPriority;
|
|
+ __u8 bCacheRatioFlag;
|
|
+ __u8 bCacheRatio;
|
|
+ __u8 bSurfaceScanPriority;
|
|
+ __u8 bReservedBytes[15];
|
|
+ __u8 bClearConfiguration[8];
|
|
+ __u32 uChangeCount;
|
|
+ __u8 bReserved[88];
|
|
+ __u32 uFailureCode;
|
|
+ __u8 bFailureDescription[80];
|
|
+} CSMI_SAS_RAID_CONTROL,
|
|
+ *PCSMI_SAS_RAID_CONTROL;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_CONTROL_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_RAID_CONTROL Information;
|
|
+} CSMI_SAS_RAID_CONTROL_BUFFER,
|
|
+ *PCSMI_SAS_RAID_CONTROL_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_GET_RAID_ELEMENT
|
|
+
|
|
+typedef struct _CSMI_SAS_DRIVE_EXTENT_INFO {
|
|
+ __u32 uDriveIndex;
|
|
+ __u8 bExtentType;
|
|
+ __u8 bReservedBytes[7];
|
|
+ struct
|
|
+ {
|
|
+ __u32 uLowPart;
|
|
+ __u32 uHighPart;
|
|
+ } ulExtentOffset;
|
|
+ struct
|
|
+ {
|
|
+ __u32 uLowPart;
|
|
+ __u32 uHighPart;
|
|
+ } ulExtentBlocks;
|
|
+ __u32 uRaidSetIndex;
|
|
+ __u8 bReserved[96];
|
|
+} CSMI_SAS_DRIVE_EXTENT_INFO,
|
|
+ *PCSMI_SAS_DRIVE_EXTENT_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_MODULE_INFO {
|
|
+ __u8 bReserved[128];
|
|
+} CSMI_SAS_RAID_MODULE_INFO,
|
|
+ *PCSMI_SAS_RAID_MODULE_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_DRIVE_LOCATION {
|
|
+ __u8 bConnector[16];
|
|
+ __u8 bBoxName[16];
|
|
+ __u32 uBay;
|
|
+ __u8 bReservedBytes[4];
|
|
+ __u8 bAttachedSASAddress[8];
|
|
+ __u8 bAttachedPhyIdentifier;
|
|
+ __u8 bReserved[79];
|
|
+} CSMI_SAS_DRIVE_LOCATION,
|
|
+ *PCSMI_SAS_DRIVE_LOCATION;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA {
|
|
+ __u8 bNegotiatedLinkRate[2];
|
|
+ __u8 bReserved[126];
|
|
+} CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA,
|
|
+ *PCSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA;
|
|
+
|
|
+typedef struct _CSMI_SAS_DRIVE_INFO {
|
|
+ CSMI_SAS_RAID_DRIVES Device;
|
|
+ CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA Data;
|
|
+ CSMI_SAS_DRIVE_LOCATION Location;
|
|
+ __u8 bReserved[16];
|
|
+} CSMI_SAS_DRIVE_INFO,
|
|
+ *PCSMI_SAS_DRIVE_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_ELEMENT {
|
|
+ __u32 uEnumerationType;
|
|
+ __u32 uElementIndex;
|
|
+ __u32 uNumElements;
|
|
+ __u32 uChangeCount;
|
|
+ __u32 uSubElementIndex;
|
|
+ __u8 bReserved[32];
|
|
+ __u32 uFailureCode;
|
|
+ __u8 bFailureDescription[80];
|
|
+ union {
|
|
+ CSMI_SAS_DRIVE_INFO Drive;
|
|
+ CSMI_SAS_RAID_MODULE_INFO Module;
|
|
+ CSMI_SAS_DRIVE_EXTENT_INFO Extent;
|
|
+ } Element;
|
|
+} CSMI_SAS_RAID_ELEMENT,
|
|
+ *PCSMI_SAS_RAID_ELEMENT;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_ELEMENT_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_RAID_ELEMENT Information;
|
|
+} CSMI_SAS_RAID_ELEMENT_BUFFER,
|
|
+ *PCSMI_SAS_RAID_ELEMENT_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_SET_RAID_OPERATION
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_SET_LIST {
|
|
+ __u32 uRaidSetIndex;
|
|
+ __u8 bExistingLun[8];
|
|
+ __u8 bNewLun[8];
|
|
+ __u8 bReserved[12];
|
|
+} CSMI_SAS_RAID_SET_LIST,
|
|
+ *PCSMI_SAS_RAID_SET_LIST;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_SET_DRIVE_LIST {
|
|
+ __u32 uDriveIndex;
|
|
+ __u8 bDriveUsage;
|
|
+ __u8 bReserved[27];
|
|
+} CSMI_SAS_RAID_SET_DRIVE_LIST,
|
|
+ *PCSMI_SAS_RAID_SET_DRIVE_LIST;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_SET_SPARE_INFO {
|
|
+ __u32 uRaidSetIndex;
|
|
+ __u32 uDriveCount;
|
|
+ __u8 bApplicationScratchPad[16];
|
|
+ __u8 bReserved[104];
|
|
+} CSMI_SAS_RAID_SET_SPARE_INFO,
|
|
+ *PCSMI_SAS_RAID_SET_SPARE_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_SET_ONLINE_STATE_INFO {
|
|
+ __u32 uRaidSetIndex;
|
|
+ __u8 bOnlineState;
|
|
+ __u8 bReserved[123];
|
|
+} CSMI_SAS_RAID_SET_ONLINE_STATE_INFO,
|
|
+ *PCSMI_SAS_RAID_SET_ONLINE_STATE_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_SET_CACHE_INFO {
|
|
+ __u32 uRaidSetIndex;
|
|
+ __u8 bCacheSetting;
|
|
+ __u8 bCacheRatioFlag;
|
|
+ __u8 bCacheRatio;
|
|
+ __u8 bReserved[121];
|
|
+} CSMI_SAS_RAID_SET_CACHE_INFO,
|
|
+ *PCSMI_SAS_RAID_SET_CACHE_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO {
|
|
+ __u32 uRaidSetIndex;
|
|
+ __u8 bWriteProtectSetting;
|
|
+ __u8 bReserved[123];
|
|
+} CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO,
|
|
+ *PCSMI_SAS_RAID_SET_WRITE_PROTECT_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_SET_DELETE_INFO {
|
|
+ __u32 uRaidSetIndex;
|
|
+ __u8 bReserved[124];
|
|
+} CSMI_SAS_RAID_SET_DELETE_INFO,
|
|
+ *PCSMI_SAS_RAID_SET_DELETE_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_SET_MODIFY_INFO {
|
|
+ __u8 bRaidType;
|
|
+ __u8 bReservedBytes[7];
|
|
+ __u32 uStripeSize;
|
|
+ struct
|
|
+ {
|
|
+ __u32 uLowPart;
|
|
+ __u32 uHighPart;
|
|
+ } ulRaidSetBlocks;
|
|
+ struct
|
|
+ {
|
|
+ __u32 uLowPart;
|
|
+ __u32 uHighPart;
|
|
+ } ulRaidSetExtentOffset;
|
|
+ __u32 uDriveCount;
|
|
+ __u8 bReserved[96];
|
|
+} CSMI_SAS_RAID_SET_MODIFY_INFO,
|
|
+ *PCSMI_SAS_RAID_SET_MODIFY_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_SET_TRANSFORM_INFO {
|
|
+ __u8 bTransformType;
|
|
+ __u8 bReservedBytes[3];
|
|
+ __u32 uRaidSetIndex;
|
|
+ __u8 bRaidType;
|
|
+ __u8 bReservedBytes2[11];
|
|
+ __u32 uAdditionalRaidSetIndex;
|
|
+ __u32 uRaidSetCount;
|
|
+ __u8 bApplicationScratchPad[16];
|
|
+ CSMI_SAS_RAID_SET_MODIFY_INFO Modify;
|
|
+ __u8 bReserved[80];
|
|
+} CSMI_SAS_RAID_SET_TRANSFORM_INFO,
|
|
+ *PCSMI_SAS_RAID_SET_TRANSFORM_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_SET_LABEL_INFO {
|
|
+ __u32 uRaidSetIndex;
|
|
+ __u8 bLabel[16];
|
|
+ __u8 bReserved[108];
|
|
+} CSMI_SAS_RAID_SET_LABEL_INFO,
|
|
+ *PCSMI_SAS_RAID_SET_LABEL_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_SET_CREATE_INFO {
|
|
+ __u8 bRaidType;
|
|
+ __u8 bReservedBytes[7];
|
|
+ __u32 uStripeSize;
|
|
+ __u32 uTrackSectorCount;
|
|
+ struct
|
|
+ {
|
|
+ __u32 uLowPart;
|
|
+ __u32 uHighPart;
|
|
+ } ulRaidSetBlocks;
|
|
+ struct
|
|
+ {
|
|
+ __u32 uLowPart;
|
|
+ __u32 uHighPart;
|
|
+ } ulRaidSetExtentOffset;
|
|
+ __u32 uDriveCount;
|
|
+ __u8 bLabel[16];
|
|
+ __u32 uRaidSetIndex;
|
|
+ __u8 bApplicationScratchPad[16];
|
|
+ __u32 uNumberOfHeads;
|
|
+ __u32 uNumberOfTracks;
|
|
+ __u8 bReserved[48];
|
|
+} CSMI_SAS_RAID_SET_CREATE_INFO,
|
|
+ *PCSMI_SAS_RAID_SET_CREATE_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_SET_OPERATION {
|
|
+ __u32 uOperationType;
|
|
+ __u32 uChangeCount;
|
|
+ __u32 uFailureCode;
|
|
+ __u8 bFailureDescription[80];
|
|
+ __u8 bReserved[28];
|
|
+ union {
|
|
+ CSMI_SAS_RAID_SET_CREATE_INFO Create;
|
|
+ CSMI_SAS_RAID_SET_LABEL_INFO Label;
|
|
+ CSMI_SAS_RAID_SET_TRANSFORM_INFO Transform;
|
|
+ CSMI_SAS_RAID_SET_DELETE_INFO Delete;
|
|
+ CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO Protect;
|
|
+ CSMI_SAS_RAID_SET_CACHE_INFO Cache;
|
|
+ CSMI_SAS_RAID_SET_ONLINE_STATE_INFO State;
|
|
+ CSMI_SAS_RAID_SET_SPARE_INFO Spare;
|
|
+ } Operation;
|
|
+ union {
|
|
+ CSMI_SAS_RAID_SET_DRIVE_LIST DriveList[1];
|
|
+ CSMI_SAS_RAID_SET_LIST RaidSetList[1];
|
|
+ } Parameters;
|
|
+} CSMI_SAS_RAID_SET_OPERATION,
|
|
+ *PCSMI_SAS_RAID_SET_OPERATION;
|
|
+
|
|
+typedef struct _CSMI_SAS_RAID_SET_OPERATION_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_RAID_SET_OPERATION Information;
|
|
+} CSMI_SAS_RAID_SET_OPERATION_BUFFER,
|
|
+ *PCSMI_SAS_RAID_SET_OPERATION_BUFFER;
|
|
+
|
|
+/* * * * * * * * * * SAS HBA Class Structures * * * * * * * * * */
|
|
+
|
|
+// CC_CSMI_SAS_GET_PHY_INFO
|
|
+
|
|
+typedef struct _CSMI_SAS_IDENTIFY {
|
|
+ __u8 bDeviceType;
|
|
+ __u8 bRestricted;
|
|
+ __u8 bInitiatorPortProtocol;
|
|
+ __u8 bTargetPortProtocol;
|
|
+ __u8 bRestricted2[8];
|
|
+ __u8 bSASAddress[8];
|
|
+ __u8 bPhyIdentifier;
|
|
+ __u8 bSignalClass;
|
|
+ __u8 bReserved[6];
|
|
+} CSMI_SAS_IDENTIFY,
|
|
+ *PCSMI_SAS_IDENTIFY;
|
|
+
|
|
+typedef struct _CSMI_SAS_PHY_ENTITY {
|
|
+ CSMI_SAS_IDENTIFY Identify;
|
|
+ __u8 bPortIdentifier;
|
|
+ __u8 bNegotiatedLinkRate;
|
|
+ __u8 bMinimumLinkRate;
|
|
+ __u8 bMaximumLinkRate;
|
|
+ __u8 bPhyChangeCount;
|
|
+ __u8 bAutoDiscover;
|
|
+ __u8 bPhyFeatures;
|
|
+ __u8 bReserved;
|
|
+ CSMI_SAS_IDENTIFY Attached;
|
|
+} CSMI_SAS_PHY_ENTITY,
|
|
+ *PCSMI_SAS_PHY_ENTITY;
|
|
+
|
|
+typedef struct _CSMI_SAS_PHY_INFO {
|
|
+ __u8 bNumberOfPhys;
|
|
+ __u8 bReserved[3];
|
|
+ CSMI_SAS_PHY_ENTITY Phy[32];
|
|
+} CSMI_SAS_PHY_INFO,
|
|
+ *PCSMI_SAS_PHY_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_PHY_INFO_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_PHY_INFO Information;
|
|
+} CSMI_SAS_PHY_INFO_BUFFER,
|
|
+ *PCSMI_SAS_PHY_INFO_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_SET_PHY_INFO
|
|
+
|
|
+typedef struct _CSMI_SAS_SET_PHY_INFO {
|
|
+ __u8 bPhyIdentifier;
|
|
+ __u8 bNegotiatedLinkRate;
|
|
+ __u8 bProgrammedMinimumLinkRate;
|
|
+ __u8 bProgrammedMaximumLinkRate;
|
|
+ __u8 bSignalClass;
|
|
+ __u8 bReserved[3];
|
|
+} CSMI_SAS_SET_PHY_INFO,
|
|
+ *PCSMI_SAS_SET_PHY_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_SET_PHY_INFO_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_SET_PHY_INFO Information;
|
|
+} CSMI_SAS_SET_PHY_INFO_BUFFER,
|
|
+ *PCSMI_SAS_SET_PHY_INFO_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_GET_LINK_ERRORS
|
|
+
|
|
+typedef struct _CSMI_SAS_LINK_ERRORS {
|
|
+ __u8 bPhyIdentifier;
|
|
+ __u8 bResetCounts;
|
|
+ __u8 bReserved[2];
|
|
+ __u32 uInvalidDwordCount;
|
|
+ __u32 uRunningDisparityErrorCount;
|
|
+ __u32 uLossOfDwordSyncCount;
|
|
+ __u32 uPhyResetProblemCount;
|
|
+} CSMI_SAS_LINK_ERRORS,
|
|
+ *PCSMI_SAS_LINK_ERRORS;
|
|
+
|
|
+typedef struct _CSMI_SAS_LINK_ERRORS_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_LINK_ERRORS Information;
|
|
+} CSMI_SAS_LINK_ERRORS_BUFFER,
|
|
+ *PCSMI_SAS_LINK_ERRORS_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_SMP_PASSTHRU
|
|
+
|
|
+typedef struct _CSMI_SAS_SMP_REQUEST {
|
|
+ __u8 bFrameType;
|
|
+ __u8 bFunction;
|
|
+ __u8 bReserved[2];
|
|
+ __u8 bAdditionalRequestBytes[1016];
|
|
+} CSMI_SAS_SMP_REQUEST,
|
|
+ *PCSMI_SAS_SMP_REQUEST;
|
|
+
|
|
+typedef struct _CSMI_SAS_SMP_RESPONSE {
|
|
+ __u8 bFrameType;
|
|
+ __u8 bFunction;
|
|
+ __u8 bFunctionResult;
|
|
+ __u8 bReserved;
|
|
+ __u8 bAdditionalResponseBytes[1016];
|
|
+} CSMI_SAS_SMP_RESPONSE,
|
|
+ *PCSMI_SAS_SMP_RESPONSE;
|
|
+
|
|
+typedef struct _CSMI_SAS_SMP_PASSTHRU {
|
|
+ __u8 bPhyIdentifier;
|
|
+ __u8 bPortIdentifier;
|
|
+ __u8 bConnectionRate;
|
|
+ __u8 bReserved;
|
|
+ __u8 bDestinationSASAddress[8];
|
|
+ __u32 uRequestLength;
|
|
+ CSMI_SAS_SMP_REQUEST Request;
|
|
+ __u8 bConnectionStatus;
|
|
+ __u8 bReserved2[3];
|
|
+ __u32 uResponseBytes;
|
|
+ CSMI_SAS_SMP_RESPONSE Response;
|
|
+} CSMI_SAS_SMP_PASSTHRU,
|
|
+ *PCSMI_SAS_SMP_PASSTHRU;
|
|
+
|
|
+typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_SMP_PASSTHRU Parameters;
|
|
+} CSMI_SAS_SMP_PASSTHRU_BUFFER,
|
|
+ *PCSMI_SAS_SMP_PASSTHRU_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_SSP_PASSTHRU
|
|
+
|
|
+typedef struct _CSMI_SAS_SSP_PASSTHRU {
|
|
+ __u8 bPhyIdentifier;
|
|
+ __u8 bPortIdentifier;
|
|
+ __u8 bConnectionRate;
|
|
+ __u8 bReserved;
|
|
+ __u8 bDestinationSASAddress[8];
|
|
+ __u8 bLun[8];
|
|
+ __u8 bCDBLength;
|
|
+ __u8 bAdditionalCDBLength;
|
|
+ __u8 bReserved2[2];
|
|
+ __u8 bCDB[16];
|
|
+ __u32 uFlags;
|
|
+ __u8 bAdditionalCDB[24];
|
|
+ __u32 uDataLength;
|
|
+} CSMI_SAS_SSP_PASSTHRU,
|
|
+ *PCSMI_SAS_SSP_PASSTHRU;
|
|
+
|
|
+typedef struct _CSMI_SAS_SSP_PASSTHRU_STATUS {
|
|
+ __u8 bConnectionStatus;
|
|
+ __u8 bSSPStatus;
|
|
+ __u8 bReserved[2];
|
|
+ __u8 bDataPresent;
|
|
+ __u8 bStatus;
|
|
+ __u8 bResponseLength[2];
|
|
+ __u8 bResponse[256];
|
|
+ __u32 uDataBytes;
|
|
+} CSMI_SAS_SSP_PASSTHRU_STATUS,
|
|
+ *PCSMI_SAS_SSP_PASSTHRU_STATUS;
|
|
+
|
|
+typedef struct _CSMI_SAS_SSP_PASSTHRU_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_SSP_PASSTHRU Parameters;
|
|
+ CSMI_SAS_SSP_PASSTHRU_STATUS Status;
|
|
+ __u8 bDataBuffer[1];
|
|
+} CSMI_SAS_SSP_PASSTHRU_BUFFER,
|
|
+ *PCSMI_SAS_SSP_PASSTHRU_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_STP_PASSTHRU
|
|
+
|
|
+typedef struct _CSMI_SAS_STP_PASSTHRU {
|
|
+ __u8 bPhyIdentifier;
|
|
+ __u8 bPortIdentifier;
|
|
+ __u8 bConnectionRate;
|
|
+ __u8 bReserved;
|
|
+ __u8 bDestinationSASAddress[8];
|
|
+ __u8 bReserved2[4];
|
|
+ __u8 bCommandFIS[20];
|
|
+ __u32 uFlags;
|
|
+ __u32 uDataLength;
|
|
+} CSMI_SAS_STP_PASSTHRU,
|
|
+ *PCSMI_SAS_STP_PASSTHRU;
|
|
+
|
|
+typedef struct _CSMI_SAS_STP_PASSTHRU_STATUS {
|
|
+ __u8 bConnectionStatus;
|
|
+ __u8 bReserved[3];
|
|
+ __u8 bStatusFIS[20];
|
|
+ __u32 uSCR[16];
|
|
+ __u32 uDataBytes;
|
|
+} CSMI_SAS_STP_PASSTHRU_STATUS,
|
|
+ *PCSMI_SAS_STP_PASSTHRU_STATUS;
|
|
+
|
|
+typedef struct _CSMI_SAS_STP_PASSTHRU_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_STP_PASSTHRU Parameters;
|
|
+ CSMI_SAS_STP_PASSTHRU_STATUS Status;
|
|
+ __u8 bDataBuffer[1];
|
|
+} CSMI_SAS_STP_PASSTHRU_BUFFER,
|
|
+ *PCSMI_SAS_STP_PASSTHRU_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_GET_SATA_SIGNATURE
|
|
+
|
|
+typedef struct _CSMI_SAS_SATA_SIGNATURE {
|
|
+ __u8 bPhyIdentifier;
|
|
+ __u8 bReserved[3];
|
|
+ __u8 bSignatureFIS[20];
|
|
+} CSMI_SAS_SATA_SIGNATURE,
|
|
+ *PCSMI_SAS_SATA_SIGNATURE;
|
|
+
|
|
+typedef struct _CSMI_SAS_SATA_SIGNATURE_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_SATA_SIGNATURE Signature;
|
|
+} CSMI_SAS_SATA_SIGNATURE_BUFFER,
|
|
+ *PCSMI_SAS_SATA_SIGNATURE_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_GET_SCSI_ADDRESS
|
|
+
|
|
+typedef struct _CSMI_SAS_GET_SCSI_ADDRESS_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ __u8 bSASAddress[8];
|
|
+ __u8 bSASLun[8];
|
|
+ __u8 bHostIndex;
|
|
+ __u8 bPathId;
|
|
+ __u8 bTargetId;
|
|
+ __u8 bLun;
|
|
+} CSMI_SAS_GET_SCSI_ADDRESS_BUFFER,
|
|
+ *PCSMI_SAS_GET_SCSI_ADDRESS_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_GET_DEVICE_ADDRESS
|
|
+
|
|
+typedef struct _CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ __u8 bHostIndex;
|
|
+ __u8 bPathId;
|
|
+ __u8 bTargetId;
|
|
+ __u8 bLun;
|
|
+ __u8 bSASAddress[8];
|
|
+ __u8 bSASLun[8];
|
|
+} CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER,
|
|
+ *PCSMI_SAS_GET_DEVICE_ADDRESS_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_TASK_MANAGEMENT
|
|
+
|
|
+typedef struct _CSMI_SAS_SSP_TASK_IU {
|
|
+ __u8 bHostIndex;
|
|
+ __u8 bPathId;
|
|
+ __u8 bTargetId;
|
|
+ __u8 bLun;
|
|
+ __u32 uFlags;
|
|
+ __u32 uQueueTag;
|
|
+ __u32 uReserved;
|
|
+ __u8 bTaskManagementFunction;
|
|
+ __u8 bReserved[7];
|
|
+ __u32 uInformation;
|
|
+} CSMI_SAS_SSP_TASK_IU,
|
|
+ *PCSMI_SAS_SSP_TASK_IU;
|
|
+
|
|
+typedef struct _CSMI_SAS_SSP_TASK_IU_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_SSP_TASK_IU Parameters;
|
|
+ CSMI_SAS_SSP_PASSTHRU_STATUS Status;
|
|
+} CSMI_SAS_SSP_TASK_IU_BUFFER,
|
|
+ *PCSMI_SAS_SSP_TASK_IU_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_GET_CONNECTOR_INFO
|
|
+
|
|
+typedef struct _CSMI_SAS_GET_CONNECTOR_INFO {
|
|
+ __u32 uPinout;
|
|
+ __u8 bConnector[16];
|
|
+ __u8 bLocation;
|
|
+ __u8 bReserved[15];
|
|
+} CSMI_SAS_CONNECTOR_INFO,
|
|
+ *PCSMI_SAS_CONNECTOR_INFO;
|
|
+
|
|
+typedef struct _CSMI_SAS_CONNECTOR_INFO_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ CSMI_SAS_CONNECTOR_INFO Reference[32];
|
|
+} CSMI_SAS_CONNECTOR_INFO_BUFFER,
|
|
+ *PCSMI_SAS_CONNECTOR_INFO_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_GET_LOCATION
|
|
+
|
|
+typedef struct _CSMI_SAS_LOCATION_IDENTIFIER {
|
|
+ __u32 bLocationFlags;
|
|
+ __u8 bSASAddress[8];
|
|
+ __u8 bSASLun[8];
|
|
+ __u8 bEnclosureIdentifier[8];
|
|
+ __u8 bEnclosureName[32];
|
|
+ __u8 bBayPrefix[32];
|
|
+ __u8 bBayIdentifier;
|
|
+ __u8 bLocationState;
|
|
+ __u8 bReserved[2];
|
|
+} CSMI_SAS_LOCATION_IDENTIFIER,
|
|
+ *PCSMI_SAS_LOCATION_IDENTIFIER;
|
|
+
|
|
+typedef struct _CSMI_SAS_GET_LOCATION_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ __u8 bHostIndex;
|
|
+ __u8 bPathId;
|
|
+ __u8 bTargetId;
|
|
+ __u8 bLun;
|
|
+ __u8 bIdentify;
|
|
+ __u8 bNumberOfLocationIdentifiers;
|
|
+ __u8 bLengthOfLocationIdentifier;
|
|
+ CSMI_SAS_LOCATION_IDENTIFIER Location[1];
|
|
+} CSMI_SAS_GET_LOCATION_BUFFER,
|
|
+ *PCSMI_SAS_GET_LOCATION_BUFFER;
|
|
+
|
|
+// CC_CSMI_SAS_PHY_CONTROL
|
|
+
|
|
+typedef struct _CSMI_SAS_CHARACTER {
|
|
+ __u8 bTypeFlags;
|
|
+ __u8 bValue;
|
|
+} CSMI_SAS_CHARACTER,
|
|
+ *PCSMI_SAS_CHARACTER;
|
|
+
|
|
+typedef struct _CSMI_SAS_PHY_CONTROL {
|
|
+ __u8 bType;
|
|
+ __u8 bRate;
|
|
+ __u8 bReserved[6];
|
|
+ __u32 uVendorUnique[8];
|
|
+ __u32 uTransmitterFlags;
|
|
+ __i8 bTransmitAmplitude;
|
|
+ __i8 bTransmitterPreemphasis;
|
|
+ __i8 bTransmitterSlewRate;
|
|
+ __i8 bTransmitterReserved[13];
|
|
+ __u8 bTransmitterVendorUnique[64];
|
|
+ __u32 uReceiverFlags;
|
|
+ __i8 bReceiverThreshold;
|
|
+ __i8 bReceiverEqualizationGain;
|
|
+ __i8 bReceiverReserved[14];
|
|
+ __u8 bReceiverVendorUnique[64];
|
|
+ __u32 uPatternFlags;
|
|
+ __u8 bFixedPattern;
|
|
+ __u8 bUserPatternLength;
|
|
+ __u8 bPatternReserved[6];
|
|
+ CSMI_SAS_CHARACTER UserPatternBuffer[16];
|
|
+} CSMI_SAS_PHY_CONTROL,
|
|
+ *PCSMI_SAS_PHY_CONTROL;
|
|
+
|
|
+typedef struct _CSMI_SAS_PHY_CONTROL_BUFFER {
|
|
+ IOCTL_HEADER IoctlHeader;
|
|
+ __u32 uFunction;
|
|
+ __u8 bPhyIdentifier;
|
|
+ __u16 usLengthOfControl;
|
|
+ __u8 bNumberOfControls;
|
|
+ __u8 bReserved[4];
|
|
+ __u32 uLinkFlags;
|
|
+ __u8 bSpinupRate;
|
|
+ __u8 bLinkReserved[7];
|
|
+ __u32 uVendorUnique[8];
|
|
+ CSMI_SAS_PHY_CONTROL Control[1];
|
|
+} CSMI_SAS_PHY_CONTROL_BUFFER,
|
|
+ *PCSMI_SAS_PHY_CONTROL_BUFFER;
|
|
+
|
|
+//EDM #pragma CSMI_SAS_END_PACK
|
|
+#pragma pack()
|
|
+
|
|
+#endif // _CSMI_SAS_H_
|
|
--- a/drivers/message/fusion/lsi/mpi.h
|
|
+++ b/drivers/message/fusion/lsi/mpi.h
|
|
@@ -6,7 +6,7 @@
|
|
* Title: MPI Message independent structures and definitions
|
|
* Creation Date: July 27, 2000
|
|
*
|
|
- * mpi.h Version: 01.05.16
|
|
+ * mpi.h Version: 01.05.17
|
|
*
|
|
* Version History
|
|
* ---------------
|
|
@@ -82,6 +82,7 @@
|
|
* 08-07-07 01.05.14 Bumped MPI_HEADER_VERSION_UNIT.
|
|
* 01-15-08 01.05.15 Bumped MPI_HEADER_VERSION_UNIT.
|
|
* 03-28-08 01.05.16 Bumped MPI_HEADER_VERSION_UNIT.
|
|
+ * 07-11-08 01.05.17 Bumped MPI_HEADER_VERSION_UNIT.
|
|
* --------------------------------------------------------------------------
|
|
*/
|
|
|
|
@@ -112,7 +113,7 @@
|
|
/* Note: The major versions of 0xe0 through 0xff are reserved */
|
|
|
|
/* versioning for this MPI header set */
|
|
-#define MPI_HEADER_VERSION_UNIT (0x13)
|
|
+#define MPI_HEADER_VERSION_UNIT (0x14)
|
|
#define MPI_HEADER_VERSION_DEV (0x00)
|
|
#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00)
|
|
#define MPI_HEADER_VERSION_UNIT_SHIFT (8)
|
|
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
|
|
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
|
|
@@ -6,7 +6,7 @@
|
|
* Title: MPI Config message, structures, and Pages
|
|
* Creation Date: July 27, 2000
|
|
*
|
|
- * mpi_cnfg.h Version: 01.05.18
|
|
+ * mpi_cnfg.h Version: 01.05.19
|
|
*
|
|
* Version History
|
|
* ---------------
|
|
@@ -322,6 +322,14 @@
|
|
* 03-28-08 01.05.18 Defined new bits in Manufacturing Page 4 ExtFlags field
|
|
* to control coercion size and the mixing of SAS and SATA
|
|
* SSD drives.
|
|
+ * 07-11-08 01.05.19 Added defines MPI_MANPAGE4_EXTFLAGS_RAID0_SINGLE_DRIVE
|
|
+ * and MPI_MANPAGE4_EXTFLAGS_SSD_SCRUB_DISABLE for ExtFlags
|
|
+ * field of Manufacturing Page 4.
|
|
+ * Added defines for a new bit in BIOS Page 1 BiosOptions
|
|
+ * field to control adapter scan order.
|
|
+ * Added BootDeviceWaitTime field to SAS IO Unit Page 2.
|
|
+ * Added MPI_SAS_PHY0_PHYINFO_PHY_VACANT for use in PhyInfo
|
|
+ * field of SAS Expander Page 1.
|
|
* --------------------------------------------------------------------------
|
|
*/
|
|
|
|
@@ -700,6 +708,8 @@ typedef struct _CONFIG_PAGE_MANUFACTURIN
|
|
#define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01)
|
|
|
|
/* defines for the ExtFlags field */
|
|
+#define MPI_MANPAGE4_EXTFLAGS_RAID0_SINGLE_DRIVE (0x0400)
|
|
+#define MPI_MANPAGE4_EXTFLAGS_SSD_SCRUB_DISABLE (0x0200)
|
|
#define MPI_MANPAGE4_EXTFLAGS_MASK_COERCION_SIZE (0x0180)
|
|
#define MPI_MANPAGE4_EXTFLAGS_SHIFT_COERCION_SIZE (7)
|
|
#define MPI_MANPAGE4_EXTFLAGS_1GB_COERCION_SIZE (0)
|
|
@@ -1219,6 +1229,10 @@ typedef struct _CONFIG_PAGE_BIOS_1
|
|
#define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400)
|
|
#define MPI_BIOSPAGE1_OPTIONS_FC_ENABLE (0x00000200)
|
|
#define MPI_BIOSPAGE1_OPTIONS_SAS_ENABLE (0x00000100)
|
|
+
|
|
+#define MPI_BIOSPAGE1_OPTIONS_SCAN_HIGH_TO_LOW (0x00000002)
|
|
+#define MPI_BIOSPAGE1_OPTIONS_SCAN_LOW_TO_HIGH (0x00000000)
|
|
+
|
|
#define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001)
|
|
|
|
/* values for the IOCSettings field */
|
|
@@ -2712,7 +2726,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_
|
|
{
|
|
CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
|
|
U8 NumDevsPerEnclosure; /* 08h */
|
|
- U8 Reserved1; /* 09h */
|
|
+ U8 BootDeviceWaitTime; /* 09h */
|
|
U16 Reserved2; /* 0Ah */
|
|
U16 MaxPersistentIDs; /* 0Ch */
|
|
U16 NumPersistentIDsUsed; /* 0Eh */
|
|
@@ -2722,7 +2736,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_
|
|
} 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 (0x06)
|
|
+#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x07)
|
|
|
|
/* values for SAS IO Unit Page 2 Status field */
|
|
#define MPI_SAS_IOUNIT2_STATUS_DEVICE_LIMIT_EXCEEDED (0x08)
|
|
@@ -2997,6 +3011,7 @@ typedef struct _CONFIG_PAGE_SAS_PHY_0
|
|
#define MPI_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01)
|
|
|
|
/* values for SAS PHY Page 0 PhyInfo field */
|
|
+#define MPI_SAS_PHY0_PHYINFO_PHY_VACANT (0x80000000)
|
|
#define MPI_SAS_PHY0_PHYINFO_SATA_PORT_ACTIVE (0x00004000)
|
|
#define MPI_SAS_PHY0_PHYINFO_SATA_PORT_SELECTOR (0x00002000)
|
|
#define MPI_SAS_PHY0_PHYINFO_VIRTUAL_PHY (0x00001000)
|
|
--- a/drivers/message/fusion/lsi/mpi_history.txt
|
|
+++ b/drivers/message/fusion/lsi/mpi_history.txt
|
|
@@ -6,15 +6,15 @@
|
|
Copyright (c) 2000-2008 LSI Corporation.
|
|
|
|
---------------------------------------
|
|
- Header Set Release Version: 01.05.19
|
|
- Header Set Release Date: 03-28-08
|
|
+ Header Set Release Version: 01.05.20
|
|
+ Header Set Release Date: 07-11-08
|
|
---------------------------------------
|
|
|
|
Filename Current version Prior version
|
|
---------- --------------- -------------
|
|
- mpi.h 01.05.16 01.05.15
|
|
- mpi_ioc.h 01.05.16 01.05.15
|
|
- mpi_cnfg.h 01.05.18 01.05.17
|
|
+ mpi.h 01.05.17 01.05.16
|
|
+ mpi_ioc.h 01.05.16 01.05.16
|
|
+ mpi_cnfg.h 01.05.19 01.05.18
|
|
mpi_init.h 01.05.09 01.05.09
|
|
mpi_targ.h 01.05.06 01.05.06
|
|
mpi_fc.h 01.05.01 01.05.01
|
|
@@ -24,7 +24,7 @@
|
|
mpi_inb.h 01.05.01 01.05.01
|
|
mpi_sas.h 01.05.05 01.05.05
|
|
mpi_type.h 01.05.02 01.05.02
|
|
- mpi_history.txt 01.05.19 01.05.18
|
|
+ mpi_history.txt 01.05.20 01.05.19
|
|
|
|
|
|
* Date Version Description
|
|
@@ -99,6 +99,7 @@ mpi.h
|
|
* 08-07-07 01.05.14 Bumped MPI_HEADER_VERSION_UNIT.
|
|
* 01-15-08 01.05.15 Bumped MPI_HEADER_VERSION_UNIT.
|
|
* 03-28-08 01.05.16 Bumped MPI_HEADER_VERSION_UNIT.
|
|
+ * 07-11-08 01.05.17 Bumped MPI_HEADER_VERSION_UNIT.
|
|
* --------------------------------------------------------------------------
|
|
|
|
mpi_ioc.h
|
|
@@ -130,7 +131,7 @@ mpi_ioc.h
|
|
* 08-08-01 01.02.01 Original release for v1.2 work.
|
|
* New format for FWVersion and ProductId in
|
|
* MSG_IOC_FACTS_REPLY and MPI_FW_HEADER.
|
|
- * 08-31-01 01.02.02 Added event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
|
|
+ * 08-31-01 01.02.02 Addded event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
|
|
* related structure and defines.
|
|
* Added event MPI_EVENT_ON_BUS_TIMER_EXPIRED.
|
|
* Added MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE.
|
|
@@ -190,7 +191,7 @@ mpi_ioc.h
|
|
* 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 notification.
|
|
+ * asynchronous notificaiton.
|
|
* Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event
|
|
* data structure.
|
|
* Added new ImageType values for FWDownload and FWUpload
|
|
@@ -523,6 +524,14 @@ mpi_cnfg.h
|
|
* 03-28-08 01.05.18 Defined new bits in Manufacturing Page 4 ExtFlags field
|
|
* to control coercion size and the mixing of SAS and SATA
|
|
* SSD drives.
|
|
+ * 07-11-08 01.05.19 Added defines MPI_MANPAGE4_EXTFLAGS_RAID0_SINGLE_DRIVE
|
|
+ * and MPI_MANPAGE4_EXTFLAGS_SSD_SCRUB_DISABLE for ExtFlags
|
|
+ * field of Manufacturing Page 4.
|
|
+ * Added defines for a new bit in BIOS Page 1 BiosOptions
|
|
+ * field to control adapter scan order.
|
|
+ * Added BootDeviceWaitTime field to SAS IO Unit Page 2.
|
|
+ * Added MPI_SAS_PHY0_PHYINFO_PHY_VACANT for use in PhyInfo
|
|
+ * field of SAS Expander Page 1.
|
|
* --------------------------------------------------------------------------
|
|
|
|
mpi_init.h
|
|
@@ -623,7 +632,7 @@ mpi_fc.h
|
|
* 11-02-00 01.01.01 Original release for post 1.0 work
|
|
* 12-04-00 01.01.02 Added messages for Common Transport Send and
|
|
* Primitive Send.
|
|
- * 01-09-01 01.01.03 Modified some of the new flags to have an MPI prefix
|
|
+ * 01-09-01 01.01.03 Modifed some of the new flags to have an MPI prefix
|
|
* and modified the FcPrimitiveSend flags.
|
|
* 01-25-01 01.01.04 Move InitiatorIndex in LinkServiceRsp reply to a larger
|
|
* field.
|
|
@@ -743,20 +752,20 @@ mpi_type.h
|
|
|
|
mpi_history.txt Parts list history
|
|
|
|
-Filename 01.05.19 01.05.18 01.05.17 01.05.16 01.05.15
|
|
----------- -------- -------- -------- -------- --------
|
|
-mpi.h 01.05.16 01.05.15 01.05.14 01.05.13 01.05.12
|
|
-mpi_ioc.h 01.05.16 01.05.15 01.05.15 01.05.14 01.05.13
|
|
-mpi_cnfg.h 01.05.18 01.05.17 01.05.16 01.05.15 01.05.14
|
|
-mpi_init.h 01.05.09 01.05.09 01.05.09 01.05.09 01.05.09
|
|
-mpi_targ.h 01.05.06 01.05.06 01.05.06 01.05.06 01.05.06
|
|
-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.05 01.05.05 01.05.04 01.05.03 01.05.03
|
|
-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.05 01.05.05 01.05.04 01.05.04 01.05.04
|
|
-mpi_type.h 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02
|
|
+Filename 01.05.20 01.05.19 01.05.18 01.05.17 01.05.16 01.05.15
|
|
+---------- -------- -------- -------- -------- -------- --------
|
|
+mpi.h 01.05.17 01.05.16 01.05.15 01.05.14 01.05.13 01.05.12
|
|
+mpi_ioc.h 01.05.16 01.05.16 01.05.15 01.05.15 01.05.14 01.05.13
|
|
+mpi_cnfg.h 01.05.19 01.05.18 01.05.17 01.05.16 01.05.15 01.05.14
|
|
+mpi_init.h 01.05.09 01.05.09 01.05.09 01.05.09 01.05.09 01.05.09
|
|
+mpi_targ.h 01.05.06 01.05.06 01.05.06 01.05.06 01.05.06 01.05.06
|
|
+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.05 01.05.05 01.05.05 01.05.04 01.05.03 01.05.03
|
|
+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.05 01.05.05 01.05.05 01.05.04 01.05.04 01.05.04
|
|
+mpi_type.h 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02
|
|
|
|
Filename 01.05.14 01.05.13 01.05.12 01.05.11 01.05.10 01.05.09
|
|
---------- -------- -------- -------- -------- -------- --------
|
|
--- a/drivers/message/fusion/lsi/mpi_log_sas.h
|
|
+++ b/drivers/message/fusion/lsi/mpi_log_sas.h
|
|
@@ -161,11 +161,10 @@
|
|
|
|
#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_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)
|
|
@@ -180,8 +179,7 @@
|
|
#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_SUB_CODE_BREAK_ON_SATA_CONNECTION (0x00002000)
|
|
-/* not currently used in mainline */
|
|
+#define PL_LOGINFO_SUB_CODE_BREAK_ON_SATA_CONNECTION (0x00002000) /* not currently used in mainline */
|
|
#define PL_LOGINFO_SUB_CODE_BREAK_ON_STUCK_LINK (0x00003000)
|
|
#define PL_LOGINFO_SUB_CODE_BREAK_ON_STUCK_LINK_AIP (0x00004000)
|
|
#define PL_LOGINFO_SUB_CODE_BREAK_ON_INCOMPLETE_BREAK_RCVD (0x00005000)
|
|
@@ -309,6 +307,8 @@
|
|
#define IR_LOGINFO_DEV_FW_UPDATE_ERR_PORT_IO_TIMEOUTS_REQUIRED (0x00010055)
|
|
/* Device Firmware Update: Unable to allocate memory for page */
|
|
#define IR_LOGINFO_DEV_FW_UPDATE_ERR_ALLOC_CFG_PAGE (0x00010056)
|
|
+/* Device Firmware Update: */
|
|
+//#define IR_LOGINFO_DEV_FW_UPDATE_ERR_ (0x00010054)
|
|
|
|
|
|
/****************************************************************************/
|
|
--- a/drivers/message/fusion/lsi/mpi_type.h
|
|
+++ b/drivers/message/fusion/lsi/mpi_type.h
|
|
@@ -20,6 +20,7 @@
|
|
* 08-08-01 01.02.01 Original release for v1.2 work.
|
|
* 05-11-04 01.03.01 Original release for MPI v1.3.
|
|
* 08-19-04 01.05.01 Original release for MPI v1.5.
|
|
+ * 08-30-05 01.05.02 Added PowerPC option to #ifdef's.
|
|
* --------------------------------------------------------------------------
|
|
*/
|
|
|
|
@@ -49,8 +50,18 @@ typedef signed short S16;
|
|
typedef unsigned short U16;
|
|
|
|
|
|
-typedef int32_t S32;
|
|
-typedef u_int32_t U32;
|
|
+#if defined(unix) || defined(__arm) || defined(ALPHA) || defined(__PPC__) || defined(__ppc)
|
|
+
|
|
+ typedef signed int S32;
|
|
+ typedef unsigned int U32;
|
|
+
|
|
+#else
|
|
+
|
|
+ typedef signed long S32;
|
|
+ typedef unsigned long U32;
|
|
+
|
|
+#endif
|
|
+
|
|
|
|
typedef struct _S64
|
|
{
|
|
--- a/drivers/message/fusion/mptbase.c
|
|
+++ b/drivers/message/fusion/mptbase.c
|
|
@@ -58,6 +58,7 @@
|
|
#include <linux/delay.h>
|
|
#include <linux/interrupt.h> /* needed for in_interrupt() proto */
|
|
#include <linux/dma-mapping.h>
|
|
+#include <linux/sort.h>
|
|
#include <asm/io.h>
|
|
#ifdef CONFIG_MTRR
|
|
#include <asm/mtrr.h>
|
|
@@ -100,12 +101,13 @@ 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)");
|
|
|
|
-static int mpt_debug_level;
|
|
+int mpt_debug_level;
|
|
static int mpt_set_debug_level(const char *val, struct kernel_param *kp);
|
|
module_param_call(mpt_debug_level, mpt_set_debug_level, param_get_int,
|
|
&mpt_debug_level, 0600);
|
|
MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h \
|
|
- (default=0)");
|
|
+EXPORT_SYMBOL(mpt_debug_level);
|
|
|
|
int mpt_fwfault_debug;
|
|
EXPORT_SYMBOL(mpt_fwfault_debug);
|
|
@@ -126,7 +128,7 @@ static int mfcounter = 0;
|
|
* Public data...
|
|
*/
|
|
|
|
-static struct proc_dir_entry *mpt_proc_root_dir;
|
|
+struct proc_dir_entry *mpt_proc_root_dir;
|
|
|
|
#define WHOINIT_UNKNOWN 0xAA
|
|
|
|
@@ -144,7 +146,7 @@ static int MptDriverClass[MPT_MAX_PRO
|
|
static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
|
|
/* Reset handler lookup table */
|
|
static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
|
|
-static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
|
|
+static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
|
|
|
|
|
|
/*
|
|
@@ -157,7 +159,6 @@ static u8 last_drv_idx;
|
|
/*
|
|
* Forward protos...
|
|
*/
|
|
-static irqreturn_t mpt_interrupt(int irq, void *bus_id);
|
|
static int mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
|
|
MPT_FRAME_HDR *reply);
|
|
static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
|
|
@@ -188,8 +189,8 @@ static int GetIoUnitPage2(MPT_ADAPTER *i
|
|
int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
|
|
static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
|
|
static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
|
|
-static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
|
|
-static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
|
|
+static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
|
|
+static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
|
|
static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc);
|
|
static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch,
|
|
int sleepFlag);
|
|
@@ -220,11 +221,11 @@ static void mpt_inactive_raid_list_free(
|
|
static int __init fusion_init (void);
|
|
static void __exit fusion_exit (void);
|
|
|
|
-#define CHIPREG_READ32(addr) readl_relaxed(addr)
|
|
+#define CHIPREG_READ32(addr) readl_relaxed(addr)
|
|
#define CHIPREG_READ32_dmasync(addr) readl(addr)
|
|
-#define CHIPREG_WRITE32(addr,val) writel(val, addr)
|
|
+#define CHIPREG_WRITE32(addr,val) writel(val, addr)
|
|
#define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
|
|
-#define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
|
|
+#define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
|
|
|
|
static void
|
|
pci_disable_io_access(struct pci_dev *pdev)
|
|
@@ -246,6 +247,15 @@ pci_enable_io_access(struct pci_dev *pde
|
|
pci_write_config_word(pdev, PCI_COMMAND, command_reg);
|
|
}
|
|
|
|
+/**
|
|
+ * mpt_set_debug_level - global setting of the mpt_debug_level
|
|
+ * found via /sys/module/mptbase/parameters/mpt_debug_level
|
|
+ * @val:
|
|
+ * @kp:
|
|
+ *
|
|
+ * Returns
|
|
+ **/
|
|
+
|
|
static int mpt_set_debug_level(const char *val, struct kernel_param *kp)
|
|
{
|
|
int ret = param_set_int(val, kp);
|
|
@@ -492,6 +502,9 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
|
|
mpt_sas_log_info(ioc, log_info);
|
|
}
|
|
|
|
+ /* TODO - add shost_attrs, or command line option, and
|
|
+ * extend this to SAS/FC
|
|
+ */
|
|
if (ioc_stat & MPI_IOCSTATUS_MASK)
|
|
mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
|
|
|
|
@@ -782,6 +795,8 @@ mpt_device_driver_register(struct mpt_pc
|
|
|
|
/* call per pci device probe entry point */
|
|
list_for_each_entry(ioc, &ioc_list, list) {
|
|
+ if (!pci_get_drvdata(ioc->pcidev))
|
|
+ continue;
|
|
id = ioc->pcidev->driver ?
|
|
ioc->pcidev->driver->id_table : NULL;
|
|
if (dd_cbfunc->probe)
|
|
@@ -914,7 +929,8 @@ mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER
|
|
|
|
DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
|
|
|
|
- mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
|
|
+ mf_dma_addr = (ioc->req_frames_low_dma + req_offset) |
|
|
+ ioc->RequestNB[req_idx];
|
|
dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d "
|
|
"RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx,
|
|
ioc->RequestNB[req_idx]));
|
|
@@ -1023,7 +1039,8 @@ mpt_add_sge_64bit(void *pAddr, u32 flags
|
|
}
|
|
|
|
/**
|
|
- * mpt_add_sge_64bit_1078 - Place a simple 64 bit SGE at address pAddr (1078 workaround).
|
|
+ * mpt_add_sge_64bit_1078 - Place a simple 64 bit SGE at address pAddr
|
|
+ * (1078 workaround).
|
|
* @pAddr: virtual address for SGE
|
|
* @flagslength: SGE flags and data transfer length
|
|
* @dma_addr: Physical address
|
|
@@ -1140,7 +1157,7 @@ mpt_send_handshake_request(u8 cb_idx, MP
|
|
* is in proper (pre-alloc'd) request buffer range...
|
|
*/
|
|
ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
|
|
- if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
|
|
+ if (ii >= 0 && ii < ioc->req_depth) {
|
|
MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
|
|
mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
|
|
mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
|
|
@@ -1582,6 +1599,7 @@ mpt_get_product_name(u16 vendor, u16 dev
|
|
* @ioc: Pointer to pointer to IOC adapter
|
|
*
|
|
**/
|
|
+#define convert_to_kb(x) ((x) << (PAGE_SHIFT - 10))
|
|
static int
|
|
mpt_mapresources(MPT_ADAPTER *ioc)
|
|
{
|
|
@@ -1591,9 +1609,9 @@ mpt_mapresources(MPT_ADAPTER *ioc)
|
|
unsigned long port;
|
|
u32 msize;
|
|
u32 psize;
|
|
- u8 revision;
|
|
int r = -ENODEV;
|
|
struct pci_dev *pdev;
|
|
+ struct sysinfo s;
|
|
|
|
pdev = ioc->pcidev;
|
|
ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
|
|
@@ -1608,22 +1626,21 @@ mpt_mapresources(MPT_ADAPTER *ioc)
|
|
return r;
|
|
}
|
|
|
|
- pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
|
|
-
|
|
if (sizeof(dma_addr_t) > 4) {
|
|
- const uint64_t required_mask = dma_get_required_mask
|
|
- (&pdev->dev);
|
|
+ uint64_t required_mask;
|
|
+
|
|
+ required_mask = dma_get_required_mask(&pdev->dev);
|
|
+
|
|
if (required_mask > DMA_BIT_MASK(32)
|
|
&& !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
|
|
&& !pci_set_consistent_dma_mask(pdev,
|
|
- DMA_BIT_MASK(64))) {
|
|
+ DMA_BIT_MASK(64))) {
|
|
ioc->dma_mask = DMA_BIT_MASK(64);
|
|
dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
|
|
": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
|
|
ioc->name));
|
|
} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
|
|
- && !pci_set_consistent_dma_mask(pdev,
|
|
- DMA_BIT_MASK(32))) {
|
|
+ && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
|
|
ioc->dma_mask = DMA_BIT_MASK(32);
|
|
dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
|
|
": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
|
|
@@ -1635,8 +1652,7 @@ mpt_mapresources(MPT_ADAPTER *ioc)
|
|
}
|
|
} else {
|
|
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
|
|
- && !pci_set_consistent_dma_mask(pdev,
|
|
- DMA_BIT_MASK(32))) {
|
|
+ && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
|
|
ioc->dma_mask = DMA_BIT_MASK(32);
|
|
dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
|
|
": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
|
|
@@ -1648,6 +1664,11 @@ mpt_mapresources(MPT_ADAPTER *ioc)
|
|
}
|
|
}
|
|
|
|
+ si_meminfo(&s);
|
|
+ printk(MYIOC_s_INFO_FMT "%s BIT PCI BUS DMA ADDRESSING SUPPORTED, "
|
|
+ "total memory = %ld kB\n",
|
|
+ ioc->name, ioc->dma_mask == DMA_BIT_MASK(64) ? "64" : "32",
|
|
+ convert_to_kb(s.totalram));
|
|
mem_phys = msize = 0;
|
|
port = psize = 0;
|
|
for (ii = 0; ii < DEVICE_COUNT_RESOURCE; ii++) {
|
|
@@ -1804,7 +1825,6 @@ mpt_attach(struct pci_dev *pdev, const s
|
|
/* Find lookup slot. */
|
|
INIT_LIST_HEAD(&ioc->list);
|
|
|
|
-
|
|
/* Initialize workqueue */
|
|
INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
|
|
|
|
@@ -1841,14 +1861,14 @@ mpt_attach(struct pci_dev *pdev, const s
|
|
case MPI_MANUFACTPAGE_DEVICEID_FC929X:
|
|
if (revision < XL_929) {
|
|
/* 929X Chip Fix. Set Split transactions level
|
|
- * for PCIX. Set MOST bits to zero.
|
|
- */
|
|
+ * for PCIX. Set MOST bits to zero.
|
|
+ */
|
|
pci_read_config_byte(pdev, 0x6a, &pcixcmd);
|
|
pcixcmd &= 0x8F;
|
|
pci_write_config_byte(pdev, 0x6a, pcixcmd);
|
|
} else {
|
|
/* 929XL Chip Fix. Set MMRBC to 0x08.
|
|
- */
|
|
+ */
|
|
pci_read_config_byte(pdev, 0x6a, &pcixcmd);
|
|
pcixcmd |= 0x08;
|
|
pci_write_config_byte(pdev, 0x6a, pcixcmd);
|
|
@@ -1948,7 +1968,6 @@ mpt_attach(struct pci_dev *pdev, const s
|
|
iounmap(ioc->memmap);
|
|
if (r != -5)
|
|
pci_release_selected_regions(pdev, ioc->bars);
|
|
-
|
|
destroy_workqueue(ioc->reset_work_q);
|
|
ioc->reset_work_q = NULL;
|
|
|
|
@@ -2000,7 +2019,7 @@ mpt_attach(struct pci_dev *pdev, const s
|
|
void
|
|
mpt_detach(struct pci_dev *pdev)
|
|
{
|
|
- MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
|
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
|
char pname[32];
|
|
u8 cb_idx;
|
|
unsigned long flags;
|
|
@@ -2273,6 +2292,15 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
|
|
/* hard_reset_done = 0 if a soft reset was performed
|
|
* and 1 if a hard reset was performed.
|
|
*/
|
|
+ if (!hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
|
|
+ /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
|
|
+ dprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": alt-ioc reply irq re-enabled\n",
|
|
+ ioc->alt_ioc->name));
|
|
+ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
|
|
+ ioc->alt_ioc->active = 1;
|
|
+ reset_alt_ioc_active = 0;
|
|
+ }
|
|
+
|
|
if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
|
|
if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
|
|
alt_ioc_ready = 1;
|
|
@@ -2472,7 +2500,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
|
|
/*
|
|
* Initalize link list for inactive raid volumes.
|
|
*/
|
|
- mutex_init(&ioc->raid_data.inactive_list_mutex);
|
|
+ init_MUTEX(&ioc->raid_data.inactive_list_mutex);
|
|
INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
|
|
|
|
switch (ioc->bus_type) {
|
|
@@ -2641,13 +2669,12 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
|
|
if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY)
|
|
printk(MYIOC_s_ERR_FMT "%s: IOC msg unit "
|
|
"reset failed to put ioc in ready state!\n",
|
|
- ioc->name, __func__);
|
|
+ ioc->name, __FUNCTION__);
|
|
} else
|
|
printk(MYIOC_s_ERR_FMT "%s: IOC msg unit reset "
|
|
- "failed!\n", ioc->name, __func__);
|
|
+ "failed!\n", ioc->name, __FUNCTION__);
|
|
}
|
|
|
|
-
|
|
/* Disable adapter interrupts! */
|
|
synchronize_irq(ioc->pcidev->irq);
|
|
CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
|
|
@@ -2690,8 +2717,10 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
|
|
mpt_inactive_raid_list_free(ioc);
|
|
kfree(ioc->raid_data.pIocPg2);
|
|
kfree(ioc->raid_data.pIocPg3);
|
|
+ kfree(ioc->raid_data.pIocPg6);
|
|
ioc->spi_data.nvram = NULL;
|
|
ioc->raid_data.pIocPg3 = NULL;
|
|
+ ioc->raid_data.pIocPg6 = NULL;
|
|
|
|
if (ioc->spi_data.pIocPg4 != NULL) {
|
|
sz = ioc->spi_data.IocPg4Sz;
|
|
@@ -2882,6 +2911,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
|
|
*/
|
|
if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
|
|
statefault = 2;
|
|
+ ioc->is_fault = 1;
|
|
printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
|
|
ioc->name);
|
|
printk(MYIOC_s_WARN_FMT " FAULT code = %04xh\n",
|
|
@@ -3066,6 +3096,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
|
|
}
|
|
|
|
facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
|
|
+ if (facts->MsgVersion == MPI_VERSION_01_05)
|
|
+ facts->HeaderVersion = le16_to_cpu(facts->HeaderVersion);
|
|
facts->MsgContext = le32_to_cpu(facts->MsgContext);
|
|
facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
|
|
facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
|
|
@@ -3301,7 +3333,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepF
|
|
if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
|
|
// set MsgVersion and HeaderVersion host driver was built with
|
|
ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
|
|
- ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
|
|
+ ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
|
|
|
|
if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
|
|
ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
|
|
@@ -3516,13 +3548,15 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
|
|
u32 flagsLength;
|
|
int ii, sz, reply_sz;
|
|
int cmdStatus;
|
|
- int request_size;
|
|
+ int request_size;
|
|
+
|
|
/* If the image size is 0, we are done.
|
|
*/
|
|
- if ((sz = ioc->facts.FWImageSize) == 0)
|
|
+ sz = ioc->facts.FWImageSize;
|
|
+ if (!sz)
|
|
return 0;
|
|
|
|
- if (mpt_alloc_fw_memory(ioc, ioc->facts.FWImageSize) != 0)
|
|
+ if (mpt_alloc_fw_memory(ioc, sz) != 0)
|
|
return -ENOMEM;
|
|
|
|
dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
|
|
@@ -3557,7 +3591,7 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
|
|
ioc->SGE_size;
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending FW Upload "
|
|
" (req @ %p) fw_size=%d mf_request_size=%d\n", ioc->name, prequest,
|
|
- ioc->facts.FWImageSize, request_size));
|
|
+ sz, request_size));
|
|
DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest);
|
|
|
|
ii = mpt_handshake_req_reply_wait(ioc, request_size, (u32 *)prequest,
|
|
@@ -3574,9 +3608,9 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
|
|
int status;
|
|
status = le16_to_cpu(preply->IOCStatus) &
|
|
MPI_IOCSTATUS_MASK;
|
|
- if (status == MPI_IOCSTATUS_SUCCESS &&
|
|
- ioc->facts.FWImageSize ==
|
|
- le32_to_cpu(preply->ActualImageSize))
|
|
+ if ((status == MPI_IOCSTATUS_SUCCESS) &&
|
|
+ (ioc->facts.FWImageSize ==
|
|
+ le32_to_cpu(preply->ActualImageSize)))
|
|
cmdStatus = 0;
|
|
}
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n",
|
|
@@ -3618,7 +3652,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
|
|
u32 diagRwData;
|
|
u32 nextImage;
|
|
u32 load_addr;
|
|
- u32 ioc_state=0;
|
|
+ u32 doorbell;
|
|
|
|
ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
|
|
ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
|
|
@@ -3672,6 +3706,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
|
|
CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
|
|
|
|
/* Set the DiagRwEn and Disable ARM bits */
|
|
+ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
|
|
CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
|
|
|
|
fwSize = (pFwHeader->ImageSize + 3)/4;
|
|
@@ -3713,11 +3748,13 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
|
|
}
|
|
|
|
/* Write the IopResetVectorRegAddr */
|
|
- ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr));
|
|
+ ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n",
|
|
+ ioc->name, pFwHeader->IopResetRegAddr));
|
|
CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
|
|
|
|
/* Write the IopResetVectorValue */
|
|
- ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
|
|
+ ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n",
|
|
+ ioc->name, pFwHeader->IopResetVectorValue));
|
|
CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
|
|
|
|
/* Clear the internal flash bad bit - autoincrementing register,
|
|
@@ -3734,17 +3771,6 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
|
|
CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
|
|
CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
|
|
|
|
- } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
|
|
- diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
|
|
- CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
|
|
- MPI_DIAG_CLEAR_FLASH_BAD_SIG);
|
|
-
|
|
- /* wait 1 msec */
|
|
- if (sleepFlag == CAN_SLEEP) {
|
|
- msleep (1);
|
|
- } else {
|
|
- mdelay (1);
|
|
- }
|
|
}
|
|
|
|
if (ioc->errata_flag_1064)
|
|
@@ -3754,51 +3780,64 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw
|
|
ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot diag0val=%x, "
|
|
"turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
|
|
ioc->name, diag0val));
|
|
- diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
|
|
+ diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM);
|
|
ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot now diag0val=%x\n",
|
|
ioc->name, diag0val));
|
|
CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
|
|
|
|
- /* Write 0xFF to reset the sequencer */
|
|
- CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
|
|
+ if (ioc->bus_type == SAS ) {
|
|
+ /* wait 1 sec */
|
|
+ if (sleepFlag == CAN_SLEEP)
|
|
+ msleep(1000);
|
|
+ else
|
|
+ mdelay(1000);
|
|
|
|
- if (ioc->bus_type == SAS) {
|
|
- ioc_state = mpt_GetIocState(ioc, 0);
|
|
- if ( (GetIocFacts(ioc, sleepFlag,
|
|
- MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
|
|
- ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "GetIocFacts failed: IocState=%x\n",
|
|
- ioc->name, ioc_state));
|
|
- return -EFAULT;
|
|
+ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
|
|
+ ddlprintk(ioc, printk (MYIOC_s_DEBUG_FMT
|
|
+ "diag0val=%x, turning off RW_ENABLE\n", ioc->name,
|
|
+ diag0val));
|
|
+ diag0val &= ~(MPI_DIAG_RW_ENABLE);
|
|
+ ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
+ "now diag0val=%x\n", ioc->name, diag0val));
|
|
+ CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
|
|
+
|
|
+ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
|
|
+ if (diag0val & MPI_DIAG_FLASH_BAD_SIG) {
|
|
+ diag0val |= MPI_DIAG_CLEAR_FLASH_BAD_SIG;
|
|
+ CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
|
|
+ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
|
|
}
|
|
+ diag0val &= ~(MPI_DIAG_DISABLE_ARM);
|
|
+ CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
|
|
+ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
|
|
+ CHIPREG_WRITE32(&ioc->chip->DiagRwAddress, 0x3f000004);
|
|
}
|
|
|
|
- for (count=0; count<HZ*20; count++) {
|
|
- if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
|
|
- ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- "downloadboot successful! (count=%d) IocState=%x\n",
|
|
- ioc->name, count, ioc_state));
|
|
- if (ioc->bus_type == SAS) {
|
|
+ /* Write 0xFF to reset the sequencer */
|
|
+ CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
|
|
+
|
|
+ for (count = 0; count < 30; count ++) {
|
|
+ doorbell = CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_IOC_STATE_MASK;
|
|
+ if (doorbell == MPI_IOC_STATE_READY) {
|
|
+ if (ioc->bus_type == SAS)
|
|
return 0;
|
|
- }
|
|
if ((SendIocInit(ioc, sleepFlag)) != 0) {
|
|
- ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- "downloadboot: SendIocInit failed\n",
|
|
- ioc->name));
|
|
+ ddlprintk(ioc, printk(MYIOC_s_WARN_FMT
|
|
+ "SendIocInit failed\n", ioc->name));
|
|
return -EFAULT;
|
|
}
|
|
ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- "downloadboot: SendIocInit successful\n",
|
|
- ioc->name));
|
|
+ "SendIocInit successful\n", ioc->name));
|
|
return 0;
|
|
}
|
|
- if (sleepFlag == CAN_SLEEP) {
|
|
- msleep (10);
|
|
- } else {
|
|
- mdelay (10);
|
|
- }
|
|
+ ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "looking for READY STATE:"
|
|
+ " doorbell=%x count=%d\n", ioc->name, doorbell, count));
|
|
+ if (sleepFlag == CAN_SLEEP)
|
|
+ msleep(1000);
|
|
+ else
|
|
+ mdelay(1000);
|
|
}
|
|
- ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- "downloadboot failed! IocState=%x\n",ioc->name, ioc_state));
|
|
+ ddlprintk(ioc, printk(MYIOC_s_WARN_FMT "downloadboot failed! count=%d\n", ioc->name, count));
|
|
return -EFAULT;
|
|
}
|
|
|
|
@@ -3853,6 +3892,7 @@ KickStart(MPT_ADAPTER *ioc, int force, i
|
|
if (hard_reset_done < 0)
|
|
return hard_reset_done;
|
|
|
|
+ /* may not have worked but hard_reset_done doesn't always signal failure */
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n",
|
|
ioc->name));
|
|
|
|
@@ -3861,7 +3901,7 @@ KickStart(MPT_ADAPTER *ioc, int force, i
|
|
ioc_state = mpt_GetIocState(ioc, 1);
|
|
if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStart successful! (cnt=%d)\n",
|
|
- ioc->name, cnt));
|
|
+ ioc->name, cnt));
|
|
return hard_reset_done;
|
|
}
|
|
if (sleepFlag == CAN_SLEEP) {
|
|
@@ -3899,7 +3939,7 @@ static int
|
|
mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
|
|
{
|
|
u32 diag0val;
|
|
- u32 doorbell;
|
|
+ u32 doorbell = 0;
|
|
int hard_reset_done = 0;
|
|
int count = 0;
|
|
u32 diag1val = 0;
|
|
@@ -3931,8 +3971,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
|
|
*/
|
|
for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
|
|
if (MptResetHandlers[cb_idx])
|
|
- (*(MptResetHandlers[cb_idx]))(ioc,
|
|
- MPT_IOC_PRE_RESET);
|
|
+ (*(MptResetHandlers[cb_idx]))(ioc, MPT_IOC_PRE_RESET);
|
|
}
|
|
|
|
for (count = 0; count < 60; count ++) {
|
|
@@ -3941,29 +3980,39 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
|
|
|
|
drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
"looking for READY STATE: doorbell=%x"
|
|
- " count=%d\n",
|
|
+ " count=%d\n",
|
|
ioc->name, doorbell, count));
|
|
|
|
if (doorbell == MPI_IOC_STATE_READY) {
|
|
return 1;
|
|
}
|
|
|
|
+ /*
|
|
+ * Early out for hard fault
|
|
+ */
|
|
+ if (count && doorbell == MPI_IOC_STATE_FAULT)
|
|
+ break;
|
|
+
|
|
/* wait 1 sec */
|
|
if (sleepFlag == CAN_SLEEP)
|
|
msleep(1000);
|
|
else
|
|
mdelay(1000);
|
|
}
|
|
+
|
|
+ if (doorbell != MPI_IOC_STATE_READY)
|
|
+ printk(MYIOC_s_ERR_FMT "Failed to come READY after "
|
|
+ "reset! IocState=%x", ioc->name, doorbell);
|
|
return -1;
|
|
}
|
|
|
|
/* Use "Diagnostic reset" method! (only thing available!) */
|
|
diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
|
|
|
|
- if (ioc->debug_level & MPT_DEBUG) {
|
|
+ if (ioc->debug_level & MPT_DEBUG_RESET) {
|
|
if (ioc->alt_ioc)
|
|
diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
|
|
- dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n",
|
|
+ drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n",
|
|
ioc->name, diag0val, diag1val));
|
|
}
|
|
|
|
@@ -3999,14 +4048,14 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
|
|
|
|
diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
|
|
|
|
- dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
|
|
+ drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
|
|
ioc->name, diag0val));
|
|
}
|
|
|
|
- if (ioc->debug_level & MPT_DEBUG) {
|
|
+ if (ioc->debug_level & MPT_DEBUG_RESET) {
|
|
if (ioc->alt_ioc)
|
|
diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
|
|
- dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n",
|
|
+ drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n",
|
|
ioc->name, diag0val, diag1val));
|
|
}
|
|
/*
|
|
@@ -4022,7 +4071,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
|
|
*/
|
|
CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
|
|
hard_reset_done = 1;
|
|
- dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n",
|
|
+ drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n",
|
|
ioc->name));
|
|
|
|
/*
|
|
@@ -4033,11 +4082,9 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
|
|
*/
|
|
for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
|
|
if (MptResetHandlers[cb_idx]) {
|
|
- mpt_signal_reset(cb_idx,
|
|
- ioc, MPT_IOC_PRE_RESET);
|
|
+ mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
|
|
if (ioc->alt_ioc) {
|
|
- mpt_signal_reset(cb_idx,
|
|
- ioc->alt_ioc, MPT_IOC_PRE_RESET);
|
|
+ mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_PRE_RESET);
|
|
}
|
|
}
|
|
}
|
|
@@ -4059,7 +4106,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
|
|
break;
|
|
}
|
|
|
|
- dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n",
|
|
+ drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n",
|
|
ioc->name, diag0val, count));
|
|
/* wait 1 sec */
|
|
if (sleepFlag == CAN_SLEEP) {
|
|
@@ -4092,6 +4139,12 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
|
|
break;
|
|
}
|
|
|
|
+ /*
|
|
+ * Early out for hard fault
|
|
+ */
|
|
+ if (count && doorbell == MPI_IOC_STATE_FAULT)
|
|
+ break;
|
|
+
|
|
/* wait 1 sec */
|
|
if (sleepFlag == CAN_SLEEP) {
|
|
msleep (1000);
|
|
@@ -4108,10 +4161,10 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
|
|
}
|
|
|
|
diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
|
|
- if (ioc->debug_level & MPT_DEBUG) {
|
|
+ if (ioc->debug_level & MPT_DEBUG_RESET) {
|
|
if (ioc->alt_ioc)
|
|
diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
|
|
- dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n",
|
|
+ drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n",
|
|
ioc->name, diag0val, diag1val));
|
|
}
|
|
|
|
@@ -4167,11 +4220,11 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
|
|
return -3;
|
|
}
|
|
|
|
- if (ioc->debug_level & MPT_DEBUG) {
|
|
+ if (ioc->debug_level & MPT_DEBUG_RESET) {
|
|
if (ioc->alt_ioc)
|
|
diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
|
|
- dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n",
|
|
- ioc->name, diag0val, diag1val));
|
|
+ drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n",
|
|
+ ioc->name, diag0val, diag1val));
|
|
}
|
|
|
|
/*
|
|
@@ -4207,7 +4260,7 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_
|
|
drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOC reset(0x%02x)!\n",
|
|
ioc->name, reset_type));
|
|
CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
|
|
- if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
|
|
+ if ((r = WaitForDoorbellAck(ioc, 15, sleepFlag)) < 0)
|
|
return r;
|
|
|
|
/* FW ACK'd request, wait for READY state
|
|
@@ -4258,7 +4311,7 @@ initChainBuffers(MPT_ADAPTER *ioc)
|
|
{
|
|
u8 *mem;
|
|
int sz, ii, num_chain;
|
|
- int scale, num_sge, numSGE;
|
|
+ int scale, num_sge, numSGE;
|
|
|
|
/* ReqToChain size must equal the req_depth
|
|
* index = req_idx
|
|
@@ -4271,14 +4324,14 @@ initChainBuffers(MPT_ADAPTER *ioc)
|
|
|
|
ioc->ReqToChain = (int *) mem;
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReqToChain alloc @ %p, sz=%d bytes\n",
|
|
- ioc->name, mem, sz));
|
|
+ ioc->name, mem, sz));
|
|
mem = kmalloc(sz, GFP_ATOMIC);
|
|
if (mem == NULL)
|
|
return -1;
|
|
|
|
ioc->RequestNB = (int *) mem;
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestNB alloc @ %p, sz=%d bytes\n",
|
|
- ioc->name, mem, sz));
|
|
+ ioc->name, mem, sz));
|
|
}
|
|
for (ii = 0; ii < ioc->req_depth; ii++) {
|
|
ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
|
|
@@ -4345,7 +4398,7 @@ initChainBuffers(MPT_ADAPTER *ioc)
|
|
|
|
ioc->ChainToChain = (int *) mem;
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainToChain alloc @ %p, sz=%d bytes\n",
|
|
- ioc->name, mem, sz));
|
|
+ ioc->name, mem, sz));
|
|
} else {
|
|
mem = (u8 *) ioc->ChainToChain;
|
|
}
|
|
@@ -4411,22 +4464,22 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
|
|
|
|
total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
|
|
- ioc->name, ioc->reply_sz, ioc->reply_depth));
|
|
+ ioc->name, ioc->reply_sz, ioc->reply_depth));
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d[%x] bytes\n",
|
|
- ioc->name, reply_sz, reply_sz));
|
|
+ ioc->name, reply_sz, reply_sz));
|
|
|
|
sz = (ioc->req_sz * ioc->req_depth);
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d bytes, RequestDepth=%d\n",
|
|
- ioc->name, ioc->req_sz, ioc->req_depth));
|
|
+ ioc->name, ioc->req_sz, ioc->req_depth));
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d[%x] bytes\n",
|
|
- ioc->name, sz, sz));
|
|
+ ioc->name, sz, sz));
|
|
total_size += sz;
|
|
|
|
sz = num_chain * ioc->req_sz; /* chain buffer pool size */
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d bytes, ChainDepth=%d\n",
|
|
- ioc->name, ioc->req_sz, num_chain));
|
|
+ ioc->name, ioc->req_sz, num_chain));
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
|
|
- ioc->name, sz, sz, num_chain));
|
|
+ ioc->name, sz, sz, num_chain));
|
|
|
|
total_size += sz;
|
|
mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
|
|
@@ -4437,7 +4490,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
|
|
}
|
|
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Total alloc @ %p[%p], sz=%d[%x] bytes\n",
|
|
- ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
|
|
+ ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
|
|
|
|
memset(mem, 0, total_size);
|
|
ioc->alloc_total += total_size;
|
|
@@ -4448,7 +4501,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
|
|
ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
|
|
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
|
|
- ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
|
|
+ ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
|
|
|
|
alloc_dma += reply_sz;
|
|
mem += reply_sz;
|
|
@@ -4459,7 +4512,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
|
|
ioc->req_frames_dma = alloc_dma;
|
|
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffers @ %p[%p]\n",
|
|
- ioc->name, mem, (void *)(ulong)alloc_dma));
|
|
+ ioc->name, mem, (void *)(ulong)alloc_dma));
|
|
|
|
ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
|
|
|
|
@@ -4487,13 +4540,11 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffers @ %p(%p)\n",
|
|
ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
|
|
|
|
- /* Initialize the free chain Q.
|
|
- */
|
|
+ /* Initialize the free chain Q. */
|
|
|
|
INIT_LIST_HEAD(&ioc->FreeChainQ);
|
|
|
|
- /* Post the chain buffers to the FreeChainQ.
|
|
- */
|
|
+ /* Post the chain buffers to the FreeChainQ. */
|
|
mem = (u8 *)ioc->ChainBuffer;
|
|
for (i=0; i < num_chain; i++) {
|
|
mf = (MPT_FRAME_HDR *) mem;
|
|
@@ -4530,15 +4581,14 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
|
|
ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
|
|
ioc->alloc_total += sz;
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SenseBuffers @ %p[%p]\n",
|
|
- ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
|
|
+ ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
|
|
|
|
}
|
|
|
|
- /* Post Reply frames to FIFO
|
|
- */
|
|
+ /* Post Reply frames to FIFO */
|
|
alloc_dma = ioc->alloc_dma;
|
|
dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
|
|
- ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
|
|
+ ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
|
|
|
|
for (i = 0; i < ioc->reply_depth; i++) {
|
|
/* Write each address to the IOC! */
|
|
@@ -4767,18 +4817,18 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int
|
|
cntdn = 1000 * howlong;
|
|
if (sleepFlag == CAN_SLEEP) {
|
|
while (--cntdn) {
|
|
+ msleep(1);
|
|
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
|
|
if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
|
|
break;
|
|
- msleep(1);
|
|
count++;
|
|
}
|
|
} else {
|
|
while (--cntdn) {
|
|
+ udelay (1000);
|
|
intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
|
|
if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
|
|
break;
|
|
- udelay (1000);
|
|
count++;
|
|
}
|
|
}
|
|
@@ -5015,7 +5065,7 @@ mptbase_sas_persist_operation(MPT_ADAPTE
|
|
MPT_FRAME_HDR *mf = NULL;
|
|
MPIHeader_t *mpi_hdr;
|
|
int ret = 0;
|
|
- unsigned long timeleft;
|
|
+ unsigned long timeleft;
|
|
|
|
mutex_lock(&ioc->mptbase_cmds.mutex);
|
|
|
|
@@ -5044,7 +5094,7 @@ mptbase_sas_persist_operation(MPT_ADAPTE
|
|
printk(KERN_DEBUG "%s: no msg frames!\n", __func__);
|
|
ret = -1;
|
|
goto out;
|
|
- }
|
|
+ }
|
|
|
|
mpi_hdr = (MPIHeader_t *) mf;
|
|
sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
|
|
@@ -5063,7 +5113,8 @@ mptbase_sas_persist_operation(MPT_ADAPTE
|
|
if (!timeleft) {
|
|
printk(KERN_DEBUG "%s: Issuing Reset from %s!!\n",
|
|
ioc->name, __func__);
|
|
- mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
+ if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
|
|
+ mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
mpt_free_msg_frame(ioc, mf);
|
|
}
|
|
goto out;
|
|
@@ -5097,12 +5148,12 @@ static void
|
|
mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
|
|
MpiEventDataRaid_t * pRaidEventData)
|
|
{
|
|
- int volume;
|
|
- int reason;
|
|
- int disk;
|
|
- int status;
|
|
- int flags;
|
|
- int state;
|
|
+ int volume;
|
|
+ int reason;
|
|
+ int disk;
|
|
+ int status;
|
|
+ int flags;
|
|
+ int state;
|
|
|
|
volume = pRaidEventData->VolumeID;
|
|
reason = pRaidEventData->ReasonCode;
|
|
@@ -5198,8 +5249,8 @@ mptbase_raid_process_event_data(MPT_ADAP
|
|
: state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
|
|
? "failed requested"
|
|
: state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
|
|
- ? "offline"
|
|
- : "state unknown",
|
|
+ ? "offline"
|
|
+ : "state unknown",
|
|
flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
|
|
? ", out of sync" : "",
|
|
flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
|
|
@@ -5477,7 +5528,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
|
|
*/
|
|
ioc->spi_data.bus_reset =
|
|
(le32_to_cpu(pPP2->PortFlags) &
|
|
- MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
|
|
+ MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
|
|
0 : 1 ;
|
|
|
|
/* Save the Port Page 2 data
|
|
@@ -5556,6 +5607,69 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTE
|
|
return 0;
|
|
}
|
|
|
|
+static void
|
|
+mpt_read_ioc_pg_6(MPT_ADAPTER *ioc)
|
|
+{
|
|
+ CONFIGPARMS cfg;
|
|
+ ConfigPageHeader_t header;
|
|
+ IOCPage6_t *pIoc6=NULL;
|
|
+ dma_addr_t ioc6_dma;
|
|
+ int iocpage6sz;
|
|
+ void *mem;
|
|
+
|
|
+ /* Free the old page
|
|
+ */
|
|
+ if (ioc->raid_data.pIocPg6) {
|
|
+ kfree(ioc->raid_data.pIocPg6);
|
|
+ ioc->raid_data.pIocPg6 = NULL;
|
|
+ }
|
|
+
|
|
+ /* There is at least one physical disk.
|
|
+ * Read and save IOC Page 3
|
|
+ */
|
|
+ header.PageVersion = 0;
|
|
+ header.PageLength = 0;
|
|
+ header.PageNumber = 6;
|
|
+ header.PageType = MPI_CONFIG_PAGETYPE_IOC;
|
|
+ cfg.cfghdr.hdr = &header;
|
|
+ cfg.physAddr = -1;
|
|
+ cfg.pageAddr = 0;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.dir = 0;
|
|
+ cfg.timeout = 0;
|
|
+ if (mpt_config(ioc, &cfg) != 0)
|
|
+ goto out;
|
|
+
|
|
+ if (header.PageLength == 0)
|
|
+ goto out;
|
|
+
|
|
+ /* Read Header good, alloc memory
|
|
+ */
|
|
+ iocpage6sz = header.PageLength * 4;
|
|
+ pIoc6 = pci_alloc_consistent(ioc->pcidev, iocpage6sz, &ioc6_dma);
|
|
+ if (!pIoc6)
|
|
+ goto out;
|
|
+
|
|
+ /* Read the Page and save the data
|
|
+ * into malloc'd memory.
|
|
+ */
|
|
+ cfg.physAddr = ioc6_dma;
|
|
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
+ if (mpt_config(ioc, &cfg) != 0)
|
|
+ goto out;
|
|
+
|
|
+ mem = kmalloc(iocpage6sz, GFP_ATOMIC);
|
|
+ if (!mem)
|
|
+ goto out;
|
|
+
|
|
+ memcpy(mem, pIoc6, iocpage6sz);
|
|
+ ioc->raid_data.pIocPg6 = mem;
|
|
+
|
|
+ out:
|
|
+ if (pIoc6)
|
|
+ pci_free_consistent(ioc->pcidev, iocpage6sz, pIoc6, ioc6_dma);
|
|
+}
|
|
+
|
|
/**
|
|
* mpt_inactive_raid_list_free - This clears this link list.
|
|
* @ioc : pointer to per adapter structure
|
|
@@ -5568,13 +5682,13 @@ mpt_inactive_raid_list_free(MPT_ADAPTER
|
|
if (list_empty(&ioc->raid_data.inactive_list))
|
|
return;
|
|
|
|
- mutex_lock(&ioc->raid_data.inactive_list_mutex);
|
|
+ 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);
|
|
}
|
|
- mutex_unlock(&ioc->raid_data.inactive_list_mutex);
|
|
+ up(&ioc->raid_data.inactive_list_mutex);
|
|
}
|
|
|
|
/**
|
|
@@ -5591,10 +5705,12 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *i
|
|
ConfigPageHeader_t hdr;
|
|
dma_addr_t dma_handle;
|
|
pRaidVolumePage0_t buffer = NULL;
|
|
- int i;
|
|
- RaidPhysDiskPage0_t phys_disk;
|
|
+ int i, j;
|
|
+ RaidPhysDiskPage0_t phys_disk;
|
|
+ RaidPhysDiskPage1_t *phys_disk_1;
|
|
struct inactive_raid_component_info *component_info;
|
|
int handle_inactive_volumes;
|
|
+ int num_paths, device_is_online;
|
|
|
|
memset(&cfg, 0 , sizeof(CONFIGPARMS));
|
|
memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
|
|
@@ -5633,12 +5749,35 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *i
|
|
if (!handle_inactive_volumes)
|
|
goto out;
|
|
|
|
- mutex_lock(&ioc->raid_data.inactive_list_mutex);
|
|
+ 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 (phys_disk.PhysDiskStatus.State !=
|
|
+ MPI_PHYSDISK0_STATUS_ONLINE)
|
|
+ continue;
|
|
+
|
|
+ /* check to see if device is online by checking phys_disk_pg1 */
|
|
+ device_is_online = 0;
|
|
+ num_paths = mpt_raid_phys_disk_get_num_paths(ioc,
|
|
+ buffer->PhysDisk[i].PhysDiskNum);
|
|
+ if (num_paths < 2)
|
|
+ continue;
|
|
+ phys_disk_1 = kzalloc(offsetof(RaidPhysDiskPage1_t,Path) +
|
|
+ (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
|
|
+ if (!phys_disk_1)
|
|
+ continue;
|
|
+ mpt_raid_phys_disk_pg1(ioc, buffer->PhysDisk[i].PhysDiskNum,
|
|
+ phys_disk_1);
|
|
+ for (j = 0; j < num_paths && !device_is_online; j++)
|
|
+ if (!phys_disk_1->Path[j].Flags)
|
|
+ device_is_online = 1;
|
|
+ kfree(phys_disk_1);
|
|
+ if (!device_is_online)
|
|
+ continue;
|
|
+
|
|
if ((component_info = kmalloc(sizeof (*component_info),
|
|
GFP_KERNEL)) == NULL)
|
|
continue;
|
|
@@ -5653,7 +5792,7 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *i
|
|
list_add_tail(&component_info->list,
|
|
&ioc->raid_data.inactive_list);
|
|
}
|
|
- mutex_unlock(&ioc->raid_data.inactive_list_mutex);
|
|
+ up(&ioc->raid_data.inactive_list_mutex);
|
|
|
|
out:
|
|
if (buffer)
|
|
@@ -5743,8 +5882,8 @@ mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc,
|
|
int
|
|
mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, u8 phys_disk_num)
|
|
{
|
|
- CONFIGPARMS cfg;
|
|
- ConfigPageHeader_t hdr;
|
|
+ CONFIGPARMS cfg;
|
|
+ ConfigPageHeader_t hdr;
|
|
dma_addr_t dma_handle;
|
|
pRaidPhysDiskPage1_t buffer = NULL;
|
|
int rc;
|
|
@@ -5795,7 +5934,6 @@ mpt_raid_phys_disk_get_num_paths(MPT_ADA
|
|
|
|
return rc;
|
|
}
|
|
-EXPORT_SYMBOL(mpt_raid_phys_disk_get_num_paths);
|
|
|
|
/**
|
|
* mpt_raid_phys_disk_pg1 - returns phys disk page 1
|
|
@@ -5809,11 +5947,10 @@ EXPORT_SYMBOL(mpt_raid_phys_disk_get_num
|
|
* -ENOMEM if pci_alloc failed
|
|
**/
|
|
int
|
|
-mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num,
|
|
- RaidPhysDiskPage1_t *phys_disk)
|
|
+mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num, RaidPhysDiskPage1_t *phys_disk)
|
|
{
|
|
- CONFIGPARMS cfg;
|
|
- ConfigPageHeader_t hdr;
|
|
+ CONFIGPARMS cfg;
|
|
+ ConfigPageHeader_t hdr;
|
|
dma_addr_t dma_handle;
|
|
pRaidPhysDiskPage1_t buffer = NULL;
|
|
int rc;
|
|
@@ -5863,17 +6000,14 @@ mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc,
|
|
for (i = 0; i < phys_disk->NumPhysDiskPaths; i++) {
|
|
phys_disk->Path[i].PhysDiskID = buffer->Path[i].PhysDiskID;
|
|
phys_disk->Path[i].PhysDiskBus = buffer->Path[i].PhysDiskBus;
|
|
- phys_disk->Path[i].OwnerIdentifier =
|
|
- buffer->Path[i].OwnerIdentifier;
|
|
+ phys_disk->Path[i].OwnerIdentifier = buffer->Path[i].OwnerIdentifier;
|
|
phys_disk->Path[i].Flags = le16_to_cpu(buffer->Path[i].Flags);
|
|
memcpy(&sas_address, &buffer->Path[i].WWID, sizeof(__le64));
|
|
sas_address = le64_to_cpu(sas_address);
|
|
memcpy(&phys_disk->Path[i].WWID, &sas_address, sizeof(__le64));
|
|
- memcpy(&sas_address,
|
|
- &buffer->Path[i].OwnerWWID, sizeof(__le64));
|
|
+ memcpy(&sas_address, &buffer->Path[i].OwnerWWID, sizeof(__le64));
|
|
sas_address = le64_to_cpu(sas_address);
|
|
- memcpy(&phys_disk->Path[i].OwnerWWID,
|
|
- &sas_address, sizeof(__le64));
|
|
+ memcpy(&phys_disk->Path[i].OwnerWWID, &sas_address, sizeof(__le64));
|
|
}
|
|
|
|
out:
|
|
@@ -5884,8 +6018,33 @@ mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc,
|
|
|
|
return rc;
|
|
}
|
|
-EXPORT_SYMBOL(mpt_raid_phys_disk_pg1);
|
|
|
|
+/**
|
|
+ * mpt_sort_ioc_pg2 - compare function for sorting volumes
|
|
+ * in ascending order
|
|
+ * @a: ioc_pg2 raid volume page
|
|
+ * @b: ioc_pg2 raid volume page
|
|
+ *
|
|
+ * Return:
|
|
+ * 0 same, 1 (a is bigger), -1 (b is bigger)
|
|
+ **/
|
|
+static int
|
|
+mpt_sort_ioc_pg2(const void *a, const void *b)
|
|
+{
|
|
+ ConfigPageIoc2RaidVol_t * volume_a = (ConfigPageIoc2RaidVol_t *)a;
|
|
+ ConfigPageIoc2RaidVol_t * volume_b = (ConfigPageIoc2RaidVol_t *)b;
|
|
+
|
|
+ if (volume_a->VolumeBus == volume_b->VolumeBus) {
|
|
+ if (volume_a->VolumeID == volume_b->VolumeID)
|
|
+ return 0;
|
|
+ if (volume_a->VolumeID < volume_b->VolumeID)
|
|
+ return -1;
|
|
+ return 1;
|
|
+ }
|
|
+ if (volume_a->VolumeBus < volume_b->VolumeBus)
|
|
+ return -1;
|
|
+ return 1;
|
|
+}
|
|
|
|
/**
|
|
* mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
|
|
@@ -5949,16 +6108,22 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
|
|
if (!mem)
|
|
goto out;
|
|
|
|
+ /*
|
|
+ * sort volumes in ascending order
|
|
+ */
|
|
+ sort(pIoc2->RaidVolume, pIoc2->NumActiveVolumes,
|
|
+ sizeof(ConfigPageIoc2RaidVol_t), mpt_sort_ioc_pg2, NULL);
|
|
memcpy(mem, (u8 *)pIoc2, iocpage2sz);
|
|
ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
|
|
|
|
- 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);
|
|
|
|
+ mpt_read_ioc_pg_3(ioc);
|
|
+ mpt_read_ioc_pg_6(ioc);
|
|
+
|
|
out:
|
|
pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
|
|
|
|
@@ -6118,6 +6283,9 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
|
|
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
if (mpt_config(ioc, &cfg) == 0) {
|
|
|
|
+#if defined(CPQ_CIM)
|
|
+ ioc->pci_slot_number = pIoc1->PCISlotNum;
|
|
+#endif
|
|
tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
|
|
if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
|
|
tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
|
|
@@ -6294,9 +6462,9 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS
|
|
long timeout;
|
|
int ret;
|
|
u8 page_type = 0, extend_page;
|
|
- unsigned long timeleft;
|
|
+ unsigned long timeleft;
|
|
unsigned long flags;
|
|
- int in_isr;
|
|
+ int in_isr;
|
|
u8 issue_hard_reset = 0;
|
|
u8 retry_count = 0;
|
|
|
|
@@ -6308,7 +6476,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS
|
|
dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
|
|
ioc->name));
|
|
return -EPERM;
|
|
- }
|
|
+ }
|
|
|
|
/* don't send a config page during diag reset */
|
|
spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
|
|
@@ -6447,7 +6615,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS
|
|
dcprintk(ioc, printk(KERN_DEBUG "IOCStatus=%04xh, IOCLogInfo=%08xh\n",
|
|
ret, le32_to_cpu(pReply->IOCLogInfo)));
|
|
|
|
-out:
|
|
+ out:
|
|
|
|
CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status)
|
|
mutex_unlock(&ioc->mptbase_cmds.mutex);
|
|
@@ -6455,7 +6623,8 @@ out:
|
|
issue_hard_reset = 0;
|
|
printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
|
|
ioc->name, __func__);
|
|
- mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
+ if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
|
|
+ mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
mpt_free_msg_frame(ioc, mf);
|
|
/* attempt one retry for a timed out command */
|
|
if (!retry_count) {
|
|
@@ -6469,7 +6638,6 @@ out:
|
|
}
|
|
}
|
|
return ret;
|
|
-
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
@@ -6823,7 +6991,7 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc,
|
|
*size = y;
|
|
}
|
|
/**
|
|
- * mpt_set_taskmgmt_in_progress_flag - set flags associated with task management
|
|
+ * mpt_set_taskmgmt_in_progress_flag - set flags associated with task managment
|
|
* @ioc: Pointer to MPT_ADAPTER structure
|
|
*
|
|
* Returns 0 for SUCCESS or -1 if FAILED.
|
|
@@ -6840,6 +7008,7 @@ mpt_set_taskmgmt_in_progress_flag(MPT_AD
|
|
if (ioc->ioc_reset_in_progress || ioc->taskmgmt_in_progress ||
|
|
(ioc->alt_ioc && ioc->alt_ioc->taskmgmt_in_progress)) {
|
|
retval = -1;
|
|
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
goto out;
|
|
}
|
|
retval = 0;
|
|
@@ -6849,14 +7018,14 @@ mpt_set_taskmgmt_in_progress_flag(MPT_AD
|
|
ioc->alt_ioc->taskmgmt_in_progress = 1;
|
|
ioc->alt_ioc->taskmgmt_quiesce_io = 1;
|
|
}
|
|
- out:
|
|
spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
+
|
|
+ out:
|
|
return retval;
|
|
}
|
|
-EXPORT_SYMBOL(mpt_set_taskmgmt_in_progress_flag);
|
|
|
|
/**
|
|
- * mpt_clear_taskmgmt_in_progress_flag - clear flags associated with task management
|
|
+ * mpt_clear_taskmgmt_in_progress_flag - clear flags associated with task managment
|
|
* @ioc: Pointer to MPT_ADAPTER structure
|
|
*
|
|
**/
|
|
@@ -6874,8 +7043,6 @@ mpt_clear_taskmgmt_in_progress_flag(MPT_
|
|
}
|
|
spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
}
|
|
-EXPORT_SYMBOL(mpt_clear_taskmgmt_in_progress_flag);
|
|
-
|
|
|
|
/**
|
|
* mpt_halt_firmware - Halts the firmware if it is operational and panic
|
|
@@ -6893,20 +7060,173 @@ mpt_halt_firmware(MPT_ADAPTER *ioc)
|
|
if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
|
|
printk(MYIOC_s_ERR_FMT "IOC is in FAULT state (%04xh)!!!\n",
|
|
ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
|
|
+ if(mpt_fwfault_debug == 2)
|
|
+ for(;;);
|
|
+ else
|
|
panic("%s: IOC Fault (%04xh)!!!\n", ioc->name,
|
|
ioc_raw_state & MPI_DOORBELL_DATA_MASK);
|
|
} else {
|
|
CHIPREG_WRITE32(&ioc->chip->Doorbell, 0xC0FFEE00);
|
|
- panic("%s: Firmware is halted due to command timeout\n",
|
|
- ioc->name);
|
|
+ if(mpt_fwfault_debug == 2) {
|
|
+ printk("%s: Firmware is halted due to command timeout\n"
|
|
+ ,ioc->name);
|
|
+ for(;;);
|
|
+ }
|
|
+ else
|
|
+ panic("%s: Firmware is halted due to command timeout\n",
|
|
+ ioc->name);
|
|
}
|
|
}
|
|
-EXPORT_SYMBOL(mpt_halt_firmware);
|
|
|
|
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
-/*
|
|
- * Reset Handling
|
|
- */
|
|
+/**
|
|
+ * mpt_SoftResetHandler - Issues a less expensive reset
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @sleepFlag: Indicates if sleep or schedule must be called.
|
|
+
|
|
+ *
|
|
+ * Returns 0 for SUCCESS or -1 if FAILED.
|
|
+ *
|
|
+ * Message Unit Reset - instructs the IOC to reset the Reply Post and
|
|
+ * Free FIFO's. All the Message Frames on Reply Free FIFO are discarded.
|
|
+ * All posted buffers are freed, and event notification is turned off.
|
|
+ * IOC doesnt reply to any outstanding request. This will transfer IOC
|
|
+ * to READY state.
|
|
+ **/
|
|
+int
|
|
+mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
|
|
+{
|
|
+ int rc;
|
|
+ int ii;
|
|
+ u8 cb_idx;
|
|
+ unsigned long flags;
|
|
+ u32 ioc_state;
|
|
+ unsigned long time_count;
|
|
+ int i;
|
|
+
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SoftResetHandler Entered!\n", ioc->name));
|
|
+
|
|
+ ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK;
|
|
+
|
|
+ if(mpt_fwfault_debug)
|
|
+ mpt_halt_firmware(ioc);
|
|
+
|
|
+ if (ioc_state == MPI_IOC_STATE_FAULT || ioc_state == MPI_IOC_STATE_RESET) {
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
+ "skipping, either in FAULT or RESET state!\n", ioc->name));
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (ioc->bus_type == FC) {
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
+ "skipping, because the bus type is FC!\n", ioc->name));
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
|
|
+ if (ioc->ioc_reset_in_progress) {
|
|
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
+ return -1;
|
|
+ }
|
|
+ ioc->ioc_reset_in_progress = 1;
|
|
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
+
|
|
+ rc = -1;
|
|
+
|
|
+ for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
|
|
+ if (MptResetHandlers[cb_idx])
|
|
+ mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
|
|
+ }
|
|
+
|
|
+ spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
|
|
+ if (ioc->taskmgmt_in_progress) {
|
|
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
+ return -1;
|
|
+ }
|
|
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
+ /* Disable reply interrupts (also blocks FreeQ) */
|
|
+ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
|
|
+ ioc->active = 0;
|
|
+ time_count = jiffies;
|
|
+
|
|
+ rc = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
|
|
+
|
|
+ for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
|
|
+ if (MptResetHandlers[cb_idx])
|
|
+ mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
|
|
+ }
|
|
+
|
|
+ if (rc)
|
|
+ goto out;
|
|
+
|
|
+ ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK;
|
|
+ if (ioc_state != MPI_IOC_STATE_READY)
|
|
+ goto out;
|
|
+
|
|
+ for (ii = 0; ii < 5; ii++) {
|
|
+ /* Get IOC facts! Allow 5 retries */
|
|
+ if ((rc = GetIocFacts(ioc, sleepFlag,
|
|
+ MPT_HOSTEVENT_IOC_RECOVER)) == 0)
|
|
+ break;
|
|
+ if (sleepFlag == CAN_SLEEP) {
|
|
+ msleep(100);
|
|
+ } else {
|
|
+ mdelay(100);
|
|
+ }
|
|
+ }
|
|
+ if (ii == 5)
|
|
+ goto out;
|
|
+
|
|
+ if ((rc = PrimeIocFifos(ioc)) != 0)
|
|
+ goto out;
|
|
+
|
|
+ if ((rc = SendIocInit(ioc, sleepFlag)) != 0)
|
|
+ goto out;
|
|
+
|
|
+ if ((rc = SendEventNotification(ioc, 1, sleepFlag)) != 0)
|
|
+ goto out;
|
|
+
|
|
+ if (ioc->hard_resets < -1)
|
|
+ ioc->hard_resets++;
|
|
+
|
|
+ /*
|
|
+ * At this point, we know soft reset succeeded.
|
|
+ */
|
|
+
|
|
+ ioc->active = 1;
|
|
+ CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
|
|
+
|
|
+ out:
|
|
+ spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
|
|
+ ioc->ioc_reset_in_progress = 0;
|
|
+ ioc->taskmgmt_quiesce_io = 0;
|
|
+ ioc->taskmgmt_in_progress = 0;
|
|
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
+
|
|
+ if (ioc->active) { /* otherwise, hard reset coming */
|
|
+ for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
|
|
+ if (MptResetHandlers[cb_idx])
|
|
+ mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
|
|
+ }
|
|
+ }
|
|
+ /*
|
|
+ * Cleanup diag buffer allocated memory
|
|
+ */
|
|
+ for (i = 0; i < MPI_DIAG_BUF_TYPE_COUNT; i++) {
|
|
+ if (ioc->DiagBuffer[i] == NULL)
|
|
+ continue;
|
|
+ pci_free_consistent(ioc->pcidev, ioc->DiagBuffer_sz[i],
|
|
+ ioc->DiagBuffer[i], ioc->DiagBuffer_dma[i]);
|
|
+ ioc->DiagBuffer[i] = NULL;
|
|
+ ioc->DiagBuffer_Status[i] = 0;
|
|
+ }
|
|
+
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SoftResetHandler: completed (%d seconds): %s\n",
|
|
+ ioc->name, jiffies_to_msecs(jiffies - time_count)/1000,
|
|
+ ((rc == 0) ? "SUCCESS" : "FAILED")));
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/**
|
|
* mpt_HardResetHandler - Generic reset handler
|
|
@@ -6931,7 +7251,7 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, i
|
|
u8 cb_idx;
|
|
unsigned long flags;
|
|
unsigned long time_count;
|
|
-
|
|
+ int i;
|
|
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name));
|
|
#ifdef MFCNT
|
|
printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
|
|
@@ -6969,22 +7289,23 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, i
|
|
}
|
|
|
|
time_count = jiffies;
|
|
- rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag);
|
|
- if (rc != 0) {
|
|
- printk(KERN_WARNING MYNAM
|
|
- ": WARNING - (%d) Cannot recover %s\n", rc, ioc->name);
|
|
+ if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
|
|
+ printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n",
|
|
+ rc, ioc->name);
|
|
} else {
|
|
if (ioc->hard_resets < -1)
|
|
ioc->hard_resets++;
|
|
}
|
|
|
|
spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
|
|
- ioc->ioc_reset_in_progress = 0;
|
|
+ if (ioc->is_fault == 1)
|
|
+ ioc->is_fault = 2;
|
|
ioc->taskmgmt_quiesce_io = 0;
|
|
+ ioc->ioc_reset_in_progress = 0;
|
|
ioc->taskmgmt_in_progress = 0;
|
|
if (ioc->alt_ioc) {
|
|
- ioc->alt_ioc->ioc_reset_in_progress = 0;
|
|
ioc->alt_ioc->taskmgmt_quiesce_io = 0;
|
|
+ ioc->alt_ioc->ioc_reset_in_progress = 0;
|
|
ioc->alt_ioc->taskmgmt_in_progress = 0;
|
|
}
|
|
spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
@@ -6993,11 +7314,22 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, i
|
|
if (MptResetHandlers[cb_idx]) {
|
|
mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
|
|
if (ioc->alt_ioc)
|
|
- mpt_signal_reset(cb_idx,
|
|
- ioc->alt_ioc, MPT_IOC_POST_RESET);
|
|
+ mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_POST_RESET);
|
|
}
|
|
}
|
|
|
|
+ /*
|
|
+ * Cleanup diag buffer allocated memory
|
|
+ */
|
|
+ for (i = 0; i < MPI_DIAG_BUF_TYPE_COUNT; i++) {
|
|
+ if (ioc->DiagBuffer[i] == NULL)
|
|
+ continue;
|
|
+ pci_free_consistent(ioc->pcidev, ioc->DiagBuffer_sz[i],
|
|
+ ioc->DiagBuffer[i], ioc->DiagBuffer_dma[i]);
|
|
+ ioc->DiagBuffer[i] = NULL;
|
|
+ ioc->DiagBuffer_Status[i] = 0;
|
|
+ }
|
|
+
|
|
dtmprintk(ioc,
|
|
printk(MYIOC_s_DEBUG_FMT
|
|
"HardResetHandler: completed (%d seconds): %s\n", ioc->name,
|
|
@@ -7150,6 +7482,11 @@ mpt_display_event_info(MPT_ADAPTER *ioc,
|
|
"SAS Device Status Change: Internal Device "
|
|
"Reset : id=%d channel=%d", id, channel);
|
|
break;
|
|
+ case MPI_EVENT_SAS_DEV_STAT_RC_CMPL_INTERNAL_DEV_RESET:
|
|
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
|
|
+ "SAS Device Status Change: Internal Device "
|
|
+ "Reset Completed: 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 "
|
|
@@ -7170,6 +7507,11 @@ mpt_display_event_info(MPT_ADAPTER *ioc,
|
|
"SAS Device Status Change: Internal Query "
|
|
"Task : id=%d channel=%d", id, channel);
|
|
break;
|
|
+ case MPI_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
|
|
+ snprintf(evStr, EVENT_DESCR_STR_SZ,
|
|
+ "SAS Device Status Change: Async Notification "
|
|
+ "Task : id=%d channel=%d", id, channel);
|
|
+ break;
|
|
default:
|
|
snprintf(evStr, EVENT_DESCR_STR_SZ,
|
|
"SAS Device Status Change: Unknown: "
|
|
@@ -7336,12 +7678,28 @@ mpt_display_event_info(MPT_ADAPTER *ioc,
|
|
{
|
|
u8 phy_num = (u8)(evData0);
|
|
u8 port_num = (u8)(evData0 >> 8);
|
|
- u8 port_width = (u8)(evData0 >> 16);
|
|
+ u8 num_phys = (u8)(evData0 >> 16);
|
|
u8 primative = (u8)(evData0 >> 24);
|
|
+ char *primative_str = NULL;
|
|
+
|
|
+ switch (primative) {
|
|
+ case MPI_EVENT_PRIMITIVE_CHANGE:
|
|
+ primative_str = "change";
|
|
+ break;
|
|
+ case MPI_EVENT_PRIMITIVE_EXPANDER:
|
|
+ primative_str = "expander";
|
|
+ break;
|
|
+ case MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT:
|
|
+ primative_str = "asyn event";
|
|
+ break;
|
|
+ default:
|
|
+ primative_str = "reserved";
|
|
+ break;
|
|
+ }
|
|
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);
|
|
+ "SAS Broadcast Primative: phy=%d port=%d "
|
|
+ "num_phys=%d primative=%s (0x%02x)",
|
|
+ phy_num, port_num, num_phys, primative_str, primative);
|
|
break;
|
|
}
|
|
|
|
@@ -7712,7 +8070,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 l
|
|
"IO Not Yet Executed", /* 13h */
|
|
"IO Executed", /* 14h */
|
|
"Persistent Reservation Out Not Affiliation "
|
|
- "Owner", /* 15h */
|
|
+ "Owner", /* 15h */
|
|
"Open Transmit DMA Abort", /* 16h */
|
|
"IO Device Missing Delay Retry", /* 17h */
|
|
"IO Cancelled Due to Recieve Error", /* 18h */
|
|
@@ -7737,19 +8095,19 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 l
|
|
NULL /* 07h */
|
|
};
|
|
static char *raid_sub_code_str[] = {
|
|
- NULL, /* 00h */
|
|
+ NULL, /* 00h */
|
|
"Volume Creation Failed: Data Passed too "
|
|
- "Large", /* 01h */
|
|
+ "Large", /* 01h */
|
|
"Volume Creation Failed: Duplicate Volumes "
|
|
- "Attempted", /* 02h */
|
|
+ "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 */
|
|
+ "MFG Page 4", /* 06h */
|
|
"Volume Creation Failed: Creating Internal "
|
|
- "Structures", /* 07h */
|
|
+ "Structures", /* 07h */
|
|
NULL, /* 08h */
|
|
NULL, /* 09h */
|
|
NULL, /* 0Ah */
|
|
@@ -7758,12 +8116,12 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 l
|
|
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 */
|
|
+ "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 */
|
|
@@ -7774,12 +8132,12 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 l
|
|
NULL, /* 1Dh */
|
|
NULL, /* 1Eh */
|
|
NULL, /* 1Fh */
|
|
- "Phys Disk failed: Too Many Phys Disks", /* 20h */
|
|
+ "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 <channel:id>", /* 23h */
|
|
+ "Phys Disk failed: DMA Error", /* 22h */
|
|
+ "Phys Disk failed: Invalid <channel:id>", /* 23h */
|
|
"Phys Disk failed: Creating Phys Disk Config "
|
|
- "Page", /* 24h */
|
|
+ "Page", /* 24h */
|
|
NULL, /* 25h */
|
|
NULL, /* 26h */
|
|
NULL, /* 27h */
|
|
@@ -7797,22 +8155,22 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 l
|
|
"Device ", /* 32h */
|
|
"Compatibility Error: Removable Device Found", /* 33h */
|
|
"Compatibility Error: Device SCSI Version not "
|
|
- "2 or Higher", /* 34h */
|
|
+ "2 or Higher", /* 34h */
|
|
"Compatibility Error: SATA Device, 48 BIT LBA "
|
|
- "not Supported", /* 35h */
|
|
+ "not Supported", /* 35h */
|
|
"Compatibility Error: Device doesn't have "
|
|
- "512 Byte Block Sizes", /* 36h */
|
|
+ "512 Byte Block Sizes", /* 36h */
|
|
"Compatibility Error: Volume Type Check Failed", /* 37h */
|
|
"Compatibility Error: Volume Type is "
|
|
- "Unsupported by FW", /* 38h */
|
|
+ "Unsupported by FW", /* 38h */
|
|
"Compatibility Error: Disk Drive too Small for "
|
|
- "use in Volume", /* 39h */
|
|
+ "use in Volume", /* 39h */
|
|
"Compatibility Error: Phys Disk for Create "
|
|
- "Volume not Found", /* 3Ah */
|
|
+ "Volume not Found", /* 3Ah */
|
|
"Compatibility Error: Too Many or too Few "
|
|
- "Disks for Volume Type", /* 3Bh */
|
|
+ "Disks for Volume Type", /* 3Bh */
|
|
"Compatibility Error: Disk stripe Sizes "
|
|
- "Must be 64KB", /* 3Ch */
|
|
+ "Must be 64KB", /* 3Ch */
|
|
"Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
|
|
};
|
|
|
|
@@ -8210,6 +8568,7 @@ EXPORT_SYMBOL(mpt_resume);
|
|
EXPORT_SYMBOL(mpt_suspend);
|
|
#endif
|
|
EXPORT_SYMBOL(ioc_list);
|
|
+EXPORT_SYMBOL(mpt_proc_root_dir);
|
|
EXPORT_SYMBOL(mpt_register);
|
|
EXPORT_SYMBOL(mpt_deregister);
|
|
EXPORT_SYMBOL(mpt_event_register);
|
|
@@ -8227,13 +8586,18 @@ EXPORT_SYMBOL(mpt_verify_adapter);
|
|
EXPORT_SYMBOL(mpt_GetIocState);
|
|
EXPORT_SYMBOL(mpt_print_ioc_summary);
|
|
EXPORT_SYMBOL(mpt_HardResetHandler);
|
|
+EXPORT_SYMBOL(mpt_SoftResetHandler);
|
|
EXPORT_SYMBOL(mpt_config);
|
|
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);
|
|
-
|
|
+EXPORT_SYMBOL(mpt_raid_phys_disk_pg1);
|
|
+EXPORT_SYMBOL(mpt_raid_phys_disk_get_num_paths);
|
|
+EXPORT_SYMBOL(mpt_set_taskmgmt_in_progress_flag);
|
|
+EXPORT_SYMBOL(mpt_clear_taskmgmt_in_progress_flag);
|
|
+EXPORT_SYMBOL(mpt_halt_firmware);
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/**
|
|
* fusion_init - Fusion MPT base driver initialization routine.
|
|
--- a/drivers/message/fusion/mptbase.h
|
|
+++ b/drivers/message/fusion/mptbase.h
|
|
@@ -49,10 +49,6 @@
|
|
#define MPTBASE_H_INCLUDED
|
|
/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
|
|
-#include <linux/kernel.h>
|
|
-#include <linux/pci.h>
|
|
-#include <linux/mutex.h>
|
|
-
|
|
#include "lsi/mpi_type.h"
|
|
#include "lsi/mpi.h" /* Fusion MPI(nterface) basic defs */
|
|
#include "lsi/mpi_ioc.h" /* Fusion MPT IOC(ontroller) defs */
|
|
@@ -76,9 +72,13 @@
|
|
#define COPYRIGHT "Copyright (c) 1999-2008 " MODULEAUTHOR
|
|
#endif
|
|
|
|
-#define MPT_LINUX_VERSION_COMMON "3.04.13"
|
|
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.13"
|
|
+#define MPT_LINUX_VERSION_COMMON "4.22.00.00"
|
|
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-4.22.00.00"
|
|
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
|
|
+#define MPT_LINUX_MAJOR_VERSION 4
|
|
+#define MPT_LINUX_MINOR_VERSION 22
|
|
+#define MPT_LINUX_BUILD_VERSION 00
|
|
+#define MPT_LINUX_RELEASE_VERSION 00
|
|
|
|
#define show_mptmod_ver(s,ver) \
|
|
printk(KERN_INFO "%s %s\n", s, ver);
|
|
@@ -87,6 +87,8 @@
|
|
/*
|
|
* Fusion MPT(linux) driver configurable stuff...
|
|
*/
|
|
+#define MPT_POLLING_INTERVAL 1000 /* in milliseconds */
|
|
+
|
|
#define MPT_MAX_ADAPTERS 18
|
|
#define MPT_MAX_PROTOCOL_DRIVERS 16
|
|
#define MPT_MAX_BUS 1 /* Do not change */
|
|
@@ -135,7 +137,6 @@
|
|
|
|
#define MPT_COALESCING_TIMEOUT 0x10
|
|
|
|
-
|
|
/*
|
|
* SCSI transfer rate defines.
|
|
*/
|
|
@@ -164,10 +165,10 @@
|
|
/*
|
|
* Set the MAX_SGE value based on user input.
|
|
*/
|
|
-#ifdef CONFIG_FUSION_MAX_SGE
|
|
-#if CONFIG_FUSION_MAX_SGE < 16
|
|
+#ifdef CONFIG_FUSION_MAX_SGE
|
|
+#if CONFIG_FUSION_MAX_SGE < 16
|
|
#define MPT_SCSI_SG_DEPTH 16
|
|
-#elif CONFIG_FUSION_MAX_SGE > 128
|
|
+#elif CONFIG_FUSION_MAX_SGE > 128
|
|
#define MPT_SCSI_SG_DEPTH 128
|
|
#else
|
|
#define MPT_SCSI_SG_DEPTH CONFIG_FUSION_MAX_SGE
|
|
@@ -176,10 +177,10 @@
|
|
#define MPT_SCSI_SG_DEPTH 40
|
|
#endif
|
|
|
|
-#ifdef CONFIG_FUSION_MAX_FC_SGE
|
|
-#if CONFIG_FUSION_MAX_FC_SGE < 16
|
|
+#ifdef CONFIG_FUSION_MAX_FC_SGE
|
|
+#if CONFIG_FUSION_MAX_FC_SGE < 16
|
|
#define MPT_SCSI_FC_SG_DEPTH 16
|
|
-#elif CONFIG_FUSION_MAX_FC_SGE > 256
|
|
+#elif CONFIG_FUSION_MAX_FC_SGE > 256
|
|
#define MPT_SCSI_FC_SG_DEPTH 256
|
|
#else
|
|
#define MPT_SCSI_FC_SG_DEPTH CONFIG_FUSION_MAX_FC_SGE
|
|
@@ -189,9 +190,8 @@
|
|
#endif
|
|
|
|
/* debug print string length used for events and iocstatus */
|
|
-# define EVENT_DESCR_STR_SZ 100
|
|
+# define EVENT_DESCR_STR_SZ 100
|
|
|
|
-#define MPT_POLLING_INTERVAL 1000 /* in milliseconds */
|
|
|
|
#ifdef __KERNEL__ /* { */
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
@@ -239,7 +239,6 @@ typedef struct _ATTO_CONFIG_PAGE_SCSI_PO
|
|
} fATTO_CONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_ATTO_CONFIG_PAGE_SCSI_PORT_2,
|
|
ATTO_SCSIPortPage2_t, MPI_POINTER pATTO_SCSIPortPage2_t;
|
|
|
|
-
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/*
|
|
* MPT protocol driver defs...
|
|
@@ -369,6 +368,31 @@ typedef struct _SYSIF_REGS
|
|
* in conjunction with SYSIF_REGS accesses!
|
|
*/
|
|
|
|
+/*
|
|
+ * End to End Data Protection Support
|
|
+ */
|
|
+#define EEDP_SUPPORT
|
|
+#ifdef EEDP_SUPPORT
|
|
+
|
|
+#define PRO_R MPI_SCSIIO32_EEDPFLAGS_CHKRM_OP
|
|
+#define PRO_W MPI_SCSIIO32_EEDPFLAGS_INSERT_OP
|
|
+#define PRO_V MPI_SCSIIO32_EEDPFLAGS_INSERT_OP
|
|
+
|
|
+/* the read capacity 16 byte parameter block - defined in SBC-3 */
|
|
+struct read_cap_parameter{
|
|
+ u64 logical_block_addr;
|
|
+ u32 logical_block_length;
|
|
+ u8 prot_en:1;
|
|
+ u8 p_type:3;
|
|
+ u8 reserved0:4;
|
|
+ u8 logical_blocks_per_phyical_block:4;
|
|
+ u8 reserved1:4;
|
|
+ u16 lowest_aligned_log_block_address:14;
|
|
+ u16 reserved2:2;
|
|
+ u8 reserved3[16];
|
|
+};
|
|
+#endif
|
|
+
|
|
|
|
/*
|
|
* Dynamic Multi-Pathing specific stuff...
|
|
@@ -378,7 +402,7 @@ typedef struct _SYSIF_REGS
|
|
#define MPT_TARGET_NO_NEGO_WIDE 0x01
|
|
#define MPT_TARGET_NO_NEGO_SYNC 0x02
|
|
#define MPT_TARGET_NO_NEGO_QAS 0x04
|
|
-#define MPT_TAPE_NEGO_IDP 0x08
|
|
+#define MPT_TAPE_NEGO_IDP 0x08
|
|
|
|
/*
|
|
* VirtDevice - FC LUN device or SCSI target device
|
|
@@ -387,8 +411,8 @@ typedef struct _VirtTarget {
|
|
struct scsi_target *starget;
|
|
u8 tflags;
|
|
u8 ioc_id;
|
|
- u8 id;
|
|
- u8 channel;
|
|
+ u8 id; /* logical target id */
|
|
+ u8 channel; /* logical channel number */
|
|
u8 minSyncFactor; /* 0xFF is async */
|
|
u8 maxOffset; /* 0 if async */
|
|
u8 maxWidth; /* 0 if narrow, 1 if wide */
|
|
@@ -396,13 +420,18 @@ typedef struct _VirtTarget {
|
|
u8 raidVolume; /* set, if RAID Volume */
|
|
u8 type; /* byte 0 of Inquiry data */
|
|
u8 deleted; /* target in process of being removed */
|
|
- u32 num_luns;
|
|
+ int num_luns;
|
|
} VirtTarget;
|
|
|
|
typedef struct _VirtDevice {
|
|
VirtTarget *vtarget;
|
|
u8 configured_lun;
|
|
int lun;
|
|
+#ifdef EEDP_SUPPORT
|
|
+ u8 eedp_enable;
|
|
+ u8 eedp_type;
|
|
+ u32 eedp_block_length;
|
|
+#endif
|
|
} VirtDevice;
|
|
|
|
/*
|
|
@@ -442,21 +471,14 @@ do { \
|
|
} while (0)
|
|
|
|
|
|
-/*
|
|
- * IOCTL structure and associated defines
|
|
- */
|
|
-
|
|
-#define MPTCTL_RESET_OK 0x01 /* Issue Bus Reset */
|
|
-
|
|
#define MPT_MGMT_STATUS_RF_VALID 0x01 /* The Reply Frame is VALID */
|
|
#define MPT_MGMT_STATUS_COMMAND_GOOD 0x02 /* Command Status GOOD */
|
|
#define MPT_MGMT_STATUS_PENDING 0x04 /* command is pending */
|
|
-#define MPT_MGMT_STATUS_DID_IOCRESET 0x08 /* IOC Reset occurred
|
|
- on the current*/
|
|
+#define MPT_MGMT_STATUS_DID_IOCRESET 0x08 /* IOC Reset occurred on the current*/
|
|
#define MPT_MGMT_STATUS_SENSE_VALID 0x10 /* valid sense info */
|
|
#define MPT_MGMT_STATUS_TIMER_ACTIVE 0x20 /* obsolete */
|
|
-#define MPT_MGMT_STATUS_FREE_MF 0x40 /* free the mf from
|
|
- complete routine */
|
|
+#define MPT_MGMT_STATUS_FREE_MF 0x40 /* free the mf from complete routine */
|
|
+
|
|
|
|
#define INITIALIZE_MGMT_STATUS(status) \
|
|
status = MPT_MGMT_STATUS_PENDING;
|
|
@@ -475,7 +497,7 @@ typedef struct _MPT_MGMT {
|
|
u8 status; /* current command status */
|
|
int completion_code;
|
|
u32 msg_context;
|
|
-} MPT_MGMT;
|
|
+}MPT_MGMT;
|
|
|
|
/*
|
|
* Event Structure and define
|
|
@@ -538,7 +560,7 @@ typedef struct _SasCfgData {
|
|
* @inactive_list
|
|
*/
|
|
struct inactive_raid_component_info {
|
|
- struct list_head list;
|
|
+ struct list_head list;
|
|
u8 volumeID; /* volume target id */
|
|
u8 volumeBus; /* volume channel */
|
|
IOC_3_PHYS_DISK d; /* phys disk info */
|
|
@@ -547,7 +569,8 @@ struct inactive_raid_component_info {
|
|
typedef struct _RaidCfgData {
|
|
IOCPage2_t *pIocPg2; /* table of Raid Volumes */
|
|
IOCPage3_t *pIocPg3; /* table of physical disks */
|
|
- struct mutex inactive_list_mutex;
|
|
+ IOCPage6_t *pIocPg6; /* table of IR static data */
|
|
+ struct semaphore inactive_list_mutex;
|
|
struct list_head inactive_list; /* link list for physical
|
|
disk that belong in
|
|
inactive volumes */
|
|
@@ -578,8 +601,8 @@ struct mptfc_rport_info
|
|
};
|
|
|
|
typedef void (*MPT_ADD_SGE)(void *pAddr, u32 flagslength, dma_addr_t dma_addr);
|
|
-typedef void (*MPT_ADD_CHAIN)(void *pAddr, u8 next, u16 length,
|
|
- dma_addr_t dma_addr);
|
|
+typedef void (*MPT_ADD_CHAIN)(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr);
|
|
+typedef void (*MPT_SCHEDULE_TARGET_RESET)(void *ioc);
|
|
|
|
/*
|
|
* Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
|
|
@@ -591,8 +614,7 @@ typedef struct _MPT_ADAPTER
|
|
char name[MPT_NAME_LENGTH]; /* "iocN" */
|
|
char prod_name[MPT_NAME_LENGTH]; /* "LSIFC9x9" */
|
|
#ifdef CONFIG_FUSION_LOGGING
|
|
- /* used in mpt_display_event_info */
|
|
- char evStr[EVENT_DESCR_STR_SZ];
|
|
+ char evStr[EVENT_DESCR_STR_SZ]; /* used in mpt_display_event_info */
|
|
#endif
|
|
char board_name[16];
|
|
char board_assembly[16];
|
|
@@ -605,8 +627,8 @@ typedef struct _MPT_ADAPTER
|
|
SYSIF_REGS __iomem *chip; /* == c8817000 (mmap) */
|
|
SYSIF_REGS __iomem *pio_chip; /* Programmed IO (downloadboot) */
|
|
u8 bus_type;
|
|
- u32 mem_phys; /* == f4020000 (mmap) */
|
|
- u32 pio_mem_phys; /* Programmed IO (downloadboot) */
|
|
+ unsigned long mem_phys; /* == f4020000 (mmap) */
|
|
+ unsigned long pio_mem_phys; /* Programmed IO (downloadboot) */
|
|
int mem_size; /* mmap memory size */
|
|
int number_of_buses;
|
|
int devices_per_bus;
|
|
@@ -621,10 +643,8 @@ typedef struct _MPT_ADAPTER
|
|
int reply_depth; /* Num Allocated reply frames */
|
|
int reply_sz; /* Reply frame size */
|
|
int num_chain; /* Number of chain buffers */
|
|
- MPT_ADD_SGE add_sge; /* Pointer to add_sge
|
|
- function */
|
|
- MPT_ADD_CHAIN add_chain; /* Pointer to add_chain
|
|
- function */
|
|
+ MPT_ADD_SGE add_sge; /* Pointer to add_sge function */
|
|
+ MPT_ADD_CHAIN add_chain; /* Pointer to add_chain function */
|
|
/* Pool of buffers for chaining. ReqToChain
|
|
* and ChainToChain track index of chain buffers.
|
|
* ChainBuffer (DMA) virt/phys addresses.
|
|
@@ -653,18 +673,18 @@ typedef struct _MPT_ADAPTER
|
|
dma_addr_t sense_buf_pool_dma;
|
|
u32 sense_buf_low_dma;
|
|
u8 *HostPageBuffer; /* SAS - host page buffer support */
|
|
- u32 HostPageBuffer_sz;
|
|
- dma_addr_t HostPageBuffer_dma;
|
|
+ u32 HostPageBuffer_sz;
|
|
+ dma_addr_t HostPageBuffer_dma;
|
|
int mtrr_reg;
|
|
struct pci_dev *pcidev; /* struct pci_dev pointer */
|
|
- int bars; /* bitmask of BAR's that must be configured */
|
|
- int msi_enable;
|
|
+ int bars; /* bitmask of BAR's that must be configured */
|
|
+ int msi_enable;
|
|
u8 __iomem *memmap; /* mmap address */
|
|
struct Scsi_Host *sh; /* Scsi Host pointer */
|
|
- SpiCfgData spi_data; /* Scsi config. data */
|
|
- RaidCfgData raid_data; /* Raid config. data */
|
|
- SasCfgData sas_data; /* Sas config. data */
|
|
- FcCfgData fc_data; /* Fc config. data */
|
|
+ SpiCfgData spi_data; /* Scsi config. data */
|
|
+ RaidCfgData raid_data; /* Raid config. data */
|
|
+ SasCfgData sas_data; /* Sas config. data */
|
|
+ FcCfgData fc_data; /* Fc config. data */
|
|
struct proc_dir_entry *ioc_dentry;
|
|
struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */
|
|
u32 biosVersion; /* BIOS version from IO Unit Page 2 */
|
|
@@ -673,7 +693,7 @@ typedef struct _MPT_ADAPTER
|
|
int eventLogSize; /* Max number of cached events */
|
|
struct _mpt_ioctl_events *events; /* pointer to event log */
|
|
u8 *cached_fw; /* Pointer to FW */
|
|
- dma_addr_t cached_fw_dma;
|
|
+ dma_addr_t cached_fw_dma;
|
|
int hs_reply_idx;
|
|
#ifndef MFCNT
|
|
u32 pad0;
|
|
@@ -688,8 +708,14 @@ typedef struct _MPT_ADAPTER
|
|
FCPortPage0_t fc_port_page0[2];
|
|
LANPage0_t lan_cnfg_page0;
|
|
LANPage1_t lan_cnfg_page1;
|
|
+#if defined(CPQ_CIM)
|
|
+ u32 csmi_change_count; /* count to track all IR
|
|
+ events for CSMI */
|
|
+ u8 pci_slot_number; /* ioc page 1 - pci slot number */
|
|
+#endif
|
|
|
|
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
|
|
@@ -701,7 +727,6 @@ typedef struct _MPT_ADAPTER
|
|
u8 FirstWhoInit;
|
|
u8 upload_fw; /* If set, do a fw upload */
|
|
u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */
|
|
- u8 pad1[4];
|
|
u8 DoneCtx;
|
|
u8 TaskCtx;
|
|
u8 InternalCtx;
|
|
@@ -709,37 +734,39 @@ typedef struct _MPT_ADAPTER
|
|
struct net_device *netdev;
|
|
struct list_head sas_topology;
|
|
struct mutex sas_topology_mutex;
|
|
+ u8 disable_hotplug_remove;
|
|
|
|
- struct workqueue_struct *fw_event_q;
|
|
+ struct workqueue_struct *fw_event_q;
|
|
struct list_head fw_event_list;
|
|
spinlock_t fw_event_lock;
|
|
u8 fw_events_off; /* if '1', then ignore events */
|
|
- char fw_event_q_name[MPT_KOBJ_NAME_LEN];
|
|
-
|
|
- struct mutex sas_discovery_mutex;
|
|
- u8 sas_discovery_runtime;
|
|
- u8 sas_discovery_ignore_events;
|
|
+ char fw_event_q_name[MPT_KOBJ_NAME_LEN];
|
|
|
|
- /* port_info object for the host */
|
|
- struct mptsas_portinfo *hba_port_info;
|
|
+ struct mptsas_portinfo *hba_port_info; /* port_info object for the host */
|
|
u64 hba_port_sas_addr;
|
|
u16 hba_port_num_phy;
|
|
struct list_head sas_device_info_list;
|
|
- struct mutex sas_device_info_mutex;
|
|
+ struct semaphore sas_device_info_mutex;
|
|
u8 old_sas_discovery_protocal;
|
|
u8 sas_discovery_quiesce_io;
|
|
int sas_index; /* index refrencing */
|
|
MPT_MGMT sas_mgmt;
|
|
- MPT_MGMT mptbase_cmds; /* for sending config pages */
|
|
MPT_MGMT internal_cmds;
|
|
+ MPT_MGMT mptbase_cmds; /* for sending config pages */
|
|
MPT_MGMT taskmgmt_cmds;
|
|
- MPT_MGMT ioctl_cmds;
|
|
- spinlock_t taskmgmt_lock; /* diagnostic reset lock */
|
|
+ MPT_MGMT ioctl_cmds; /* ioctl data pointer */
|
|
+ spinlock_t taskmgmt_lock; /* diagnostic reset lock */
|
|
int taskmgmt_in_progress;
|
|
u8 taskmgmt_quiesce_io;
|
|
u8 ioc_reset_in_progress;
|
|
- struct work_struct sas_persist_task;
|
|
+ MPT_SCHEDULE_TARGET_RESET schedule_target_reset;
|
|
+#if defined(CPQ_CIM)
|
|
+ u8 num_ports;
|
|
+#endif
|
|
|
|
+ char reset_work_q_name[MPT_KOBJ_NAME_LEN];
|
|
+ struct workqueue_struct *reset_work_q;
|
|
+ struct delayed_work fault_reset_work;
|
|
struct work_struct fc_setup_reset_work;
|
|
struct list_head fc_rports;
|
|
struct work_struct fc_lsc_work;
|
|
@@ -748,26 +775,32 @@ typedef struct _MPT_ADAPTER
|
|
struct work_struct fc_rescan_work;
|
|
char fc_rescan_work_q_name[MPT_KOBJ_NAME_LEN];
|
|
struct workqueue_struct *fc_rescan_work_q;
|
|
-
|
|
- /* driver forced bus resets count */
|
|
- unsigned long hard_resets;
|
|
- /* fw/external bus resets count */
|
|
- unsigned long soft_resets;
|
|
- /* cmd timeouts */
|
|
- unsigned long timeouts;
|
|
-
|
|
+ unsigned long hard_resets; /* driver forced bus resets count */
|
|
+ unsigned long soft_resets; /* fw/external bus resets count */
|
|
+ unsigned long timeouts; /* cmd timeouts */
|
|
struct scsi_cmnd **ScsiLookup;
|
|
spinlock_t scsi_lookup_lock;
|
|
- u64 dma_mask;
|
|
+ int sdev_queue_depth; /* sdev queue depth */
|
|
+ u64 dma_mask;
|
|
u32 broadcast_aen_busy;
|
|
- char reset_work_q_name[MPT_KOBJ_NAME_LEN];
|
|
- struct workqueue_struct *reset_work_q;
|
|
- struct delayed_work fault_reset_work;
|
|
-
|
|
+#if defined(DIAG_BUFFER_SUPPORT)
|
|
+ u8 *DiagBuffer[MPI_DIAG_BUF_TYPE_COUNT];
|
|
+ u32 DataSize[MPI_DIAG_BUF_TYPE_COUNT];
|
|
+ u32 DiagBuffer_sz[MPI_DIAG_BUF_TYPE_COUNT];
|
|
+ dma_addr_t DiagBuffer_dma[MPI_DIAG_BUF_TYPE_COUNT];
|
|
+ u8 TraceLevel[MPI_DIAG_BUF_TYPE_COUNT];
|
|
+ u8 DiagBuffer_Status[MPI_DIAG_BUF_TYPE_COUNT];
|
|
+ u32 UniqueId[MPI_DIAG_BUF_TYPE_COUNT];
|
|
+ u32 ExtendedType[MPI_DIAG_BUF_TYPE_COUNT];
|
|
+ u32 ProductSpecific[MPI_DIAG_BUF_TYPE_COUNT][4];
|
|
+#endif
|
|
u8 sg_addr_size;
|
|
- u8 in_rescan;
|
|
u8 SGE_size;
|
|
-
|
|
+ u8 in_rescan;
|
|
+ /* diag buffer bits for sysfs */
|
|
+ u8 is_fault;
|
|
+ u32 ring_buffer_offset;
|
|
+ u32 ring_buffer_sz;
|
|
} MPT_ADAPTER;
|
|
|
|
/*
|
|
@@ -804,11 +837,9 @@ typedef struct _mpt_sge {
|
|
dma_addr_t Address;
|
|
} MptSge_t;
|
|
|
|
-
|
|
#define mpt_msg_flags(ioc) \
|
|
- (ioc->sg_addr_size == sizeof(u64)) ? \
|
|
- MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 : \
|
|
- MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32
|
|
+ (ioc->sg_addr_size == sizeof(u64)) ? MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 : \
|
|
+ MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32
|
|
|
|
#define MPT_SGE_FLAGS_64_BIT_ADDRESSING \
|
|
(MPI_SGE_FLAGS_64_BIT_ADDRESSING << MPI_SGE_FLAGS_SHIFT)
|
|
@@ -830,26 +861,10 @@ typedef struct _mpt_sge {
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
|
|
-#define SCSI_STD_SENSE_BYTES 18
|
|
-#define SCSI_STD_INQUIRY_BYTES 36
|
|
-#define SCSI_MAX_INQUIRY_BYTES 96
|
|
-
|
|
/*
|
|
* MPT_SCSI_HOST defines - Used by the IOCTL and the SCSI drivers
|
|
* Private to the driver.
|
|
*/
|
|
-/* LOCAL structure and fields used when processing
|
|
- * internally generated commands. These include:
|
|
- * bus scan, dv and config requests.
|
|
- */
|
|
-typedef struct _MPT_LOCAL_REPLY {
|
|
- ConfigPageHeader_t header;
|
|
- int completion;
|
|
- u8 sense[SCSI_STD_SENSE_BYTES];
|
|
- u8 scsiStatus;
|
|
- u8 skip;
|
|
- u32 pad;
|
|
-} MPT_LOCAL_REPLY;
|
|
|
|
#define MPT_HOST_BUS_UNKNOWN (0xFF)
|
|
#define MPT_HOST_TOO_MANY_TM (0x05)
|
|
@@ -865,13 +880,6 @@ typedef struct _MPT_LOCAL_REPLY {
|
|
#define MPT_NVRAM_WIDE_DISABLE (0x00100000)
|
|
#define MPT_NVRAM_BOOT_CHOICE (0x00200000)
|
|
|
|
-/* The TM_STATE variable is used to provide strict single threading of TM
|
|
- * requests as well as communicate TM error conditions.
|
|
- */
|
|
-#define TM_STATE_NONE (0)
|
|
-#define TM_STATE_IN_PROGRESS (1)
|
|
-#define TM_STATE_ERROR (2)
|
|
-
|
|
typedef enum {
|
|
FC,
|
|
SPI,
|
|
@@ -881,7 +889,7 @@ typedef enum {
|
|
typedef struct _MPT_SCSI_HOST {
|
|
MPT_ADAPTER *ioc;
|
|
ushort sel_timeout[MPT_MAX_FC_DEVICES];
|
|
- char *info_kbuf;
|
|
+ char *info_kbuf;
|
|
long last_queue_full;
|
|
u16 spi_pending;
|
|
struct list_head target_reset_list;
|
|
@@ -889,14 +897,6 @@ typedef struct _MPT_SCSI_HOST {
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/*
|
|
- * More Dynamic Multi-Pathing stuff...
|
|
- */
|
|
-
|
|
-/* Forward decl, a strange C thing, to prevent gcc compiler warnings */
|
|
-struct scsi_cmnd;
|
|
-
|
|
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
-/*
|
|
* Generic structure passed to the base mpt_config function.
|
|
*/
|
|
typedef struct _x_config_parms {
|
|
@@ -934,37 +934,37 @@ extern MPT_FRAME_HDR *mpt_get_msg_frame(
|
|
extern void mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
|
|
extern void mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
|
|
extern void mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
|
|
-
|
|
extern int mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag);
|
|
extern int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp);
|
|
extern u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
|
|
extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan);
|
|
extern int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
|
|
+extern int mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
|
|
extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
|
|
extern int 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);
|
|
-extern int mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num,
|
|
- pRaidPhysDiskPage1_t phys_disk);
|
|
-extern int mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc,
|
|
- u8 phys_disk_num);
|
|
+extern int mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage1_t phys_disk);
|
|
+extern int mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, u8 phys_disk_num);
|
|
+
|
|
extern int mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc);
|
|
extern void mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc);
|
|
-extern void mpt_halt_firmware(MPT_ADAPTER *ioc);
|
|
-
|
|
+extern void mpt_halt_firmware(MPT_ADAPTER *ioc);
|
|
|
|
/*
|
|
* Public data decl's...
|
|
*/
|
|
extern struct list_head ioc_list;
|
|
+extern struct proc_dir_entry *mpt_proc_root_dir;
|
|
+extern int mpt_debug_level;
|
|
extern int mpt_fwfault_debug;
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
#endif /* } __KERNEL__ */
|
|
|
|
-#ifdef CONFIG_64BIT
|
|
+#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__) || defined(__powerpc64__)
|
|
#define CAST_U32_TO_PTR(x) ((void *)(u64)x)
|
|
#define CAST_PTR_TO_U32(x) ((u32)(u64)x)
|
|
#else
|
|
--- a/drivers/message/fusion/mptctl.c
|
|
+++ b/drivers/message/fusion/mptctl.c
|
|
@@ -71,6 +71,15 @@
|
|
#include "mptbase.h"
|
|
#include "mptctl.h"
|
|
|
|
+#if defined(CPQ_CIM)
|
|
+#include "mptsas.h"
|
|
+#include "csmi/csmisas.h"
|
|
+#endif // CPQ_CIM
|
|
+
|
|
+#if defined(DIAG_BUFFER_SUPPORT)
|
|
+#include "rejected_ioctls/diag_buffer.h"
|
|
+#endif
|
|
+
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
#define my_NAME "Fusion MPT misc device (ioctl) driver"
|
|
#define my_VERSION MPT_LINUX_VERSION_COMMON
|
|
@@ -113,6 +122,42 @@ static int mptctl_do_reset(unsigned long
|
|
static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
|
|
static int mptctl_hp_targetinfo(unsigned long arg);
|
|
|
|
+#if defined(CPQ_CIM)
|
|
+/* csmisas proto's*/
|
|
+static int csmisas_get_driver_info(unsigned long arg);
|
|
+static int csmisas_get_cntlr_status(unsigned long arg);
|
|
+static int csmisas_get_cntlr_config(unsigned long arg);
|
|
+static int csmisas_get_phy_info(unsigned long arg);
|
|
+static int csmisas_get_scsi_address(unsigned long arg);
|
|
+static int csmisas_get_link_errors(unsigned long arg);
|
|
+static int csmisas_smp_passthru(unsigned long arg);
|
|
+static int csmisas_firmware_download(unsigned long arg);
|
|
+static int csmisas_get_raid_info(unsigned long arg);
|
|
+static int csmisas_get_raid_config(unsigned long arg);
|
|
+static int csmisas_get_raid_features(unsigned long arg);
|
|
+static int csmisas_set_raid_control(unsigned long arg);
|
|
+static int csmisas_get_raid_element(unsigned long arg);
|
|
+static int csmisas_set_raid_operation(unsigned long arg);
|
|
+static int csmisas_set_phy_info(unsigned long arg);
|
|
+static int csmisas_ssp_passthru(unsigned long arg);
|
|
+static int csmisas_stp_passthru(unsigned long arg);
|
|
+static int csmisas_get_sata_signature(unsigned long arg);
|
|
+static int csmisas_get_device_address(unsigned long arg);
|
|
+static int csmisas_task_managment(unsigned long arg);
|
|
+static int csmisas_phy_control(unsigned long arg);
|
|
+static int csmisas_get_connector_info(unsigned long arg);
|
|
+static int csmisas_get_location(unsigned long arg);
|
|
+#endif // CPQ_CIM
|
|
+
|
|
+#if defined(DIAG_BUFFER_SUPPORT)
|
|
+/* diag_buffer proto's */
|
|
+static int mptctl_register_diag_buffer(unsigned long arg);
|
|
+static int mptctl_release_diag_buffer(unsigned long arg);
|
|
+static int mptctl_unregister_diag_buffer(unsigned long arg);
|
|
+static int mptctl_query_diag_buffer(unsigned long arg);
|
|
+static int mptctl_read_diag_buffer(unsigned long arg);
|
|
+#endif // DIAG_BUFFER_SUPPORT
|
|
+
|
|
static int mptctl_probe(struct pci_dev *, const struct pci_device_id *);
|
|
static void mptctl_remove(struct pci_dev *);
|
|
|
|
@@ -128,7 +173,6 @@ static MptSge_t *kbuf_alloc_2_sgl(int by
|
|
struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
|
|
static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
|
|
struct buflist *buflist, MPT_ADAPTER *ioc);
|
|
-static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function);
|
|
|
|
/*
|
|
* Reset Handler cleanup function
|
|
@@ -234,8 +278,7 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME
|
|
le32_to_cpu(reply->u.reply.IOCLogInfo)));
|
|
|
|
if ((req->u.hdr.Function == MPI_FUNCTION_SCSI_IO_REQUEST) ||
|
|
- (req->u.hdr.Function ==
|
|
- MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
|
|
+ (req->u.hdr.Function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
|
|
|
|
if (reply->u.sreply.SCSIStatus || reply->u.sreply.SCSIState)
|
|
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
@@ -246,8 +289,7 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME
|
|
le16_to_cpu(reply->u.sreply.TaskTag),
|
|
le32_to_cpu(reply->u.sreply.TransferCount)));
|
|
|
|
- if (reply->u.sreply.SCSIState &
|
|
- MPI_SCSI_STATE_AUTOSENSE_VALID) {
|
|
+ if (reply->u.sreply.SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
|
|
sz = req->u.scsireq.SenseBufferLength;
|
|
req_index =
|
|
le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
|
|
@@ -262,10 +304,16 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME
|
|
/* We are done, issue wake up
|
|
*/
|
|
if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_PENDING) {
|
|
- if (req->u.hdr.Function == MPI_FUNCTION_SCSI_TASK_MGMT)
|
|
+ if (req->u.hdr.Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
|
|
mpt_clear_taskmgmt_in_progress_flag(ioc);
|
|
- ioc->ioctl_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
|
|
- complete(&ioc->ioctl_cmds.done);
|
|
+ ioc->ioctl_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
|
|
+ complete(&ioc->ioctl_cmds.done);
|
|
+ if (ioc->bus_type == SAS)
|
|
+ ioc->schedule_target_reset(ioc);
|
|
+ } else {
|
|
+ ioc->ioctl_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
|
|
+ complete(&ioc->ioctl_cmds.done);
|
|
+ }
|
|
}
|
|
|
|
out_continuation:
|
|
@@ -275,55 +323,14 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME
|
|
return 1;
|
|
}
|
|
|
|
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
-/* mptctl_timeout_expired
|
|
- *
|
|
- * Expecting an interrupt, however timed out.
|
|
- *
|
|
- */
|
|
-static void
|
|
-mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
|
|
-{
|
|
- unsigned long flags;
|
|
-
|
|
- dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": %s\n",
|
|
- ioc->name, __func__));
|
|
-
|
|
- if (mpt_fwfault_debug)
|
|
- mpt_halt_firmware(ioc);
|
|
-
|
|
- spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
|
|
- if (ioc->ioc_reset_in_progress) {
|
|
- spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
- CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status)
|
|
- mpt_free_msg_frame(ioc, mf);
|
|
- return;
|
|
- }
|
|
- spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
-
|
|
-
|
|
- if (!mptctl_bus_reset(ioc, mf->u.hdr.Function))
|
|
- return;
|
|
-
|
|
- /* Issue a reset for this device.
|
|
- * The IOC is not responding.
|
|
- */
|
|
- dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
|
|
- ioc->name));
|
|
- CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status)
|
|
- mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
- mpt_free_msg_frame(ioc, mf);
|
|
-}
|
|
-
|
|
static int
|
|
mptctl_taskmgmt_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
|
|
{
|
|
if (!mf)
|
|
return 0;
|
|
|
|
- dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- "TaskMgmt completed (mf=%p, mr=%p)\n",
|
|
- ioc->name, mf, mr));
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p, mr=%p)\n",
|
|
+ ioc->name, mf, mr));
|
|
|
|
ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
|
|
|
|
@@ -338,17 +345,15 @@ mptctl_taskmgmt_reply(MPT_ADAPTER *ioc,
|
|
mpt_clear_taskmgmt_in_progress_flag(ioc);
|
|
ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
|
|
complete(&ioc->taskmgmt_cmds.done);
|
|
+ if (ioc->bus_type == SAS)
|
|
+ ioc->schedule_target_reset(ioc);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
-/* mptctl_bus_reset
|
|
- *
|
|
- * Bus reset code.
|
|
- *
|
|
- */
|
|
-static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)
|
|
+static int
|
|
+mptctl_do_taskmgmt(MPT_ADAPTER *ioc, u8 tm_type, u8 bus_id, u8 target_id)
|
|
{
|
|
MPT_FRAME_HDR *mf;
|
|
SCSITaskMgmt_t *pScsiTm;
|
|
@@ -359,13 +364,6 @@ static int mptctl_bus_reset(MPT_ADAPTER
|
|
unsigned long time_count;
|
|
u16 iocstatus;
|
|
|
|
- /* bus reset is only good for SCSI IO, RAID PASSTHRU */
|
|
- if (!(function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) ||
|
|
- (function == MPI_FUNCTION_SCSI_IO_REQUEST)) {
|
|
- dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
|
|
- "TaskMgmt, not SCSI_IO!!\n", ioc->name));
|
|
- return -EPERM;
|
|
- }
|
|
|
|
mutex_lock(&ioc->taskmgmt_cmds.mutex);
|
|
if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
|
|
@@ -375,15 +373,13 @@ static int mptctl_bus_reset(MPT_ADAPTER
|
|
|
|
retval = 0;
|
|
|
|
- /* Send request
|
|
- */
|
|
- mf = mpt_get_msg_frame(mptctl_taskmgmt_id, ioc);
|
|
- if (mf == NULL) {
|
|
- dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
|
|
- "TaskMgmt, no msg frames!!\n", ioc->name));
|
|
+ if ((mf = mpt_get_msg_frame(mptctl_taskmgmt_id, ioc)) == NULL) {
|
|
+ dtmprintk(ioc,
|
|
+ printk(MYIOC_s_WARN_FMT "TaskMgmt, no msg frames!!\n",
|
|
+ ioc->name));
|
|
mpt_clear_taskmgmt_in_progress_flag(ioc);
|
|
retval = -ENOMEM;
|
|
- goto mptctl_bus_reset_done;
|
|
+ goto tm_done;
|
|
}
|
|
|
|
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
|
|
@@ -392,10 +388,13 @@ static int mptctl_bus_reset(MPT_ADAPTER
|
|
pScsiTm = (SCSITaskMgmt_t *) mf;
|
|
memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
|
|
pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
|
|
- pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
|
|
- pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
|
|
- pScsiTm->TargetID = 0;
|
|
- pScsiTm->Bus = 0;
|
|
+ pScsiTm->TaskType = tm_type;
|
|
+ if ((tm_type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) &&
|
|
+ (ioc->bus_type == FC))
|
|
+ pScsiTm->MsgFlags =
|
|
+ MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
|
|
+ pScsiTm->TargetID = target_id;
|
|
+ pScsiTm->Bus = bus_id;
|
|
pScsiTm->ChainOffset = 0;
|
|
pScsiTm->Reserved = 0;
|
|
pScsiTm->Reserved1 = 0;
|
|
@@ -406,43 +405,45 @@ static int mptctl_bus_reset(MPT_ADAPTER
|
|
pScsiTm->Reserved2[ii] = 0;
|
|
|
|
switch (ioc->bus_type) {
|
|
- case FC:
|
|
- timeout = 40;
|
|
- break;
|
|
- case SAS:
|
|
- timeout = 30;
|
|
- break;
|
|
- case SPI:
|
|
- default:
|
|
- timeout = 2;
|
|
- break;
|
|
+ case FC:
|
|
+ timeout = 40;
|
|
+ break;
|
|
+ case SAS:
|
|
+ timeout = 30;
|
|
+ break;
|
|
+ case SPI:
|
|
+ default:
|
|
+ timeout = 10;
|
|
+ break;
|
|
}
|
|
|
|
- dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- "TaskMgmt type=%d timeout=%ld\n",
|
|
- ioc->name, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, timeout));
|
|
+ dtmprintk(ioc,
|
|
+ printk(MYIOC_s_DEBUG_FMT "TaskMgmt type=%d timeout=%ld\n",
|
|
+ ioc->name, tm_type, timeout));
|
|
|
|
INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
|
|
- CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
|
|
time_count = jiffies;
|
|
if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
|
|
(ioc->facts.MsgVersion >= MPI_VERSION_01_05))
|
|
mpt_put_msg_frame_hi_pri(mptctl_taskmgmt_id, ioc, mf);
|
|
else {
|
|
retval = mpt_send_handshake_request(mptctl_taskmgmt_id, ioc,
|
|
- sizeof(SCSITaskMgmt_t), (u32 *)pScsiTm, CAN_SLEEP);
|
|
+ sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
|
|
if (retval != 0) {
|
|
- dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
|
|
+ dfailprintk(ioc,
|
|
+ printk(MYIOC_s_ERR_FMT
|
|
"TaskMgmt send_handshake FAILED!"
|
|
" (ioc %p, mf %p, rc=%d) \n", ioc->name,
|
|
ioc, mf, retval));
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
mpt_clear_taskmgmt_in_progress_flag(ioc);
|
|
- goto mptctl_bus_reset_done;
|
|
+ goto tm_done;
|
|
}
|
|
}
|
|
|
|
/* Now wait for the command to complete */
|
|
ii = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ);
|
|
+
|
|
if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
"TaskMgmt failed\n", ioc->name));
|
|
@@ -452,14 +453,14 @@ static int mptctl_bus_reset(MPT_ADAPTER
|
|
retval = 0;
|
|
else
|
|
retval = -1; /* return failure */
|
|
- goto mptctl_bus_reset_done;
|
|
+ goto tm_done;
|
|
}
|
|
|
|
if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
|
|
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
"TaskMgmt failed\n", ioc->name));
|
|
retval = -1; /* return failure */
|
|
- goto mptctl_bus_reset_done;
|
|
+ goto tm_done;
|
|
}
|
|
|
|
pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
|
|
@@ -467,7 +468,7 @@ static int mptctl_bus_reset(MPT_ADAPTER
|
|
"TaskMgmt fw_channel = %d, fw_id = %d, task_type=0x%02X, "
|
|
"iocstatus=0x%04X\n\tloginfo=0x%08X, response_code=0x%02X, "
|
|
"term_cmnds=%d\n", ioc->name, pScsiTmReply->Bus,
|
|
- pScsiTmReply->TargetID, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
|
|
+ pScsiTmReply->TargetID, tm_type,
|
|
le16_to_cpu(pScsiTmReply->IOCStatus),
|
|
le32_to_cpu(pScsiTmReply->IOCLogInfo),
|
|
pScsiTmReply->ResponseCode,
|
|
@@ -485,14 +486,67 @@ static int mptctl_bus_reset(MPT_ADAPTER
|
|
retval = -1; /* return failure */
|
|
}
|
|
|
|
-
|
|
- mptctl_bus_reset_done:
|
|
+ tm_done:
|
|
mutex_unlock(&ioc->taskmgmt_cmds.mutex);
|
|
CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
|
|
return retval;
|
|
}
|
|
|
|
|
|
+static void
|
|
+mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ int ret_val = -1;
|
|
+ SCSIIORequest_t *scsi_req = (SCSIIORequest_t *) mf;
|
|
+ u8 function = mf->u.hdr.Function;
|
|
+
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": %s\n",
|
|
+ ioc->name, __FUNCTION__));
|
|
+
|
|
+ if(mpt_fwfault_debug)
|
|
+ mpt_halt_firmware(ioc);
|
|
+
|
|
+ spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
|
|
+ if (ioc->ioc_reset_in_progress) {
|
|
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
+ CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status)
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ return;
|
|
+ }
|
|
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
+
|
|
+
|
|
+ CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status)
|
|
+
|
|
+ if (ioc->bus_type == SAS) {
|
|
+ if (function == MPI_FUNCTION_SCSI_IO_REQUEST)
|
|
+ ret_val = mptctl_do_taskmgmt(ioc,
|
|
+ MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
|
|
+ scsi_req->Bus, scsi_req->TargetID);
|
|
+ else if (function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)
|
|
+ ret_val = mptctl_do_taskmgmt(ioc,
|
|
+ MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
|
|
+ scsi_req->Bus, 0);
|
|
+ if (!ret_val)
|
|
+ return;
|
|
+ } else {
|
|
+ if ((function == MPI_FUNCTION_SCSI_IO_REQUEST) ||
|
|
+ (function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH))
|
|
+ ret_val = mptctl_do_taskmgmt(ioc,
|
|
+ MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
|
|
+ scsi_req->Bus, 0);
|
|
+ if (!ret_val)
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling Reset! \n",
|
|
+ ioc->name));
|
|
+ if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
|
|
+ mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+}
|
|
+
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/* mptctl_ioc_reset
|
|
*
|
|
@@ -580,15 +634,17 @@ static int
|
|
mptctl_fasync(int fd, struct file *filep, int mode)
|
|
{
|
|
MPT_ADAPTER *ioc;
|
|
- int ret;
|
|
|
|
- lock_kernel();
|
|
list_for_each_entry(ioc, &ioc_list, list)
|
|
ioc->aen_event_read_flag=0;
|
|
|
|
- ret = fasync_helper(fd, filep, mode, &async_queue);
|
|
- unlock_kernel();
|
|
- return ret;
|
|
+ return fasync_helper(fd, filep, mode, &async_queue);
|
|
+}
|
|
+
|
|
+static int
|
|
+mptctl_release(struct inode *inode, struct file *filep)
|
|
+{
|
|
+ return fasync_helper(-1, filep, 0, &async_queue);
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
@@ -608,6 +664,7 @@ __mptctl_ioctl(struct file *file, unsign
|
|
int ret;
|
|
MPT_ADAPTER *iocp = NULL;
|
|
|
|
+
|
|
if (copy_from_user(&khdr, uhdr, sizeof(khdr))) {
|
|
printk(KERN_ERR MYNAM "%s::mptctl_ioctl() @%d - "
|
|
"Unable to copy mpt_ioctl_header data @ %p\n",
|
|
@@ -624,12 +681,6 @@ __mptctl_ioctl(struct file *file, unsign
|
|
(iocp == NULL))
|
|
return -ENODEV;
|
|
|
|
- if (!iocp->active) {
|
|
- printk(KERN_DEBUG MYNAM "%s::mptctl_ioctl() @%d - Controller disabled.\n",
|
|
- __FILE__, __LINE__);
|
|
- return -EFAULT;
|
|
- }
|
|
-
|
|
/* Handle those commands that are just returning
|
|
* information stored in the driver.
|
|
* These commands should never time out and are unaffected
|
|
@@ -649,6 +700,25 @@ __mptctl_ioctl(struct file *file, unsign
|
|
return mptctl_eventreport(arg);
|
|
} else if (cmd == MPTFWREPLACE) {
|
|
return mptctl_replace_fw(arg);
|
|
+#if defined(DIAG_BUFFER_SUPPORT)
|
|
+/* diag_buffer static data calls*/
|
|
+ } else if (cmd == MPTDIAGQUERY) {
|
|
+ return mptctl_query_diag_buffer(arg);
|
|
+ } else if (cmd == MPTDIAGUNREGISTER) {
|
|
+ return mptctl_unregister_diag_buffer(arg);
|
|
+#endif
|
|
+
|
|
+#if defined(CPQ_CIM)
|
|
+/* csmisas static data calls*/
|
|
+ } else if (cmd == CC_CSMI_SAS_GET_DRIVER_INFO) {
|
|
+ return csmisas_get_driver_info(arg);
|
|
+ } else if (cmd == CC_CSMI_SAS_GET_CNTLR_STATUS) {
|
|
+ return csmisas_get_cntlr_status(arg);
|
|
+ } else if (cmd == CC_CSMI_SAS_GET_SCSI_ADDRESS) {
|
|
+ return csmisas_get_scsi_address(arg);
|
|
+ } else if (cmd == CC_CSMI_SAS_GET_DEVICE_ADDRESS){
|
|
+ return csmisas_get_device_address(arg);
|
|
+#endif // CPQ_CIM
|
|
}
|
|
|
|
/* All of these commands require an interrupt or
|
|
@@ -657,6 +727,8 @@ __mptctl_ioctl(struct file *file, unsign
|
|
if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0)
|
|
return ret;
|
|
|
|
+// dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT ": mptctl_ioctl()\n", iocp->name));
|
|
+
|
|
if (cmd == MPTFWDOWNLOAD)
|
|
ret = mptctl_fw_download(arg);
|
|
else if (cmd == MPTCOMMAND)
|
|
@@ -667,6 +739,57 @@ __mptctl_ioctl(struct file *file, unsign
|
|
ret = mptctl_hp_hostinfo(arg, _IOC_SIZE(cmd));
|
|
else if (cmd == HP_GETTARGETINFO)
|
|
ret = mptctl_hp_targetinfo(arg);
|
|
+#if defined(CPQ_CIM)
|
|
+/* csmisas requiring fw calls*/
|
|
+ else if (cmd == CC_CSMI_SAS_GET_CNTLR_CONFIG)
|
|
+ ret = csmisas_get_cntlr_config(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_GET_PHY_INFO)
|
|
+ ret = csmisas_get_phy_info(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_GET_SATA_SIGNATURE)
|
|
+ ret = csmisas_get_sata_signature(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_GET_LINK_ERRORS)
|
|
+ ret = csmisas_get_link_errors(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_SMP_PASSTHRU)
|
|
+ ret = csmisas_smp_passthru(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_SSP_PASSTHRU)
|
|
+ ret = csmisas_ssp_passthru(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_FIRMWARE_DOWNLOAD)
|
|
+ ret = csmisas_firmware_download(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_GET_RAID_INFO)
|
|
+ ret = csmisas_get_raid_info(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_GET_RAID_CONFIG)
|
|
+ ret = csmisas_get_raid_config(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_GET_RAID_FEATURES)
|
|
+ ret = csmisas_get_raid_features(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_SET_RAID_CONTROL)
|
|
+ ret = csmisas_set_raid_control(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_GET_RAID_ELEMENT)
|
|
+ ret = csmisas_get_raid_element(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_SET_RAID_OPERATION)
|
|
+ ret = csmisas_set_raid_operation(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_SET_PHY_INFO)
|
|
+ ret = csmisas_set_phy_info(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_STP_PASSTHRU)
|
|
+ ret = csmisas_stp_passthru(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_TASK_MANAGEMENT)
|
|
+ ret = csmisas_task_managment(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_PHY_CONTROL)
|
|
+ ret = csmisas_phy_control(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_GET_CONNECTOR_INFO)
|
|
+ ret = csmisas_get_connector_info(arg);
|
|
+ else if (cmd == CC_CSMI_SAS_GET_LOCATION)
|
|
+ ret = csmisas_get_location(arg);
|
|
+#endif // CPQ_CIM
|
|
+
|
|
+#if defined(DIAG_BUFFER_SUPPORT)
|
|
+/* diag_buffer requiring fw calls*/
|
|
+ else if (cmd == MPTDIAGREGISTER)
|
|
+ ret = mptctl_register_diag_buffer(arg);
|
|
+ else if (cmd == MPTDIAGRELEASE)
|
|
+ ret = mptctl_release_diag_buffer(arg);
|
|
+ else if (cmd == MPTDIAGREADBUFFER)
|
|
+ ret = mptctl_read_diag_buffer(arg);
|
|
+#endif // DIAG_BUFFER_SUPPORT
|
|
else
|
|
ret = -EINVAL;
|
|
|
|
@@ -699,6 +822,7 @@ static int mptctl_do_reset(unsigned long
|
|
}
|
|
|
|
if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) {
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
printk(KERN_DEBUG MYNAM "%s@%d::mptctl_do_reset - ioc%d not found!\n",
|
|
__FILE__, __LINE__, krinfo.hdr.iocnum);
|
|
return -ENODEV; /* (-6) No such device or address */
|
|
@@ -789,13 +913,13 @@ mptctl_do_fw_download(int ioc, char __us
|
|
unsigned long timeleft;
|
|
|
|
if (mpt_verify_adapter(ioc, &iocp) < 0) {
|
|
- printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n",
|
|
- ioc);
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
+ printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n", ioc);
|
|
return -ENODEV; /* (-6) No such device or address */
|
|
} else {
|
|
|
|
/* Valid device. Get a message frame and construct the FW download message.
|
|
- */
|
|
+ */
|
|
if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
|
|
return -EAGAIN;
|
|
}
|
|
@@ -870,8 +994,7 @@ mptctl_do_fw_download(int ioc, char __us
|
|
* 96 8
|
|
* 64 4
|
|
*/
|
|
- maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) -
|
|
- sizeof(FWDownloadTCSGE_t))
|
|
+ maxfrags = (iocp->req_sz - sizeof(MPIHeader_t) - sizeof(FWDownloadTCSGE_t))
|
|
/ iocp->SGE_size;
|
|
if (numfrags > maxfrags) {
|
|
ret = -EMLINK;
|
|
@@ -904,8 +1027,8 @@ mptctl_do_fw_download(int ioc, char __us
|
|
n++;
|
|
if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {
|
|
printk(MYIOC_s_ERR_FMT "%s@%d::_ioctl_fwdl - "
|
|
- "Unable to copy f/w buffer hunk#%d @ %p\n",
|
|
- iocp->name, __FILE__, __LINE__, n, ufwbuf);
|
|
+ "Unable to copy f/w buffer hunk#%d @ %p\n",
|
|
+ iocp->name, __FILE__, __LINE__, n, ufwbuf);
|
|
goto fwdl_out;
|
|
}
|
|
fw_bytes_copied += bl->len;
|
|
@@ -930,7 +1053,7 @@ retry_wait:
|
|
timeleft = wait_for_completion_timeout(&iocp->ioctl_cmds.done, HZ*60);
|
|
if (!(iocp->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
ret = -ETIME;
|
|
- printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __func__);
|
|
+ printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __FUNCTION__);
|
|
if (iocp->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
|
|
mpt_free_msg_frame(iocp, mf);
|
|
goto fwdl_out;
|
|
@@ -943,7 +1066,7 @@ retry_wait:
|
|
}
|
|
|
|
if (!(iocp->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
|
|
- printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __func__);
|
|
+ printk(MYIOC_s_WARN_FMT "%s: failed\n", iocp->name, __FUNCTION__);
|
|
mpt_free_msg_frame(iocp, mf);
|
|
ret = -ENODATA;
|
|
goto fwdl_out;
|
|
@@ -955,21 +1078,21 @@ retry_wait:
|
|
ReplyMsg = (pFWDownloadReply_t)iocp->ioctl_cmds.reply;
|
|
iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;
|
|
if (iocstat == MPI_IOCSTATUS_SUCCESS) {
|
|
- printk(MYIOC_s_INFO_FMT "F/W update successfull!\n", iocp->name);
|
|
+ printk(MYIOC_s_INFO_FMT ": F/W update successfully sent!\n", iocp->name);
|
|
return 0;
|
|
} else if (iocstat == MPI_IOCSTATUS_INVALID_FUNCTION) {
|
|
- printk(MYIOC_s_WARN_FMT "Hmmm... F/W download not supported!?!\n",
|
|
- iocp->name);
|
|
+ printk(MYIOC_s_WARN_FMT "Hmmm... doesn't support F/W download?\n",
|
|
+ iocp->name);
|
|
printk(MYIOC_s_WARN_FMT "(time to go bang on somebodies door)\n",
|
|
- iocp->name);
|
|
+ iocp->name);
|
|
return -EBADRQC;
|
|
} else if (iocstat == MPI_IOCSTATUS_BUSY) {
|
|
printk(MYIOC_s_WARN_FMT "IOC_BUSY!\n", iocp->name);
|
|
printk(MYIOC_s_WARN_FMT "(try again later?)\n", iocp->name);
|
|
return -EBUSY;
|
|
} else {
|
|
- printk(MYIOC_s_WARN_FMT "ioctl_fwdl() returned [bad] status = %04xh\n",
|
|
- iocp->name, iocstat);
|
|
+ printk(MYIOC_s_WARN_FMT "returned [bad] status = %04xh\n",
|
|
+ iocp->name, iocstat);
|
|
printk(MYIOC_s_WARN_FMT "(bad VooDoo)\n", iocp->name);
|
|
return -ENOMSG;
|
|
}
|
|
@@ -979,7 +1102,7 @@ fwdl_out:
|
|
|
|
CLEAR_MGMT_STATUS(iocp->ioctl_cmds.status);
|
|
SET_MGMT_MSG_CONTEXT(iocp->ioctl_cmds.msg_context, 0);
|
|
- kfree_sgl(sgl, sgl_dma, buflist, iocp);
|
|
+ kfree_sgl(sgl, sgl_dma, buflist, iocp);
|
|
return ret;
|
|
}
|
|
|
|
@@ -1061,9 +1184,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i
|
|
alloc_sz = alloc_sz / 2;
|
|
if (alloc_sz == 0) {
|
|
printk(MYIOC_s_WARN_FMT "-SG: No can do - "
|
|
- "not enough memory! :-(\n", ioc->name);
|
|
+ "not enough memory! :-(\n", ioc->name);
|
|
printk(MYIOC_s_WARN_FMT "-SG: (freeing %d frags)\n",
|
|
- ioc->name, numfrags);
|
|
+ ioc->name, numfrags);
|
|
goto free_and_fail;
|
|
}
|
|
continue;
|
|
@@ -1072,8 +1195,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i
|
|
|
|
bytes_allocd += this_alloc;
|
|
sgl->FlagsLength = (0x10000000|sgdir|this_alloc);
|
|
- dma_addr = pci_map_single(ioc->pcidev,
|
|
- buflist[buflist_ent].kptr, this_alloc, dir);
|
|
+ if (ioc->sg_addr_size == sizeof(u64))
|
|
+ sgl->FlagsLength |= MPT_SGE_FLAGS_64_BIT_ADDRESSING;
|
|
+ dma_addr = pci_map_single(ioc->pcidev, buflist[buflist_ent].kptr, this_alloc, dir);
|
|
sgl->Address = dma_addr;
|
|
|
|
fragcnt++;
|
|
@@ -1087,8 +1211,8 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i
|
|
|
|
/* Need to chain? */
|
|
if (fragcnt == sg_spill) {
|
|
- printk(MYIOC_s_WARN_FMT
|
|
- "-SG: No can do - " "Chain required! :-(\n", ioc->name);
|
|
+ printk(MYIOC_s_WARN_FMT "-SG: No can do - "
|
|
+ "Chain required! :-(\n", ioc->name);
|
|
printk(MYIOC_s_WARN_FMT "(freeing %d frags)\n", ioc->name, numfrags);
|
|
goto free_and_fail;
|
|
}
|
|
@@ -1097,9 +1221,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i
|
|
if (numfrags*8 > MAX_SGL_BYTES){
|
|
/* GRRRRR... */
|
|
printk(MYIOC_s_WARN_FMT "-SG: No can do - "
|
|
- "too many SG frags! :-(\n", ioc->name);
|
|
+ "too many SG frags! :-(\n", ioc->name);
|
|
printk(MYIOC_s_WARN_FMT "-SG: (freeing %d frags)\n",
|
|
- ioc->name, numfrags);
|
|
+ ioc->name, numfrags);
|
|
goto free_and_fail;
|
|
}
|
|
}
|
|
@@ -1221,7 +1345,7 @@ mptctl_getiocinfo (unsigned long arg, un
|
|
unsigned int port;
|
|
int cim_rev;
|
|
u8 revision;
|
|
- struct scsi_device *sdev;
|
|
+ struct scsi_device *sdev;
|
|
VirtDevice *vdevice;
|
|
|
|
/* Add of PCI INFO results in unaligned access for
|
|
@@ -1256,6 +1380,7 @@ mptctl_getiocinfo (unsigned long arg, un
|
|
|
|
if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
|
|
(ioc == NULL)) {
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
printk(KERN_DEBUG MYNAM "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",
|
|
__FILE__, __LINE__, iocnum);
|
|
kfree(karg);
|
|
@@ -1265,8 +1390,8 @@ mptctl_getiocinfo (unsigned long arg, un
|
|
/* Verify the data transfer size is correct. */
|
|
if (karg->hdr.maxDataSize != data_size) {
|
|
printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - "
|
|
- "Structure size mismatch. Command not completed.\n",
|
|
- ioc->name, __FILE__, __LINE__);
|
|
+ "Structure size mismatch. Command not completed.\n",
|
|
+ ioc->name, __FILE__, __LINE__);
|
|
kfree(karg);
|
|
return -EFAULT;
|
|
}
|
|
@@ -1318,6 +1443,8 @@ mptctl_getiocinfo (unsigned long arg, un
|
|
if (ioc->sh) {
|
|
shost_for_each_device(sdev, ioc->sh) {
|
|
vdevice = sdev->hostdata;
|
|
+ if (vdevice == NULL || vdevice->vtarget == NULL)
|
|
+ continue;
|
|
if (vdevice->vtarget->tflags &
|
|
MPT_TARGET_FLAGS_RAID_COMPONENT)
|
|
continue;
|
|
@@ -1378,7 +1505,7 @@ mptctl_gettargetinfo (unsigned long arg)
|
|
int maxWordsLeft;
|
|
int numBytes;
|
|
u8 port;
|
|
- struct scsi_device *sdev;
|
|
+ struct scsi_device *sdev;
|
|
|
|
if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
|
|
printk(KERN_ERR MYNAM "%s@%d::mptctl_gettargetinfo - "
|
|
@@ -1389,6 +1516,7 @@ mptctl_gettargetinfo (unsigned long arg)
|
|
|
|
if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
(ioc == NULL)) {
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
printk(KERN_DEBUG MYNAM "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",
|
|
__FILE__, __LINE__, iocnum);
|
|
return -ENODEV;
|
|
@@ -1405,8 +1533,8 @@ mptctl_gettargetinfo (unsigned long arg)
|
|
port = karg.hdr.port;
|
|
|
|
if (maxWordsLeft <= 0) {
|
|
- printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo() - no memory available!\n",
|
|
- ioc->name, __FILE__, __LINE__);
|
|
+ printk(MYIOC_s_ERR_FMT "%s::mptctl_gettargetinfo() @%d - no memory available!\n",
|
|
+ ioc->name, __FILE__, __LINE__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
@@ -1426,8 +1554,8 @@ mptctl_gettargetinfo (unsigned long arg)
|
|
*/
|
|
pmem = kzalloc(numBytes, GFP_KERNEL);
|
|
if (!pmem) {
|
|
- printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo() - no memory available!\n",
|
|
- ioc->name, __FILE__, __LINE__);
|
|
+ printk(MYIOC_s_ERR_FMT "%s::mptctl_gettargetinfo() @%d - no memory available!\n",
|
|
+ ioc->name, __FILE__, __LINE__);
|
|
return -ENOMEM;
|
|
}
|
|
pdata = (int *) pmem;
|
|
@@ -1439,6 +1567,8 @@ mptctl_gettargetinfo (unsigned long arg)
|
|
if (!maxWordsLeft)
|
|
continue;
|
|
vdevice = sdev->hostdata;
|
|
+ if (vdevice == NULL || vdevice->vtarget == NULL)
|
|
+ continue;
|
|
if (vdevice->vtarget->tflags &
|
|
MPT_TARGET_FLAGS_RAID_COMPONENT)
|
|
continue;
|
|
@@ -1503,6 +1633,7 @@ mptctl_readtest (unsigned long arg)
|
|
|
|
if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
(ioc == NULL)) {
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
printk(KERN_DEBUG MYNAM "%s::mptctl_readtest() @%d - ioc%d not found!\n",
|
|
__FILE__, __LINE__, iocnum);
|
|
return -ENODEV;
|
|
@@ -1564,6 +1695,7 @@ mptctl_eventquery (unsigned long arg)
|
|
|
|
if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
(ioc == NULL)) {
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
printk(KERN_DEBUG MYNAM "%s::mptctl_eventquery() @%d - ioc%d not found!\n",
|
|
__FILE__, __LINE__, iocnum);
|
|
return -ENODEV;
|
|
@@ -1603,6 +1735,7 @@ mptctl_eventenable (unsigned long arg)
|
|
|
|
if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
(ioc == NULL)) {
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
printk(KERN_DEBUG MYNAM "%s::mptctl_eventenable() @%d - ioc%d not found!\n",
|
|
__FILE__, __LINE__, iocnum);
|
|
return -ENODEV;
|
|
@@ -1616,15 +1749,14 @@ mptctl_eventenable (unsigned long arg)
|
|
int sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
|
|
ioc->events = kzalloc(sz, GFP_KERNEL);
|
|
if (!ioc->events) {
|
|
- printk(MYIOC_s_ERR_FMT
|
|
- ": ERROR - Insufficient memory to add adapter!\n",
|
|
+ printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
|
|
ioc->name);
|
|
return -ENOMEM;
|
|
}
|
|
ioc->alloc_total += sz;
|
|
|
|
ioc->eventContext = 0;
|
|
- }
|
|
+ }
|
|
|
|
/* Update the IOC event logging flag.
|
|
*/
|
|
@@ -1652,13 +1784,14 @@ mptctl_eventreport (unsigned long arg)
|
|
|
|
if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
(ioc == NULL)) {
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
printk(KERN_DEBUG MYNAM "%s::mptctl_eventreport() @%d - ioc%d not found!\n",
|
|
__FILE__, __LINE__, iocnum);
|
|
return -ENODEV;
|
|
}
|
|
+
|
|
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventreport called.\n",
|
|
ioc->name));
|
|
-
|
|
numBytes = karg.hdr.maxDataSize - sizeof(mpt_ioctl_header);
|
|
maxEvents = numBytes/sizeof(MPT_IOCTL_EVENTS);
|
|
|
|
@@ -1706,6 +1839,7 @@ mptctl_replace_fw (unsigned long arg)
|
|
|
|
if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
(ioc == NULL)) {
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
printk(KERN_DEBUG MYNAM "%s::mptctl_replace_fw() @%d - ioc%d not found!\n",
|
|
__FILE__, __LINE__, iocnum);
|
|
return -ENODEV;
|
|
@@ -1737,8 +1871,8 @@ mptctl_replace_fw (unsigned long arg)
|
|
*/
|
|
if (copy_from_user(ioc->cached_fw, uarg->newImage, newFwSize)) {
|
|
printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_replace_fw - "
|
|
- "Unable to read in mpt_ioctl_replace_fw image "
|
|
- "@ %p\n", ioc->name, __FILE__, __LINE__, uarg);
|
|
+ "Unable to read in mpt_ioctl_replace_fw image "
|
|
+ "@ %p\n", ioc->name, __FILE__, __LINE__, uarg);
|
|
mpt_free_fw_memory(ioc);
|
|
return -EFAULT;
|
|
}
|
|
@@ -1755,7 +1889,7 @@ mptctl_replace_fw (unsigned long arg)
|
|
*
|
|
* Outputs: None.
|
|
* Return: 0 if successful
|
|
- * -EBUSY if previous command timeout and IOC reset is not complete.
|
|
+ * -EBUSY if previous command timout and IOC reset is not complete.
|
|
* -EFAULT if data unavailable
|
|
* -ENODEV if no such device/adapter
|
|
* -ETIME if timer expires
|
|
@@ -1780,6 +1914,7 @@ mptctl_mpt_command (unsigned long arg)
|
|
|
|
if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
(ioc == NULL)) {
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
printk(KERN_DEBUG MYNAM "%s::mptctl_mpt_command() @%d - ioc%d not found!\n",
|
|
__FILE__, __LINE__, iocnum);
|
|
return -ENODEV;
|
|
@@ -1795,7 +1930,7 @@ mptctl_mpt_command (unsigned long arg)
|
|
*
|
|
* Outputs: None.
|
|
* Return: 0 if successful
|
|
- * -EBUSY if previous command timeout and IOC reset is not complete.
|
|
+ * -EBUSY if previous command timout and IOC reset is not complete.
|
|
* -EFAULT if data unavailable
|
|
* -ENODEV if no such device/adapter
|
|
* -ETIME if timer expires
|
|
@@ -1818,7 +1953,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
int sz, rc = 0;
|
|
int msgContext;
|
|
u16 req_idx;
|
|
- ulong timeout;
|
|
+ unsigned long timeout;
|
|
unsigned long timeleft;
|
|
struct scsi_device *sdev;
|
|
unsigned long flags;
|
|
@@ -1831,6 +1966,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
|
|
if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
(ioc == NULL)) {
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
printk(KERN_DEBUG MYNAM "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n",
|
|
__FILE__, __LINE__, iocnum);
|
|
return -ENODEV;
|
|
@@ -1862,8 +1998,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
|
|
/* Get a free request frame and save the message context.
|
|
*/
|
|
- if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
|
|
- return -EAGAIN;
|
|
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
|
|
+ return -EAGAIN;
|
|
|
|
hdr = (MPIHeader_t *) mf;
|
|
msgContext = le32_to_cpu(hdr->MsgContext);
|
|
@@ -1884,11 +2020,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
hdr->MsgContext = cpu_to_le32(msgContext);
|
|
function = hdr->Function;
|
|
|
|
-
|
|
/* Verify that this request is allowed.
|
|
*/
|
|
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sending mpi function (0x%02X), req=%p\n",
|
|
- ioc->name, hdr->Function, mf));
|
|
+ ioc->name, function, mf));
|
|
|
|
switch (function) {
|
|
case MPI_FUNCTION_IOC_FACTS:
|
|
@@ -1967,6 +2102,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
struct scsi_target *starget = scsi_target(sdev);
|
|
VirtTarget *vtarget = starget->hostdata;
|
|
|
|
+ if (vtarget == NULL)
|
|
+ continue;
|
|
if ((pScsiReq->TargetID == vtarget->id) &&
|
|
(pScsiReq->Bus == vtarget->channel) &&
|
|
(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
|
|
@@ -1987,7 +2124,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
pScsiReq->Control = cpu_to_le32(scsidir | qtag);
|
|
pScsiReq->DataLength = cpu_to_le32(dataSize);
|
|
|
|
-
|
|
} else {
|
|
printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
|
|
"SCSI driver is not loaded. \n",
|
|
@@ -2000,7 +2136,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
case MPI_FUNCTION_SMP_PASSTHROUGH:
|
|
/* Check mf->PassthruFlags to determine if
|
|
* transfer is ImmediateMode or not.
|
|
- * Immediate mode returns data in the ReplyFrame.
|
|
+ * Immediate mode returns data in the reply.
|
|
* Else, we are sending request and response data
|
|
* in two SGLs at the end of the mf.
|
|
*/
|
|
@@ -2077,12 +2213,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
{
|
|
SCSITaskMgmt_t *pScsiTm;
|
|
pScsiTm = (SCSITaskMgmt_t *)mf;
|
|
- dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- "\tTaskType=0x%x MsgFlags=0x%x "
|
|
- "TaskMsgContext=0x%x id=%d channel=%d\n",
|
|
- ioc->name, pScsiTm->TaskType, le32_to_cpu
|
|
- (pScsiTm->TaskMsgContext), pScsiTm->MsgFlags,
|
|
- pScsiTm->TargetID, pScsiTm->Bus));
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\tTaskType=0x%x MsgFlags=0x%x "
|
|
+ "TaskMsgContext=0x%x id=%d channel=%d\n", ioc->name, pScsiTm->TaskType,
|
|
+ le32_to_cpu(pScsiTm->TaskMsgContext), pScsiTm->MsgFlags,
|
|
+ pScsiTm->TargetID, pScsiTm->Bus));
|
|
break;
|
|
}
|
|
|
|
@@ -2094,7 +2228,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
/* Verify that all entries in the IOC INIT match
|
|
* existing setup (and in LE format).
|
|
*/
|
|
- if (sizeof(dma_addr_t) == sizeof(u64)) {
|
|
+ if (ioc->sg_addr_size == sizeof(u64)) {
|
|
high_addr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32));
|
|
sense_high= cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
|
|
} else {
|
|
@@ -2102,6 +2236,11 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
sense_high= 0;
|
|
}
|
|
|
|
+ if (!pInit->MaxDevices && !pInit->MaxBuses) {
|
|
+ pInit->MaxDevices = ioc->facts.MaxDevices;
|
|
+ pInit->MaxBuses = ioc->facts.MaxBuses;
|
|
+ }
|
|
+
|
|
if ((pInit->Flags != 0) || (pInit->MaxDevices != ioc->facts.MaxDevices) ||
|
|
(pInit->MaxBuses != ioc->facts.MaxBuses) ||
|
|
(pInit->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) ||
|
|
@@ -2137,12 +2276,12 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
MPI_FUNCTION_FC_ABORT
|
|
MPI_FUNCTION_LAN_SEND
|
|
MPI_FUNCTION_LAN_RECEIVE
|
|
- MPI_FUNCTION_LAN_RESET
|
|
+ MPI_FUNCTION_LAN_RESET
|
|
*/
|
|
|
|
printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
|
|
"Illegal request (function 0x%x) \n",
|
|
- ioc->name, __FILE__, __LINE__, hdr->Function);
|
|
+ ioc->name, __FILE__, __LINE__, function);
|
|
rc = -EFAULT;
|
|
goto done_free_mem;
|
|
}
|
|
@@ -2168,7 +2307,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
if (karg.dataInSize > 0) {
|
|
flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
|
|
MPI_SGE_FLAGS_END_OF_BUFFER |
|
|
- MPI_SGE_FLAGS_DIRECTION)
|
|
+ MPI_SGE_FLAGS_DIRECTION )
|
|
<< MPI_SGE_FLAGS_SHIFT;
|
|
} else {
|
|
flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
|
|
@@ -2230,7 +2369,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
|
|
SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, hdr->MsgContext);
|
|
INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
|
|
- if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
|
|
+ if (function == MPI_FUNCTION_SCSI_TASK_MGMT) {
|
|
|
|
mutex_lock(&ioc->taskmgmt_cmds.mutex);
|
|
if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
|
|
@@ -2244,8 +2383,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
(ioc->facts.MsgVersion >= MPI_VERSION_01_05))
|
|
mpt_put_msg_frame_hi_pri(mptctl_id, ioc, mf);
|
|
else {
|
|
- rc =mpt_send_handshake_request(mptctl_id, ioc,
|
|
- sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
|
|
+ rc = mpt_send_handshake_request(mptctl_id, ioc,
|
|
+ sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
|
|
if (rc != 0) {
|
|
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
|
|
"send_handshake FAILED! (ioc %p, mf %p)\n",
|
|
@@ -2256,19 +2395,17 @@ mptctl_do_mpt_command (struct mpt_ioctl_
|
|
goto done_free_mem;
|
|
}
|
|
}
|
|
-
|
|
} else
|
|
mpt_put_msg_frame(mptctl_id, ioc, mf);
|
|
|
|
/* Now wait for the command to complete */
|
|
timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
|
|
retry_wait:
|
|
- timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
|
|
- HZ*timeout);
|
|
+ timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done, HZ*timeout);
|
|
if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
rc = -ETIME;
|
|
dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "%s: TIMED OUT!\n",
|
|
- ioc->name, __func__));
|
|
+ ioc->name, __FUNCTION__));
|
|
if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
|
|
if (function == MPI_FUNCTION_SCSI_TASK_MGMT)
|
|
mutex_unlock(&ioc->taskmgmt_cmds.mutex);
|
|
@@ -2279,7 +2416,8 @@ retry_wait:
|
|
mutex_unlock(&ioc->taskmgmt_cmds.mutex);
|
|
mptctl_timeout_expired(ioc, mf);
|
|
mf = NULL;
|
|
- } else
|
|
+ }
|
|
+ else
|
|
goto retry_wait;
|
|
goto done_free_mem;
|
|
}
|
|
@@ -2287,7 +2425,6 @@ retry_wait:
|
|
if (function == MPI_FUNCTION_SCSI_TASK_MGMT)
|
|
mutex_unlock(&ioc->taskmgmt_cmds.mutex);
|
|
|
|
-
|
|
mf = NULL;
|
|
|
|
/* If a valid reply frame, copy to the user.
|
|
@@ -2295,8 +2432,7 @@ retry_wait:
|
|
*/
|
|
if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) {
|
|
if (karg.maxReplyBytes < ioc->reply_sz) {
|
|
- sz = min(karg.maxReplyBytes,
|
|
- 4*ioc->ioctl_cmds.reply[2]);
|
|
+ sz = min(karg.maxReplyBytes, 4*ioc->ioctl_cmds.reply[2]);
|
|
} else {
|
|
sz = min(ioc->reply_sz, 4*ioc->ioctl_cmds.reply[2]);
|
|
}
|
|
@@ -2318,8 +2454,7 @@ retry_wait:
|
|
if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_SENSE_VALID) {
|
|
sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
|
|
if (sz > 0) {
|
|
- if (copy_to_user(karg.senseDataPtr,
|
|
- ioc->ioctl_cmds.sense, sz)) {
|
|
+ if (copy_to_user(karg.senseDataPtr, ioc->ioctl_cmds.sense, sz)) {
|
|
printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
|
|
"Unable to write sense data to user %p\n",
|
|
ioc->name, __FILE__, __LINE__,
|
|
@@ -2334,8 +2469,7 @@ retry_wait:
|
|
* to user.
|
|
*/
|
|
if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD) &&
|
|
- (karg.dataInSize > 0) && (bufIn.kptr)) {
|
|
-
|
|
+ (karg.dataInSize > 0) && (bufIn.kptr)) {
|
|
if (copy_to_user(karg.dataInBufPtr,
|
|
bufIn.kptr, karg.dataInSize)) {
|
|
printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - "
|
|
@@ -2378,7 +2512,7 @@ done_free_mem:
|
|
* Outputs: None.
|
|
* Return: 0 if successful
|
|
* -EFAULT if data unavailable
|
|
- * -EBUSY if previous command timeout and IOC reset is not complete.
|
|
+ * -EBUSY if previous command timout and IOC reset is not complete.
|
|
* -ENODEV if no such device/adapter
|
|
* -ETIME if timer expires
|
|
* -ENOMEM if memory allocation error
|
|
@@ -2389,18 +2523,17 @@ mptctl_hp_hostinfo(unsigned long arg, un
|
|
hp_host_info_t __user *uarg = (void __user *) arg;
|
|
MPT_ADAPTER *ioc;
|
|
struct pci_dev *pdev;
|
|
- char *pbuf=NULL;
|
|
+ char *pbuf=NULL;
|
|
dma_addr_t buf_dma;
|
|
hp_host_info_t karg;
|
|
- CONFIGPARMS cfg;
|
|
- ConfigPageHeader_t hdr;
|
|
int iocnum;
|
|
- int rc, cim_rev;
|
|
+ int cim_rev;
|
|
ToolboxIstwiReadWriteRequest_t *IstwiRWRequest;
|
|
MPT_FRAME_HDR *mf = NULL;
|
|
MPIHeader_t *mpi_hdr;
|
|
unsigned long timeleft;
|
|
int retval;
|
|
+ u32 MsgContext;
|
|
|
|
/* Reset long to int. Should affect IA64 and SPARC only
|
|
*/
|
|
@@ -2420,13 +2553,14 @@ mptctl_hp_hostinfo(unsigned long arg, un
|
|
|
|
if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
(ioc == NULL)) {
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
printk(KERN_DEBUG MYNAM "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n",
|
|
__FILE__, __LINE__, iocnum);
|
|
return -ENODEV;
|
|
}
|
|
+
|
|
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": mptctl_hp_hostinfo called.\n",
|
|
ioc->name));
|
|
-
|
|
/* Fill in the data and return the structure to the calling
|
|
* program
|
|
*/
|
|
@@ -2466,42 +2600,9 @@ mptctl_hp_hostinfo(unsigned long arg, un
|
|
karg.fw_version[10] = (ioc->facts.FWVersion.Struct.Dev % 10 ) + '0';
|
|
karg.fw_version[11] = '\0';
|
|
|
|
- /* Issue a config request to get the device serial number
|
|
- */
|
|
- hdr.PageVersion = 0;
|
|
- hdr.PageLength = 0;
|
|
- hdr.PageNumber = 0;
|
|
- hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
|
|
- cfg.cfghdr.hdr = &hdr;
|
|
- cfg.physAddr = -1;
|
|
- cfg.pageAddr = 0;
|
|
- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
- cfg.dir = 0; /* read */
|
|
- cfg.timeout = 10;
|
|
+ strncpy(karg.serial_number, ioc->board_tracer, 16);
|
|
|
|
- strncpy(karg.serial_number, " ", 24);
|
|
- if (mpt_config(ioc, &cfg) == 0) {
|
|
- if (cfg.cfghdr.hdr->PageLength > 0) {
|
|
- /* Issue the second config page request */
|
|
- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
-
|
|
- pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma);
|
|
- if (pbuf) {
|
|
- cfg.physAddr = buf_dma;
|
|
- if (mpt_config(ioc, &cfg) == 0) {
|
|
- ManufacturingPage0_t *pdata = (ManufacturingPage0_t *) pbuf;
|
|
- if (strlen(pdata->BoardTracerNumber) > 1) {
|
|
- strncpy(karg.serial_number, pdata->BoardTracerNumber, 24);
|
|
- karg.serial_number[24-1]='\0';
|
|
- }
|
|
- }
|
|
- pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
|
|
- pbuf = NULL;
|
|
- }
|
|
- }
|
|
- }
|
|
- rc = mpt_GetIocState(ioc, 1);
|
|
- switch (rc) {
|
|
+ switch (mpt_GetIocState(ioc, 1)) {
|
|
case MPI_IOC_STATE_OPERATIONAL:
|
|
karg.ioc_status = HP_STATUS_OK;
|
|
break;
|
|
@@ -2537,21 +2638,23 @@ mptctl_hp_hostinfo(unsigned long arg, un
|
|
}
|
|
}
|
|
|
|
- /*
|
|
+ /*
|
|
* Gather ISTWI(Industry Standard Two Wire Interface) Data
|
|
*/
|
|
if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) {
|
|
- dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
|
|
- "%s, no msg frames!!\n", ioc->name, __func__));
|
|
+ dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
|
|
+ ioc->name,__FUNCTION__));
|
|
+ retval = -ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
IstwiRWRequest = (ToolboxIstwiReadWriteRequest_t *)mf;
|
|
mpi_hdr = (MPIHeader_t *) mf;
|
|
+ MsgContext = mpi_hdr->MsgContext;
|
|
memset(IstwiRWRequest,0,sizeof(ToolboxIstwiReadWriteRequest_t));
|
|
IstwiRWRequest->Function = MPI_FUNCTION_TOOLBOX;
|
|
IstwiRWRequest->Tool = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL;
|
|
- IstwiRWRequest->MsgContext = mpi_hdr->MsgContext;
|
|
+ IstwiRWRequest->MsgContext = MsgContext;
|
|
IstwiRWRequest->Flags = MPI_TB_ISTWI_FLAGS_READ;
|
|
IstwiRWRequest->NumAddressBytes = 0x01;
|
|
IstwiRWRequest->DataLength = cpu_to_le16(0x04);
|
|
@@ -2561,23 +2664,21 @@ mptctl_hp_hostinfo(unsigned long arg, un
|
|
IstwiRWRequest->DeviceAddr = 0xB0;
|
|
|
|
pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma);
|
|
- if (!pbuf)
|
|
+ if (!pbuf) {
|
|
+ retval = -ENOMEM;
|
|
goto out;
|
|
- ioc->add_sge((char *)&IstwiRWRequest->SGL,
|
|
- (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma);
|
|
+ }
|
|
+ ioc->add_sge((char *)&IstwiRWRequest->SGL, (MPT_SGE_FLAGS_SSIMPLE_READ|4),buf_dma);
|
|
|
|
retval = 0;
|
|
- SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context,
|
|
- IstwiRWRequest->MsgContext);
|
|
+ SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, IstwiRWRequest->MsgContext);
|
|
INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
|
|
mpt_put_msg_frame(mptctl_id, ioc, mf);
|
|
-
|
|
retry_wait:
|
|
- timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
|
|
- HZ*MPT_IOCTL_DEFAULT_TIMEOUT);
|
|
+ timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done, HZ*MPT_IOCTL_DEFAULT_TIMEOUT);
|
|
if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
retval = -ETIME;
|
|
- printk(MYIOC_s_WARN_FMT "%s: failed\n", ioc->name, __func__);
|
|
+ printk(MYIOC_s_WARN_FMT "%s: failed\n", ioc->name, __FUNCTION__);
|
|
if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
|
|
mpt_free_msg_frame(ioc, mf);
|
|
goto out;
|
|
@@ -2617,7 +2718,7 @@ retry_wait:
|
|
return -EFAULT;
|
|
}
|
|
|
|
- return 0;
|
|
+ return retval;
|
|
|
|
}
|
|
|
|
@@ -2627,7 +2728,7 @@ retry_wait:
|
|
* Outputs: None.
|
|
* Return: 0 if successful
|
|
* -EFAULT if data unavailable
|
|
- * -EBUSY if previous command timeout and IOC reset is not complete.
|
|
+ * -EBUSY if previous command timout and IOC reset is not complete.
|
|
* -ENODEV if no such device/adapter
|
|
* -ETIME if timer expires
|
|
* -ENOMEM if memory allocation error
|
|
@@ -2639,12 +2740,12 @@ mptctl_hp_targetinfo(unsigned long arg)
|
|
SCSIDevicePage0_t *pg0_alloc;
|
|
SCSIDevicePage3_t *pg3_alloc;
|
|
MPT_ADAPTER *ioc;
|
|
- MPT_SCSI_HOST *hd = NULL;
|
|
+ MPT_SCSI_HOST *hd = NULL;
|
|
hp_target_info_t karg;
|
|
int iocnum;
|
|
int data_sz;
|
|
dma_addr_t page_dma;
|
|
- CONFIGPARMS cfg;
|
|
+ CONFIGPARMS cfg;
|
|
ConfigPageHeader_t hdr;
|
|
int tmp, np, rc = 0;
|
|
|
|
@@ -2657,13 +2758,14 @@ mptctl_hp_targetinfo(unsigned long arg)
|
|
|
|
if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
(ioc == NULL)) {
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
printk(KERN_DEBUG MYNAM "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
|
|
__FILE__, __LINE__, iocnum);
|
|
return -ENODEV;
|
|
}
|
|
- dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n",
|
|
- ioc->name));
|
|
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": mptctl_hp_targetinfo called.\n",
|
|
+ ioc->name));
|
|
/* There is nothing to do for FCP parts.
|
|
*/
|
|
if ((ioc->bus_type == SAS) || (ioc->bus_type == FC))
|
|
@@ -2773,10 +2875,11 @@ mptctl_hp_targetinfo(unsigned long arg)
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
|
|
-static const struct file_operations mptctl_fops = {
|
|
+static struct file_operations mptctl_fops = {
|
|
.owner = THIS_MODULE,
|
|
.llseek = no_llseek,
|
|
- .fasync = mptctl_fasync,
|
|
+ .release = mptctl_release,
|
|
+ .fasync = mptctl_fasync,
|
|
.unlocked_ioctl = mptctl_ioctl,
|
|
#ifdef CONFIG_COMPAT
|
|
.compat_ioctl = compat_mpctl_ioctl,
|
|
@@ -2812,8 +2915,9 @@ compat_mptfwxfer_ioctl(struct file *filp
|
|
iocnumX = kfw32.iocnum & 0xFF;
|
|
if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
|
|
(iocp == NULL)) {
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
printk(KERN_DEBUG MYNAM "::compat_mptfwxfer_ioctl @%d - ioc%d not found!\n",
|
|
- __LINE__, iocnumX);
|
|
+ __LINE__, iocnumX);
|
|
return -ENODEV;
|
|
}
|
|
|
|
@@ -2852,8 +2956,9 @@ compat_mpt_command(struct file *filp, un
|
|
iocnumX = karg32.hdr.iocnum & 0xFF;
|
|
if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
|
|
(iocp == NULL)) {
|
|
+ if (mpt_debug_level & MPT_DEBUG_IOCTL)
|
|
printk(KERN_DEBUG MYNAM "::compat_mpt_command @%d - ioc%d not found!\n",
|
|
- __LINE__, iocnumX);
|
|
+ __LINE__, iocnumX);
|
|
return -ENODEV;
|
|
}
|
|
|
|
@@ -2902,6 +3007,31 @@ static long compat_mpctl_ioctl(struct fi
|
|
case MPTHARDRESET:
|
|
case HP_GETHOSTINFO:
|
|
case HP_GETTARGETINFO:
|
|
+#if defined(CPQ_CIM)
|
|
+ case CC_CSMI_SAS_GET_DRIVER_INFO:
|
|
+ case CC_CSMI_SAS_GET_CNTLR_CONFIG:
|
|
+ case CC_CSMI_SAS_GET_CNTLR_STATUS:
|
|
+ case CC_CSMI_SAS_GET_SCSI_ADDRESS:
|
|
+ case CC_CSMI_SAS_GET_DEVICE_ADDRESS:
|
|
+ case CC_CSMI_SAS_GET_PHY_INFO:
|
|
+ case CC_CSMI_SAS_GET_SATA_SIGNATURE:
|
|
+ case CC_CSMI_SAS_GET_LINK_ERRORS:
|
|
+ case CC_CSMI_SAS_SMP_PASSTHRU:
|
|
+ case CC_CSMI_SAS_SSP_PASSTHRU:
|
|
+ case CC_CSMI_SAS_FIRMWARE_DOWNLOAD:
|
|
+ case CC_CSMI_SAS_GET_RAID_INFO:
|
|
+ case CC_CSMI_SAS_GET_RAID_CONFIG:
|
|
+ case CC_CSMI_SAS_GET_RAID_FEATURES:
|
|
+ case CC_CSMI_SAS_SET_RAID_CONTROL:
|
|
+ case CC_CSMI_SAS_GET_RAID_ELEMENT:
|
|
+ case CC_CSMI_SAS_SET_RAID_OPERATION:
|
|
+ case CC_CSMI_SAS_SET_PHY_INFO:
|
|
+ case CC_CSMI_SAS_STP_PASSTHRU:
|
|
+ case CC_CSMI_SAS_TASK_MANAGEMENT:
|
|
+ case CC_CSMI_SAS_PHY_CONTROL:
|
|
+ case CC_CSMI_SAS_GET_CONNECTOR_INFO:
|
|
+ case CC_CSMI_SAS_GET_LOCATION:
|
|
+#endif /* CPQ_CIM */
|
|
case MPTTEST:
|
|
ret = __mptctl_ioctl(f, cmd, arg);
|
|
break;
|
|
@@ -2938,6 +3068,7 @@ mptctl_probe(struct pci_dev *pdev, const
|
|
|
|
mutex_init(&ioc->ioctl_cmds.mutex);
|
|
init_completion(&ioc->ioctl_cmds.done);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -2951,6 +3082,22 @@ mptctl_probe(struct pci_dev *pdev, const
|
|
static void
|
|
mptctl_remove(struct pci_dev *pdev)
|
|
{
|
|
+#if defined(DIAG_BUFFER_SUPPORT)
|
|
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
|
+ int i;
|
|
+
|
|
+ /*
|
|
+ * Cleanup diag buffer allocated memory
|
|
+ */
|
|
+ for (i = 0; i < MPI_DIAG_BUF_TYPE_COUNT; i++) {
|
|
+ if (ioc->DiagBuffer[i] == NULL)
|
|
+ continue;
|
|
+ pci_free_consistent(ioc->pcidev, ioc->DiagBuffer_sz[i],
|
|
+ ioc->DiagBuffer[i], ioc->DiagBuffer_dma[i]);
|
|
+ ioc->DiagBuffer[i] = NULL;
|
|
+ ioc->DiagBuffer_Status[i] = 0;
|
|
+ }
|
|
+#endif
|
|
}
|
|
|
|
static struct mpt_pci_driver mptctl_driver = {
|
|
@@ -3012,16 +3159,23 @@ static void mptctl_exit(void)
|
|
|
|
/* De-register reset handler from base module */
|
|
mpt_reset_deregister(mptctl_id);
|
|
+ mpt_reset_deregister(mptctl_taskmgmt_id);
|
|
|
|
/* De-register callback handler from base module */
|
|
mpt_deregister(mptctl_id);
|
|
- mpt_reset_deregister(mptctl_taskmgmt_id);
|
|
-
|
|
- mpt_device_driver_deregister(MPTCTL_DRIVER);
|
|
|
|
+ mpt_device_driver_deregister(MPTCTL_DRIVER);
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
|
|
+#if defined(CPQ_CIM)
|
|
+#include "csmi/csmisas.c"
|
|
+#endif // CPQ_CIM
|
|
+
|
|
+#if defined(DIAG_BUFFER_SUPPORT)
|
|
+#include "rejected_ioctls/diag_buffer.c"
|
|
+#endif
|
|
+
|
|
module_init(mptctl_init);
|
|
module_exit(mptctl_exit);
|
|
--- a/drivers/message/fusion/mptctl.h
|
|
+++ b/drivers/message/fusion/mptctl.h
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * linux/drivers/message/fusion/mptioctl.h
|
|
+ * linux/drivers/message/fusion/mptctl.h
|
|
* Fusion MPT misc device (ioctl) driver.
|
|
* For use with PCI chip/adapter(s):
|
|
* LSIFC9xx/LSI409xx Fibre Channel
|
|
@@ -460,8 +460,5 @@ typedef struct _hp_target_info {
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
|
|
-
|
|
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
-
|
|
#endif
|
|
|
|
--- a/drivers/message/fusion/mptdebug.h
|
|
+++ b/drivers/message/fusion/mptdebug.h
|
|
@@ -17,6 +17,10 @@
|
|
*
|
|
* Example: (programming for MPT_DEBUG_EVENTS on host 5)
|
|
*
|
|
+ * global setting:
|
|
+ * echo 8 > /sys/module/mptbase/parameters/mpt_debug_level
|
|
+ *
|
|
+ * per host setting:
|
|
* echo 8 > /sys/class/scsi_host/host5/debug_level
|
|
*
|
|
* --------------------------------------------------------
|
|
@@ -55,10 +59,11 @@
|
|
#define MPT_DEBUG_RESET 0x00008000
|
|
#define MPT_DEBUG_SCSI 0x00010000
|
|
#define MPT_DEBUG_IOCTL 0x00020000
|
|
+#define MPT_DEBUG_CSMISAS 0x00040000
|
|
#define MPT_DEBUG_FC 0x00080000
|
|
#define MPT_DEBUG_SAS 0x00100000
|
|
#define MPT_DEBUG_SAS_WIDE 0x00200000
|
|
-#define MPT_DEBUG_36GB_MEM 0x00400000
|
|
+#define MPT_DEBUG_36GB_MEM 0x00400000
|
|
|
|
/*
|
|
* CONFIG_FUSION_LOGGING - enabled in Kconfig
|
|
@@ -127,6 +132,9 @@
|
|
#define dctlprintk(IOC, CMD) \
|
|
MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_IOCTL)
|
|
|
|
+#define dcsmisasprintk(IOC, CMD) \
|
|
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CSMISAS)
|
|
+
|
|
#define dfcprintk(IOC, CMD) \
|
|
MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_FC)
|
|
|
|
@@ -139,7 +147,6 @@
|
|
#define d36memprintk(IOC, CMD) \
|
|
MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_36GB_MEM)
|
|
|
|
-
|
|
/*
|
|
* Verbose logging
|
|
*/
|
|
--- a/drivers/message/fusion/mptfc.c
|
|
+++ b/drivers/message/fusion/mptfc.c
|
|
@@ -43,6 +43,7 @@
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
+#include <linux/version.h>
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
@@ -52,8 +53,10 @@
|
|
#include <linux/delay.h> /* for mdelay */
|
|
#include <linux/interrupt.h> /* needed for in_interrupt() proto */
|
|
#include <linux/reboot.h> /* notifier code */
|
|
+#include <linux/sched.h>
|
|
#include <linux/workqueue.h>
|
|
#include <linux/sort.h>
|
|
+#include <linux/pci.h>
|
|
|
|
#include <scsi/scsi.h>
|
|
#include <scsi/scsi_cmnd.h>
|
|
@@ -80,10 +83,18 @@ MODULE_VERSION(my_VERSION);
|
|
static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */
|
|
module_param(mptfc_dev_loss_tmo, int, 0);
|
|
MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
|
|
- " transport to wait for an rport to "
|
|
+ " transport to wait for an rport to "
|
|
" return following a device loss event."
|
|
" Default=60.");
|
|
|
|
+static int mpt_sdev_queue_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
|
|
+static int mptfc_set_sdev_queue_depth(const char *val, struct kernel_param *kp);
|
|
+module_param_call(mpt_sdev_queue_depth, mptfc_set_sdev_queue_depth,
|
|
+ param_get_int, &mpt_sdev_queue_depth, 0600);
|
|
+MODULE_PARM_DESC(mpt_sdev_queue_depth,
|
|
+ " Max Device Queue Depth (default="
|
|
+ __MODULE_STRING(MPT_SCSI_CMD_PER_DEV_HIGH) ")");
|
|
+
|
|
/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
|
|
#define MPTFC_MAX_LUN (16895)
|
|
static int max_lun = MPTFC_MAX_LUN;
|
|
@@ -118,7 +129,7 @@ static struct scsi_host_template mptfc_d
|
|
.slave_configure = mptscsih_slave_configure,
|
|
.target_destroy = mptfc_target_destroy,
|
|
.slave_destroy = mptscsih_slave_destroy,
|
|
- .change_queue_depth = mptscsih_change_queue_depth,
|
|
+ .change_queue_depth = mptscsih_change_queue_depth,
|
|
.eh_abort_handler = mptfc_abort,
|
|
.eh_device_reset_handler = mptfc_dev_reset,
|
|
.eh_bus_reset_handler = mptfc_bus_reset,
|
|
@@ -183,6 +194,35 @@ static struct fc_function_template mptfc
|
|
.show_host_symbolic_name = 1,
|
|
};
|
|
|
|
+/**
|
|
+ * mptfc_set_sdev_queue_depth - global setting of the mpt_sdev_queue_depth
|
|
+ * found via /sys/module/mptfc/parameters/mpt_sdev_queue_depth
|
|
+ * @val:
|
|
+ * @kp:
|
|
+ *
|
|
+ * Returns
|
|
+ **/
|
|
+static int
|
|
+mptfc_set_sdev_queue_depth(const char *val, struct kernel_param *kp)
|
|
+{
|
|
+ int ret = param_set_int(val, kp);
|
|
+ MPT_ADAPTER *ioc;
|
|
+ struct scsi_device *sdev;
|
|
+
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ list_for_each_entry(ioc, &ioc_list, list) {
|
|
+ if (ioc->bus_type != FC)
|
|
+ continue;
|
|
+ shost_for_each_device(sdev, ioc->sh)
|
|
+ mptscsih_change_queue_depth(sdev, mpt_sdev_queue_depth,
|
|
+ SCSI_QDEPTH_DEFAULT);
|
|
+ ioc->sdev_queue_depth = mpt_sdev_queue_depth;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int
|
|
mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
|
|
int (*func)(struct scsi_cmnd *SCpnt),
|
|
@@ -194,7 +234,7 @@ mptfc_block_error_handler(struct scsi_cm
|
|
struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
|
|
unsigned long flags;
|
|
int ready;
|
|
- MPT_ADAPTER *ioc;
|
|
+ MPT_ADAPTER *ioc;
|
|
|
|
hd = shost_priv(SCpnt->device->host);
|
|
ioc = hd->ioc;
|
|
@@ -231,28 +271,28 @@ static int
|
|
mptfc_abort(struct scsi_cmnd *SCpnt)
|
|
{
|
|
return
|
|
- mptfc_block_error_handler(SCpnt, mptscsih_abort, __func__);
|
|
+ mptfc_block_error_handler(SCpnt, mptscsih_abort, __FUNCTION__);
|
|
}
|
|
|
|
static int
|
|
mptfc_dev_reset(struct scsi_cmnd *SCpnt)
|
|
{
|
|
return
|
|
- mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __func__);
|
|
+ mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __FUNCTION__);
|
|
}
|
|
|
|
static int
|
|
mptfc_bus_reset(struct scsi_cmnd *SCpnt)
|
|
{
|
|
return
|
|
- mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __func__);
|
|
+ mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __FUNCTION__);
|
|
}
|
|
|
|
static int
|
|
mptfc_host_reset(struct scsi_cmnd *SCpnt)
|
|
{
|
|
return
|
|
- mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __func__);
|
|
+ mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __FUNCTION__);
|
|
}
|
|
|
|
static void
|
|
@@ -335,7 +375,7 @@ mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, in
|
|
|
|
data_sz = hdr.PageLength * 4;
|
|
ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
|
|
- &page0_dma);
|
|
+ &page0_dma);
|
|
rc = -ENOMEM;
|
|
if (!ppage0_alloc)
|
|
break;
|
|
@@ -371,7 +411,7 @@ mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, in
|
|
*p_pp0++ = p_p0++; /* save addr */
|
|
}
|
|
pci_free_consistent(ioc->pcidev, data_sz,
|
|
- (u8 *) ppage0_alloc, page0_dma);
|
|
+ (u8 *) ppage0_alloc, page0_dma);
|
|
if (rc != 0)
|
|
break;
|
|
|
|
@@ -476,6 +516,7 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int
|
|
if (vtarget) {
|
|
vtarget->id = pg0->CurrentTargetID;
|
|
vtarget->channel = pg0->CurrentBus;
|
|
+ vtarget->deleted = 0;
|
|
}
|
|
}
|
|
*((struct mptfc_rport_info **)rport->dd_data) = ri;
|
|
@@ -513,6 +554,7 @@ mptfc_target_destroy(struct scsi_target
|
|
struct fc_rport *rport;
|
|
struct mptfc_rport_info *ri;
|
|
|
|
+ printk("%s - starget=%p\n", __FUNCTION__, starget);
|
|
rport = starget_to_rport(starget);
|
|
if (rport) {
|
|
ri = *((struct mptfc_rport_info **)rport->dd_data);
|
|
@@ -560,6 +602,7 @@ mptfc_target_alloc(struct scsi_target *s
|
|
|
|
return rc;
|
|
}
|
|
+
|
|
/*
|
|
* mptfc_dump_lun_info
|
|
* @ioc
|
|
@@ -589,7 +632,6 @@ mptfc_dump_lun_info(MPT_ADAPTER *ioc, st
|
|
(unsigned long long)nn));
|
|
}
|
|
|
|
-
|
|
/*
|
|
* OS entry point to allow host driver to alloc memory
|
|
* for each scsi device. Called once per device the bus scan.
|
|
@@ -604,7 +646,7 @@ mptfc_slave_alloc(struct scsi_device *sd
|
|
VirtDevice *vdevice;
|
|
struct scsi_target *starget;
|
|
struct fc_rport *rport;
|
|
- MPT_ADAPTER *ioc;
|
|
+ MPT_ADAPTER *ioc;
|
|
|
|
starget = scsi_target(sdev);
|
|
rport = starget_to_rport(starget);
|
|
@@ -614,11 +656,10 @@ mptfc_slave_alloc(struct scsi_device *sd
|
|
|
|
hd = shost_priv(sdev->host);
|
|
ioc = hd->ioc;
|
|
-
|
|
vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
|
|
if (!vdevice) {
|
|
printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
|
|
- ioc->name, sizeof(VirtDevice));
|
|
+ ioc->name, sizeof(VirtDevice));
|
|
return -ENOMEM;
|
|
}
|
|
|
|
@@ -635,10 +676,7 @@ mptfc_slave_alloc(struct scsi_device *sd
|
|
vdevice->lun = sdev->lun;
|
|
|
|
vtarget->num_luns++;
|
|
-
|
|
-
|
|
mptfc_dump_lun_info(ioc, rport, sdev, vtarget);
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
@@ -944,11 +982,12 @@ start_over:
|
|
return rc;
|
|
}
|
|
|
|
-static void
|
|
+static int
|
|
mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc)
|
|
{
|
|
int ii;
|
|
FCPortPage1_t *pp1;
|
|
+ int rc;
|
|
|
|
#define MPTFC_FW_DEVICE_TIMEOUT (1)
|
|
#define MPTFC_FW_IO_PEND_TIMEOUT (1)
|
|
@@ -956,8 +995,8 @@ mptfc_SetFcPortPage1_defaults(MPT_ADAPTE
|
|
#define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS)
|
|
|
|
for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
|
|
- if (mptfc_GetFcPortPage1(ioc, ii) != 0)
|
|
- continue;
|
|
+ if ((rc = mptfc_GetFcPortPage1(ioc, ii)) < 0)
|
|
+ return rc;
|
|
pp1 = ioc->fc_data.fc_port_page1[ii].data;
|
|
if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT)
|
|
&& (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT)
|
|
@@ -968,8 +1007,10 @@ mptfc_SetFcPortPage1_defaults(MPT_ADAPTE
|
|
pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT;
|
|
pp1->Flags &= ~OFF_FLAGS;
|
|
pp1->Flags |= ON_FLAGS;
|
|
- mptfc_WriteFcPortPage1(ioc, ii);
|
|
+ if ((rc = mptfc_WriteFcPortPage1(ioc, ii)) < 0)
|
|
+ return rc;
|
|
}
|
|
+ return 0;
|
|
}
|
|
|
|
|
|
@@ -1003,10 +1044,10 @@ mptfc_init_host_attr(MPT_ADAPTER *ioc,in
|
|
fc_host_maxframe_size(sh) = pp0->MaxFrameSize;
|
|
|
|
fc_host_node_name(sh) =
|
|
- (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;
|
|
+ (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;
|
|
|
|
fc_host_port_name(sh) =
|
|
- (u64)pp0->WWPN.High << 32 | (u64)pp0->WWPN.Low;
|
|
+ (u64)pp0->WWPN.High << 32 | (u64)pp0->WWPN.Low;
|
|
|
|
fc_host_port_id(sh) = pp0->PortIdentifier;
|
|
|
|
@@ -1082,10 +1123,13 @@ mptfc_link_status_change(struct work_str
|
|
static void
|
|
mptfc_setup_reset(struct work_struct *work)
|
|
{
|
|
- MPT_ADAPTER *ioc =
|
|
+ MPT_ADAPTER *ioc =
|
|
container_of(work, MPT_ADAPTER, fc_setup_reset_work);
|
|
u64 pn;
|
|
struct mptfc_rport_info *ri;
|
|
+ struct scsi_target *starget;
|
|
+ VirtTarget *vtarget;
|
|
+
|
|
|
|
/* reset about to happen, delete (block) all rports */
|
|
list_for_each_entry(ri, &ioc->fc_rports, list) {
|
|
@@ -1093,6 +1137,12 @@ mptfc_setup_reset(struct work_struct *wo
|
|
ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;
|
|
fc_remote_port_delete(ri->rport); /* won't sleep */
|
|
ri->rport = NULL;
|
|
+ starget = ri->starget;
|
|
+ if (starget) {
|
|
+ vtarget = starget->hostdata;
|
|
+ if (vtarget)
|
|
+ vtarget->deleted = 1;
|
|
+ }
|
|
|
|
pn = (u64)ri->pg0.WWPN.High << 32 |
|
|
(u64)ri->pg0.WWPN.Low;
|
|
@@ -1111,8 +1161,22 @@ mptfc_rescan_devices(struct work_struct
|
|
MPT_ADAPTER *ioc =
|
|
container_of(work, MPT_ADAPTER, fc_rescan_work);
|
|
int ii;
|
|
+ int rc;
|
|
u64 pn;
|
|
struct mptfc_rport_info *ri;
|
|
+ struct scsi_target *starget;
|
|
+ VirtTarget *vtarget;
|
|
+
|
|
+ /*
|
|
+ * if cannot set defaults, something's really wrong, bail out
|
|
+ */
|
|
+
|
|
+ if ((rc = mptfc_SetFcPortPage1_defaults(ioc)) < 0) {
|
|
+ dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
|
|
+ "mptfc_rescan.%d: unable to set PP1 defaults, rc %d.\n",
|
|
+ ioc->name, ioc->sh->host_no, rc));
|
|
+ return;
|
|
+ }
|
|
|
|
/* start by tagging all ports as missing */
|
|
list_for_each_entry(ri, &ioc->fc_rports, list) {
|
|
@@ -1140,6 +1204,12 @@ mptfc_rescan_devices(struct work_struct
|
|
MPT_RPORT_INFO_FLAGS_MISSING);
|
|
fc_remote_port_delete(ri->rport); /* won't sleep */
|
|
ri->rport = NULL;
|
|
+ starget = ri->starget;
|
|
+ if (starget) {
|
|
+ vtarget = starget->hostdata;
|
|
+ if (vtarget)
|
|
+ vtarget->deleted = 1;
|
|
+ }
|
|
|
|
pn = (u64)ri->pg0.WWPN.High << 32 |
|
|
(u64)ri->pg0.WWPN.Low;
|
|
@@ -1157,7 +1227,7 @@ mptfc_probe(struct pci_dev *pdev, const
|
|
{
|
|
struct Scsi_Host *sh;
|
|
MPT_SCSI_HOST *hd;
|
|
- MPT_ADAPTER *ioc;
|
|
+ MPT_ADAPTER *ioc;
|
|
unsigned long flags;
|
|
int ii;
|
|
int numSGE = 0;
|
|
@@ -1215,7 +1285,7 @@ mptfc_probe(struct pci_dev *pdev, const
|
|
ioc->name);
|
|
error = -1;
|
|
goto out_mptfc_probe;
|
|
- }
|
|
+ }
|
|
|
|
spin_lock_init(&ioc->fc_rescan_work_lock);
|
|
INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices);
|
|
@@ -1238,6 +1308,10 @@ mptfc_probe(struct pci_dev *pdev, const
|
|
sh->max_id = ioc->pfacts->MaxDevices;
|
|
sh->max_lun = max_lun;
|
|
|
|
+ sh->this_id = ioc->pfacts[0].PortSCSIID;
|
|
+
|
|
+ ioc->sdev_queue_depth = mpt_sdev_queue_depth;
|
|
+
|
|
/* Required entry.
|
|
*/
|
|
sh->unique_id = ioc->id;
|
|
@@ -1300,8 +1374,8 @@ mptfc_probe(struct pci_dev *pdev, const
|
|
|
|
/* initialize workqueue */
|
|
|
|
- snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name),
|
|
- "mptfc_wq_%d", sh->host_no);
|
|
+ snprintf(ioc->fc_rescan_work_q_name, MPT_KOBJ_NAME_LEN, "mptfc_wq_%d",
|
|
+ sh->host_no);
|
|
ioc->fc_rescan_work_q =
|
|
create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
|
|
if (!ioc->fc_rescan_work_q)
|
|
@@ -1314,7 +1388,6 @@ mptfc_probe(struct pci_dev *pdev, const
|
|
for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
|
|
(void) mptfc_GetFcPortPage0(ioc, ii);
|
|
}
|
|
- mptfc_SetFcPortPage1_defaults(ioc);
|
|
|
|
/*
|
|
* scan for rports -
|
|
@@ -1352,8 +1425,8 @@ mptfc_event_process(MPT_ADAPTER *ioc, Ev
|
|
unsigned long flags;
|
|
int rc=1;
|
|
|
|
- devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
|
|
- ioc->name, event));
|
|
+ if (ioc->bus_type != FC)
|
|
+ return 0;
|
|
|
|
if (ioc->sh == NULL ||
|
|
((hd = shost_priv(ioc->sh)) == NULL))
|
|
@@ -1390,45 +1463,45 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int re
|
|
unsigned long flags;
|
|
|
|
rc = mptscsih_ioc_reset(ioc,reset_phase);
|
|
- if (rc == 0)
|
|
+ if ((ioc->bus_type != FC) || (!rc))
|
|
return rc;
|
|
|
|
-
|
|
- dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- ": IOC %s_reset routed to FC host driver!\n",ioc->name,
|
|
- reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
|
|
- reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
|
|
-
|
|
- if (reset_phase == MPT_IOC_SETUP_RESET) {
|
|
+ switch(reset_phase) {
|
|
+ case MPT_IOC_SETUP_RESET:
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
+ "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __FUNCTION__));
|
|
spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
|
|
if (ioc->fc_rescan_work_q) {
|
|
queue_work(ioc->fc_rescan_work_q,
|
|
&ioc->fc_setup_reset_work);
|
|
}
|
|
spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
|
|
- }
|
|
-
|
|
- else if (reset_phase == MPT_IOC_PRE_RESET) {
|
|
- }
|
|
-
|
|
- else { /* MPT_IOC_POST_RESET */
|
|
- mptfc_SetFcPortPage1_defaults(ioc);
|
|
+ break;
|
|
+ case MPT_IOC_PRE_RESET:
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
+ "%s: MPT_IOC_PRE_RESET\n", ioc->name, __FUNCTION__));
|
|
+ break;
|
|
+ case MPT_IOC_POST_RESET:
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
+ "%s: MPT_IOC_POST_RESET\n", ioc->name, __FUNCTION__));
|
|
spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
|
|
if (ioc->fc_rescan_work_q) {
|
|
queue_work(ioc->fc_rescan_work_q,
|
|
&ioc->fc_rescan_work);
|
|
}
|
|
spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/**
|
|
* mptfc_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
|
|
*
|
|
* Returns 0 for success, non-zero for failure.
|
|
- */
|
|
+ **/
|
|
static int __init
|
|
mptfc_init(void)
|
|
{
|
|
@@ -1460,12 +1533,11 @@ mptfc_init(void)
|
|
return error;
|
|
}
|
|
|
|
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/**
|
|
* mptfc_remove - Remove fc infrastructure for devices
|
|
* @pdev: Pointer to pci_dev structure
|
|
*
|
|
- */
|
|
+ **/
|
|
static void __devexit
|
|
mptfc_remove(struct pci_dev *pdev)
|
|
{
|
|
@@ -1475,6 +1547,8 @@ mptfc_remove(struct pci_dev *pdev)
|
|
unsigned long flags;
|
|
int ii;
|
|
|
|
+ printk("%s -pdev=%p\n", __FUNCTION__, pdev);
|
|
+
|
|
/* destroy workqueue */
|
|
if ((work_q=ioc->fc_rescan_work_q)) {
|
|
spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
|
|
@@ -1517,7 +1591,6 @@ mptfc_exit(void)
|
|
|
|
mpt_reset_deregister(mptfcDoneCtx);
|
|
mpt_event_deregister(mptfcDoneCtx);
|
|
-
|
|
mpt_deregister(mptfcInternalCtx);
|
|
mpt_deregister(mptfcTaskCtx);
|
|
mpt_deregister(mptfcDoneCtx);
|
|
--- a/drivers/message/fusion/mptlan.c
|
|
+++ b/drivers/message/fusion/mptlan.c
|
|
@@ -6,7 +6,6 @@
|
|
*
|
|
* Copyright (c) 2000-2008 LSI Corporation
|
|
* (mailto:DL-MPTFusionLinux@lsi.com)
|
|
- *
|
|
*/
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/*
|
|
@@ -78,6 +77,12 @@ MODULE_VERSION(my_VERSION);
|
|
* Fusion MPT LAN private structures
|
|
*/
|
|
|
|
+struct NAA_Hosed {
|
|
+ u16 NAA;
|
|
+ u8 ieee[FC_ALEN];
|
|
+ struct NAA_Hosed *next;
|
|
+};
|
|
+
|
|
struct BufferControl {
|
|
struct sk_buff *skb;
|
|
dma_addr_t dma;
|
|
@@ -107,6 +112,7 @@ struct mpt_lan_priv {
|
|
|
|
u32 total_posted;
|
|
u32 total_received;
|
|
+ struct net_device_stats stats; /* Per device statistics */
|
|
|
|
struct delayed_work post_buckets_task;
|
|
struct net_device *dev;
|
|
@@ -153,6 +159,16 @@ static u8 LanCtx = MPT_MAX_PROTOCOL_DRIV
|
|
static u32 max_buckets_out = 127;
|
|
static u32 tx_max_out_p = 127 - 16;
|
|
|
|
+#ifdef QLOGIC_NAA_WORKAROUND
|
|
+static struct NAA_Hosed *mpt_bad_naa = NULL;
|
|
+DEFINE_RWLOCK(bad_naa_lock);
|
|
+#endif
|
|
+
|
|
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
+/*
|
|
+ * Fusion MPT LAN external data
|
|
+ */
|
|
+
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/**
|
|
* lan_reply - Handle all data sent from the hardware.
|
|
@@ -179,8 +195,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H
|
|
u32 tmsg = CAST_PTR_TO_U32(reply);
|
|
|
|
dioprintk((KERN_INFO MYNAM ": %s/%s: @lan_reply, tmsg %08x\n",
|
|
- IOC_AND_NETDEV_NAMES_s_s(dev),
|
|
- tmsg));
|
|
+ IOC_AND_NETDEV_NAMES_s_s(dev), tmsg));
|
|
|
|
switch (GET_LAN_FORM(tmsg)) {
|
|
|
|
@@ -429,6 +444,7 @@ mpt_lan_open(struct net_device *dev)
|
|
dlprintk((KERN_INFO MYNAM "/lo: Finished initializing RcvCtl\n"));
|
|
|
|
mpt_lan_post_receive_buckets(priv);
|
|
+
|
|
printk(KERN_INFO MYNAM ": %s/%s: interface up & active\n",
|
|
IOC_AND_NETDEV_NAMES_s_s(dev));
|
|
|
|
@@ -572,7 +588,6 @@ mpt_lan_tx_timeout(struct net_device *de
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
-//static inline int
|
|
static int
|
|
mpt_lan_send_turbo(struct net_device *dev, u32 tmsg)
|
|
{
|
|
@@ -585,12 +600,12 @@ mpt_lan_send_turbo(struct net_device *de
|
|
ctx = GET_LAN_BUFFER_CONTEXT(tmsg);
|
|
sent = priv->SendCtl[ctx].skb;
|
|
|
|
- dev->stats.tx_packets++;
|
|
- dev->stats.tx_bytes += sent->len;
|
|
+ priv->stats.tx_packets++;
|
|
+ priv->stats.tx_bytes += sent->len;
|
|
|
|
dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
|
|
IOC_AND_NETDEV_NAMES_s_s(dev),
|
|
- __func__, sent));
|
|
+ __FUNCTION__, sent));
|
|
|
|
priv->SendCtl[ctx].skb = NULL;
|
|
pci_unmap_single(mpt_dev->pcidev, priv->SendCtl[ctx].dma,
|
|
@@ -627,7 +642,7 @@ mpt_lan_send_reply(struct net_device *de
|
|
|
|
switch (le16_to_cpu(pSendRep->IOCStatus) & MPI_IOCSTATUS_MASK) {
|
|
case MPI_IOCSTATUS_SUCCESS:
|
|
- dev->stats.tx_packets += count;
|
|
+ priv->stats.tx_packets += count;
|
|
break;
|
|
|
|
case MPI_IOCSTATUS_LAN_CANCELED:
|
|
@@ -635,13 +650,13 @@ mpt_lan_send_reply(struct net_device *de
|
|
break;
|
|
|
|
case MPI_IOCSTATUS_INVALID_SGL:
|
|
- dev->stats.tx_errors += count;
|
|
+ priv->stats.tx_errors += count;
|
|
printk (KERN_ERR MYNAM ": %s/%s: ERROR - Invalid SGL sent to IOC!\n",
|
|
IOC_AND_NETDEV_NAMES_s_s(dev));
|
|
goto out;
|
|
|
|
default:
|
|
- dev->stats.tx_errors += count;
|
|
+ priv->stats.tx_errors += count;
|
|
break;
|
|
}
|
|
|
|
@@ -652,11 +667,11 @@ mpt_lan_send_reply(struct net_device *de
|
|
ctx = GET_LAN_BUFFER_CONTEXT(le32_to_cpu(*pContext));
|
|
|
|
sent = priv->SendCtl[ctx].skb;
|
|
- dev->stats.tx_bytes += sent->len;
|
|
+ priv->stats.tx_bytes += sent->len;
|
|
|
|
dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
|
|
IOC_AND_NETDEV_NAMES_s_s(dev),
|
|
- __func__, sent));
|
|
+ __FUNCTION__, sent));
|
|
|
|
priv->SendCtl[ctx].skb = NULL;
|
|
pci_unmap_single(mpt_dev->pcidev, priv->SendCtl[ctx].dma,
|
|
@@ -695,7 +710,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
|
|
u16 cur_naa = 0x1000;
|
|
|
|
dioprintk((KERN_INFO MYNAM ": %s called, skb_addr = %p\n",
|
|
- __func__, skb));
|
|
+ __FUNCTION__, skb));
|
|
|
|
spin_lock_irqsave(&priv->txfidx_lock, flags);
|
|
if (priv->mpt_txfidx_tail < 0) {
|
|
@@ -703,8 +718,8 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
|
|
spin_unlock_irqrestore(&priv->txfidx_lock, flags);
|
|
|
|
printk (KERN_ERR "%s: no tx context available: %u\n",
|
|
- __func__, priv->mpt_txfidx_tail);
|
|
- return NETDEV_TX_BUSY;
|
|
+ __FUNCTION__, priv->mpt_txfidx_tail);
|
|
+ return 1;
|
|
}
|
|
|
|
mf = mpt_get_msg_frame(LanCtx, mpt_dev);
|
|
@@ -713,8 +728,8 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
|
|
spin_unlock_irqrestore(&priv->txfidx_lock, flags);
|
|
|
|
printk (KERN_ERR "%s: Unable to alloc request frame\n",
|
|
- __func__);
|
|
- return NETDEV_TX_BUSY;
|
|
+ __FUNCTION__);
|
|
+ return 1;
|
|
}
|
|
|
|
ctx = priv->mpt_txfidx[priv->mpt_txfidx_tail--];
|
|
@@ -731,7 +746,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
|
|
skb_reset_mac_header(skb);
|
|
skb_pull(skb, 12);
|
|
|
|
- dma = pci_map_single(mpt_dev->pcidev, skb->data, skb->len,
|
|
+ dma = pci_map_single(mpt_dev->pcidev, skb->data, skb->len,
|
|
PCI_DMA_TODEVICE);
|
|
|
|
priv->SendCtl[ctx].skb = skb;
|
|
@@ -761,6 +776,32 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
|
|
|
|
mac = skb_mac_header(skb);
|
|
|
|
+#ifdef QLOGIC_NAA_WORKAROUND
|
|
+{
|
|
+ struct NAA_Hosed *nh;
|
|
+
|
|
+ /* Munge the NAA for Tx packets to QLogic boards, which don't follow
|
|
+ RFC 2625. The longer I look at this, the more my opinion of Qlogic
|
|
+ drops. */
|
|
+ read_lock_irq(&bad_naa_lock);
|
|
+ for (nh = mpt_bad_naa; nh != NULL; nh=nh->next) {
|
|
+ if ((nh->ieee[0] == mac[0]) &&
|
|
+ (nh->ieee[1] == mac[1]) &&
|
|
+ (nh->ieee[2] == mac[2]) &&
|
|
+ (nh->ieee[3] == mac[3]) &&
|
|
+ (nh->ieee[4] == mac[4]) &&
|
|
+ (nh->ieee[5] == mac[5])) {
|
|
+ cur_naa = nh->NAA;
|
|
+ dlprintk ((KERN_INFO "mptlan/sdu_send: using NAA value "
|
|
+ "= %04x.\n", cur_naa));
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ read_unlock_irq(&bad_naa_lock);
|
|
+}
|
|
+#endif
|
|
+
|
|
+
|
|
pTrans->TransactionDetails[0] = cpu_to_le32((cur_naa << 16) |
|
|
(mac[0] << 8) |
|
|
(mac[1] << 0));
|
|
@@ -784,7 +825,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
|
|
MPI_SGE_FLAGS_END_OF_LIST) << MPI_SGE_FLAGS_SHIFT) |
|
|
skb->len);
|
|
pSimple->Address.Low = cpu_to_le32((u32) dma);
|
|
- if (sizeof(dma_addr_t) > sizeof(u32))
|
|
+ if (mpt_dev->sg_addr_size > sizeof(u32))
|
|
pSimple->Address.High = cpu_to_le32((u32) ((u64) dma >> 32));
|
|
else
|
|
pSimple->Address.High = 0;
|
|
@@ -796,7 +837,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s
|
|
IOC_AND_NETDEV_NAMES_s_s(dev),
|
|
le32_to_cpu(pSimple->FlagsLength)));
|
|
|
|
- return NETDEV_TX_OK;
|
|
+ return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
@@ -807,7 +848,7 @@ mpt_lan_wake_post_buckets_task(struct ne
|
|
*/
|
|
{
|
|
struct mpt_lan_priv *priv = netdev_priv(dev);
|
|
-
|
|
+
|
|
if (test_and_set_bit(0, &priv->post_buckets_active) == 0) {
|
|
if (priority) {
|
|
schedule_delayed_work(&priv->post_buckets_task, 0);
|
|
@@ -816,7 +857,7 @@ mpt_lan_wake_post_buckets_task(struct ne
|
|
dioprintk((KERN_INFO MYNAM ": post_buckets queued on "
|
|
"timer.\n"));
|
|
}
|
|
- dioprintk((KERN_INFO MYNAM ": %s/%s: Queued post_buckets task.\n",
|
|
+ dioprintk((KERN_INFO MYNAM ": %s/%s: Queued post_buckets task.\n",
|
|
IOC_AND_NETDEV_NAMES_s_s(dev) ));
|
|
}
|
|
}
|
|
@@ -833,8 +874,8 @@ mpt_lan_receive_skb(struct net_device *d
|
|
"delivered to upper level.\n",
|
|
IOC_AND_NETDEV_NAMES_s_s(dev), skb->len));
|
|
|
|
- dev->stats.rx_bytes += skb->len;
|
|
- dev->stats.rx_packets++;
|
|
+ priv->stats.rx_bytes += skb->len;
|
|
+ priv->stats.rx_packets++;
|
|
|
|
skb->dev = dev;
|
|
netif_rx(skb);
|
|
@@ -1073,7 +1114,6 @@ mpt_lan_receive_post_reply(struct net_de
|
|
PCI_DMA_FROMDEVICE);
|
|
|
|
skb_copy_from_linear_data(old_skb, skb_put(skb, len), len);
|
|
-
|
|
pci_dma_sync_single_for_device(mpt_dev->pcidev,
|
|
priv->RcvCtl[ctx].dma,
|
|
priv->RcvCtl[ctx].len,
|
|
@@ -1121,22 +1161,20 @@ mpt_lan_receive_post_reply(struct net_de
|
|
"(priv->buckets_out = %d)\n",
|
|
IOC_AND_NETDEV_NAMES_s_s(dev),
|
|
remaining, atomic_read(&priv->buckets_out));
|
|
-
|
|
+
|
|
if ((remaining < priv->bucketthresh) &&
|
|
((atomic_read(&priv->buckets_out) - remaining) >
|
|
MPT_LAN_BUCKETS_REMAIN_MISMATCH_THRESH)) {
|
|
-
|
|
printk (KERN_WARNING MYNAM " Mismatch between driver's "
|
|
"buckets_out count and fw's BucketsRemaining "
|
|
"count has crossed the threshold, issuing a "
|
|
"LanReset to clear the fw's hashtable. You may "
|
|
"want to check your /var/log/messages for \"CRC "
|
|
"error\" event notifications.\n");
|
|
-
|
|
mpt_lan_reset(dev);
|
|
mpt_lan_wake_post_buckets_task(dev, 0);
|
|
}
|
|
-
|
|
+
|
|
return mpt_lan_receive_skb(dev, skb);
|
|
}
|
|
|
|
@@ -1164,7 +1202,7 @@ mpt_lan_post_receive_buckets(struct mpt_
|
|
|
|
dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, Start_buckets = %u, buckets_out = %u\n",
|
|
IOC_AND_NETDEV_NAMES_s_s(dev),
|
|
- __func__, buckets, curr));
|
|
+ __FUNCTION__, buckets, curr));
|
|
|
|
max = (mpt_dev->req_sz - MPT_LAN_RECEIVE_POST_REQUEST_SIZE) /
|
|
(MPT_LAN_TRANSACTION32_SIZE + sizeof(SGESimple64_t));
|
|
@@ -1173,9 +1211,9 @@ mpt_lan_post_receive_buckets(struct mpt_
|
|
mf = mpt_get_msg_frame(LanCtx, mpt_dev);
|
|
if (mf == NULL) {
|
|
printk (KERN_ERR "%s: Unable to alloc request frame\n",
|
|
- __func__);
|
|
+ __FUNCTION__);
|
|
dioprintk((KERN_ERR "%s: %u buckets remaining\n",
|
|
- __func__, buckets));
|
|
+ __FUNCTION__, buckets));
|
|
goto out;
|
|
}
|
|
pRecvReq = (LANReceivePostRequest_t *) mf;
|
|
@@ -1200,7 +1238,7 @@ mpt_lan_post_receive_buckets(struct mpt_
|
|
spin_lock_irqsave(&priv->rxfidx_lock, flags);
|
|
if (priv->mpt_rxfidx_tail < 0) {
|
|
printk (KERN_ERR "%s: Can't alloc context\n",
|
|
- __func__);
|
|
+ __FUNCTION__);
|
|
spin_unlock_irqrestore(&priv->rxfidx_lock,
|
|
flags);
|
|
break;
|
|
@@ -1223,7 +1261,7 @@ mpt_lan_post_receive_buckets(struct mpt_
|
|
if (skb == NULL) {
|
|
printk (KERN_WARNING
|
|
MYNAM "/%s: Can't alloc skb\n",
|
|
- __func__);
|
|
+ __FUNCTION__);
|
|
priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx;
|
|
spin_unlock_irqrestore(&priv->rxfidx_lock, flags);
|
|
break;
|
|
@@ -1251,7 +1289,7 @@ mpt_lan_post_receive_buckets(struct mpt_
|
|
MPI_SGE_FLAGS_SIMPLE_ELEMENT |
|
|
MPI_SGE_FLAGS_64_BIT_ADDRESSING) << MPI_SGE_FLAGS_SHIFT) | len);
|
|
pSimple->Address.Low = cpu_to_le32((u32) priv->RcvCtl[ctx].dma);
|
|
- if (sizeof(dma_addr_t) > sizeof(u32))
|
|
+ if (mpt_dev->sg_addr_size > sizeof(u32))
|
|
pSimple->Address.High = cpu_to_le32((u32) ((u64) priv->RcvCtl[ctx].dma >> 32));
|
|
else
|
|
pSimple->Address.High = 0;
|
|
@@ -1261,7 +1299,7 @@ mpt_lan_post_receive_buckets(struct mpt_
|
|
|
|
if (pSimple == NULL) {
|
|
/**/ printk (KERN_WARNING MYNAM "/%s: No buckets posted\n",
|
|
-/**/ __func__);
|
|
+/**/ __FUNCTION__);
|
|
mpt_free_msg_frame(mpt_dev, mf);
|
|
goto out;
|
|
}
|
|
@@ -1285,9 +1323,9 @@ mpt_lan_post_receive_buckets(struct mpt_
|
|
|
|
out:
|
|
dioprintk((KERN_INFO MYNAM "/%s: End_buckets = %u, priv->buckets_out = %u\n",
|
|
- __func__, buckets, atomic_read(&priv->buckets_out)));
|
|
+ __FUNCTION__, buckets, atomic_read(&priv->buckets_out)));
|
|
dioprintk((KERN_INFO MYNAM "/%s: Posted %u buckets and received %u back\n",
|
|
- __func__, priv->total_posted, priv->total_received));
|
|
+ __FUNCTION__, priv->total_posted, priv->total_received));
|
|
|
|
clear_bit(0, &priv->post_buckets_active);
|
|
}
|
|
@@ -1296,7 +1334,7 @@ static void
|
|
mpt_lan_post_receive_buckets_work(struct work_struct *work)
|
|
{
|
|
mpt_lan_post_receive_buckets(container_of(work, struct mpt_lan_priv,
|
|
- post_buckets_task.work));
|
|
+ post_buckets_task.work));
|
|
}
|
|
|
|
static const struct net_device_ops mpt_netdev_ops = {
|
|
@@ -1311,11 +1349,10 @@ static const struct net_device_ops mpt_n
|
|
static struct net_device *
|
|
mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
|
|
{
|
|
- struct net_device *dev;
|
|
- struct mpt_lan_priv *priv;
|
|
+ struct net_device *dev = alloc_fcdev(sizeof(struct mpt_lan_priv));
|
|
+ struct mpt_lan_priv *priv = NULL;
|
|
u8 HWaddr[FC_ALEN], *a;
|
|
|
|
- dev = alloc_fcdev(sizeof(struct mpt_lan_priv));
|
|
if (!dev)
|
|
return NULL;
|
|
|
|
@@ -1327,8 +1364,9 @@ mpt_register_lan_device (MPT_ADAPTER *mp
|
|
priv->mpt_dev = mpt_dev;
|
|
priv->pnum = pnum;
|
|
|
|
+ memset(&priv->post_buckets_task, 0, sizeof(priv->post_buckets_task));
|
|
INIT_DELAYED_WORK(&priv->post_buckets_task,
|
|
- mpt_lan_post_receive_buckets_work);
|
|
+ mpt_lan_post_receive_buckets_work);
|
|
priv->post_buckets_active = 0;
|
|
|
|
dlprintk((KERN_INFO MYNAM "@%d: bucketlen = %d\n",
|
|
@@ -1351,6 +1389,8 @@ mpt_register_lan_device (MPT_ADAPTER *mp
|
|
spin_lock_init(&priv->txfidx_lock);
|
|
spin_lock_init(&priv->rxfidx_lock);
|
|
|
|
+ memset(&priv->stats, 0, sizeof(priv->stats));
|
|
+
|
|
/* Grab pre-fetched LANPage1 stuff. :-) */
|
|
a = (u8 *) &mpt_dev->lan_cnfg_page1.HardwareAddressLow;
|
|
|
|
@@ -1372,6 +1412,8 @@ mpt_register_lan_device (MPT_ADAPTER *mp
|
|
tx_max_out_p : MPT_TX_MAX_OUT_LIM;
|
|
|
|
dev->netdev_ops = &mpt_netdev_ops;
|
|
+
|
|
+/* Not in 2.3.42. Need 2.3.45+ */
|
|
dev->watchdog_timeo = MPT_LAN_TX_TIMEOUT;
|
|
|
|
dlprintk((KERN_INFO MYNAM ": Finished registering dev "
|
|
@@ -1387,7 +1429,7 @@ mpt_register_lan_device (MPT_ADAPTER *mp
|
|
static int
|
|
mptlan_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
{
|
|
- MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
|
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
|
struct net_device *dev;
|
|
int i;
|
|
|
|
@@ -1414,14 +1456,16 @@ mptlan_probe(struct pci_dev *pdev, const
|
|
ioc->pfacts[i].PortNumber);
|
|
continue;
|
|
}
|
|
-
|
|
+
|
|
printk(KERN_INFO MYNAM ": %s: Fusion MPT LAN device "
|
|
"registered as '%s'\n", ioc->name, dev->name);
|
|
printk(KERN_INFO MYNAM ": %s/%s: "
|
|
- "LanAddr = %pM\n",
|
|
+ "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
|
|
IOC_AND_NETDEV_NAMES_s_s(dev),
|
|
- dev->dev_addr);
|
|
-
|
|
+ dev->dev_addr[0], dev->dev_addr[1],
|
|
+ dev->dev_addr[2], dev->dev_addr[3],
|
|
+ dev->dev_addr[4], dev->dev_addr[5]);
|
|
+
|
|
ioc->netdev = dev;
|
|
|
|
return 0;
|
|
@@ -1433,7 +1477,7 @@ mptlan_probe(struct pci_dev *pdev, const
|
|
static void
|
|
mptlan_remove(struct pci_dev *pdev)
|
|
{
|
|
- MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
|
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
|
struct net_device *dev = ioc->netdev;
|
|
|
|
if(dev != NULL) {
|
|
@@ -1466,7 +1510,6 @@ static int __init mpt_lan_init (void)
|
|
}
|
|
|
|
dlprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));
|
|
-
|
|
mpt_device_driver_register(&mptlan_driver, MPTLAN_DRIVER);
|
|
return 0;
|
|
}
|
|
@@ -1505,8 +1548,9 @@ mpt_lan_type_trans(struct sk_buff *skb,
|
|
|
|
printk (KERN_WARNING MYNAM ": %s: WARNING - Broadcast swap F/W bug detected!\n",
|
|
NETDEV_PTR_TO_IOC_NAME_s(dev));
|
|
- printk (KERN_WARNING MYNAM ": Please update sender @ MAC_addr = %pM\n",
|
|
- fch->saddr);
|
|
+ printk (KERN_WARNING MYNAM ": Please update sender @ MAC_addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
+ fch->saddr[0], fch->saddr[1], fch->saddr[2],
|
|
+ fch->saddr[3], fch->saddr[4], fch->saddr[5]);
|
|
}
|
|
|
|
if (*fch->daddr & 1) {
|
|
@@ -1525,6 +1569,80 @@ mpt_lan_type_trans(struct sk_buff *skb,
|
|
|
|
fcllc = (struct fcllc *)skb->data;
|
|
|
|
+#ifdef QLOGIC_NAA_WORKAROUND
|
|
+{
|
|
+ u16 source_naa = fch->stype, found = 0;
|
|
+
|
|
+ /* Workaround for QLogic not following RFC 2625 in regards to the NAA
|
|
+ value. */
|
|
+
|
|
+ if ((source_naa & 0xF000) == 0)
|
|
+ source_naa = swab16(source_naa);
|
|
+
|
|
+ if (fcllc->ethertype == htons(ETH_P_ARP))
|
|
+ dlprintk ((KERN_INFO "mptlan/type_trans: got arp req/rep w/ naa of "
|
|
+ "%04x.\n", source_naa));
|
|
+
|
|
+ if ((fcllc->ethertype == htons(ETH_P_ARP)) &&
|
|
+ ((source_naa >> 12) != MPT_LAN_NAA_RFC2625)){
|
|
+ struct NAA_Hosed *nh, *prevnh;
|
|
+ int i;
|
|
+
|
|
+ dlprintk ((KERN_INFO "mptlan/type_trans: ARP Req/Rep from "
|
|
+ "system with non-RFC 2625 NAA value (%04x).\n",
|
|
+ source_naa));
|
|
+
|
|
+ write_lock_irq(&bad_naa_lock);
|
|
+ for (prevnh = nh = mpt_bad_naa; nh != NULL;
|
|
+ prevnh=nh, nh=nh->next) {
|
|
+ if ((nh->ieee[0] == fch->saddr[0]) &&
|
|
+ (nh->ieee[1] == fch->saddr[1]) &&
|
|
+ (nh->ieee[2] == fch->saddr[2]) &&
|
|
+ (nh->ieee[3] == fch->saddr[3]) &&
|
|
+ (nh->ieee[4] == fch->saddr[4]) &&
|
|
+ (nh->ieee[5] == fch->saddr[5])) {
|
|
+ found = 1;
|
|
+ dlprintk ((KERN_INFO "mptlan/type_trans: ARP Re"
|
|
+ "q/Rep w/ bad NAA from system already"
|
|
+ " in DB.\n"));
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if ((!found) && (nh == NULL)) {
|
|
+
|
|
+ nh = kmalloc(sizeof(struct NAA_Hosed), GFP_KERNEL);
|
|
+ dlprintk ((KERN_INFO "mptlan/type_trans: ARP Req/Rep w/"
|
|
+ " bad NAA from system not yet in DB.\n"));
|
|
+
|
|
+ if (nh != NULL) {
|
|
+ nh->next = NULL;
|
|
+ if (!mpt_bad_naa)
|
|
+ mpt_bad_naa = nh;
|
|
+ if (prevnh)
|
|
+ prevnh->next = nh;
|
|
+
|
|
+ nh->NAA = source_naa; /* Set the S_NAA value. */
|
|
+ for (i = 0; i < FC_ALEN; i++)
|
|
+ nh->ieee[i] = fch->saddr[i];
|
|
+ dlprintk ((KERN_INFO "Got ARP from %02x:%02x:%02x:%02x:"
|
|
+ "%02x:%02x with non-compliant S_NAA value.\n",
|
|
+ fch->saddr[0], fch->saddr[1], fch->saddr[2],
|
|
+ fch->saddr[3], fch->saddr[4],fch->saddr[5]));
|
|
+ } else {
|
|
+ printk (KERN_ERR "mptlan/type_trans: Unable to"
|
|
+ " kmalloc a NAA_Hosed struct.\n");
|
|
+ }
|
|
+ } else if (!found) {
|
|
+ printk (KERN_ERR "mptlan/type_trans: found not"
|
|
+ " set, but nh isn't null. Evil "
|
|
+ "funkiness abounds.\n");
|
|
+ }
|
|
+ write_unlock_irq(&bad_naa_lock);
|
|
+ }
|
|
+}
|
|
+#endif
|
|
+
|
|
/* Strip the SNAP header from ARP packets since we don't
|
|
* pass them through to the 802.2/SNAP layers.
|
|
*/
|
|
--- a/drivers/message/fusion/mptlan.h
|
|
+++ b/drivers/message/fusion/mptlan.h
|
|
@@ -6,7 +6,6 @@
|
|
*
|
|
* Copyright (c) 2000-2008 LSI Corporation
|
|
* (mailto:DL-MPTFusionLinux@lsi.com)
|
|
- *
|
|
*/
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/*
|
|
@@ -73,6 +72,7 @@
|
|
|
|
#include <asm/uaccess.h>
|
|
#include <asm/io.h>
|
|
+#include <linux/pci.h>
|
|
|
|
/* Override mptbase.h by pre-defining these! */
|
|
#define MODULEAUTHOR "LSI Corporation"
|
|
--- a/drivers/message/fusion/mptsas.c
|
|
+++ b/drivers/message/fusion/mptsas.c
|
|
@@ -47,9 +47,11 @@
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/errno.h>
|
|
-#include <linux/jiffies.h>
|
|
+#include <linux/sched.h>
|
|
#include <linux/workqueue.h>
|
|
+#include <linux/interrupt.h>
|
|
#include <linux/delay.h> /* for mdelay */
|
|
+#include <linux/pci.h>
|
|
|
|
#include <scsi/scsi.h>
|
|
#include <scsi/scsi_cmnd.h>
|
|
@@ -62,7 +64,6 @@
|
|
#include "mptscsih.h"
|
|
#include "mptsas.h"
|
|
|
|
-
|
|
#define my_NAME "Fusion MPT SAS Host driver"
|
|
#define my_VERSION MPT_LINUX_VERSION_COMMON
|
|
#define MYNAM "mptsas"
|
|
@@ -73,6 +74,7 @@
|
|
#define MPTSAS_RAID_CHANNEL 1
|
|
|
|
#define SAS_CONFIG_PAGE_TIMEOUT 30
|
|
+
|
|
MODULE_AUTHOR(MODULEAUTHOR);
|
|
MODULE_DESCRIPTION(my_NAME);
|
|
MODULE_LICENSE("GPL");
|
|
@@ -84,6 +86,25 @@ MODULE_PARM_DESC(mpt_pt_clear,
|
|
" Clear persistency table: enable=1 "
|
|
"(default=MPTSCSIH_PT_CLEAR=0)");
|
|
|
|
+static int mpt_cmd_retry_count = 300;
|
|
+module_param(mpt_cmd_retry_count, int, 0);
|
|
+MODULE_PARM_DESC(mpt_cmd_retry_count,
|
|
+ " Device discovery TUR command retry count: default=300");
|
|
+
|
|
+static int mpt_disable_hotplug_remove = 0;
|
|
+module_param(mpt_disable_hotplug_remove, int, 0);
|
|
+MODULE_PARM_DESC(mpt_disable_hotplug_remove,
|
|
+ " Disable hotpug remove events: default=0");
|
|
+
|
|
+static int mpt_sdev_queue_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
|
|
+static int mptsas_set_sdev_queue_depth(const char *val,
|
|
+ struct kernel_param *kp);
|
|
+module_param_call(mpt_sdev_queue_depth, mptsas_set_sdev_queue_depth,
|
|
+ param_get_int, &mpt_sdev_queue_depth, 0600);
|
|
+MODULE_PARM_DESC(mpt_sdev_queue_depth,
|
|
+ " Max Device Queue Depth (default="
|
|
+ __MODULE_STRING(MPT_SCSI_CMD_PER_DEV_HIGH) ")");
|
|
+
|
|
/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
|
|
#define MPTSAS_MAX_LUN (16895)
|
|
static int max_lun = MPTSAS_MAX_LUN;
|
|
@@ -96,7 +117,6 @@ static u8 mptsasInternalCtx = MPT_MAX_PR
|
|
static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
|
|
static u8 mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS;
|
|
|
|
-static void mptsas_firmware_event_work(struct work_struct *work);
|
|
static void mptsas_send_sas_event(struct fw_event_work *fw_event);
|
|
static void mptsas_send_raid_event(struct fw_event_work *fw_event);
|
|
static void mptsas_send_ir2_event(struct fw_event_work *fw_event);
|
|
@@ -126,6 +146,39 @@ static void mptsas_broadcast_primative_w
|
|
static void mptsas_handle_queue_full_event(struct fw_event_work *fw_event);
|
|
static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id);
|
|
|
|
+
|
|
+void mptsas_schedule_target_reset(void *ioc);
|
|
+static void mptsas_firmware_event_work(struct work_struct *work);
|
|
+
|
|
+/**
|
|
+ * mptsas_set_sdev_queue_depth - global setting of the mpt_sdev_queue_depth
|
|
+ * found via /sys/module/mptsas/parameters/mpt_sdev_queue_depth
|
|
+ * @val:
|
|
+ * @kp:
|
|
+ *
|
|
+ * Returns
|
|
+ **/
|
|
+static int
|
|
+mptsas_set_sdev_queue_depth(const char *val, struct kernel_param *kp)
|
|
+{
|
|
+ int ret = param_set_int(val, kp);
|
|
+ MPT_ADAPTER *ioc;
|
|
+ struct scsi_device *sdev;
|
|
+
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ list_for_each_entry(ioc, &ioc_list, list) {
|
|
+ if (ioc->bus_type != SAS)
|
|
+ continue;
|
|
+ shost_for_each_device(sdev, ioc->sh)
|
|
+ mptscsih_change_queue_depth(sdev, mpt_sdev_queue_depth,
|
|
+ SCSI_QDEPTH_DEFAULT);
|
|
+ ioc->sdev_queue_depth = mpt_sdev_queue_depth;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
|
|
MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
|
|
{
|
|
@@ -279,6 +332,10 @@ mptsas_add_fw_event(MPT_ADAPTER *ioc, st
|
|
{
|
|
unsigned long flags;
|
|
|
|
+#if defined(CPQ_CIM)
|
|
+ ioc->csmi_change_count++;
|
|
+#endif
|
|
+
|
|
spin_lock_irqsave(&ioc->fw_event_lock, flags);
|
|
list_add_tail(&fw_event->list, &ioc->fw_event_list);
|
|
INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work);
|
|
@@ -297,7 +354,7 @@ mptsas_requeue_fw_event(MPT_ADAPTER *ioc
|
|
unsigned long flags;
|
|
spin_lock_irqsave(&ioc->fw_event_lock, flags);
|
|
devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task "
|
|
- "(fw_event=0x%p)\n", ioc->name, __func__, fw_event));
|
|
+ "(fw_event=0x%p)\n", ioc->name,__FUNCTION__, fw_event));
|
|
fw_event->retries++;
|
|
queue_delayed_work(ioc->fw_event_q, &fw_event->work,
|
|
msecs_to_jiffies(delay));
|
|
@@ -325,7 +382,7 @@ mptsas_cleanup_fw_event_q(MPT_ADAPTER *i
|
|
{
|
|
struct fw_event_work *fw_event, *next;
|
|
struct mptsas_target_reset_event *target_reset_list, *n;
|
|
- MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
|
|
+ MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
|
|
|
|
/* flush the target_reset_list */
|
|
if (!list_empty(&hd->target_reset_list)) {
|
|
@@ -436,7 +493,14 @@ mptsas_is_end_device(struct mptsas_devin
|
|
return 0;
|
|
}
|
|
|
|
-/* no mutex */
|
|
+/**
|
|
+ * mptsas_port_delete -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @port_details:
|
|
+ *
|
|
+ * (no mutex)
|
|
+ *
|
|
+ **/
|
|
static void
|
|
mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
|
|
{
|
|
@@ -465,6 +529,11 @@ mptsas_port_delete(MPT_ADAPTER *ioc, str
|
|
kfree(port_details);
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_get_rphy -
|
|
+ * @phy_info:
|
|
+ *
|
|
+ **/
|
|
static inline struct sas_rphy *
|
|
mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
|
|
{
|
|
@@ -474,6 +543,13 @@ mptsas_get_rphy(struct mptsas_phyinfo *p
|
|
return NULL;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_set_rphy -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @phy_info:
|
|
+ * @rphy:
|
|
+ *
|
|
+ **/
|
|
static inline void
|
|
mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
|
|
{
|
|
@@ -491,6 +567,11 @@ mptsas_set_rphy(MPT_ADAPTER *ioc, struct
|
|
}
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_get_port -
|
|
+ * @phy_info:
|
|
+ *
|
|
+ **/
|
|
static inline struct sas_port *
|
|
mptsas_get_port(struct mptsas_phyinfo *phy_info)
|
|
{
|
|
@@ -500,6 +581,13 @@ mptsas_get_port(struct mptsas_phyinfo *p
|
|
return NULL;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_set_port -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @phy_info:
|
|
+ * @port:
|
|
+ *
|
|
+ **/
|
|
static inline void
|
|
mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port)
|
|
{
|
|
@@ -514,6 +602,11 @@ mptsas_set_port(MPT_ADAPTER *ioc, struct
|
|
}
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_get_starget -
|
|
+ * @phy_info:
|
|
+ *
|
|
+ **/
|
|
static inline struct scsi_target *
|
|
mptsas_get_starget(struct mptsas_phyinfo *phy_info)
|
|
{
|
|
@@ -523,6 +616,12 @@ mptsas_get_starget(struct mptsas_phyinfo
|
|
return NULL;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_set_starget -
|
|
+ * @phy_info:
|
|
+ * @starget:
|
|
+ *
|
|
+ **/
|
|
static inline void
|
|
mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
|
|
starget)
|
|
@@ -544,15 +643,15 @@ static void
|
|
mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
|
|
u64 sas_address, u32 device_info, u16 slot, u64 enclosure_logical_id)
|
|
{
|
|
- struct mptsas_device_info *sas_info, *next;
|
|
+ struct sas_device_info *sas_info, *next;
|
|
struct scsi_device *sdev;
|
|
struct scsi_target *starget;
|
|
- struct sas_rphy *rphy;
|
|
+ struct sas_rphy *rphy;
|
|
|
|
/*
|
|
* Delete all matching devices out of the list
|
|
*/
|
|
- mutex_lock(&ioc->sas_device_info_mutex);
|
|
+ down(&ioc->sas_device_info_mutex);
|
|
list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
|
|
list) {
|
|
if (!sas_info->is_logical_volume &&
|
|
@@ -564,7 +663,7 @@ mptsas_add_device_component(MPT_ADAPTER
|
|
}
|
|
}
|
|
|
|
- sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
|
|
+ sas_info = kzalloc(sizeof(struct sas_device_info), GFP_KERNEL);
|
|
if (!sas_info)
|
|
goto out;
|
|
|
|
@@ -594,7 +693,7 @@ mptsas_add_device_component(MPT_ADAPTER
|
|
}
|
|
|
|
out:
|
|
- mutex_unlock(&ioc->sas_device_info_mutex);
|
|
+ up(&ioc->sas_device_info_mutex);
|
|
return;
|
|
}
|
|
|
|
@@ -631,23 +730,23 @@ mptsas_add_device_component_by_fw(MPT_AD
|
|
}
|
|
|
|
/**
|
|
- * mptsas_add_device_component_starget_ir - Handle Integrated RAID, adding each individual device to list
|
|
+ * mptsas_add_device_component_starget_ir - Handle Integrated RAID, adding
|
|
+ * each individual device to list
|
|
* @ioc: Pointer to MPT_ADAPTER structure
|
|
* @channel: fw mapped id's
|
|
* @id:
|
|
*
|
|
**/
|
|
static void
|
|
-mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc,
|
|
- struct scsi_target *starget)
|
|
+mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc, struct scsi_target *starget)
|
|
{
|
|
CONFIGPARMS cfg;
|
|
ConfigPageHeader_t hdr;
|
|
dma_addr_t dma_handle;
|
|
pRaidVolumePage0_t buffer = NULL;
|
|
int i;
|
|
- RaidPhysDiskPage0_t phys_disk;
|
|
- struct mptsas_device_info *sas_info, *next;
|
|
+ RaidPhysDiskPage0_t phys_disk;
|
|
+ struct sas_device_info *sas_info, *next;
|
|
|
|
memset(&cfg, 0 , sizeof(CONFIGPARMS));
|
|
memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
|
|
@@ -684,14 +783,14 @@ mptsas_add_device_component_starget_ir(M
|
|
*/
|
|
for (i = 0; i < buffer->NumPhysDisks; i++) {
|
|
|
|
- if (mpt_raid_phys_disk_pg0(ioc,
|
|
+ if(mpt_raid_phys_disk_pg0(ioc,
|
|
buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
|
|
continue;
|
|
|
|
mptsas_add_device_component_by_fw(ioc, phys_disk.PhysDiskBus,
|
|
phys_disk.PhysDiskID);
|
|
|
|
- mutex_lock(&ioc->sas_device_info_mutex);
|
|
+ down(&ioc->sas_device_info_mutex);
|
|
list_for_each_entry(sas_info, &ioc->sas_device_info_list,
|
|
list) {
|
|
if (!sas_info->is_logical_volume &&
|
|
@@ -701,14 +800,13 @@ mptsas_add_device_component_starget_ir(M
|
|
sas_info->volume_id = starget->id;
|
|
}
|
|
}
|
|
- mutex_unlock(&ioc->sas_device_info_mutex);
|
|
-
|
|
+ up(&ioc->sas_device_info_mutex);
|
|
}
|
|
|
|
/*
|
|
* Delete all matching devices out of the list
|
|
*/
|
|
- mutex_lock(&ioc->sas_device_info_mutex);
|
|
+ down(&ioc->sas_device_info_mutex);
|
|
list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
|
|
list) {
|
|
if (sas_info->is_logical_volume && sas_info->fw.id ==
|
|
@@ -718,7 +816,7 @@ mptsas_add_device_component_starget_ir(M
|
|
}
|
|
}
|
|
|
|
- sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
|
|
+ sas_info = kzalloc(sizeof(struct sas_device_info), GFP_KERNEL);
|
|
if (sas_info) {
|
|
sas_info->fw.id = starget->id;
|
|
sas_info->os.id = starget->id;
|
|
@@ -727,7 +825,7 @@ mptsas_add_device_component_starget_ir(M
|
|
INIT_LIST_HEAD(&sas_info->list);
|
|
list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
|
|
}
|
|
- mutex_unlock(&ioc->sas_device_info_mutex);
|
|
+ up(&ioc->sas_device_info_mutex);
|
|
|
|
out:
|
|
if (buffer)
|
|
@@ -770,7 +868,8 @@ mptsas_add_device_component_starget(MPT_
|
|
}
|
|
|
|
/**
|
|
- * mptsas_del_device_component_by_os - Once a device has been removed, we mark the entry in the list as being cached
|
|
+ * mptsas_del_device_component_by_os - Once a device has been removed, we
|
|
+ * mark the entry in the list as being cached
|
|
* @ioc: Pointer to MPT_ADAPTER structure
|
|
* @channel: os mapped id's
|
|
* @id:
|
|
@@ -779,7 +878,7 @@ mptsas_add_device_component_starget(MPT_
|
|
static void
|
|
mptsas_del_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id)
|
|
{
|
|
- struct mptsas_device_info *sas_info, *next;
|
|
+ struct sas_device_info *sas_info, *next;
|
|
|
|
/*
|
|
* Set is_cached flag
|
|
@@ -799,20 +898,24 @@ mptsas_del_device_component_by_os(MPT_AD
|
|
static void
|
|
mptsas_del_device_components(MPT_ADAPTER *ioc)
|
|
{
|
|
- struct mptsas_device_info *sas_info, *next;
|
|
+ struct sas_device_info *sas_info, *next;
|
|
|
|
- mutex_lock(&ioc->sas_device_info_mutex);
|
|
+ down(&ioc->sas_device_info_mutex);
|
|
list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
|
|
list) {
|
|
list_del(&sas_info->list);
|
|
kfree(sas_info);
|
|
}
|
|
- mutex_unlock(&ioc->sas_device_info_mutex);
|
|
+ up(&ioc->sas_device_info_mutex);
|
|
}
|
|
|
|
|
|
/*
|
|
* mptsas_setup_wide_ports
|
|
+ * configuration
|
|
+ * in the sas_topology
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @port_info:
|
|
*
|
|
* Updates for new and existing narrow/wide port configuration
|
|
* in the sas_topology
|
|
@@ -836,13 +939,14 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc
|
|
continue;
|
|
if (port_details->num_phys < 2)
|
|
continue;
|
|
+
|
|
/*
|
|
* Removing a phy from a port, letting the last
|
|
* phy be removed by firmware events.
|
|
*/
|
|
dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- "%s: [%p]: deleting phy = %d\n",
|
|
- ioc->name, __func__, port_details, i));
|
|
+ "%s: [%p]: deleting phy = %d\n",
|
|
+ ioc->name, __FUNCTION__, port_details, i));
|
|
port_details->num_phys--;
|
|
port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
|
|
memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
|
|
@@ -945,19 +1049,18 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc
|
|
}
|
|
|
|
/**
|
|
- * csmisas_find_vtarget
|
|
- *
|
|
- * @ioc
|
|
- * @volume_id
|
|
- * @volume_bus
|
|
+ * mptsas_find_vtarget - obtain vtarget object for non-raid devices
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @channel:
|
|
+ * @id:
|
|
*
|
|
**/
|
|
static VirtTarget *
|
|
mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
|
|
{
|
|
- struct scsi_device *sdev;
|
|
+ struct scsi_device *sdev;
|
|
VirtDevice *vdevice;
|
|
- VirtTarget *vtarget = NULL;
|
|
+ VirtTarget *vtarget = NULL;
|
|
|
|
shost_for_each_device(sdev, ioc->sh) {
|
|
vdevice = sdev->hostdata;
|
|
@@ -1017,16 +1120,14 @@ mptsas_queue_rescan(MPT_ADAPTER *ioc)
|
|
|
|
|
|
/**
|
|
- * mptsas_target_reset
|
|
- *
|
|
- * Issues TARGET_RESET to end device using handshaking method
|
|
- *
|
|
- * @ioc
|
|
- * @channel
|
|
- * @id
|
|
+ * mptsas_target_reset - Issues TARGET_RESET to end device using
|
|
+ * handshaking method
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @channel:
|
|
+ * @id:
|
|
*
|
|
- * Returns (1) success
|
|
- * (0) failure
|
|
+ * Returns (1) success
|
|
+ * (0) failure
|
|
*
|
|
**/
|
|
static int
|
|
@@ -1034,6 +1135,7 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8
|
|
{
|
|
MPT_FRAME_HDR *mf;
|
|
SCSITaskMgmt_t *pScsiTm;
|
|
+
|
|
if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0)
|
|
return 0;
|
|
|
|
@@ -1075,16 +1177,27 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8
|
|
return 0;
|
|
}
|
|
|
|
+static void
|
|
+mptsas_block_io_sdev(struct scsi_device *sdev, void *data)
|
|
+{
|
|
+ scsi_device_set_state(sdev, SDEV_BLOCK);
|
|
+}
|
|
+
|
|
+static void
|
|
+mptsas_block_io_starget(struct scsi_target *starget)
|
|
+{
|
|
+ if (starget)
|
|
+ starget_for_each_device(starget, NULL, mptsas_block_io_sdev);
|
|
+}
|
|
+
|
|
/**
|
|
- * 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
|
|
+ * mptsas_target_reset_queue -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @sas_event_data:
|
|
*
|
|
+ * 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.
|
|
**/
|
|
static void
|
|
mptsas_target_reset_queue(MPT_ADAPTER *ioc,
|
|
@@ -1098,10 +1211,12 @@ mptsas_target_reset_queue(MPT_ADAPTER *i
|
|
id = sas_event_data->TargetID;
|
|
channel = sas_event_data->Bus;
|
|
|
|
- if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
|
|
- return;
|
|
-
|
|
- vtarget->deleted = 1; /* block IO */
|
|
+ if ((vtarget = mptsas_find_vtarget(ioc, channel, id))) {
|
|
+ if (!ioc->disable_hotplug_remove) {
|
|
+ mptsas_block_io_starget(vtarget->starget);
|
|
+ vtarget->deleted = 1; /* block IO */
|
|
+ }
|
|
+ }
|
|
|
|
target_reset_list = kzalloc(sizeof(struct mptsas_target_reset_event),
|
|
GFP_ATOMIC);
|
|
@@ -1124,20 +1239,57 @@ mptsas_target_reset_queue(MPT_ADAPTER *i
|
|
}
|
|
|
|
/**
|
|
- * mptsas_taskmgmt_complete - complete SAS task management function
|
|
+ * mptsas_schedule_target_reset- send pending target reset
|
|
+ * @iocp: per adapter object
|
|
+ *
|
|
+ * This function will delete scheduled target reset from the list and
|
|
+ * try to send next target reset. This will be called from completion
|
|
+ * context of any Task managment command.
|
|
+ */
|
|
+
|
|
+void
|
|
+mptsas_schedule_target_reset(void *iocp)
|
|
+{
|
|
+ MPT_ADAPTER *ioc = (MPT_ADAPTER*)(iocp);
|
|
+ MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
|
|
+ struct list_head *head = &hd->target_reset_list;
|
|
+ struct mptsas_target_reset_event *target_reset_list;
|
|
+ u8 id, channel;
|
|
+ /*
|
|
+ * 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);
|
|
+
|
|
+ id = target_reset_list->sas_event_data.TargetID;
|
|
+ channel = target_reset_list->sas_event_data.Bus;
|
|
+ target_reset_list->time_count = jiffies;
|
|
+
|
|
+ if (mptsas_target_reset(ioc, channel, id))
|
|
+ target_reset_list->target_reset_issued = 1;
|
|
+ return;
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * mptsas_taskmgmt_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: Pointer to MPT_ADAPTER structure
|
|
*
|
|
- * 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.
|
|
**/
|
|
static int
|
|
mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
|
|
{
|
|
MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
|
|
- struct list_head *head = &hd->target_reset_list;
|
|
- u8 id, channel;
|
|
+ struct list_head *head = &hd->target_reset_list;
|
|
struct mptsas_target_reset_event *target_reset_list;
|
|
+ u8 id, channel;
|
|
SCSITaskMgmtReply_t *pScsiTmReply;
|
|
|
|
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed: "
|
|
@@ -1212,32 +1364,15 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *io
|
|
&target_reset_list->sas_event_data);
|
|
|
|
|
|
- /*
|
|
- * issue target reset to next device in the queue
|
|
- */
|
|
-
|
|
- head = &hd->target_reset_list;
|
|
- if (list_empty(head))
|
|
- return 1;
|
|
-
|
|
- target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
|
|
- list);
|
|
-
|
|
- id = target_reset_list->sas_event_data.TargetID;
|
|
- channel = target_reset_list->sas_event_data.Bus;
|
|
- target_reset_list->time_count = jiffies;
|
|
-
|
|
- if (mptsas_target_reset(ioc, channel, id))
|
|
- target_reset_list->target_reset_issued = 1;
|
|
+ ioc->schedule_target_reset(ioc);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
- * mptscsih_ioc_reset
|
|
- *
|
|
- * @ioc
|
|
- * @reset_phase
|
|
+ * mptsas_ioc_reset -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @reset_phase:
|
|
*
|
|
**/
|
|
static int
|
|
@@ -1282,7 +1417,6 @@ mptsas_ioc_reset(MPT_ADAPTER *ioc, int r
|
|
return rc;
|
|
}
|
|
|
|
-
|
|
/**
|
|
* enum device_state -
|
|
* @DEVICE_RETRY: need to retry the TUR
|
|
@@ -1296,6 +1430,15 @@ enum device_state{
|
|
DEVICE_READY,
|
|
};
|
|
|
|
+
|
|
+/**
|
|
+ * mptsas_sas_enclosure_pg0 -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @enclosure:
|
|
+ * @form:
|
|
+ * @form_specific:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
|
|
u32 form, u32 form_specific)
|
|
@@ -1440,7 +1583,8 @@ mptsas_add_end_device(MPT_ADAPTER *ioc,
|
|
}
|
|
|
|
/**
|
|
- * mptsas_del_end_device - report a deleted end device to sas transport layer
|
|
+ * mptsas_del_end_device - report a deleted end device to sas transport
|
|
+ * layer
|
|
* @ioc: Pointer to MPT_ADAPTER structure
|
|
* @phy_info: decribes attached device
|
|
*
|
|
@@ -1638,13 +1782,297 @@ mptsas_firmware_event_work(struct work_s
|
|
|
|
|
|
|
|
+/**
|
|
+ * mptsas_get_lun_number - returns the first entry in report_luns table
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @channel:
|
|
+ * @id:
|
|
+ * @lun:
|
|
+ *
|
|
+ */
|
|
+static int
|
|
+mptsas_get_lun_number(MPT_ADAPTER *ioc, u8 channel, u8 id, int *lun)
|
|
+{
|
|
+ INTERNAL_CMD *iocmd;
|
|
+ struct scsi_lun *lun_data;
|
|
+ dma_addr_t lun_data_dma;
|
|
+ u32 lun_data_len;
|
|
+ u8 *data;
|
|
+ MPT_SCSI_HOST *hd;
|
|
+ int rc;
|
|
+ u32 length, num_luns;
|
|
+
|
|
+ iocmd = NULL;
|
|
+ hd = shost_priv(ioc->sh);
|
|
+ lun_data_len = (255 * sizeof(struct scsi_lun));
|
|
+ lun_data = pci_alloc_consistent(ioc->pcidev, lun_data_len,
|
|
+ &lun_data_dma);
|
|
+ if (!lun_data) {
|
|
+ printk(MYIOC_s_ERR_FMT "%s: pci_alloc_consistent(%d) FAILED!\n",
|
|
+ ioc->name, __FUNCTION__, lun_data_len);
|
|
+ rc = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ iocmd = kzalloc(sizeof(INTERNAL_CMD), GFP_KERNEL);
|
|
+ if (!iocmd) {
|
|
+ printk(MYIOC_s_ERR_FMT "%s: kzalloc(%zd) FAILED!\n",
|
|
+ ioc->name, __FUNCTION__, sizeof(INTERNAL_CMD));
|
|
+ rc = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Report Luns
|
|
+ */
|
|
+ iocmd->cmd = REPORT_LUNS;
|
|
+ iocmd->data_dma = lun_data_dma;
|
|
+ iocmd->data = (u8 *)lun_data;
|
|
+ iocmd->size = lun_data_len;
|
|
+ iocmd->channel = channel;
|
|
+ iocmd->id = id;
|
|
+
|
|
+ if ((rc = mptscsih_do_cmd(hd, iocmd)) < 0) {
|
|
+ printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d: "
|
|
+ "report_luns failed due to rc=0x%x\n", ioc->name,
|
|
+ __FUNCTION__, channel, id, rc);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (rc != MPT_SCANDV_GOOD) {
|
|
+ printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d: "
|
|
+ "report_luns failed due to rc=0x%x\n", ioc->name,
|
|
+ __FUNCTION__, channel, id, rc);
|
|
+ rc = -rc;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ data = (u8 *)lun_data;
|
|
+ length = ((data[0] << 24) | (data[1] << 16) |
|
|
+ (data[2] << 8) | (data[3] << 0));
|
|
+
|
|
+ num_luns = (length / sizeof(struct scsi_lun));
|
|
+ if (!num_luns)
|
|
+ goto out;
|
|
+ /* return 1st lun in the list */
|
|
+ *lun = scsilun_to_int(&lun_data[1]);
|
|
+
|
|
+#if 0
|
|
+ /* some debugging, left commented out */
|
|
+ {
|
|
+ struct scsi_lun *lunp;
|
|
+ for (lunp = &lun_data[1]; lunp <= &lun_data[num_luns]; lunp++)
|
|
+ printk("%x\n", scsilun_to_int(lunp));
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ out:
|
|
+ if (lun_data)
|
|
+ pci_free_consistent(ioc->pcidev, lun_data_len, lun_data,
|
|
+ lun_data_dma);
|
|
+ kfree(iocmd);
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * mptsas_test_unit_ready -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @channel:
|
|
+ * @id:
|
|
+ * @count: retry count
|
|
+ *
|
|
+ */
|
|
+enum device_state
|
|
+mptsas_test_unit_ready(MPT_ADAPTER *ioc, u8 channel, u8 id, u16 count)
|
|
+{
|
|
+ INTERNAL_CMD *iocmd;
|
|
+ MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
|
|
+ enum device_state state;
|
|
+ int rc;
|
|
+ u8 skey, asc, ascq;
|
|
+ u8 retry_ua;
|
|
+
|
|
+ if (count >= mpt_cmd_retry_count)
|
|
+ return DEVICE_ERROR;
|
|
+
|
|
+ retry_ua = 0;
|
|
+ iocmd = kzalloc(sizeof(INTERNAL_CMD), GFP_KERNEL);
|
|
+ if (!iocmd) {
|
|
+ printk(MYIOC_s_ERR_FMT "%s: kzalloc(%zd) FAILED!\n",
|
|
+ __FUNCTION__, ioc->name, sizeof(INTERNAL_CMD));
|
|
+ return DEVICE_ERROR;
|
|
+ }
|
|
+
|
|
+ state = DEVICE_ERROR;
|
|
+ iocmd->cmd = TEST_UNIT_READY;
|
|
+ iocmd->data_dma = -1;
|
|
+ iocmd->data = NULL;
|
|
+
|
|
+ if (mptscsih_is_phys_disk(ioc, channel, id)) {
|
|
+ iocmd->flags |= MPT_ICFLAG_PHYS_DISK;
|
|
+ iocmd->physDiskNum = mptscsih_raid_id_to_num(ioc, channel, id);
|
|
+ iocmd->id = id;
|
|
+ }
|
|
+ iocmd->channel = channel;
|
|
+ iocmd->id = id;
|
|
+
|
|
+ retry:
|
|
+ devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: fw_channel=%d "
|
|
+ "fw_id=%d retry=%d\n", ioc->name, __FUNCTION__, channel, id, count));
|
|
+ rc = mptscsih_do_cmd(hd, iocmd);
|
|
+ devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: rc=0x%02x\n",
|
|
+ ioc->name, __FUNCTION__, rc));
|
|
+ if (rc < 0) {
|
|
+ printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d: "
|
|
+ "tur failed due to timeout\n", ioc->name,
|
|
+ __FUNCTION__, channel, id);
|
|
+ goto tur_done;
|
|
+ }
|
|
+
|
|
+ switch(rc) {
|
|
+ case MPT_SCANDV_GOOD:
|
|
+ state = DEVICE_READY;
|
|
+ goto tur_done;
|
|
+ case MPT_SCANDV_BUSY:
|
|
+ devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: "
|
|
+ "fw_channel=%d fw_id=%d : device busy\n",
|
|
+ ioc->name, __FUNCTION__, channel, id));
|
|
+ state = DEVICE_RETRY;
|
|
+ break;
|
|
+ case MPT_SCANDV_DID_RESET:
|
|
+ devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: "
|
|
+ "fw_channel=%d fw_id=%d : did reset\n",
|
|
+ ioc->name, __FUNCTION__, channel, id));
|
|
+ state = DEVICE_RETRY;
|
|
+ break;
|
|
+ case MPT_SCANDV_SENSE:
|
|
+ skey = ioc->internal_cmds.sense[2] & 0x0F;
|
|
+ asc = ioc->internal_cmds.sense[12];
|
|
+ ascq = ioc->internal_cmds.sense[13];
|
|
+
|
|
+ devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: "
|
|
+ "fw_channel=%d fw_id=%d : [sense_key,asc,"
|
|
+ "ascq]: [0x%02x,0x%02x,0x%02x]\n", ioc->name,
|
|
+ __FUNCTION__, channel, id, skey, asc, ascq));
|
|
+
|
|
+ if (skey == UNIT_ATTENTION) {
|
|
+ state = DEVICE_RETRY;
|
|
+ break;
|
|
+ } else if (skey == NOT_READY) {
|
|
+ /*
|
|
+ * medium isn't present
|
|
+ */
|
|
+ if (asc == 0x3a) {
|
|
+ state = DEVICE_READY;
|
|
+ goto tur_done;
|
|
+ }
|
|
+ /*
|
|
+ * LU becoming ready, or
|
|
+ * LU hasn't self-configured yet
|
|
+ */
|
|
+ if ((asc == 0x04 && ascq == 0x01) ||
|
|
+ (asc == 0x04 && ascq == 0x11) ||
|
|
+ asc == 0x3e) {
|
|
+ state = DEVICE_RETRY;
|
|
+ break;
|
|
+ }
|
|
+ } else if (skey == ILLEGAL_REQUEST) {
|
|
+ /* try sending a tur to a non-zero lun number */
|
|
+ if (!iocmd->lun && !mptsas_get_lun_number(ioc,
|
|
+ channel, id, &iocmd->lun) && iocmd->lun)
|
|
+ goto retry;
|
|
+ }
|
|
+ printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d : "
|
|
+ "tur failed due to [sense_key,asc,ascq]: "
|
|
+ "[0x%02x,0x%02x,0x%02x]\n", ioc->name,
|
|
+ __FUNCTION__, channel, id, skey, asc, ascq);
|
|
+ goto tur_done;
|
|
+ case MPT_SCANDV_SELECTION_TIMEOUT:
|
|
+ printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d: "
|
|
+ "tur failed due to no device\n", ioc->name,
|
|
+ __FUNCTION__, channel,
|
|
+ id);
|
|
+ goto tur_done;
|
|
+ case MPT_SCANDV_SOME_ERROR:
|
|
+ printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d: "
|
|
+ "tur failed due to some error\n", ioc->name,
|
|
+ __FUNCTION__,
|
|
+ channel, id);
|
|
+ goto tur_done;
|
|
+ default:
|
|
+ printk(MYIOC_s_ERR_FMT
|
|
+ "%s: fw_channel=%d fw_id=%d: tur failed due to "
|
|
+ "unknown rc=0x%02x\n", ioc->name, __FUNCTION__,
|
|
+ channel, id, rc );
|
|
+ goto tur_done;
|
|
+ }
|
|
+ tur_done:
|
|
+ kfree(iocmd);
|
|
+ return state;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * mptsas_issue_tlr - Enabling Transport Layer Retries
|
|
+ * @hd:
|
|
+ * @sdev:
|
|
+ *
|
|
+ **/
|
|
+static void
|
|
+mptsas_issue_tlr(MPT_SCSI_HOST *hd, struct scsi_device *sdev)
|
|
+{
|
|
+ INTERNAL_CMD *iocmd;
|
|
+ VirtDevice *vdevice = sdev->hostdata;
|
|
+ u8 retries;
|
|
+ u8 rc;
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
+
|
|
+ if ( sdev->inquiry[8] == 'H' &&
|
|
+ sdev->inquiry[9] == 'P' &&
|
|
+ sdev->inquiry[10] == ' ' &&
|
|
+ sdev->inquiry[11] == ' ' &&
|
|
+ sdev->inquiry[12] == ' ' &&
|
|
+ sdev->inquiry[13] == ' ' &&
|
|
+ sdev->inquiry[14] == ' ' &&
|
|
+ sdev->inquiry[15] == ' ' ) {
|
|
+
|
|
+ iocmd = kzalloc(sizeof(INTERNAL_CMD), GFP_KERNEL);
|
|
+ if (!iocmd) {
|
|
+ printk(MYIOC_s_ERR_FMT "%s: kzalloc(%zd) FAILED!\n",
|
|
+ __FUNCTION__, ioc->name, sizeof(INTERNAL_CMD));
|
|
+ return;
|
|
+ }
|
|
+ iocmd->id = vdevice->vtarget->id;
|
|
+ iocmd->channel = vdevice->vtarget->channel;
|
|
+ iocmd->lun = vdevice->lun;
|
|
+ iocmd->physDiskNum = -1;
|
|
+ iocmd->cmd = TRANSPORT_LAYER_RETRIES;
|
|
+ iocmd->data_dma = -1;
|
|
+ for (retries = 0, rc = -1; retries < 3; retries++) {
|
|
+ rc = mptscsih_do_cmd(hd, iocmd);
|
|
+ if (!rc)
|
|
+ break;
|
|
+ }
|
|
+ if (rc != 0)
|
|
+ printk(MYIOC_s_DEBUG_FMT "unable to enable TLR on"
|
|
+ " fw_channel %d, fw_id %d, lun=%d\n",
|
|
+ ioc->name, vdevice->vtarget->channel,
|
|
+ vdevice->vtarget->id, sdev->lun);
|
|
+ kfree(iocmd);
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * mptsas_slave_configure -
|
|
+ * @sdev:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_slave_configure(struct scsi_device *sdev)
|
|
{
|
|
struct Scsi_Host *host = sdev->host;
|
|
- MPT_SCSI_HOST *hd = shost_priv(host);
|
|
- MPT_ADAPTER *ioc = hd->ioc;
|
|
- VirtDevice *vdevice = sdev->hostdata;
|
|
+ MPT_SCSI_HOST *hd = shost_priv(host);
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
+ VirtDevice *vdevice = sdev->hostdata;
|
|
|
|
if (vdevice->vtarget->deleted) {
|
|
sdev_printk(KERN_INFO, sdev, "clearing deleted flag\n");
|
|
@@ -1664,10 +2092,19 @@ mptsas_slave_configure(struct scsi_devic
|
|
|
|
mptsas_add_device_component_starget(ioc, scsi_target(sdev));
|
|
|
|
+ if (sdev->type == TYPE_TAPE &&
|
|
+ (ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_TLR ))
|
|
+ mptsas_issue_tlr(hd, sdev);
|
|
out:
|
|
+
|
|
return mptscsih_slave_configure(sdev);
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_target_alloc -
|
|
+ * @starget:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_target_alloc(struct scsi_target *starget)
|
|
{
|
|
@@ -1677,7 +2114,7 @@ mptsas_target_alloc(struct scsi_target *
|
|
u8 id, channel;
|
|
struct sas_rphy *rphy;
|
|
struct mptsas_portinfo *p;
|
|
- int i;
|
|
+ int i;
|
|
MPT_ADAPTER *ioc = hd->ioc;
|
|
|
|
vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
|
|
@@ -1698,13 +2135,9 @@ mptsas_target_alloc(struct scsi_target *
|
|
kfree(vtarget);
|
|
return -ENXIO;
|
|
}
|
|
- for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
|
|
- if (id == ioc->raid_data.pIocPg2->
|
|
- RaidVolume[i].VolumeID) {
|
|
- channel = ioc->raid_data.pIocPg2->
|
|
- RaidVolume[i].VolumeBus;
|
|
- }
|
|
- }
|
|
+ for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
|
|
+ if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
|
|
+ channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
|
|
vtarget->raidVolume = 1;
|
|
goto out;
|
|
}
|
|
@@ -1720,6 +2153,12 @@ mptsas_target_alloc(struct scsi_target *
|
|
channel = p->phy_info[i].attached.channel;
|
|
mptsas_set_starget(&p->phy_info[i], starget);
|
|
|
|
+ starget_printk(KERN_INFO, starget, MYIOC_s_FMT
|
|
+ "add device: fw_channel %d, fw_id %d, phy %d, sas_addr 0x%llx\n",
|
|
+ ioc->name, p->phy_info[i].attached.channel,
|
|
+ p->phy_info[i].attached.id, p->phy_info[i].attached.phy_id,
|
|
+ (unsigned long long)p->phy_info[i].attached.sas_address);
|
|
+
|
|
/*
|
|
* Exposing hidden raid components
|
|
*/
|
|
@@ -1746,6 +2185,11 @@ mptsas_target_alloc(struct scsi_target *
|
|
return 0;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_target_destroy -
|
|
+ * @starget:
|
|
+ *
|
|
+ **/
|
|
static void
|
|
mptsas_target_destroy(struct scsi_target *starget)
|
|
{
|
|
@@ -1753,7 +2197,7 @@ mptsas_target_destroy(struct scsi_target
|
|
MPT_SCSI_HOST *hd = shost_priv(host);
|
|
struct sas_rphy *rphy;
|
|
struct mptsas_portinfo *p;
|
|
- int i;
|
|
+ int i;
|
|
MPT_ADAPTER *ioc = hd->ioc;
|
|
VirtTarget *vtarget;
|
|
|
|
@@ -1765,7 +2209,6 @@ mptsas_target_destroy(struct scsi_target
|
|
mptsas_del_device_component_by_os(ioc, starget->channel,
|
|
starget->id);
|
|
|
|
-
|
|
if (starget->channel == MPTSAS_RAID_CHANNEL)
|
|
goto out;
|
|
|
|
@@ -1794,7 +2237,11 @@ mptsas_target_destroy(struct scsi_target
|
|
starget->hostdata = NULL;
|
|
}
|
|
|
|
-
|
|
+/**
|
|
+ * mptsas_slave_alloc -
|
|
+ * @sdev:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_slave_alloc(struct scsi_device *sdev)
|
|
{
|
|
@@ -1803,8 +2250,8 @@ mptsas_slave_alloc(struct scsi_device *s
|
|
struct sas_rphy *rphy;
|
|
struct mptsas_portinfo *p;
|
|
VirtDevice *vdevice;
|
|
- struct scsi_target *starget;
|
|
- int i;
|
|
+ struct scsi_target *starget;
|
|
+ int i;
|
|
MPT_ADAPTER *ioc = hd->ioc;
|
|
|
|
vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
|
|
@@ -1816,6 +2263,9 @@ mptsas_slave_alloc(struct scsi_device *s
|
|
starget = scsi_target(sdev);
|
|
vdevice->vtarget = starget->hostdata;
|
|
|
|
+ /*
|
|
+ * RAID volumes placed beyond the last expected port.
|
|
+ */
|
|
if (sdev->channel == MPTSAS_RAID_CHANNEL)
|
|
goto out;
|
|
|
|
@@ -1849,6 +2299,12 @@ mptsas_slave_alloc(struct scsi_device *s
|
|
return 0;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_qcmd -
|
|
+ * @SCpnt:
|
|
+ * @done:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
|
|
{
|
|
@@ -1868,7 +2324,8 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, voi
|
|
if (ioc->sas_discovery_quiesce_io)
|
|
return SCSI_MLQUEUE_HOST_BUSY;
|
|
|
|
-// scsi_print_command(SCpnt);
|
|
+ if (ioc->debug_level & MPT_DEBUG_SCSI)
|
|
+ scsi_print_command(SCpnt);
|
|
|
|
return mptscsih_qcmd(SCpnt,done);
|
|
}
|
|
@@ -1878,7 +2335,7 @@ static struct scsi_host_template mptsas_
|
|
.module = THIS_MODULE,
|
|
.proc_name = "mptsas",
|
|
.proc_info = mptscsih_proc_info,
|
|
- .name = "MPT SPI Host",
|
|
+ .name = "MPT SAS Host",
|
|
.info = mptscsih_info,
|
|
.queuecommand = mptsas_qcmd,
|
|
.target_alloc = mptsas_target_alloc,
|
|
@@ -1886,7 +2343,7 @@ static struct scsi_host_template mptsas_
|
|
.slave_configure = mptsas_slave_configure,
|
|
.target_destroy = mptsas_target_destroy,
|
|
.slave_destroy = mptscsih_slave_destroy,
|
|
- .change_queue_depth = mptscsih_change_queue_depth,
|
|
+ .change_queue_depth = mptscsih_change_queue_depth,
|
|
.eh_abort_handler = mptscsih_abort,
|
|
.eh_device_reset_handler = mptscsih_dev_reset,
|
|
.eh_bus_reset_handler = mptscsih_bus_reset,
|
|
@@ -1901,6 +2358,11 @@ static struct scsi_host_template mptsas_
|
|
.shost_attrs = mptscsih_host_attrs,
|
|
};
|
|
|
|
+/**
|
|
+ * mptsas_get_linkerrors -
|
|
+ * @phy:
|
|
+ *
|
|
+ **/
|
|
static int mptsas_get_linkerrors(struct sas_phy *phy)
|
|
{
|
|
MPT_ADAPTER *ioc = phy_to_ioc(phy);
|
|
@@ -1963,6 +2425,13 @@ static int mptsas_get_linkerrors(struct
|
|
return error;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_mgmt_done -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @req:
|
|
+ * @reply:
|
|
+ *
|
|
+ **/
|
|
static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
|
|
MPT_FRAME_HDR *reply)
|
|
{
|
|
@@ -1981,6 +2450,12 @@ static int mptsas_mgmt_done(MPT_ADAPTER
|
|
return 0;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_phy_reset -
|
|
+ * @phy:
|
|
+ * @hard_reset:
|
|
+ *
|
|
+ **/
|
|
static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
|
|
{
|
|
MPT_ADAPTER *ioc = phy_to_ioc(phy);
|
|
@@ -2019,14 +2494,16 @@ static int mptsas_phy_reset(struct sas_p
|
|
|
|
INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
|
|
mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
|
|
-
|
|
- timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
|
|
- 10 * HZ);
|
|
- if (!timeleft) {
|
|
- /* On timeout reset the board */
|
|
+ timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10*HZ);
|
|
+ if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
+ error = -ETIME;
|
|
mpt_free_msg_frame(ioc, mf);
|
|
- mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
- error = -ETIMEDOUT;
|
|
+ if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
|
|
+ goto out_unlock;
|
|
+ if (!timeleft) {
|
|
+ if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
|
|
+ mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
+ }
|
|
goto out_unlock;
|
|
}
|
|
|
|
@@ -2055,6 +2532,12 @@ static int mptsas_phy_reset(struct sas_p
|
|
return error;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_get_enclosure_identifier -
|
|
+ * @rphy:
|
|
+ * @identifier:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
|
|
{
|
|
@@ -2089,6 +2572,11 @@ mptsas_get_enclosure_identifier(struct s
|
|
return error;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_get_bay_identifier -
|
|
+ * @rphy:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_get_bay_identifier(struct sas_rphy *rphy)
|
|
{
|
|
@@ -2176,10 +2664,14 @@ static int mptsas_smp_handler(struct Scs
|
|
(((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
|
|
|
|
/* request */
|
|
- flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
|
|
- MPI_SGE_FLAGS_END_OF_BUFFER |
|
|
- MPI_SGE_FLAGS_DIRECTION)
|
|
- << MPI_SGE_FLAGS_SHIFT;
|
|
+
|
|
+ flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
|
|
+ MPI_SGE_FLAGS_SYSTEM_ADDRESS |
|
|
+ MPI_SGE_FLAGS_HOST_TO_IOC |
|
|
+ MPI_SGE_FLAGS_END_OF_BUFFER;
|
|
+
|
|
+ flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
|
|
+
|
|
flagsLength |= (blk_rq_bytes(req) - 4);
|
|
|
|
dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
|
|
@@ -2200,20 +2692,27 @@ static int mptsas_smp_handler(struct Scs
|
|
dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio),
|
|
blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
|
|
if (!dma_addr_in)
|
|
- goto unmap;
|
|
+ goto out_unmap;
|
|
+
|
|
ioc->add_sge(psge, flagsLength, dma_addr_in);
|
|
|
|
INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
|
|
mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
|
|
|
|
timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
|
|
- if (!timeleft) {
|
|
- printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __func__);
|
|
- /* On timeout reset the board */
|
|
- mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
- ret = -ETIMEDOUT;
|
|
- goto unmap;
|
|
+ if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
+ ret = -ETIME;
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ mf = NULL;
|
|
+ if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
|
|
+ goto out_unmap;
|
|
+ if (!timeleft) {
|
|
+ if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
|
|
+ mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
+ }
|
|
+ goto out_unmap;
|
|
}
|
|
+
|
|
mf = NULL;
|
|
|
|
if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
|
|
@@ -2230,7 +2729,7 @@ static int mptsas_smp_handler(struct Scs
|
|
ioc->name, __func__);
|
|
ret = -ENXIO;
|
|
}
|
|
-unmap:
|
|
+out_unmap:
|
|
if (dma_addr_out)
|
|
pci_unmap_single(ioc->pcidev, dma_addr_out, blk_rq_bytes(req),
|
|
PCI_DMA_BIDIRECTIONAL);
|
|
@@ -2247,6 +2746,7 @@ out:
|
|
return ret;
|
|
}
|
|
|
|
+
|
|
static struct sas_function_template mptsas_transport_functions = {
|
|
.get_linkerrors = mptsas_get_linkerrors,
|
|
.get_enclosure_identifier = mptsas_get_enclosure_identifier,
|
|
@@ -2257,6 +2757,12 @@ static struct sas_function_template mpts
|
|
|
|
static struct scsi_transport_template *mptsas_transport_template;
|
|
|
|
+/**
|
|
+ * mptsas_sas_io_unit_pg0 -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @port_info:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
|
|
{
|
|
@@ -2305,7 +2811,7 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc,
|
|
|
|
port_info->num_phys = buffer->NumPhys;
|
|
port_info->phy_info = kcalloc(port_info->num_phys,
|
|
- sizeof(struct mptsas_phyinfo), GFP_KERNEL);
|
|
+ sizeof(struct mptsas_phyinfo),GFP_KERNEL);
|
|
if (!port_info->phy_info) {
|
|
error = -ENOMEM;
|
|
goto out_free_consistent;
|
|
@@ -2335,6 +2841,11 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc,
|
|
return error;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_sas_io_unit_pg1 -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
|
|
{
|
|
@@ -2350,11 +2861,11 @@ mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
|
|
|
|
cfg.cfghdr.ehdr = &hdr;
|
|
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
- cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
|
|
cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
|
|
cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
|
|
cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
|
|
cfg.cfghdr.ehdr->PageNumber = 1;
|
|
+ cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
|
|
|
|
error = mpt_config(ioc, &cfg);
|
|
if (error)
|
|
@@ -2392,6 +2903,14 @@ mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
|
|
return error;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_sas_phy_pg0 -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @phy_info:
|
|
+ * @form:
|
|
+ * @form_specific:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
|
|
u32 form, u32 form_specific)
|
|
@@ -2412,12 +2931,12 @@ mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, str
|
|
|
|
cfg.cfghdr.ehdr = &hdr;
|
|
cfg.dir = 0; /* read */
|
|
- cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
|
|
|
|
/* Get Phy Pg 0 for each Phy. */
|
|
cfg.physAddr = -1;
|
|
cfg.pageAddr = form + form_specific;
|
|
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
|
|
|
|
error = mpt_config(ioc, &cfg);
|
|
if (error)
|
|
@@ -2456,6 +2975,14 @@ mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, str
|
|
return error;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_sas_device_pg0 -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @device_info:
|
|
+ * @form:
|
|
+ * @form_specific:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
|
|
u32 form, u32 form_specific)
|
|
@@ -2482,7 +3009,6 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc,
|
|
cfg.dir = 0; /* read */
|
|
cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
|
|
|
|
- memset(device_info, 0, sizeof(struct mptsas_devinfo));
|
|
error = mpt_config(ioc, &cfg);
|
|
if (error)
|
|
goto out;
|
|
@@ -2502,6 +3028,12 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc,
|
|
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
|
|
error = mpt_config(ioc, &cfg);
|
|
+
|
|
+ if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
|
|
+ error = -ENODEV;
|
|
+ goto out_free_consistent;
|
|
+ }
|
|
+
|
|
if (error)
|
|
goto out_free_consistent;
|
|
|
|
@@ -2530,6 +3062,14 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc,
|
|
return error;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_sas_expander_pg0 -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @port_info:
|
|
+ * @form:
|
|
+ * @form_specific:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
|
|
u32 form, u32 form_specific)
|
|
@@ -2557,7 +3097,6 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc
|
|
cfg.dir = 0; /* read */
|
|
cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
|
|
|
|
- memset(port_info, 0, sizeof(struct mptsas_portinfo));
|
|
error = mpt_config(ioc, &cfg);
|
|
if (error)
|
|
goto out;
|
|
@@ -2578,18 +3117,18 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc
|
|
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
|
|
error = mpt_config(ioc, &cfg);
|
|
- if (error)
|
|
- goto out_free_consistent;
|
|
-
|
|
- if (!buffer->NumPhys) {
|
|
+ if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
|
|
error = -ENODEV;
|
|
goto out_free_consistent;
|
|
}
|
|
|
|
+ if (error)
|
|
+ goto out_free_consistent;
|
|
+
|
|
/* save config data */
|
|
port_info->num_phys = (buffer->NumPhys) ? buffer->NumPhys : 1;
|
|
port_info->phy_info = kcalloc(port_info->num_phys,
|
|
- sizeof(struct mptsas_phyinfo), GFP_KERNEL);
|
|
+ sizeof(struct mptsas_phyinfo),GFP_KERNEL);
|
|
if (!port_info->phy_info) {
|
|
error = -ENOMEM;
|
|
goto out_free_consistent;
|
|
@@ -2613,6 +3152,14 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc
|
|
return error;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_sas_expander_pg1 -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @phy_info:
|
|
+ * @form:
|
|
+ * @form_specific:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
|
|
u32 form, u32 form_specific)
|
|
@@ -2658,7 +3205,6 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc
|
|
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
|
|
error = mpt_config(ioc, &cfg);
|
|
-
|
|
if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
|
|
error = -ENODEV;
|
|
goto out;
|
|
@@ -2686,6 +3232,199 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc
|
|
return error;
|
|
}
|
|
|
|
+struct rep_manu_request{
|
|
+ u8 smp_frame_type;
|
|
+ u8 function;
|
|
+ u8 reserved;
|
|
+ u8 request_length;
|
|
+};
|
|
+
|
|
+struct rep_manu_reply{
|
|
+ u8 smp_frame_type; /* 0x41 */
|
|
+ u8 function; /* 0x01 */
|
|
+ u8 function_result;
|
|
+ u8 response_length;
|
|
+ u16 expander_change_count;
|
|
+ u8 reserved0[2];
|
|
+ u8 sas_format:1;
|
|
+ u8 reserved1:7;
|
|
+ u8 reserved2[3];
|
|
+ u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
|
|
+ u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
|
|
+ u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
|
|
+ u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
|
|
+ u16 component_id;
|
|
+ u8 component_revision_id;
|
|
+ u8 reserved3;
|
|
+ u8 vendor_specific[8];
|
|
+};
|
|
+
|
|
+/**
|
|
+ * mptsas_exp_repmanufacture_info -
|
|
+ * @ioc: per adapter object
|
|
+ * @sas_address: expander sas address
|
|
+ * @edev: the sas_expander_device object
|
|
+ *
|
|
+ * Fills in the sas_expander_device object when SMP port is created.
|
|
+ *
|
|
+ * Returns 0 for success, non-zero for failure.
|
|
+ */
|
|
+static int
|
|
+mptsas_exp_repmanufacture_info(MPT_ADAPTER *ioc,
|
|
+ u64 sas_address, struct sas_expander_device *edev)
|
|
+{
|
|
+ MPT_FRAME_HDR *mf;
|
|
+ SmpPassthroughRequest_t *smpreq;
|
|
+ SmpPassthroughReply_t *smprep;
|
|
+ struct rep_manu_reply *manufacture_reply;
|
|
+ struct rep_manu_request *manufacture_request;
|
|
+ int ret;
|
|
+ int flagsLength;
|
|
+ unsigned long timeleft;
|
|
+ char *psge;
|
|
+ unsigned long flags;
|
|
+ void *data_out = NULL;
|
|
+ dma_addr_t data_out_dma = 0;
|
|
+ u32 sz;
|
|
+
|
|
+ spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
|
|
+ if (ioc->ioc_reset_in_progress) {
|
|
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
+ printk(MYIOC_s_INFO_FMT "%s: host reset in progress!\n",
|
|
+ __func__, ioc->name);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
+
|
|
+ ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+
|
|
+ mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
|
|
+ if (!mf) {
|
|
+ ret = -ENOMEM;
|
|
+ goto out_unlock;
|
|
+ }
|
|
+
|
|
+ smpreq = (SmpPassthroughRequest_t *)mf;
|
|
+ memset(smpreq, 0, sizeof(*smpreq));
|
|
+
|
|
+ sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
|
|
+
|
|
+ data_out = pci_alloc_consistent(ioc->pcidev, sz, &data_out_dma);
|
|
+ if (!data_out) {
|
|
+ printk(KERN_ERR "Memory allocation failure at %s:%d/%s()!\n",
|
|
+ __FILE__, __LINE__, __func__);
|
|
+ ret = -ENOMEM;
|
|
+ goto put_mf;
|
|
+ }
|
|
+
|
|
+ manufacture_request = data_out;
|
|
+ manufacture_request->smp_frame_type = 0x40;
|
|
+ manufacture_request->function = 1;
|
|
+ manufacture_request->reserved = 0;
|
|
+ manufacture_request->request_length = 0;
|
|
+
|
|
+ smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
|
|
+ smpreq->PhysicalPort = 0xFF;
|
|
+ *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
|
|
+ smpreq->RequestDataLength = sizeof(struct rep_manu_request);
|
|
+
|
|
+ psge = (char *)
|
|
+ (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
|
|
+
|
|
+ flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
|
|
+ MPI_SGE_FLAGS_SYSTEM_ADDRESS |
|
|
+ MPI_SGE_FLAGS_HOST_TO_IOC |
|
|
+ MPI_SGE_FLAGS_END_OF_BUFFER;
|
|
+ flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
|
|
+ flagsLength |= sizeof(struct rep_manu_request);
|
|
+
|
|
+ ioc->add_sge(psge, flagsLength, data_out_dma);
|
|
+ psge += ioc->SGE_size;
|
|
+
|
|
+ flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
|
|
+ MPI_SGE_FLAGS_SYSTEM_ADDRESS |
|
|
+ MPI_SGE_FLAGS_IOC_TO_HOST |
|
|
+ MPI_SGE_FLAGS_END_OF_BUFFER;
|
|
+ flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
|
|
+ flagsLength |= sizeof(struct rep_manu_reply);
|
|
+ ioc->add_sge(psge, flagsLength, data_out_dma +
|
|
+ sizeof(struct rep_manu_request));
|
|
+
|
|
+ INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
|
|
+ mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
|
|
+
|
|
+ timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
|
|
+ if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
+ ret = -ETIME;
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ mf = NULL;
|
|
+ if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
|
|
+ goto out_free;
|
|
+ if (!timeleft) {
|
|
+ if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
|
|
+ mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
+ }
|
|
+ goto out_free;
|
|
+ }
|
|
+
|
|
+ mf = NULL;
|
|
+
|
|
+ if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
|
|
+ u8 *tmp;
|
|
+
|
|
+ smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
|
|
+ if (le16_to_cpu(smprep->ResponseDataLength) !=
|
|
+ sizeof(struct rep_manu_reply))
|
|
+ goto out_free;
|
|
+
|
|
+ manufacture_reply = data_out + sizeof(struct rep_manu_request);
|
|
+ strncpy(edev->vendor_id, manufacture_reply->vendor_id,
|
|
+ SAS_EXPANDER_VENDOR_ID_LEN);
|
|
+ strncpy(edev->product_id, manufacture_reply->product_id,
|
|
+ SAS_EXPANDER_PRODUCT_ID_LEN);
|
|
+ strncpy(edev->product_rev, manufacture_reply->product_rev,
|
|
+ SAS_EXPANDER_PRODUCT_REV_LEN);
|
|
+ edev->level = manufacture_reply->sas_format;
|
|
+ if (manufacture_reply->sas_format) {
|
|
+ strncpy(edev->component_vendor_id,
|
|
+ manufacture_reply->component_vendor_id,
|
|
+ SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
|
|
+ tmp = (u8 *)&manufacture_reply->component_id;
|
|
+ edev->component_id = tmp[0] << 8 | tmp[1];
|
|
+ edev->component_revision_id =
|
|
+ manufacture_reply->component_revision_id;
|
|
+ }
|
|
+
|
|
+ } else {
|
|
+ printk(MYIOC_s_ERR_FMT
|
|
+ "%s: smp passthru reply failed to be returned\n",
|
|
+ ioc->name, __func__);
|
|
+ ret = -ENXIO;
|
|
+ }
|
|
+
|
|
+out_free:
|
|
+ if (data_out_dma)
|
|
+ pci_free_consistent(ioc->pcidev, sz, data_out, data_out_dma);
|
|
+put_mf:
|
|
+ if (mf)
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+out_unlock:
|
|
+ CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
|
|
+ mutex_unlock(&ioc->sas_mgmt.mutex);
|
|
+out:
|
|
+ return ret;
|
|
+
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * mptsas_parse_device_info -
|
|
+ * @identify:
|
|
+ * @device_info:
|
|
+ *
|
|
+ **/
|
|
static void
|
|
mptsas_parse_device_info(struct sas_identify *identify,
|
|
struct mptsas_devinfo *device_info)
|
|
@@ -2745,6 +3484,13 @@ mptsas_parse_device_info(struct sas_iden
|
|
}
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_probe_one_phy -
|
|
+ * @dev:
|
|
+ * @phy_info:
|
|
+ * @local:
|
|
+ *
|
|
+ **/
|
|
static int mptsas_probe_one_phy(struct device *dev,
|
|
struct mptsas_phyinfo *phy_info, int index, int local)
|
|
{
|
|
@@ -2868,7 +3614,6 @@ static int mptsas_probe_one_phy(struct d
|
|
ioc = phy_to_ioc(phy_info->phy);
|
|
|
|
if (phy_info->sas_port_add_phy) {
|
|
-
|
|
if (!port) {
|
|
port = sas_port_alloc_num(dev);
|
|
if (!port) {
|
|
@@ -2886,20 +3631,18 @@ static int mptsas_probe_one_phy(struct d
|
|
devtprintk(ioc, dev_printk(KERN_DEBUG, &port->dev,
|
|
MYIOC_s_FMT "add port %d, sas_addr (0x%llx)\n",
|
|
ioc->name, port->port_identifier,
|
|
- (unsigned long long)phy_info->
|
|
- attached.sas_address));
|
|
+ (unsigned long long)phy_info->attached.sas_address));
|
|
}
|
|
- dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- "sas_port_add_phy: phy_id=%d\n",
|
|
- ioc->name, phy_info->phy_id));
|
|
+ dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_port_add_phy: phy_id=%d\n",
|
|
+ ioc->name, phy_info->phy_id));
|
|
sas_port_add_phy(port, phy_info->phy);
|
|
phy_info->sas_port_add_phy = 0;
|
|
devtprintk(ioc, dev_printk(KERN_DEBUG, &phy_info->phy->dev,
|
|
MYIOC_s_FMT "add phy %d, phy-obj (0x%p)\n", ioc->name,
|
|
phy_info->phy_id, phy_info->phy));
|
|
}
|
|
- if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
|
|
|
|
+ if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
|
|
struct sas_rphy *rphy;
|
|
struct device *parent;
|
|
struct sas_identify identify;
|
|
@@ -2967,12 +3710,23 @@ static int mptsas_probe_one_phy(struct d
|
|
goto out;
|
|
}
|
|
mptsas_set_rphy(ioc, phy_info, rphy);
|
|
+ if (identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
|
|
+ identify.device_type == SAS_FANOUT_EXPANDER_DEVICE)
|
|
+ mptsas_exp_repmanufacture_info(ioc,
|
|
+ identify.sas_address,
|
|
+ rphy_to_expander_device(rphy));
|
|
}
|
|
|
|
out:
|
|
return error;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_probe_hba_phys -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @handle:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
|
|
{
|
|
@@ -3403,13 +4157,12 @@ mptsas_send_link_status_event(struct fw_
|
|
if (!port_info) {
|
|
if (ioc->old_sas_discovery_protocal) {
|
|
port_info = mptsas_expander_add(ioc,
|
|
- le16_to_cpu(link_data->DevHandle));
|
|
+ le16_to_cpu(link_data->DevHandle));
|
|
if (port_info)
|
|
goto out;
|
|
}
|
|
goto out;
|
|
}
|
|
-
|
|
if (port_info == ioc->hba_port_info)
|
|
mptsas_probe_hba_phys(ioc);
|
|
else
|
|
@@ -3434,7 +4187,7 @@ static void
|
|
mptsas_not_responding_devices(MPT_ADAPTER *ioc)
|
|
{
|
|
struct mptsas_portinfo buffer, *port_info;
|
|
- struct mptsas_device_info *sas_info;
|
|
+ struct sas_device_info *sas_info;
|
|
struct mptsas_devinfo sas_device;
|
|
u32 handle;
|
|
VirtTarget *vtarget = NULL;
|
|
@@ -3443,6 +4196,9 @@ mptsas_not_responding_devices(MPT_ADAPTE
|
|
int retval, retry_count;
|
|
unsigned long flags;
|
|
|
|
+ if (ioc->disable_hotplug_remove)
|
|
+ return;
|
|
+
|
|
mpt_findImVolumes(ioc);
|
|
|
|
spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
|
|
@@ -3456,74 +4212,66 @@ mptsas_not_responding_devices(MPT_ADAPTE
|
|
spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
|
|
/* devices, logical volumes */
|
|
- mutex_lock(&ioc->sas_device_info_mutex);
|
|
redo_device_scan:
|
|
list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
|
|
if (sas_info->is_cached)
|
|
continue;
|
|
if (!sas_info->is_logical_volume) {
|
|
- sas_device.handle = 0;
|
|
- retry_count = 0;
|
|
+ sas_device.handle = 0;
|
|
+ retry_count = 0;
|
|
retry_page:
|
|
- retval = mptsas_sas_device_pg0(ioc, &sas_device,
|
|
+ retval = mptsas_sas_device_pg0(ioc, &sas_device,
|
|
(MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID
|
|
<< MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
|
|
(sas_info->fw.channel << 8) +
|
|
sas_info->fw.id);
|
|
|
|
- if (sas_device.handle)
|
|
- continue;
|
|
- if (retval == -EBUSY) {
|
|
- spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
|
|
- if (ioc->ioc_reset_in_progress) {
|
|
- dfailprintk(ioc,
|
|
- printk(MYIOC_s_DEBUG_FMT
|
|
- "%s: exiting due to reset\n",
|
|
- ioc->name, __func__));
|
|
- spin_unlock_irqrestore
|
|
- (&ioc->taskmgmt_lock, flags);
|
|
- mutex_unlock(&ioc->
|
|
- sas_device_info_mutex);
|
|
- return;
|
|
- }
|
|
- spin_unlock_irqrestore(&ioc->taskmgmt_lock,
|
|
- flags);
|
|
+ if (sas_device.handle)
|
|
+ continue;
|
|
+ if (retval == -EBUSY) {
|
|
+ spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
|
|
+ if (ioc->ioc_reset_in_progress) {
|
|
+ dfailprintk(ioc,
|
|
+ printk(MYIOC_s_DEBUG_FMT
|
|
+ "%s: exiting due to reset\n",
|
|
+ ioc->name, __func__));
|
|
+ spin_unlock_irqrestore
|
|
+ (&ioc->taskmgmt_lock, flags);
|
|
+ return;
|
|
}
|
|
+ spin_unlock_irqrestore(&ioc->taskmgmt_lock,
|
|
+ flags);
|
|
+ }
|
|
|
|
- if (retval && (retval != -ENODEV)) {
|
|
- if (retry_count < 10) {
|
|
- retry_count++;
|
|
- goto retry_page;
|
|
- } else {
|
|
- devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- "%s: Config page retry exceeded retry "
|
|
- "count deleting device 0x%llx\n",
|
|
- ioc->name, __func__,
|
|
- sas_info->sas_address));
|
|
- }
|
|
+ if (retval && (retval != -ENODEV)) {
|
|
+ if (retry_count < 10) {
|
|
+ retry_count++;
|
|
+ goto retry_page;
|
|
+ } else {
|
|
+ devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
+ "%s: Config page retry exceeded retry "
|
|
+ "count deleting device 0x%llx\n",
|
|
+ ioc->name, __func__,
|
|
+ sas_info->sas_address));
|
|
}
|
|
+ }
|
|
|
|
- /* delete device */
|
|
- vtarget = mptsas_find_vtarget(ioc,
|
|
+ /* delete device */
|
|
+ vtarget = mptsas_find_vtarget(ioc,
|
|
sas_info->fw.channel, sas_info->fw.id);
|
|
-
|
|
- if (vtarget)
|
|
- vtarget->deleted = 1;
|
|
-
|
|
- phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
|
|
- sas_info->sas_address);
|
|
-
|
|
- if (phy_info) {
|
|
- mptsas_del_end_device(ioc, phy_info);
|
|
- goto redo_device_scan;
|
|
- }
|
|
+ if (vtarget)
|
|
+ vtarget->deleted = 1;
|
|
+ phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
|
|
+ sas_info->sas_address);
|
|
+ if (phy_info) {
|
|
+ mptsas_del_end_device(ioc, phy_info);
|
|
+ goto redo_device_scan;
|
|
+ }
|
|
} else
|
|
mptsas_volume_delete(ioc, sas_info->fw.id);
|
|
}
|
|
- mutex_unlock(&ioc->sas_device_info_mutex);
|
|
|
|
/* expanders */
|
|
- mutex_lock(&ioc->sas_topology_mutex);
|
|
redo_expander_scan:
|
|
list_for_each_entry(port_info, &ioc->sas_topology, list) {
|
|
|
|
@@ -3551,7 +4299,6 @@ retry_page:
|
|
goto redo_expander_scan;
|
|
}
|
|
}
|
|
- mutex_unlock(&ioc->sas_topology_mutex);
|
|
}
|
|
|
|
/**
|
|
@@ -3563,7 +4310,7 @@ static void
|
|
mptsas_probe_expanders(MPT_ADAPTER *ioc)
|
|
{
|
|
struct mptsas_portinfo buffer, *port_info;
|
|
- u32 handle;
|
|
+ u32 handle;
|
|
int i;
|
|
|
|
handle = 0xFFFF;
|
|
@@ -3611,9 +4358,11 @@ mptsas_probe_expanders(MPT_ADAPTER *ioc)
|
|
static void
|
|
mptsas_probe_devices(MPT_ADAPTER *ioc)
|
|
{
|
|
+ u16 retry_count;
|
|
u16 handle;
|
|
struct mptsas_devinfo sas_device;
|
|
struct mptsas_phyinfo *phy_info;
|
|
+ enum device_state state;
|
|
|
|
handle = 0xFFFF;
|
|
while (!(mptsas_sas_device_pg0(ioc, &sas_device,
|
|
@@ -3634,7 +4383,17 @@ mptsas_probe_devices(MPT_ADAPTER *ioc)
|
|
if (mptsas_get_rphy(phy_info))
|
|
continue;
|
|
|
|
- mptsas_add_end_device(ioc, phy_info);
|
|
+ state = DEVICE_RETRY;
|
|
+ retry_count = 0;
|
|
+ while(state == DEVICE_RETRY) {
|
|
+ state = mptsas_test_unit_ready(ioc, sas_device.channel,
|
|
+ sas_device.id, retry_count++);
|
|
+ ssleep(1);
|
|
+ }
|
|
+ if (state == DEVICE_READY)
|
|
+ mptsas_add_end_device(ioc, phy_info);
|
|
+ else
|
|
+ memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
|
|
}
|
|
}
|
|
|
|
@@ -3676,13 +4435,14 @@ mptsas_scan_sas_topology(MPT_ADAPTER *io
|
|
}
|
|
|
|
|
|
+
|
|
static void
|
|
mptsas_handle_queue_full_event(struct fw_event_work *fw_event)
|
|
{
|
|
MPT_ADAPTER *ioc;
|
|
EventDataQueueFull_t *qfull_data;
|
|
- struct mptsas_device_info *sas_info;
|
|
- struct scsi_device *sdev;
|
|
+ struct sas_device_info *sas_info;
|
|
+ struct scsi_device *sdev;
|
|
int depth;
|
|
int id = -1;
|
|
int channel = -1;
|
|
@@ -3697,7 +4457,7 @@ mptsas_handle_queue_full_event(struct fw
|
|
current_depth = le16_to_cpu(qfull_data->CurrentDepth);
|
|
|
|
/* if hidden raid component, look for the volume id */
|
|
- mutex_lock(&ioc->sas_device_info_mutex);
|
|
+ down(&ioc->sas_device_info_mutex);
|
|
if (mptscsih_is_phys_disk(ioc, fw_channel, fw_id)) {
|
|
list_for_each_entry(sas_info, &ioc->sas_device_info_list,
|
|
list) {
|
|
@@ -3730,7 +4490,7 @@ mptsas_handle_queue_full_event(struct fw
|
|
}
|
|
|
|
out:
|
|
- mutex_unlock(&ioc->sas_device_info_mutex);
|
|
+ up(&ioc->sas_device_info_mutex);
|
|
|
|
if (id != -1) {
|
|
shost_for_each_device(sdev, ioc->sh) {
|
|
@@ -3764,6 +4524,12 @@ mptsas_handle_queue_full_event(struct fw
|
|
}
|
|
|
|
|
|
+/**
|
|
+ * mptsas_find_phyinfo_by_sas_address -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @sas_address:
|
|
+ *
|
|
+ **/
|
|
static struct mptsas_phyinfo *
|
|
mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
|
|
{
|
|
@@ -3788,6 +4554,7 @@ mptsas_find_phyinfo_by_sas_address(MPT_A
|
|
return phy_info;
|
|
}
|
|
|
|
+
|
|
/**
|
|
* mptsas_find_phyinfo_by_phys_disk_num -
|
|
* @ioc: Pointer to MPT_ADAPTER structure
|
|
@@ -3814,7 +4581,7 @@ mptsas_find_phyinfo_by_phys_disk_num(MPT
|
|
num_paths = mpt_raid_phys_disk_get_num_paths(ioc, phys_disk_num);
|
|
if (!num_paths)
|
|
goto out;
|
|
- phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
|
|
+ phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t,Path) +
|
|
(num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
|
|
if (!phys_disk)
|
|
goto out;
|
|
@@ -3827,8 +4594,7 @@ mptsas_find_phyinfo_by_phys_disk_num(MPT
|
|
(channel == phys_disk->Path[i].PhysDiskBus)) {
|
|
memcpy(&sas_address, &phys_disk->Path[i].WWID,
|
|
sizeof(u64));
|
|
- phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
|
|
- sas_address);
|
|
+ phy_info = mptsas_find_phyinfo_by_sas_address(ioc, sas_address);
|
|
goto out;
|
|
}
|
|
}
|
|
@@ -3850,11 +4616,9 @@ mptsas_find_phyinfo_by_phys_disk_num(MPT
|
|
continue;
|
|
if (port_info->phy_info[i].attached.phys_disk_num == ~0)
|
|
continue;
|
|
- if ((port_info->phy_info[i].attached.phys_disk_num ==
|
|
- phys_disk_num) &&
|
|
- (port_info->phy_info[i].attached.id == id) &&
|
|
- (port_info->phy_info[i].attached.channel ==
|
|
- channel))
|
|
+ if (port_info->phy_info[i].attached.phys_disk_num == phys_disk_num &&
|
|
+ port_info->phy_info[i].attached.id == id &&
|
|
+ port_info->phy_info[i].attached.channel == channel)
|
|
phy_info = &port_info->phy_info[i];
|
|
}
|
|
}
|
|
@@ -3862,6 +4626,12 @@ mptsas_find_phyinfo_by_phys_disk_num(MPT
|
|
return phy_info;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_reprobe_lun -
|
|
+ * @sdev:
|
|
+ * @data:
|
|
+ *
|
|
+ **/
|
|
static void
|
|
mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
|
|
{
|
|
@@ -3871,6 +4641,12 @@ mptsas_reprobe_lun(struct scsi_device *s
|
|
rc = scsi_device_reprobe(sdev);
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_reprobe_target -
|
|
+ * @starget:
|
|
+ * @uld_attach:
|
|
+ *
|
|
+ **/
|
|
static void
|
|
mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
|
|
{
|
|
@@ -3878,6 +4654,15 @@ mptsas_reprobe_target(struct scsi_target
|
|
mptsas_reprobe_lun);
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_adding_inactive_raid_components -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @channel:
|
|
+ * @id:
|
|
+ *
|
|
+ *
|
|
+ * TODO: check for hotspares
|
|
+ **/
|
|
static void
|
|
mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
|
|
{
|
|
@@ -3885,7 +4670,7 @@ mptsas_adding_inactive_raid_components(M
|
|
ConfigPageHeader_t hdr;
|
|
dma_addr_t dma_handle;
|
|
pRaidVolumePage0_t buffer = NULL;
|
|
- RaidPhysDiskPage0_t phys_disk;
|
|
+ RaidPhysDiskPage0_t phys_disk;
|
|
int i;
|
|
struct mptsas_phyinfo *phy_info;
|
|
struct mptsas_devinfo sas_device;
|
|
@@ -3896,6 +4681,7 @@ mptsas_adding_inactive_raid_components(M
|
|
cfg.pageAddr = (channel << 8) + id;
|
|
cfg.cfghdr.hdr = &hdr;
|
|
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
|
|
+ cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
|
|
|
|
if (mpt_config(ioc, &cfg) != 0)
|
|
goto out;
|
|
@@ -3956,6 +4742,7 @@ mptsas_hotplug_work(MPT_ADAPTER *ioc, st
|
|
struct scsi_target * starget;
|
|
struct mptsas_devinfo sas_device;
|
|
VirtTarget *vtarget;
|
|
+ enum device_state state;
|
|
int i;
|
|
|
|
switch (hot_plug_info->event_type) {
|
|
@@ -3995,13 +4782,27 @@ mptsas_hotplug_work(MPT_ADAPTER *ioc, st
|
|
if (mptsas_get_rphy(phy_info))
|
|
break;
|
|
|
|
- mptsas_add_end_device(ioc, phy_info);
|
|
+ state = mptsas_test_unit_ready(ioc, phy_info->attached.channel,
|
|
+ phy_info->attached.id, fw_event->retries);
|
|
+
|
|
+ if (state == DEVICE_RETRY && !ioc->fw_events_off) {
|
|
+ mptsas_requeue_fw_event(ioc, fw_event, 1000);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (state == DEVICE_READY)
|
|
+ mptsas_add_end_device(ioc, phy_info);
|
|
+ else
|
|
+ memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
|
|
break;
|
|
|
|
case MPTSAS_DEL_DEVICE:
|
|
- phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
|
|
- hot_plug_info->sas_address);
|
|
- mptsas_del_end_device(ioc, phy_info);
|
|
+
|
|
+ if (!ioc->disable_hotplug_remove) {
|
|
+ phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
|
|
+ hot_plug_info->sas_address);
|
|
+ mptsas_del_end_device(ioc, phy_info);
|
|
+ }
|
|
break;
|
|
|
|
case MPTSAS_DEL_PHYSDISK:
|
|
@@ -4009,9 +4810,8 @@ mptsas_hotplug_work(MPT_ADAPTER *ioc, st
|
|
mpt_findImVolumes(ioc);
|
|
|
|
phy_info = mptsas_find_phyinfo_by_phys_disk_num(
|
|
- ioc, hot_plug_info->phys_disk_num,
|
|
- hot_plug_info->channel,
|
|
- hot_plug_info->id);
|
|
+ ioc, hot_plug_info->phys_disk_num, hot_plug_info->channel,
|
|
+ hot_plug_info->id);
|
|
mptsas_del_end_device(ioc, phy_info);
|
|
break;
|
|
|
|
@@ -4162,6 +4962,14 @@ mptsas_hotplug_work(MPT_ADAPTER *ioc, st
|
|
mptsas_free_fw_event(ioc, fw_event);
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_send_sas_event
|
|
+ *
|
|
+ *
|
|
+ * @ioc
|
|
+ * @sas_event_data
|
|
+ *
|
|
+ **/
|
|
static void
|
|
mptsas_send_sas_event(struct fw_event_work *fw_event)
|
|
{
|
|
@@ -4228,6 +5036,15 @@ mptsas_send_sas_event(struct fw_event_wo
|
|
}
|
|
}
|
|
|
|
+
|
|
+/**
|
|
+ * mptsas_send_raid_event
|
|
+ *
|
|
+ *
|
|
+ * @ioc
|
|
+ * @raid_event_data
|
|
+ *
|
|
+ **/
|
|
static void
|
|
mptsas_send_raid_event(struct fw_event_work *fw_event)
|
|
{
|
|
@@ -4347,19 +5164,19 @@ mptsas_send_raid_event(struct fw_event_w
|
|
/**
|
|
* mptsas_issue_tm - send mptsas internal tm request
|
|
* @ioc: Pointer to MPT_ADAPTER structure
|
|
- * @type: Task Management type
|
|
- * @channel: channel number for task management
|
|
- * @id: Logical Target ID for reset (if appropriate)
|
|
- * @lun: Logical unit for reset (if appropriate)
|
|
- * @task_context: Context for the task to be aborted
|
|
- * @timeout: timeout for task management control
|
|
+ * @type
|
|
+ * @channel
|
|
+ * @id
|
|
+ * @lun
|
|
+ * @task_context
|
|
+ * @timeout
|
|
*
|
|
- * return 0 on success and -1 on failure:
|
|
+ * return:
|
|
*
|
|
- */
|
|
+ **/
|
|
static int
|
|
-mptsas_issue_tm(MPT_ADAPTER *ioc, u8 type, u8 channel, u8 id, u64 lun,
|
|
- int task_context, ulong timeout, u8 *issue_reset)
|
|
+mptsas_issue_tm(MPT_ADAPTER *ioc, u8 type, u8 channel, u8 id, u64 lun, int task_context, ulong timeout,
|
|
+ u8 *issue_reset)
|
|
{
|
|
MPT_FRAME_HDR *mf;
|
|
SCSITaskMgmt_t *pScsiTm;
|
|
@@ -4367,8 +5184,7 @@ mptsas_issue_tm(MPT_ADAPTER *ioc, u8 typ
|
|
unsigned long timeleft;
|
|
|
|
*issue_reset = 0;
|
|
- mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
|
|
- if (mf == NULL) {
|
|
+ if ((mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc)) == NULL) {
|
|
retval = -1; /* return failure */
|
|
dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt request: no "
|
|
"msg frames!!\n", ioc->name));
|
|
@@ -4426,20 +5242,20 @@ mptsas_issue_tm(MPT_ADAPTER *ioc, u8 typ
|
|
}
|
|
|
|
/**
|
|
- * mptsas_broadcast_primative_work - Handle broadcast primitives
|
|
+ * mptsas_broadcast_primative_work - Work queue thread to handle
|
|
+ * broadcast primitive events
|
|
* @work: work queue payload containing info describing the event
|
|
*
|
|
- * this will be handled in workqueue context.
|
|
- */
|
|
+ **/
|
|
static void
|
|
mptsas_broadcast_primative_work(struct fw_event_work *fw_event)
|
|
{
|
|
MPT_ADAPTER *ioc = fw_event->ioc;
|
|
- MPT_FRAME_HDR *mf;
|
|
- VirtDevice *vdevice;
|
|
+ MPT_FRAME_HDR *mf;
|
|
+ VirtDevice *vdevice;
|
|
int ii;
|
|
struct scsi_cmnd *sc;
|
|
- SCSITaskMgmtReply_t *pScsiTmReply;
|
|
+ SCSITaskMgmtReply_t * pScsiTmReply;
|
|
u8 issue_reset;
|
|
int task_context;
|
|
u8 channel, id;
|
|
@@ -4448,7 +5264,7 @@ mptsas_broadcast_primative_work(struct f
|
|
u32 query_count;
|
|
|
|
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- "%s - enter\n", ioc->name, __func__));
|
|
+ "%s - enter\n", ioc->name, __FUNCTION__));
|
|
|
|
mutex_lock(&ioc->taskmgmt_cmds.mutex);
|
|
if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
|
|
@@ -4506,7 +5322,7 @@ mptsas_broadcast_primative_work(struct f
|
|
out:
|
|
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
"%s - exit, query_count = %d termination_count = %d\n",
|
|
- ioc->name, __func__, query_count, termination_count));
|
|
+ ioc->name, __FUNCTION__, query_count, termination_count));
|
|
|
|
ioc->broadcast_aen_busy = 0;
|
|
mpt_clear_taskmgmt_in_progress_flag(ioc);
|
|
@@ -4514,20 +5330,19 @@ mptsas_broadcast_primative_work(struct f
|
|
|
|
if (issue_reset) {
|
|
printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
|
|
- ioc->name, __func__);
|
|
- mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
+ ioc->name, __FUNCTION__);
|
|
+ if (mpt_SoftResetHandler(ioc, CAN_SLEEP))
|
|
+ mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
}
|
|
mptsas_free_fw_event(ioc, fw_event);
|
|
}
|
|
|
|
-/*
|
|
- * mptsas_send_ir2_event - handle exposing hidden disk when
|
|
- * an inactive raid volume is added
|
|
- *
|
|
- * @ioc: Pointer to MPT_ADAPTER structure
|
|
- * @ir2_data
|
|
+/**
|
|
+ * 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(struct fw_event_work *fw_event)
|
|
{
|
|
@@ -4569,6 +5384,13 @@ mptsas_send_ir2_event(struct fw_event_wo
|
|
mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
|
|
}
|
|
|
|
+
|
|
+/**
|
|
+ * mptsas_event_process -
|
|
+ * @ioc: Pointer to MPT_ADAPTER structure
|
|
+ * @reply:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
|
|
{
|
|
@@ -4577,6 +5399,9 @@ mptsas_event_process(MPT_ADAPTER *ioc, E
|
|
struct fw_event_work *fw_event;
|
|
unsigned long delay;
|
|
|
|
+ if (ioc->bus_type != SAS)
|
|
+ return 0;
|
|
+
|
|
/* events turned off due to host reset or driver unloading */
|
|
if (ioc->fw_events_off)
|
|
return 0;
|
|
@@ -4659,6 +5484,7 @@ mptsas_event_process(MPT_ADAPTER *ioc, E
|
|
return 0;
|
|
}
|
|
|
|
+
|
|
/* Delete a volume when no longer listed in ioc pg2
|
|
*/
|
|
static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id)
|
|
@@ -4678,18 +5504,24 @@ static void mptsas_volume_delete(MPT_ADA
|
|
goto release_sdev;
|
|
out:
|
|
printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
|
|
- "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, id);
|
|
+ "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,id);
|
|
scsi_remove_device(sdev);
|
|
release_sdev:
|
|
scsi_device_put(sdev);
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_probe -
|
|
+ * @pdev:
|
|
+ * @id:
|
|
+ *
|
|
+ **/
|
|
static int
|
|
mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
{
|
|
struct Scsi_Host *sh;
|
|
MPT_SCSI_HOST *hd;
|
|
- MPT_ADAPTER *ioc;
|
|
+ MPT_ADAPTER *ioc;
|
|
unsigned long flags;
|
|
int ii;
|
|
int numSGE = 0;
|
|
@@ -4707,7 +5539,7 @@ mptsas_probe(struct pci_dev *pdev, const
|
|
ioc->DoneCtx = mptsasDoneCtx;
|
|
ioc->TaskCtx = mptsasTaskCtx;
|
|
ioc->InternalCtx = mptsasInternalCtx;
|
|
-
|
|
+ ioc->schedule_target_reset = &mptsas_schedule_target_reset;
|
|
/* Added sanity check on readiness of the MPT adapter.
|
|
*/
|
|
if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
|
|
@@ -4748,7 +5580,7 @@ mptsas_probe(struct pci_dev *pdev, const
|
|
ioc->name);
|
|
error = -1;
|
|
goto out_mptsas_probe;
|
|
- }
|
|
+ }
|
|
|
|
spin_lock_irqsave(&ioc->FreeQlock, flags);
|
|
|
|
@@ -4773,10 +5605,10 @@ mptsas_probe(struct pci_dev *pdev, const
|
|
|
|
INIT_LIST_HEAD(&ioc->sas_topology);
|
|
mutex_init(&ioc->sas_topology_mutex);
|
|
- mutex_init(&ioc->sas_discovery_mutex);
|
|
mutex_init(&ioc->sas_mgmt.mutex);
|
|
init_completion(&ioc->sas_mgmt.done);
|
|
|
|
+
|
|
/* Verify that we won't exceed the maximum
|
|
* number of chain buffers
|
|
* We can optimize: ZZ = req_sz/sizeof(SGE)
|
|
@@ -4786,6 +5618,7 @@ mptsas_probe(struct pci_dev *pdev, const
|
|
* A slightly different algorithm is required for
|
|
* 64bit SGEs.
|
|
*/
|
|
+
|
|
scale = ioc->req_sz/ioc->SGE_size;
|
|
if (ioc->sg_addr_size == sizeof(u64)) {
|
|
numSGE = (scale - 1) *
|
|
@@ -4822,12 +5655,16 @@ mptsas_probe(struct pci_dev *pdev, const
|
|
dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
|
|
ioc->name, ioc->ScsiLookup));
|
|
|
|
+ ioc->sdev_queue_depth = mpt_sdev_queue_depth;
|
|
ioc->sas_data.ptClear = mpt_pt_clear;
|
|
-
|
|
hd->last_queue_full = 0;
|
|
+ ioc->disable_hotplug_remove = mpt_disable_hotplug_remove;
|
|
+ if (ioc->disable_hotplug_remove)
|
|
+ printk(MYIOC_s_INFO_FMT "disabling hotplug remove\n", ioc->name);
|
|
+
|
|
INIT_LIST_HEAD(&hd->target_reset_list);
|
|
INIT_LIST_HEAD(&ioc->sas_device_info_list);
|
|
- mutex_init(&ioc->sas_device_info_mutex);
|
|
+ init_MUTEX(&ioc->sas_device_info_mutex);
|
|
|
|
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
|
|
|
|
@@ -4865,7 +5702,14 @@ mptsas_shutdown(struct pci_dev *pdev)
|
|
mptsas_cleanup_fw_event_q(ioc);
|
|
}
|
|
|
|
-static void __devexit mptsas_remove(struct pci_dev *pdev)
|
|
+
|
|
+/**
|
|
+ * mptsas_remove -
|
|
+ * @pdev:
|
|
+ *
|
|
+ **/
|
|
+static void __devexit
|
|
+mptsas_remove(struct pci_dev *pdev)
|
|
{
|
|
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
|
struct mptsas_portinfo *p, *n;
|
|
@@ -4875,7 +5719,6 @@ static void __devexit mptsas_remove(stru
|
|
|
|
mptsas_del_device_components(ioc);
|
|
|
|
- ioc->sas_discovery_ignore_events = 1;
|
|
sas_remove_host(ioc->sh);
|
|
|
|
mutex_lock(&ioc->sas_topology_mutex);
|
|
@@ -4920,6 +5763,10 @@ static struct pci_driver mptsas_driver =
|
|
#endif
|
|
};
|
|
|
|
+/**
|
|
+ * mptsas_init -
|
|
+ *
|
|
+ **/
|
|
static int __init
|
|
mptsas_init(void)
|
|
{
|
|
@@ -4950,6 +5797,10 @@ mptsas_init(void)
|
|
return error;
|
|
}
|
|
|
|
+/**
|
|
+ * mptsas_exit -
|
|
+ *
|
|
+ **/
|
|
static void __exit
|
|
mptsas_exit(void)
|
|
{
|
|
--- a/drivers/message/fusion/mptsas.h
|
|
+++ b/drivers/message/fusion/mptsas.h
|
|
@@ -50,8 +50,8 @@
|
|
/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
|
|
struct mptsas_target_reset_event {
|
|
- struct list_head list;
|
|
- EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data;
|
|
+ struct list_head list;
|
|
+ MpiEventDataSasDeviceStatusChange_t sas_event_data;
|
|
u8 target_reset_issued;
|
|
unsigned long time_count;
|
|
};
|
|
@@ -61,34 +61,32 @@ enum mptsas_hotplug_action {
|
|
MPTSAS_DEL_DEVICE,
|
|
MPTSAS_ADD_RAID,
|
|
MPTSAS_DEL_RAID,
|
|
+ MPTSAS_ADD_INACTIVE_VOLUME,
|
|
MPTSAS_ADD_PHYSDISK,
|
|
MPTSAS_ADD_PHYSDISK_REPROBE,
|
|
MPTSAS_DEL_PHYSDISK,
|
|
MPTSAS_DEL_PHYSDISK_REPROBE,
|
|
- MPTSAS_ADD_INACTIVE_VOLUME,
|
|
+ MPTSAS_REQUEUE_EVENT,
|
|
MPTSAS_IGNORE_EVENT,
|
|
};
|
|
|
|
-struct mptsas_mapping{
|
|
+struct sas_mapping{
|
|
u8 id;
|
|
u8 channel;
|
|
};
|
|
|
|
-struct mptsas_device_info {
|
|
- struct list_head list;
|
|
- struct mptsas_mapping os; /* operating system mapping*/
|
|
- struct mptsas_mapping fw; /* firmware mapping */
|
|
+struct sas_device_info {
|
|
+ struct list_head list;
|
|
+ struct sas_mapping os; /* operating system mapping*/
|
|
+ struct sas_mapping fw; /* firmware mapping */
|
|
u64 sas_address;
|
|
u32 device_info; /* specific bits for devices */
|
|
u16 slot; /* enclosure slot id */
|
|
u64 enclosure_logical_id; /*enclosure address */
|
|
u8 is_logical_volume; /* is this logical volume */
|
|
- /* this belongs to volume */
|
|
- u8 is_hidden_raid_component;
|
|
- /* this valid when is_hidden_raid_component set */
|
|
- u8 volume_id;
|
|
- /* cached data for a removed device */
|
|
- u8 is_cached;
|
|
+ u8 is_hidden_raid_component; /* this belongs to volume */
|
|
+ u8 volume_id; /* this valid when is_hidden_raid_component set */
|
|
+ u8 is_cached; /* cached data for a removed device */
|
|
};
|
|
|
|
struct mptsas_hotplug_event {
|
|
@@ -104,19 +102,23 @@ struct mptsas_hotplug_event {
|
|
struct scsi_device *sdev;
|
|
};
|
|
|
|
+
|
|
struct fw_event_work {
|
|
- struct list_head list;
|
|
+ struct list_head list;
|
|
struct delayed_work work;
|
|
- MPT_ADAPTER *ioc;
|
|
+ MPT_ADAPTER *ioc;
|
|
u32 event;
|
|
u8 retries;
|
|
u8 event_data[1];
|
|
};
|
|
|
|
-struct mptsas_discovery_event {
|
|
+#if 0
|
|
+struct mptsas_link_status_event {
|
|
struct work_struct work;
|
|
+ MpiEventDataSasPhyLinkStatus_t link_data;
|
|
MPT_ADAPTER *ioc;
|
|
};
|
|
+#endif
|
|
|
|
/*
|
|
* SAS topology structures
|
|
@@ -146,20 +148,20 @@ struct mptsas_devinfo {
|
|
* Specific details on ports, wide/narrow
|
|
*/
|
|
struct mptsas_portinfo_details{
|
|
- u16 num_phys; /* number of phys belong to this port */
|
|
- u64 phy_bitmask; /* TODO, extend support for 255 phys */
|
|
- struct sas_rphy *rphy; /* transport layer rphy object */
|
|
+ u16 num_phys; /* number of phys beloing to this port */
|
|
+ u64 phy_bitmask; /* this needs extending to support 128 phys */
|
|
+ struct sas_rphy *rphy; /* rphy for end devices */
|
|
struct sas_port *port; /* transport layer port object */
|
|
struct scsi_target *starget;
|
|
struct mptsas_portinfo *port_info;
|
|
};
|
|
|
|
struct mptsas_phyinfo {
|
|
- u16 handle; /* unique id to address this */
|
|
- u8 phy_id; /* phy index */
|
|
- u8 port_id; /* firmware port identifier */
|
|
+ u16 handle; /* handle for this phy */
|
|
+ u8 phy_id; /* phy index */
|
|
+ u8 port_id; /* port number this phy is part of */
|
|
u8 negotiated_link_rate; /* nego'd link rate for this phy */
|
|
- u8 hw_link_rate; /* hardware max/min phys link rate */
|
|
+ u8 hw_link_rate; /* hardware max/min phys link rate */
|
|
u8 programmed_link_rate; /* programmed max/min phy link rate */
|
|
u8 sas_port_add_phy; /* flag to request sas_port_add_phy*/
|
|
struct mptsas_devinfo identify; /* point to phy device info */
|
|
@@ -171,7 +173,7 @@ struct mptsas_phyinfo {
|
|
|
|
struct mptsas_portinfo {
|
|
struct list_head list;
|
|
- u16 num_phys; /* number of phys */
|
|
+ u16 num_phys; /* number of phys */
|
|
struct mptsas_phyinfo *phy_info;
|
|
};
|
|
|
|
@@ -186,6 +188,12 @@ struct mptsas_enclosure {
|
|
u8 sep_id; /* SEP device logical target id */
|
|
u8 sep_channel; /* SEP channel logical channel id */
|
|
};
|
|
-
|
|
+#if 0
|
|
+struct mptsas_broadcast_primative_event {
|
|
+ struct delayed_work aen_work;
|
|
+ MPT_ADAPTER *ioc;
|
|
+};
|
|
+#endif
|
|
/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
#endif
|
|
+
|
|
--- a/drivers/message/fusion/mptscsih.c
|
|
+++ b/drivers/message/fusion/mptscsih.c
|
|
@@ -53,7 +53,9 @@
|
|
#include <linux/delay.h> /* for mdelay */
|
|
#include <linux/interrupt.h> /* needed for in_interrupt() proto */
|
|
#include <linux/reboot.h> /* notifier code */
|
|
+#include <linux/sched.h>
|
|
#include <linux/workqueue.h>
|
|
+#include <linux/pci.h>
|
|
|
|
#include <scsi/scsi.h>
|
|
#include <scsi/scsi_cmnd.h>
|
|
@@ -77,10 +79,15 @@ MODULE_LICENSE("GPL");
|
|
MODULE_VERSION(my_VERSION);
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
+typedef struct _BIG_SENSE_BUF {
|
|
+ u8 data[MPT_SENSE_BUFFER_ALLOC];
|
|
+} BIG_SENSE_BUF;
|
|
+
|
|
+
|
|
/*
|
|
* Other private/forward protos...
|
|
*/
|
|
-struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
|
|
+struct scsi_cmnd * mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
|
|
static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i);
|
|
static void mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd);
|
|
static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd);
|
|
@@ -93,32 +100,20 @@ static int mptscsih_AddSGE(MPT_ADAPTER *
|
|
static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
|
|
static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
|
|
|
|
-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_synchronize_cache(struct scsi_device *sdev, MPT_SCSI_HOST *hd, VirtDevice *vdevice);
|
|
|
|
-void
|
|
-mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code);
|
|
-static int mptscsih_get_completion_code(MPT_ADAPTER *ioc,
|
|
- MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
|
|
-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);
|
|
-
|
|
-static int
|
|
-mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type,
|
|
- SCSITaskMgmtReply_t *pScsiTmReply);
|
|
-void mptscsih_remove(struct pci_dev *);
|
|
-void mptscsih_shutdown(struct pci_dev *);
|
|
+void mptscsih_remove(struct pci_dev *);
|
|
+void mptscsih_shutdown(struct pci_dev *);
|
|
#ifdef CONFIG_PM
|
|
-int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
|
|
-int mptscsih_resume(struct pci_dev *pdev);
|
|
+int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
|
|
+int mptscsih_resume(struct pci_dev *pdev);
|
|
#endif
|
|
-
|
|
-#define SNS_LEN(scp) SCSI_SENSE_BUFFERSIZE
|
|
-
|
|
+static int mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type,
|
|
+ SCSITaskMgmtReply_t *pScsiTmReply);
|
|
+static int mptscsih_get_completion_code(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
|
|
+ MPT_FRAME_HDR *reply);
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/*
|
|
@@ -178,7 +173,7 @@ static int
|
|
mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
|
|
SCSIIORequest_t *pReq, int req_idx)
|
|
{
|
|
- char *psge;
|
|
+ char *psge;
|
|
char *chainSge;
|
|
struct scatterlist *sg;
|
|
int frm_sz;
|
|
@@ -193,16 +188,29 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct
|
|
dma_addr_t v2;
|
|
u32 RequestNB;
|
|
|
|
- sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
|
|
+#ifdef EEDP_SUPPORT
|
|
+ if (pReq->Function == MPI_FUNCTION_SCSI_IO_32) {
|
|
+ SCSIIO32Request_t *mpi_request = (SCSIIO32Request_t *)pReq;
|
|
+
|
|
+ sgdir = le32_to_cpu(mpi_request->Control)
|
|
+ & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
|
|
+ psge = (char *) &mpi_request->SGL;
|
|
+ } else {
|
|
+#endif
|
|
+ sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
|
|
+ psge = (char *) &pReq->SGL;
|
|
+#ifdef EEDP_SUPPORT
|
|
+ }
|
|
+#endif
|
|
if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
|
|
sgdir = MPT_TRANSFER_HOST_TO_IOC;
|
|
} else {
|
|
sgdir = MPT_TRANSFER_IOC_TO_HOST;
|
|
}
|
|
|
|
- psge = (char *) &pReq->SGL;
|
|
frm_sz = ioc->req_sz;
|
|
|
|
+
|
|
/* Map the data portion, if any.
|
|
* sges_left = 0 if no data transfer.
|
|
*/
|
|
@@ -214,7 +222,7 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct
|
|
*/
|
|
sg = scsi_sglist(SCpnt);
|
|
sg_done = 0;
|
|
- sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
|
|
+ sgeOffset = psge - (char *) pReq;
|
|
chainSge = NULL;
|
|
|
|
/* Prior to entering this loop - the following must be set
|
|
@@ -237,7 +245,7 @@ nextSGEset:
|
|
thisxfer = sg_dma_len(sg);
|
|
if (thisxfer == 0) {
|
|
/* Get next SG element from the OS */
|
|
- sg = sg_next(sg);
|
|
+ sg = mpt_sg_next(sg);
|
|
sg_done++;
|
|
continue;
|
|
}
|
|
@@ -246,7 +254,7 @@ nextSGEset:
|
|
ioc->add_sge(psge, sgflags | thisxfer, v2);
|
|
|
|
/* Get next SG element from the OS */
|
|
- sg = sg_next(sg);
|
|
+ sg = mpt_sg_next(sg);
|
|
psge += ioc->SGE_size;
|
|
sgeOffset += ioc->SGE_size;
|
|
sg_done++;
|
|
@@ -346,7 +354,7 @@ nextSGEset:
|
|
if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
|
|
dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
"getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
|
|
- ioc->name, pReq->CDB[0], SCpnt));
|
|
+ ioc->name, pReq->CDB[0], SCpnt));
|
|
return FAILED;
|
|
}
|
|
|
|
@@ -392,7 +400,7 @@ mptscsih_issue_sep_command(MPT_ADAPTER *
|
|
U32 SlotStatus)
|
|
{
|
|
MPT_FRAME_HDR *mf;
|
|
- SEPRequest_t *SEPMsg;
|
|
+ SEPRequest_t *SEPMsg;
|
|
|
|
if (ioc->bus_type != SAS)
|
|
return;
|
|
@@ -598,14 +606,16 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
|
|
req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
|
|
req_idx_MR = (mr != NULL) ?
|
|
le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
|
|
-
|
|
- /* Special case, where already freed message frame is received from
|
|
- * Firmware. It happens with Resetting IOC.
|
|
- * Return immediately. Do not care
|
|
- */
|
|
if ((req_idx != req_idx_MR) ||
|
|
- (le32_to_cpu(mf->u.frame.linkage.arg1) == 0xdeadbeaf))
|
|
+ (le32_to_cpu(mf->u.frame.linkage.arg1) == 0xdeadbeaf)) {
|
|
+ printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
|
|
+ ioc->name);
|
|
+ printk (MYIOC_s_ERR_FMT
|
|
+ "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
|
|
+ ioc->name, req_idx, req_idx_MR, mf, mr,
|
|
+ mptscsih_get_scsi_lookup(ioc, req_idx_MR));
|
|
return 0;
|
|
+ }
|
|
|
|
sc = mptscsih_getclear_scsi_lookup(ioc, req_idx);
|
|
if (sc == NULL) {
|
|
@@ -658,6 +668,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
|
|
;
|
|
} else {
|
|
u32 xfer_cnt;
|
|
+ u32 difftransfer;
|
|
u16 status;
|
|
u8 scsi_state, scsi_status;
|
|
u32 log_info;
|
|
@@ -668,6 +679,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
|
|
xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
|
|
scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
|
|
log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
|
|
+ vdevice = sc->device->hostdata;
|
|
|
|
/*
|
|
* if we get a data underrun indication, yet no data was
|
|
@@ -685,18 +697,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
|
|
if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
|
|
mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
|
|
|
|
- /*
|
|
- * Look for + dump FCP ResponseInfo[]!
|
|
- */
|
|
- if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
|
|
- pScsiReply->ResponseInfo) {
|
|
- printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] "
|
|
- "FCP_ResponseInfo=%08xh\n", ioc->name,
|
|
- sc->device->host->host_no, sc->device->channel,
|
|
- sc->device->id, sc->device->lun,
|
|
- le32_to_cpu(pScsiReply->ResponseInfo));
|
|
- }
|
|
-
|
|
switch(status) {
|
|
case MPI_IOCSTATUS_BUSY: /* 0x0002 */
|
|
case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
|
|
@@ -724,7 +724,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
|
|
if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
|
|
hd->sel_timeout[pScsiReq->TargetID]++;
|
|
|
|
- vdevice = sc->device->hostdata;
|
|
if (!vdevice)
|
|
break;
|
|
vtarget = vdevice->vtarget;
|
|
@@ -769,7 +768,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
|
|
sc->result = DID_RESET << 16;
|
|
|
|
case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
|
|
- if (ioc->bus_type == FC)
|
|
+ if ( ioc->bus_type == FC )
|
|
sc->result = DID_ERROR << 16;
|
|
else
|
|
sc->result = DID_RESET << 16;
|
|
@@ -830,7 +829,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
|
|
}
|
|
if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
|
|
/* What to do?
|
|
- */
|
|
+ */
|
|
sc->result = DID_SOFT_ERROR << 16;
|
|
}
|
|
else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
|
|
@@ -923,7 +922,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
|
|
|
|
}
|
|
else if (scsi_state &
|
|
- (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
|
|
+ (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
|
|
) {
|
|
/*
|
|
* What to do?
|
|
@@ -954,6 +953,13 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
|
|
case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
|
|
sc->result = DID_SOFT_ERROR << 16;
|
|
break;
|
|
+#ifdef EEDP_SUPPORT
|
|
+ case MPI_IOCSTATUS_EEDP_GUARD_ERROR:
|
|
+ case MPI_IOCSTATUS_EEDP_REF_TAG_ERROR:
|
|
+ case MPI_IOCSTATUS_EEDP_APP_TAG_ERROR:
|
|
+ sc->result = DID_PARITY << 16;
|
|
+ break;
|
|
+#endif /* EEDP Support */
|
|
|
|
case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
|
|
case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
|
|
@@ -1143,8 +1149,8 @@ mptscsih_report_queue_full(struct scsi_c
|
|
void
|
|
mptscsih_remove(struct pci_dev *pdev)
|
|
{
|
|
- MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
|
- struct Scsi_Host *host = ioc->sh;
|
|
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
|
+ struct Scsi_Host *host = ioc->sh;
|
|
MPT_SCSI_HOST *hd;
|
|
int sz1;
|
|
|
|
@@ -1204,7 +1210,7 @@ mptscsih_shutdown(struct pci_dev *pdev)
|
|
int
|
|
mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
{
|
|
- MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
|
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
|
|
|
scsi_block_requests(ioc->sh);
|
|
flush_scheduled_work();
|
|
@@ -1221,7 +1227,7 @@ mptscsih_suspend(struct pci_dev *pdev, p
|
|
int
|
|
mptscsih_resume(struct pci_dev *pdev)
|
|
{
|
|
- MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
|
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
|
|
int rc;
|
|
|
|
rc = mpt_resume(pdev);
|
|
@@ -1280,13 +1286,13 @@ mptscsih_copy_mem_info(struct info_str *
|
|
}
|
|
|
|
if (info->pos < info->offset) {
|
|
- data += (info->offset - info->pos);
|
|
- len -= (info->offset - info->pos);
|
|
+ data += (info->offset - info->pos);
|
|
+ len -= (info->offset - info->pos);
|
|
}
|
|
|
|
if (len > 0) {
|
|
- memcpy(info->buffer + info->pos, data, len);
|
|
- info->pos += len;
|
|
+ memcpy(info->buffer + info->pos, data, len);
|
|
+ info->pos += len;
|
|
}
|
|
}
|
|
|
|
@@ -1326,12 +1332,12 @@ mptscsih_host_info(MPT_ADAPTER *ioc, cha
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/**
|
|
* mptscsih_proc_info - Return information about MPT adapter
|
|
- * @host: scsi host struct
|
|
- * @buffer: if write, user data; if read, buffer for user
|
|
+ * @host: scsi host struct
|
|
+ * @buffer: if write, user data; if read, buffer for user
|
|
* @start: returns the buffer address
|
|
- * @offset: if write, 0; if read, the current offset into the buffer from
|
|
- * the previous read.
|
|
- * @length: if write, return length;
|
|
+ * @offset: if write, 0; if read, the current offset into the buffer from
|
|
+ * the previous read.
|
|
+ * @length: if write, return length;
|
|
* @func: write = 1; read = 0
|
|
*
|
|
* (linux scsi_host_template.info routine)
|
|
@@ -1358,6 +1364,103 @@ mptscsih_proc_info(struct Scsi_Host *hos
|
|
return size;
|
|
}
|
|
|
|
+#ifdef EEDP_SUPPORT
|
|
+u8 opcode_protection[256] = {
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, PRO_W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V,
|
|
+ 0, 0, 0, PRO_W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
+
|
|
+/**
|
|
+ * _scsih_setup_eedp - setup MPI request for EEDP transfer
|
|
+ * @ioc:
|
|
+ * @scmd: pointer to scsi command object
|
|
+ * @mpi_request: pointer to the SCSI_IO reqest message frame
|
|
+ *
|
|
+ * Supporting protection 1 only.
|
|
+ *
|
|
+ * Returns nothing
|
|
+ */
|
|
+static int
|
|
+_scsih_setup_eedp(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd, SCSIIO32Request_t *mpi_request)
|
|
+{
|
|
+ VirtDevice *vdevice = scmd->device->hostdata;
|
|
+ u16 eedp_flags;
|
|
+ u8 scsi_opcode;
|
|
+ int lba_byte;
|
|
+ u32 *lba32;
|
|
+
|
|
+ vdevice = scmd->device->hostdata;
|
|
+ if (!vdevice->eedp_enable)
|
|
+ return -1;
|
|
+
|
|
+ /* protection type 1 support only */
|
|
+ if (vdevice->eedp_type != 0)
|
|
+ return -1;
|
|
+
|
|
+ /* check whether scsi opcode supports eedp transfer */
|
|
+ scsi_opcode = scmd->cmnd[0];
|
|
+ eedp_flags = opcode_protection[scsi_opcode];
|
|
+ if (!eedp_flags)
|
|
+ return -1;
|
|
+
|
|
+ /*
|
|
+ * enable ref/app/guard checking
|
|
+ * auto increment ref and app tag
|
|
+ */
|
|
+ mpi_request->EEDPFlags = eedp_flags |
|
|
+ MPI_SCSIIO32_EEDPFLAGS_INC_PRI_REFTAG |
|
|
+ MPI_SCSIIO32_EEDPFLAGS_T10_CHK_REFTAG |
|
|
+ MPI_SCSIIO32_EEDPFLAGS_T10_CHK_LBATAG |
|
|
+ MPI_SCSIIO32_EEDPFLAGS_T10_CHK_GUARD;
|
|
+
|
|
+ /* set block size */
|
|
+ mpi_request->EEDPBlockSize = vdevice->eedp_block_length;
|
|
+ mpi_request->EEDPBlockSize += 8;
|
|
+ memset(mpi_request->CDB.CDB32, 0, 32);
|
|
+
|
|
+ mpi_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xFFFF;
|
|
+
|
|
+ /* set reference tag to low 32bit lba */
|
|
+ lba_byte = (scmd->cmd_len == 16) ? 6 : 2;
|
|
+ lba32 = (u32 *)&scmd->cmnd[lba_byte];
|
|
+ mpi_request->CDB.EEDP32.PrimaryReferenceTag = *lba32;
|
|
+
|
|
+ /* set RDPROTECT, WRPROTECT, VRPROTECT bits to (001b) */
|
|
+ scmd->cmnd[1] = (scmd->cmnd[1] & 0x1F) | 0x20;
|
|
+
|
|
+ /* add the rest of the bits */
|
|
+ mpi_request->Port = 0;
|
|
+ mpi_request->Flags = MPI_SCSIIO32_FLAGS_FORM_SCSIID;
|
|
+ mpi_request->DeviceAddress.SCSIID.TargetID = vdevice->vtarget->id;
|
|
+ mpi_request->DeviceAddress.SCSIID.Bus = vdevice->vtarget->channel;
|
|
+ mpi_request->ChainOffset = 0;
|
|
+ mpi_request->Function = MPI_FUNCTION_SCSI_IO_32;
|
|
+ mpi_request->CDBLength = scmd->cmd_len;
|
|
+ mpi_request->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
|
|
+ mpi_request->MsgFlags = mpt_msg_flags(ioc);
|
|
+ int_to_scsilun(scmd->device->lun, (struct scsi_lun *)mpi_request->LUN);
|
|
+ memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
|
|
+ mpi_request->SGLOffset0 = offsetof(SCSIIO32Request_t, SGL) / 4;
|
|
+ mpi_request->SGLOffset1 = 0;
|
|
+ mpi_request->SGLOffset2 = 0;
|
|
+ mpi_request->SGLOffset3 = 0;
|
|
+ return 0;
|
|
+}
|
|
+#endif /* EEDP Support */
|
|
+
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
#define ADD_INDEX_LOG(req_ent) do { } while(0)
|
|
|
|
@@ -1444,6 +1547,36 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
|
|
|
|
/* Use the above information to set up the message frame
|
|
*/
|
|
+#ifdef EEDP_SUPPORT
|
|
+ if (_scsih_setup_eedp(ioc, SCpnt, (SCSIIO32Request_t *)mf) == 0) {
|
|
+ SCSIIO32Request_t *mpi_request = (SCSIIO32Request_t *)mf;
|
|
+
|
|
+ /* finish off setting the rest of the SCSIIO32 */
|
|
+ mpi_request->Control = cpu_to_le32(scsictl);
|
|
+ mpi_request->DataLength = cpu_to_le32(datalen);
|
|
+
|
|
+ /* SenseBuffer low address */
|
|
+ mpi_request->SenseBufferLowAddr =
|
|
+ cpu_to_le32(ioc->sense_buf_low_dma
|
|
+ + (my_idx * MPT_SENSE_BUFFER_ALLOC));
|
|
+
|
|
+ /* Now add the SG list
|
|
+ * Always have a SGE even if null length.
|
|
+ */
|
|
+ if (datalen == 0) {
|
|
+ /* Add a NULL SGE */
|
|
+ ioc->add_sge((char *)&mpi_request->SGL,
|
|
+ MPT_SGE_FLAGS_SSIMPLE_READ | 0,
|
|
+ (dma_addr_t) -1);
|
|
+ } else {
|
|
+ /* Add a 32 or 64 bit SGE */
|
|
+ if (mptscsih_AddSGE(ioc, SCpnt,
|
|
+ pScsiReq, my_idx) != SUCCESS)
|
|
+ goto fail;
|
|
+ }
|
|
+ goto send_mf;
|
|
+ }
|
|
+#endif
|
|
pScsiReq->TargetID = (u8) vdevice->vtarget->id;
|
|
pScsiReq->Bus = vdevice->vtarget->channel;
|
|
pScsiReq->ChainOffset = 0;
|
|
@@ -1489,6 +1622,9 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v
|
|
goto fail;
|
|
}
|
|
|
|
+#ifdef EEDP_SUPPORT
|
|
+ send_mf:
|
|
+#endif
|
|
SCpnt->host_scribble = (unsigned char *)mf;
|
|
mptscsih_set_scsi_lookup(ioc, my_idx, SCpnt);
|
|
|
|
@@ -1560,6 +1696,137 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *i
|
|
*/
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
+
|
|
+static int
|
|
+mptscsih_scandv_bus_reset(MPT_ADAPTER *ioc)
|
|
+{
|
|
+ MPT_FRAME_HDR *mf;
|
|
+ SCSITaskMgmt_t *pScsiTm;
|
|
+ SCSITaskMgmtReply_t *pScsiTmReply;
|
|
+ int ii;
|
|
+ int retval;
|
|
+ unsigned long timeout;
|
|
+ unsigned long time_count;
|
|
+ u16 iocstatus;
|
|
+
|
|
+ mutex_lock(&ioc->taskmgmt_cmds.mutex);
|
|
+ if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
|
|
+ mutex_unlock(&ioc->taskmgmt_cmds.mutex);
|
|
+ return -EPERM;
|
|
+ }
|
|
+
|
|
+ /* Send request
|
|
+ */
|
|
+ if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
|
|
+ dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt, no msg frames!!\n",
|
|
+ ioc->name));
|
|
+ mpt_clear_taskmgmt_in_progress_flag(ioc);
|
|
+ retval = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
|
|
+ ioc->name, mf));
|
|
+
|
|
+ pScsiTm = (SCSITaskMgmt_t *) mf;
|
|
+ memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
|
|
+ pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
|
|
+ pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
|
|
+ pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
|
|
+ pScsiTm->TargetID = 0;
|
|
+ pScsiTm->Bus = 0;
|
|
+ pScsiTm->ChainOffset = 0;
|
|
+ pScsiTm->Reserved = 0;
|
|
+ pScsiTm->Reserved1 = 0;
|
|
+ pScsiTm->TaskMsgContext = 0;
|
|
+ for (ii= 0; ii < 8; ii++)
|
|
+ pScsiTm->LUN[ii] = 0;
|
|
+ for (ii=0; ii < 7; ii++)
|
|
+ pScsiTm->Reserved2[ii] = 0;
|
|
+
|
|
+ switch (ioc->bus_type) {
|
|
+ case FC:
|
|
+ timeout = 40;
|
|
+ break;
|
|
+ case SAS:
|
|
+ timeout = 30;
|
|
+ break;
|
|
+ case SPI:
|
|
+ default:
|
|
+ timeout = 2;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt type=%d timeout=%ld\n",
|
|
+ ioc->name, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, timeout));
|
|
+
|
|
+ INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
|
|
+ CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
|
|
+ retval = 0;
|
|
+ time_count = jiffies;
|
|
+ if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
|
|
+ (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
|
|
+ mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
|
|
+ else {
|
|
+ retval = mpt_send_handshake_request(ioc->TaskCtx, ioc,
|
|
+ sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
|
|
+ if (retval != 0) {
|
|
+ dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "TaskMgmt send_handshake FAILED!"
|
|
+ " (ioc %p, mf %p, rc=%d) \n", ioc->name,
|
|
+ ioc, mf, retval));
|
|
+ mpt_clear_taskmgmt_in_progress_flag(ioc);
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Now wait for the command to complete */
|
|
+ ii = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ);
|
|
+ if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
+ "TaskMgmt failed\n", ioc->name));
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ mpt_clear_taskmgmt_in_progress_flag(ioc);
|
|
+ retval = -1; /* return failure */
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
+ "TaskMgmt failed\n", ioc->name));
|
|
+ retval = -1; /* return failure */
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
+ "TaskMgmt fw_channel = %d, fw_id = %d, task_type = 0x%02X,\n"
|
|
+ "\tiocstatus = 0x%04X, loginfo = 0x%08X, response_code = 0x%02X,\n"
|
|
+ "\tterm_cmnds = %d\n", ioc->name, pScsiTmReply->Bus,
|
|
+ pScsiTmReply->TargetID, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
|
|
+ le16_to_cpu(pScsiTmReply->IOCStatus),
|
|
+ le32_to_cpu(pScsiTmReply->IOCLogInfo),
|
|
+ pScsiTmReply->ResponseCode,
|
|
+ le32_to_cpu(pScsiTmReply->TerminationCount)));
|
|
+
|
|
+ iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
|
|
+
|
|
+ if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
|
|
+ iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED ||
|
|
+ iocstatus == MPI_IOCSTATUS_SUCCESS)
|
|
+ retval = 0;
|
|
+ else {
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
+ "TaskMgmt failed\n", ioc->name));
|
|
+ retval = -1; /* return failure */
|
|
+ }
|
|
+
|
|
+ out:
|
|
+ mutex_unlock(&ioc->taskmgmt_cmds.mutex);
|
|
+ CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/**
|
|
* mptscsih_IssueTaskMgmt - Generic send Task Management function.
|
|
* @hd: Pointer to MPT_SCSI_HOST structure
|
|
@@ -1579,14 +1846,13 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *i
|
|
*
|
|
**/
|
|
int
|
|
-mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int 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;
|
|
int ii;
|
|
int retval;
|
|
- MPT_ADAPTER *ioc = hd->ioc;
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
unsigned long timeleft;
|
|
u8 issue_hard_reset;
|
|
u32 ioc_raw_state;
|
|
@@ -1646,7 +1912,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd
|
|
pScsiTm->TaskType = type;
|
|
pScsiTm->Reserved1 = 0;
|
|
pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
|
|
- ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
|
|
+ ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
|
|
|
|
int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
|
|
|
|
@@ -1705,7 +1971,8 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd
|
|
if (issue_hard_reset) {
|
|
printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
|
|
ioc->name, __func__);
|
|
- retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
+ if ((retval = mpt_SoftResetHandler(ioc, CAN_SLEEP)) != 0)
|
|
+ retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
mpt_free_msg_frame(ioc, mf);
|
|
}
|
|
|
|
@@ -1713,7 +1980,6 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd
|
|
mutex_unlock(&ioc->taskmgmt_cmds.mutex);
|
|
return retval;
|
|
}
|
|
-EXPORT_SYMBOL(mptscsih_IssueTaskMgmt);
|
|
|
|
static int
|
|
mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
|
|
@@ -1722,6 +1988,7 @@ mptscsih_get_tm_timeout(MPT_ADAPTER *ioc
|
|
case FC:
|
|
return 40;
|
|
case SAS:
|
|
+ return 30;
|
|
case SPI:
|
|
default:
|
|
return 10;
|
|
@@ -1746,7 +2013,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
|
|
int scpnt_idx;
|
|
int retval;
|
|
VirtDevice *vdevice;
|
|
- ulong sn = SCpnt->serial_number;
|
|
+ ulong sn = SCpnt->serial_number;
|
|
MPT_ADAPTER *ioc;
|
|
|
|
/* If we can't locate our host adapter structure, return FAILED status.
|
|
@@ -1771,7 +2038,21 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
|
|
ioc->name, SCpnt));
|
|
SCpnt->result = DID_NO_CONNECT << 16;
|
|
SCpnt->scsi_done(SCpnt);
|
|
- retval = 0;
|
|
+ retval = SUCCESS;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /* Find this command
|
|
+ */
|
|
+ if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) {
|
|
+ /* Cmd not found in ScsiLookup.
|
|
+ * Do OS callback.
|
|
+ */
|
|
+ SCpnt->result = DID_RESET << 16;
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
+ "task abort: command not in the active list! (sc=%p)\n",
|
|
+ ioc->name, SCpnt));
|
|
+ retval = SUCCESS;
|
|
goto out;
|
|
}
|
|
|
|
@@ -1786,25 +2067,23 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
|
|
goto out;
|
|
}
|
|
|
|
- /* Find this command
|
|
+ /* Task aborts are not supported for volumes.
|
|
*/
|
|
- if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) {
|
|
- /* Cmd not found in ScsiLookup.
|
|
- * Do OS callback.
|
|
- */
|
|
+ if (vdevice->vtarget->raidVolume) {
|
|
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
+ "task abort: raid volume (sc=%p)\n",
|
|
+ ioc->name, SCpnt));
|
|
SCpnt->result = DID_RESET << 16;
|
|
- dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: "
|
|
- "Command not in the active list! (sc=%p)\n", ioc->name,
|
|
- SCpnt));
|
|
- retval = SUCCESS;
|
|
+ retval = FAILED;
|
|
goto out;
|
|
}
|
|
|
|
+ if (mpt_fwfault_debug)
|
|
+ mpt_halt_firmware(ioc);
|
|
+
|
|
if (ioc->timeouts < -1)
|
|
ioc->timeouts++;
|
|
|
|
- if (mpt_fwfault_debug)
|
|
- mpt_halt_firmware(ioc);
|
|
|
|
/* Most important! Set TaskMsgContext to SCpnt's MsgContext!
|
|
* (the IO to be ABORT'd)
|
|
@@ -1821,6 +2100,10 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
|
|
vdevice->vtarget->id, vdevice->lun,
|
|
ctx2abort, mptscsih_get_tm_timeout(ioc));
|
|
|
|
+
|
|
+ /* check to see whether command actually completed and/or
|
|
+ * terminated
|
|
+ */
|
|
if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx &&
|
|
SCpnt->serial_number == sn) {
|
|
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
@@ -1836,7 +2119,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
|
|
|
|
out:
|
|
printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
|
|
- ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), SCpnt);
|
|
+ ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED" ), SCpnt);
|
|
|
|
return retval;
|
|
}
|
|
@@ -1964,7 +2247,7 @@ int
|
|
mptscsih_host_reset(struct scsi_cmnd *SCpnt)
|
|
{
|
|
MPT_SCSI_HOST * hd;
|
|
- int status = SUCCESS;
|
|
+ int status = SUCCESS;
|
|
MPT_ADAPTER *ioc;
|
|
int retval;
|
|
|
|
@@ -1975,9 +2258,6 @@ mptscsih_host_reset(struct scsi_cmnd *SC
|
|
return FAILED;
|
|
}
|
|
|
|
- /* make sure we have no outstanding commands at this stage */
|
|
- mptscsih_flush_running_cmds(hd);
|
|
-
|
|
ioc = hd->ioc;
|
|
printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n",
|
|
ioc->name, SCpnt);
|
|
@@ -1985,7 +2265,9 @@ mptscsih_host_reset(struct scsi_cmnd *SC
|
|
/* If our attempts to reset the host failed, then return a failed
|
|
* status. The host will be taken off line by the SCSI mid-layer.
|
|
*/
|
|
- retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
+ if ((retval = mpt_SoftResetHandler(ioc, CAN_SLEEP)) != 0)
|
|
+ retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
+
|
|
if (retval < 0)
|
|
status = FAILED;
|
|
else
|
|
@@ -1997,6 +2279,7 @@ mptscsih_host_reset(struct scsi_cmnd *SC
|
|
return status;
|
|
}
|
|
|
|
+
|
|
static int
|
|
mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type,
|
|
SCSITaskMgmtReply_t *pScsiTmReply)
|
|
@@ -2083,7 +2366,6 @@ mptscsih_taskmgmt_response_code(MPT_ADAP
|
|
printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
|
|
ioc->name, response_code, desc);
|
|
}
|
|
-EXPORT_SYMBOL(mptscsih_taskmgmt_response_code);
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/**
|
|
@@ -2119,6 +2401,8 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *
|
|
mpt_clear_taskmgmt_in_progress_flag(ioc);
|
|
ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
|
|
complete(&ioc->taskmgmt_cmds.done);
|
|
+ if (ioc->bus_type == SAS)
|
|
+ ioc->schedule_target_reset(ioc);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
@@ -2135,7 +2419,7 @@ mptscsih_bios_param(struct scsi_device *
|
|
int heads;
|
|
int sectors;
|
|
sector_t cylinders;
|
|
- ulong dummy;
|
|
+ ulong dummy;
|
|
|
|
heads = 64;
|
|
sectors = 32;
|
|
@@ -2164,14 +2448,15 @@ mptscsih_bios_param(struct scsi_device *
|
|
return 0;
|
|
}
|
|
|
|
-/* Search IOC page 3 to determine if this is hidden physical disk
|
|
+/**
|
|
+ * Search IOC page 3 to determine if this is hidden physical disk
|
|
*
|
|
*/
|
|
int
|
|
mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
|
|
{
|
|
struct inactive_raid_component_info *component_info;
|
|
- int i, j;
|
|
+ u8 i, j;
|
|
RaidPhysDiskPage1_t *phys_disk;
|
|
int rc = 0;
|
|
int num_paths;
|
|
@@ -2197,7 +2482,7 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc,
|
|
ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum);
|
|
if (num_paths < 2)
|
|
continue;
|
|
- phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
|
|
+ phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t,Path) +
|
|
(num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
|
|
if (!phys_disk)
|
|
continue;
|
|
@@ -2224,21 +2509,20 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc,
|
|
kfree(phys_disk);
|
|
}
|
|
|
|
-
|
|
/*
|
|
* Check inactive list for matching phys disks
|
|
*/
|
|
if (list_empty(&ioc->raid_data.inactive_list))
|
|
goto out;
|
|
|
|
- mutex_lock(&ioc->raid_data.inactive_list_mutex);
|
|
+ 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;
|
|
}
|
|
- mutex_unlock(&ioc->raid_data.inactive_list_mutex);
|
|
+ up(&ioc->raid_data.inactive_list_mutex);
|
|
|
|
out:
|
|
return rc;
|
|
@@ -2249,10 +2533,10 @@ u8
|
|
mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
|
|
{
|
|
struct inactive_raid_component_info *component_info;
|
|
- int i, j;
|
|
+ int i,j;
|
|
RaidPhysDiskPage1_t *phys_disk;
|
|
int rc = -ENXIO;
|
|
- int num_paths;
|
|
+ u8 num_paths;
|
|
|
|
if (!ioc->raid_data.pIocPg3)
|
|
goto out;
|
|
@@ -2275,7 +2559,7 @@ mptscsih_raid_id_to_num(MPT_ADAPTER *ioc
|
|
ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum);
|
|
if (num_paths < 2)
|
|
continue;
|
|
- phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
|
|
+ phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t,Path) +
|
|
(num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
|
|
if (!phys_disk)
|
|
continue;
|
|
@@ -2308,14 +2592,14 @@ mptscsih_raid_id_to_num(MPT_ADAPTER *ioc
|
|
if (list_empty(&ioc->raid_data.inactive_list))
|
|
goto out;
|
|
|
|
- mutex_lock(&ioc->raid_data.inactive_list_mutex);
|
|
+ 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;
|
|
}
|
|
- mutex_unlock(&ioc->raid_data.inactive_list_mutex);
|
|
+ up(&ioc->raid_data.inactive_list_mutex);
|
|
|
|
out:
|
|
return rc;
|
|
@@ -2333,15 +2617,17 @@ mptscsih_slave_destroy(struct scsi_devic
|
|
MPT_SCSI_HOST *hd = shost_priv(host);
|
|
VirtTarget *vtarget;
|
|
VirtDevice *vdevice;
|
|
- struct scsi_target *starget;
|
|
+ struct scsi_target *starget;
|
|
|
|
starget = scsi_target(sdev);
|
|
vtarget = starget->hostdata;
|
|
+ vtarget->num_luns--;
|
|
vdevice = sdev->hostdata;
|
|
+ if (!vdevice)
|
|
+ return;
|
|
|
|
mptscsih_search_running_cmds(hd, vdevice);
|
|
- vtarget->num_luns--;
|
|
- mptscsih_synchronize_cache(hd, vdevice);
|
|
+ mptscsih_synchronize_cache(sdev, hd, vdevice);
|
|
kfree(vdevice);
|
|
sdev->hostdata = NULL;
|
|
}
|
|
@@ -2359,8 +2645,8 @@ int
|
|
mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
|
|
{
|
|
MPT_SCSI_HOST *hd = shost_priv(sdev->host);
|
|
- VirtTarget *vtarget;
|
|
- struct scsi_target *starget;
|
|
+ VirtTarget *vtarget;
|
|
+ struct scsi_target *starget;
|
|
int max_depth;
|
|
int tagged;
|
|
MPT_ADAPTER *ioc = hd->ioc;
|
|
@@ -2372,15 +2658,13 @@ mptscsih_change_queue_depth(struct scsi_
|
|
return -EOPNOTSUPP;
|
|
|
|
if (ioc->bus_type == SPI) {
|
|
- if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
|
|
- max_depth = 1;
|
|
- else if (sdev->type == TYPE_DISK &&
|
|
- vtarget->minSyncFactor <= MPT_ULTRA160)
|
|
+ if (sdev->type == TYPE_DISK &&
|
|
+ vtarget->minSyncFactor <= MPT_ULTRA160)
|
|
max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
|
|
else
|
|
max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
|
|
} else
|
|
- max_depth = ioc->sh->can_queue;
|
|
+ max_depth = ioc->sh->can_queue;
|
|
|
|
if (!sdev->tagged_supported)
|
|
max_depth = 1;
|
|
@@ -2393,9 +2677,120 @@ mptscsih_change_queue_depth(struct scsi_
|
|
tagged = MSG_SIMPLE_TAG;
|
|
|
|
scsi_adjust_queue_depth(sdev, tagged, qdepth);
|
|
+
|
|
+ if (sdev->inquiry_len > 7)
|
|
+ sdev_printk(KERN_INFO, sdev, MYIOC_s_FMT "qdepth=%d, "
|
|
+ "tagged=%d, simple=%d, ordered=%d, scsi_level=%d, "
|
|
+ "cmd_que=%d\n", ioc->name, sdev->queue_depth,
|
|
+ sdev->tagged_supported, sdev->simple_tags,
|
|
+ sdev->ordered_tags, sdev->scsi_level,
|
|
+ (sdev->inquiry[7] & 2) >> 1);
|
|
+
|
|
return sdev->queue_depth;
|
|
}
|
|
|
|
+#ifdef EEDP_SUPPORT
|
|
+/**
|
|
+ * _scsih_read_capacity_16 - send READ_CAPACITY_16 to target
|
|
+ *
|
|
+ */
|
|
+static int
|
|
+_scsih_read_capacity_16(MPT_SCSI_HOST *hd, int id, int channel, u32 lun,
|
|
+ void *data, u32 length)
|
|
+{
|
|
+ INTERNAL_CMD iocmd;
|
|
+ dma_addr_t data_dma;
|
|
+ struct read_cap_parameter *parameter_data;
|
|
+ u32 data_length;
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
+ int rc;
|
|
+ int count;
|
|
+ u8 skey;
|
|
+ u8 asc;
|
|
+ u8 ascq;
|
|
+
|
|
+ data_length = sizeof(struct read_cap_parameter);
|
|
+ parameter_data = pci_alloc_consistent(ioc->pcidev,
|
|
+ data_length, &data_dma);
|
|
+ if (!parameter_data) {
|
|
+ printk(MYIOC_s_ERR_FMT "failure at %s:%d/%s()!\n",
|
|
+ ioc->name, __FILE__, __LINE__, __func__);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ iocmd.cmd = SERVICE_ACTION_IN;
|
|
+ iocmd.data_dma = data_dma;
|
|
+ iocmd.data = (u8 *)parameter_data;
|
|
+ iocmd.size = data_length;
|
|
+ iocmd.channel = channel;
|
|
+ iocmd.id = id;
|
|
+ iocmd.lun = lun;
|
|
+
|
|
+ for (count=0; count < 4; count++) {
|
|
+ rc = mptscsih_do_cmd(hd, &iocmd);
|
|
+
|
|
+ if(rc == MPT_SCANDV_GOOD) {
|
|
+ memcpy(data, parameter_data,
|
|
+ min_t(u32, data_length, length));
|
|
+ break;
|
|
+ } else if(rc == MPT_SCANDV_BUSY) {
|
|
+ devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: "
|
|
+ "fw_channel=%d fw_id=%d : device busy\n",
|
|
+ ioc->name, __FUNCTION__, channel, id));
|
|
+ continue;
|
|
+ } else if(rc == MPT_SCANDV_DID_RESET) {
|
|
+ devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: "
|
|
+ "fw_channel=%d fw_id=%d : did reset\n",
|
|
+ ioc->name, __FUNCTION__, channel, id));
|
|
+ continue;
|
|
+ } else if(rc == MPT_SCANDV_SENSE) {
|
|
+ skey = ioc->internal_cmds.sense[2] & 0x0F;
|
|
+ asc = ioc->internal_cmds.sense[12];
|
|
+ ascq = ioc->internal_cmds.sense[13];
|
|
+ devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: "
|
|
+ "fw_channel=%d fw_id=%d : [sense_key,arc,ascq]: "
|
|
+ "[0x%02x,0x%02x,0x%02x]\n", ioc->name,
|
|
+ __FUNCTION__, channel, id, skey, asc, ascq));
|
|
+ if( skey == UNIT_ATTENTION ||
|
|
+ skey == NOT_READY ||
|
|
+ skey == ILLEGAL_REQUEST ) {
|
|
+ continue;
|
|
+ } else {
|
|
+ printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d : "
|
|
+ "tur failed due to [sense_key,asc,ascq]: "
|
|
+ "[0x%02x,0x%02x,0x%02x]\n", ioc->name,
|
|
+ __FUNCTION__, channel, id, skey, asc, ascq);
|
|
+ break;
|
|
+ }
|
|
+ } else if(rc == MPT_SCANDV_SELECTION_TIMEOUT) {
|
|
+ printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d: "
|
|
+ "read capacity failed due to no device\n", ioc->name,
|
|
+ __FUNCTION__, channel, id);
|
|
+ break;
|
|
+ } else if(rc == MPT_SCANDV_SOME_ERROR) {
|
|
+ printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d: "
|
|
+ "read capacity failed due to some error\n", ioc->name,
|
|
+ __FUNCTION__, channel, id);
|
|
+ break;
|
|
+ } else {
|
|
+ printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d: "
|
|
+ "read capacity failed due to some error\n", ioc->name,
|
|
+ __FUNCTION__, channel, id);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if(count > 4 && rc != 0) {
|
|
+ printk(MYIOC_s_ERR_FMT "%s: fw_channel=%d fw_id=%d: "
|
|
+ "read capacity failed to many times\n", ioc->name,
|
|
+ __FUNCTION__, channel, id);
|
|
+ }
|
|
+
|
|
+ pci_free_consistent(ioc->pcidev, data_length, parameter_data, data_dma);
|
|
+ return rc;
|
|
+}
|
|
+#endif
|
|
+
|
|
/*
|
|
* OS entry point to adjust the queue_depths on a per-device basis.
|
|
* Called once per device the bus scan. Use it to force the queue_depth
|
|
@@ -2408,7 +2803,7 @@ mptscsih_slave_configure(struct scsi_dev
|
|
struct Scsi_Host *sh = sdev->host;
|
|
VirtTarget *vtarget;
|
|
VirtDevice *vdevice;
|
|
- struct scsi_target *starget;
|
|
+ struct scsi_target *starget;
|
|
MPT_SCSI_HOST *hd = shost_priv(sh);
|
|
MPT_ADAPTER *ioc = hd->ioc;
|
|
|
|
@@ -2416,6 +2811,45 @@ mptscsih_slave_configure(struct scsi_dev
|
|
vtarget = starget->hostdata;
|
|
vdevice = sdev->hostdata;
|
|
|
|
+#ifdef EEDP_SUPPORT
|
|
+ if ((!(vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)) &&
|
|
+ (!(vdevice->vtarget->raidVolume))) {
|
|
+
|
|
+ struct read_cap_parameter data;
|
|
+ memset(&data, 0, sizeof(struct read_cap_parameter));
|
|
+
|
|
+ /*
|
|
+ * check PROTECT bit
|
|
+ *
|
|
+ * NOTE: The crack monkey target mode driver doesn't
|
|
+ * set this bit(bug has been reported).
|
|
+ * The cm_target command line option is a work around.
|
|
+ */
|
|
+ if (!(sdev->inquiry[5] & 1))
|
|
+ goto out;
|
|
+
|
|
+ if ((ioc->bus_type == FC) &&
|
|
+ (_scsih_read_capacity_16(hd, vtarget->id,
|
|
+ vtarget->channel, sdev->lun, &data,
|
|
+ sizeof(struct read_cap_parameter)) == 0)) {
|
|
+ vdevice->eedp_enable = data.prot_en;
|
|
+ vdevice->eedp_type = data.p_type;
|
|
+ vdevice->eedp_block_length =
|
|
+ be32_to_cpu(data.logical_block_length);
|
|
+
|
|
+ if (!vdevice->eedp_enable)
|
|
+ goto out;
|
|
+
|
|
+ sdev_printk(KERN_INFO, sdev, "EEDP enabled: "
|
|
+ "protection_type(%d), block_length(%d)\n",
|
|
+ vdevice->eedp_type+1,
|
|
+ vdevice->eedp_block_length);
|
|
+ }
|
|
+ }
|
|
+ out:
|
|
+#endif /* EEDP Support */
|
|
+
|
|
+
|
|
dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
"device @ %p, channel=%d, id=%d, lun=%d\n",
|
|
ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
|
|
@@ -2427,6 +2861,11 @@ mptscsih_slave_configure(struct scsi_dev
|
|
|
|
vdevice->configured_lun = 1;
|
|
|
|
+ if ((ioc->bus_type != SAS) && (sdev->id > sh->max_id)) {
|
|
+ /* error case, should never happen */
|
|
+ scsi_adjust_queue_depth(sdev, 0, 1);
|
|
+ goto slave_configure_exit;
|
|
+ }
|
|
dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
"Queue depth=%d, tflags=%x\n",
|
|
ioc->name, sdev->queue_depth, vtarget->tflags));
|
|
@@ -2437,8 +2876,10 @@ mptscsih_slave_configure(struct scsi_dev
|
|
ioc->name, vtarget->negoFlags, vtarget->maxOffset,
|
|
vtarget->minSyncFactor));
|
|
|
|
- mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH,
|
|
+ mptscsih_change_queue_depth(sdev, ioc->sdev_queue_depth,
|
|
SCSI_QDEPTH_DEFAULT);
|
|
+
|
|
+slave_configure_exit:
|
|
dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
"tagged %d, simple %d, ordered %d\n",
|
|
ioc->name,sdev->tagged_supported, sdev->simple_tags,
|
|
@@ -2463,7 +2904,7 @@ mptscsih_copy_sense_data(struct scsi_cmn
|
|
VirtDevice *vdevice;
|
|
SCSIIORequest_t *pReq;
|
|
u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
|
|
- MPT_ADAPTER *ioc = hd->ioc;
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
|
|
/* Get target structure
|
|
*/
|
|
@@ -2477,8 +2918,11 @@ mptscsih_copy_sense_data(struct scsi_cmn
|
|
/* Copy the sense received into the scsi command block. */
|
|
req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
|
|
sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
|
|
- memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
|
|
|
|
+ if (sense_count > SCSI_SENSE_BUFFERSIZE)
|
|
+ sense_count = SCSI_SENSE_BUFFERSIZE;
|
|
+
|
|
+ memcpy(sc->sense_buffer, sense_data, sense_count);
|
|
/* Log SMART data (asc = 0x5D, non-IM case only) if required.
|
|
*/
|
|
if ((ioc->events) && (ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
|
|
@@ -2496,12 +2940,10 @@ mptscsih_copy_sense_data(struct scsi_cmn
|
|
ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
|
|
|
|
ioc->eventContext++;
|
|
- if (ioc->pcidev->vendor ==
|
|
- PCI_VENDOR_ID_IBM) {
|
|
- mptscsih_issue_sep_command(ioc,
|
|
- vdevice->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
|
|
- vdevice->vtarget->tflags |=
|
|
- MPT_TARGET_FLAGS_LED_ON;
|
|
+ if (ioc->pcidev->vendor == PCI_VENDOR_ID_IBM) {
|
|
+ mptscsih_issue_sep_command(ioc, vdevice->vtarget,
|
|
+ MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
|
|
+ vdevice->vtarget->tflags |= MPT_TARGET_FLAGS_LED_ON;
|
|
}
|
|
}
|
|
}
|
|
@@ -2512,12 +2954,16 @@ mptscsih_copy_sense_data(struct scsi_cmn
|
|
}
|
|
|
|
/**
|
|
- * mptscsih_get_scsi_lookup - retrieves scmd entry
|
|
+ * mptscsih_get_scsi_lookup
|
|
+ *
|
|
+ * retrieves scmd entry from ScsiLookup[] array list
|
|
+ *
|
|
* @ioc: Pointer to MPT_ADAPTER structure
|
|
* @i: index into the array
|
|
*
|
|
* Returns the scsi_cmd pointer
|
|
- */
|
|
+ *
|
|
+ **/
|
|
struct scsi_cmnd *
|
|
mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i)
|
|
{
|
|
@@ -2530,10 +2976,12 @@ mptscsih_get_scsi_lookup(MPT_ADAPTER *io
|
|
|
|
return scmd;
|
|
}
|
|
-EXPORT_SYMBOL(mptscsih_get_scsi_lookup);
|
|
|
|
/**
|
|
- * mptscsih_getclear_scsi_lookup - retrieves and clears scmd entry from ScsiLookup[] array list
|
|
+ * mptscsih_getclear_scsi_lookup
|
|
+ *
|
|
+ * retrieves and clears scmd entry from ScsiLookup[] array list
|
|
+ *
|
|
* @ioc: Pointer to MPT_ADAPTER structure
|
|
* @i: index into the array
|
|
*
|
|
@@ -2604,7 +3052,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int
|
|
{
|
|
MPT_SCSI_HOST *hd;
|
|
|
|
- if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL)
|
|
+ if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
|
|
return 0;
|
|
|
|
hd = shost_priv(ioc->sh);
|
|
@@ -2684,7 +3132,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
|
|
SCSIIOReply_t *pReply;
|
|
u8 cmd;
|
|
u16 req_idx;
|
|
- u8 *sense_data;
|
|
+ u8 *sense_data;
|
|
int sz;
|
|
|
|
ioc->internal_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
|
|
@@ -2722,8 +3170,8 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
|
|
/**
|
|
* mptscsih_get_completion_code -
|
|
* @ioc: Pointer to MPT_ADAPTER structure
|
|
- * @req: Pointer to original MPT request frame
|
|
- * @reply: Pointer to MPT reply frame (NULL if TurboReply)
|
|
+ * @reply:
|
|
+ * @cmd:
|
|
*
|
|
**/
|
|
static int
|
|
@@ -2829,7 +3277,7 @@ mptscsih_get_completion_code(MPT_ADAPTER
|
|
*
|
|
* > 0 if command complete but some type of completion error.
|
|
*/
|
|
-static int
|
|
+int
|
|
mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
|
|
{
|
|
MPT_FRAME_HDR *mf;
|
|
@@ -2849,7 +3297,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
|
|
if (ioc->ioc_reset_in_progress) {
|
|
spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- "%s: busy with host reset\n", ioc->name, __func__));
|
|
+ "%s: busy with host reset\n", ioc->name, __FUNCTION__));
|
|
return MPT_SCANDV_BUSY;
|
|
}
|
|
spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
|
|
@@ -2945,6 +3393,35 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
|
|
timeout = 10;
|
|
break;
|
|
|
|
+ case REPORT_LUNS:
|
|
+ cmdLen = 12;
|
|
+ dir = MPI_SCSIIO_CONTROL_READ;
|
|
+ CDB[0] = cmd;
|
|
+ CDB[6] = (io->size >> 24) & 0xFF;
|
|
+ CDB[7] = (io->size >> 16) & 0xFF;
|
|
+ CDB[8] = (io->size >> 8) & 0xFF;
|
|
+ CDB[9] = io->size & 0xFF;
|
|
+ timeout = 10;
|
|
+ break;
|
|
+
|
|
+ case TRANSPORT_LAYER_RETRIES:
|
|
+ CDB[0] = cmd;
|
|
+ CDB[1] = 0x01;
|
|
+ cmdLen = 6;
|
|
+ dir = MPI_SCSIIO_CONTROL_READ;
|
|
+ timeout = 10;
|
|
+ break;
|
|
+#ifdef EEDP_SUPPORT
|
|
+ case SERVICE_ACTION_IN:
|
|
+ CDB[0] = cmd;
|
|
+ CDB[1] = 0x10;
|
|
+ CDB[13] = io->size & 0xFF;
|
|
+ dir = MPI_SCSIIO_CONTROL_READ;
|
|
+ timeout = 10;
|
|
+ cmdLen = 16;
|
|
+ break;
|
|
+#endif
|
|
+
|
|
default:
|
|
/* Error Case */
|
|
ret = -EFAULT;
|
|
@@ -3032,9 +3509,12 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
|
|
goto out;
|
|
}
|
|
if (!timeleft) {
|
|
+ if (!mptscsih_scandv_bus_reset(ioc))
|
|
+ goto out;
|
|
printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
|
|
ioc->name, __func__);
|
|
- mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
+ if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
|
|
+ mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
mpt_free_msg_frame(ioc, mf);
|
|
}
|
|
goto out;
|
|
@@ -3050,6 +3530,73 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
|
|
return ret;
|
|
}
|
|
|
|
+int
|
|
+mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
|
|
+{
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
+ MpiRaidActionRequest_t *pReq;
|
|
+ MPT_FRAME_HDR *mf;
|
|
+ int ret;
|
|
+ unsigned long timeleft;
|
|
+
|
|
+ mutex_lock(&ioc->internal_cmds.mutex);
|
|
+
|
|
+ /* Get and Populate a free Frame
|
|
+ */
|
|
+ if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
|
|
+ dfailprintk(hd->ioc, printk(MYIOC_s_WARN_FMT "%s: no msg frames!\n",
|
|
+ ioc->name, __FUNCTION__));
|
|
+ ret = -EAGAIN;
|
|
+ goto out;
|
|
+ }
|
|
+ pReq = (MpiRaidActionRequest_t *)mf;
|
|
+ if (quiesce)
|
|
+ pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO;
|
|
+ else
|
|
+ pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO;
|
|
+ pReq->Reserved1 = 0;
|
|
+ pReq->ChainOffset = 0;
|
|
+ pReq->Function = MPI_FUNCTION_RAID_ACTION;
|
|
+ pReq->VolumeID = id;
|
|
+ pReq->VolumeBus = channel;
|
|
+ pReq->PhysDiskNum = 0;
|
|
+ pReq->MsgFlags = 0;
|
|
+ pReq->Reserved2 = 0;
|
|
+ pReq->ActionDataWord = 0; /* Reserved for this action */
|
|
+
|
|
+ ioc->add_sge((char *)&pReq->ActionDataSGE,
|
|
+ MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
|
|
+
|
|
+ ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n",
|
|
+ ioc->name, pReq->Action, channel, id));
|
|
+
|
|
+ INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status)
|
|
+ mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
|
|
+ timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done, 10*HZ);
|
|
+ if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
+ ret = -ETIME;
|
|
+ dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: TIMED OUT!\n",
|
|
+ ioc->name, __FUNCTION__));
|
|
+ if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
|
|
+ goto out;
|
|
+ if (!timeleft) {
|
|
+ printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
|
|
+ ioc->name, __FUNCTION__);
|
|
+ if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
|
|
+ mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ }
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ ret = ioc->internal_cmds.completion_code;
|
|
+
|
|
+ out:
|
|
+ CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
|
|
+ mutex_unlock(&ioc->internal_cmds.mutex);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/**
|
|
* mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
|
|
@@ -3061,9 +3608,10 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
|
|
*
|
|
*/
|
|
static void
|
|
-mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
|
|
+mptscsih_synchronize_cache(struct scsi_device *sdev, MPT_SCSI_HOST *hd, VirtDevice *vdevice)
|
|
{
|
|
INTERNAL_CMD iocmd;
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
|
|
/* Ignore hidden raid components, this is handled when the command
|
|
* is sent to the volume
|
|
@@ -3075,23 +3623,124 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST
|
|
!vdevice->configured_lun)
|
|
return;
|
|
|
|
- /* Following parameters will not change
|
|
- * in this routine.
|
|
- */
|
|
+ memset(&iocmd, 0, sizeof(INTERNAL_CMD));
|
|
iocmd.cmd = SYNCHRONIZE_CACHE;
|
|
- iocmd.flags = 0;
|
|
iocmd.physDiskNum = -1;
|
|
iocmd.data = NULL;
|
|
iocmd.data_dma = -1;
|
|
- iocmd.size = 0;
|
|
- iocmd.rsvd = iocmd.rsvd2 = 0;
|
|
iocmd.channel = vdevice->vtarget->channel;
|
|
iocmd.id = vdevice->vtarget->id;
|
|
iocmd.lun = vdevice->lun;
|
|
|
|
+ sdev_printk(KERN_INFO, sdev, MYIOC_s_FMT "SYNCHRONIZE_CACHE: fw_channel %d,"
|
|
+ " fw_id %d\n", ioc->name, vdevice->vtarget->channel, vdevice->vtarget->id);
|
|
mptscsih_do_cmd(hd, &iocmd);
|
|
}
|
|
|
|
+/*
|
|
+ * shost attributes
|
|
+ */
|
|
+static ssize_t
|
|
+mptscsih_fault_show(struct device *dev, struct device_attribute *attr,
|
|
+ char *buf)
|
|
+{
|
|
+ struct Scsi_Host *host = class_to_shost(dev);
|
|
+ MPT_SCSI_HOST *hd = shost_priv(host);
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
+
|
|
+ return snprintf(buf, PAGE_SIZE, "%d\n", ioc->is_fault);
|
|
+}
|
|
+static ssize_t
|
|
+mptscsih_fault_store(struct device *dev, struct device_attribute *attr,
|
|
+ const char *buf, size_t count)
|
|
+{
|
|
+ struct Scsi_Host *host = class_to_shost(dev);
|
|
+ MPT_SCSI_HOST *hd = shost_priv(host);
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
+ int val = 0;
|
|
+
|
|
+ if (sscanf(buf, "%d", &val) != 1)
|
|
+ return -EINVAL;
|
|
+
|
|
+ ioc->is_fault = val;
|
|
+ return strlen(buf);
|
|
+
|
|
+}
|
|
+
|
|
+struct DIAG_BUFFER_START {
|
|
+ u32 Size;
|
|
+ u32 DiagVersion;
|
|
+ u8 BufferType;
|
|
+ u8 Reserved[3];
|
|
+ u32 Reserved1;
|
|
+ u32 Reserved2;
|
|
+ u32 Reserved3;
|
|
+};
|
|
+
|
|
+static ssize_t
|
|
+mptscsih_ring_buffer_size_show(struct device *dev,
|
|
+ struct device_attribute *attr, char *buf)
|
|
+{
|
|
+ struct Scsi_Host *host = class_to_shost(dev);
|
|
+ MPT_SCSI_HOST *hd = shost_priv(host);
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
+ u32 size = 0;
|
|
+ struct DIAG_BUFFER_START *request_data;
|
|
+
|
|
+ ioc->ring_buffer_sz = 0;
|
|
+ if (!ioc->DiagBuffer[0])
|
|
+ return 0;
|
|
+
|
|
+ request_data = (struct DIAG_BUFFER_START *)ioc->DiagBuffer[0];
|
|
+ if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 ||
|
|
+ le32_to_cpu(request_data->DiagVersion) == 0x01000000) &&
|
|
+ le32_to_cpu(request_data->Reserved3) == 0x4742444c) {
|
|
+ size = le32_to_cpu(request_data->Size);
|
|
+ ioc->ring_buffer_sz = size;
|
|
+ }
|
|
+
|
|
+ return snprintf(buf, PAGE_SIZE, "%d\n", size);
|
|
+}
|
|
+
|
|
+static ssize_t
|
|
+mptscsih_ring_buffer_show(struct device *dev,
|
|
+ struct device_attribute *attr, char *buf)
|
|
+{
|
|
+ struct Scsi_Host *host = class_to_shost(dev);
|
|
+ MPT_SCSI_HOST *hd = shost_priv(host);
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
+ void *request_data;
|
|
+ u32 size;
|
|
+
|
|
+ if (!ioc->DiagBuffer[0])
|
|
+ return 0;
|
|
+
|
|
+ if (ioc->ring_buffer_offset > ioc->ring_buffer_sz)
|
|
+ return 0;
|
|
+
|
|
+ size = ioc->ring_buffer_sz - ioc->ring_buffer_offset;
|
|
+ size = (size > PAGE_SIZE) ? PAGE_SIZE : size;
|
|
+ request_data = ioc->DiagBuffer[0] + ioc->ring_buffer_offset;
|
|
+ memcpy(buf, request_data, size);
|
|
+ return size;
|
|
+}
|
|
+
|
|
+static ssize_t
|
|
+mptscsih_ring_buffer_store(struct device *dev, struct device_attribute *attr,
|
|
+ const char *buf, size_t count)
|
|
+{
|
|
+ struct Scsi_Host *host = class_to_shost(dev);
|
|
+ MPT_SCSI_HOST *hd = shost_priv(host);
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
+ int val = 0;
|
|
+
|
|
+ if (sscanf(buf, "%d", &val) != 1)
|
|
+ return -EINVAL;
|
|
+
|
|
+ ioc->ring_buffer_offset = val;
|
|
+ return strlen(buf);
|
|
+}
|
|
+
|
|
static ssize_t
|
|
mptscsih_version_fw_show(struct device *dev, struct device_attribute *attr,
|
|
char *buf)
|
|
@@ -3106,7 +3755,6 @@ mptscsih_version_fw_show(struct device *
|
|
(ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
|
|
ioc->facts.FWVersion.Word & 0x000000FF);
|
|
}
|
|
-static DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
|
|
|
|
static ssize_t
|
|
mptscsih_version_bios_show(struct device *dev, struct device_attribute *attr,
|
|
@@ -3116,13 +3764,12 @@ mptscsih_version_bios_show(struct device
|
|
MPT_SCSI_HOST *hd = shost_priv(host);
|
|
MPT_ADAPTER *ioc = hd->ioc;
|
|
|
|
- return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
|
|
+ return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
|
|
(ioc->biosVersion & 0xFF000000) >> 24,
|
|
(ioc->biosVersion & 0x00FF0000) >> 16,
|
|
(ioc->biosVersion & 0x0000FF00) >> 8,
|
|
ioc->biosVersion & 0x000000FF);
|
|
}
|
|
-static DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL);
|
|
|
|
static ssize_t
|
|
mptscsih_version_mpi_show(struct device *dev, struct device_attribute *attr,
|
|
@@ -3132,14 +3779,17 @@ mptscsih_version_mpi_show(struct device
|
|
MPT_SCSI_HOST *hd = shost_priv(host);
|
|
MPT_ADAPTER *ioc = hd->ioc;
|
|
|
|
- return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion);
|
|
+ if (ioc->facts.MsgVersion >= MPI_VERSION_01_05)
|
|
+ return snprintf(buf, PAGE_SIZE, "%03x.%02x\n",
|
|
+ ioc->facts.MsgVersion, ioc->facts.HeaderVersion >> 8);
|
|
+ else
|
|
+ return snprintf(buf, PAGE_SIZE, "%03x\n",
|
|
+ ioc->facts.MsgVersion);
|
|
}
|
|
-static DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
|
|
|
|
static ssize_t
|
|
mptscsih_version_product_show(struct device *dev,
|
|
- struct device_attribute *attr,
|
|
-char *buf)
|
|
+ struct device_attribute *attr, char *buf)
|
|
{
|
|
struct Scsi_Host *host = class_to_shost(dev);
|
|
MPT_SCSI_HOST *hd = shost_priv(host);
|
|
@@ -3147,8 +3797,6 @@ char *buf)
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name);
|
|
}
|
|
-static DEVICE_ATTR(version_product, S_IRUGO,
|
|
- mptscsih_version_product_show, NULL);
|
|
|
|
static ssize_t
|
|
mptscsih_version_nvdata_persistent_show(struct device *dev,
|
|
@@ -3162,8 +3810,6 @@ mptscsih_version_nvdata_persistent_show(
|
|
return snprintf(buf, PAGE_SIZE, "%02xh\n",
|
|
ioc->nvdata_version_persistent);
|
|
}
|
|
-static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
|
|
- mptscsih_version_nvdata_persistent_show, NULL);
|
|
|
|
static ssize_t
|
|
mptscsih_version_nvdata_default_show(struct device *dev,
|
|
@@ -3175,8 +3821,6 @@ mptscsih_version_nvdata_default_show(str
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default);
|
|
}
|
|
-static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
|
|
- mptscsih_version_nvdata_default_show, NULL);
|
|
|
|
static ssize_t
|
|
mptscsih_board_name_show(struct device *dev, struct device_attribute *attr,
|
|
@@ -3188,11 +3832,10 @@ mptscsih_board_name_show(struct device *
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name);
|
|
}
|
|
-static DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
|
|
|
|
static ssize_t
|
|
-mptscsih_board_assembly_show(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
+mptscsih_board_assembly_show(struct device *dev, struct device_attribute *attr,
|
|
+ char *buf)
|
|
{
|
|
struct Scsi_Host *host = class_to_shost(dev);
|
|
MPT_SCSI_HOST *hd = shost_priv(host);
|
|
@@ -3200,8 +3843,6 @@ mptscsih_board_assembly_show(struct devi
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly);
|
|
}
|
|
-static DEVICE_ATTR(board_assembly, S_IRUGO,
|
|
- mptscsih_board_assembly_show, NULL);
|
|
|
|
static ssize_t
|
|
mptscsih_board_tracer_show(struct device *dev, struct device_attribute *attr,
|
|
@@ -3213,8 +3854,6 @@ mptscsih_board_tracer_show(struct device
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer);
|
|
}
|
|
-static DEVICE_ATTR(board_tracer, S_IRUGO,
|
|
- mptscsih_board_tracer_show, NULL);
|
|
|
|
static ssize_t
|
|
mptscsih_io_delay_show(struct device *dev, struct device_attribute *attr,
|
|
@@ -3226,8 +3865,6 @@ mptscsih_io_delay_show(struct device *de
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
|
|
}
|
|
-static DEVICE_ATTR(io_delay, S_IRUGO,
|
|
- mptscsih_io_delay_show, NULL);
|
|
|
|
static ssize_t
|
|
mptscsih_device_delay_show(struct device *dev, struct device_attribute *attr,
|
|
@@ -3239,8 +3876,6 @@ mptscsih_device_delay_show(struct device
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
|
|
}
|
|
-static DEVICE_ATTR(device_delay, S_IRUGO,
|
|
- mptscsih_device_delay_show, NULL);
|
|
|
|
static ssize_t
|
|
mptscsih_debug_level_show(struct device *dev, struct device_attribute *attr,
|
|
@@ -3252,6 +3887,7 @@ mptscsih_debug_level_show(struct device
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level);
|
|
}
|
|
+
|
|
static ssize_t
|
|
mptscsih_debug_level_store(struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
@@ -3265,14 +3901,78 @@ mptscsih_debug_level_store(struct device
|
|
return -EINVAL;
|
|
|
|
ioc->debug_level = val;
|
|
- printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n",
|
|
- ioc->name, ioc->debug_level);
|
|
+ printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n", ioc->name,
|
|
+ ioc->debug_level);
|
|
+ return strlen(buf);
|
|
+}
|
|
+
|
|
+static ssize_t
|
|
+mptscsih_disable_hotplug_remove_show(struct device *dev,
|
|
+ struct device_attribute *attr,
|
|
+ char *buf)
|
|
+{
|
|
+ struct Scsi_Host *host = class_to_shost(dev);
|
|
+ MPT_SCSI_HOST *hd = shost_priv(host);
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
+
|
|
+ return snprintf(buf, PAGE_SIZE, "%02xh\n", ioc->disable_hotplug_remove);
|
|
+}
|
|
+static ssize_t
|
|
+mptscsih_disable_hotplug_remove_store(struct device *dev,
|
|
+ struct device_attribute *attr,
|
|
+ const char *buf, size_t count)
|
|
+{
|
|
+ struct Scsi_Host *host = class_to_shost(dev);
|
|
+ MPT_SCSI_HOST *hd = shost_priv(host);
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
+ int val = 0;
|
|
+
|
|
+ if (sscanf(buf, "%x", &val) != 1)
|
|
+ return -EINVAL;
|
|
+
|
|
+ ioc->disable_hotplug_remove = val;
|
|
+ if (ioc->disable_hotplug_remove)
|
|
+ printk(MYIOC_s_INFO_FMT "disabling hotplug remove\n",
|
|
+ ioc->name);
|
|
+ else
|
|
+ printk(MYIOC_s_INFO_FMT "eanbling hotplug remove\n", ioc->name);
|
|
return strlen(buf);
|
|
}
|
|
+
|
|
+static DEVICE_ATTR(fault, S_IRUGO | S_IWUSR,
|
|
+ mptscsih_fault_show, mptscsih_fault_store);
|
|
+static DEVICE_ATTR(ring_buffer_size, S_IRUGO,
|
|
+ mptscsih_ring_buffer_size_show, NULL);
|
|
+static DEVICE_ATTR(ring_buffer, S_IRUGO | S_IWUSR,
|
|
+ mptscsih_ring_buffer_show, mptscsih_ring_buffer_store);
|
|
+static DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
|
|
+static DEVICE_ATTR(version_bios, S_IRUGO,
|
|
+ mptscsih_version_bios_show, NULL);
|
|
+static DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
|
|
+static DEVICE_ATTR(version_product, S_IRUGO,
|
|
+ mptscsih_version_product_show, NULL);
|
|
+static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
|
|
+ mptscsih_version_nvdata_persistent_show, NULL);
|
|
+static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
|
|
+ mptscsih_version_nvdata_default_show, NULL);
|
|
+static DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
|
|
+static DEVICE_ATTR(board_assembly, S_IRUGO,
|
|
+ mptscsih_board_assembly_show, NULL);
|
|
+static DEVICE_ATTR(board_tracer, S_IRUGO,
|
|
+ mptscsih_board_tracer_show, NULL);
|
|
+static DEVICE_ATTR(io_delay, S_IRUGO,
|
|
+ mptscsih_io_delay_show, NULL);
|
|
+static DEVICE_ATTR(device_delay, S_IRUGO,
|
|
+ mptscsih_device_delay_show, NULL);
|
|
static DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
|
|
- mptscsih_debug_level_show, mptscsih_debug_level_store);
|
|
+ mptscsih_debug_level_show, mptscsih_debug_level_store);
|
|
+static DEVICE_ATTR(disable_hotplug_remove, S_IRUGO | S_IWUSR,
|
|
+ mptscsih_disable_hotplug_remove_show, mptscsih_disable_hotplug_remove_store);
|
|
|
|
struct device_attribute *mptscsih_host_attrs[] = {
|
|
+ &dev_attr_fault,
|
|
+ &dev_attr_ring_buffer_size,
|
|
+ &dev_attr_ring_buffer,
|
|
&dev_attr_version_fw,
|
|
&dev_attr_version_bios,
|
|
&dev_attr_version_mpi,
|
|
@@ -3285,6 +3985,7 @@ struct device_attribute *mptscsih_host_a
|
|
&dev_attr_io_delay,
|
|
&dev_attr_device_delay,
|
|
&dev_attr_debug_level,
|
|
+ &dev_attr_disable_hotplug_remove,
|
|
NULL,
|
|
};
|
|
|
|
@@ -3312,5 +4013,9 @@ EXPORT_SYMBOL(mptscsih_scandv_complete);
|
|
EXPORT_SYMBOL(mptscsih_event_process);
|
|
EXPORT_SYMBOL(mptscsih_ioc_reset);
|
|
EXPORT_SYMBOL(mptscsih_change_queue_depth);
|
|
-
|
|
+EXPORT_SYMBOL(mptscsih_IssueTaskMgmt);
|
|
+EXPORT_SYMBOL(mptscsih_do_cmd);
|
|
+EXPORT_SYMBOL(mptscsih_quiesce_raid);
|
|
+EXPORT_SYMBOL(mptscsih_get_scsi_lookup);
|
|
+EXPORT_SYMBOL(mptscsih_taskmgmt_response_code);
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
--- a/drivers/message/fusion/mptscsih.h
|
|
+++ b/drivers/message/fusion/mptscsih.h
|
|
@@ -85,12 +85,14 @@
|
|
#define MPTSCSIH_DOMAIN_VALIDATION 1
|
|
#define MPTSCSIH_MAX_WIDTH 1
|
|
#define MPTSCSIH_MIN_SYNC 0x08
|
|
+#define MPTSCSIH_QAS 1
|
|
#define MPTSCSIH_SAF_TE 0
|
|
#define MPTSCSIH_PT_CLEAR 0
|
|
|
|
+#define TRANSPORT_LAYER_RETRIES 0xC2
|
|
#endif
|
|
|
|
-
|
|
+#define mpt_sg_next(sg) sg_next(sg)
|
|
typedef struct _internal_cmd {
|
|
char *data; /* data pointer */
|
|
dma_addr_t data_dma; /* data dma address */
|
|
@@ -114,9 +116,7 @@ extern int mptscsih_resume(struct pci_de
|
|
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_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel,
|
|
- u8 id, int lun, int ctx2abort, ulong timeout);
|
|
-extern void mptscsih_slave_destroy(struct scsi_device *device);
|
|
+extern void mptscsih_slave_destroy(struct scsi_device *sdev);
|
|
extern int mptscsih_slave_configure(struct scsi_device *device);
|
|
extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
|
|
extern int mptscsih_dev_reset(struct scsi_cmnd * SCpnt);
|
|
@@ -130,8 +130,11 @@ extern int mptscsih_event_process(MPT_AD
|
|
extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
|
|
extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth,
|
|
int reason);
|
|
+extern int mptscsih_IssueTaskMgmt(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);
|
|
+extern int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
|
|
extern struct device_attribute *mptscsih_host_attrs[];
|
|
-extern struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
|
|
+extern int mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id);
|
|
+extern struct scsi_cmnd * mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
|
|
extern void mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code);
|
|
--- a/drivers/message/fusion/mptspi.c
|
|
+++ b/drivers/message/fusion/mptspi.c
|
|
@@ -43,7 +43,7 @@
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
-
|
|
+#include <linux/version.h>
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
@@ -53,8 +53,10 @@
|
|
#include <linux/delay.h> /* for mdelay */
|
|
#include <linux/interrupt.h> /* needed for in_interrupt() proto */
|
|
#include <linux/reboot.h> /* notifier code */
|
|
+#include <linux/sched.h>
|
|
#include <linux/workqueue.h>
|
|
#include <linux/raid_class.h>
|
|
+#include <linux/pci.h>
|
|
|
|
#include <scsi/scsi.h>
|
|
#include <scsi/scsi_cmnd.h>
|
|
@@ -83,6 +85,10 @@ static int mpt_saf_te = MPTSCSIH_SAF_TE;
|
|
module_param(mpt_saf_te, int, 0);
|
|
MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)");
|
|
|
|
+static int mpt_qas = MPTSCSIH_QAS;
|
|
+module_param(mpt_qas, int, 1);
|
|
+MODULE_PARM_DESC(mpt_qas, " Quick Arbitration and Selection (QAS) enabled=1, disabled=0 (default=MPTSCSIH_QAS=1)");
|
|
+
|
|
static void mptspi_write_offset(struct scsi_target *, int);
|
|
static void mptspi_write_width(struct scsi_target *, int);
|
|
static int mptspi_write_spi_device_pg1(struct scsi_target *,
|
|
@@ -95,12 +101,12 @@ static u8 mptspiTaskCtx = MPT_MAX_PROTOC
|
|
static u8 mptspiInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
|
|
|
|
/**
|
|
- * mptspi_setTargetNegoParms - Update the target negotiation parameters
|
|
+ * mptspi_setTargetNegoParms - Update the target negotiation parameters
|
|
* @hd: Pointer to a SCSI Host Structure
|
|
* @target: per target private data
|
|
* @sdev: SCSI device
|
|
*
|
|
- * Update the target negotiation parameters based on the the Inquiry
|
|
+ * Update the target negotiation parameters based on the the Inquiry
|
|
* data, adapter capabilities, and NVRAM settings.
|
|
**/
|
|
static void
|
|
@@ -131,7 +137,7 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST
|
|
if (scsi_device_sync(sdev)) {
|
|
factor = pspi_data->minSyncFactor;
|
|
if (!scsi_device_dt(sdev))
|
|
- factor = MPT_ULTRA2;
|
|
+ factor = MPT_ULTRA2;
|
|
else {
|
|
if (!scsi_device_ius(sdev) &&
|
|
!scsi_device_qas(sdev))
|
|
@@ -209,6 +215,10 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST
|
|
target->maxOffset = offset;
|
|
target->maxWidth = width;
|
|
|
|
+ spi_min_period(scsi_target(sdev)) = factor;
|
|
+ spi_max_offset(scsi_target(sdev)) = offset;
|
|
+ spi_max_width(scsi_target(sdev)) = width;
|
|
+
|
|
target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
|
|
|
|
/* Disable unused features.
|
|
@@ -230,7 +240,7 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST
|
|
*/
|
|
|
|
ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- "Disabling QAS due to noQas=%02x on id=%d!\n", ioc->name, noQas, id));
|
|
+ "Disabling QAS due to noQas=%02x on id=%d!\n", ioc->name, noQas, id));
|
|
}
|
|
}
|
|
|
|
@@ -262,7 +272,7 @@ mptspi_writeIOCPage4(MPT_SCSI_HOST *hd,
|
|
*/
|
|
if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
|
|
dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
|
|
- "writeIOCPage4 : no msg frames!\n",ioc->name));
|
|
+ "writeIOCPage4 : no msg frames!\n", ioc->name));
|
|
return -EAGAIN;
|
|
}
|
|
|
|
@@ -304,7 +314,7 @@ mptspi_writeIOCPage4(MPT_SCSI_HOST *hd,
|
|
|
|
ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
"writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
|
|
- ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel));
|
|
+ ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel));
|
|
|
|
mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
|
|
|
|
@@ -371,7 +381,7 @@ mptspi_initTarget(MPT_SCSI_HOST *hd, Vir
|
|
* non-zero = true
|
|
* zero = false
|
|
*
|
|
- */
|
|
+ **/
|
|
static int
|
|
mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id)
|
|
{
|
|
@@ -399,12 +409,11 @@ static int mptspi_target_alloc(struct sc
|
|
struct Scsi_Host *shost = dev_to_shost(&starget->dev);
|
|
struct _MPT_SCSI_HOST *hd = shost_priv(shost);
|
|
VirtTarget *vtarget;
|
|
- MPT_ADAPTER *ioc;
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
|
|
if (hd == NULL)
|
|
return -ENODEV;
|
|
|
|
- ioc = hd->ioc;
|
|
vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
|
|
if (!vtarget)
|
|
return -ENOMEM;
|
|
@@ -471,9 +480,12 @@ mptspi_target_destroy(struct scsi_target
|
|
static void
|
|
mptspi_print_write_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii)
|
|
{
|
|
- ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "id=%d Requested = 0x%08x"
|
|
+ if (!(hd->ioc->debug_level & MPT_DEBUG_DV))
|
|
+ return;
|
|
+
|
|
+ starget_printk(KERN_DEBUG, starget, MYIOC_s_FMT "Wrote = 0x%08x"
|
|
" ( %s factor = 0x%02x @ offset = 0x%02x %s%s%s%s%s%s%s%s)\n",
|
|
- hd->ioc->name, starget->id, ii,
|
|
+ hd->ioc->name, ii,
|
|
ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "",
|
|
((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF),
|
|
ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "",
|
|
@@ -483,7 +495,7 @@ mptspi_print_write_nego(struct _MPT_SCSI
|
|
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 ": ""));
|
|
+ ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": "");
|
|
}
|
|
|
|
/**
|
|
@@ -496,9 +508,12 @@ mptspi_print_write_nego(struct _MPT_SCSI
|
|
static void
|
|
mptspi_print_read_nego(struct _MPT_SCSI_HOST *hd, struct scsi_target *starget, u32 ii)
|
|
{
|
|
- ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "id=%d Read = 0x%08x"
|
|
+ if (!(hd->ioc->debug_level & MPT_DEBUG_DV))
|
|
+ return;
|
|
+
|
|
+ starget_printk(KERN_DEBUG, starget, MYIOC_s_FMT "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,
|
|
+ hd->ioc->name, ii,
|
|
ii & MPI_SCSIDEVPAGE0_NP_WIDE ? "Wide ": "",
|
|
((ii >> 8) & 0xFF), ((ii >> 16) & 0xFF),
|
|
ii & MPI_SCSIDEVPAGE0_NP_IU ? "IU ": "",
|
|
@@ -508,7 +523,7 @@ mptspi_print_read_nego(struct _MPT_SCSI_
|
|
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 ": ""));
|
|
+ ii & MPI_SCSIDEVPAGE0_NP_PCOMP_EN ? "PCOMP ": "");
|
|
}
|
|
|
|
static int mptspi_read_spi_device_pg0(struct scsi_target *starget,
|
|
@@ -557,9 +572,11 @@ static int mptspi_read_spi_device_pg0(st
|
|
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
|
|
cfg.dir = 0;
|
|
cfg.pageAddr = starget->id;
|
|
+ cfg.timeout = 60;
|
|
|
|
if (mpt_config(ioc, &cfg)) {
|
|
- starget_printk(KERN_ERR, starget, MYIOC_s_FMT "mpt_config failed\n", ioc->name);
|
|
+ starget_printk(KERN_ERR, starget,
|
|
+ MYIOC_s_FMT "mpt_config failed\n", ioc->name);
|
|
goto out_free;
|
|
}
|
|
err = 0;
|
|
@@ -614,76 +631,11 @@ static void mptspi_read_parameters(struc
|
|
spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;
|
|
}
|
|
|
|
-int
|
|
-mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
|
|
-{
|
|
- MPT_ADAPTER *ioc = hd->ioc;
|
|
- MpiRaidActionRequest_t *pReq;
|
|
- MPT_FRAME_HDR *mf;
|
|
- int ret;
|
|
- unsigned long timeleft;
|
|
-
|
|
- mutex_lock(&ioc->internal_cmds.mutex);
|
|
-
|
|
- /* Get and Populate a free Frame
|
|
- */
|
|
- if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
|
|
- dfailprintk(hd->ioc, printk(MYIOC_s_WARN_FMT
|
|
- "%s: no msg frames!\n", ioc->name, __func__));
|
|
- ret = -EAGAIN;
|
|
- goto out;
|
|
- }
|
|
- pReq = (MpiRaidActionRequest_t *)mf;
|
|
- if (quiesce)
|
|
- pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO;
|
|
- else
|
|
- pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO;
|
|
- pReq->Reserved1 = 0;
|
|
- pReq->ChainOffset = 0;
|
|
- pReq->Function = MPI_FUNCTION_RAID_ACTION;
|
|
- pReq->VolumeID = id;
|
|
- pReq->VolumeBus = channel;
|
|
- pReq->PhysDiskNum = 0;
|
|
- pReq->MsgFlags = 0;
|
|
- pReq->Reserved2 = 0;
|
|
- pReq->ActionDataWord = 0; /* Reserved for this action */
|
|
-
|
|
- ioc->add_sge((char *)&pReq->ActionDataSGE,
|
|
- MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
|
|
-
|
|
- ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n",
|
|
- ioc->name, pReq->Action, channel, id));
|
|
-
|
|
- INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status)
|
|
- mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
|
|
- timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done, 10*HZ);
|
|
- if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
- ret = -ETIME;
|
|
- dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: TIMED OUT!\n",
|
|
- ioc->name, __func__));
|
|
- if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
|
|
- goto out;
|
|
- if (!timeleft) {
|
|
- printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
|
|
- ioc->name, __func__);
|
|
- mpt_HardResetHandler(ioc, CAN_SLEEP);
|
|
- mpt_free_msg_frame(ioc, mf);
|
|
- }
|
|
- goto out;
|
|
- }
|
|
-
|
|
- ret = ioc->internal_cmds.completion_code;
|
|
-
|
|
- out:
|
|
- CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
|
|
- mutex_unlock(&ioc->internal_cmds.mutex);
|
|
- return ret;
|
|
-}
|
|
-
|
|
static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
|
|
struct scsi_device *sdev)
|
|
{
|
|
VirtTarget *vtarget = scsi_target(sdev)->hostdata;
|
|
+ struct scsi_target *starget = scsi_target(sdev);
|
|
MPT_ADAPTER *ioc = hd->ioc;
|
|
|
|
/* no DV on RAID devices */
|
|
@@ -691,11 +643,20 @@ static void mptspi_dv_device(struct _MPT
|
|
mptspi_is_raid(hd, sdev->id))
|
|
return;
|
|
|
|
+ if (ioc->debug_level & MPT_DEBUG_DV)
|
|
+ starget_printk(KERN_DEBUG, starget, MYIOC_s_FMT
|
|
+ "sdtr=%d, wdtr=%d, ppr=%d, min_period=0x%02x, "
|
|
+ "max_offset=0x%02x, max_width=%d, nego_flags=0x%02x, "
|
|
+ "tflags=0x%02x\n", ioc->name, sdev->sdtr, sdev->wdtr,
|
|
+ sdev->ppr, spi_min_period(starget),
|
|
+ spi_max_offset(starget), spi_max_width(starget),
|
|
+ vtarget->negoFlags, vtarget->tflags);
|
|
+
|
|
/* If this is a piece of a RAID, then quiesce first */
|
|
if (sdev->channel == 1 &&
|
|
mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) {
|
|
- starget_printk(KERN_ERR, scsi_target(sdev), MYIOC_s_FMT
|
|
- "Integrated RAID quiesce failed\n", ioc->name);
|
|
+ starget_printk(KERN_ERR, scsi_target(sdev),
|
|
+ MYIOC_s_FMT "Integrated RAID quiesce failed\n", ioc->name);
|
|
return;
|
|
}
|
|
|
|
@@ -705,8 +666,8 @@ static void mptspi_dv_device(struct _MPT
|
|
|
|
if (sdev->channel == 1 &&
|
|
mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
|
|
- starget_printk(KERN_ERR, scsi_target(sdev), MYIOC_s_FMT
|
|
- "Integrated RAID resume failed\n", ioc->name);
|
|
+ starget_printk(KERN_ERR, scsi_target(sdev),
|
|
+ MYIOC_s_FMT "Integrated RAID resume failed\n", ioc->name);
|
|
|
|
mptspi_read_parameters(sdev->sdev_target);
|
|
spi_display_xfer_agreement(sdev->sdev_target);
|
|
@@ -728,7 +689,7 @@ static int mptspi_slave_alloc(struct scs
|
|
vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
|
|
if (!vdevice) {
|
|
printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
|
|
- ioc->name, sizeof(VirtDevice));
|
|
+ ioc->name, sizeof(VirtDevice));
|
|
return -ENOMEM;
|
|
}
|
|
|
|
@@ -750,21 +711,13 @@ static int mptspi_slave_configure(struct
|
|
{
|
|
struct _MPT_SCSI_HOST *hd = shost_priv(sdev->host);
|
|
VirtTarget *vtarget = scsi_target(sdev)->hostdata;
|
|
- int ret;
|
|
+ int ret;
|
|
|
|
mptspi_initTarget(hd, vtarget, sdev);
|
|
-
|
|
ret = mptscsih_slave_configure(sdev);
|
|
-
|
|
if (ret)
|
|
return ret;
|
|
|
|
- ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_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))
|
|
@@ -869,8 +822,8 @@ static int mptspi_write_spi_device_pg1(s
|
|
|
|
pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL);
|
|
if (pg1 == NULL) {
|
|
- starget_printk(KERN_ERR, starget, MYIOC_s_FMT
|
|
- "dma_alloc_coherent for parameters failed\n", ioc->name);
|
|
+ starget_printk(KERN_ERR, starget,
|
|
+ MYIOC_s_FMT "dma_alloc_coherent for parameters failed\n", ioc->name);
|
|
return -EINVAL;
|
|
}
|
|
|
|
@@ -899,8 +852,8 @@ static int mptspi_write_spi_device_pg1(s
|
|
mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters));
|
|
|
|
if (mpt_config(ioc, &cfg)) {
|
|
- starget_printk(KERN_ERR, starget, MYIOC_s_FMT
|
|
- "mpt_config failed\n", ioc->name);
|
|
+ starget_printk(KERN_ERR, starget,
|
|
+ MYIOC_s_FMT "mpt_config failed\n", ioc->name);
|
|
goto out_free;
|
|
}
|
|
err = 0;
|
|
@@ -975,14 +928,15 @@ static void mptspi_write_dt(struct scsi_
|
|
if (spi_period(starget) == -1)
|
|
mptspi_read_parameters(starget);
|
|
|
|
- if (!dt && spi_period(starget) < 10)
|
|
- spi_period(starget) = 10;
|
|
+ if (!dt) {
|
|
+ spi_qas(starget) = 0;
|
|
+ spi_iu(starget) = 0;
|
|
+ }
|
|
|
|
spi_dt(starget) = dt;
|
|
|
|
nego = mptspi_getRP(starget);
|
|
|
|
-
|
|
pg1.RequestedParameters = cpu_to_le32(nego);
|
|
pg1.Reserved = 0;
|
|
pg1.Configuration = 0;
|
|
@@ -998,9 +952,6 @@ static void mptspi_write_iu(struct scsi_
|
|
if (spi_period(starget) == -1)
|
|
mptspi_read_parameters(starget);
|
|
|
|
- if (!iu && spi_period(starget) < 9)
|
|
- spi_period(starget) = 9;
|
|
-
|
|
spi_iu(starget) = iu;
|
|
|
|
nego = mptspi_getRP(starget);
|
|
@@ -1042,9 +993,11 @@ static void mptspi_write_qas(struct scsi
|
|
struct _MPT_SCSI_HOST *hd = shost_priv(shost);
|
|
VirtTarget *vtarget = starget->hostdata;
|
|
u32 nego;
|
|
+ MPT_ADAPTER *ioc = hd->ioc;
|
|
|
|
- if ((vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) ||
|
|
- hd->ioc->spi_data.noQas)
|
|
+ if (!mpt_qas ||
|
|
+ (vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) ||
|
|
+ ioc->spi_data.noQas)
|
|
spi_qas(starget) = 0;
|
|
else
|
|
spi_qas(starget) = qas;
|
|
@@ -1065,8 +1018,8 @@ static void mptspi_write_width(struct sc
|
|
|
|
if (!width) {
|
|
spi_dt(starget) = 0;
|
|
- if (spi_period(starget) < 10)
|
|
- spi_period(starget) = 10;
|
|
+ spi_qas(starget) = 0;
|
|
+ spi_iu(starget) = 0;
|
|
}
|
|
|
|
spi_width(starget) = width;
|
|
@@ -1086,10 +1039,17 @@ struct work_queue_wrapper {
|
|
int disk;
|
|
};
|
|
|
|
-static void mpt_work_wrapper(struct work_struct *work)
|
|
+static void
|
|
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
|
|
+mpt_work_wrapper(struct work_struct *work)
|
|
{
|
|
struct work_queue_wrapper *wqw =
|
|
container_of(work, struct work_queue_wrapper, work);
|
|
+#else
|
|
+mpt_work_wrapper(void *data)
|
|
+{
|
|
+ struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
|
|
+#endif
|
|
struct _MPT_SCSI_HOST *hd = wqw->hd;
|
|
MPT_ADAPTER *ioc = hd->ioc;
|
|
struct Scsi_Host *shost = ioc->sh;
|
|
@@ -1117,12 +1077,12 @@ static void mpt_work_wrapper(struct work
|
|
if(vtarget->id != disk)
|
|
continue;
|
|
|
|
- starget_printk(KERN_INFO, vtarget->starget, MYIOC_s_FMT
|
|
- "Integrated RAID requests DV of new device\n", ioc->name);
|
|
+ starget_printk(KERN_INFO, vtarget->starget,
|
|
+ MYIOC_s_FMT "Integrated RAID requests DV of new device\n", ioc->name);
|
|
mptspi_dv_device(hd, sdev);
|
|
}
|
|
- shost_printk(KERN_INFO, shost, MYIOC_s_FMT
|
|
- "Integrated RAID detects new device %d\n", ioc->name, disk);
|
|
+ shost_printk(KERN_INFO, shost,
|
|
+ MYIOC_s_FMT "Integrated RAID detects new device %d\n", ioc->name, disk);
|
|
scsi_scan_target(&ioc->sh->shost_gendev, 1, disk, 0, 1);
|
|
}
|
|
|
|
@@ -1133,12 +1093,16 @@ static void mpt_dv_raid(struct _MPT_SCSI
|
|
MPT_ADAPTER *ioc = hd->ioc;
|
|
|
|
if (!wqw) {
|
|
- shost_printk(KERN_ERR, ioc->sh, MYIOC_s_FMT
|
|
- "Failed to act on RAID event for physical disk %d\n",
|
|
+ shost_printk(KERN_ERR, ioc->sh,
|
|
+ MYIOC_s_FMT "Failed to act on RAID event for physical disk %d\n",
|
|
ioc->name, disk);
|
|
return;
|
|
}
|
|
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
|
|
INIT_WORK(&wqw->work, mpt_work_wrapper);
|
|
+#else
|
|
+ INIT_WORK(&wqw->work, mpt_work_wrapper, wqw);
|
|
+#endif
|
|
wqw->hd = hd;
|
|
wqw->disk = disk;
|
|
|
|
@@ -1151,6 +1115,9 @@ mptspi_event_process(MPT_ADAPTER *ioc, E
|
|
u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
|
|
struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
|
|
|
|
+ if (ioc->bus_type != SPI)
|
|
+ return 0;
|
|
+
|
|
if (hd && event == MPI_EVENT_INTEGRATED_RAID) {
|
|
int reason
|
|
= (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
|
|
@@ -1225,14 +1192,20 @@ static struct pci_device_id mptspi_pci_t
|
|
MODULE_DEVICE_TABLE(pci, mptspi_pci_table);
|
|
|
|
|
|
-/*
|
|
+/**
|
|
* renegotiate for a given target
|
|
- */
|
|
+ **/
|
|
static void
|
|
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
|
|
mptspi_dv_renegotiate_work(struct work_struct *work)
|
|
{
|
|
struct work_queue_wrapper *wqw =
|
|
container_of(work, struct work_queue_wrapper, work);
|
|
+#else
|
|
+mptspi_dv_renegotiate_work(void *data)
|
|
+{
|
|
+ struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
|
|
+#endif
|
|
struct _MPT_SCSI_HOST *hd = wqw->hd;
|
|
struct scsi_device *sdev;
|
|
struct scsi_target *starget;
|
|
@@ -1267,38 +1240,43 @@ mptspi_dv_renegotiate(struct _MPT_SCSI_H
|
|
if (!wqw)
|
|
return;
|
|
|
|
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
|
|
INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work);
|
|
+#else
|
|
+ INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work, wqw);
|
|
+#endif
|
|
wqw->hd = hd;
|
|
|
|
schedule_work(&wqw->work);
|
|
}
|
|
|
|
-/*
|
|
+/**
|
|
* spi module reset handler
|
|
- */
|
|
+ **/
|
|
static int
|
|
mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
|
|
{
|
|
+ struct _MPT_SCSI_HOST *hd = NULL;
|
|
int rc;
|
|
|
|
rc = mptscsih_ioc_reset(ioc, reset_phase);
|
|
+ if ((ioc->bus_type != SPI) || (!rc))
|
|
+ goto out;
|
|
|
|
- /* only try to do a renegotiation if we're properly set up
|
|
- * if we get an ioc fault on bringup, ioc->sh will be NULL */
|
|
- if (reset_phase == MPT_IOC_POST_RESET &&
|
|
- ioc->sh) {
|
|
- struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
|
|
+ hd = shost_priv(ioc->sh);
|
|
+ if (!hd->ioc)
|
|
+ goto out;
|
|
|
|
+ if (ioc->active && reset_phase == MPT_IOC_POST_RESET)
|
|
mptspi_dv_renegotiate(hd);
|
|
- }
|
|
-
|
|
+ out:
|
|
return rc;
|
|
}
|
|
|
|
#ifdef CONFIG_PM
|
|
-/*
|
|
+/**
|
|
* spi module resume handler
|
|
- */
|
|
+ **/
|
|
static int
|
|
mptspi_resume(struct pci_dev *pdev)
|
|
{
|
|
@@ -1315,13 +1293,13 @@ mptspi_resume(struct pci_dev *pdev)
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
-/*
|
|
+/**
|
|
* mptspi_probe - Installs scsi devices per bus.
|
|
* @pdev: Pointer to pci_dev structure
|
|
*
|
|
* Returns 0 for success, non-zero for failure.
|
|
*
|
|
- */
|
|
+ **/
|
|
static int
|
|
mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
{
|
|
@@ -1446,6 +1424,7 @@ mptspi_probe(struct pci_dev *pdev, const
|
|
(ioc->req_sz - 64) / ioc->SGE_size;
|
|
}
|
|
|
|
+
|
|
if (numSGE < sh->sg_tablesize) {
|
|
/* Reset this value */
|
|
dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
@@ -1454,11 +1433,11 @@ mptspi_probe(struct pci_dev *pdev, const
|
|
sh->sg_tablesize = numSGE;
|
|
}
|
|
|
|
- spin_unlock_irqrestore(&ioc->FreeQlock, flags);
|
|
-
|
|
hd = shost_priv(sh);
|
|
hd->ioc = ioc;
|
|
|
|
+ spin_unlock_irqrestore(&ioc->FreeQlock, flags);
|
|
+
|
|
/* SCSI needs scsi_cmnd lookup table!
|
|
* (with size equal to req_depth*PtrSz!)
|
|
*/
|
|
@@ -1472,12 +1451,11 @@ mptspi_probe(struct pci_dev *pdev, const
|
|
dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
|
|
ioc->name, ioc->ScsiLookup));
|
|
|
|
+ ioc->sdev_queue_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
|
|
ioc->spi_data.Saf_Te = mpt_saf_te;
|
|
ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
|
|
- "saf_te %x\n",
|
|
- ioc->name,
|
|
- mpt_saf_te));
|
|
- ioc->spi_data.noQas = 0;
|
|
+ "saf_te %x\n", ioc->name, mpt_saf_te));
|
|
+ ioc->spi_data.noQas = mpt_qas ? 0 : MPT_TARGET_NO_NEGO_QAS;
|
|
|
|
hd->last_queue_full = 0;
|
|
hd->spi_pending = 0;
|
|
@@ -1528,7 +1506,7 @@ static struct pci_driver mptspi_driver =
|
|
* mptspi_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
|
|
*
|
|
* Returns 0 for success, non-zero for failure.
|
|
- */
|
|
+ **/
|
|
static int __init
|
|
mptspi_init(void)
|
|
{
|
|
@@ -1558,7 +1536,8 @@ mptspi_init(void)
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
/**
|
|
* mptspi_exit - Unregisters MPT adapter(s)
|
|
- */
|
|
+ *
|
|
+ **/
|
|
static void __exit
|
|
mptspi_exit(void)
|
|
{
|
|
@@ -1566,7 +1545,6 @@ mptspi_exit(void)
|
|
|
|
mpt_reset_deregister(mptspiDoneCtx);
|
|
mpt_event_deregister(mptspiDoneCtx);
|
|
-
|
|
mpt_deregister(mptspiInternalCtx);
|
|
mpt_deregister(mptspiTaskCtx);
|
|
mpt_deregister(mptspiDoneCtx);
|
|
--- /dev/null
|
|
+++ b/drivers/message/fusion/rejected_ioctls/diag_buffer.c
|
|
@@ -0,0 +1,671 @@
|
|
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
+/* REGISTER DIAG BUFFER Routine.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -EBUSY if previous command timout and IOC reset is not complete.
|
|
+ * -ENODEV if no such device/adapter
|
|
+ * -ETIME if timer expires
|
|
+ * -ENOMEM if memory allocation error
|
|
+ */
|
|
+static int
|
|
+mptctl_register_diag_buffer (unsigned long arg)
|
|
+{
|
|
+ mpt_diag_register_t __user *uarg = (void __user *) arg;
|
|
+ mpt_diag_register_t karg;
|
|
+ MPT_ADAPTER *ioc;
|
|
+ int iocnum, rc, ii;
|
|
+ void * request_data;
|
|
+ dma_addr_t request_data_dma;
|
|
+ u32 request_data_sz;
|
|
+ MPT_FRAME_HDR *mf;
|
|
+ DiagBufferPostRequest_t *diag_buffer_post_request;
|
|
+ DiagBufferPostReply_t *diag_buffer_post_reply;
|
|
+ u32 tmp;
|
|
+ u8 buffer_type;
|
|
+ unsigned long timeleft;
|
|
+
|
|
+ rc = 0;
|
|
+ if (copy_from_user(&karg, uarg, sizeof(mpt_diag_register_t))) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Unable to read in mpt_diag_register_t struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
+ (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s enter.\n", ioc->name,
|
|
+ __FUNCTION__));
|
|
+ buffer_type = karg.data.BufferType;
|
|
+ if (!(ioc->facts.IOCCapabilities & MPT_DIAG_CAPABILITY(buffer_type))) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: doesn't have Capability for "
|
|
+ "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if (ioc->DiagBuffer_Status[buffer_type] &
|
|
+ MPT_DIAG_BUFFER_IS_REGISTERED) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: already has a Registered "
|
|
+ "buffer for buffer_type=%x\n", ioc->name, __FUNCTION__,
|
|
+ buffer_type);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ /* Get a free request frame and save the message context.
|
|
+ */
|
|
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
|
|
+ return -EAGAIN;
|
|
+
|
|
+ request_data = ioc->DiagBuffer[buffer_type];
|
|
+ request_data_sz = karg.data.RequestedBufferSize;
|
|
+
|
|
+ if (request_data) {
|
|
+ request_data_dma = ioc->DiagBuffer_dma[buffer_type];
|
|
+ if (request_data_sz != ioc->DiagBuffer_sz[buffer_type]) {
|
|
+ pci_free_consistent(ioc->pcidev,
|
|
+ ioc->DiagBuffer_sz[buffer_type],
|
|
+ request_data, request_data_dma);
|
|
+ request_data = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (request_data == NULL) {
|
|
+ ioc->DiagBuffer_sz[buffer_type] = 0;
|
|
+ ioc->DiagBuffer_dma[buffer_type] = 0;
|
|
+ ioc->DataSize[buffer_type] = 0;
|
|
+ request_data = pci_alloc_consistent(
|
|
+ ioc->pcidev, request_data_sz, &request_data_dma);
|
|
+ if (request_data == NULL) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: pci_alloc_consistent"
|
|
+ " FAILED, (request_sz=%d)\n", ioc->name,
|
|
+ __FUNCTION__, request_data_sz);
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ return -EAGAIN;
|
|
+ }
|
|
+ ioc->DiagBuffer[buffer_type] = request_data;
|
|
+ ioc->DiagBuffer_sz[buffer_type] = request_data_sz;
|
|
+ ioc->DiagBuffer_dma[buffer_type] = request_data_dma;
|
|
+ }
|
|
+
|
|
+ ioc->DiagBuffer_Status[buffer_type] = 0;
|
|
+ diag_buffer_post_request = (DiagBufferPostRequest_t *)mf;
|
|
+ diag_buffer_post_request->Function = MPI_FUNCTION_DIAG_BUFFER_POST;
|
|
+ diag_buffer_post_request->ChainOffset = 0;
|
|
+ diag_buffer_post_request->BufferType = karg.data.BufferType;
|
|
+ diag_buffer_post_request->TraceLevel = ioc->TraceLevel[buffer_type] =
|
|
+ karg.data.TraceLevel;
|
|
+ diag_buffer_post_request->MsgFlags = 0;
|
|
+ diag_buffer_post_request->Reserved1 = 0;
|
|
+ diag_buffer_post_request->Reserved2 = 0;
|
|
+ diag_buffer_post_request->Reserved3 = 0;
|
|
+ diag_buffer_post_request->BufferAddress.High = 0;
|
|
+ if (buffer_type == MPI_DIAG_BUF_TYPE_EXTENDED)
|
|
+ ioc->ExtendedType[buffer_type] = karg.data.ExtendedType;
|
|
+ else
|
|
+ ioc->ExtendedType[buffer_type] = 0;
|
|
+ diag_buffer_post_request->ExtendedType =
|
|
+ cpu_to_le32(ioc->ExtendedType[buffer_type]);
|
|
+ ioc->UniqueId[buffer_type] = karg.data.UniqueId;
|
|
+ diag_buffer_post_request->BufferLength = cpu_to_le32(request_data_sz);
|
|
+ for (ii = 0; ii < 4; ii++) {
|
|
+ ioc->ProductSpecific[buffer_type][ii] =
|
|
+ karg.data.ProductSpecific[ii];
|
|
+ diag_buffer_post_request->ProductSpecific[ii] =
|
|
+ cpu_to_le32(ioc->ProductSpecific[buffer_type][ii]);
|
|
+ }
|
|
+
|
|
+ tmp = request_data_dma & 0xFFFFFFFF;
|
|
+ diag_buffer_post_request->BufferAddress.Low = cpu_to_le32(tmp);
|
|
+ if (ioc->sg_addr_size == sizeof(u64)) {
|
|
+ tmp = (u32)((u64)request_data_dma >> 32);
|
|
+ diag_buffer_post_request->BufferAddress.High = cpu_to_le32(tmp);
|
|
+ }
|
|
+
|
|
+ SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context,
|
|
+ diag_buffer_post_request->MsgContext);
|
|
+ INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
|
|
+ mpt_put_msg_frame(mptctl_id, ioc, mf);
|
|
+ timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
|
|
+ MPT_IOCTL_DEFAULT_TIMEOUT*HZ);
|
|
+ if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
+ rc = -ETIME;
|
|
+ printk(MYIOC_s_WARN_FMT "%s: failed\n", ioc->name,
|
|
+ __FUNCTION__);
|
|
+ if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ goto out;
|
|
+ }
|
|
+ if (!timeleft)
|
|
+ mptctl_timeout_expired(ioc, mf);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /* process the completed Reply Message Frame */
|
|
+ if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) == 0) {
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: status=%x\n",
|
|
+ ioc->name, __FUNCTION__, ioc->ioctl_cmds.status));
|
|
+ rc = -EFAULT;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ diag_buffer_post_reply = (DiagBufferPostReply_t *)ioc->ioctl_cmds.reply;
|
|
+ if (le16_to_cpu(diag_buffer_post_reply->IOCStatus) ==
|
|
+ MPI_IOCSTATUS_SUCCESS) {
|
|
+ if (diag_buffer_post_reply->MsgLength > 5)
|
|
+ ioc->DataSize[buffer_type] =
|
|
+ le32_to_cpu(diag_buffer_post_reply->TransferLength);
|
|
+ ioc->DiagBuffer_Status[buffer_type] |=
|
|
+ MPT_DIAG_BUFFER_IS_REGISTERED;
|
|
+ } else {
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: IOCStatus=%x "
|
|
+ "IOCLogInfo=%x\n", ioc->name, __FUNCTION__,
|
|
+ diag_buffer_post_reply->IOCStatus,
|
|
+ diag_buffer_post_reply->IOCLogInfo));
|
|
+ rc = -EFAULT;
|
|
+ }
|
|
+
|
|
+ out:
|
|
+
|
|
+ CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
|
|
+ SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
|
|
+ if (rc) {
|
|
+ pci_free_consistent(ioc->pcidev, request_data_sz,
|
|
+ request_data, request_data_dma);
|
|
+ ioc->DiagBuffer[buffer_type] = NULL;
|
|
+ ioc->DiagBuffer_sz[buffer_type] = 0;
|
|
+ ioc->DiagBuffer_dma[buffer_type] = 0;
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
+/* RELEASE DIAG BUFFER Routine.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -EBUSY if previous command timout and IOC reset is not complete.
|
|
+ * -ENODEV if no such device/adapter
|
|
+ * -ETIME if timer expires
|
|
+ * -ENOMEM if memory allocation error
|
|
+ */
|
|
+static int
|
|
+mptctl_release_diag_buffer (unsigned long arg)
|
|
+{
|
|
+ mpt_diag_release_t __user *uarg = (void __user *) arg;
|
|
+ mpt_diag_release_t karg;
|
|
+ MPT_ADAPTER *ioc;
|
|
+ void * request_data;
|
|
+ int iocnum, rc;
|
|
+ MPT_FRAME_HDR *mf;
|
|
+ DiagReleaseRequest_t *diag_release;
|
|
+ DiagReleaseReply_t *diag_release_reply;
|
|
+ u8 buffer_type;
|
|
+ unsigned long timeleft;
|
|
+
|
|
+ rc = 0;
|
|
+ if (copy_from_user(&karg, uarg, sizeof(mpt_diag_release_t))) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Unable to read in mpt_diag_release_t struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
+ (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s enter.\n", ioc->name,
|
|
+ __FUNCTION__));
|
|
+ buffer_type = karg.data.UniqueId & 0x000000ff;
|
|
+ if (!(ioc->facts.IOCCapabilities & MPT_DIAG_CAPABILITY(buffer_type))) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: doesn't have Capability for "
|
|
+ "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if ((ioc->DiagBuffer_Status[buffer_type] &
|
|
+ MPT_DIAG_BUFFER_IS_REGISTERED) == 0 ) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: buffer_type=%x is not "
|
|
+ "registered\n", ioc->name, __FUNCTION__, buffer_type);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (karg.data.UniqueId != ioc->UniqueId[buffer_type]) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: unique_id=%x is not registered\n",
|
|
+ ioc->name, __FUNCTION__, karg.data.UniqueId);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (ioc->DiagBuffer_Status[buffer_type] & MPT_DIAG_BUFFER_IS_RELEASED) {
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: buffer_type=%x "
|
|
+ "is already released\n", ioc->name, __FUNCTION__,
|
|
+ buffer_type));
|
|
+ return rc;
|
|
+ }
|
|
+
|
|
+ request_data = ioc->DiagBuffer[buffer_type];
|
|
+
|
|
+ if (request_data == NULL) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: doesn't have buffer for "
|
|
+ "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ /* Get a free request frame and save the message context.
|
|
+ */
|
|
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
|
|
+ return -EAGAIN;
|
|
+
|
|
+ diag_release = (DiagReleaseRequest_t *)mf;
|
|
+ diag_release->Function = MPI_FUNCTION_DIAG_RELEASE;
|
|
+ diag_release->BufferType = buffer_type;
|
|
+ diag_release->ChainOffset = 0;
|
|
+ diag_release->Reserved1 = 0;
|
|
+ diag_release->Reserved2 = 0;
|
|
+ diag_release->Reserved3 = 0;
|
|
+ diag_release->MsgFlags = 0;
|
|
+
|
|
+ SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context,
|
|
+ diag_release->MsgContext);
|
|
+ INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
|
|
+ mpt_put_msg_frame(mptctl_id, ioc, mf);
|
|
+ timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
|
|
+ MPT_IOCTL_DEFAULT_TIMEOUT*HZ);
|
|
+ if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
+ rc = -ETIME;
|
|
+ printk(MYIOC_s_WARN_FMT "%s: failed\n", ioc->name,
|
|
+ __FUNCTION__);
|
|
+ if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ goto out;
|
|
+ }
|
|
+ if (!timeleft)
|
|
+ mptctl_timeout_expired(ioc, mf);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /* process the completed Reply Message Frame */
|
|
+ if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) == 0) {
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: status=%x\n",
|
|
+ ioc->name, __FUNCTION__, ioc->ioctl_cmds.status));
|
|
+ rc = -EFAULT;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ diag_release_reply = (DiagReleaseReply_t *)ioc->ioctl_cmds.reply;
|
|
+ if (le16_to_cpu(diag_release_reply->IOCStatus) !=
|
|
+ MPI_IOCSTATUS_SUCCESS) {
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: IOCStatus=%x "
|
|
+ "IOCLogInfo=%x\n",
|
|
+ ioc->name, __FUNCTION__, diag_release_reply->IOCStatus,
|
|
+ diag_release_reply->IOCLogInfo));
|
|
+ rc = -EFAULT;
|
|
+ } else
|
|
+ ioc->DiagBuffer_Status[buffer_type] |=
|
|
+ MPT_DIAG_BUFFER_IS_RELEASED;
|
|
+
|
|
+ out:
|
|
+
|
|
+ CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
|
|
+ SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
+/* UNREGISTER DIAG BUFFER Routine.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -EBUSY if previous command timout and IOC reset is not complete.
|
|
+ * -ENODEV if no such device/adapter
|
|
+ * -ETIME if timer expires
|
|
+ * -ENOMEM if memory allocation error
|
|
+ */
|
|
+static int
|
|
+mptctl_unregister_diag_buffer (unsigned long arg)
|
|
+{
|
|
+ mpt_diag_unregister_t __user *uarg = (void __user *) arg;
|
|
+ mpt_diag_unregister_t karg;
|
|
+ MPT_ADAPTER *ioc;
|
|
+ int iocnum;
|
|
+ void * request_data;
|
|
+ dma_addr_t request_data_dma;
|
|
+ u32 request_data_sz;
|
|
+ u8 buffer_type;
|
|
+
|
|
+ if (copy_from_user(&karg, uarg, sizeof(mpt_diag_unregister_t))) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Unable to read in mpt_diag_unregister_t struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
+ (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s enter.\n", ioc->name,
|
|
+ __FUNCTION__));
|
|
+ buffer_type = karg.data.UniqueId & 0x000000ff;
|
|
+ if (!(ioc->facts.IOCCapabilities & MPT_DIAG_CAPABILITY(buffer_type))) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: doesn't have Capability for "
|
|
+ "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ if ((ioc->DiagBuffer_Status[buffer_type] &
|
|
+ MPT_DIAG_BUFFER_IS_REGISTERED) == 0) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: buffer_type=%x is not "
|
|
+ "registered\n", ioc->name, __FUNCTION__, buffer_type);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ if ((ioc->DiagBuffer_Status[buffer_type] &
|
|
+ MPT_DIAG_BUFFER_IS_RELEASED) == 0) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: buffer_type=%x has not been "
|
|
+ "released\n", ioc->name, __FUNCTION__, buffer_type);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (karg.data.UniqueId != ioc->UniqueId[buffer_type]) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: unique_id=%x is not registered\n",
|
|
+ ioc->name, __FUNCTION__, karg.data.UniqueId);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ request_data = ioc->DiagBuffer[buffer_type];
|
|
+ if (!request_data) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: doesn't have buffer for "
|
|
+ "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ request_data_sz = ioc->DiagBuffer_sz[buffer_type];
|
|
+ request_data_dma = ioc->DiagBuffer_dma[buffer_type];
|
|
+ pci_free_consistent(ioc->pcidev, request_data_sz,
|
|
+ request_data, request_data_dma);
|
|
+ ioc->DiagBuffer[buffer_type] = NULL;
|
|
+ ioc->DiagBuffer_Status[buffer_type] = 0;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
+/* QUERY DIAG BUFFER Routine.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -EBUSY if previous command timout and IOC reset is not complete.
|
|
+ * -ENODEV if no such device/adapter
|
|
+ * -ETIME if timer expires
|
|
+ * -ENOMEM if memory allocation error
|
|
+ */
|
|
+static int
|
|
+mptctl_query_diag_buffer (unsigned long arg)
|
|
+{
|
|
+ mpt_diag_query_t __user *uarg = (void __user *)arg;
|
|
+ mpt_diag_query_t karg;
|
|
+ MPT_ADAPTER *ioc;
|
|
+ void * request_data;
|
|
+ int iocnum, ii, rc;
|
|
+ u8 buffer_type;
|
|
+
|
|
+ rc = -EFAULT;
|
|
+ if (copy_from_user(&karg, uarg, sizeof(mpt_diag_query_t))) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Unable to read in mpt_diag_query_t struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ karg.data.Flags = 0;
|
|
+ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
+ (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s enter.\n", ioc->name,
|
|
+ __FUNCTION__));
|
|
+ buffer_type = karg.data.BufferType;
|
|
+ if (!(ioc->facts.IOCCapabilities & MPT_DIAG_CAPABILITY(buffer_type))) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: doesn't have Capability for "
|
|
+ "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if ((ioc->DiagBuffer_Status[buffer_type] &
|
|
+ MPT_DIAG_BUFFER_IS_REGISTERED) == 0) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: buffer_type=%x is not "
|
|
+ "registered\n", ioc->name, __FUNCTION__, buffer_type);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (karg.data.UniqueId & 0xffffff00) {
|
|
+ if (karg.data.UniqueId != ioc->UniqueId[buffer_type]) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: unique_id=%x is not "
|
|
+ "registered\n", ioc->name, __FUNCTION__,
|
|
+ karg.data.UniqueId);
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ request_data = ioc->DiagBuffer[buffer_type];
|
|
+ if (!request_data) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: doesn't have buffer for "
|
|
+ "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ rc = 0;
|
|
+ if (buffer_type == MPI_DIAG_BUF_TYPE_EXTENDED) {
|
|
+ if (karg.data.ExtendedType != ioc->ExtendedType[buffer_type])
|
|
+ goto out;
|
|
+ } else
|
|
+ karg.data.ExtendedType = 0;
|
|
+
|
|
+ if (ioc->DiagBuffer_Status[buffer_type] & MPT_DIAG_BUFFER_IS_RELEASED)
|
|
+ karg.data.Flags = 3;
|
|
+ else
|
|
+ karg.data.Flags = 7;
|
|
+ karg.data.TraceLevel = ioc->TraceLevel[buffer_type];
|
|
+ for (ii = 0; ii < 4; ii++)
|
|
+ karg.data.ProductSpecific[ii] =
|
|
+ ioc->ProductSpecific[buffer_type][ii];
|
|
+ karg.data.DataSize = ioc->DiagBuffer_sz[buffer_type];
|
|
+ karg.data.DriverAddedBufferSize = 0;
|
|
+ karg.data.UniqueId = ioc->UniqueId[buffer_type];
|
|
+
|
|
+ out:
|
|
+ if (copy_to_user(uarg, &karg, sizeof(mpt_diag_query_t))) {
|
|
+ printk(MYIOC_s_ERR_FMT "%s Unable to write mpt_diag_query_t "
|
|
+ "data @ %p\n", ioc->name, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
|
|
+/* READ DIAG BUFFER Routine.
|
|
+ *
|
|
+ * Outputs: None.
|
|
+ * Return: 0 if successful
|
|
+ * -EFAULT if data unavailable
|
|
+ * -EBUSY if previous command timout and IOC reset is not complete.
|
|
+ * -ENODEV if no such device/adapter
|
|
+ * -ETIME if timer expires
|
|
+ * -ENOMEM if memory allocation error
|
|
+ */
|
|
+static int
|
|
+mptctl_read_diag_buffer (unsigned long arg)
|
|
+{
|
|
+ mpt_diag_read_buffer_t __user *uarg = (void __user *) arg;
|
|
+ mpt_diag_read_buffer_t karg;
|
|
+ MPT_ADAPTER *ioc;
|
|
+ void *request_data, *diagData;
|
|
+ dma_addr_t request_data_dma;
|
|
+ DiagBufferPostRequest_t *diag_buffer_post_request;
|
|
+ DiagBufferPostReply_t *diag_buffer_post_reply;
|
|
+ MPT_FRAME_HDR *mf;
|
|
+ int iocnum, rc, ii;
|
|
+ u8 buffer_type;
|
|
+ u32 tmp;
|
|
+ unsigned long timeleft;
|
|
+
|
|
+ rc = 0;
|
|
+ if (copy_from_user(&karg, uarg, sizeof(mpt_diag_read_buffer_t))) {
|
|
+ printk(KERN_ERR "%s@%d::%s - "
|
|
+ "Unable to read in mpt_diag_read_buffer_t struct @ %p\n",
|
|
+ __FILE__, __LINE__, __FUNCTION__, uarg);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
|
|
+ (ioc == NULL)) {
|
|
+ printk(KERN_ERR "%s::%s() @%d - ioc%d not found!\n",
|
|
+ __FILE__, __FUNCTION__, __LINE__, iocnum);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s enter.\n", ioc->name,
|
|
+ __FUNCTION__));
|
|
+ buffer_type = karg.data.UniqueId & 0x000000ff;
|
|
+ if (!(ioc->facts.IOCCapabilities & MPT_DIAG_CAPABILITY(buffer_type))) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: doesn't have Capability "
|
|
+ "for buffer_type=%x\n", ioc->name, __FUNCTION__,
|
|
+ buffer_type);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (karg.data.UniqueId != ioc->UniqueId[buffer_type]) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: unique_id=%x is not registered\n",
|
|
+ ioc->name, __FUNCTION__, karg.data.UniqueId);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ request_data = ioc->DiagBuffer[buffer_type];
|
|
+ if (!request_data) {
|
|
+ printk(MYIOC_s_DEBUG_FMT "%s: doesn't have buffer for "
|
|
+ "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ diagData = (void *)(request_data + karg.data.StartingOffset);
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: diagData=%p "
|
|
+ "request_data=%p StartingOffset=%x\n", ioc->name, __FUNCTION__,
|
|
+ diagData, request_data, karg.data.StartingOffset));
|
|
+
|
|
+ if (copy_to_user((void __user *)&uarg->data.DiagnosticData[0],
|
|
+ diagData, karg.data.BytesToRead)) {
|
|
+ printk(MYIOC_s_ERR_FMT "%s: Unable to write "
|
|
+ "mpt_diag_read_buffer_t data @ %p\n", ioc->name,
|
|
+ __FUNCTION__, diagData);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
+ if ((karg.data.Flags & MPI_FW_DIAG_FLAG_REREGISTER) == 0)
|
|
+ goto out;
|
|
+
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: Reregister "
|
|
+ "buffer_type=%x\n", ioc->name, __FUNCTION__, buffer_type));
|
|
+ if ((ioc->DiagBuffer_Status[buffer_type] &
|
|
+ MPT_DIAG_BUFFER_IS_RELEASED) == 0) {
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: buffer_type=%x "
|
|
+ "is still registered\n", ioc->name, __FUNCTION__,
|
|
+ buffer_type));
|
|
+ return rc;
|
|
+ }
|
|
+ /* Get a free request frame and save the message context.
|
|
+ */
|
|
+ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL)
|
|
+ return -EAGAIN;
|
|
+
|
|
+ diag_buffer_post_request = (DiagBufferPostRequest_t *)mf;
|
|
+ diag_buffer_post_request->Function = MPI_FUNCTION_DIAG_BUFFER_POST;
|
|
+ diag_buffer_post_request->ChainOffset = 0;
|
|
+ diag_buffer_post_request->BufferType = buffer_type;
|
|
+ diag_buffer_post_request->TraceLevel =
|
|
+ ioc->TraceLevel[buffer_type];
|
|
+ diag_buffer_post_request->MsgFlags = 0;
|
|
+ diag_buffer_post_request->Reserved1 = 0;
|
|
+ diag_buffer_post_request->Reserved2 = 0;
|
|
+ diag_buffer_post_request->Reserved3 = 0;
|
|
+ diag_buffer_post_request->BufferAddress.High = 0;
|
|
+ if ( buffer_type == MPI_DIAG_BUF_TYPE_EXTENDED )
|
|
+ diag_buffer_post_request->ExtendedType =
|
|
+ cpu_to_le32(ioc->ExtendedType[buffer_type]);
|
|
+ diag_buffer_post_request->BufferLength =
|
|
+ cpu_to_le32(ioc->DiagBuffer_sz[buffer_type]);
|
|
+ for (ii = 0; ii < 4; ii++)
|
|
+ diag_buffer_post_request->ProductSpecific[ii] =
|
|
+ cpu_to_le32(ioc->ProductSpecific[buffer_type][ii]);
|
|
+ request_data_dma = ioc->DiagBuffer_dma[buffer_type];
|
|
+ tmp = request_data_dma & 0xFFFFFFFF;
|
|
+ diag_buffer_post_request->BufferAddress.Low = cpu_to_le32(tmp);
|
|
+ if (ioc->sg_addr_size == sizeof(u64)) {
|
|
+ tmp = (u32)((u64)request_data_dma >> 32);
|
|
+ diag_buffer_post_request->BufferAddress.High = cpu_to_le32(tmp);
|
|
+ }
|
|
+
|
|
+ SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context,
|
|
+ diag_buffer_post_request->MsgContext);
|
|
+ INITIALIZE_MGMT_STATUS(ioc->ioctl_cmds.status)
|
|
+ mpt_put_msg_frame(mptctl_id, ioc, mf);
|
|
+ timeleft = wait_for_completion_timeout(&ioc->ioctl_cmds.done,
|
|
+ MPT_IOCTL_DEFAULT_TIMEOUT*HZ);
|
|
+ if (!(ioc->ioctl_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
|
|
+ rc = -ETIME;
|
|
+ printk(MYIOC_s_WARN_FMT "%s: failed\n", ioc->name,
|
|
+ __FUNCTION__);
|
|
+ if (ioc->ioctl_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
|
|
+ mpt_free_msg_frame(ioc, mf);
|
|
+ goto out;
|
|
+ }
|
|
+ if (!timeleft)
|
|
+ mptctl_timeout_expired(ioc, mf);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /* process the completed Reply Message Frame */
|
|
+ if ((ioc->ioctl_cmds.status & MPT_MGMT_STATUS_RF_VALID) == 0) {
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: status=%x\n",
|
|
+ ioc->name, __FUNCTION__, ioc->ioctl_cmds.status));
|
|
+ rc = -EFAULT;
|
|
+ }
|
|
+
|
|
+ diag_buffer_post_reply = (DiagBufferPostReply_t *)ioc->ioctl_cmds.reply;
|
|
+ if (le16_to_cpu(diag_buffer_post_reply->IOCStatus) ==
|
|
+ MPI_IOCSTATUS_SUCCESS) {
|
|
+ if (diag_buffer_post_reply->MsgLength > 5)
|
|
+ ioc->DataSize[buffer_type] =
|
|
+ le32_to_cpu(diag_buffer_post_reply->TransferLength);
|
|
+ ioc->DiagBuffer_Status[buffer_type] |=
|
|
+ MPT_DIAG_BUFFER_IS_REGISTERED;
|
|
+ } else {
|
|
+ dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: IOCStatus=%x "
|
|
+ "IOCLogInfo=%x\n", ioc->name, __FUNCTION__,
|
|
+ diag_buffer_post_reply->IOCStatus,
|
|
+ diag_buffer_post_reply->IOCLogInfo));
|
|
+ rc = -EFAULT;
|
|
+ }
|
|
+
|
|
+ out:
|
|
+ CLEAR_MGMT_STATUS(ioc->ioctl_cmds.status)
|
|
+ SET_MGMT_MSG_CONTEXT(ioc->ioctl_cmds.msg_context, 0);
|
|
+ return rc;
|
|
+}
|
|
--- /dev/null
|
|
+++ b/drivers/message/fusion/rejected_ioctls/diag_buffer.h
|
|
@@ -0,0 +1,101 @@
|
|
+#define MPTDIAGREGISTER _IOWR(MPT_MAGIC_NUMBER,26,mpt_diag_register_t)
|
|
+#define MPTDIAGRELEASE _IOWR(MPT_MAGIC_NUMBER,27,mpt_diag_release_t)
|
|
+#define MPTDIAGUNREGISTER _IOWR(MPT_MAGIC_NUMBER,28,mpt_diag_unregister_t)
|
|
+#define MPTDIAGQUERY _IOWR(MPT_MAGIC_NUMBER,29,mpt_diag_query_t)
|
|
+#define MPTDIAGREADBUFFER _IOWR(MPT_MAGIC_NUMBER,30,mpt_diag_read_buffer_t)
|
|
+
|
|
+#define MPI_FW_DIAG_IOCTL (0x80646961)
|
|
+#define MPI_FW_DIAG_TYPE_REGISTER (0x00000001)
|
|
+#define MPI_FW_DIAG_TYPE_UNREGISTER (0x00000002)
|
|
+#define MPI_FW_DIAG_TYPE_QUERY (0x00000003)
|
|
+#define MPI_FW_DIAG_TYPE_READ_BUFFER (0x00000004)
|
|
+#define MPI_FW_DIAG_TYPE_RELEASE (0x00000005)
|
|
+
|
|
+#define MPI_FW_DIAG_INVALID_UID (0x00000000)
|
|
+#define FW_DIAGNOSTIC_BUFFER_COUNT (3)
|
|
+#define FW_DIAGNOSTIC_UID_NOT_FOUND (0xFF)
|
|
+
|
|
+#define MPI_FW_DIAG_ERROR_SUCCESS (0x00000000)
|
|
+#define MPI_FW_DIAG_ERROR_FAILURE (0x00000001)
|
|
+#define MPI_FW_DIAG_ERROR_INVALID_PARAMETER (0x00000002)
|
|
+#define MPI_FW_DIAG_ERROR_POST_FAILED (0x00000010)
|
|
+#define MPI_FW_DIAG_ERROR_INVALID_UID (0x00000011)
|
|
+
|
|
+#define MPI_FW_DIAG_ERROR_RELEASE_FAILED (0x00000012)
|
|
+#define MPI_FW_DIAG_ERROR_NO_BUFFER (0x00000013)
|
|
+#define MPI_FW_DIAG_ERROR_ALREADY_RELEASED (0x00000014)
|
|
+
|
|
+#define MPT_DIAG_CAPABILITY(bufftype) (MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER << bufftype)
|
|
+
|
|
+#define MPT_DIAG_BUFFER_IS_REGISTERED 1
|
|
+#define MPT_DIAG_BUFFER_IS_RELEASED 2
|
|
+
|
|
+typedef struct _MPI_FW_DIAG_REGISTER {
|
|
+ u8 TraceLevel;
|
|
+ u8 BufferType;
|
|
+ u16 Flags;
|
|
+ u32 ExtendedType;
|
|
+ u32 ProductSpecific[4];
|
|
+ u32 RequestedBufferSize;
|
|
+ u32 UniqueId;
|
|
+} MPI_FW_DIAG_REGISTER, *PTR_MPI_FW_DIAG_REGISTER;
|
|
+
|
|
+typedef struct _mpt_diag_register {
|
|
+ mpt_ioctl_header hdr;
|
|
+ MPI_FW_DIAG_REGISTER data;
|
|
+} mpt_diag_register_t;
|
|
+
|
|
+typedef struct _MPI_FW_DIAG_UNREGISTER {
|
|
+ u32 UniqueId;
|
|
+} MPI_FW_DIAG_UNREGISTER, *PTR_MPI_FW_DIAG_UNREGISTER;
|
|
+
|
|
+typedef struct _mpt_diag_unregister {
|
|
+ mpt_ioctl_header hdr;
|
|
+ MPI_FW_DIAG_UNREGISTER data;
|
|
+} mpt_diag_unregister_t;
|
|
+
|
|
+#define MPI_FW_DIAG_FLAG_APP_OWNED (0x0001)
|
|
+#define MPI_FW_DIAG_FLAG_BUFFER_VALID (0x0002)
|
|
+#define MPI_FW_DIAG_FLAG_FW_BUFFER_ACCESS (0x0004)
|
|
+
|
|
+typedef struct _MPI_FW_DIAG_QUERY {
|
|
+ u8 TraceLevel;
|
|
+ u8 BufferType;
|
|
+ u16 Flags;
|
|
+ u32 ExtendedType;
|
|
+ u32 ProductSpecific[4];
|
|
+ u32 DataSize;
|
|
+ u32 DriverAddedBufferSize;
|
|
+ u32 UniqueId;
|
|
+} MPI_FW_DIAG_QUERY, *PTR_MPI_FW_DIAG_QUERY;
|
|
+
|
|
+typedef struct _mpt_diag_query {
|
|
+ mpt_ioctl_header hdr;
|
|
+ MPI_FW_DIAG_QUERY data;
|
|
+} mpt_diag_query_t;
|
|
+
|
|
+typedef struct _MPI_FW_DIAG_RELEASE {
|
|
+ u32 UniqueId;
|
|
+} MPI_FW_DIAG_RELEASE, *PTR_MPI_FW_DIAG_RELEASE;
|
|
+
|
|
+typedef struct _mpt_diag_release {
|
|
+ mpt_ioctl_header hdr;
|
|
+ MPI_FW_DIAG_RELEASE data;
|
|
+} mpt_diag_release_t;
|
|
+
|
|
+#define MPI_FW_DIAG_FLAG_REREGISTER (0x0001)
|
|
+
|
|
+typedef struct _MPI_FW_DIAG_READ_BUFFER {
|
|
+ u8 Status;
|
|
+ u8 Reserved;
|
|
+ u16 Flags;
|
|
+ u32 StartingOffset;
|
|
+ u32 BytesToRead;
|
|
+ u32 UniqueId;
|
|
+ u32 DiagnosticData[1];
|
|
+} MPI_FW_DIAG_READ_BUFFER, *PTR_MPI_FW_DIAG_READ_BUFFER;
|
|
+
|
|
+typedef struct _mpt_diag_read_buffer {
|
|
+ mpt_ioctl_header hdr;
|
|
+ MPI_FW_DIAG_READ_BUFFER data;
|
|
+} mpt_diag_read_buffer_t;
|