isci: Intel(R) C600 Series Chipset Storage Control Unit Driver
Support for the up to 2x4-port 6Gb/s SAS controllers embedded in the chipset. This is a snapshot of the first publicly available version of the driver, commit 4c1db2d0 in the 'historical' branch. git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git historical Signed-off-by: Maciej Trela <maciej.trela@intel.com> Signed-off-by: Dave Jiang <dave.jiang@intel.com> Signed-off-by: Edmund Nadolski <edmund.nadolski@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
@@ -830,6 +830,40 @@ config SCSI_GDTH
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called gdth.
|
||||
|
||||
config SCSI_ISCI
|
||||
tristate "Intel(R) C600 Series Chipset SAS Controller"
|
||||
depends on PCI && SCSI
|
||||
# little endian host assumptions
|
||||
depends on X86
|
||||
# (temporary): dma api misuse
|
||||
depends on !DMAR
|
||||
# (temporary): known alpha quality driver
|
||||
depends on EXPERIMENTAL
|
||||
select SCSI_SAS_LIBSAS
|
||||
---help---
|
||||
This driver supports the 6Gb/s SAS capabilities of the storage
|
||||
control unit found in the Intel(R) C600 series chipset.
|
||||
|
||||
The experimental tag will be removed after the driver exits alpha
|
||||
|
||||
choice
|
||||
prompt "Default Silicon Revision"
|
||||
depends on SCSI_ISCI
|
||||
default PBG_HBA_A2
|
||||
# temporary A-step silicon is pre-production
|
||||
|
||||
config PBG_HBA_BETA
|
||||
bool "B0"
|
||||
|
||||
config PBG_HBA_A2
|
||||
bool "A2"
|
||||
|
||||
config PBG_HBA_A0
|
||||
bool "A0"
|
||||
|
||||
endchoice
|
||||
|
||||
|
||||
config SCSI_GENERIC_NCR5380
|
||||
tristate "Generic NCR5380/53c400 SCSI PIO support"
|
||||
depends on ISA && SCSI
|
||||
|
||||
@@ -73,6 +73,7 @@ obj-$(CONFIG_SCSI_AACRAID) += aacraid/
|
||||
obj-$(CONFIG_SCSI_AIC7XXX_OLD) += aic7xxx_old.o
|
||||
obj-$(CONFIG_SCSI_AIC94XX) += aic94xx/
|
||||
obj-$(CONFIG_SCSI_PM8001) += pm8001/
|
||||
obj-$(CONFIG_SCSI_ISCI) += isci/
|
||||
obj-$(CONFIG_SCSI_IPS) += ips.o
|
||||
obj-$(CONFIG_SCSI_FD_MCS) += fd_mcs.o
|
||||
obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o
|
||||
|
||||
30
drivers/scsi/isci/Makefile
Normal file
30
drivers/scsi/isci/Makefile
Normal file
@@ -0,0 +1,30 @@
|
||||
#TODO kill SCIC_SDS_4_ENABLED it is always true for this
|
||||
#generation of silicon
|
||||
EXTRA_CFLAGS += -DSCIC_SDS_4_ENABLED
|
||||
|
||||
#temporary until atapi support ready
|
||||
EXTRA_CFLAGS += -DDISABLE_ATAPI
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/scsi/isci/core/ -Idrivers/scsi/isci/
|
||||
obj-$(CONFIG_SCSI_ISCI) += isci.o
|
||||
isci-objs := init.o phy.o request.o sata.o \
|
||||
remote_device.o port.o timers.o deprecated.o \
|
||||
host.o task.o events.o \
|
||||
core/scic_sds_controller.o \
|
||||
core/scic_sds_remote_device.o \
|
||||
core/scic_sds_request.o \
|
||||
core/scic_sds_stp_request.o \
|
||||
core/scic_sds_stp_packet_request.o \
|
||||
core/scic_sds_stp_remote_device.o \
|
||||
core/scic_sds_port.o \
|
||||
core/scic_sds_port_configuration_agent.o \
|
||||
core/scic_sds_phy.o \
|
||||
core/scic_sds_ssp_request.o \
|
||||
core/scic_sds_remote_node_context.o \
|
||||
core/scic_sds_smp_request.o \
|
||||
core/scic_sds_smp_remote_device.o \
|
||||
core/scic_sds_remote_node_table.o \
|
||||
core/scic_sds_unsolicited_frame_control.o \
|
||||
core/sci_base_memory_descriptor_list.o \
|
||||
core/sci_base_state_machine.o \
|
||||
core/sci_util.o
|
||||
554
drivers/scsi/isci/core/intel_ata.h
Normal file
554
drivers/scsi/isci/core/intel_ata.h
Normal file
@@ -0,0 +1,554 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file defines all of the ATA related constants, enumerations, and types.
|
||||
* Please note that this file does not necessarily contain an exhaustive
|
||||
* list of all constants, commands, sub-commands, etc.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ATA_H_
|
||||
#define _ATA_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATA_COMMAND_CODES These constants depict the various ATA command codes
|
||||
* defined in the ATA/ATAPI specification.
|
||||
*/
|
||||
#define ATA_IDENTIFY_DEVICE 0xEC
|
||||
#define ATA_CHECK_POWER_MODE 0xE5
|
||||
#define ATA_STANDBY 0xE2
|
||||
#define ATA_STANDBY_IMMED 0xE0
|
||||
#define ATA_IDLE_IMMED 0xE1
|
||||
#define ATA_IDLE 0xE3
|
||||
#define ATA_FLUSH_CACHE 0xE7
|
||||
#define ATA_FLUSH_CACHE_EXT 0xEA
|
||||
#define ATA_READ_DMA_EXT 0x25
|
||||
#define ATA_READ_DMA 0xC8
|
||||
#define ATA_READ_SECTORS_EXT 0x24
|
||||
#define ATA_READ_SECTORS 0x20
|
||||
#define ATA_WRITE_DMA_EXT 0x35
|
||||
#define ATA_WRITE_DMA 0xCA
|
||||
#define ATA_WRITE_SECTORS_EXT 0x34
|
||||
#define ATA_WRITE_SECTORS 0x30
|
||||
#define ATA_WRITE_UNCORRECTABLE 0x45
|
||||
#define ATA_READ_VERIFY_SECTORS 0x40
|
||||
#define ATA_READ_VERIFY_SECTORS_EXT 0x42
|
||||
#define ATA_READ_BUFFER 0xE4
|
||||
#define ATA_WRITE_BUFFER 0xE8
|
||||
#define ATA_EXECUTE_DEVICE_DIAG 0x90
|
||||
#define ATA_SET_FEATURES 0xEF
|
||||
#define ATA_SMART 0xB0
|
||||
#define ATA_PACKET_IDENTIFY 0xA1
|
||||
#define ATA_PACKET 0xA0
|
||||
#define ATA_READ_FPDMA 0x60
|
||||
#define ATA_WRITE_FPDMA 0x61
|
||||
#define ATA_READ_LOG_EXT 0x2F
|
||||
#define ATA_NOP 0x00
|
||||
#define ATA_DEVICE_RESET 0x08
|
||||
#define ATA_MEDIA_EJECT 0xED
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATA_SMART_SUB_COMMAND_CODES These constants define the ATA SMART command
|
||||
* sub-codes that can be executed.
|
||||
*/
|
||||
#define ATA_SMART_SUB_CMD_ENABLE 0xD8
|
||||
#define ATA_SMART_SUB_CMD_DISABLE 0xD9
|
||||
#define ATA_SMART_SUB_CMD_RETURN_STATUS 0xDA
|
||||
#define ATA_SMART_SUB_CMD_READ_LOG 0xD5
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATA_SET_FEATURES_SUB_COMMAND_CODES These constants define the ATA SET
|
||||
* FEATURES command sub-codes that can be executed.
|
||||
*/
|
||||
#define ATA_SET_FEATURES_SUB_CMD_ENABLE_CACHE 0x02
|
||||
#define ATA_SET_FEATURES_SUB_CMD_DISABLE_CACHE 0x82
|
||||
#define ATA_SET_FEATURES_SUB_CMD_DISABLE_READ_AHEAD 0x55
|
||||
#define ATA_SET_FEATURES_SUB_CMD_ENABLE_READ_AHEAD 0xAA
|
||||
#define ATA_SET_FEATURES_SUB_CMD_SET_TRANSFER_MODE 0x3
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATA_READ_LOG_EXT_PAGE_CODES This is a list of log page codes available for
|
||||
* use.
|
||||
*/
|
||||
#define ATA_LOG_PAGE_NCQ_ERROR 0x10
|
||||
#define ATA_LOG_PAGE_SMART_SELF_TEST 0x06
|
||||
#define ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST 0x07
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATA_LOG_PAGE_NCQ_ERROR_CONSTANTS These constants define standard values for
|
||||
* use when requesting the NCQ error log page.
|
||||
*/
|
||||
#define ATA_LOG_PAGE_NCQ_ERROR_SECTOR 0
|
||||
#define ATA_LOG_PAGE_NCQ_ERROR_SECTOR_COUNT 1
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATA_STATUS_REGISTER_BITS The following are status register bit definitions
|
||||
* per ATA/ATAPI-7.
|
||||
*/
|
||||
#define ATA_STATUS_REG_BSY_BIT 0x80
|
||||
#define ATA_STATUS_REG_DEVICE_FAULT_BIT 0x20
|
||||
#define ATA_STATUS_REG_ERROR_BIT 0x01
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATA_ERROR_REGISTER_BITS The following are error register bit definitions per
|
||||
* ATA/ATAPI-7.
|
||||
*/
|
||||
#define ATA_ERROR_REG_NO_MEDIA_BIT 0x02
|
||||
#define ATA_ERROR_REG_ABORT_BIT 0x04
|
||||
#define ATA_ERROR_REG_MEDIA_CHANGE_REQUEST_BIT 0x08
|
||||
#define ATA_ERROR_REG_ID_NOT_FOUND_BIT 0x10
|
||||
#define ATA_ERROR_REG_MEDIA_CHANGE_BIT 0x20
|
||||
#define ATA_ERROR_REG_UNCORRECTABLE_BIT 0x40
|
||||
#define ATA_ERROR_REG_WRITE_PROTECTED_BIT 0x40
|
||||
#define ATA_ERROR_REG_ICRC_BIT 0x80
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATA_CONTROL_REGISTER_BITS The following are control register bit definitions
|
||||
* per ATA/ATAPI-7
|
||||
*/
|
||||
#define ATA_CONTROL_REG_INTERRUPT_ENABLE_BIT 0x02
|
||||
#define ATA_CONTROL_REG_SOFT_RESET_BIT 0x04
|
||||
#define ATA_CONTROL_REG_HIGH_ORDER_BYTE_BIT 0x80
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATA_DEVICE_HEAD_REGISTER_BITS The following are device/head register bit
|
||||
* definitions per ATA/ATAPI-7.
|
||||
*/
|
||||
#define ATA_DEV_HEAD_REG_LBA_MODE_ENABLE 0x40
|
||||
#define ATA_DEV_HEAD_REG_FUA_ENABLE 0x80
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATA_IDENTIFY_DEVICE_FIELD_LENGTHS The following constants define the number
|
||||
* of bytes contained in various fields found in the IDENTIFY DEVICE data
|
||||
* structure.
|
||||
*/
|
||||
#define ATA_IDENTIFY_SERIAL_NUMBER_LEN 20
|
||||
#define ATA_IDENTIFY_MODEL_NUMBER_LEN 40
|
||||
#define ATA_IDENTIFY_FW_REVISION_LEN 8
|
||||
#define ATA_IDENTIFY_48_LBA_LEN 8
|
||||
#define ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN 30
|
||||
#define ATA_IDENTIFY_WWN_LEN 8
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATA_IDENTIFY_DEVICE_FIELD_MASKS The following constants define bit masks
|
||||
* utilized to determine if a feature is supported/enabled or if a bit is
|
||||
* simply set inside of the IDENTIFY DEVICE data structre.
|
||||
*/
|
||||
#define ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE 0x0080
|
||||
#define ATA_IDENTIFY_CAPABILITIES1_NORMAL_DMA_ENABLE 0x0100
|
||||
#define ATA_IDENTIFY_CAPABILITIES1_STANDBY_ENABLE 0x2000
|
||||
#define ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE 0x0001
|
||||
#define ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE 0x0400
|
||||
#define ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE 0x0100
|
||||
#define ATA_IDENTIFY_COMMAND_SET_ENABLED0_SMART_ENABLE 0x0001
|
||||
#define ATA_IDENTIFY_SATA_CAPABILITIES_NCQ_ENABLE 0x0100
|
||||
#define ATA_IDENTIFY_NCQ_QUEUE_DEPTH_ENABLE 0x001F
|
||||
#define ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE 0x0100
|
||||
#define ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_MASK 0x000F
|
||||
#define ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_ENABLE 0x2000
|
||||
#define ATA_IDENTIFY_WRITE_UNCORRECTABLE_SUPPORT 0x0004
|
||||
#define ATA_IDENTIFY_COMMAND_SET_SMART_SELF_TEST_SUPPORTED 0x0002
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATAPI_IDENTIFY_DEVICE_FIELD_MASKS These constants define the various bit
|
||||
* definitions for the fields in the PACKET IDENTIFY DEVICE data structure.
|
||||
*/
|
||||
#define ATAPI_IDENTIFY_16BYTE_CMD_PCKT_ENABLE 0x01
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATA_PACKET_FEATURE_BITS These constants define the various bit definitions
|
||||
* for the ATA PACKET feature register.
|
||||
*/
|
||||
#define ATA_PACKET_FEATURE_DMA 0x01
|
||||
#define ATA_PACKET_FEATURE_OVL 0x02
|
||||
#define ATA_PACKET_FEATURE_DMADIR 0x04
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATA_Device_Power_Mode_Values These constants define the power mode values
|
||||
* returned by ATA_Check_Power_Mode
|
||||
*/
|
||||
#define ATA_STANDBY_POWER_MODE 0x00
|
||||
#define ATA_IDLE_POWER_MODE 0x80
|
||||
#define ATA_ACTIVE_POWER_MODE 0xFF
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ATA_WRITE_UNCORRECTIABLE feature field values These constants define the
|
||||
* Write Uncorrectable feature values used with the SATI translation.
|
||||
*/
|
||||
#define ATA_WRITE_UNCORRECTABLE_PSUEDO 0x55
|
||||
#define ATA_WRITE_UNCORRECTABLE_FLAGGED 0xAA
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* struct ATA_IDENTIFY_DEVICE - This structure depicts the ATA IDENTIFY DEVICE
|
||||
* data format.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct ata_identify_device_data {
|
||||
u16 general_config_bits; /* word 00 */
|
||||
u16 obsolete0; /* word 01 (num cylinders) */
|
||||
u16 vendor_specific_config_bits; /* word 02 */
|
||||
u16 obsolete1; /* word 03 (num heads) */
|
||||
u16 retired1[2]; /* words 04-05 */
|
||||
u16 obsolete2; /* word 06 (sectors / track) */
|
||||
u16 reserved_for_compact_flash1[2]; /* words 07-08 */
|
||||
u16 retired0; /* word 09 */
|
||||
u8 serial_number[ATA_IDENTIFY_SERIAL_NUMBER_LEN]; /* word 10-19 */
|
||||
u16 retired2[2]; /* words 20-21 */
|
||||
u16 obsolete4; /* word 22 */
|
||||
u8 firmware_revision[ATA_IDENTIFY_FW_REVISION_LEN]; /* words 23-26 */
|
||||
u8 model_number[ATA_IDENTIFY_MODEL_NUMBER_LEN]; /* words 27-46 */
|
||||
u16 max_sectors_per_multiple; /* word 47 */
|
||||
u16 reserved0; /* word 48 */
|
||||
u16 capabilities1; /* word 49 */
|
||||
u16 capabilities2; /* word 50 */
|
||||
u16 obsolete5[2]; /* words 51-52 */
|
||||
u16 validity_bits; /* word 53 */
|
||||
u16 obsolete6[5]; /*
|
||||
* words 54-58 Used to be:
|
||||
* current cylinders,
|
||||
* current heads,
|
||||
* current sectors/Track,
|
||||
* current capacity */
|
||||
u16 current_max_sectors_per_multiple; /* word 59 */
|
||||
u8 total_num_sectors[4]; /* words 60-61 */
|
||||
u16 obsolete7; /* word 62 */
|
||||
u16 multi_word_dma_mode; /* word 63 */
|
||||
u16 pio_modes_supported; /* word 64 */
|
||||
u16 min_multiword_dma_transfer_cycle; /* word 65 */
|
||||
u16 rec_min_multiword_dma_transfer_cycle; /* word 66 */
|
||||
u16 min_pio_transfer_no_flow_ctrl; /* word 67 */
|
||||
u16 min_pio_transfer_with_flow_ctrl; /* word 68 */
|
||||
u16 reserved1[2]; /* words 69-70 */
|
||||
u16 reserved2[4]; /* words 71-74 */
|
||||
u16 queue_depth; /* word 75 */
|
||||
u16 serial_ata_capabilities; /* word 76 */
|
||||
u16 serial_ata_reserved; /* word 77 */
|
||||
u16 serial_ata_features_supported; /* word 78 */
|
||||
u16 serial_ata_features_enabled; /* word 79 */
|
||||
u16 major_version_number; /* word 80 */
|
||||
u16 minor_version_number; /* word 81 */
|
||||
u16 command_set_supported0; /* word 82 */
|
||||
u16 command_set_supported1; /* word 83 */
|
||||
u16 command_set_supported_extention; /* word 84 */
|
||||
u16 command_set_enabled0; /* word 85 */
|
||||
u16 command_set_enabled1; /* word 86 */
|
||||
u16 command_set_default; /* word 87 */
|
||||
u16 ultra_dma_mode; /* word 88 */
|
||||
u16 security_erase_completion_time; /* word 89 */
|
||||
u16 enhanced_security_erase_time; /* word 90 */
|
||||
u16 current_power_mgmt_value; /* word 91 */
|
||||
u16 master_password_revision; /* word 92 */
|
||||
u16 hardware_reset_result; /* word 93 */
|
||||
u16 current_acoustic_management_value; /* word 94 */
|
||||
u16 stream_min_request_size; /* word 95 */
|
||||
u16 stream_transfer_time; /* word 96 */
|
||||
u16 stream_access_latency; /* word 97 */
|
||||
u16 stream_performance_granularity[2]; /* words 98-99 */
|
||||
u8 max_48bit_lba[ATA_IDENTIFY_48_LBA_LEN]; /* words 100-103 */
|
||||
u16 streaming_transfer_time; /* word 104 */
|
||||
u16 reserved3; /* word 105 */
|
||||
u16 physical_logical_sector_info; /* word 106 */
|
||||
u16 acoustic_test_interseek_delay; /* word 107 */
|
||||
u8 world_wide_name[ATA_IDENTIFY_WWN_LEN]; /* words 108-111 */
|
||||
u8 reserved_for_wwn_extention[ATA_IDENTIFY_WWN_LEN]; /* words 112-115 */
|
||||
u16 reserved4; /* word 116 */
|
||||
u8 words_per_logical_sector[4]; /* words 117-118 */
|
||||
u16 command_set_supported2; /* word 119 */
|
||||
u16 reserved5[7]; /* words 120-126 */
|
||||
u16 removable_media_status; /* word 127 */
|
||||
u16 security_status; /* word 128 */
|
||||
u16 vendor_specific1[31]; /* words 129-159 */
|
||||
u16 cfa_power_mode1; /* word 160 */
|
||||
u16 reserved_for_compact_flash2[7]; /* words 161-167 */
|
||||
u16 device_nominal_form_factor; /* word 168 */
|
||||
u16 reserved_for_compact_flash3[7]; /* words 169-175 */
|
||||
u16 current_media_serial_number[ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN]; /* words 176-205 */
|
||||
u16 reserved6[3]; /* words 206-208 */
|
||||
u16 logical_sector_alignment; /* words 209 */
|
||||
u16 reserved7[7]; /* words 210-216 */
|
||||
u16 nominal_media_rotation_rate; /* word 217 */
|
||||
u16 reserved8[37]; /* words 218-254 */
|
||||
u16 integrity_word; /* word 255 */
|
||||
|
||||
};
|
||||
|
||||
#define ATA_IDENTIFY_DEVICE_GET_OFFSET(field_name) \
|
||||
((unsigned long)&(((struct ata_identify_device_data *)0)->field_name))
|
||||
#define ATA_IDENTIFY_DEVICE_WCE_ENABLE 0x20
|
||||
#define ATA_IDENTIFY_DEVICE_RA_ENABLE 0x40
|
||||
|
||||
/**
|
||||
* struct ATAPI_IDENTIFY_PACKET_DATA - The following structure depicts the
|
||||
* ATA-ATAPI 7 version of the IDENTIFY PACKET DEVICE data structure.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct atapi_identify_packet_device {
|
||||
u16 generalConfigBits; /* word 00 */
|
||||
u16 reserved0; /* word 01 (num cylinders) */
|
||||
u16 uniqueConfigBits; /* word 02 */
|
||||
u16 reserved1[7]; /* words 03 - 09 */
|
||||
u8 serialNumber[ATA_IDENTIFY_SERIAL_NUMBER_LEN]; /* word 10-19 */
|
||||
u16 reserved2[3]; /* words 20-22 */
|
||||
u8 firmwareRevision[ATA_IDENTIFY_FW_REVISION_LEN]; /* words 23-26 */
|
||||
u8 modelNumber[ATA_IDENTIFY_MODEL_NUMBER_LEN]; /* words 27-46 */
|
||||
u16 reserved4[2]; /* words 47-48 */
|
||||
u16 capabilities1; /* word 49 */
|
||||
u16 capabilities2; /* word 50 */
|
||||
u16 obsolete0[2]; /* words 51-52 */
|
||||
u16 validityBits; /* word 53 */
|
||||
u16 reserved[8]; /* words 54-61 */
|
||||
|
||||
u16 DMADIRBitRequired; /* word 62, page2 */
|
||||
u16 multiWordDmaMode; /* word 63 */
|
||||
u16 pioModesSupported; /* word 64 */
|
||||
u16 minMultiwordDmaTransferCycle; /* word 65 */
|
||||
u16 recMinMultiwordDmaTransferCycle; /* word 66 */
|
||||
u16 minPioTransferNoFlowCtrl; /* word 67 */
|
||||
u16 minPioTransferWithFlowCtrl; /* word 68 */
|
||||
u16 reserved6[2]; /* words 69-70 */
|
||||
u16 nsFromPACKETReceiptToBusRelease; /* word 71 */
|
||||
u16 nsFromSERVICEReceiptToBSYreset; /* wore 72 */
|
||||
u16 reserved7[2]; /* words 73-74 */
|
||||
u16 queueDepth; /* word 75 */
|
||||
u16 serialAtaCapabilities; /* word 76 */
|
||||
u16 serialAtaReserved; /* word 77 */
|
||||
u16 serialAtaFeaturesSupported; /* word 78 */
|
||||
u16 serialAtaFeaturesEnabled; /* word 79 */
|
||||
|
||||
u16 majorVersionNumber; /* word 80, page3 */
|
||||
u16 minorVersionNumber; /* word 81 */
|
||||
u16 commandSetSupported0; /* word 82 */
|
||||
u16 commandSetSupported1; /* word 83 */
|
||||
|
||||
u16 commandSetSupportedExtention; /* word 84, page4 */
|
||||
u16 commandSetEnabled0; /* word 85 */
|
||||
u16 commandSetEnabled1; /* word 86 */
|
||||
u16 commandSetDefault; /* word 87 */
|
||||
|
||||
u16 ultraDmaMode; /* word 88, page5 */
|
||||
u16 reserved8[4]; /* words 89 - 92 */
|
||||
|
||||
u16 hardwareResetResult; /* word 93, page6 */
|
||||
u16 currentAcousticManagementValue; /* word 94 */
|
||||
u16 reserved9[30]; /* words 95-124 */
|
||||
u16 ATAPIByteCount0Behavior; /* word 125 */
|
||||
u16 obsolete1; /* word 126 */
|
||||
u16 removableMediaStatus; /* word 127, */
|
||||
|
||||
u16 securityStatus; /* word 128, page7 */
|
||||
u16 vendorSpecific1[31]; /* words 129-159 */
|
||||
u16 reservedForCompactFlash[16]; /* words 160-175 */
|
||||
u16 reserved10[79]; /* words 176-254 */
|
||||
u16 integrityWord; /* word 255 */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ata_extended_smart_self_test_log - The following structure depicts
|
||||
* the ATA-8 version of the Extended SMART self test log page descriptor
|
||||
* entry.
|
||||
*
|
||||
*
|
||||
*/
|
||||
union ata_descriptor_entry {
|
||||
struct DESCRIPTOR_ENTRY {
|
||||
u8 lba_field;
|
||||
u8 status_byte;
|
||||
u8 time_stamp_low;
|
||||
u8 time_stamp_high;
|
||||
u8 checkpoint_byte;
|
||||
u8 failing_lba_low;
|
||||
u8 failing_lba_mid;
|
||||
u8 failing_lba_high;
|
||||
u8 failing_lba_low_ext;
|
||||
u8 failing_lba_mid_ext;
|
||||
u8 failing_lba_high_ext;
|
||||
|
||||
u8 vendor_specific1;
|
||||
u8 vendor_specific2;
|
||||
u8 vendor_specific3;
|
||||
u8 vendor_specific4;
|
||||
u8 vendor_specific5;
|
||||
u8 vendor_specific6;
|
||||
u8 vendor_specific7;
|
||||
u8 vendor_specific8;
|
||||
u8 vendor_specific9;
|
||||
u8 vendor_specific10;
|
||||
u8 vendor_specific11;
|
||||
u8 vendor_specific12;
|
||||
u8 vendor_specific13;
|
||||
u8 vendor_specific14;
|
||||
u8 vendor_specific15;
|
||||
} DESCRIPTOR_ENTRY;
|
||||
|
||||
u8 descriptor_entry[26];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ata_extended_smart_self_test_log - The following structure depicts
|
||||
* the ATA-8 version of the SMART self test log page descriptor entry.
|
||||
*
|
||||
*
|
||||
*/
|
||||
union ata_smart_descriptor_entry {
|
||||
struct SMART_DESCRIPTOR_ENTRY {
|
||||
u8 lba_field;
|
||||
u8 status_byte;
|
||||
u8 time_stamp_low;
|
||||
u8 time_stamp_high;
|
||||
u8 checkpoint_byte;
|
||||
u8 failing_lba_low;
|
||||
u8 failing_lba_mid;
|
||||
u8 failing_lba_high;
|
||||
u8 failing_lba_low_ext;
|
||||
|
||||
u8 vendor_specific1;
|
||||
u8 vendor_specific2;
|
||||
u8 vendor_specific3;
|
||||
u8 vendor_specific4;
|
||||
u8 vendor_specific5;
|
||||
u8 vendor_specific6;
|
||||
u8 vendor_specific7;
|
||||
u8 vendor_specific8;
|
||||
u8 vendor_specific9;
|
||||
u8 vendor_specific10;
|
||||
u8 vendor_specific11;
|
||||
u8 vendor_specific12;
|
||||
u8 vendor_specific13;
|
||||
u8 vendor_specific14;
|
||||
u8 vendor_specific15;
|
||||
} SMART_DESCRIPTOR_ENTRY;
|
||||
|
||||
u8 smart_descriptor_entry[24];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ata_extended_smart_self_test_log - The following structure depicts
|
||||
* the ATA-8 version of the Extended SMART self test log page.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct ata_extended_smart_self_test_log {
|
||||
u8 self_test_log_data_structure_revision_number; /* byte 0 */
|
||||
u8 reserved0; /* byte 1 */
|
||||
u8 self_test_descriptor_index[2]; /* byte 2-3 */
|
||||
|
||||
union ata_descriptor_entry descriptor_entrys[19]; /* bytes 4-497 */
|
||||
|
||||
u8 vendor_specific[2]; /* byte 498-499 */
|
||||
u8 reserved1[11]; /* byte 500-510 */
|
||||
u8 data_structure_checksum; /* byte 511 */
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ata_extended_smart_self_test_log - The following structure depicts
|
||||
* the ATA-8 version of the SMART self test log page.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct ata_smart_self_test_log {
|
||||
u8 self_test_log_data_structure_revision_number[2]; /* bytes 0-1 */
|
||||
|
||||
union ata_smart_descriptor_entry descriptor_entrys[21]; /* bytes 2-505 */
|
||||
|
||||
u8 vendor_specific[2]; /* byte 506-507 */
|
||||
u8 self_test_index; /* byte 508 */
|
||||
u8 reserved1[2]; /* byte 509-510 */
|
||||
u8 data_structure_checksum; /* byte 511 */
|
||||
|
||||
};
|
||||
|
||||
#endif /* _ATA_H_ */
|
||||
|
||||
948
drivers/scsi/isci/core/intel_sas.h
Normal file
948
drivers/scsi/isci/core/intel_sas.h
Normal file
@@ -0,0 +1,948 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _INTEL_SAS_H_
|
||||
#define _INTEL_SAS_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the definitions relating to structures, constants,
|
||||
* etc. defined by the SAS specification.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "intel_sata.h"
|
||||
#include "intel_scsi.h"
|
||||
|
||||
/**
|
||||
* struct sci_sas_address - This structure depicts how a SAS address is
|
||||
* represented by SCI.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_sas_address {
|
||||
/**
|
||||
* This member contains the higher 32-bits of the SAS address.
|
||||
*/
|
||||
u32 high;
|
||||
|
||||
/**
|
||||
* This member contains the lower 32-bits of the SAS address.
|
||||
*/
|
||||
u32 low;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sci_sas_identify_address_frame_protocols - This structure depicts the
|
||||
* contents of bytes 2 and 3 in the SAS IDENTIFY ADDRESS FRAME (IAF).
|
||||
*
|
||||
* For specific information on each of these individual fields please reference
|
||||
* the SAS specification Link layer section on address frames.
|
||||
*/
|
||||
struct sci_sas_identify_address_frame_protocols {
|
||||
union {
|
||||
struct {
|
||||
u16 restricted1:1;
|
||||
u16 smp_initiator:1;
|
||||
u16 stp_initiator:1;
|
||||
u16 ssp_initiator:1;
|
||||
u16 reserved3:4;
|
||||
u16 restricted2:1;
|
||||
u16 smp_target:1;
|
||||
u16 stp_target:1;
|
||||
u16 ssp_target:1;
|
||||
u16 reserved4:4;
|
||||
} bits;
|
||||
|
||||
u16 all;
|
||||
} u;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sci_sas_identify_address_frame - This structure depicts the contents
|
||||
* of the SAS IDENTIFY ADDRESS FRAME (IAF).
|
||||
*
|
||||
* For specific information on each of these individual fields please reference
|
||||
* the SAS specification Link layer section on address frames.
|
||||
*/
|
||||
struct sci_sas_identify_address_frame {
|
||||
u16 address_frame_type:4;
|
||||
u16 device_type:3;
|
||||
u16 reserved1:1;
|
||||
u16 reason:4;
|
||||
u16 reserved2:4;
|
||||
|
||||
struct sci_sas_identify_address_frame_protocols protocols;
|
||||
|
||||
struct sci_sas_address device_name;
|
||||
struct sci_sas_address sas_address;
|
||||
|
||||
u32 phy_identifier:8;
|
||||
u32 break_reply_capable:1;
|
||||
u32 requested_in_zpsds:1;
|
||||
u32 in_zpsds_persistent:1;
|
||||
u32 reserved5:21;
|
||||
|
||||
u32 reserved6[4];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sas_capabilities - This structure depicts the various SAS
|
||||
* capabilities supported by the directly attached target device. For
|
||||
* specific information on each of these individual fields please reference
|
||||
* the SAS specification Phy layer section on speed negotiation windows.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sas_capabilities {
|
||||
union {
|
||||
#if defined (SCIC_SDS_4_ENABLED)
|
||||
struct {
|
||||
/**
|
||||
* The SAS specification indicates the start bit shall always be set to
|
||||
* 1. This implementation will have the start bit set to 0 if the
|
||||
* PHY CAPABILITIES were either not received or speed negotiation failed.
|
||||
*/
|
||||
u32 start:1;
|
||||
u32 tx_ssc_type:1;
|
||||
u32 reserved1:2;
|
||||
u32 requested_logical_link_rate:4;
|
||||
|
||||
u32 gen1_without_ssc_supported:1;
|
||||
u32 gen1_with_ssc_supported:1;
|
||||
u32 gen2_without_ssc_supported:1;
|
||||
u32 gen2_with_ssc_supported:1;
|
||||
u32 gen3_without_ssc_supported:1;
|
||||
u32 gen3_with_ssc_supported:1;
|
||||
u32 reserved2:17;
|
||||
u32 parity:1;
|
||||
} bits;
|
||||
#endif /* (SCIC_SDS_4_ENABLED) */
|
||||
|
||||
u32 all;
|
||||
} u;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* enum _SCI_SAS_LINK_RATE - This enumeration depicts the SAS specification
|
||||
* defined link speeds.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_sas_link_rate {
|
||||
SCI_SAS_NO_LINK_RATE = 0,
|
||||
SCI_SATA_SPINUP_HOLD = 0x3,
|
||||
SCI_SAS_150_GB = 0x8,
|
||||
SCI_SAS_300_GB = 0x9,
|
||||
SCI_SAS_600_GB = 0xA
|
||||
};
|
||||
|
||||
/**
|
||||
* enum _SCI_SAS_TASK_ATTRIBUTE - This enumeration depicts the SAM/SAS
|
||||
* specification defined task attribute values for a command information
|
||||
* unit.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_sas_task_attribute {
|
||||
SCI_SAS_SIMPLE_ATTRIBUTE = 0,
|
||||
SCI_SAS_HEAD_OF_QUEUE_ATTRIBUTE = 1,
|
||||
SCI_SAS_ORDERED_ATTRIBUTE = 2,
|
||||
SCI_SAS_ACA_ATTRIBUTE = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum _SCI_SAS_TASK_MGMT_FUNCTION - This enumeration depicts the SAM/SAS
|
||||
* specification defined task management functions.
|
||||
*
|
||||
* This HARD_RESET function listed here is not actually defined as a task
|
||||
* management function in the industry standard.
|
||||
*/
|
||||
enum sci_sas_task_mgmt_function {
|
||||
SCI_SAS_ABORT_TASK = SCSI_TASK_REQUEST_ABORT_TASK,
|
||||
SCI_SAS_ABORT_TASK_SET = SCSI_TASK_REQUEST_ABORT_TASK_SET,
|
||||
SCI_SAS_CLEAR_TASK_SET = SCSI_TASK_REQUEST_CLEAR_TASK_SET,
|
||||
SCI_SAS_LOGICAL_UNIT_RESET = SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET,
|
||||
SCI_SAS_I_T_NEXUS_RESET = SCSI_TASK_REQUEST_I_T_NEXUS_RESET,
|
||||
SCI_SAS_CLEAR_ACA = SCSI_TASK_REQUEST_CLEAR_ACA,
|
||||
SCI_SAS_QUERY_TASK = SCSI_TASK_REQUEST_QUERY_TASK,
|
||||
SCI_SAS_QUERY_TASK_SET = SCSI_TASK_REQUEST_QUERY_TASK_SET,
|
||||
SCI_SAS_QUERY_ASYNCHRONOUS_EVENT = SCSI_TASK_REQUEST_QUERY_UNIT_ATTENTION,
|
||||
SCI_SAS_HARD_RESET = 0xFF
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* enum _SCI_SAS_FRAME_TYPE - This enumeration depicts the SAS specification
|
||||
* defined SSP frame types.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_sas_frame_type {
|
||||
SCI_SAS_DATA_FRAME = 0x01,
|
||||
SCI_SAS_XFER_RDY_FRAME = 0x05,
|
||||
SCI_SAS_COMMAND_FRAME = 0x06,
|
||||
SCI_SAS_RESPONSE_FRAME = 0x07,
|
||||
SCI_SAS_TASK_FRAME = 0x16
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sci_ssp_command_iu - This structure depicts the contents of the SSP
|
||||
* COMMAND INFORMATION UNIT. For specific information on each of these
|
||||
* individual fields please reference the SAS specification SSP transport
|
||||
* layer section.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_ssp_command_iu {
|
||||
u32 lun_upper;
|
||||
u32 lun_lower;
|
||||
|
||||
u32 additional_cdb_length:6;
|
||||
u32 reserved0:2;
|
||||
u32 reserved1:8;
|
||||
u32 enable_first_burst:1;
|
||||
u32 task_priority:4;
|
||||
u32 task_attribute:3;
|
||||
u32 reserved2:8;
|
||||
|
||||
u32 cdb[4];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sci_ssp_task_iu - This structure depicts the contents of the SSP TASK
|
||||
* INFORMATION UNIT. For specific information on each of these individual
|
||||
* fields please reference the SAS specification SSP transport layer section.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_ssp_task_iu {
|
||||
u32 lun_upper;
|
||||
u32 lun_lower;
|
||||
|
||||
u32 reserved0:8;
|
||||
u32 task_function:8;
|
||||
u32 reserved1:8;
|
||||
u32 reserved2:8;
|
||||
|
||||
u32 reserved3:16;
|
||||
u32 task_tag:16;
|
||||
|
||||
u32 reserved4[3];
|
||||
|
||||
};
|
||||
|
||||
#define SSP_RESPONSE_IU_MAX_DATA 64
|
||||
|
||||
#define SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK (0x03)
|
||||
|
||||
|
||||
#define sci_ssp_get_sense_data_length(sense_data_length_buffer) \
|
||||
SCIC_BUILD_DWORD(sense_data_length_buffer)
|
||||
|
||||
#define sci_ssp_get_response_data_length(response_data_length_buffer) \
|
||||
SCIC_BUILD_DWORD(response_data_length_buffer)
|
||||
|
||||
/**
|
||||
* struct sci_ssp_response_iu - This structure depicts the contents of the SSP
|
||||
* RESPONSE INFORMATION UNIT. For specific information on each of these
|
||||
* individual fields please reference the SAS specification SSP transport
|
||||
* layer section.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_ssp_response_iu {
|
||||
u8 reserved0[8];
|
||||
|
||||
u8 retry_delay_timer[2];
|
||||
u8 data_present;
|
||||
u8 status;
|
||||
|
||||
u8 reserved1[4];
|
||||
u8 sense_data_length[4];
|
||||
u8 response_data_length[4];
|
||||
|
||||
u32 data[SSP_RESPONSE_IU_MAX_DATA];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* enum _SCI_SAS_DATA_PRESENT_TYPE - This enumeration depicts the SAS
|
||||
* specification defined SSP data present types in struct sci_ssp_response_iu.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_ssp_response_iu_data_present_type {
|
||||
SCI_SSP_RESPONSE_IU_NO_DATA = 0x00,
|
||||
SCI_SSP_RESPONSE_IU_RESPONSE_DATA = 0x01,
|
||||
SCI_SSP_RESPONSE_IU_SENSE_DATA = 0x02
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sci_ssp_frame_header - This structure depicts the contents of an SSP
|
||||
* frame header. For specific information on the individual fields please
|
||||
* reference the SAS specification transport layer SSP frame format.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_ssp_frame_header {
|
||||
/* Word 0 */
|
||||
u32 hashed_destination_address:24;
|
||||
u32 frame_type:8;
|
||||
|
||||
/* Word 1 */
|
||||
u32 hashed_source_address:24;
|
||||
u32 reserved1_0:8;
|
||||
|
||||
/* Word 2 */
|
||||
u32 reserved2_2:6;
|
||||
u32 fill_bytes:2;
|
||||
u32 reserved2_1:3;
|
||||
u32 tlr_control:2;
|
||||
u32 retry_data_frames:1;
|
||||
u32 retransmit:1;
|
||||
u32 changing_data_pointer:1;
|
||||
u32 reserved2_0:16;
|
||||
|
||||
/* Word 3 */
|
||||
u32 uiResv4;
|
||||
|
||||
/* Word 4 */
|
||||
u16 target_port_transfer_tag;
|
||||
u16 tag;
|
||||
|
||||
/* Word 5 */
|
||||
u32 data_offset;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smp_request_header - This structure defines the contents of an SMP
|
||||
* Request header.
|
||||
*
|
||||
* For specific information on each of these individual fields please reference
|
||||
* the SAS specification.
|
||||
*/
|
||||
struct smp_request_header {
|
||||
u8 smp_frame_type; /* byte 0 */
|
||||
u8 function; /* byte 1 */
|
||||
u8 allocated_response_length; /* byte 2 */
|
||||
u8 request_length; /* byte 3 */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smp_response_header - This structure depicts the contents of the SAS
|
||||
* SMP DISCOVER RESPONSE frame. For specific information on each of these
|
||||
* individual fields please reference the SAS specification Link layer
|
||||
* section on address frames.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct smp_response_header {
|
||||
u8 smp_frame_type; /* byte 0 */
|
||||
u8 function; /* byte 1 */
|
||||
u8 function_result; /* byte 2 */
|
||||
u8 response_length; /* byte 3 */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smp_request_general - This structure defines the contents of an SMP
|
||||
* Request that is comprised of the struct smp_request_header and a CRC.
|
||||
*
|
||||
* For specific information on each of these individual fields please reference
|
||||
* the SAS specification.
|
||||
*/
|
||||
struct smp_request_general {
|
||||
u32 crc; /* bytes 4-7 */
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smp_request_phy_identifier - This structure defines the contents of
|
||||
* an SMP Request that is comprised of the struct smp_request_header and a phy
|
||||
* identifier. Examples: SMP_REQUEST_DISCOVER, SMP_REQUEST_REPORT_PHY_SATA.
|
||||
*
|
||||
* For specific information on each of these individual fields please reference
|
||||
* the SAS specification.
|
||||
*/
|
||||
struct smp_request_phy_identifier {
|
||||
u32 reserved_byte4_7; /* bytes 4-7 */
|
||||
|
||||
u32 ignore_zone_group:1; /* byte 8 */
|
||||
u32 reserved_byte8:7;
|
||||
|
||||
u32 phy_identifier:8; /* byte 9 */
|
||||
u32 reserved_byte10:8; /* byte 10 */
|
||||
u32 reserved_byte11:8; /* byte 11 */
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smp_request_configure_route_information - This structure defines the
|
||||
* contents of an SMP Configure Route Information request.
|
||||
*
|
||||
* For specific information on each of these individual fields please reference
|
||||
* the SAS specification.
|
||||
*/
|
||||
struct smp_request_configure_route_information {
|
||||
u32 expected_expander_change_count:16; /* bytes 4-5 */
|
||||
u32 expander_route_index_high:8;
|
||||
u32 expander_route_index:8; /* bytes 6-7 */
|
||||
|
||||
u32 reserved_byte8:8; /* bytes 8 */
|
||||
u32 phy_identifier:8; /* bytes 9 */
|
||||
u32 reserved_byte_10_11:16; /* bytes 10-11 */
|
||||
|
||||
u32 reserved_byte_12_bit_0_6:7;
|
||||
u32 disable_route_entry:1; /* byte 12 */
|
||||
u32 reserved_byte_13_15:24; /* bytes 13-15 */
|
||||
|
||||
u32 routed_sas_address[2]; /* bytes 16-23 */
|
||||
u8 reserved_byte_24_39[16]; /* bytes 24-39 */
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smp_request_phy_control - This structure defines the contents of an
|
||||
* SMP Phy Controler request.
|
||||
*
|
||||
* For specific information on each of these individual fields please reference
|
||||
* the SAS specification.
|
||||
*/
|
||||
struct smp_request_phy_control {
|
||||
u16 expected_expander_change_count; /* byte 4-5 */
|
||||
|
||||
u16 reserved_byte_6_7; /* byte 6-7 */
|
||||
u8 reserved_byte_8; /* byte 8 */
|
||||
|
||||
u8 phy_identifier; /* byte 9 */
|
||||
u8 phy_operation; /* byte 10 */
|
||||
|
||||
u8 update_partial_pathway_timeout_value:1;
|
||||
u8 reserved_byte_11_bit_1_7:7; /* byte 11 */
|
||||
|
||||
u8 reserved_byte_12_23[12]; /* byte 12-23 */
|
||||
|
||||
u8 attached_device_name[8]; /* byte 24-31 */
|
||||
|
||||
u8 reserved_byte_32_bit_3_0:4; /* byte 32 */
|
||||
u8 programmed_minimum_physical_link_rate:4;
|
||||
|
||||
u8 reserved_byte_33_bit_3_0:4; /* byte 33 */
|
||||
u8 programmed_maximum_physical_link_rate:4;
|
||||
|
||||
u16 reserved_byte_34_35; /* byte 34-35 */
|
||||
|
||||
u8 partial_pathway_timeout_value:4;
|
||||
u8 reserved_byte_36_bit_4_7:4; /* byte 36 */
|
||||
|
||||
u16 reserved_byte_37_38; /* byte 37-38 */
|
||||
u8 reserved_byte_39; /* byte 39 */
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smp_request_vendor_specific - This structure depicts the vendor
|
||||
* specific space for SMP request.
|
||||
*
|
||||
*
|
||||
*/
|
||||
#define SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH 1016
|
||||
struct smp_request_vendor_specific {
|
||||
u8 request_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smp_request - This structure simply unionizes the existing request
|
||||
* structures into a common request type.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct smp_request {
|
||||
struct smp_request_header header;
|
||||
|
||||
union { /* bytes 4-N */
|
||||
struct smp_request_general report_general;
|
||||
struct smp_request_phy_identifier discover;
|
||||
struct smp_request_general report_manufacturer_information;
|
||||
struct smp_request_phy_identifier report_phy_sata;
|
||||
struct smp_request_phy_control phy_control;
|
||||
struct smp_request_phy_identifier report_phy_error_log;
|
||||
struct smp_request_phy_identifier report_route_information;
|
||||
struct smp_request_configure_route_information configure_route_information;
|
||||
struct smp_request_vendor_specific vendor_specific_request;
|
||||
} request;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct smp_response_report_general - This structure depicts the SMP Report
|
||||
* General for expander devices. It adheres to the SAS-2.1 specification.
|
||||
*
|
||||
* For specific information on each of these individual fields please reference
|
||||
* the SAS specification Application layer section on SMP.
|
||||
*/
|
||||
struct smp_response_report_general {
|
||||
u16 expander_change_count; /* byte 4-5 */
|
||||
u16 expander_route_indexes; /* byte 6-7 */
|
||||
|
||||
u32 reserved_byte8:7; /* byte 8 bit 0-6 */
|
||||
u32 long_response:1; /* byte 8 bit 7 */
|
||||
|
||||
u32 number_of_phys:8; /* byte 9 */
|
||||
|
||||
u32 configurable_route_table:1; /* byte 10 */
|
||||
u32 configuring:1;
|
||||
u32 configures_others:1;
|
||||
u32 open_reject_retry_supported:1;
|
||||
u32 stp_continue_awt:1;
|
||||
u32 self_configuring:1;
|
||||
u32 zone_configuring:1;
|
||||
u32 table_to_table_supported:1;
|
||||
|
||||
u32 reserved_byte11:8; /* byte 11 */
|
||||
|
||||
u32 enclosure_logical_identifier_high; /* byte 12-15 */
|
||||
u32 enclosure_logical_identifier_low; /* byte 16-19 */
|
||||
|
||||
u32 reserved_byte20_23;
|
||||
u32 reserved_byte24_27;
|
||||
|
||||
};
|
||||
|
||||
struct smp_response_report_general_long {
|
||||
struct smp_response_report_general sas1_1;
|
||||
|
||||
struct {
|
||||
u16 reserved1;
|
||||
u16 stp_bus_inactivity_time_limit;
|
||||
u16 stp_max_connect_time_limit;
|
||||
u16 stp_smp_i_t_nexus_loss_time;
|
||||
|
||||
u32 zoning_enabled:1;
|
||||
u32 zoning_supported:1;
|
||||
u32 physicaL_presence_asserted:1;
|
||||
u32 zone_locked:1;
|
||||
u32 reserved2:1;
|
||||
u32 num_zone_groups:3;
|
||||
u32 saving_zoning_enabled_supported:3;
|
||||
u32 saving_zone_perms_table_supported:1;
|
||||
u32 saving_zone_phy_info_supported:1;
|
||||
u32 saving_zone_manager_password_supported:1;
|
||||
u32 saving:1;
|
||||
u32 reserved3:1;
|
||||
u32 max_number_routed_sas_addresses:16;
|
||||
|
||||
struct sci_sas_address active_zone_manager_sas_address;
|
||||
|
||||
u16 zone_lock_inactivity_time_limit;
|
||||
u16 reserved4;
|
||||
|
||||
u8 reserved5;
|
||||
u8 first_enclosure_connector_element_index;
|
||||
u8 number_of_enclosure_connector_element_indices;
|
||||
u8 reserved6;
|
||||
|
||||
u32 reserved7:7;
|
||||
u32 reduced_functionality:1;
|
||||
u32 time_to_reduce_functionality:8;
|
||||
u32 initial_time_to_reduce_functionality:8;
|
||||
u8 max_reduced_functionality_time;
|
||||
|
||||
u16 last_self_config_status_descriptor_index;
|
||||
u16 max_number_of_stored_self_config_status_descriptors;
|
||||
|
||||
u16 last_phy_event_list_descriptor_index;
|
||||
u16 max_number_of_stored_phy_event_list_descriptors;
|
||||
} sas2;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smp_response_report_manufacturer_information - This structure depicts
|
||||
* the SMP report manufacturer information for expander devices. It adheres
|
||||
* to the SAS-2.1 specification.
|
||||
*
|
||||
* For specific information on each of these individual fields please reference
|
||||
* the SAS specification Application layer section on SMP.
|
||||
*/
|
||||
struct smp_response_report_manufacturer_information {
|
||||
u32 expander_change_count:16; /* bytes 4-5 */
|
||||
u32 reserved1:16;
|
||||
|
||||
u32 sas1_1_format:1;
|
||||
u32 reserved2:31;
|
||||
|
||||
u8 vendor_id[8];
|
||||
u8 product_id[16];
|
||||
u8 product_revision_level[4];
|
||||
u8 component_vendor_id[8];
|
||||
u8 component_id[2];
|
||||
u8 component_revision_level;
|
||||
u8 reserved3;
|
||||
u8 vendor_specific[8];
|
||||
|
||||
};
|
||||
|
||||
#define SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE 52
|
||||
#define SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE 116
|
||||
|
||||
/**
|
||||
* struct smp_discover_response_protocols - This structure depicts the discover
|
||||
* response where the supported protocols by the remote phy are specified.
|
||||
*
|
||||
* For specific information on each of these individual fields please reference
|
||||
* the SAS specification Link layer section on address frames.
|
||||
*/
|
||||
struct smp_discover_response_protocols {
|
||||
union {
|
||||
struct {
|
||||
u16 attached_sata_host:1;
|
||||
u16 attached_smp_initiator:1;
|
||||
u16 attached_stp_initiator:1;
|
||||
u16 attached_ssp_initiator:1;
|
||||
u16 reserved3:4;
|
||||
u16 attached_sata_device:1;
|
||||
u16 attached_smp_target:1;
|
||||
u16 attached_stp_target:1;
|
||||
u16 attached_ssp_target:1;
|
||||
u16 reserved4:3;
|
||||
u16 attached_sata_port_selector:1;
|
||||
} bits;
|
||||
|
||||
u16 all;
|
||||
} u;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SMP_RESPONSE_DISCOVER_FORMAT - This structure defines the SMP phy
|
||||
* discover response format. It handles both SAS1.1 and SAS 2 definitions.
|
||||
* The unions indicate locations where the SAS specification versions differ
|
||||
* from one another.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct smp_response_discover {
|
||||
|
||||
union {
|
||||
struct {
|
||||
u8 reserved[2];
|
||||
} sas1_1;
|
||||
|
||||
struct {
|
||||
u16 expander_change_count;
|
||||
} sas2;
|
||||
|
||||
} u1;
|
||||
|
||||
u8 reserved1[3];
|
||||
u8 phy_identifier;
|
||||
u8 reserved2[2];
|
||||
|
||||
union {
|
||||
struct {
|
||||
u16 reserved1:4;
|
||||
u16 attached_device_type:3;
|
||||
u16 reserved2:1;
|
||||
u16 negotiated_physical_link_rate:4;
|
||||
u16 reserved3:4;
|
||||
} sas1_1;
|
||||
|
||||
struct {
|
||||
u16 attached_reason:4;
|
||||
u16 attached_device_type:3;
|
||||
u16 reserved2:1;
|
||||
u16 negotiated_logical_link_rate:4;
|
||||
u16 reserved3:4;
|
||||
} sas2;
|
||||
|
||||
} u2;
|
||||
|
||||
struct smp_discover_response_protocols protocols;
|
||||
struct sci_sas_address sas_address;
|
||||
struct sci_sas_address attached_sas_address;
|
||||
|
||||
u8 attached_phy_identifier;
|
||||
|
||||
union {
|
||||
struct {
|
||||
u8 reserved;
|
||||
} sas1_1;
|
||||
|
||||
struct {
|
||||
u8 attached_break_reply_capable:1;
|
||||
u8 attached_requested_inside_zpsds:1;
|
||||
u8 attached_inside_zpsds_persistent:1;
|
||||
u8 reserved1:5;
|
||||
} sas2;
|
||||
|
||||
} u3;
|
||||
|
||||
u8 reserved_for_identify[6];
|
||||
|
||||
u32 hardware_min_physical_link_rate:4;
|
||||
u32 programmed_min_physical_link_rate:4;
|
||||
u32 hardware_max_physical_link_rate:4;
|
||||
u32 programmed_max_physical_link_rate:4;
|
||||
u32 phy_change_count:8;
|
||||
u32 partial_pathway_timeout_value:4;
|
||||
u32 reserved5:3;
|
||||
u32 virtual_phy:1;
|
||||
|
||||
u32 routing_attribute:4;
|
||||
u32 reserved6:4;
|
||||
u32 connector_type:7;
|
||||
u32 reserved7:1;
|
||||
u32 connector_element_index:8;
|
||||
u32 connector_physical_link:8;
|
||||
|
||||
u16 reserved8;
|
||||
u16 vendor_specific;
|
||||
|
||||
union {
|
||||
struct {
|
||||
/**
|
||||
* In the SAS 1.1 specification this structure ends after 52 bytes.
|
||||
* As a result, the contents of this field should never have a
|
||||
* real value. It is undefined.
|
||||
*/
|
||||
u8 undefined[SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE
|
||||
- SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE];
|
||||
} sas1_1;
|
||||
|
||||
struct {
|
||||
struct sci_sas_address attached_device_name;
|
||||
|
||||
u32 zoning_enabled:1;
|
||||
u32 inside_zpsds:1;
|
||||
u32 zone_group_persistent:1;
|
||||
u32 reserved1:1;
|
||||
u32 requested_inside_zpsds:1;
|
||||
u32 inside_zpsds_persistent:1;
|
||||
u32 requested_inside_zpsds_changed_by_expander:1;
|
||||
u32 reserved2:1;
|
||||
u32 reserved_for_zoning_fields:16;
|
||||
u32 zone_group:8;
|
||||
|
||||
u8 self_configuration_status;
|
||||
u8 self_configuration_levels_completed;
|
||||
u16 reserved_for_self_config_fields;
|
||||
|
||||
struct sci_sas_address self_configuration_sas_address;
|
||||
|
||||
u32 programmed_phy_capabilities;
|
||||
u32 current_phy_capabilities;
|
||||
u32 attached_phy_capabilities;
|
||||
|
||||
u32 reserved3;
|
||||
|
||||
u32 reserved4:16;
|
||||
u32 negotiated_physical_link_rate:4;
|
||||
u32 reason:4;
|
||||
u32 hardware_muxing_supported:1;
|
||||
u32 negotiated_ssc:1;
|
||||
u32 reserved5:6;
|
||||
|
||||
u32 default_zoning_enabled:1;
|
||||
u32 reserved6:1;
|
||||
u32 default_zone_group_persistent:1;
|
||||
u32 reserved7:1;
|
||||
u32 default_requested_inside_zpsds:1;
|
||||
u32 default_inside_zpsds_persistent:1;
|
||||
u32 reserved8:2;
|
||||
u32 reserved9:16;
|
||||
u32 default_zone_group:8;
|
||||
|
||||
u32 saved_zoning_enabled:1;
|
||||
u32 reserved10:1;
|
||||
u32 saved_zone_group_persistent:1;
|
||||
u32 reserved11:1;
|
||||
u32 saved_requested_inside_zpsds:1;
|
||||
u32 saved_inside_zpsds_persistent:1;
|
||||
u32 reserved12:18;
|
||||
u32 saved_zone_group:8;
|
||||
|
||||
u32 reserved14:2;
|
||||
u32 shadow_zone_group_persistent:1;
|
||||
u32 reserved15:1;
|
||||
u32 shadow_requested_inside_zpsds:1;
|
||||
u32 shadow_inside_zpsds_persistent:1;
|
||||
u32 reserved16:18;
|
||||
u32 shadow_zone_group:8;
|
||||
|
||||
u8 device_slot_number;
|
||||
u8 device_slot_group_number;
|
||||
u8 device_slot_group_output_connector[6];
|
||||
} sas2;
|
||||
|
||||
} u4;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smp_response_report_phy_sata - This structure depicts the contents of
|
||||
* the SAS SMP REPORT PHY SATA frame. For specific information on each of
|
||||
* these individual fields please reference the SAS specification Link layer
|
||||
* section on address frames.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct smp_response_report_phy_sata {
|
||||
u32 ignored_byte_4_7; /* bytes 4-7 */
|
||||
|
||||
u32 affiliations_valid:1;
|
||||
u32 affiliations_supported:1;
|
||||
u32 reserved_byte11:6; /* byte 11 */
|
||||
u32 ignored_byte10:8; /* byte 10 */
|
||||
u32 phy_identifier:8; /* byte 9 */
|
||||
u32 reserved_byte_8:8; /* byte 8 */
|
||||
|
||||
u32 reserved_12_15;
|
||||
u32 stp_sas_address[2];
|
||||
u8 device_to_host_fis[20];
|
||||
u32 reserved_44_47;
|
||||
u32 affiliated_stp_initiator_sas_address[2];
|
||||
|
||||
};
|
||||
|
||||
struct smp_response_vendor_specific {
|
||||
u8 response_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH];
|
||||
};
|
||||
|
||||
union smp_response_body {
|
||||
struct smp_response_report_general report_general;
|
||||
struct smp_response_report_manufacturer_information report_manufacturer_information;
|
||||
struct smp_response_discover discover;
|
||||
struct smp_response_report_phy_sata report_phy_sata;
|
||||
struct smp_response_vendor_specific vendor_specific_response;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smp_response - This structure simply unionizes the existing response
|
||||
* structures into a common response type.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct smp_response {
|
||||
struct smp_response_header header;
|
||||
|
||||
union smp_response_body response;
|
||||
|
||||
};
|
||||
|
||||
/* SMP Request Functions */
|
||||
#define SMP_FUNCTION_REPORT_GENERAL 0x00
|
||||
#define SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION 0x01
|
||||
#define SMP_FUNCTION_DISCOVER 0x10
|
||||
#define SMP_FUNCTION_REPORT_PHY_ERROR_LOG 0x11
|
||||
#define SMP_FUNCTION_REPORT_PHY_SATA 0x12
|
||||
#define SMP_FUNCTION_REPORT_ROUTE_INFORMATION 0X13
|
||||
#define SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION 0X90
|
||||
#define SMP_FUNCTION_PHY_CONTROL 0x91
|
||||
#define SMP_FUNCTION_PHY_TEST 0x92
|
||||
|
||||
#define SMP_FRAME_TYPE_REQUEST 0x40
|
||||
#define SMP_FRAME_TYPE_RESPONSE 0x41
|
||||
|
||||
#define PHY_OPERATION_NOP 0x00
|
||||
#define PHY_OPERATION_LINK_RESET 0x01
|
||||
#define PHY_OPERATION_HARD_RESET 0x02
|
||||
#define PHY_OPERATION_DISABLE 0x03
|
||||
#define PHY_OPERATION_CLEAR_ERROR_LOG 0x05
|
||||
#define PHY_OPERATION_CLEAR_AFFILIATION 0x06
|
||||
|
||||
#define NPLR_PHY_ENABLED_UNK_LINK_RATE 0x00
|
||||
#define NPLR_PHY_DISABLED 0x01
|
||||
#define NPLR_PHY_ENABLED_SPD_NEG_FAILED 0x02
|
||||
#define NPLR_PHY_ENABLED_SATA_HOLD 0x03
|
||||
#define NPLR_PHY_ENABLED_1_5G 0x08
|
||||
#define NPLR_PHY_ENABLED_3_0G 0x09
|
||||
|
||||
/* SMP Function Result values. */
|
||||
#define SMP_RESULT_FUNCTION_ACCEPTED 0x00
|
||||
#define SMP_RESULT_UNKNOWN_FUNCTION 0x01
|
||||
#define SMP_RESULT_FUNCTION_FAILED 0x02
|
||||
#define SMP_RESULT_INVALID_REQUEST_FRAME_LEN 0x03
|
||||
#define SMP_RESULT_INAVALID_EXPANDER_CHANGE_COUNT 0x04
|
||||
#define SMP_RESULT_BUSY 0x05
|
||||
#define SMP_RESULT_INCOMPLETE_DESCRIPTOR_LIST 0x06
|
||||
#define SMP_RESULT_PHY_DOES_NOT_EXIST 0x10
|
||||
#define SMP_RESULT_INDEX_DOES_NOT_EXIST 0x11
|
||||
#define SMP_RESULT_PHY_DOES_NOT_SUPPORT_SATA 0x12
|
||||
#define SMP_RESULT_UNKNOWN_PHY_OPERATION 0x13
|
||||
#define SMP_RESULT_UNKNOWN_PHY_TEST_FUNCTION 0x14
|
||||
#define SMP_RESULT_PHY_TEST_IN_PROGRESS 0x15
|
||||
#define SMP_RESULT_PHY_VACANT 0x16
|
||||
|
||||
/* Attached Device Types */
|
||||
#define SMP_NO_DEVICE_ATTACHED 0
|
||||
#define SMP_END_DEVICE_ONLY 1
|
||||
#define SMP_EDGE_EXPANDER_DEVICE 2
|
||||
#define SMP_FANOUT_EXPANDER_DEVICE 3
|
||||
|
||||
/* Expander phy routine attribute */
|
||||
#define DIRECT_ROUTING_ATTRIBUTE 0
|
||||
#define SUBTRACTIVE_ROUTING_ATTRIBUTE 1
|
||||
#define TABLE_ROUTING_ATTRIBUTE 2
|
||||
|
||||
#endif /* _INTEL_SAS_H_ */
|
||||
|
||||
95
drivers/scsi/isci/core/intel_sat.h
Normal file
95
drivers/scsi/isci/core/intel_sat.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SAT_H_
|
||||
#define _SAT_H_
|
||||
|
||||
/**
|
||||
* This file contains constants and constructs defined in the SCSI to ATA
|
||||
* Translation (SAT) T10 standard. For more information please refer to
|
||||
* www.t10.org.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SAT_PROTOCOLS These constants indicate the various protocol values that can
|
||||
* be supported in a SAT translator.
|
||||
*/
|
||||
#define SAT_PROTOCOL_ATA_HARD_RESET 0
|
||||
#define SAT_PROTOCOL_SOFT_RESET 1
|
||||
#define SAT_PROTOCOL_NON_DATA 3
|
||||
#define SAT_PROTOCOL_PIO_DATA_IN 4
|
||||
#define SAT_PROTOCOL_PIO_DATA_OUT 5
|
||||
#define SAT_PROTOCOL_DMA 6
|
||||
#define SAT_PROTOCOL_DMA_QUEUED 7
|
||||
#define SAT_PROTOCOL_DEVICE_DIAGNOSTIC 8
|
||||
#define SAT_PROTOCOL_DEVICE_RESET 9
|
||||
#define SAT_PROTOCOL_UDMA_DATA_IN 10
|
||||
#define SAT_PROTOCOL_UDMA_DATA_OUT 11
|
||||
#define SAT_PROTOCOL_FPDMA 12
|
||||
#define SAT_PROTOCOL_RETURN_RESPONSE_INFO 15
|
||||
|
||||
#define SAT_PROTOCOL_PACKET 0x10
|
||||
#define SAT_PROTOCOL_PACKET_NON_DATA (SAT_PROTOCOL_PACKET | 0x0)
|
||||
#define SAT_PROTOCOL_PACKET_DMA_DATA_IN (SAT_PROTOCOL_PACKET | 0x1)
|
||||
#define SAT_PROTOCOL_PACKET_DMA_DATA_OUT (SAT_PROTOCOL_PACKET | 0x2)
|
||||
#define SAT_PROTOCOL_PACKET_PIO_DATA_IN (SAT_PROTOCOL_PACKET | 0x3)
|
||||
#define SAT_PROTOCOL_PACKET_PIO_DATA_OUT (SAT_PROTOCOL_PACKET | 0x4)
|
||||
|
||||
#endif /* _SAT_H_ */
|
||||
|
||||
280
drivers/scsi/isci/core/intel_sata.h
Normal file
280
drivers/scsi/isci/core/intel_sata.h
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SATA_H_
|
||||
#define _SATA_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
* This file defines all of the SATA releated constants, enumerations, and
|
||||
* types. Please note that this file does not necessarily contain an
|
||||
* exhaustive list of all contants and commands.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SATA FIS Types These constants depict the various SATA FIS types devined in
|
||||
* the serial ATA specification.
|
||||
*/
|
||||
#define SATA_FIS_TYPE_REGH2D 0x27
|
||||
#define SATA_FIS_TYPE_REGD2H 0x34
|
||||
#define SATA_FIS_TYPE_SETDEVBITS 0xA1
|
||||
#define SATA_FIS_TYPE_DMA_ACTIVATE 0x39
|
||||
#define SATA_FIS_TYPE_DMA_SETUP 0x41
|
||||
#define SATA_FIS_TYPE_BIST_ACTIVATE 0x58
|
||||
#define SATA_FIS_TYPE_PIO_SETUP 0x5F
|
||||
#define SATA_FIS_TYPE_DATA 0x46
|
||||
|
||||
#define SATA_REGISTER_FIS_SIZE 0x20
|
||||
|
||||
/**
|
||||
* struct sata_fis_header - This is the common definition for a SATA FIS Header
|
||||
* word. A different header word is defined for any FIS type that does not
|
||||
* use the standard header.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sata_fis_header {
|
||||
u32 fis_type:8; /* word 0 */
|
||||
u32 pm_port:4;
|
||||
u32 reserved:1;
|
||||
u32 direction_flag:1; /* direction */
|
||||
u32 interrupt_flag:1;
|
||||
u32 command_flag:1; /* command, auto_activate, or notification */
|
||||
u32 status:8;
|
||||
u32 error:8;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct sata_fis_reg_h2d - This is the definition for a SATA Host to Device
|
||||
* Register FIS.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sata_fis_reg_h2d {
|
||||
u32 fis_type:8; /* word 0 */
|
||||
u32 pm_port:4;
|
||||
u32 reserved0:3;
|
||||
u32 command_flag:1;
|
||||
u32 command:8;
|
||||
u32 features:8;
|
||||
u32 lba_low:8; /* word 1 */
|
||||
u32 lba_mid:8;
|
||||
u32 lba_high:8;
|
||||
u32 device:8;
|
||||
u32 lba_low_exp:8; /* word 2 */
|
||||
u32 lba_mid_exp:8;
|
||||
u32 lba_high_exp:8;
|
||||
u32 features_exp:8;
|
||||
u32 sector_count:8; /* word 3 */
|
||||
u32 sector_count_exp:8;
|
||||
u32 reserved1:8;
|
||||
u32 control:8;
|
||||
u32 reserved2; /* word 4 */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sata_fis_reg_d2h - SATA Device To Host FIS
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sata_fis_reg_d2h {
|
||||
u32 fis_type:8; /* word 0 */
|
||||
u32 pm_port:4;
|
||||
u32 reserved0:2;
|
||||
u32 irq:1;
|
||||
u32 reserved1:1;
|
||||
u32 status:8;
|
||||
u32 error:8;
|
||||
u8 lba_low; /* word 1 */
|
||||
u8 lba_mid;
|
||||
u8 lba_high;
|
||||
u8 device;
|
||||
u8 lba_low_exp; /* word 2 */
|
||||
u8 lba_mid_exp;
|
||||
u8 lba_high_exp;
|
||||
u8 reserved;
|
||||
u8 sector_count; /* word 3 */
|
||||
u8 sector_count_exp;
|
||||
u16 reserved2;
|
||||
u32 reserved3;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Status field bit definitions
|
||||
*/
|
||||
#define SATA_FIS_STATUS_DEVBITS_MASK (0x77)
|
||||
|
||||
/**
|
||||
* struct sata_fis_set_dev_bits - SATA Set Device Bits FIS
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sata_fis_set_dev_bits {
|
||||
u32 fis_type:8; /* word 0 */
|
||||
u32 pm_port:4;
|
||||
u32 reserved0:2;
|
||||
u32 irq:1;
|
||||
u32 notification:1;
|
||||
u32 status_low:4;
|
||||
u32 status_high:4;
|
||||
u32 error:8;
|
||||
u32 s_active; /* word 1 */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sata_fis_dma_activate - SATA DMA Activate FIS
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sata_fis_dma_activate {
|
||||
u32 fis_type:8; /* word 0 */
|
||||
u32 pm_port:4;
|
||||
u32 reserved0:24;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* The lower 5 bits in the DMA Buffer ID Low field of the DMA Setup are used to
|
||||
* communicate the command tag.
|
||||
*/
|
||||
#define SATA_DMA_SETUP_TAG_ENABLE 0x1F
|
||||
|
||||
#define SATA_DMA_SETUP_AUTO_ACT_ENABLE 0x80
|
||||
|
||||
/**
|
||||
* struct sata_fis_dma_setup - SATA DMA Setup FIS
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sata_fis_dma_setup {
|
||||
u32 fis_type:8; /* word 0 */
|
||||
u32 pm_port:4;
|
||||
u32 reserved_00:1;
|
||||
u32 direction:1;
|
||||
u32 irq:1;
|
||||
u32 auto_activate:1;
|
||||
u32 reserved_01:16;
|
||||
u32 dma_buffer_id_low; /* word 1 */
|
||||
u32 dma_buffer_id_high; /* word 2 */
|
||||
u32 reserved0; /* word 3 */
|
||||
u32 dma_buffer_offset; /* word 4 */
|
||||
u32 dma_transfer_count; /* word 5 */
|
||||
u32 reserved1; /* word 6 */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sata_fis_bist_activate - SATA BIST Activate FIS
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sata_fis_bist_activate {
|
||||
u32 fis_type:8; /* word 0 */
|
||||
u32 reserved0:8;
|
||||
u32 pattern_definition:8;
|
||||
u32 reserved1:8;
|
||||
u32 data1; /* word 1 */
|
||||
u32 data2; /* word 1 */
|
||||
};
|
||||
|
||||
/*
|
||||
* SATA PIO Setup FIS
|
||||
*/
|
||||
struct sata_fis_pio_setup {
|
||||
u32 fis_type:8; /* word 0 */
|
||||
u32 pm_port:4;
|
||||
u32 reserved_00:1;
|
||||
u32 direction:1;
|
||||
u32 irq:1;
|
||||
u32 reserved_01:1;
|
||||
u32 status:8;
|
||||
u32 error:8;
|
||||
u32 lba_low:8; /* word 1 */
|
||||
u32 lba_mid:8;
|
||||
u32 lba_high:8;
|
||||
u32 device:8;
|
||||
u32 lba_low_exp:8; /* word 2 */
|
||||
u32 lba_mid_exp:8;
|
||||
u32 lba_high_exp:8;
|
||||
u32 reserved:8;
|
||||
u32 sector_count:8; /* word 3 */
|
||||
u32 sector_count_exp:8;
|
||||
u32 reserved1:8;
|
||||
u32 ending_status:8;
|
||||
u32 transfter_count:16; /* word 4 */
|
||||
u32 reserved3:16;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sata_fis_data - SATA Data FIS
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sata_fis_data {
|
||||
u32 fis_type:8; /* word 0 */
|
||||
u32 pm_port:4;
|
||||
u32 reserved0:24;
|
||||
u8 data[4]; /* word 1 */
|
||||
};
|
||||
|
||||
#endif /* _SATA_H_ */
|
||||
474
drivers/scsi/isci/core/intel_scsi.h
Normal file
474
drivers/scsi/isci/core/intel_scsi.h
Normal file
@@ -0,0 +1,474 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file defines all of the SCSI related constants, enumerations, and
|
||||
* types. Please note that this file does not necessarily contain an
|
||||
* exhaustive list of all constants, commands, sub-commands, etc.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SCSI_H__
|
||||
#define _SCSI_H__
|
||||
|
||||
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* * C O N S T A N T S A N D M A C R O S
|
||||
* ****************************************************************************** */
|
||||
|
||||
/**
|
||||
* enum _SCSI_TASK_MGMT_REQUEST_CODES - This enumberation contains the
|
||||
* constants to be used for SCSI task management request codes. SAM does
|
||||
* not specify any particular values for these codes so constants used here
|
||||
* are the same as those specified in SAS.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum scsi_task_mgmt_request_codes {
|
||||
SCSI_TASK_REQUEST_ABORT_TASK = 0x01,
|
||||
SCSI_TASK_REQUEST_ABORT_TASK_SET = 0x02,
|
||||
SCSI_TASK_REQUEST_CLEAR_TASK_SET = 0x04,
|
||||
SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET = 0x08,
|
||||
SCSI_TASK_REQUEST_I_T_NEXUS_RESET = 0x10,
|
||||
SCSI_TASK_REQUEST_CLEAR_ACA = 0x40,
|
||||
SCSI_TASK_REQUEST_QUERY_TASK = 0x80,
|
||||
SCSI_TASK_REQUEST_QUERY_TASK_SET = 0x81,
|
||||
SCSI_TASK_REQUEST_QUERY_UNIT_ATTENTION = 0x82,
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* enum _SCSI_TASK_MGMT_RESPONSE_CODES - This enumeration contains all of the
|
||||
* SCSI task management response codes.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum scsi_task_mgmt_response_codes {
|
||||
SCSI_TASK_MGMT_FUNC_COMPLETE = 0,
|
||||
SCSI_INVALID_FRAME = 2,
|
||||
SCSI_TASK_MGMT_FUNC_NOT_SUPPORTED = 4,
|
||||
SCSI_TASK_MGMT_FUNC_FAILED = 5,
|
||||
SCSI_TASK_MGMT_FUNC_SUCCEEDED = 8,
|
||||
SCSI_INVALID_LUN = 9
|
||||
};
|
||||
|
||||
/**
|
||||
* enum _SCSI_SENSE_RESPONSE_CODE - this enumeration depicts the types of sense
|
||||
* data responses as per SPC-3.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum scsi_sense_response_code {
|
||||
SCSI_FIXED_CURRENT_RESPONSE_CODE = 0x70,
|
||||
SCSI_FIXED_DEFERRED_RESPONSE_CODE = 0x71,
|
||||
SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE = 0x72,
|
||||
SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE = 0x73
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* This constant represents the valid bit located in byte 0 of a FIXED
|
||||
* format sense data. */
|
||||
#define SCSI_FIXED_SENSE_DATA_VALID_BIT 0x80
|
||||
|
||||
#define SCSI_FIXED_SENSE_DATA_BASE_LENGTH 18
|
||||
|
||||
/* This value is used in the DATAPRES field of the SCSI Response IU. */
|
||||
#define SCSI_RESPONSE_DATA_PRES_SENSE_DATA 0x02
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCSI_SENSE_KEYS These constants delineate all of the SCSI protocol sense key
|
||||
* constants
|
||||
*/
|
||||
#define SCSI_SENSE_NO_SENSE 0x00
|
||||
#define SCSI_SENSE_RECOVERED_ERROR 0x01
|
||||
#define SCSI_SENSE_NOT_READY 0x02
|
||||
#define SCSI_SENSE_MEDIUM_ERROR 0x03
|
||||
#define SCSI_SENSE_HARDWARE_ERROR 0x04
|
||||
#define SCSI_SENSE_ILLEGAL_REQUEST 0x05
|
||||
#define SCSI_SENSE_UNIT_ATTENTION 0x06
|
||||
#define SCSI_SENSE_DATA_PROTECT 0x07
|
||||
#define SCSI_SENSE_BLANK_CHECK 0x08
|
||||
#define SCSI_SENSE_VENDOR_SPECIFIC 0x09
|
||||
#define SCSI_SENSE_COPY_ABORTED 0x0A
|
||||
#define SCSI_SENSE_ABORTED_COMMAND 0x0B
|
||||
#define SCSI_SENSE_VOLUME_OVERFLOW 0x0D
|
||||
#define SCSI_SENSE_MISCOMPARE 0x0E
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCSI_ADDITIONAL_SENSE_CODES These constants delineate all of the SCSI
|
||||
* protocol additional sense code constants.
|
||||
*/
|
||||
#define SCSI_ASC_NO_ADDITIONAL_SENSE 0x00
|
||||
#define SCSI_ASC_INITIALIZING_COMMAND_REQUIRED 0x04
|
||||
#define SCSI_ASC_LUN_SELF_TEST_IN_PROGRESS 0x04
|
||||
#define SCSI_ASC_LUN_FORMAT_IN_PROGRESS 0x04
|
||||
#define SCSI_ASC_LUN_NOT_RESPOND_TO_SELECTION 0x05
|
||||
#define SCSI_ASC_UNRECOVERED_READ_ERROR 0x11
|
||||
#define SCSI_ASC_INVALID_COMMAND_OPERATION_CODE 0x20
|
||||
#define SCSI_ASC_LBA_OUT_OF_RANGE 0x21
|
||||
#define SCSI_ASC_INVALID_FIELD_IN_CDB 0x24
|
||||
#define SCSI_ASC_INVALID_FIELD_IN_PARM_LIST 0x26
|
||||
#define SCSI_ASC_WRITE_PROTECTED 0x27
|
||||
#define SCSI_ASC_NOT_READY_TO_READY_CHANGE 0x28
|
||||
#define SCSI_ASC_SAVING_PARMS_NOT_SUPPORTED 0x39
|
||||
#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A
|
||||
#define SCSI_ASC_INTERNAL_TARGET_FAILURE 0x44
|
||||
#define SCSI_ASC_IU_CRC_ERROR_DETECTED 0x47
|
||||
#define SCSI_ASC_MEDIUM_REMOVAL_REQUEST 0x5A
|
||||
#define SCSI_ASC_COMMAND_SEQUENCE_ERROR 0x2C
|
||||
#define SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED 0x53
|
||||
#define SCSI_ASC_HARDWARE_IMPENDING_FAILURE 0x5D
|
||||
#define SCSI_ASC_POWER_STATE_CHANGE 0x5E
|
||||
#define SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT 0x40
|
||||
#define SCSI_ASC_ATA_DEVICE_FEATURE_NOT_ENABLED 0x67
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCSI_ADDITIONAL_SENSE_CODE_QUALIFIERS This enumeration contains all of the
|
||||
* used SCSI protocol additional sense code qualifier constants.
|
||||
*/
|
||||
#define SCSI_ASCQ_NO_ADDITIONAL_SENSE 0x00
|
||||
#define SCSI_ASCQ_INVALID_FIELD_IN_CDB 0x00
|
||||
#define SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST 0x00
|
||||
#define SCSI_ASCQ_LUN_NOT_RESPOND_TO_SELECTION 0x00
|
||||
#define SCSI_ASCQ_INTERNAL_TARGET_FAILURE 0x00
|
||||
#define SCSI_ASCQ_LBA_OUT_OF_RANGE 0x00
|
||||
#define SCSI_ASCQ_MEDIUM_NOT_PRESENT 0x00
|
||||
#define SCSI_ASCQ_NOT_READY_TO_READY_CHANGE 0x00
|
||||
#define SCSI_ASCQ_WRITE_PROTECTED 0x00
|
||||
#define SCSI_ASCQ_UNRECOVERED_READ_ERROR 0x00
|
||||
#define SCSI_ASCQ_SAVING_PARMS_NOT_SUPPORTED 0x00
|
||||
#define SCSI_ASCQ_INVALID_COMMAND_OPERATION_CODE 0x00
|
||||
#define SCSI_ASCQ_MEDIUM_REMOVAL_REQUEST 0x01
|
||||
#define SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02
|
||||
#define SCSI_ASCQ_IU_CRC_ERROR_DETECTED 0x03
|
||||
#define SCSI_ASCQ_LUN_FORMAT_IN_PROGRESS 0x04
|
||||
#define SCSI_ASCQ_LUN_SELF_TEST_IN_PROGRESS 0x09
|
||||
#define SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE 0x10
|
||||
#define SCSI_ASCQ_IDLE_CONDITION_ACTIVATE_BY_COMMAND 0x03
|
||||
#define SCSI_ASCQ_STANDBY_CONDITION_ACTIVATE_BY_COMMAND 0x04
|
||||
#define SCSI_ASCQ_POWER_STATE_CHANGE_TO_IDLE 0x42
|
||||
#define SCSI_ASCQ_POWER_STATE_CHANGE_TO_STANDBY 0x43
|
||||
#define SCSI_ASCQ_ATA_DEVICE_FEATURE_NOT_ENABLED 0x0B
|
||||
#define SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL 0x04
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCSI_STATUS_CODES These constants define all of the used SCSI status values.
|
||||
*/
|
||||
#define SCSI_STATUS_GOOD 0x00
|
||||
#define SCSI_STATUS_CHECK_CONDITION 0x02
|
||||
#define SCSI_STATUS_CONDITION_MET 0x04
|
||||
#define SCSI_STATUS_BUSY 0x08
|
||||
#define SCSI_STATUS_TASKFULL 0x28
|
||||
#define SCSI_STATUS_ACA 0x30
|
||||
#define SCSI_STATUS_ABORT 0x40
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCSI_OPERATION_CODES These constants delineate all of the SCSI
|
||||
* command/operation codes.
|
||||
*/
|
||||
#define SCSI_INQUIRY 0x12
|
||||
#define SCSI_READ_CAPACITY_10 0x25
|
||||
#define SCSI_SERVICE_ACTION_IN_16 0x9E
|
||||
#define SCSI_TEST_UNIT_READY 0x00
|
||||
#define SCSI_START_STOP_UNIT 0x1B
|
||||
#define SCSI_SYNCHRONIZE_CACHE_10 0x35
|
||||
#define SCSI_SYNCHRONIZE_CACHE_16 0x91
|
||||
#define SCSI_REQUEST_SENSE 0x03
|
||||
#define SCSI_REPORT_LUNS 0xA0
|
||||
#define SCSI_REASSIGN_BLOCKS 0x07
|
||||
#define SCSI_READ_6 0x08
|
||||
#define SCSI_READ_10 0x28
|
||||
#define SCSI_READ_12 0xA8
|
||||
#define SCSI_READ_16 0x88
|
||||
#define SCSI_WRITE_6 0x0A
|
||||
#define SCSI_WRITE_10 0x2A
|
||||
#define SCSI_WRITE_12 0xAA
|
||||
#define SCSI_WRITE_16 0x8A
|
||||
#define SCSI_VERIFY_10 0x2F
|
||||
#define SCSI_VERIFY_12 0xAF
|
||||
#define SCSI_VERIFY_16 0x8F
|
||||
#define SCSI_SEEK_6 0x01
|
||||
#define SCSI_SEEK_10 0x02
|
||||
#define SCSI_WRITE_VERIFY 0x2E
|
||||
#define SCSI_FORMAT_UNIT 0x04
|
||||
#define SCSI_READ_BUFFER 0x3C
|
||||
#define SCSI_WRITE_BUFFER 0x3B
|
||||
#define SCSI_SEND_DIAGNOSTIC 0x1D
|
||||
#define SCSI_RECEIVE_DIAGNOSTIC 0x1C
|
||||
#define SCSI_MODE_SENSE_6 0x1A
|
||||
#define SCSI_MODE_SENSE_10 0x5A
|
||||
#define SCSI_MODE_SELECT_6 0x15
|
||||
#define SCSI_MODE_SELECT_10 0x55
|
||||
#define SCSI_MAINTENANCE_IN 0xA3
|
||||
#define SCSI_LOG_SENSE 0x4D
|
||||
#define SCSI_LOG_SELECT 0x4C
|
||||
#define SCSI_RESERVE_6 0x16
|
||||
#define SCSI_RESERVE_10 0x56
|
||||
#define SCSI_RELEASE_6 0x17
|
||||
#define SCSI_RELEASE_10 0x57
|
||||
#define SCSI_ATA_PASSTHRU_12 0xA1
|
||||
#define SCSI_ATA_PASSTHRU_16 0x85
|
||||
#define SCSI_WRITE_LONG_10 0x3F
|
||||
#define SCSI_WRITE_LONG_16 0x9F
|
||||
#define SCSI_PERSISTENT_RESERVE_IN 0x5E
|
||||
#define SCSI_PERSISTENT_RESERVE_OUT 0x5F
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCSI_SERVICE_ACTION_IN_CODES Service action in operations.
|
||||
*/
|
||||
#define SCSI_SERVICE_ACTION_IN_CODES_READ_CAPACITY_16 0x10
|
||||
|
||||
#define SCSI_SERVICE_ACTION_MASK 0x1f
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCSI_MAINTENANCE_IN_SERVICE_ACTION_CODES MAINTENANCE IN service action codes.
|
||||
*/
|
||||
#define SCSI_REPORT_TASK_MGMT 0x0D
|
||||
#define SCSI_REPORT_OP_CODES 0x0C
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCSI_MODE_PAGE_CONTROLS These constants delineate all of the used SCSI Mode
|
||||
* Page control values.
|
||||
*/
|
||||
#define SCSI_MODE_SENSE_PC_CURRENT 0x0
|
||||
#define SCSI_MODE_SENSE_PC_CHANGEABLE 0x1
|
||||
#define SCSI_MODE_SENSE_PC_DEFAULT 0x2
|
||||
#define SCSI_MODE_SENSE_PC_SAVED 0x3
|
||||
|
||||
#define SCSI_MODE_SENSE_PC_SHIFT 0x06
|
||||
#define SCSI_MODE_SENSE_PAGE_CODE_ENABLE 0x3F
|
||||
#define SCSI_MODE_SENSE_DBD_ENABLE 0x08
|
||||
#define SCSI_MODE_SENSE_LLBAA_ENABLE 0x10
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCSI_MODE_PAGE_CODES These constants delineate all of the used SCSI Mode
|
||||
* Page codes.
|
||||
*/
|
||||
#define SCSI_MODE_PAGE_READ_WRITE_ERROR 0x01
|
||||
#define SCSI_MODE_PAGE_DISCONNECT_RECONNECT 0x02
|
||||
#define SCSI_MODE_PAGE_CACHING 0x08
|
||||
#define SCSI_MODE_PAGE_CONTROL 0x0A
|
||||
#define SCSI_MODE_PAGE_PROTOCOL_SPECIFIC_PORT 0x19
|
||||
#define SCSI_MODE_PAGE_POWER_CONDITION 0x1A
|
||||
#define SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL 0x1C
|
||||
#define SCSI_MODE_PAGE_ALL_PAGES 0x3F
|
||||
|
||||
#define SCSI_MODE_SENSE_ALL_SUB_PAGES_CODE 0xFF
|
||||
#define SCSI_MODE_SENSE_NO_SUB_PAGES_CODE 0x0
|
||||
#define SCSI_MODE_SENSE_PROTOCOL_PORT_NUM_SUBPAGES 0x1
|
||||
#define SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT 0x04
|
||||
#define SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT 0x20
|
||||
#define SCSI_MODE_PAGE_DEXCPT_ENABLE 0x08
|
||||
#define SCSI_MODE_SENSE_HEADER_FUA_ENABLE 0x10
|
||||
#define SCSI_MODE_PAGE_POWER_CONDITION_STANDBY 0x1
|
||||
#define SCSI_MODE_PAGE_POWER_CONDITION_IDLE 0x2
|
||||
|
||||
#define SCSI_MODE_SENSE_6_HEADER_LENGTH 4
|
||||
#define SCSI_MODE_SENSE_10_HEADER_LENGTH 8
|
||||
#define SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH 8
|
||||
#define SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH 16
|
||||
|
||||
#define SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE 0x08
|
||||
#define SCSI_MODE_PAGE_19_SAS_ID 0x6
|
||||
#define SCSI_MODE_PAGE_19_SUB1_PAGE_NUM 0x1
|
||||
#define SCSI_MODE_PAGE_19_SUB1_PC 0x59
|
||||
|
||||
#define SCSI_MODE_HEADER_MEDIUM_TYPE_SBC 0x00
|
||||
|
||||
/* Mode Select constrains related masks value */
|
||||
#define SCSI_MODE_SELECT_PF_BIT 0x1
|
||||
#define SCSI_MODE_SELECT_PF_MASK 0x10
|
||||
#define SCSI_MODE_SELECT_MODE_PAGE_MRIE_BYTE 0x6
|
||||
#define SCSI_MODE_SELECT_MODE_PAGE_MRIE_MASK 0x0F
|
||||
#define SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK 0x40
|
||||
#define SCSI_MODE_SELECT_MODE_PAGE_01_AWRE_MASK 0x80
|
||||
#define SCSI_MODE_SELECT_MODE_PAGE_01_ARRE_MASK 0x40
|
||||
#define SCSI_MODE_SELECT_MODE_PAGE_01_RC_ERBITS_MASK 0x1F
|
||||
#define SCSI_MODE_SELECT_MODE_PAGE_08_FSW_LBCSS_NVDIS 0xC1
|
||||
#define SCSI_MODE_SELECT_MODE_PAGE_1C_PERF_TEST 0x84
|
||||
#define SCSI_MODE_SELECT_MODE_PAGE_0A_TST_TMF_RLEC 0xF1
|
||||
#define SCSI_MODE_SELECT_MODE_PAGE_0A_MODIFIER 0xF0
|
||||
#define SCSI_MODE_SELECT_MODE_PAGE_0A_UA_SWP 0x38
|
||||
#define SCSI_MODE_SELECT_MODE_PAGE_0A_TAS_AUTO 0x47
|
||||
|
||||
|
||||
#define SCSI_CONTROL_BYTE_NACA_BIT_ENABLE 0x04
|
||||
#define SCSI_MOVE_FUA_BIT_ENABLE 0x08
|
||||
#define SCSI_READ_CAPACITY_PMI_BIT_ENABLE 0x01
|
||||
#define SCSI_READ_CAPACITY_10_DATA_LENGTH 8
|
||||
#define SCSI_READ_CAPACITY_16_DATA_LENGTH 32
|
||||
|
||||
/* Inquiry constants */
|
||||
#define SCSI_INQUIRY_EVPD_ENABLE 0x01
|
||||
#define SCSI_INQUIRY_PAGE_CODE_OFFSET 0x02
|
||||
#define SCSI_INQUIRY_SUPPORTED_PAGES_PAGE 0x00
|
||||
#define SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE 0x80
|
||||
#define SCSI_INQUIRY_DEVICE_ID_PAGE 0x83
|
||||
#define SCSI_INQUIRY_ATA_INFORMATION_PAGE 0x89
|
||||
#define SCSI_INQUIRY_BLOCK_DEVICE_PAGE 0xB1
|
||||
#define SCSI_INQUIRY_BLOCK_DEVICE_LENGTH 0x3C
|
||||
#define SCSI_INQUIRY_STANDARD_ALLOCATION_LENGTH 0x24 /* 36 */
|
||||
|
||||
#define SCSI_REQUEST_SENSE_ALLOCATION_LENGTH 0xFC /* 252 */
|
||||
|
||||
/** Defines the log page codes that are use in gathing Smart data
|
||||
*/
|
||||
#define SCSI_LOG_PAGE_SUPPORTED_PAGES 0x00
|
||||
#define SCSI_LOG_PAGE_INFORMATION_EXCEPTION 0x2F
|
||||
#define SCSI_LOG_PAGE_SELF_TEST 0x10
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCSI_INQUIRY_VPD The following are constants used with vital product data
|
||||
* inquiry pages. Values are already shifted into the proper nibble location.
|
||||
*/
|
||||
#define SCSI_PIV_ENABLE 0x80
|
||||
#define SCSI_LUN_ASSOCIATION 0x00
|
||||
#define SCSI_TARGET_PORT_ASSOCIATION 0x10
|
||||
|
||||
#define SCSI_VEN_UNIQUE_IDENTIFIER_TYPE 0x00
|
||||
#define SCSI_NAA_IDENTIFIER_TYPE 0x03
|
||||
|
||||
#define SCSI_T10_IDENTIFIER_TYPE 0x01
|
||||
#define SCSI_BINARY_CODE_SET 0x01
|
||||
#define SCSI_ASCII_CODE_SET 0x02
|
||||
#define SCSI_FC_PROTOCOL_IDENTIFIER 0x00
|
||||
#define SCSI_SAS_PROTOCOL_IDENTIFIER 0x60
|
||||
|
||||
#define SCSI_VERIFY_BYTCHK_ENABLED 0x02
|
||||
|
||||
#define SCSI_SYNCHRONIZE_CACHE_IMMED_ENABLED 0x02
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCSI_START_STOP_UNIT_POWER_CONDITION_CODES The following are SCSI Start Stop
|
||||
* Unit command Power Condition codes.
|
||||
*/
|
||||
#define SCSI_START_STOP_UNIT_POWER_CONDITION_START_VALID 0x0
|
||||
#define SCSI_START_STOP_UNIT_POWER_CONDITION_ACTIVE 0x1
|
||||
#define SCSI_START_STOP_UNIT_POWER_CONDITION_IDLE 0x2
|
||||
#define SCSI_START_STOP_UNIT_POWER_CONDITION_STANDBY 0x3
|
||||
#define SCSI_START_STOP_UNIT_POWER_CONDITION_LU_CONTROL 0x7
|
||||
#define SCSI_START_STOP_UNIT_POWER_CONDITION_FORCE_S_CONTROL 0xB
|
||||
|
||||
#define SCSI_START_STOP_UNIT_IMMED_MASK 0x1
|
||||
#define SCSI_START_STOP_UNIT_IMMED_SHIFT 0
|
||||
|
||||
#define SCSI_START_STOP_UNIT_START_BIT_MASK 0x1
|
||||
#define SCSI_START_STOP_UNIT_START_BIT_SHIFT 0
|
||||
|
||||
#define SCSI_START_STOP_UNIT_LOEJ_BIT_MASK 0x2
|
||||
#define SCSI_START_STOP_UNIT_LOEJ_BIT_SHIFT 1
|
||||
|
||||
#define SCSI_START_STOP_UNIT_NO_FLUSH_MASK 0x4
|
||||
#define SCSI_START_STOP_UNIT_NO_FLUSH_SHIFT 2
|
||||
|
||||
#define SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_MASK 0xF
|
||||
#define SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_SHIFT 0
|
||||
|
||||
#define SCSI_START_STOP_UNIT_POWER_CONDITION_MASK 0xF0
|
||||
#define SCSI_START_STOP_UNIT_POWER_CONDITION_SHIFT 4
|
||||
|
||||
#define SCSI_LOG_SENSE_PC_FIELD_MASK 0xC0
|
||||
#define SCSI_LOG_SENSE_PC_FIELD_SHIFT 6
|
||||
|
||||
#define SCSI_LOG_SENSE_PAGE_CODE_FIELD_MASK 0x3F
|
||||
#define SCSI_LOG_SENSE_PAGE_CODE_FIELD_SHIFT 0
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* MRIE - Method of reporting informational exceptions codes
|
||||
*/
|
||||
#define NO_REPORTING_INFO_EXCEPTION_CONDITION 0x0
|
||||
#define ASYNCHRONOUS_EVENT_REPORTING 0x1
|
||||
#define ESTABLISH_UNIT_ATTENTION_CONDITION 0x2
|
||||
#define CONDITIONALLY_GENERATE_RECOVERED_ERROR 0x3
|
||||
#define UNCONDITIONALLY_GENERATE_RECOVERED_ERROR 0x4
|
||||
#define GENERATE_NO_SENSE 0x5
|
||||
#define REPORT_INFO_EXCEPTION_CONDITION_ON_REQUEST 0x6
|
||||
|
||||
#define SCSI_INFORMATION_EXCEPTION_DEXCPT_BIT 0x08
|
||||
|
||||
/* Reassign Blocks masks */
|
||||
#define SCSI_REASSIGN_BLOCKS_LONGLBA_BIT 0x02
|
||||
#define SCSI_REASSIGN_BLOCKS_LONGLIST_BIT 0x01
|
||||
|
||||
#endif /* _SCSI_H_ */
|
||||
|
||||
156
drivers/scsi/isci/core/sati_device.h
Normal file
156
drivers/scsi/isci/core/sati_device.h
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SATI_DEVICE_H_
|
||||
#define _SATI_DEVICE_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the defintions for the SATI remote device object.
|
||||
* Some translations require information to be remembered on a per device
|
||||
* basis. This information is stored in the object defined in this file.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sati_types.h"
|
||||
#include "intel_ata.h"
|
||||
|
||||
/**
|
||||
* enum _SATI_DEVICE_STATE - This enumeration depicts the various states
|
||||
* possible for the a translation remote device object.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sati_device_state {
|
||||
SATI_DEVICE_STATE_OPERATIONAL,
|
||||
SATI_DEVICE_STATE_STOPPED,
|
||||
SATI_DEVICE_STATE_STANDBY,
|
||||
SATI_DEVICE_STATE_IDLE,
|
||||
SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED,
|
||||
SATI_DEVICE_STATE_FORMAT_UNIT_IN_PROGRESS,
|
||||
SATI_DEVICE_STATE_SELF_TEST_IN_PROGRESS,
|
||||
SATI_DEVICE_STATE_SEQUENCE_INCOMPLETE,
|
||||
SATI_DEVICE_STATE_UNIT_ATTENTION_CONDITION
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SATI_DEVICE_CAPABILITIES These constants define the various capabilities
|
||||
* that a remote device may support for which there is an impact on translation.
|
||||
*/
|
||||
#define SATI_DEVICE_CAP_UDMA_ENABLE 0x00000001
|
||||
#define SATI_DEVICE_CAP_NCQ_REQUESTED_ENABLE 0x00000002
|
||||
#define SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE 0x00000004
|
||||
#define SATI_DEVICE_CAP_48BIT_ENABLE 0x00000008
|
||||
#define SATI_DEVICE_CAP_DMA_FUA_ENABLE 0x00000010
|
||||
#define SATI_DEVICE_CAP_SMART_SUPPORT 0x00000020
|
||||
#define SATI_DEVICE_CAP_REMOVABLE_MEDIA 0x00000040
|
||||
#define SATI_DEVICE_CAP_SMART_ENABLE 0x00000080
|
||||
#define SATI_DEVICE_CAP_WRITE_UNCORRECTABLE_ENABLE 0x00000100
|
||||
#define SATI_DEVICE_CAP_MULTIPLE_SECTORS_PER_PHYSCIAL_SECTOR 0x00000200
|
||||
#define SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT 0x00000400
|
||||
|
||||
|
||||
/**
|
||||
* struct sati_device - The SATI_DEVICE structure define the state of the
|
||||
* remote device with respect to translation.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sati_device {
|
||||
/**
|
||||
* This field simply dictates the state of the SATI device.
|
||||
*/
|
||||
enum sati_device_state state;
|
||||
|
||||
/**
|
||||
* This field indicates features supported by the remote device that
|
||||
* impact translation execution.
|
||||
*/
|
||||
u16 capabilities;
|
||||
|
||||
/**
|
||||
* This field indicates the depth of the native command queue supported
|
||||
* by the device.
|
||||
*/
|
||||
u8 ncq_depth;
|
||||
|
||||
/**
|
||||
* This field stores the additional sense code for a unit attention
|
||||
* condition.
|
||||
*/
|
||||
u8 unit_attention_asc;
|
||||
|
||||
/**
|
||||
* This field indicates the additional sense code qualifier for a unit
|
||||
* attention condition.
|
||||
*/
|
||||
u8 unit_attention_ascq;
|
||||
|
||||
};
|
||||
|
||||
void sati_device_construct(
|
||||
struct sati_device *device,
|
||||
bool is_ncq_enabled,
|
||||
u8 max_ncq_depth);
|
||||
|
||||
void sati_device_update_capabilities(
|
||||
struct sati_device *device,
|
||||
struct ata_identify_device_data *identify);
|
||||
|
||||
#endif /* _SATI_TRANSLATOR_SEQUENCE_H_ */
|
||||
|
||||
304
drivers/scsi/isci/core/sati_translator_sequence.h
Normal file
304
drivers/scsi/isci/core/sati_translator_sequence.h
Normal file
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SATI_TRANSLATOR_SEQUENCE_H_
|
||||
#define _SATI_TRANSLATOR_SEQUENCE_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the defintions for the SATI translator sequence.
|
||||
* A translator sequence is simply a defintion for the various sequences of
|
||||
* commands that occur in this translator.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sati_device.h"
|
||||
|
||||
/**
|
||||
* enum _SATI_TRANSLATOR_SEQUENCE_TYPE - This enumeration defines the possible
|
||||
* sequence types for the translator.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sati_translator_sequence_type {
|
||||
/* SCSI Primary Command (SPC) sequences. */
|
||||
SATI_SEQUENCE_REPORT_LUNS,
|
||||
SATI_SEQUENCE_TEST_UNIT_READY,
|
||||
SATI_SEQUENCE_INQUIRY_STANDARD,
|
||||
SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES,
|
||||
SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER,
|
||||
SATI_SEQUENCE_INQUIRY_DEVICE_ID,
|
||||
SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE,
|
||||
SATI_SEQUENCE_MODE_SENSE_6_CACHING,
|
||||
SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL,
|
||||
SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR,
|
||||
SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT,
|
||||
SATI_SEQUENCE_MODE_SENSE_6_CONTROL,
|
||||
SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES,
|
||||
SATI_SEQUENCE_MODE_SENSE_10_CACHING,
|
||||
SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL,
|
||||
SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR,
|
||||
SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT,
|
||||
SATI_SEQUENCE_MODE_SENSE_10_CONTROL,
|
||||
SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES,
|
||||
SATI_SEQUENCE_MODE_SELECT_MODE_PAGE_CACHING,
|
||||
SATI_SEQUENCE_MODE_SELECT_MODE_POWER_CONDITION,
|
||||
SATI_SEQUENCE_MODE_SELECT_MODE_INFORMATION_EXCEPT_CONTROL,
|
||||
|
||||
/* Log Sense Sequences */
|
||||
SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE,
|
||||
SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE,
|
||||
SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE,
|
||||
SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE,
|
||||
|
||||
/* SCSI Block Command (SBC) sequences. */
|
||||
|
||||
SATI_SEQUENCE_READ_6,
|
||||
SATI_SEQUENCE_READ_10,
|
||||
SATI_SEQUENCE_READ_12,
|
||||
SATI_SEQUENCE_READ_16,
|
||||
|
||||
SATI_SEQUENCE_READ_CAPACITY_10,
|
||||
SATI_SEQUENCE_READ_CAPACITY_16,
|
||||
|
||||
SATI_SEQUENCE_SYNCHRONIZE_CACHE,
|
||||
|
||||
SATI_SEQUENCE_VERIFY_10,
|
||||
SATI_SEQUENCE_VERIFY_12,
|
||||
SATI_SEQUENCE_VERIFY_16,
|
||||
|
||||
SATI_SEQUENCE_WRITE_6,
|
||||
SATI_SEQUENCE_WRITE_10,
|
||||
SATI_SEQUENCE_WRITE_12,
|
||||
SATI_SEQUENCE_WRITE_16,
|
||||
|
||||
SATI_SEQUENCE_START_STOP_UNIT,
|
||||
|
||||
SATI_SEQUENCE_REASSIGN_BLOCKS,
|
||||
|
||||
/* SCSI Task Requests sequences */
|
||||
|
||||
SATI_SEQUENCE_LUN_RESET,
|
||||
|
||||
SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS,
|
||||
SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE,
|
||||
|
||||
SATI_SEQUENCE_WRITE_LONG
|
||||
|
||||
};
|
||||
|
||||
#define SATI_SEQUENCE_TYPE_READ_MIN SATI_SEQUENCE_READ_6
|
||||
#define SATI_SEQUENCE_TYPE_READ_MAX SATI_SEQUENCE_READ_16
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SATI_SEQUENCE_STATES These constants depict the various state values
|
||||
* associated with a translation sequence.
|
||||
*/
|
||||
#define SATI_SEQUENCE_STATE_INITIAL 0
|
||||
#define SATI_SEQUENCE_STATE_TRANSLATE_DATA 1
|
||||
#define SATI_SEQUENCE_STATE_AWAIT_RESPONSE 2
|
||||
#define SATI_SEQUENCE_STATE_FINAL 3
|
||||
#define SATI_SEQUENCE_STATE_INCOMPLETE 4
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SATI_DATA_DIRECTIONS These constants depict the various types of data
|
||||
* directions for a translation sequence. Data can flow in/out (read/write) or
|
||||
* no data at all.
|
||||
*/
|
||||
#define SATI_DATA_DIRECTION_NONE 0
|
||||
#define SATI_DATA_DIRECTION_IN 1
|
||||
#define SATI_DATA_DIRECTION_OUT 2
|
||||
|
||||
/**
|
||||
* struct SATI_MODE_SELECT_PROCESSING_STATE - This structure contains all of
|
||||
* the current processing states for processing mode select 6 and 10
|
||||
* commands' parameter fields.
|
||||
*
|
||||
*
|
||||
*/
|
||||
typedef struct SATI_MODE_SELECT_PROCESSING_STATE {
|
||||
u8 *mode_pages;
|
||||
u32 mode_page_offset;
|
||||
u32 mode_pages_size;
|
||||
u32 size_of_data_processed;
|
||||
u32 total_ata_command_sent;
|
||||
u32 ata_command_sent_for_cmp; /* cmp: current mode page */
|
||||
bool current_mode_page_processed;
|
||||
|
||||
} SATI_MODE_SELECT_PROCESSING_STATE_T;
|
||||
|
||||
|
||||
enum SATI_REASSIGN_BLOCKS_ATA_COMMAND_STATUS {
|
||||
SATI_REASSIGN_BLOCKS_READY_TO_SEND,
|
||||
SATI_REASSIGN_BLOCKS_COMMAND_FAIL,
|
||||
SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sati_reassign_blocks_processing_state - This structure contains all
|
||||
* of the current processing states for processing reassign block command's
|
||||
* parameter fields.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sati_reassign_blocks_processing_state {
|
||||
u32 lba_offset;
|
||||
u32 block_lists_size;
|
||||
u8 lba_size;
|
||||
u32 size_of_data_processed;
|
||||
u32 ata_command_sent_for_current_lba;
|
||||
bool current_lba_processed;
|
||||
enum SATI_REASSIGN_BLOCKS_ATA_COMMAND_STATUS ata_command_status;
|
||||
|
||||
};
|
||||
|
||||
#define SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH 12
|
||||
|
||||
/**
|
||||
* struct sati_atapi_data - The SATI_ATAPI_DATA structure is for sati atapi IO
|
||||
* specific data.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sati_atapi_data {
|
||||
u8 request_sense_cdb[SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sati_translator_sequence - This structure contains all of the
|
||||
* translation information associated with a particular request.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sati_translator_sequence {
|
||||
/**
|
||||
* This field contains the sequence type determined by the SATI.
|
||||
*/
|
||||
u8 type;
|
||||
|
||||
/**
|
||||
* This field indicates the current state for the sequence.
|
||||
*/
|
||||
u8 state;
|
||||
|
||||
/**
|
||||
* This field indicates the data direction (none, read, or write) for
|
||||
* the translated request.
|
||||
*/
|
||||
u8 data_direction;
|
||||
|
||||
/**
|
||||
* This field contains the SATA/ATA protocol to be utilized during
|
||||
* the IO transfer.
|
||||
*/
|
||||
u8 protocol;
|
||||
|
||||
/**
|
||||
* This field is utilized for sequences requiring data translation.
|
||||
* It specifies the amount of data requested by the caller from the
|
||||
* operation. It's necessary, because at times the user requests less
|
||||
* data than is available. Thus, we need to avoid overrunning the
|
||||
* buffer.
|
||||
*/
|
||||
u32 allocation_length;
|
||||
|
||||
/**
|
||||
* This field specifies the amount of data that will actually be
|
||||
* transfered across the wire for this ATA request.
|
||||
*/
|
||||
u32 ata_transfer_length;
|
||||
|
||||
/**
|
||||
* This field specifies the amount of data bytes that have been
|
||||
* set in a translation sequence. It will be incremented every time
|
||||
* a data byte has been set by a sati translation.
|
||||
*/
|
||||
u16 number_data_bytes_set;
|
||||
|
||||
/**
|
||||
* This field indicates whether or not the sense response has been set
|
||||
* by the translation sequence.
|
||||
*/
|
||||
bool is_sense_response_set;
|
||||
|
||||
/**
|
||||
* This field specifies the remote device context for which this
|
||||
* translator sequence is destined.
|
||||
*/
|
||||
struct sati_device *device;
|
||||
|
||||
/**
|
||||
* This field is utilized to provide the translator with memory space
|
||||
* required for translations that utilize multiple requests.
|
||||
*/
|
||||
union {
|
||||
u32 translated_command;
|
||||
u32 move_sector_count;
|
||||
u32 scratch;
|
||||
struct sati_reassign_blocks_processing_state reassign_blocks_process_state;
|
||||
SATI_MODE_SELECT_PROCESSING_STATE_T process_state;
|
||||
struct sati_atapi_data sati_atapi_data;
|
||||
} command_specific_data;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* _SATI_TRANSLATOR_SEQUENCE_H_ */
|
||||
|
||||
145
drivers/scsi/isci/core/sati_types.h
Normal file
145
drivers/scsi/isci/core/sati_types.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SATI_TYPES_H_
|
||||
#define _SATI_TYPES_H_
|
||||
|
||||
/**
|
||||
* This file contains various type definitions to be utilized with SCSI to ATA
|
||||
* Translation Implementation.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* enum _SATI_STATUS - This enumeration defines the possible return values from
|
||||
* the SATI translation methods.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sati_status {
|
||||
/**
|
||||
* This indicates that the translation was supported and occurred
|
||||
* without error.
|
||||
*/
|
||||
SATI_SUCCESS,
|
||||
|
||||
/**
|
||||
* This indicates that the translation was supported, occurred without
|
||||
* error, and no additional translation is necessary. This is done in
|
||||
* conditions where the SCSI command doesn't require any interaction with
|
||||
* the remote device.
|
||||
*/
|
||||
SATI_COMPLETE,
|
||||
|
||||
/**
|
||||
* This indicated everything SATI_COMPLETE does in addition to the response data
|
||||
* not using all the memory allocated by the OS.
|
||||
*/
|
||||
SATI_COMPLETE_IO_DONE_EARLY,
|
||||
|
||||
/**
|
||||
* This indicates that translator sequence has finished some specific
|
||||
* command in the sequence, but additional commands are necessary.
|
||||
*/
|
||||
SATI_SEQUENCE_INCOMPLETE,
|
||||
|
||||
/**
|
||||
* This indicates a general failure has occurred for which no further
|
||||
* specification information is available.
|
||||
*/
|
||||
SATI_FAILURE,
|
||||
|
||||
/**
|
||||
* This indicates that the result of the IO request indicates a
|
||||
* failure. The caller should reference the corresponding response
|
||||
* data for further details.
|
||||
*/
|
||||
SATI_FAILURE_CHECK_RESPONSE_DATA,
|
||||
|
||||
/**
|
||||
* This status indicates that the supplied sequence type doesn't map
|
||||
* to an existing definition.
|
||||
*/
|
||||
SATI_FAILURE_INVALID_SEQUENCE_TYPE,
|
||||
|
||||
/**
|
||||
* This status indicates that the supplied sequence state doesn't match
|
||||
* the operation being requested by the user.
|
||||
*/
|
||||
SATI_FAILURE_INVALID_STATE
|
||||
|
||||
};
|
||||
|
||||
#if (!defined(DISABLE_SATI_MODE_SENSE) \
|
||||
|| !defined(DISABLE_SATI_MODE_SELECT) \
|
||||
|| !defined(DISABLE_SATI_REQUEST_SENSE)) \
|
||||
|
||||
#if !defined(ENABLE_SATI_MODE_PAGES)
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This macro enables the common mode page data structures and code. Currently,
|
||||
* MODE SENSE, MODE SELECT, and REQUEST SENSE all make reference to this common
|
||||
* code. As a result, enable the common mode page code if any of these 3 are
|
||||
* being translated.
|
||||
*/
|
||||
#define ENABLE_SATI_MODE_PAGES
|
||||
#endif /* !defined(ENABLE_SATI_MODE_PAGES) */
|
||||
|
||||
#endif /* MODE_SENSE/SELECT/REQUEST_SENSE */
|
||||
|
||||
#endif /* _SATI_TYPES_H_ */
|
||||
|
||||
306
drivers/scsi/isci/core/sci_base_controller.h
Normal file
306
drivers/scsi/isci/core/sci_base_controller.h
Normal file
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_BASE_CONTROLLER_H_
|
||||
#define _SCI_BASE_CONTROLLER_H_
|
||||
|
||||
#include "intel_sas.h"
|
||||
#include "sci_controller_constants.h"
|
||||
#include "sci_base_state.h"
|
||||
#include "sci_base_memory_descriptor_list.h"
|
||||
#include "sci_base_state_machine.h"
|
||||
#include "sci_object.h"
|
||||
|
||||
struct sci_base_memory_descriptor_list;
|
||||
|
||||
/**
|
||||
* enum sci_base_controller_states - This enumeration depicts all the states
|
||||
* for the common controller state machine.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_base_controller_states {
|
||||
/**
|
||||
* Simply the initial state for the base controller state machine.
|
||||
*/
|
||||
SCI_BASE_CONTROLLER_STATE_INITIAL = 0,
|
||||
|
||||
/**
|
||||
* This state indicates that the controller is reset. The memory for
|
||||
* the controller is in it's initial state, but the controller requires
|
||||
* initialization.
|
||||
* This state is entered from the INITIAL state.
|
||||
* This state is entered from the RESETTING state.
|
||||
*/
|
||||
SCI_BASE_CONTROLLER_STATE_RESET,
|
||||
|
||||
/**
|
||||
* This state is typically an action state that indicates the controller
|
||||
* is in the process of initialization. In this state no new IO operations
|
||||
* are permitted.
|
||||
* This state is entered from the RESET state.
|
||||
*/
|
||||
SCI_BASE_CONTROLLER_STATE_INITIALIZING,
|
||||
|
||||
/**
|
||||
* This state indicates that the controller has been successfully
|
||||
* initialized. In this state no new IO operations are permitted.
|
||||
* This state is entered from the INITIALIZING state.
|
||||
*/
|
||||
SCI_BASE_CONTROLLER_STATE_INITIALIZED,
|
||||
|
||||
/**
|
||||
* This state indicates the the controller is in the process of becoming
|
||||
* ready (i.e. starting). In this state no new IO operations are permitted.
|
||||
* This state is entered from the INITIALIZED state.
|
||||
*/
|
||||
SCI_BASE_CONTROLLER_STATE_STARTING,
|
||||
|
||||
/**
|
||||
* This state indicates the controller is now ready. Thus, the user
|
||||
* is able to perform IO operations on the controller.
|
||||
* This state is entered from the STARTING state.
|
||||
*/
|
||||
SCI_BASE_CONTROLLER_STATE_READY,
|
||||
|
||||
/**
|
||||
* This state is typically an action state that indicates the controller
|
||||
* is in the process of resetting. Thus, the user is unable to perform
|
||||
* IO operations on the controller. A reset is considered destructive in
|
||||
* most cases.
|
||||
* This state is entered from the READY state.
|
||||
* This state is entered from the FAILED state.
|
||||
* This state is entered from the STOPPED state.
|
||||
*/
|
||||
SCI_BASE_CONTROLLER_STATE_RESETTING,
|
||||
|
||||
/**
|
||||
* This state indicates that the controller is in the process of stopping.
|
||||
* In this state no new IO operations are permitted, but existing IO
|
||||
* operations are allowed to complete.
|
||||
* This state is entered from the READY state.
|
||||
*/
|
||||
SCI_BASE_CONTROLLER_STATE_STOPPING,
|
||||
|
||||
/**
|
||||
* This state indicates that the controller has successfully been stopped.
|
||||
* In this state no new IO operations are permitted.
|
||||
* This state is entered from the STOPPING state.
|
||||
*/
|
||||
SCI_BASE_CONTROLLER_STATE_STOPPED,
|
||||
|
||||
/**
|
||||
* This state indicates that the controller could not successfully be
|
||||
* initialized. In this state no new IO operations are permitted.
|
||||
* This state is entered from the INITIALIZING state.
|
||||
* This state is entered from the STARTING state.
|
||||
* This state is entered from the STOPPING state.
|
||||
* This state is entered from the RESETTING state.
|
||||
*/
|
||||
SCI_BASE_CONTROLLER_STATE_FAILED,
|
||||
|
||||
SCI_BASE_CONTROLLER_MAX_STATES
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sci_base_controller - The base controller object abstracts the fields
|
||||
* common to all SCI controller objects.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_base_controller {
|
||||
/**
|
||||
* The field specifies that the parent object for the base controller
|
||||
* is the base object itself.
|
||||
*/
|
||||
struct sci_base_object parent;
|
||||
|
||||
/**
|
||||
* This field points to the memory descriptor list associated with this
|
||||
* controller. The MDL indicates the memory requirements necessary for
|
||||
* this controller object.
|
||||
*/
|
||||
struct sci_base_memory_descriptor_list mdl;
|
||||
|
||||
/**
|
||||
* This field contains the information for the base controller state
|
||||
* machine.
|
||||
*/
|
||||
struct sci_base_state_machine state_machine;
|
||||
};
|
||||
|
||||
/* Forward declarations */
|
||||
struct sci_base_remote_device;
|
||||
struct sci_base_request;
|
||||
|
||||
typedef enum sci_status
|
||||
(*sci_base_controller_handler_t)(struct sci_base_controller *);
|
||||
|
||||
typedef enum sci_status
|
||||
(*sci_base_controller_timed_handler_t)(struct sci_base_controller *, u32);
|
||||
|
||||
typedef enum sci_status
|
||||
(*sci_base_controller_request_handler_t)(struct sci_base_controller *,
|
||||
struct sci_base_remote_device *,
|
||||
struct sci_base_request *);
|
||||
|
||||
typedef enum sci_status
|
||||
(*sci_base_controller_start_request_handler_t)(struct sci_base_controller *,
|
||||
struct sci_base_remote_device *,
|
||||
struct sci_base_request *, u16);
|
||||
|
||||
/**
|
||||
* struct sci_base_controller_state_handler - This structure contains all of
|
||||
* the state handler methods common to base controller state machines.
|
||||
* Handler methods provide the ability to change the behavior for user
|
||||
* requests or transitions depending on the state the machine is in.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_base_controller_state_handler {
|
||||
/**
|
||||
* The start_handler specifies the method invoked when a user attempts to
|
||||
* start a controller.
|
||||
*/
|
||||
sci_base_controller_timed_handler_t start;
|
||||
|
||||
/**
|
||||
* The stop_handler specifies the method invoked when a user attempts to
|
||||
* stop a controller.
|
||||
*/
|
||||
sci_base_controller_timed_handler_t stop;
|
||||
|
||||
/**
|
||||
* The reset_handler specifies the method invoked when a user attempts to
|
||||
* reset a controller.
|
||||
*/
|
||||
sci_base_controller_handler_t reset;
|
||||
|
||||
/**
|
||||
* The initialize_handler specifies the method invoked when a user
|
||||
* attempts to initialize a controller.
|
||||
*/
|
||||
sci_base_controller_handler_t initialize;
|
||||
|
||||
/**
|
||||
* The start_io_handler specifies the method invoked when a user
|
||||
* attempts to start an IO request for a controller.
|
||||
*/
|
||||
sci_base_controller_start_request_handler_t start_io;
|
||||
|
||||
/**
|
||||
* The complete_io_handler specifies the method invoked when a user
|
||||
* attempts to complete an IO request for a controller.
|
||||
*/
|
||||
sci_base_controller_request_handler_t complete_io;
|
||||
|
||||
/**
|
||||
* The continue_io_handler specifies the method invoked when a user
|
||||
* attempts to continue an IO request for a controller.
|
||||
*/
|
||||
sci_base_controller_request_handler_t continue_io;
|
||||
|
||||
/**
|
||||
* The start_task_handler specifies the method invoked when a user
|
||||
* attempts to start a task management request for a controller.
|
||||
*/
|
||||
sci_base_controller_start_request_handler_t start_task;
|
||||
|
||||
/**
|
||||
* The complete_task_handler specifies the method invoked when a user
|
||||
* attempts to complete a task management request for a controller.
|
||||
*/
|
||||
sci_base_controller_request_handler_t complete_task;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* sci_base_controller_construct() - Construct the base controller
|
||||
* @this_controller: This parameter specifies the base controller to be
|
||||
* constructed.
|
||||
* @state_table: This parameter specifies the table of state definitions to be
|
||||
* utilized for the controller state machine.
|
||||
* @mde_array: This parameter specifies the array of memory descriptor entries
|
||||
* to be managed by this list.
|
||||
* @mde_array_length: This parameter specifies the size of the array of entries.
|
||||
* @next_mdl: This parameter specifies a subsequent MDL object to be managed by
|
||||
* this MDL object.
|
||||
* @oem_parameters: This parameter specifies the original equipment
|
||||
* manufacturer parameters to be utilized by this controller object.
|
||||
*
|
||||
*/
|
||||
static inline void sci_base_controller_construct(
|
||||
struct sci_base_controller *scic_base,
|
||||
const struct sci_base_state *state_table,
|
||||
struct sci_physical_memory_descriptor *mdes,
|
||||
u32 mde_count,
|
||||
struct sci_base_memory_descriptor_list *next_mdl)
|
||||
{
|
||||
scic_base->parent.private = NULL;
|
||||
|
||||
sci_base_state_machine_construct(
|
||||
&scic_base->state_machine,
|
||||
&scic_base->parent,
|
||||
state_table,
|
||||
SCI_BASE_CONTROLLER_STATE_INITIAL
|
||||
);
|
||||
|
||||
sci_base_mdl_construct(&scic_base->mdl, mdes, mde_count, next_mdl);
|
||||
|
||||
sci_base_state_machine_start(&scic_base->state_machine);
|
||||
}
|
||||
|
||||
#endif /* _SCI_BASE_CONTROLLER_H_ */
|
||||
159
drivers/scsi/isci/core/sci_base_memory_descriptor_list.c
Normal file
159
drivers/scsi/isci/core/sci_base_memory_descriptor_list.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the base implementation for the memory descriptor list.
|
||||
* This is currently comprised of MDL iterator methods.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci_environment.h"
|
||||
#include "sci_base_memory_descriptor_list.h"
|
||||
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* * P U B L I C M E T H O D S
|
||||
* ****************************************************************************** */
|
||||
|
||||
void sci_mdl_first_entry(
|
||||
struct sci_base_memory_descriptor_list *base_mdl)
|
||||
{
|
||||
base_mdl->next_index = 0;
|
||||
|
||||
/*
|
||||
* If this MDL is managing another MDL, then recursively rewind that MDL
|
||||
* object as well. */
|
||||
if (base_mdl->next_mdl != SCI_INVALID_HANDLE)
|
||||
sci_mdl_first_entry(base_mdl->next_mdl);
|
||||
}
|
||||
|
||||
|
||||
void sci_mdl_next_entry(
|
||||
struct sci_base_memory_descriptor_list *base_mdl)
|
||||
{
|
||||
/*
|
||||
* If there is at least one more entry left in the array, then change
|
||||
* the next pointer to it. */
|
||||
if (base_mdl->next_index < base_mdl->length)
|
||||
base_mdl->next_index++;
|
||||
else if (base_mdl->next_index == base_mdl->length) {
|
||||
/*
|
||||
* This MDL has exhausted it's set of entries. If this MDL is managing
|
||||
* another MDL, then start iterating through that MDL. */
|
||||
if (base_mdl->next_mdl != SCI_INVALID_HANDLE)
|
||||
sci_mdl_next_entry(base_mdl->next_mdl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct sci_physical_memory_descriptor *sci_mdl_get_current_entry(
|
||||
struct sci_base_memory_descriptor_list *base_mdl)
|
||||
{
|
||||
if (base_mdl->next_index < base_mdl->length)
|
||||
return &base_mdl->mde_array[base_mdl->next_index];
|
||||
else if (base_mdl->next_index == base_mdl->length) {
|
||||
/*
|
||||
* This MDL has exhausted it's set of entries. If this MDL is managing
|
||||
* another MDL, then return it's current entry. */
|
||||
if (base_mdl->next_mdl != SCI_INVALID_HANDLE)
|
||||
return sci_mdl_get_current_entry(base_mdl->next_mdl);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* * P R O T E C T E D M E T H O D S
|
||||
* ****************************************************************************** */
|
||||
|
||||
void sci_base_mdl_construct(
|
||||
struct sci_base_memory_descriptor_list *mdl,
|
||||
struct sci_physical_memory_descriptor *mde_array,
|
||||
u32 mde_array_length,
|
||||
struct sci_base_memory_descriptor_list *next_mdl)
|
||||
{
|
||||
mdl->length = mde_array_length;
|
||||
mdl->mde_array = mde_array;
|
||||
mdl->next_index = 0;
|
||||
mdl->next_mdl = next_mdl;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
bool sci_base_mde_is_valid(
|
||||
struct sci_physical_memory_descriptor *mde,
|
||||
u32 alignment,
|
||||
u32 size,
|
||||
u16 attributes)
|
||||
{
|
||||
/* Only need the lower 32 bits to ensure alignment is met. */
|
||||
u32 physical_address = lower_32_bits(mde->physical_address);
|
||||
|
||||
if (
|
||||
((((unsigned long)mde->virtual_address) & (alignment - 1)) != 0)
|
||||
|| ((physical_address & (alignment - 1)) != 0)
|
||||
|| (mde->constant_memory_alignment != alignment)
|
||||
|| (mde->constant_memory_size != size)
|
||||
|| (mde->virtual_address == NULL)
|
||||
|| (mde->constant_memory_attributes != attributes)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
155
drivers/scsi/isci/core/sci_base_memory_descriptor_list.h
Normal file
155
drivers/scsi/isci/core/sci_base_memory_descriptor_list.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_
|
||||
#define _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_
|
||||
|
||||
/**
|
||||
* This file contains the protected interface structures, constants and
|
||||
* interface methods for the struct sci_base_memory_descriptor_list object.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "sci_types.h"
|
||||
#include "sci_memory_descriptor_list.h"
|
||||
|
||||
|
||||
/**
|
||||
* struct sci_base_memory_descriptor_list - This structure contains all of the
|
||||
* fields necessary to implement a simple stack for managing the list of
|
||||
* available controller indices.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_base_memory_descriptor_list {
|
||||
/**
|
||||
* This field indicates the length of the memory descriptor entry array.
|
||||
*/
|
||||
u32 length;
|
||||
|
||||
/**
|
||||
* This field is utilized to provide iterator pattern functionality.
|
||||
* It indicates the index of the next memory descriptor in the iteration.
|
||||
*/
|
||||
u32 next_index;
|
||||
|
||||
/**
|
||||
* This field will point to the list of memory descriptors.
|
||||
*/
|
||||
struct sci_physical_memory_descriptor *mde_array;
|
||||
|
||||
/**
|
||||
* This field simply allows a user to chain memory descriptor lists
|
||||
* together if desired. This field will be initialized to
|
||||
* SCI_INVALID_HANDLE.
|
||||
*/
|
||||
struct sci_base_memory_descriptor_list *next_mdl;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* sci_base_mdl_construct() - This method is invoked to construct an memory
|
||||
* descriptor list. It initializes the fields of the MDL.
|
||||
* @mdl: This parameter specifies the memory descriptor list to be constructed.
|
||||
* @mde_array: This parameter specifies the array of memory descriptor entries
|
||||
* to be managed by this list.
|
||||
* @mde_array_length: This parameter specifies the size of the array of entries.
|
||||
* @next_mdl: This parameter specifies a subsequent MDL object to be managed by
|
||||
* this MDL object.
|
||||
*
|
||||
* none.
|
||||
*/
|
||||
void sci_base_mdl_construct(
|
||||
struct sci_base_memory_descriptor_list *mdl,
|
||||
struct sci_physical_memory_descriptor *mde_array,
|
||||
u32 mde_array_length,
|
||||
struct sci_base_memory_descriptor_list *next_mdl);
|
||||
|
||||
/**
|
||||
* sci_base_mde_construct() -
|
||||
*
|
||||
* This macro constructs an memory descriptor entry with the given alignment
|
||||
* and size
|
||||
*/
|
||||
#define sci_base_mde_construct(mde, alignment, size, attributes) \
|
||||
{ \
|
||||
(mde)->constant_memory_alignment = (alignment); \
|
||||
(mde)->constant_memory_size = (size); \
|
||||
(mde)->constant_memory_attributes = (attributes); \
|
||||
}
|
||||
|
||||
/**
|
||||
* sci_base_mde_is_valid() - This method validates that the memory descriptor
|
||||
* is correctly filled out by the SCI User
|
||||
* @mde: This parameter is the mde entry to validate
|
||||
* @alignment: This parameter specifies the expected alignment of the memory
|
||||
* for the mde.
|
||||
* @size: This parameter specifies the memory size expected for the mde its
|
||||
* value should not have been changed by the SCI User.
|
||||
* @attributes: This parameter specifies the attributes for the memory
|
||||
* descriptor provided.
|
||||
*
|
||||
* bool This method returns an indication as to whether the supplied MDE is
|
||||
* valid or not. true The MDE is valid. false The MDE is not valid.
|
||||
*/
|
||||
bool sci_base_mde_is_valid(
|
||||
struct sci_physical_memory_descriptor *mde,
|
||||
u32 alignment,
|
||||
u32 size,
|
||||
u16 attributes);
|
||||
|
||||
#endif /* _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_ */
|
||||
205
drivers/scsi/isci/core/sci_base_phy.h
Normal file
205
drivers/scsi/isci/core/sci_base_phy.h
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_BASE_PHY_H_
|
||||
#define _SCI_BASE_PHY_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the structures, constants, and methods common to
|
||||
* all phy object definitions.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci_base_state_machine.h"
|
||||
|
||||
/**
|
||||
* enum sci_base_phy_states - This enumeration depicts the standard states
|
||||
* common to all phy state machine implementations.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_base_phy_states {
|
||||
/**
|
||||
* Simply the initial state for the base domain state machine.
|
||||
*/
|
||||
SCI_BASE_PHY_STATE_INITIAL,
|
||||
|
||||
/**
|
||||
* This state indicates that the phy has successfully been stopped.
|
||||
* In this state no new IO operations are permitted on this phy.
|
||||
* This state is entered from the INITIAL state.
|
||||
* This state is entered from the STARTING state.
|
||||
* This state is entered from the READY state.
|
||||
* This state is entered from the RESETTING state.
|
||||
*/
|
||||
SCI_BASE_PHY_STATE_STOPPED,
|
||||
|
||||
/**
|
||||
* This state indicates that the phy is in the process of becomming
|
||||
* ready. In this state no new IO operations are permitted on this phy.
|
||||
* This state is entered from the STOPPED state.
|
||||
* This state is entered from the READY state.
|
||||
* This state is entered from the RESETTING state.
|
||||
*/
|
||||
SCI_BASE_PHY_STATE_STARTING,
|
||||
|
||||
/**
|
||||
* This state indicates the the phy is now ready. Thus, the user
|
||||
* is able to perform IO operations utilizing this phy as long as it
|
||||
* is currently part of a valid port.
|
||||
* This state is entered from the STARTING state.
|
||||
*/
|
||||
SCI_BASE_PHY_STATE_READY,
|
||||
|
||||
/**
|
||||
* This state indicates that the phy is in the process of being reset.
|
||||
* In this state no new IO operations are permitted on this phy.
|
||||
* This state is entered from the READY state.
|
||||
*/
|
||||
SCI_BASE_PHY_STATE_RESETTING,
|
||||
|
||||
/**
|
||||
* Simply the final state for the base phy state machine.
|
||||
*/
|
||||
SCI_BASE_PHY_STATE_FINAL,
|
||||
|
||||
SCI_BASE_PHY_MAX_STATES
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sci_base_phy - This structure defines all of the fields common to PHY
|
||||
* objects.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_base_phy {
|
||||
/**
|
||||
* This field depicts the parent object (struct sci_base_object) for the phy.
|
||||
*/
|
||||
struct sci_base_object parent;
|
||||
|
||||
/**
|
||||
* This field contains the information for the base phy state machine.
|
||||
*/
|
||||
struct sci_base_state_machine state_machine;
|
||||
};
|
||||
|
||||
typedef enum sci_status (*SCI_BASE_PHY_HANDLER_T)(
|
||||
struct sci_base_phy *
|
||||
);
|
||||
|
||||
/**
|
||||
* struct sci_base_phy_state_handler - This structure contains all of the state
|
||||
* handler methods common to base phy state machines. Handler methods
|
||||
* provide the ability to change the behavior for user requests or
|
||||
* transitions depending on the state the machine is in.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_base_phy_state_handler {
|
||||
/**
|
||||
* The start_handler specifies the method invoked when there is an
|
||||
* attempt to start a phy.
|
||||
*/
|
||||
SCI_BASE_PHY_HANDLER_T start_handler;
|
||||
|
||||
/**
|
||||
* The stop_handler specifies the method invoked when there is an
|
||||
* attempt to stop a phy.
|
||||
*/
|
||||
SCI_BASE_PHY_HANDLER_T stop_handler;
|
||||
|
||||
/**
|
||||
* The reset_handler specifies the method invoked when there is an
|
||||
* attempt to reset a phy.
|
||||
*/
|
||||
SCI_BASE_PHY_HANDLER_T reset_handler;
|
||||
|
||||
/**
|
||||
* The destruct_handler specifies the method invoked when attempting to
|
||||
* destruct a phy.
|
||||
*/
|
||||
SCI_BASE_PHY_HANDLER_T destruct_handler;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* sci_base_phy_construct() - Construct the base phy
|
||||
* @this_phy: This parameter specifies the base phy to be constructed.
|
||||
* @state_table: This parameter specifies the table of state definitions to be
|
||||
* utilized for the phy state machine.
|
||||
*
|
||||
*/
|
||||
static inline void sci_base_phy_construct(
|
||||
struct sci_base_phy *base_phy,
|
||||
const struct sci_base_state *state_table)
|
||||
{
|
||||
base_phy->parent.private = NULL;
|
||||
sci_base_state_machine_construct(
|
||||
&base_phy->state_machine,
|
||||
&base_phy->parent,
|
||||
state_table,
|
||||
SCI_BASE_PHY_STATE_INITIAL
|
||||
);
|
||||
|
||||
sci_base_state_machine_start(
|
||||
&base_phy->state_machine
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#endif /* _SCI_BASE_PHY_H_ */
|
||||
203
drivers/scsi/isci/core/sci_base_port.h
Normal file
203
drivers/scsi/isci/core/sci_base_port.h
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_BASE_PORT_H_
|
||||
#define _SCI_BASE_PORT_H_
|
||||
|
||||
#include "sci_base_state_machine.h"
|
||||
#include "sci_object.h"
|
||||
|
||||
/**
|
||||
* enum sci_base_port_states - This enumeration depicts all the states for the
|
||||
* common port state machine.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_base_port_states {
|
||||
/**
|
||||
* This state indicates that the port has successfully been stopped.
|
||||
* In this state no new IO operations are permitted.
|
||||
* This state is entered from the STOPPING state.
|
||||
*/
|
||||
SCI_BASE_PORT_STATE_STOPPED,
|
||||
|
||||
/**
|
||||
* This state indicates that the port is in the process of stopping.
|
||||
* In this state no new IO operations are permitted, but existing IO
|
||||
* operations are allowed to complete.
|
||||
* This state is entered from the READY state.
|
||||
*/
|
||||
SCI_BASE_PORT_STATE_STOPPING,
|
||||
|
||||
/**
|
||||
* This state indicates the port is now ready. Thus, the user is
|
||||
* able to perform IO operations on this port.
|
||||
* This state is entered from the STARTING state.
|
||||
*/
|
||||
SCI_BASE_PORT_STATE_READY,
|
||||
|
||||
/**
|
||||
* This state indicates the port is in the process of performing a hard
|
||||
* reset. Thus, the user is unable to perform IO operations on this
|
||||
* port.
|
||||
* This state is entered from the READY state.
|
||||
*/
|
||||
SCI_BASE_PORT_STATE_RESETTING,
|
||||
|
||||
/**
|
||||
* This state indicates the port has failed a reset request. This state
|
||||
* is entered when a port reset request times out.
|
||||
* This state is entered from the RESETTING state.
|
||||
*/
|
||||
SCI_BASE_PORT_STATE_FAILED,
|
||||
|
||||
SCI_BASE_PORT_MAX_STATES
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sci_base_port - The base port object abstracts the fields common to
|
||||
* all SCI port objects.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_base_port {
|
||||
/**
|
||||
* The field specifies that the parent object for the base controller
|
||||
* is the base object itself.
|
||||
*/
|
||||
struct sci_base_object parent;
|
||||
|
||||
/**
|
||||
* This field contains the information for the base port state machine.
|
||||
*/
|
||||
struct sci_base_state_machine state_machine;
|
||||
};
|
||||
|
||||
struct sci_base_phy;
|
||||
|
||||
typedef enum sci_status (*SCI_BASE_PORT_HANDLER_T)(
|
||||
struct sci_base_port *
|
||||
);
|
||||
|
||||
typedef enum sci_status (*SCI_BASE_PORT_PHY_HANDLER_T)(
|
||||
struct sci_base_port *,
|
||||
struct sci_base_phy *
|
||||
);
|
||||
|
||||
typedef enum sci_status (*SCI_BASE_PORT_RESET_HANDLER_T)(
|
||||
struct sci_base_port *,
|
||||
u32 timeout
|
||||
);
|
||||
|
||||
/**
|
||||
* struct sci_base_port_state_handler - This structure contains all of the
|
||||
* state handler methods common to base port state machines. Handler
|
||||
* methods provide the ability to change the behavior for user requests or
|
||||
* transitions depending on the state the machine is in.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_base_port_state_handler {
|
||||
/**
|
||||
* The start_handler specifies the method invoked when a user attempts to
|
||||
* start a port.
|
||||
*/
|
||||
SCI_BASE_PORT_HANDLER_T start_handler;
|
||||
|
||||
/**
|
||||
* The stop_handler specifies the method invoked when a user attempts to
|
||||
* stop a port.
|
||||
*/
|
||||
SCI_BASE_PORT_HANDLER_T stop_handler;
|
||||
|
||||
/**
|
||||
* The destruct_handler specifies the method invoked when attempting to
|
||||
* destruct a port.
|
||||
*/
|
||||
SCI_BASE_PORT_HANDLER_T destruct_handler;
|
||||
|
||||
/**
|
||||
* The reset_handler specifies the method invoked when a user attempts to
|
||||
* hard reset a port.
|
||||
*/
|
||||
SCI_BASE_PORT_RESET_HANDLER_T reset_handler;
|
||||
|
||||
/**
|
||||
* The add_phy_handler specifies the method invoked when a user attempts to
|
||||
* add another phy into the port.
|
||||
*/
|
||||
SCI_BASE_PORT_PHY_HANDLER_T add_phy_handler;
|
||||
|
||||
/**
|
||||
* The remove_phy_handler specifies the method invoked when a user
|
||||
* attempts to remove a phy from the port.
|
||||
*/
|
||||
SCI_BASE_PORT_PHY_HANDLER_T remove_phy_handler;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* sci_base_port_construct() - Construct the base port object
|
||||
* @this_port: This parameter specifies the base port to be constructed.
|
||||
* @state_table: This parameter specifies the table of state definitions to be
|
||||
* utilized for the domain state machine.
|
||||
*
|
||||
*/
|
||||
void sci_base_port_construct(
|
||||
struct sci_base_port *this_port,
|
||||
const struct sci_base_state *state_table);
|
||||
|
||||
#endif /* _SCI_BASE_PORT_H_ */
|
||||
277
drivers/scsi/isci/core/sci_base_remote_device.h
Normal file
277
drivers/scsi/isci/core/sci_base_remote_device.h
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_BASE_REMOTE_DEVICE_H_
|
||||
#define _SCI_BASE_REMOTE_DEVICE_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the structures, constants, and methods common to
|
||||
* all remote device object definitions.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci_base_state_machine.h"
|
||||
|
||||
struct sci_base_request;
|
||||
|
||||
/**
|
||||
* enum sci_base_remote_device_states - This enumeration depicts all the states
|
||||
* for the common remote device state machine.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_base_remote_device_states {
|
||||
/**
|
||||
* Simply the initial state for the base remote device state machine.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_STATE_INITIAL,
|
||||
|
||||
/**
|
||||
* This state indicates that the remote device has successfully been
|
||||
* stopped. In this state no new IO operations are permitted.
|
||||
* This state is entered from the INITIAL state.
|
||||
* This state is entered from the STOPPING state.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_STATE_STOPPED,
|
||||
|
||||
/**
|
||||
* This state indicates the the remote device is in the process of
|
||||
* becoming ready (i.e. starting). In this state no new IO operations
|
||||
* are permitted.
|
||||
* This state is entered from the STOPPED state.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_STATE_STARTING,
|
||||
|
||||
/**
|
||||
* This state indicates the remote device is now ready. Thus, the user
|
||||
* is able to perform IO operations on the remote device.
|
||||
* This state is entered from the STARTING state.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_STATE_READY,
|
||||
|
||||
/**
|
||||
* This state indicates that the remote device is in the process of
|
||||
* stopping. In this state no new IO operations are permitted, but
|
||||
* existing IO operations are allowed to complete.
|
||||
* This state is entered from the READY state.
|
||||
* This state is entered from the FAILED state.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_STATE_STOPPING,
|
||||
|
||||
/**
|
||||
* This state indicates that the remote device has failed.
|
||||
* In this state no new IO operations are permitted.
|
||||
* This state is entered from the INITIALIZING state.
|
||||
* This state is entered from the READY state.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_STATE_FAILED,
|
||||
|
||||
/**
|
||||
* This state indicates the device is being reset.
|
||||
* In this state no new IO operations are permitted.
|
||||
* This state is entered from the READY state.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_STATE_RESETTING,
|
||||
|
||||
/**
|
||||
* Simply the final state for the base remote device state machine.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_STATE_FINAL,
|
||||
|
||||
SCI_BASE_REMOTE_DEVICE_MAX_STATES
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sci_base_remote_device - The base remote device object abstracts the
|
||||
* fields common to all SCI remote device objects.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_base_remote_device {
|
||||
/**
|
||||
* The field specifies that the parent object for the base remote
|
||||
* device is the base object itself.
|
||||
*/
|
||||
struct sci_base_object parent;
|
||||
|
||||
/**
|
||||
* This field contains the information for the base remote device state
|
||||
* machine.
|
||||
*/
|
||||
struct sci_base_state_machine state_machine;
|
||||
};
|
||||
|
||||
|
||||
typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_HANDLER_T)(
|
||||
struct sci_base_remote_device *
|
||||
);
|
||||
|
||||
typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T)(
|
||||
struct sci_base_remote_device *,
|
||||
struct sci_base_request *
|
||||
);
|
||||
|
||||
typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_HIGH_PRIORITY_REQUEST_COMPLETE_HANDLER_T)(
|
||||
struct sci_base_remote_device *,
|
||||
struct sci_base_request *,
|
||||
void *,
|
||||
enum sci_io_status
|
||||
);
|
||||
|
||||
/**
|
||||
* struct sci_base_remote_device_state_handler - This structure contains all of
|
||||
* the state handler methods common to base remote device state machines.
|
||||
* Handler methods provide the ability to change the behavior for user
|
||||
* requests or transitions depending on the state the machine is in.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_base_remote_device_state_handler {
|
||||
/**
|
||||
* The start_handler specifies the method invoked when a user attempts to
|
||||
* start a remote device.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_HANDLER_T start_handler;
|
||||
|
||||
/**
|
||||
* The stop_handler specifies the method invoked when a user attempts to
|
||||
* stop a remote device.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_HANDLER_T stop_handler;
|
||||
|
||||
/**
|
||||
* The fail_handler specifies the method invoked when a remote device
|
||||
* failure has occurred. A failure may be due to an inability to
|
||||
* initialize/configure the device.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_HANDLER_T fail_handler;
|
||||
|
||||
/**
|
||||
* The destruct_handler specifies the method invoked when attempting to
|
||||
* destruct a remote device.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_HANDLER_T destruct_handler;
|
||||
|
||||
/**
|
||||
* The reset handler specifies the method invloked when requesting to reset a
|
||||
* remote device.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_HANDLER_T reset_handler;
|
||||
|
||||
/**
|
||||
* The reset complete handler specifies the method invloked when reporting
|
||||
* that a reset has completed to the remote device.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_HANDLER_T reset_complete_handler;
|
||||
|
||||
/**
|
||||
* The start_io_handler specifies the method invoked when a user
|
||||
* attempts to start an IO request for a remote device.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T start_io_handler;
|
||||
|
||||
/**
|
||||
* The complete_io_handler specifies the method invoked when a user
|
||||
* attempts to complete an IO request for a remote device.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T complete_io_handler;
|
||||
|
||||
/**
|
||||
* The continue_io_handler specifies the method invoked when a user
|
||||
* attempts to continue an IO request for a remote device.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T continue_io_handler;
|
||||
|
||||
/**
|
||||
* The start_task_handler specifies the method invoked when a user
|
||||
* attempts to start a task management request for a remote device.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T start_task_handler;
|
||||
|
||||
/**
|
||||
* The complete_task_handler specifies the method invoked when a user
|
||||
* attempts to complete a task management request for a remote device.
|
||||
*/
|
||||
SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T complete_task_handler;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* sci_base_remote_device_construct() - Construct the base remote device
|
||||
* @this_remote_device: This parameter specifies the base remote device to be
|
||||
* constructed.
|
||||
* @state_table: This parameter specifies the table of state definitions to be
|
||||
* utilized for the remote device state machine.
|
||||
*
|
||||
*/
|
||||
static inline void sci_base_remote_device_construct(
|
||||
struct sci_base_remote_device *base_dev,
|
||||
const struct sci_base_state *state_table)
|
||||
{
|
||||
base_dev->parent.private = NULL;
|
||||
sci_base_state_machine_construct(
|
||||
&base_dev->state_machine,
|
||||
&base_dev->parent,
|
||||
state_table,
|
||||
SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
|
||||
);
|
||||
|
||||
sci_base_state_machine_start(
|
||||
&base_dev->state_machine
|
||||
);
|
||||
}
|
||||
#endif /* _SCI_BASE_REMOTE_DEVICE_H_ */
|
||||
195
drivers/scsi/isci/core/sci_base_request.h
Normal file
195
drivers/scsi/isci/core/sci_base_request.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_BASE_REQUST_H_
|
||||
#define _SCI_BASE_REQUST_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the constants, types, and method declarations for
|
||||
* the SCI base IO and task request objects.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci_base_state_machine.h"
|
||||
|
||||
/**
|
||||
* enum sci_base_request_states - This enumeration depicts all the states for
|
||||
* the common request state machine.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_base_request_states {
|
||||
/**
|
||||
* Simply the initial state for the base request state machine.
|
||||
*/
|
||||
SCI_BASE_REQUEST_STATE_INITIAL,
|
||||
|
||||
/**
|
||||
* This state indicates that the request has been constructed. This state
|
||||
* is entered from the INITIAL state.
|
||||
*/
|
||||
SCI_BASE_REQUEST_STATE_CONSTRUCTED,
|
||||
|
||||
/**
|
||||
* This state indicates that the request has been started. This state is
|
||||
* entered from the CONSTRUCTED state.
|
||||
*/
|
||||
SCI_BASE_REQUEST_STATE_STARTED,
|
||||
|
||||
/**
|
||||
* This state indicates that the request has completed.
|
||||
* This state is entered from the STARTED state. This state is entered from
|
||||
* the ABORTING state.
|
||||
*/
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED,
|
||||
|
||||
/**
|
||||
* This state indicates that the request is in the process of being
|
||||
* terminated/aborted.
|
||||
* This state is entered from the CONSTRUCTED state.
|
||||
* This state is entered from the STARTED state.
|
||||
*/
|
||||
SCI_BASE_REQUEST_STATE_ABORTING,
|
||||
|
||||
/**
|
||||
* Simply the final state for the base request state machine.
|
||||
*/
|
||||
SCI_BASE_REQUEST_STATE_FINAL,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sci_base_request - The base request object abstracts the fields
|
||||
* common to all SCI IO and task request objects.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_base_request {
|
||||
/**
|
||||
* The field specifies that the parent object for the base request is the
|
||||
* base object itself.
|
||||
*/
|
||||
struct sci_base_object parent;
|
||||
|
||||
/**
|
||||
* This field contains the information for the base request state machine.
|
||||
*/
|
||||
struct sci_base_state_machine state_machine;
|
||||
};
|
||||
|
||||
typedef enum sci_status (*SCI_BASE_REQUEST_HANDLER_T)(
|
||||
struct sci_base_request *this_request
|
||||
);
|
||||
|
||||
/**
|
||||
* struct sci_base_request_state_handler - This structure contains all of the
|
||||
* state handler methods common to base IO and task request state machines.
|
||||
* Handler methods provide the ability to change the behavior for user
|
||||
* requests or transitions depending on the state the machine is in.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_base_request_state_handler {
|
||||
/**
|
||||
* The start_handler specifies the method invoked when a user attempts to
|
||||
* start a request.
|
||||
*/
|
||||
SCI_BASE_REQUEST_HANDLER_T start_handler;
|
||||
|
||||
/**
|
||||
* The abort_handler specifies the method invoked when a user attempts to
|
||||
* abort a request.
|
||||
*/
|
||||
SCI_BASE_REQUEST_HANDLER_T abort_handler;
|
||||
|
||||
/**
|
||||
* The complete_handler specifies the method invoked when a user attempts to
|
||||
* complete a request.
|
||||
*/
|
||||
SCI_BASE_REQUEST_HANDLER_T complete_handler;
|
||||
|
||||
/**
|
||||
* The destruct_handler specifies the method invoked when a user attempts to
|
||||
* destruct a request.
|
||||
*/
|
||||
SCI_BASE_REQUEST_HANDLER_T destruct_handler;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* sci_base_request_construct() - Construct the base request.
|
||||
* @this_request: This parameter specifies the base request to be constructed.
|
||||
* @state_table: This parameter specifies the table of state definitions to be
|
||||
* utilized for the request state machine.
|
||||
*
|
||||
*/
|
||||
static inline void sci_base_request_construct(
|
||||
struct sci_base_request *base_req,
|
||||
const struct sci_base_state *my_state_table)
|
||||
{
|
||||
base_req->parent.private = NULL;
|
||||
sci_base_state_machine_construct(
|
||||
&base_req->state_machine,
|
||||
&base_req->parent,
|
||||
my_state_table,
|
||||
SCI_BASE_REQUEST_STATE_INITIAL
|
||||
);
|
||||
|
||||
sci_base_state_machine_start(
|
||||
&base_req->state_machine
|
||||
);
|
||||
}
|
||||
|
||||
#endif /* _SCI_BASE_REQUST_H_ */
|
||||
90
drivers/scsi/isci/core/sci_base_state.h
Normal file
90
drivers/scsi/isci/core/sci_base_state.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_BASE_STATE_H_
|
||||
#define _SCI_BASE_STATE_H_
|
||||
|
||||
#include "sci_object.h"
|
||||
|
||||
typedef void (*SCI_BASE_STATE_HANDLER_T)(
|
||||
void
|
||||
);
|
||||
|
||||
typedef void (*SCI_STATE_TRANSITION_T)(
|
||||
struct sci_base_object *base_object
|
||||
);
|
||||
|
||||
/**
|
||||
* struct sci_base_state - The base state object abstracts the fields common to
|
||||
* all state objects defined in SCI.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_base_state {
|
||||
/**
|
||||
* This field is a function pointer that defines the method to be
|
||||
* invoked when the state is entered.
|
||||
*/
|
||||
SCI_STATE_TRANSITION_T enter_state;
|
||||
|
||||
/**
|
||||
* This field is a function pointer that defines the method to be
|
||||
* invoked when the state is exited.
|
||||
*/
|
||||
SCI_STATE_TRANSITION_T exit_state;
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SCI_BASE_STATE_H_ */
|
||||
182
drivers/scsi/isci/core/sci_base_state_machine.c
Normal file
182
drivers/scsi/isci/core/sci_base_state_machine.c
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains all of the functionality common to all state machine
|
||||
* object implementations.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci_base_state_machine.h"
|
||||
|
||||
static void sci_state_machine_exit_state(struct sci_base_state_machine *sm)
|
||||
{
|
||||
u32 state = sm->current_state_id;
|
||||
SCI_STATE_TRANSITION_T exit = sm->state_table[state].exit_state;
|
||||
|
||||
if (exit)
|
||||
exit(sm->state_machine_owner);
|
||||
}
|
||||
|
||||
static void sci_state_machine_enter_state(struct sci_base_state_machine *sm)
|
||||
{
|
||||
u32 state = sm->current_state_id;
|
||||
SCI_STATE_TRANSITION_T enter = sm->state_table[state].enter_state;
|
||||
|
||||
if (enter)
|
||||
enter(sm->state_machine_owner);
|
||||
}
|
||||
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* * P R O T E C T E D M E T H O D S
|
||||
* ****************************************************************************** */
|
||||
|
||||
/**
|
||||
* This method will set the initial state and state table for the state
|
||||
* machine. The caller should follow this request with the initialize
|
||||
* request to cause the state machine to start.
|
||||
* @sm: This parameter provides the state machine object to be
|
||||
* constructed.
|
||||
* @state_machine_owner: This parameter indicates the object that is owns the
|
||||
* state machine being constructed.
|
||||
* @state_table: This parameter specifies the table of state objects that is
|
||||
* managed by this state machine.
|
||||
* @initial_state: This parameter specifies the value of the initial state for
|
||||
* this state machine.
|
||||
*
|
||||
*/
|
||||
void sci_base_state_machine_construct(struct sci_base_state_machine *sm,
|
||||
struct sci_base_object *owner,
|
||||
const struct sci_base_state *state_table,
|
||||
u32 initial_state)
|
||||
{
|
||||
sm->state_machine_owner = owner;
|
||||
sm->initial_state_id = initial_state;
|
||||
sm->previous_state_id = initial_state;
|
||||
sm->current_state_id = initial_state;
|
||||
sm->state_table = state_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will cause the state machine to enter the initial state.
|
||||
* @sm: This parameter specifies the state machine that is to
|
||||
* be started.
|
||||
*
|
||||
* sci_base_state_machine_construct() for how to set the initial state none
|
||||
*/
|
||||
void sci_base_state_machine_start(struct sci_base_state_machine *sm)
|
||||
{
|
||||
sm->current_state_id = sm->initial_state_id;
|
||||
#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
|
||||
sci_base_subject_notify(&sm->parent);
|
||||
#endif
|
||||
sci_state_machine_enter_state(sm);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will cause the state machine to exit it's current state only.
|
||||
* @sm: This parameter specifies the state machine that is to
|
||||
* be stopped.
|
||||
*
|
||||
*/
|
||||
void sci_base_state_machine_stop(
|
||||
struct sci_base_state_machine *sm)
|
||||
{
|
||||
sci_state_machine_exit_state(sm);
|
||||
#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
|
||||
sci_base_subject_notify(&sm->parent);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* This method performs an update to the current state of the state machine.
|
||||
* @sm: This parameter specifies the state machine for which
|
||||
* the caller wishes to perform a state change.
|
||||
* @next_state: This parameter specifies the new state for the state machine.
|
||||
*
|
||||
*/
|
||||
void sci_base_state_machine_change_state(
|
||||
struct sci_base_state_machine *sm,
|
||||
u32 next_state)
|
||||
{
|
||||
sci_state_machine_exit_state(sm);
|
||||
|
||||
sm->previous_state_id = sm->current_state_id;
|
||||
sm->current_state_id = next_state;
|
||||
|
||||
#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
|
||||
/* Notify of the state change prior to entering the state. */
|
||||
sci_base_subject_notify(&sm->parent);
|
||||
#endif
|
||||
|
||||
sci_state_machine_enter_state(sm);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method simply returns the current state of the state machine to the
|
||||
* caller.
|
||||
* @sm: This parameter specifies the state machine for which to
|
||||
* retrieve the current state.
|
||||
*
|
||||
* This method returns a u32 value indicating the current state for the
|
||||
* supplied state machine.
|
||||
*/
|
||||
u32 sci_base_state_machine_get_state(struct sci_base_state_machine *sm)
|
||||
{
|
||||
return sm->current_state_id;
|
||||
}
|
||||
|
||||
139
drivers/scsi/isci/core/sci_base_state_machine.h
Normal file
139
drivers/scsi/isci/core/sci_base_state_machine.h
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_BASE_STATE_MACHINE_H_
|
||||
#define _SCI_BASE_STATE_MACHINE_H_
|
||||
|
||||
/**
|
||||
* This file contains all structures, constants, or method declarations common
|
||||
* to all state machines defined in SCI.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "sci_base_state.h"
|
||||
|
||||
|
||||
/**
|
||||
* SET_STATE_HANDLER() -
|
||||
*
|
||||
* This macro simply provides simplified retrieval of an objects state handler.
|
||||
*/
|
||||
#define SET_STATE_HANDLER(object, table, state) \
|
||||
(object)->state_handlers = &(table)[(state)]
|
||||
|
||||
/**
|
||||
* struct sci_base_state_machine - This structure defines the fields common to
|
||||
* all state machines.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_base_state_machine {
|
||||
/**
|
||||
* This field points to the start of the state machine's state table.
|
||||
*/
|
||||
const struct sci_base_state *state_table;
|
||||
|
||||
/**
|
||||
* This field points to the object to which this state machine is
|
||||
* associated. It serves as a cookie to be provided to the state
|
||||
* enter/exit methods.
|
||||
*/
|
||||
struct sci_base_object *state_machine_owner;
|
||||
|
||||
/**
|
||||
* This field simply indicates the state value for the state machine's
|
||||
* initial state.
|
||||
*/
|
||||
u32 initial_state_id;
|
||||
|
||||
/**
|
||||
* This field indicates the current state of the state machine.
|
||||
*/
|
||||
u32 current_state_id;
|
||||
|
||||
/**
|
||||
* This field indicates the previous state of the state machine.
|
||||
*/
|
||||
u32 previous_state_id;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* * P R O T E C T E D M E T H O D S
|
||||
* ****************************************************************************** */
|
||||
|
||||
void sci_base_state_machine_construct(
|
||||
struct sci_base_state_machine *this_state_machine,
|
||||
struct sci_base_object *state_machine_owner,
|
||||
const struct sci_base_state *state_table,
|
||||
u32 initial_state);
|
||||
|
||||
void sci_base_state_machine_start(
|
||||
struct sci_base_state_machine *this_state_machine);
|
||||
|
||||
void sci_base_state_machine_stop(
|
||||
struct sci_base_state_machine *this_state_machine);
|
||||
|
||||
void sci_base_state_machine_change_state(
|
||||
struct sci_base_state_machine *this_state_machine,
|
||||
u32 next_state);
|
||||
|
||||
u32 sci_base_state_machine_get_state(
|
||||
struct sci_base_state_machine *this_state_machine);
|
||||
|
||||
#endif /* _SCI_BASE_STATE_MACHINE_H_ */
|
||||
100
drivers/scsi/isci/core/sci_controller.h
Normal file
100
drivers/scsi/isci/core/sci_controller.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_CONTROLLER_H_
|
||||
#define _SCI_CONTROLLER_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the interface methods that can be called by an SCI
|
||||
* user on all SCI controller objects.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "sci_types.h"
|
||||
|
||||
struct sci_base_memory_descriptor_list;
|
||||
struct scic_sds_controller;
|
||||
|
||||
#define SCI_CONTROLLER_INVALID_IO_TAG 0xFFFF
|
||||
|
||||
/**
|
||||
* sci_controller_get_memory_descriptor_list_handle() - This method simply
|
||||
* returns a handle for the memory descriptor list associated with the
|
||||
* supplied controller. The descriptor list provides DMA safe/capable
|
||||
* memory requirements for this controller.
|
||||
* @controller: This parameter specifies the controller for which to retrieve
|
||||
* the DMA safe memory descriptor list.
|
||||
*
|
||||
* The user must adhere to the alignment requirements specified in memory
|
||||
* descriptor. In situations where the operating environment does not offer
|
||||
* memory allocation utilities supporting alignment, then it is the
|
||||
* responsibility of the user to manually align the memory buffer for SCI.
|
||||
* Thus, the user may have to allocate a larger buffer to meet the alignment.
|
||||
* Additionally, the user will need to remember the actual memory allocation
|
||||
* addresses in order to ensure the memory can be properly freed when necessary
|
||||
* to do so. This method will return a valid handle, but the MDL may not be
|
||||
* accurate until after the user has invoked the associated
|
||||
* sci_controller_initialize() routine. A pointer to a physical memory
|
||||
* descriptor array.
|
||||
*/
|
||||
struct sci_base_memory_descriptor_list *
|
||||
sci_controller_get_memory_descriptor_list_handle(
|
||||
struct scic_sds_controller *controller);
|
||||
|
||||
|
||||
#endif /* _SCI_CONTROLLER_H_ */
|
||||
|
||||
215
drivers/scsi/isci/core/sci_controller_constants.h
Normal file
215
drivers/scsi/isci/core/sci_controller_constants.h
Normal file
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_CONTROLLER_CONSTANTS_H_
|
||||
#define _SCI_CONTROLLER_CONSTANTS_H_
|
||||
|
||||
/**
|
||||
* This file contains constant values that change based on the type of core or
|
||||
* framework being managed. These constants are exported in order to
|
||||
* provide the user with information as to the bounds (i.e. how many) of
|
||||
* specific objects.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef SCIC_SDS_4_ENABLED
|
||||
|
||||
#ifndef SCI_MAX_PHYS
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This constant defines the maximum number of phy objects that can be
|
||||
* supported for the SCU Driver Standard (SDS) library. This is tied directly
|
||||
* to silicon capabilities.
|
||||
*/
|
||||
#define SCI_MAX_PHYS (4)
|
||||
#endif
|
||||
|
||||
#ifndef SCI_MAX_PORTS
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This constant defines the maximum number of port objects that can be
|
||||
* supported for the SCU Driver Standard (SDS) library. This is tied directly
|
||||
* to silicon capabilities.
|
||||
*/
|
||||
#define SCI_MAX_PORTS SCI_MAX_PHYS
|
||||
#endif
|
||||
|
||||
#ifndef SCI_MIN_SMP_PHYS
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This constant defines the minimum number of SMP phy objects that can be
|
||||
* supported for a single expander level. This was determined by using 36
|
||||
* physical phys and room for 2 virtual phys.
|
||||
*/
|
||||
#define SCI_MIN_SMP_PHYS (38)
|
||||
#endif
|
||||
|
||||
#ifndef SCI_MAX_SMP_PHYS
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This constant defines the maximum number of SMP phy objects that can be
|
||||
* supported for the SCU Driver Standard (SDS) library. This number can be
|
||||
* increased if required.
|
||||
*/
|
||||
#define SCI_MAX_SMP_PHYS (384)
|
||||
#endif
|
||||
|
||||
#ifndef SCI_MAX_REMOTE_DEVICES
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This constant defines the maximum number of remote device objects that can
|
||||
* be supported for the SCU Driver Standard (SDS) library. This is tied
|
||||
* directly to silicon capabilities.
|
||||
*/
|
||||
#define SCI_MAX_REMOTE_DEVICES (256)
|
||||
#endif
|
||||
|
||||
#ifndef SCI_MIN_REMOTE_DEVICES
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This constant defines the minimum number of remote device objects that can
|
||||
* be supported for the SCU Driver Standard (SDS) library. This # can be
|
||||
* configured for minimum memory environments to any value less than
|
||||
* SCI_MAX_REMOTE_DEVICES
|
||||
*/
|
||||
#define SCI_MIN_REMOTE_DEVICES (16)
|
||||
#endif
|
||||
|
||||
#ifndef SCI_MAX_IO_REQUESTS
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This constant defines the maximum number of IO request objects that can be
|
||||
* supported for the SCU Driver Standard (SDS) library. This is tied directly
|
||||
* to silicon capabilities.
|
||||
*/
|
||||
#define SCI_MAX_IO_REQUESTS (256)
|
||||
#endif
|
||||
|
||||
#ifndef SCI_MIN_IO_REQUESTS
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This constant defines the minimum number of IO request objects that can be
|
||||
* supported for the SCU Driver Standard (SDS) library. This # can be
|
||||
* configured for minimum memory environments to any value less than
|
||||
* SCI_MAX_IO_REQUESTS.
|
||||
*/
|
||||
#define SCI_MIN_IO_REQUESTS (1)
|
||||
#endif
|
||||
|
||||
#ifndef SCI_MAX_MSIX_MESSAGES
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This constant defines the maximum number of MSI-X interrupt vectors/messages
|
||||
* supported for an SCU hardware controller instance.
|
||||
*/
|
||||
#define SCI_MAX_MSIX_MESSAGES (2)
|
||||
#endif
|
||||
|
||||
#ifndef SCI_MAX_SCATTER_GATHER_ELEMENTS
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This constant defines the maximum number of Scatter-Gather Elements to be
|
||||
* used by any SCI component.
|
||||
*/
|
||||
#define SCI_MAX_SCATTER_GATHER_ELEMENTS 130
|
||||
#endif
|
||||
|
||||
#ifndef SCI_MIN_SCATTER_GATHER_ELEMENTS
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This constant defines the minimum number of Scatter-Gather Elements to be
|
||||
* used by any SCI component.
|
||||
*/
|
||||
#define SCI_MIN_SCATTER_GATHER_ELEMENTS 1
|
||||
#endif
|
||||
|
||||
#else /* SCIC_SDS_4_ENABLED */
|
||||
|
||||
#error "SCI Core configuration left unspecified (e.g. SCIC_SDS_4_ENABLED)"
|
||||
|
||||
#endif /* SCIC_SDS_4_ENABLED */
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This constant defines the maximum number of controllers that can occur in a
|
||||
* single silicon package.
|
||||
*/
|
||||
#define SCI_MAX_CONTROLLERS 2
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* The maximum number of supported domain objects is currently tied to the
|
||||
* maximum number of support port objects.
|
||||
*/
|
||||
#define SCI_MAX_DOMAINS SCI_MAX_PORTS
|
||||
|
||||
|
||||
#endif /* _SCI_CONTROLLER_CONSTANTS_H_ */
|
||||
|
||||
169
drivers/scsi/isci/core/sci_memory_descriptor_list.h
Normal file
169
drivers/scsi/isci/core/sci_memory_descriptor_list.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_MEMORY_DESCRIPTOR_LIST_H_
|
||||
#define _SCI_MEMORY_DESCRIPTOR_LIST_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the basic data types utilized by an SCI user or
|
||||
* implementor.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "sci_types.h"
|
||||
|
||||
struct sci_base_memory_descriptor_list;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCI_MDE_ATTRIBUTES These constants depict memory attributes for the Memory
|
||||
* Descriptor Entries (MDEs) contained in the MDL.
|
||||
*/
|
||||
#define SCI_MDE_ATTRIBUTE_CACHEABLE 0x0001
|
||||
#define SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS 0x0002
|
||||
|
||||
/**
|
||||
* struct sci_physical_memory_descriptor - This structure defines a description
|
||||
* of a memory location for the SCI implementation.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_physical_memory_descriptor {
|
||||
/**
|
||||
* This field contains the virtual address associated with this descriptor
|
||||
* element. This field shall be zero when the descriptor is retrieved from
|
||||
* the SCI implementation. The user shall set this field prior
|
||||
* sci_controller_start()
|
||||
*/
|
||||
void *virtual_address;
|
||||
|
||||
/**
|
||||
* This field contains the physical address associated with this desciptor
|
||||
* element. This field shall be zero when the descriptor is retrieved from
|
||||
* the SCI implementation. The user shall set this field prior
|
||||
* sci_controller_start()
|
||||
*/
|
||||
dma_addr_t physical_address;
|
||||
|
||||
/**
|
||||
* This field contains the size requirement for this memory descriptor.
|
||||
* A value of zero for this field indicates the end of the descriptor
|
||||
* list. The value should be treated as read only for an SCI user.
|
||||
*/
|
||||
u32 constant_memory_size;
|
||||
|
||||
/**
|
||||
* This field contains the alignment requirement for this memory
|
||||
* descriptor. A value of zero for this field indicates the end of the
|
||||
* descriptor list. All other values indicate the number of bytes to
|
||||
* achieve the necessary alignment. The value should be treated as
|
||||
* read only for an SCI user.
|
||||
*/
|
||||
u32 constant_memory_alignment;
|
||||
|
||||
/**
|
||||
* This field contains an indication regarding the desired memory
|
||||
* attributes for this memory descriptor entry.
|
||||
* Notes:
|
||||
* - If the cacheable attribute is set, the user can allocate
|
||||
* memory that is backed by cache for better performance. It
|
||||
* is not required that the memory be backed by cache.
|
||||
* - If the physically contiguous attribute is set, then the
|
||||
* entire memory must be physically contiguous across all
|
||||
* page boundaries.
|
||||
*/
|
||||
u16 constant_memory_attributes;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* sci_mdl_first_entry() - This method simply rewinds the MDL iterator back to
|
||||
* the first memory descriptor entry in the list.
|
||||
* @mdl: This parameter specifies the memory descriptor list that is to be
|
||||
* rewound.
|
||||
*
|
||||
*/
|
||||
void sci_mdl_first_entry(
|
||||
struct sci_base_memory_descriptor_list *mdl);
|
||||
|
||||
/**
|
||||
* sci_mdl_next_entry() - This method simply updates the "current" pointer to
|
||||
* the next sequential memory descriptor.
|
||||
* @mdl: This parameter specifies the memory descriptor list for which to
|
||||
* return the next memory descriptor entry in the list.
|
||||
*
|
||||
* none.
|
||||
*/
|
||||
void sci_mdl_next_entry(
|
||||
struct sci_base_memory_descriptor_list *mdl);
|
||||
|
||||
/**
|
||||
* sci_mdl_get_current_entry() - This method simply returns the current memory
|
||||
* descriptor entry.
|
||||
* @mdl: This parameter specifies the memory descriptor list for which to
|
||||
* return the current memory descriptor entry.
|
||||
*
|
||||
* This method returns a pointer to the current physical memory descriptor in
|
||||
* the MDL. NULL This value is returned if there are no descriptors in the list.
|
||||
*/
|
||||
struct sci_physical_memory_descriptor *sci_mdl_get_current_entry(
|
||||
struct sci_base_memory_descriptor_list *mdl);
|
||||
|
||||
|
||||
#endif /* _SCI_MEMORY_DESCRIPTOR_LIST_H_ */
|
||||
|
||||
99
drivers/scsi/isci/core/sci_object.h
Normal file
99
drivers/scsi/isci/core/sci_object.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_OBJECT_H_
|
||||
#define _SCI_OBJECT_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the method and constants associated with the SCI
|
||||
* base object. The SCI base object is the class from which all other
|
||||
* objects derive in the Storage Controller Interface.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "sci_types.h"
|
||||
#include "sci_status.h"
|
||||
|
||||
/**
|
||||
* struct sci_base_object - all core objects must include this as their
|
||||
* first member to permit the casting below
|
||||
*
|
||||
* TODO: unwind this assumption, convert these routines and callers to pass a struct
|
||||
* sci_base_object pointer without casting, or convert 'private' to the
|
||||
* expected type per-object
|
||||
*
|
||||
*/
|
||||
struct sci_base_object {
|
||||
void *private;
|
||||
};
|
||||
|
||||
static inline void *sci_object_get_association(void *obj)
|
||||
{
|
||||
struct sci_base_object *base = obj;
|
||||
|
||||
return base->private;
|
||||
}
|
||||
|
||||
static inline void sci_object_set_association(void *obj, void *private)
|
||||
{
|
||||
struct sci_base_object *base = obj;
|
||||
|
||||
base->private = private;
|
||||
}
|
||||
|
||||
#endif /* _SCI_OBJECT_H_ */
|
||||
|
||||
199
drivers/scsi/isci/core/sci_pool.h
Normal file
199
drivers/scsi/isci/core/sci_pool.h
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the interface to the pool class. This class allows two
|
||||
* different two different priority tasks to insert and remove items from
|
||||
* the free pool. The user of the pool is expected to evaluate the pool
|
||||
* condition empty before a get operation and pool condition full before a
|
||||
* put operation. Methods Provided: - sci_pool_create() -
|
||||
* sci_pool_initialize() - sci_pool_empty() - sci_pool_full() -
|
||||
* sci_pool_get() - sci_pool_put()
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SCI_POOL_H_
|
||||
#define _SCI_POOL_H_
|
||||
|
||||
/**
|
||||
* SCI_POOL_INCREMENT() -
|
||||
*
|
||||
* Private operation for the pool
|
||||
*/
|
||||
#define SCI_POOL_INCREMENT(this_pool, index) \
|
||||
(((index) + 1) == (this_pool).size ? 0 : (index) + 1)
|
||||
|
||||
/**
|
||||
* SCI_POOL_CREATE() -
|
||||
*
|
||||
* This creates a pool structure of pool_name. The members in the pool are of
|
||||
* type with number of elements equal to size.
|
||||
*/
|
||||
#define SCI_POOL_CREATE(pool_name, type, pool_size) \
|
||||
struct \
|
||||
{ \
|
||||
u32 size; \
|
||||
u32 get; \
|
||||
u32 put; \
|
||||
type array[(pool_size) + 1]; \
|
||||
} pool_name
|
||||
|
||||
|
||||
/**
|
||||
* sci_pool_empty() -
|
||||
*
|
||||
* This macro evaluates the pool and returns true if the pool is empty. If the
|
||||
* pool is empty the user should not perform any get operation on the pool.
|
||||
*/
|
||||
#define sci_pool_empty(this_pool) \
|
||||
((this_pool).get == (this_pool).put)
|
||||
|
||||
/**
|
||||
* sci_pool_full() -
|
||||
*
|
||||
* This macro evaluates the pool and returns true if the pool is full. If the
|
||||
* pool is full the user should not perform any put operation.
|
||||
*/
|
||||
#define sci_pool_full(this_pool) \
|
||||
(SCI_POOL_INCREMENT(this_pool, (this_pool).put) == (this_pool).get)
|
||||
|
||||
/**
|
||||
* sci_pool_size() -
|
||||
*
|
||||
* This macro returns the size of the pool created. The internal size of the
|
||||
* pool is actually 1 larger then necessary in order to ensure get and put
|
||||
* pointers can be written simultaneously by different users. As a result,
|
||||
* this macro subtracts 1 from the internal size
|
||||
*/
|
||||
#define sci_pool_size(this_pool) \
|
||||
((this_pool).size - 1)
|
||||
|
||||
/**
|
||||
* sci_pool_count() -
|
||||
*
|
||||
* This macro indicates the number of elements currently contained in the pool.
|
||||
*/
|
||||
#define sci_pool_count(this_pool) \
|
||||
(\
|
||||
sci_pool_empty((this_pool)) \
|
||||
? 0 \
|
||||
: (\
|
||||
sci_pool_full((this_pool)) \
|
||||
? sci_pool_size((this_pool)) \
|
||||
: (\
|
||||
(this_pool).get > (this_pool).put \
|
||||
? ((this_pool).size - (this_pool).get + (this_pool).put) \
|
||||
: ((this_pool).put - (this_pool).get) \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
/**
|
||||
* sci_pool_initialize() -
|
||||
*
|
||||
* This macro initializes the pool to an empty condition.
|
||||
*/
|
||||
#define sci_pool_initialize(this_pool) \
|
||||
{ \
|
||||
(this_pool).size = (sizeof((this_pool).array) / sizeof((this_pool).array[0])); \
|
||||
(this_pool).get = 0; \
|
||||
(this_pool).put = 0; \
|
||||
}
|
||||
|
||||
/**
|
||||
* sci_pool_get() -
|
||||
*
|
||||
* This macro will get the next free element from the pool. This should only be
|
||||
* called if the pool is not empty.
|
||||
*/
|
||||
#define sci_pool_get(this_pool, my_value) \
|
||||
{ \
|
||||
(my_value) = (this_pool).array[(this_pool).get]; \
|
||||
(this_pool).get = SCI_POOL_INCREMENT((this_pool), (this_pool).get); \
|
||||
}
|
||||
|
||||
/**
|
||||
* sci_pool_put() -
|
||||
*
|
||||
* This macro will put the value into the pool. This should only be called if
|
||||
* the pool is not full.
|
||||
*/
|
||||
#define sci_pool_put(this_pool, the_value) \
|
||||
{ \
|
||||
(this_pool).array[(this_pool).put] = (the_value); \
|
||||
(this_pool).put = SCI_POOL_INCREMENT((this_pool), (this_pool).put); \
|
||||
}
|
||||
|
||||
/**
|
||||
* sci_pool_erase() -
|
||||
*
|
||||
* This macro will search the pool and remove any elements in the pool matching
|
||||
* the supplied value. This method can only be utilized on pools
|
||||
*/
|
||||
#define sci_pool_erase(this_pool, type, the_value) \
|
||||
{ \
|
||||
type tmp_value; \
|
||||
u32 index; \
|
||||
u32 element_count = sci_pool_count((this_pool)); \
|
||||
\
|
||||
for (index = 0; index < element_count; index++) { \
|
||||
sci_pool_get((this_pool), tmp_value); \
|
||||
if (tmp_value != (the_value)) \
|
||||
sci_pool_put((this_pool), tmp_value); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* _SCI_POOL_H_ */
|
||||
409
drivers/scsi/isci/core/sci_status.h
Normal file
409
drivers/scsi/isci/core/sci_status.h
Normal file
@@ -0,0 +1,409 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_STATUS_H_
|
||||
#define _SCI_STATUS_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the return status codes utilized across the
|
||||
* various sub-components in SCI.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* enum _SCI_STATUS - This is the general return status enumeration for non-IO,
|
||||
* non-task management related SCI interface methods.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_status {
|
||||
/**
|
||||
* This member indicates successful completion.
|
||||
*/
|
||||
SCI_SUCCESS = 0,
|
||||
|
||||
/**
|
||||
* This value indicates that the calling method completed successfully,
|
||||
* but that the IO may have completed before having it's start method
|
||||
* invoked. This occurs during SAT translation for requests that do
|
||||
* not require an IO to the target or for any other requests that may
|
||||
* be completed without having to submit IO.
|
||||
*/
|
||||
SCI_SUCCESS_IO_COMPLETE_BEFORE_START,
|
||||
|
||||
/**
|
||||
* This Value indicates that the SCU hardware returned an early response
|
||||
* because the io request specified more data than is returned by the
|
||||
* target device (mode pages, inquiry data, etc.). The completion routine
|
||||
* will handle this case to get the actual number of bytes transferred.
|
||||
*/
|
||||
SCI_SUCCESS_IO_DONE_EARLY,
|
||||
|
||||
/**
|
||||
* This member indicates that the object for which a state change is
|
||||
* being requested is already in said state.
|
||||
*/
|
||||
SCI_WARNING_ALREADY_IN_STATE,
|
||||
|
||||
/**
|
||||
* This member indicates interrupt coalescence timer may cause SAS
|
||||
* specification compliance issues (i.e. SMP target mode response
|
||||
* frames must be returned within 1.9 milliseconds).
|
||||
*/
|
||||
SCI_WARNING_TIMER_CONFLICT,
|
||||
|
||||
/**
|
||||
* This field indicates a sequence of action is not completed yet. Mostly,
|
||||
* this status is used when multiple ATA commands are needed in a SATI translation.
|
||||
*/
|
||||
SCI_WARNING_SEQUENCE_INCOMPLETE,
|
||||
|
||||
/**
|
||||
* This member indicates that there was a general failure.
|
||||
*/
|
||||
SCI_FAILURE,
|
||||
|
||||
/**
|
||||
* This member indicates that the SCI implementation is unable to complete
|
||||
* an operation due to a critical flaw the prevents any further operation
|
||||
* (i.e. an invalid pointer).
|
||||
*/
|
||||
SCI_FATAL_ERROR,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the state
|
||||
* of the controller is in a state that prevents successful completion.
|
||||
*/
|
||||
SCI_FAILURE_INVALID_STATE,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because there is
|
||||
* insufficient resources/memory to complete the request.
|
||||
*/
|
||||
SCI_FAILURE_INSUFFICIENT_RESOURCES,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* controller object required for the operation can't be located.
|
||||
*/
|
||||
SCI_FAILURE_CONTROLLER_NOT_FOUND,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* discovered controller type is not supported by the library.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* requested initialization data version isn't supported.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* requested configuration of SAS Phys into SAS Ports is not supported.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* requested protocol is not supported by the remote device, port,
|
||||
* or controller.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_PROTOCOL,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* requested information type is not supported by the SCI implementation.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_INFORMATION_TYPE,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* device already exists.
|
||||
*/
|
||||
SCI_FAILURE_DEVICE_EXISTS,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because adding
|
||||
* a phy to the object is not possible.
|
||||
*/
|
||||
SCI_FAILURE_ADDING_PHY_UNSUPPORTED,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* requested information type is not supported by the SCI implementation.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the SCI
|
||||
* implementation does not support the supplied time limit.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_TIME_LIMIT,
|
||||
|
||||
/**
|
||||
* This member indicates the calling method failed, because the SCI
|
||||
* implementation does not contain the specified Phy.
|
||||
*/
|
||||
SCI_FAILURE_INVALID_PHY,
|
||||
|
||||
/**
|
||||
* This member indicates the calling method failed, because the SCI
|
||||
* implementation does not contain the specified Port.
|
||||
*/
|
||||
SCI_FAILURE_INVALID_PORT,
|
||||
|
||||
/**
|
||||
* This member indicates the calling method was partly successful
|
||||
* The port was reset but not all phys in port are operational
|
||||
*/
|
||||
SCI_FAILURE_RESET_PORT_PARTIAL_SUCCESS,
|
||||
|
||||
/**
|
||||
* This member indicates that calling method failed
|
||||
* The port reset did not complete because none of the phys are operational
|
||||
*/
|
||||
SCI_FAILURE_RESET_PORT_FAILURE,
|
||||
|
||||
/**
|
||||
* This member indicates the calling method failed, because the SCI
|
||||
* implementation does not contain the specified remote device.
|
||||
*/
|
||||
SCI_FAILURE_INVALID_REMOTE_DEVICE,
|
||||
|
||||
/**
|
||||
* This member indicates the calling method failed, because the remote
|
||||
* device is in a bad state and requires a reset.
|
||||
*/
|
||||
SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
|
||||
|
||||
/**
|
||||
* This member indicates the calling method failed, because the SCI
|
||||
* implementation does not contain or support the specified IO tag.
|
||||
*/
|
||||
SCI_FAILURE_INVALID_IO_TAG,
|
||||
|
||||
/**
|
||||
* This member indicates that the operation failed and the user should
|
||||
* check the response data associated with the IO.
|
||||
*/
|
||||
SCI_FAILURE_IO_RESPONSE_VALID,
|
||||
|
||||
/**
|
||||
* This member indicates that the operation failed, the failure is
|
||||
* controller implementation specific, and the response data associated
|
||||
* with the request is not valid. You can query for the controller
|
||||
* specific error information via scic_controller_get_request_status()
|
||||
*/
|
||||
SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
|
||||
|
||||
/**
|
||||
* This member indicated that the operation failed because the
|
||||
* user requested this IO to be terminated.
|
||||
*/
|
||||
SCI_FAILURE_IO_TERMINATED,
|
||||
|
||||
/**
|
||||
* This member indicates that the operation failed and the associated
|
||||
* request requires a SCSI abort task to be sent to the target.
|
||||
*/
|
||||
SCI_FAILURE_IO_REQUIRES_SCSI_ABORT,
|
||||
|
||||
/**
|
||||
* This member indicates that the operation failed because the supplied
|
||||
* device could not be located.
|
||||
*/
|
||||
SCI_FAILURE_DEVICE_NOT_FOUND,
|
||||
|
||||
/**
|
||||
* This member indicates that the operation failed because the
|
||||
* objects association is required and is not correctly set.
|
||||
*/
|
||||
SCI_FAILURE_INVALID_ASSOCIATION,
|
||||
|
||||
/**
|
||||
* This member indicates that the operation failed, because a timeout
|
||||
* occurred.
|
||||
*/
|
||||
SCI_FAILURE_TIMEOUT,
|
||||
|
||||
/**
|
||||
* This member indicates that the operation failed, because the user
|
||||
* specified a value that is either invalid or not supported.
|
||||
*/
|
||||
SCI_FAILURE_INVALID_PARAMETER_VALUE,
|
||||
|
||||
/**
|
||||
* This value indicates that the operation failed, because the number
|
||||
* of messages (MSI-X) is not supported.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT,
|
||||
|
||||
/**
|
||||
* This value indicates that the method failed due to a lack of
|
||||
* available NCQ tags.
|
||||
*/
|
||||
SCI_FAILURE_NO_NCQ_TAG_AVAILABLE,
|
||||
|
||||
/**
|
||||
* This value indicates that a protocol violation has occurred on the
|
||||
* link.
|
||||
*/
|
||||
SCI_FAILURE_PROTOCOL_VIOLATION,
|
||||
|
||||
/**
|
||||
* This value indicates a failure condition that retry may help to clear.
|
||||
*/
|
||||
SCI_FAILURE_RETRY_REQUIRED,
|
||||
|
||||
/**
|
||||
* This field indicates the retry limit was reached when a retry is attempted
|
||||
*/
|
||||
SCI_FAILURE_RETRY_LIMIT_REACHED,
|
||||
|
||||
/**
|
||||
* This member indicates the calling method was partly successful.
|
||||
* Mostly, this status is used when a LUN_RESET issued to an expander attached
|
||||
* STP device in READY NCQ substate needs to have RNC suspended/resumed
|
||||
* before posting TC.
|
||||
*/
|
||||
SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS,
|
||||
|
||||
/**
|
||||
* This field indicates an illegal phy connection based on the routing attribute
|
||||
* of both expander phy attached to each other.
|
||||
*/
|
||||
SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION,
|
||||
|
||||
/**
|
||||
* This field indicates a CONFIG ROUTE INFO command has a response with function result
|
||||
* INDEX DOES NOT EXIST, usually means exceeding max route index.
|
||||
*/
|
||||
SCI_FAILURE_EXCEED_MAX_ROUTE_INDEX,
|
||||
|
||||
/**
|
||||
* This value indicates that an unsupported PCI device ID has been
|
||||
* specified. This indicates that attempts to invoke
|
||||
* scic_library_allocate_controller() will fail.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_PCI_DEVICE_ID
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* enum _SCI_IO_STATUS - This enumeration depicts all of the possible IO
|
||||
* completion status values. Each value in this enumeration maps directly
|
||||
* to a value in the enum sci_status enumeration. Please refer to that
|
||||
* enumeration for detailed comments concerning what the status represents.
|
||||
*
|
||||
* Add the API to retrieve the SCU status from the core. Check to see that the
|
||||
* following status are properly handled: - SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL
|
||||
* - SCI_IO_FAILURE_INVALID_IO_TAG
|
||||
*/
|
||||
enum sci_io_status {
|
||||
SCI_IO_SUCCESS = SCI_SUCCESS,
|
||||
SCI_IO_FAILURE = SCI_FAILURE,
|
||||
SCI_IO_SUCCESS_COMPLETE_BEFORE_START = SCI_SUCCESS_IO_COMPLETE_BEFORE_START,
|
||||
SCI_IO_SUCCESS_IO_DONE_EARLY = SCI_SUCCESS_IO_DONE_EARLY,
|
||||
SCI_IO_FAILURE_INVALID_STATE = SCI_FAILURE_INVALID_STATE,
|
||||
SCI_IO_FAILURE_INSUFFICIENT_RESOURCES = SCI_FAILURE_INSUFFICIENT_RESOURCES,
|
||||
SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL = SCI_FAILURE_UNSUPPORTED_PROTOCOL,
|
||||
SCI_IO_FAILURE_RESPONSE_VALID = SCI_FAILURE_IO_RESPONSE_VALID,
|
||||
SCI_IO_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
|
||||
SCI_IO_FAILURE_TERMINATED = SCI_FAILURE_IO_TERMINATED,
|
||||
SCI_IO_FAILURE_REQUIRES_SCSI_ABORT = SCI_FAILURE_IO_REQUIRES_SCSI_ABORT,
|
||||
SCI_IO_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE,
|
||||
SCI_IO_FAILURE_NO_NCQ_TAG_AVAILABLE = SCI_FAILURE_NO_NCQ_TAG_AVAILABLE,
|
||||
SCI_IO_FAILURE_PROTOCOL_VIOLATION = SCI_FAILURE_PROTOCOL_VIOLATION,
|
||||
|
||||
SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
|
||||
|
||||
SCI_IO_FAILURE_RETRY_REQUIRED = SCI_FAILURE_RETRY_REQUIRED,
|
||||
SCI_IO_FAILURE_RETRY_LIMIT_REACHED = SCI_FAILURE_RETRY_LIMIT_REACHED,
|
||||
SCI_IO_FAILURE_INVALID_REMOTE_DEVICE = SCI_FAILURE_INVALID_REMOTE_DEVICE
|
||||
};
|
||||
|
||||
/**
|
||||
* enum _SCI_TASK_STATUS - This enumeration depicts all of the possible task
|
||||
* completion status values. Each value in this enumeration maps directly
|
||||
* to a value in the enum sci_status enumeration. Please refer to that
|
||||
* enumeration for detailed comments concerning what the status represents.
|
||||
*
|
||||
* Check to see that the following status are properly handled:
|
||||
*/
|
||||
enum sci_task_status {
|
||||
SCI_TASK_SUCCESS = SCI_SUCCESS,
|
||||
SCI_TASK_FAILURE = SCI_FAILURE,
|
||||
SCI_TASK_FAILURE_INVALID_STATE = SCI_FAILURE_INVALID_STATE,
|
||||
SCI_TASK_FAILURE_INSUFFICIENT_RESOURCES = SCI_FAILURE_INSUFFICIENT_RESOURCES,
|
||||
SCI_TASK_FAILURE_UNSUPPORTED_PROTOCOL = SCI_FAILURE_UNSUPPORTED_PROTOCOL,
|
||||
SCI_TASK_FAILURE_INVALID_TAG = SCI_FAILURE_INVALID_IO_TAG,
|
||||
SCI_TASK_FAILURE_RESPONSE_VALID = SCI_FAILURE_IO_RESPONSE_VALID,
|
||||
SCI_TASK_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
|
||||
SCI_TASK_FAILURE_TERMINATED = SCI_FAILURE_IO_TERMINATED,
|
||||
SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE,
|
||||
|
||||
SCI_TASK_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
|
||||
SCI_TASK_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS = SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* _SCI_STATUS_H_ */
|
||||
|
||||
88
drivers/scsi/isci/core/sci_types.h
Normal file
88
drivers/scsi/isci/core/sci_types.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_TYPES_H_
|
||||
#define _SCI_TYPES_H_
|
||||
|
||||
#include <linux/string.h>
|
||||
|
||||
#define sci_cb_make_physical_address(physical_addr, addr_upper, addr_lower) \
|
||||
((physical_addr) = (addr_lower) | ((u64)addr_upper) << 32)
|
||||
|
||||
#define SCI_INVALID_HANDLE 0x0
|
||||
|
||||
/**
|
||||
* The SCI_LIBRARY_HANDLE_T will be utilized by SCI users as an opaque handle
|
||||
* for the SCI Library object.
|
||||
*
|
||||
* SCI_LIBRARY_HANDLE_T
|
||||
*/
|
||||
typedef void *SCI_LIBRARY_HANDLE_T;
|
||||
|
||||
|
||||
typedef enum {
|
||||
SCI_IO_REQUEST_DATA_IN = 0, /* Read operation */
|
||||
SCI_IO_REQUEST_DATA_OUT, /* Write operation */
|
||||
SCI_IO_REQUEST_NO_DATA
|
||||
} SCI_IO_REQUEST_DATA_DIRECTION;
|
||||
|
||||
|
||||
enum sci_controller_mode {
|
||||
SCI_MODE_SPEED, /* Optimized for performance */
|
||||
SCI_MODE_SIZE /* Optimized for memory use */
|
||||
};
|
||||
|
||||
#endif /* _SCI_TYPES_H_ */
|
||||
|
||||
70
drivers/scsi/isci/core/sci_util.c
Normal file
70
drivers/scsi/isci/core/sci_util.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "sci_util.h"
|
||||
|
||||
void scic_word_copy_with_swap(
|
||||
u32 *destination,
|
||||
u32 *source,
|
||||
u32 word_count)
|
||||
{
|
||||
while (word_count--) {
|
||||
*destination = SCIC_SWAP_DWORD(*source);
|
||||
|
||||
source++;
|
||||
destination++;
|
||||
}
|
||||
}
|
||||
|
||||
138
drivers/scsi/isci/core/sci_util.h
Normal file
138
drivers/scsi/isci/core/sci_util.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_UTIL_H_
|
||||
#define _SCI_UTIL_H_
|
||||
|
||||
#include "sci_types.h"
|
||||
|
||||
/**
|
||||
* SCIC_SWAP_DWORD() -
|
||||
*
|
||||
* Normal byte swap macro
|
||||
*/
|
||||
#define SCIC_SWAP_DWORD(x) \
|
||||
(\
|
||||
(((x) >> 24) & 0x000000FF) \
|
||||
| (((x) >> 8) & 0x0000FF00) \
|
||||
| (((x) << 8) & 0x00FF0000) \
|
||||
| (((x) << 24) & 0xFF000000) \
|
||||
)
|
||||
|
||||
#define SCIC_BUILD_DWORD(char_buffer) \
|
||||
(\
|
||||
((char_buffer)[0] << 24) \
|
||||
| ((char_buffer)[1] << 16) \
|
||||
| ((char_buffer)[2] << 8) \
|
||||
| ((char_buffer)[3]) \
|
||||
)
|
||||
|
||||
#define SCI_FIELD_OFFSET(type, field) ((unsigned long)&(((type *)0)->field))
|
||||
|
||||
/**
|
||||
* sci_physical_address_add() -
|
||||
*
|
||||
* This macro simply performs addition on an dma_addr_t type. The
|
||||
* lower u32 value is "clipped" or "wrapped" back through 0. When this occurs
|
||||
* the upper 32-bits are incremented by 1.
|
||||
*/
|
||||
#define sci_physical_address_add(physical_address, value) \
|
||||
{ \
|
||||
u32 lower = lower_32_bits((physical_address)); \
|
||||
u32 upper = upper_32_bits((physical_address)); \
|
||||
\
|
||||
if (lower + (value) < lower) \
|
||||
upper += 1; \
|
||||
\
|
||||
lower += (value); \
|
||||
sci_cb_make_physical_address(physical_address, upper, lower); \
|
||||
}
|
||||
|
||||
/**
|
||||
* sci_physical_address_subtract() -
|
||||
*
|
||||
* This macro simply performs subtraction on an dma_addr_t type. The
|
||||
* lower u32 value is "clipped" or "wrapped" back through 0. When this occurs
|
||||
* the upper 32-bits are decremented by 1.
|
||||
*/
|
||||
#define sci_physical_address_subtract(physical_address, value) \
|
||||
{ \
|
||||
u32 lower = lower_32_bits((physical_address)); \
|
||||
u32 upper = upper_32_bits((physical_address)); \
|
||||
\
|
||||
if (lower - (value) > lower) \
|
||||
upper -= 1; \
|
||||
\
|
||||
lower -= (value); \
|
||||
sci_cb_make_physical_address(physical_address, upper, lower); \
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_word_copy_with_swap() - Copy the data from source to destination and
|
||||
* swap the bytes during the copy.
|
||||
* @destination: This parameter specifies the destination address to which the
|
||||
* data is to be copied.
|
||||
* @source: This parameter specifies the source address from which data is to
|
||||
* be copied.
|
||||
* @word_count: This parameter specifies the number of 32-bit words to copy and
|
||||
* byte swap.
|
||||
*
|
||||
*/
|
||||
void scic_word_copy_with_swap(
|
||||
u32 *destination,
|
||||
u32 *source,
|
||||
u32 word_count);
|
||||
|
||||
#endif /* _SCI_UTIL_H_ */
|
||||
347
drivers/scsi/isci/core/scic_config_parameters.h
Normal file
347
drivers/scsi/isci/core/scic_config_parameters.h
Normal file
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_USER_PARAMETERS_H_
|
||||
#define _SCIC_SDS_USER_PARAMETERS_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the structure definitions and interface methods
|
||||
* that can be called by a SCIC user on the SCU Driver Standard
|
||||
* (struct scic_sds_user_parameters) user parameter block.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "sci_types.h"
|
||||
#include "sci_status.h"
|
||||
#include "intel_sas.h"
|
||||
#include "sci_controller_constants.h"
|
||||
|
||||
struct scic_sds_controller;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCIC_SDS_PARM_PHY_SPEED These constants define the speeds utilized for a
|
||||
* phy/port.
|
||||
*/
|
||||
#define SCIC_SDS_PARM_NO_SPEED 0
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This value of 1 indicates generation 1 (i.e. 1.5 Gb/s).
|
||||
*/
|
||||
#define SCIC_SDS_PARM_GEN1_SPEED 1
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This value of 2 indicates generation 2 (i.e. 3.0 Gb/s).
|
||||
*/
|
||||
#define SCIC_SDS_PARM_GEN2_SPEED 2
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This value of 3 indicates generation 3 (i.e. 6.0 Gb/s).
|
||||
*/
|
||||
#define SCIC_SDS_PARM_GEN3_SPEED 3
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* For range checks, the max speed generation
|
||||
*/
|
||||
#define SCIC_SDS_PARM_MAX_SPEED SCIC_SDS_PARM_GEN3_SPEED
|
||||
|
||||
/**
|
||||
* struct scic_sds_user_parameters - This structure delineates the various user
|
||||
* parameters that can be changed by the core user.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_sds_user_parameters {
|
||||
struct {
|
||||
/**
|
||||
* This field specifies the NOTIFY (ENABLE SPIN UP) primitive
|
||||
* insertion frequency for this phy index.
|
||||
*/
|
||||
u32 notify_enable_spin_up_insertion_frequency;
|
||||
|
||||
/**
|
||||
* This method specifies the number of transmitted DWORDs within which
|
||||
* to transmit a single ALIGN primitive. This value applies regardless
|
||||
* of what type of device is attached or connection state. A value of
|
||||
* 0 indicates that no ALIGN primitives will be inserted.
|
||||
*/
|
||||
u16 align_insertion_frequency;
|
||||
|
||||
/**
|
||||
* This method specifies the number of transmitted DWORDs within which
|
||||
* to transmit 2 ALIGN primitives. This applies for SAS connections
|
||||
* only. A minimum value of 3 is required for this field.
|
||||
*/
|
||||
u16 in_connection_align_insertion_frequency;
|
||||
|
||||
/**
|
||||
* This field indicates the maximum speed generation to be utilized
|
||||
* by phys in the supplied port.
|
||||
* - A value of 1 indicates generation 1 (i.e. 1.5 Gb/s).
|
||||
* - A value of 2 indicates generation 2 (i.e. 3.0 Gb/s).
|
||||
* - A value of 3 indicates generation 3 (i.e. 6.0 Gb/s).
|
||||
*/
|
||||
u8 max_speed_generation;
|
||||
|
||||
} phys[SCI_MAX_PHYS];
|
||||
|
||||
/**
|
||||
* This field specifies the maximum number of direct attached devices
|
||||
* that can have power supplied to them simultaneously.
|
||||
*/
|
||||
u8 max_number_concurrent_device_spin_up;
|
||||
|
||||
/**
|
||||
* This field specifies the number of seconds to allow a phy to consume
|
||||
* power before yielding to another phy.
|
||||
*
|
||||
*/
|
||||
u8 phy_spin_up_delay_interval;
|
||||
|
||||
/**
|
||||
* These timer values specifies how long a link will remain open with no
|
||||
* activity in increments of a microsecond, it can be in increments of
|
||||
* 100 microseconds if the upper most bit is set.
|
||||
*
|
||||
*/
|
||||
u16 stp_inactivity_timeout;
|
||||
u16 ssp_inactivity_timeout;
|
||||
|
||||
/**
|
||||
* These timer values specifies how long a link will remain open in increments
|
||||
* of 100 microseconds.
|
||||
*
|
||||
*/
|
||||
u16 stp_max_occupancy_timeout;
|
||||
u16 ssp_max_occupancy_timeout;
|
||||
|
||||
/**
|
||||
* This timer value specifies how long a link will remain open with no
|
||||
* outbound traffic in increments of a microsecond.
|
||||
*
|
||||
*/
|
||||
u8 no_outbound_task_timeout;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure/union specifies the various different user parameter sets
|
||||
* available. Each type is specific to a hardware controller version.
|
||||
*
|
||||
* union scic_user_parameters
|
||||
*/
|
||||
union scic_user_parameters {
|
||||
/**
|
||||
* This field specifies the user parameters specific to the
|
||||
* Storage Controller Unit (SCU) Driver Standard (SDS) version
|
||||
* 1.
|
||||
*/
|
||||
struct scic_sds_user_parameters sds1;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCIC_SDS_OEM_PHY_MASK These constants define the valid values for phy_mask
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This is the min value assignable to a port's phy mask
|
||||
*/
|
||||
#define SCIC_SDS_PARM_PHY_MASK_MIN 0x0
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This is the max value assignable to a port's phy mask
|
||||
*/
|
||||
#define SCIC_SDS_PARM_PHY_MASK_MAX 0xF
|
||||
|
||||
/**
|
||||
* struct scic_sds_oem_parameters - This structure delineates the various OEM
|
||||
* parameters that must be set the core user.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_sds_oem_parameters {
|
||||
struct {
|
||||
/**
|
||||
* This field indicates whether Spread Spectrum Clocking (SSC)
|
||||
* should be enabled or disabled.
|
||||
*/
|
||||
bool do_enable_ssc;
|
||||
|
||||
} controller;
|
||||
|
||||
struct {
|
||||
/**
|
||||
* This field specifies the phys to be contained inside a port.
|
||||
* The bit position in the mask specifies the index of the phy
|
||||
* to be contained in the port. Multiple bits (i.e. phys)
|
||||
* can be contained in a single port.
|
||||
*/
|
||||
u8 phy_mask;
|
||||
|
||||
} ports[SCI_MAX_PORTS];
|
||||
|
||||
struct {
|
||||
/**
|
||||
* This field specifies the SAS address to be transmitted on
|
||||
* for this phy index.
|
||||
*/
|
||||
struct sci_sas_address sas_address;
|
||||
|
||||
} phys[SCI_MAX_PHYS];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure/union specifies the various different OEM parameter sets
|
||||
* available. Each type is specific to a hardware controller version.
|
||||
*
|
||||
* union scic_oem_parameters
|
||||
*/
|
||||
union scic_oem_parameters {
|
||||
/**
|
||||
* This field specifies the OEM parameters specific to the
|
||||
* Storage Controller Unit (SCU) Driver Standard (SDS) version
|
||||
* 1.
|
||||
*/
|
||||
struct scic_sds_oem_parameters sds1;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* scic_user_parameters_set() - This method allows the user to attempt to
|
||||
* change the user parameters utilized by the controller.
|
||||
* @controller: This parameter specifies the controller on which to set the
|
||||
* user parameters.
|
||||
* @user_parameters: This parameter specifies the USER_PARAMETERS object
|
||||
* containing the potential new values.
|
||||
*
|
||||
* Indicate if the update of the user parameters was successful. SCI_SUCCESS
|
||||
* This value is returned if the operation succeeded. SCI_FAILURE_INVALID_STATE
|
||||
* This value is returned if the attempt to change the user parameter failed,
|
||||
* because changing one of the parameters is not currently allowed.
|
||||
* SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the user
|
||||
* supplied an invalid interrupt coalescence time, spin up delay interval, etc.
|
||||
*/
|
||||
enum sci_status scic_user_parameters_set(
|
||||
struct scic_sds_controller *controller,
|
||||
union scic_user_parameters *user_parameters);
|
||||
|
||||
/**
|
||||
* scic_user_parameters_get() - This method allows the user to retrieve the
|
||||
* user parameters utilized by the controller.
|
||||
* @controller: This parameter specifies the controller on which to set the
|
||||
* user parameters.
|
||||
* @user_parameters: This parameter specifies the USER_PARAMETERS object into
|
||||
* which the framework shall save it's parameters.
|
||||
*
|
||||
*/
|
||||
void scic_user_parameters_get(
|
||||
struct scic_sds_controller *controller,
|
||||
union scic_user_parameters *user_parameters);
|
||||
|
||||
/**
|
||||
* scic_oem_parameters_set() - This method allows the user to attempt to change
|
||||
* the OEM parameters utilized by the controller.
|
||||
* @controller: This parameter specifies the controller on which to set the
|
||||
* user parameters.
|
||||
* @oem_parameters: This parameter specifies the OEM parameters object
|
||||
* containing the potential new values.
|
||||
*
|
||||
* Indicate if the update of the user parameters was successful. SCI_SUCCESS
|
||||
* This value is returned if the operation succeeded. SCI_FAILURE_INVALID_STATE
|
||||
* This value is returned if the attempt to change the user parameter failed,
|
||||
* because changing one of the parameters is not currently allowed.
|
||||
* SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the user
|
||||
* supplied an unsupported value for one of the OEM parameters.
|
||||
*/
|
||||
enum sci_status scic_oem_parameters_set(
|
||||
struct scic_sds_controller *controller,
|
||||
union scic_oem_parameters *oem_parameters);
|
||||
|
||||
/**
|
||||
* scic_oem_parameters_get() - This method allows the user to retreive the OEM
|
||||
* parameters utilized by the controller.
|
||||
* @controller: This parameter specifies the controller on which to set the
|
||||
* user parameters.
|
||||
* @oem_parameters: This parameter specifies the OEM parameters object in which
|
||||
* to write the core's OEM parameters.
|
||||
*
|
||||
*/
|
||||
void scic_oem_parameters_get(
|
||||
struct scic_sds_controller *controller,
|
||||
union scic_oem_parameters *oem_parameters);
|
||||
|
||||
|
||||
#endif /* _SCIC_SDS_USER_PARAMETERS_H_ */
|
||||
|
||||
586
drivers/scsi/isci/core/scic_controller.h
Normal file
586
drivers/scsi/isci/core/scic_controller.h
Normal file
@@ -0,0 +1,586 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_CONTROLLER_H_
|
||||
#define _SCIC_CONTROLLER_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the interface methods that can be called by an
|
||||
* SCIC user on a controller object.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "sci_types.h"
|
||||
#include "sci_status.h"
|
||||
#include "sci_controller.h"
|
||||
#include "scic_config_parameters.h"
|
||||
|
||||
struct scic_sds_request;
|
||||
struct scic_sds_phy;
|
||||
struct scic_sds_port;
|
||||
struct scic_sds_remote_device;
|
||||
|
||||
/**
|
||||
* enum _SCIC_INTERRUPT_TYPE - This enumeration depicts the various types of
|
||||
* interrupts that are potentially supported by a SCI Core implementation.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum scic_interrupt_type {
|
||||
SCIC_LEGACY_LINE_INTERRUPT_TYPE,
|
||||
SCIC_MSIX_INTERRUPT_TYPE,
|
||||
|
||||
/**
|
||||
* This enumeration value indicates the use of polling.
|
||||
*/
|
||||
SCIC_NO_INTERRUPTS
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* This method is called by the SCI user in order to have the SCI
|
||||
* implementation handle the interrupt. This method performs minimal
|
||||
* processing to allow for streamlined interrupt time usage.
|
||||
*
|
||||
* SCIC_CONTROLLER_INTERRUPT_HANDLER true: returned if there is an interrupt to
|
||||
* process and it was processed. false: returned if no interrupt was processed.
|
||||
*/
|
||||
typedef bool (*SCIC_CONTROLLER_INTERRUPT_HANDLER)(
|
||||
struct scic_sds_controller *controller
|
||||
);
|
||||
|
||||
/**
|
||||
* This method is called by the SCI user to process completions generated as a
|
||||
* result of a previously handled interrupt. This method will result in the
|
||||
* completion of IO requests and handling of other controller generated
|
||||
* events. This method should be called some time after the interrupt
|
||||
* handler.
|
||||
*
|
||||
* Most, if not all, of the user callback APIs are invoked from within this
|
||||
* API. As a result, the user should be cognizent of the operating level at
|
||||
* which they invoke this API.
|
||||
*/
|
||||
typedef void (*SCIC_CONTROLLER_COMPLETION_HANDLER)(
|
||||
struct scic_sds_controller *controller
|
||||
);
|
||||
|
||||
/**
|
||||
* struct scic_controller_handler_methods - This structure contains an
|
||||
* interrupt handler and completion handler function pointers.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_controller_handler_methods {
|
||||
SCIC_CONTROLLER_INTERRUPT_HANDLER interrupt_handler;
|
||||
SCIC_CONTROLLER_COMPLETION_HANDLER completion_handler;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* scic_controller_construct() - This method will attempt to construct a
|
||||
* controller object utilizing the supplied parameter information.
|
||||
* @c: This parameter specifies the controller to be constructed.
|
||||
* @scu_base: mapped base address of the scu registers
|
||||
* @smu_base: mapped base address of the smu registers
|
||||
*
|
||||
* Indicate if the controller was successfully constructed or if it failed in
|
||||
* some way. SCI_SUCCESS This value is returned if the controller was
|
||||
* successfully constructed. SCI_WARNING_TIMER_CONFLICT This value is returned
|
||||
* if the interrupt coalescence timer may cause SAS compliance issues for SMP
|
||||
* Target mode response processing. SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE
|
||||
* This value is returned if the controller does not support the supplied type.
|
||||
* SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned if the
|
||||
* controller does not support the supplied initialization data version.
|
||||
*/
|
||||
enum sci_status scic_controller_construct(struct scic_sds_controller *c,
|
||||
void __iomem *scu_base,
|
||||
void __iomem *smu_base);
|
||||
|
||||
/**
|
||||
* scic_controller_enable_interrupts() - This method will enable all controller
|
||||
* interrupts.
|
||||
* @controller: This parameter specifies the controller for which to enable
|
||||
* interrupts.
|
||||
*
|
||||
*/
|
||||
void scic_controller_enable_interrupts(
|
||||
struct scic_sds_controller *controller);
|
||||
|
||||
/**
|
||||
* scic_controller_disable_interrupts() - This method will disable all
|
||||
* controller interrupts.
|
||||
* @controller: This parameter specifies the controller for which to disable
|
||||
* interrupts.
|
||||
*
|
||||
*/
|
||||
void scic_controller_disable_interrupts(
|
||||
struct scic_sds_controller *controller);
|
||||
|
||||
/**
|
||||
* scic_controller_get_handler_methods() - This method will return provide
|
||||
* function pointers for the interrupt handler and completion handler. The
|
||||
* interrupt handler is expected to be invoked at interrupt time. The
|
||||
* completion handler is scheduled to run as a result of the interrupt
|
||||
* handler. The completion handler performs the bulk work for processing
|
||||
* silicon events.
|
||||
* @interrupt_type: This parameter informs the core which type of
|
||||
* interrupt/completion methods are being requested. These are the types:
|
||||
* SCIC_LEGACY_LINE_INTERRUPT_TYPE, SCIC_MSIX_INTERRUPT_TYPE,
|
||||
* SCIC_NO_INTERRUPTS (POLLING)
|
||||
* @message_count: This parameter informs the core the number of MSI-X messages
|
||||
* to be utilized. This parameter must be 0 when requesting legacy line
|
||||
* based handlers.
|
||||
* @handler_methods: The caller provides a pointer to a buffer of type
|
||||
* struct scic_controller_handler_methods. The size depends on the combination of
|
||||
* the interrupt_type and message_count input parameters:
|
||||
* SCIC_LEGACY_LINE_INTERRUPT_TYPE: - size =
|
||||
* sizeof(struct scic_controller_handler_methods) SCIC_MSIX_INTERRUPT_TYPE:
|
||||
* sizeof(struct scic_controller_handler_methods)
|
||||
* @handler_methods: SCIC fills out the caller's buffer with the appropriate
|
||||
* interrupt and completion handlers based on the info provided in the
|
||||
* interrupt_type and message_count input parameters. For
|
||||
* SCIC_LEGACY_LINE_INTERRUPT_TYPE, the buffer receives a single
|
||||
* struct scic_controller_handler_methods element regardless that the
|
||||
* message_count parameter is zero. For SCIC_MSIX_INTERRUPT_TYPE, the buffer
|
||||
* receives an array of elements of type struct scic_controller_handler_methods
|
||||
* where the array size is equivalent to the message_count parameter. The
|
||||
* array is zero-relative where entry zero corresponds to message-vector
|
||||
* zero, entry one corresponds to message-vector one, and so forth.
|
||||
*
|
||||
* Indicate if the handler retrieval operation was successful. SCI_SUCCESS This
|
||||
* value is returned if retrieval succeeded.
|
||||
* SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT This value is returned if the user
|
||||
* supplied an unsupported number of MSI-X messages. For legacy line interrupts
|
||||
* the only valid value is 0.
|
||||
*/
|
||||
enum sci_status scic_controller_get_handler_methods(
|
||||
enum scic_interrupt_type interrupt_type,
|
||||
u16 message_count,
|
||||
struct scic_controller_handler_methods *handler_methods);
|
||||
|
||||
/**
|
||||
* scic_controller_initialize() - This method will initialize the controller
|
||||
* hardware managed by the supplied core controller object. This method
|
||||
* will bring the physical controller hardware out of reset and enable the
|
||||
* core to determine the capabilities of the hardware being managed. Thus,
|
||||
* the core controller can determine it's exact physical (DMA capable)
|
||||
* memory requirements.
|
||||
* @controller: This parameter specifies the controller to be initialized.
|
||||
*
|
||||
* The SCI Core user must have called scic_controller_construct() on the
|
||||
* supplied controller object previously. Indicate if the controller was
|
||||
* successfully initialized or if it failed in some way. SCI_SUCCESS This value
|
||||
* is returned if the controller hardware was successfully initialized.
|
||||
*/
|
||||
enum sci_status scic_controller_initialize(
|
||||
struct scic_sds_controller *controller);
|
||||
|
||||
/**
|
||||
* scic_controller_get_suggested_start_timeout() - This method returns the
|
||||
* suggested scic_controller_start() timeout amount. The user is free to
|
||||
* use any timeout value, but this method provides the suggested minimum
|
||||
* start timeout value. The returned value is based upon empirical
|
||||
* information determined as a result of interoperability testing.
|
||||
* @controller: the handle to the controller object for which to return the
|
||||
* suggested start timeout.
|
||||
*
|
||||
* This method returns the number of milliseconds for the suggested start
|
||||
* operation timeout.
|
||||
*/
|
||||
u32 scic_controller_get_suggested_start_timeout(
|
||||
struct scic_sds_controller *controller);
|
||||
|
||||
/**
|
||||
* scic_controller_start() - This method will start the supplied core
|
||||
* controller. This method will start the staggered spin up operation. The
|
||||
* SCI User completion callback is called when the following conditions are
|
||||
* met: -# the return status of this method is SCI_SUCCESS. -# after all of
|
||||
* the phys have successfully started or been given the opportunity to start.
|
||||
* @controller: the handle to the controller object to start.
|
||||
* @timeout: This parameter specifies the number of milliseconds in which the
|
||||
* start operation should complete.
|
||||
*
|
||||
* The SCI Core user must have filled in the physical memory descriptor
|
||||
* structure via the sci_controller_get_memory_descriptor_list() method. The
|
||||
* SCI Core user must have invoked the scic_controller_initialize() method
|
||||
* prior to invoking this method. The controller must be in the INITIALIZED or
|
||||
* STARTED state. Indicate if the controller start method succeeded or failed
|
||||
* in some way. SCI_SUCCESS if the start operation succeeded.
|
||||
* SCI_WARNING_ALREADY_IN_STATE if the controller is already in the STARTED
|
||||
* state. SCI_FAILURE_INVALID_STATE if the controller is not either in the
|
||||
* INITIALIZED or STARTED states. SCI_FAILURE_INVALID_MEMORY_DESCRIPTOR if
|
||||
* there are inconsistent or invalid values in the supplied
|
||||
* struct sci_physical_memory_descriptor array.
|
||||
*/
|
||||
enum sci_status scic_controller_start(
|
||||
struct scic_sds_controller *controller,
|
||||
u32 timeout);
|
||||
|
||||
/**
|
||||
* scic_controller_stop() - This method will stop an individual controller
|
||||
* object.This method will invoke the associated user callback upon
|
||||
* completion. The completion callback is called when the following
|
||||
* conditions are met: -# the method return status is SCI_SUCCESS. -# the
|
||||
* controller has been quiesced. This method will ensure that all IO
|
||||
* requests are quiesced, phys are stopped, and all additional operation by
|
||||
* the hardware is halted.
|
||||
* @controller: the handle to the controller object to stop.
|
||||
* @timeout: This parameter specifies the number of milliseconds in which the
|
||||
* stop operation should complete.
|
||||
*
|
||||
* The controller must be in the STARTED or STOPPED state. Indicate if the
|
||||
* controller stop method succeeded or failed in some way. SCI_SUCCESS if the
|
||||
* stop operation successfully began. SCI_WARNING_ALREADY_IN_STATE if the
|
||||
* controller is already in the STOPPED state. SCI_FAILURE_INVALID_STATE if the
|
||||
* controller is not either in the STARTED or STOPPED states.
|
||||
*/
|
||||
enum sci_status scic_controller_stop(
|
||||
struct scic_sds_controller *controller,
|
||||
u32 timeout);
|
||||
|
||||
/**
|
||||
* scic_controller_reset() - This method will reset the supplied core
|
||||
* controller regardless of the state of said controller. This operation is
|
||||
* considered destructive. In other words, all current operations are wiped
|
||||
* out. No IO completions for outstanding devices occur. Outstanding IO
|
||||
* requests are not aborted or completed at the actual remote device.
|
||||
* @controller: the handle to the controller object to reset.
|
||||
*
|
||||
* Indicate if the controller reset method succeeded or failed in some way.
|
||||
* SCI_SUCCESS if the reset operation successfully started. SCI_FATAL_ERROR if
|
||||
* the controller reset operation is unable to complete.
|
||||
*/
|
||||
enum sci_status scic_controller_reset(
|
||||
struct scic_sds_controller *controller);
|
||||
|
||||
/**
|
||||
* scic_controller_start_io() - This method is called by the SCI user to
|
||||
* send/start an IO request. If the method invocation is successful, then
|
||||
* the IO request has been queued to the hardware for processing.
|
||||
* @controller: the handle to the controller object for which to start an IO
|
||||
* request.
|
||||
* @remote_device: the handle to the remote device object for which to start an
|
||||
* IO request.
|
||||
* @io_request: the handle to the io request object to start.
|
||||
* @io_tag: This parameter specifies a previously allocated IO tag that the
|
||||
* user desires to be utilized for this request. This parameter is optional.
|
||||
* The user is allowed to supply SCI_CONTROLLER_INVALID_IO_TAG as the value
|
||||
* for this parameter.
|
||||
*
|
||||
* - IO tags are a protected resource. It is incumbent upon the SCI Core user
|
||||
* to ensure that each of the methods that may allocate or free available IO
|
||||
* tags are handled in a mutually exclusive manner. This method is one of said
|
||||
* methods requiring proper critical code section protection (e.g. semaphore,
|
||||
* spin-lock, etc.). - For SATA, the user is required to manage NCQ tags. As a
|
||||
* result, it is expected the user will have set the NCQ tag field in the host
|
||||
* to device register FIS prior to calling this method. There is also a
|
||||
* requirement for the user to call scic_stp_io_set_ncq_tag() prior to invoking
|
||||
* the scic_controller_start_io() method. scic_controller_allocate_tag() for
|
||||
* more information on allocating a tag. Indicate if the controller
|
||||
* successfully started the IO request. SCI_IO_SUCCESS if the IO request was
|
||||
* successfully started. Determine the failure situations and return values.
|
||||
*/
|
||||
enum sci_io_status scic_controller_start_io(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
struct scic_sds_request *io_request,
|
||||
u16 io_tag);
|
||||
|
||||
|
||||
/**
|
||||
* scic_controller_start_task() - This method is called by the SCIC user to
|
||||
* send/start a framework task management request.
|
||||
* @controller: the handle to the controller object for which to start the task
|
||||
* management request.
|
||||
* @remote_device: the handle to the remote device object for which to start
|
||||
* the task management request.
|
||||
* @task_request: the handle to the task request object to start.
|
||||
* @io_tag: This parameter specifies a previously allocated IO tag that the
|
||||
* user desires to be utilized for this request. Note this not the io_tag
|
||||
* of the request being managed. It is to be utilized for the task request
|
||||
* itself. This parameter is optional. The user is allowed to supply
|
||||
* SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter.
|
||||
*
|
||||
* - IO tags are a protected resource. It is incumbent upon the SCI Core user
|
||||
* to ensure that each of the methods that may allocate or free available IO
|
||||
* tags are handled in a mutually exclusive manner. This method is one of said
|
||||
* methods requiring proper critical code section protection (e.g. semaphore,
|
||||
* spin-lock, etc.). - The user must synchronize this task with completion
|
||||
* queue processing. If they are not synchronized then it is possible for the
|
||||
* io requests that are being managed by the task request can complete before
|
||||
* starting the task request. scic_controller_allocate_tag() for more
|
||||
* information on allocating a tag. Indicate if the controller successfully
|
||||
* started the IO request. SCI_TASK_SUCCESS if the task request was
|
||||
* successfully started. SCI_TASK_FAILURE_REQUIRES_SCSI_ABORT This value is
|
||||
* returned if there is/are task(s) outstanding that require termination or
|
||||
* completion before this request can succeed.
|
||||
*/
|
||||
enum sci_task_status scic_controller_start_task(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
struct scic_sds_request *task_request,
|
||||
u16 io_tag);
|
||||
|
||||
/**
|
||||
* scic_controller_complete_task() - This method will perform core specific
|
||||
* completion operations for task management request. After this method is
|
||||
* invoked, the user should consider the task request as invalid until it is
|
||||
* properly reused (i.e. re-constructed).
|
||||
* @controller: The handle to the controller object for which to complete the
|
||||
* task management request.
|
||||
* @remote_device: The handle to the remote device object for which to complete
|
||||
* the task management request.
|
||||
* @task_request: the handle to the task management request object to complete.
|
||||
*
|
||||
* Indicate if the controller successfully completed the task management
|
||||
* request. SCI_SUCCESS if the completion process was successful.
|
||||
*/
|
||||
enum sci_status scic_controller_complete_task(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
struct scic_sds_request *task_request);
|
||||
|
||||
|
||||
/**
|
||||
* scic_controller_terminate_request() - This method is called by the SCI Core
|
||||
* user to terminate an ongoing (i.e. started) core IO request. This does
|
||||
* not abort the IO request at the target, but rather removes the IO request
|
||||
* from the host controller.
|
||||
* @controller: the handle to the controller object for which to terminate a
|
||||
* request.
|
||||
* @remote_device: the handle to the remote device object for which to
|
||||
* terminate a request.
|
||||
* @request: the handle to the io or task management request object to
|
||||
* terminate.
|
||||
*
|
||||
* Indicate if the controller successfully began the terminate process for the
|
||||
* IO request. SCI_SUCCESS if the terminate process was successfully started
|
||||
* for the request. Determine the failure situations and return values.
|
||||
*/
|
||||
enum sci_status scic_controller_terminate_request(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
struct scic_sds_request *request);
|
||||
|
||||
/**
|
||||
* scic_controller_complete_io() - This method will perform core specific
|
||||
* completion operations for an IO request. After this method is invoked,
|
||||
* the user should consider the IO request as invalid until it is properly
|
||||
* reused (i.e. re-constructed).
|
||||
* @controller: The handle to the controller object for which to complete the
|
||||
* IO request.
|
||||
* @remote_device: The handle to the remote device object for which to complete
|
||||
* the IO request.
|
||||
* @io_request: the handle to the io request object to complete.
|
||||
*
|
||||
* - IO tags are a protected resource. It is incumbent upon the SCI Core user
|
||||
* to ensure that each of the methods that may allocate or free available IO
|
||||
* tags are handled in a mutually exclusive manner. This method is one of said
|
||||
* methods requiring proper critical code section protection (e.g. semaphore,
|
||||
* spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI
|
||||
* Core user, using the scic_controller_allocate_io_tag() method, then it is
|
||||
* the responsibility of the caller to invoke the scic_controller_free_io_tag()
|
||||
* method to free the tag (i.e. this method will not free the IO tag). Indicate
|
||||
* if the controller successfully completed the IO request. SCI_SUCCESS if the
|
||||
* completion process was successful.
|
||||
*/
|
||||
enum sci_status scic_controller_complete_io(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
struct scic_sds_request *io_request);
|
||||
|
||||
|
||||
/**
|
||||
* scic_controller_get_port_handle() - This method simply provides the user
|
||||
* with a unique handle for a given SAS/SATA core port index.
|
||||
* @controller: This parameter represents the handle to the controller object
|
||||
* from which to retrieve a port (SAS or SATA) handle.
|
||||
* @port_index: This parameter specifies the port index in the controller for
|
||||
* which to retrieve the port handle. 0 <= port_index < maximum number of
|
||||
* phys.
|
||||
* @port_handle: This parameter specifies the retrieved port handle to be
|
||||
* provided to the caller.
|
||||
*
|
||||
* Indicate if the retrieval of the port handle was successful. SCI_SUCCESS
|
||||
* This value is returned if the retrieval was successful.
|
||||
* SCI_FAILURE_INVALID_PORT This value is returned if the supplied port id is
|
||||
* not in the supported range.
|
||||
*/
|
||||
enum sci_status scic_controller_get_port_handle(
|
||||
struct scic_sds_controller *controller,
|
||||
u8 port_index,
|
||||
struct scic_sds_port **port_handle);
|
||||
|
||||
/**
|
||||
* scic_controller_get_phy_handle() - This method simply provides the user with
|
||||
* a unique handle for a given SAS/SATA phy index/identifier.
|
||||
* @controller: This parameter represents the handle to the controller object
|
||||
* from which to retrieve a phy (SAS or SATA) handle.
|
||||
* @phy_index: This parameter specifies the phy index in the controller for
|
||||
* which to retrieve the phy handle. 0 <= phy_index < maximum number of phys.
|
||||
* @phy_handle: This parameter specifies the retrieved phy handle to be
|
||||
* provided to the caller.
|
||||
*
|
||||
* Indicate if the retrieval of the phy handle was successful. SCI_SUCCESS This
|
||||
* value is returned if the retrieval was successful. SCI_FAILURE_INVALID_PHY
|
||||
* This value is returned if the supplied phy id is not in the supported range.
|
||||
*/
|
||||
enum sci_status scic_controller_get_phy_handle(
|
||||
struct scic_sds_controller *controller,
|
||||
u8 phy_index,
|
||||
struct scic_sds_phy **phy_handle);
|
||||
|
||||
/**
|
||||
* scic_controller_allocate_io_tag() - This method will allocate a tag from the
|
||||
* pool of free IO tags. Direct allocation of IO tags by the SCI Core user
|
||||
* is optional. The scic_controller_start_io() method will allocate an IO
|
||||
* tag if this method is not utilized and the tag is not supplied to the IO
|
||||
* construct routine. Direct allocation of IO tags may provide additional
|
||||
* performance improvements in environments capable of supporting this usage
|
||||
* model. Additionally, direct allocation of IO tags also provides
|
||||
* additional flexibility to the SCI Core user. Specifically, the user may
|
||||
* retain IO tags across the lives of multiple IO requests.
|
||||
* @controller: the handle to the controller object for which to allocate the
|
||||
* tag.
|
||||
*
|
||||
* IO tags are a protected resource. It is incumbent upon the SCI Core user to
|
||||
* ensure that each of the methods that may allocate or free available IO tags
|
||||
* are handled in a mutually exclusive manner. This method is one of said
|
||||
* methods requiring proper critical code section protection (e.g. semaphore,
|
||||
* spin-lock, etc.). An unsigned integer representing an available IO tag.
|
||||
* SCI_CONTROLLER_INVALID_IO_TAG This value is returned if there are no
|
||||
* currently available tags to be allocated. All return other values indicate a
|
||||
* legitimate tag.
|
||||
*/
|
||||
u16 scic_controller_allocate_io_tag(
|
||||
struct scic_sds_controller *controller);
|
||||
|
||||
/**
|
||||
* scic_controller_free_io_tag() - This method will free an IO tag to the pool
|
||||
* of free IO tags. This method provides the SCI Core user more flexibility
|
||||
* with regards to IO tags. The user may desire to keep an IO tag after an
|
||||
* IO request has completed, because they plan on re-using the tag for a
|
||||
* subsequent IO request. This method is only legal if the tag was
|
||||
* allocated via scic_controller_allocate_io_tag().
|
||||
* @controller: This parameter specifies the handle to the controller object
|
||||
* for which to free/return the tag.
|
||||
* @io_tag: This parameter represents the tag to be freed to the pool of
|
||||
* available tags.
|
||||
*
|
||||
* - IO tags are a protected resource. It is incumbent upon the SCI Core user
|
||||
* to ensure that each of the methods that may allocate or free available IO
|
||||
* tags are handled in a mutually exclusive manner. This method is one of said
|
||||
* methods requiring proper critical code section protection (e.g. semaphore,
|
||||
* spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI
|
||||
* Core user, using the scic_controller_allocate_io_tag() method, then it is
|
||||
* the responsibility of the caller to invoke this method to free the tag. This
|
||||
* method returns an indication of whether the tag was successfully put back
|
||||
* (freed) to the pool of available tags. SCI_SUCCESS This return value
|
||||
* indicates the tag was successfully placed into the pool of available IO
|
||||
* tags. SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied tag
|
||||
* is not a valid IO tag value.
|
||||
*/
|
||||
enum sci_status scic_controller_free_io_tag(
|
||||
struct scic_sds_controller *controller,
|
||||
u16 io_tag);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* scic_controller_set_mode() - This method allows the user to configure the
|
||||
* SCI core into either a performance mode or a memory savings mode.
|
||||
* @controller: This parameter represents the handle to the controller object
|
||||
* for which to update the operating mode.
|
||||
* @mode: This parameter specifies the new mode for the controller.
|
||||
*
|
||||
* Indicate if the user successfully change the operating mode of the
|
||||
* controller. SCI_SUCCESS The user successfully updated the mode.
|
||||
*/
|
||||
enum sci_status scic_controller_set_mode(
|
||||
struct scic_sds_controller *controller,
|
||||
enum sci_controller_mode mode);
|
||||
|
||||
|
||||
/**
|
||||
* scic_controller_set_interrupt_coalescence() - This method allows the user to
|
||||
* configure the interrupt coalescence.
|
||||
* @controller: This parameter represents the handle to the controller object
|
||||
* for which its interrupt coalesce register is overridden.
|
||||
* @coalesce_number: Used to control the number of entries in the Completion
|
||||
* Queue before an interrupt is generated. If the number of entries exceed
|
||||
* this number, an interrupt will be generated. The valid range of the input
|
||||
* is [0, 256]. A setting of 0 results in coalescing being disabled.
|
||||
* @coalesce_timeout: Timeout value in microseconds. The valid range of the
|
||||
* input is [0, 2700000] . A setting of 0 is allowed and results in no
|
||||
* interrupt coalescing timeout.
|
||||
*
|
||||
* Indicate if the user successfully set the interrupt coalesce parameters.
|
||||
* SCI_SUCCESS The user successfully updated the interrutp coalescence.
|
||||
* SCI_FAILURE_INVALID_PARAMETER_VALUE The user input value is out of range.
|
||||
*/
|
||||
enum sci_status scic_controller_set_interrupt_coalescence(
|
||||
struct scic_sds_controller *controller,
|
||||
u32 coalesce_number,
|
||||
u32 coalesce_timeout);
|
||||
|
||||
struct device;
|
||||
struct scic_sds_controller *scic_controller_alloc(struct device *dev);
|
||||
|
||||
|
||||
#endif /* _SCIC_CONTROLLER_H_ */
|
||||
|
||||
512
drivers/scsi/isci/core/scic_io_request.h
Normal file
512
drivers/scsi/isci/core/scic_io_request.h
Normal file
@@ -0,0 +1,512 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_IO_REQUEST_H_
|
||||
#define _SCIC_IO_REQUEST_H_
|
||||
|
||||
/**
|
||||
* This file contains the structures and interface methods that can be
|
||||
* referenced and used by the SCI user for the SCI IO request object.
|
||||
*
|
||||
* Determine the failure situations and return values.
|
||||
*/
|
||||
|
||||
|
||||
#include "sci_types.h"
|
||||
#include "sci_status.h"
|
||||
#include "intel_sas.h"
|
||||
|
||||
struct scic_sds_request;
|
||||
struct scic_sds_remote_device;
|
||||
struct scic_sds_controller;
|
||||
|
||||
/**
|
||||
* struct scic_io_parameters - This structure contains additional optional
|
||||
* parameters for SSP IO requests. These parameters are utilized with the
|
||||
* scic_io_request_construct_advanced_ssp() method.
|
||||
*
|
||||
* Add Block-guard/DIF, TLR
|
||||
*/
|
||||
struct scic_io_parameters {
|
||||
/**
|
||||
* This sub-structure contains SCSI specific features (for use with SSP
|
||||
* IO requests).
|
||||
*/
|
||||
struct {
|
||||
/**
|
||||
* Data Integrity Format (DIF) is also known as protection information
|
||||
* or block-guard. This sub-structure contains DIF specific feature
|
||||
* information for SSP IO requests.
|
||||
*/
|
||||
struct {
|
||||
void *placeholder;
|
||||
} dif;
|
||||
|
||||
/**
|
||||
* Transport Layer Retries (TLR) is an SSP protocol specific feature.
|
||||
* This sub-structure contains Transport Layer Retries (TLR) specific
|
||||
* feature information for SSP IO requests.
|
||||
*/
|
||||
struct {
|
||||
void *placeholder;
|
||||
} tlr;
|
||||
|
||||
} scsi;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_passthru_request_callbacks - This structure contains the pointer
|
||||
* to the callback functions for constructing the passthrough request common
|
||||
* to SSP, SMP and STP. This structure must be set by the win sci layer
|
||||
* before the passthrough build is called
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_passthru_request_callbacks {
|
||||
/**
|
||||
* Function pointer to get the phy identifier for passthrough request.
|
||||
*/
|
||||
u32 (*scic_cb_passthru_get_phy_identifier)(void *, u8 *);
|
||||
/**
|
||||
* Function pointer to get the port identifier for passthrough request.
|
||||
*/
|
||||
u32 (*scic_cb_passthru_get_port_identifier)(void *, u8 *);
|
||||
/**
|
||||
* Function pointer to get the connection rate for passthrough request.
|
||||
*/
|
||||
u32 (*scic_cb_passthru_get_connection_rate)(void *, void *);
|
||||
/**
|
||||
* Function pointer to get the destination sas address for passthrough request.
|
||||
*/
|
||||
void (*scic_cb_passthru_get_destination_sas_address)(void *, u8 **);
|
||||
/**
|
||||
* Function pointer to get the transfer length for passthrough request.
|
||||
*/
|
||||
u32 (*scic_cb_passthru_get_transfer_length)(void *);
|
||||
/**
|
||||
* Function pointer to get the data direction for passthrough request.
|
||||
*/
|
||||
u32 (*scic_cb_passthru_get_data_direction)(void *);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_ssp_passthru_request_callbacks - This structure contains the
|
||||
* pointer to the callback functions for constructing the passthrough
|
||||
* request specific to SSP. This structure must be set by the win sci layer
|
||||
* before the passthrough build is called
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_ssp_passthru_request_callbacks {
|
||||
/**
|
||||
* Common callbacks for all Passthru requests
|
||||
*/
|
||||
struct scic_passthru_request_callbacks common_callbacks;
|
||||
/**
|
||||
* Function pointer to get the lun for passthrough request.
|
||||
*/
|
||||
void (*scic_cb_ssp_passthru_get_lun)(void *, u8 **);
|
||||
/**
|
||||
* Function pointer to get the cdb
|
||||
*/
|
||||
void (*scic_cb_ssp_passthru_get_cdb)(void *, u32 *, u8 **, u32 *, u8 **);
|
||||
/**
|
||||
* Function pointer to get the task attribute for passthrough request.
|
||||
*/
|
||||
u32 (*scic_cb_ssp_passthru_get_task_attribute)(void *);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_stp_passthru_request_callbacks - This structure contains the
|
||||
* pointer to the callback functions for constructing the passthrough
|
||||
* request specific to STP. This structure must be set by the win sci layer
|
||||
* before the passthrough build is called
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_stp_passthru_request_callbacks {
|
||||
/**
|
||||
* Common callbacks for all Passthru requests
|
||||
*/
|
||||
struct scic_passthru_request_callbacks common_callbacks;
|
||||
/**
|
||||
* Function pointer to get the protocol for passthrough request.
|
||||
*/
|
||||
u8 (*scic_cb_stp_passthru_get_protocol)(void *);
|
||||
/**
|
||||
* Function pointer to get the resgister fis
|
||||
*/
|
||||
void (*scic_cb_stp_passthru_get_register_fis)(void *, u8 **);
|
||||
/**
|
||||
* Function pointer to get the MULTIPLE_COUNT (bits 5,6,7 in Byte 1 in the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
|
||||
*/
|
||||
u8 (*scic_cb_stp_passthru_get_multiplecount)(void *);
|
||||
/**
|
||||
* Function pointer to get the EXTEND (bit 0 in Byte 1 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
|
||||
*/
|
||||
u8 (*scic_cb_stp_passthru_get_extend)(void *);
|
||||
/**
|
||||
* Function pointer to get the CK_COND (bit 5 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
|
||||
*/
|
||||
u8 (*scic_cb_stp_passthru_get_ckcond)(void *);
|
||||
/**
|
||||
* Function pointer to get the T_DIR (bit 3 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
|
||||
*/
|
||||
u8 (*scic_cb_stp_passthru_get_tdir)(void *);
|
||||
/**
|
||||
* Function pointer to get the BYTE_BLOCK (bit 2 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
|
||||
*/
|
||||
u8 (*scic_cb_stp_passthru_get_byteblock)(void *);
|
||||
/**
|
||||
* Function pointer to get the T_LENGTH (bits 0,1 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
|
||||
*/
|
||||
u8 (*scic_cb_stp_passthru_get_tlength)(void *);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_smp_passthru_request_callbacks - This structure contains the
|
||||
* pointer to the callback functions for constructing the passthrough
|
||||
* request specific to SMP. This structure must be set by the win sci layer
|
||||
* before the passthrough build is called
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_smp_passthru_request_callbacks {
|
||||
/**
|
||||
* Common callbacks for all Passthru requests
|
||||
*/
|
||||
struct scic_passthru_request_callbacks common_callbacks;
|
||||
|
||||
/**
|
||||
* Function pointer to get the length of the smp request and its length
|
||||
*/
|
||||
u32 (*scic_cb_smp_passthru_get_request)(void *, u8 **);
|
||||
/**
|
||||
* Function pointer to get the frame type of the smp request
|
||||
*/
|
||||
u8 (*scic_cb_smp_passthru_get_frame_type)(void *);
|
||||
/**
|
||||
* Function pointer to get the function in the the smp request
|
||||
*/
|
||||
u8 (*scic_cb_smp_passthru_get_function)(void *);
|
||||
|
||||
/**
|
||||
* Function pointer to get the "allocated response length" in the the smp request
|
||||
*/
|
||||
u8 (*scic_cb_smp_passthru_get_allocated_response_length)(void *);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* This enumeration specifies the transport protocol utilized for the request.
|
||||
*
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
* This enumeration constant indicates that no protocol has yet been
|
||||
* set.
|
||||
*/
|
||||
SCIC_NO_PROTOCOL,
|
||||
|
||||
/**
|
||||
* This enumeration constant indicates that the protocol utilized
|
||||
* is the Serial Management Protocol.
|
||||
*/
|
||||
SCIC_SMP_PROTOCOL,
|
||||
|
||||
/**
|
||||
* This enumeration constant indicates that the protocol utilized
|
||||
* is the Serial SCSI Protocol.
|
||||
*/
|
||||
SCIC_SSP_PROTOCOL,
|
||||
|
||||
/**
|
||||
* This enumeration constant indicates that the protocol utilized
|
||||
* is the Serial-ATA Tunneling Protocol.
|
||||
*/
|
||||
SCIC_STP_PROTOCOL
|
||||
|
||||
} SCIC_TRANSPORT_PROTOCOL;
|
||||
|
||||
|
||||
/**
|
||||
* scic_io_request_get_object_size() - This method simply returns the size
|
||||
* required to build an SCI based IO request object.
|
||||
*
|
||||
* Return the size of the SCI IO request object.
|
||||
*/
|
||||
u32 scic_io_request_get_object_size(
|
||||
void);
|
||||
|
||||
/**
|
||||
* scic_io_request_construct() - This method is called by the SCI user to
|
||||
* construct all SCI Core IO requests. Memory initialization and
|
||||
* functionality common to all IO request types is performed in this method.
|
||||
* @scic_controller: the handle to the core controller object for which to
|
||||
* build an IO request.
|
||||
* @scic_remote_device: the handle to the core remote device object for which
|
||||
* to build an IO request.
|
||||
* @io_tag: This parameter specifies the IO tag to be associated with this
|
||||
* request. If SCI_CONTROLLER_INVALID_IO_TAG is passed, then a copy of the
|
||||
* request is built internally. The request will be copied into the actual
|
||||
* controller request memory when the IO tag is allocated internally during
|
||||
* the scic_controller_start_io() method.
|
||||
* @user_io_request_object: This parameter specifies the user IO request to be
|
||||
* utilized during IO construction. This IO pointer will become the
|
||||
* associated object for the core IO request object.
|
||||
* @scic_io_request_memory: This parameter specifies the memory location to be
|
||||
* utilized when building the core request.
|
||||
* @new_scic_io_request_handle: This parameter specifies a pointer to the
|
||||
* handle the core will expect in further interactions with the core IO
|
||||
* request object.
|
||||
*
|
||||
* The SCI core implementation will create an association between the user IO
|
||||
* request object and the core IO request object. Indicate if the controller
|
||||
* successfully built the IO request. SCI_SUCCESS This value is returned if the
|
||||
* IO request was successfully built.
|
||||
*/
|
||||
enum sci_status scic_io_request_construct(
|
||||
struct scic_sds_controller *scic_controller,
|
||||
struct scic_sds_remote_device *scic_remote_device,
|
||||
u16 io_tag,
|
||||
void *user_io_request_object,
|
||||
void *scic_io_request_memory,
|
||||
struct scic_sds_request **new_scic_io_request_handle);
|
||||
|
||||
/**
|
||||
* scic_io_request_construct_basic_ssp() - This method is called by the SCI
|
||||
* user to build an SSP IO request.
|
||||
* @scic_io_request: This parameter specifies the handle to the io request
|
||||
* object to be built.
|
||||
*
|
||||
* - The user must have previously called scic_io_request_construct() on the
|
||||
* supplied IO request. Indicate if the controller successfully built the IO
|
||||
* request. SCI_SUCCESS This value is returned if the IO request was
|
||||
* successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned
|
||||
* if the remote_device does not support the SSP protocol.
|
||||
* SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not
|
||||
* properly set the association between the SCIC IO request and the user's IO
|
||||
* request. Please refer to the sci_object_set_association() routine for more
|
||||
* information.
|
||||
*/
|
||||
enum sci_status scic_io_request_construct_basic_ssp(
|
||||
struct scic_sds_request *scic_io_request);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* scic_io_request_construct_basic_sata() - This method is called by the SCI
|
||||
* Core user to build an STP IO request.
|
||||
* @scic_io_request: This parameter specifies the handle to the io request
|
||||
* object to be built.
|
||||
*
|
||||
* - The user must have previously called scic_io_request_construct() on the
|
||||
* supplied IO request. Indicate if the controller successfully built the IO
|
||||
* request. SCI_SUCCESS This value is returned if the IO request was
|
||||
* successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned
|
||||
* if the remote_device does not support the STP protocol.
|
||||
* SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not
|
||||
* properly set the association between the SCIC IO request and the user's IO
|
||||
* request. Please refer to the sci_object_set_association() routine for more
|
||||
* information.
|
||||
*/
|
||||
enum sci_status scic_io_request_construct_basic_sata(
|
||||
struct scic_sds_request *scic_io_request);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* scic_io_request_construct_smp() - This method is called by the SCI user to
|
||||
* build an SMP IO request.
|
||||
* @scic_io_request: This parameter specifies the handle to the io request
|
||||
* object to be built.
|
||||
*
|
||||
* - The user must have previously called scic_io_request_construct() on the
|
||||
* supplied IO request. Indicate if the controller successfully built the IO
|
||||
* request. SCI_SUCCESS This value is returned if the IO request was
|
||||
* successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned
|
||||
* if the remote_device does not support the SMP protocol.
|
||||
* SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not
|
||||
* properly set the association between the SCIC IO request and the user's IO
|
||||
* request. Please refer to the sci_object_set_association() routine for more
|
||||
* information.
|
||||
*/
|
||||
enum sci_status scic_io_request_construct_smp(
|
||||
struct scic_sds_request *scic_io_request);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* scic_request_get_controller_status() - This method returns the controller
|
||||
* specific IO/Task request status. These status values are unique to the
|
||||
* specific controller being managed by the SCIC.
|
||||
* @io_request: the handle to the IO or task management request object for
|
||||
* which to retrieve the status.
|
||||
*
|
||||
* This method returns a value indicating the controller specific request
|
||||
* status.
|
||||
*/
|
||||
u32 scic_request_get_controller_status(
|
||||
struct scic_sds_request *io_request);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* scic_io_request_get_command_iu_address() - This method will return the
|
||||
* address to the command information unit.
|
||||
* @scic_io_request: This parameter specifies the handle to the io request
|
||||
* object to be built.
|
||||
*
|
||||
* The address of the SSP/SMP command information unit.
|
||||
*/
|
||||
void *scic_io_request_get_command_iu_address(
|
||||
struct scic_sds_request *scic_io_request);
|
||||
|
||||
/**
|
||||
* scic_io_request_get_response_iu_address() - This method will return the
|
||||
* address to the response information unit. For an SSP request this buffer
|
||||
* is only valid if the IO request is completed with the status
|
||||
* SCI_FAILURE_IO_RESPONSE_VALID.
|
||||
* @scic_io_request: This parameter specifies the handle to the io request
|
||||
* object to be built.
|
||||
*
|
||||
* The address of the SSP/SMP response information unit.
|
||||
*/
|
||||
void *scic_io_request_get_response_iu_address(
|
||||
struct scic_sds_request *scic_io_request);
|
||||
|
||||
/**
|
||||
* scic_io_request_get_io_tag() - This method will return the IO tag utilized
|
||||
* by the IO request.
|
||||
* @scic_io_request: This parameter specifies the handle to the io request
|
||||
* object for which to return the IO tag.
|
||||
*
|
||||
* An unsigned integer representing the IO tag being utilized.
|
||||
* SCI_CONTROLLER_INVALID_IO_TAG This value is returned if the IO does not
|
||||
* currently have an IO tag allocated to it. All return other values indicate a
|
||||
* legitimate tag.
|
||||
*/
|
||||
u16 scic_io_request_get_io_tag(
|
||||
struct scic_sds_request *scic_io_request);
|
||||
|
||||
|
||||
/**
|
||||
* scic_stp_io_request_set_ncq_tag() - This method will assign an NCQ tag to
|
||||
* the io request object. The caller of this function must make sure that
|
||||
* only valid NCQ tags are assigned to the io request object.
|
||||
* @scic_io_request: This parameter specifies the handle to the io request
|
||||
* object to which to assign the ncq tag.
|
||||
* @ncq_tag: This parameter specifies the NCQ tag to be utilized for the
|
||||
* supplied core IO request. It is up to the user to make sure that this is
|
||||
* a valid NCQ tag.
|
||||
*
|
||||
* none This function is only valid for SATA NCQ requests.
|
||||
*/
|
||||
void scic_stp_io_request_set_ncq_tag(
|
||||
struct scic_sds_request *scic_io_request,
|
||||
u16 ncq_tag);
|
||||
|
||||
/**
|
||||
* scic_stp_io_request_get_h2d_reg_address() - This method will return the
|
||||
* address of the host to device register fis region for the io request
|
||||
* object.
|
||||
* @scic_io_request: This parameter specifies the handle to the io request
|
||||
* object from which to get the host to device register fis buffer.
|
||||
*
|
||||
* The address of the host to device register fis buffer in the io request
|
||||
* object. This function is only valid for SATA requests.
|
||||
*/
|
||||
void *scic_stp_io_request_get_h2d_reg_address(
|
||||
struct scic_sds_request *scic_io_request);
|
||||
|
||||
/**
|
||||
* scic_stp_io_request_get_d2h_reg_address() - This method will return the
|
||||
* address of the device to host register fis region for the io request
|
||||
* object.
|
||||
* @scic_io_request: This parameter specifies teh handle to the io request
|
||||
* object from which to get the device to host register fis buffer.
|
||||
*
|
||||
* The address fo the device to host register fis ending the io request. This
|
||||
* function is only valid for SATA requests.
|
||||
*/
|
||||
void *scic_stp_io_request_get_d2h_reg_address(
|
||||
struct scic_sds_request *scic_io_request);
|
||||
|
||||
|
||||
/**
|
||||
* scic_io_request_get_number_of_bytes_transferred() - This method will return
|
||||
* the number of bytes transferred from the SCU
|
||||
* @scic_io_request: This parameter specifies the handle to the io request
|
||||
* whose data length was not eqaul to the data length specified in the
|
||||
* request. When the driver gets an early io completion status from the
|
||||
* hardware, this routine should be called to get the actual number of bytes
|
||||
* transferred
|
||||
*
|
||||
* The return is the number of bytes transferred when the data legth is not
|
||||
* equal to the specified length in the io request
|
||||
*/
|
||||
u32 scic_io_request_get_number_of_bytes_transferred(
|
||||
struct scic_sds_request *scic_io_request);
|
||||
|
||||
|
||||
#endif /* _SCIC_IO_REQUEST_H_ */
|
||||
|
||||
303
drivers/scsi/isci/core/scic_phy.h
Normal file
303
drivers/scsi/isci/core/scic_phy.h
Normal file
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_PHY_H_
|
||||
#define _SCIC_PHY_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the interface methods that can be called by an
|
||||
* SCIC user on a phy (SAS or SATA) object.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "sci_types.h"
|
||||
#include "sci_status.h"
|
||||
|
||||
#include "intel_sata.h"
|
||||
#include "intel_sas.h"
|
||||
|
||||
struct scic_sds_phy;
|
||||
struct scic_sds_port;
|
||||
|
||||
/**
|
||||
* struct scic_phy_properties - This structure defines the properties common to
|
||||
* all phys that can be retrieved.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_phy_properties {
|
||||
/**
|
||||
* This field specifies the port that currently contains the
|
||||
* supplied phy. This field may be set to SCI_INVALID_HANDLE
|
||||
* if the phy is not currently contained in a port.
|
||||
*/
|
||||
struct scic_sds_port *owning_port;
|
||||
|
||||
/**
|
||||
* This field specifies the link rate at which the phy is
|
||||
* currently operating.
|
||||
*/
|
||||
enum sci_sas_link_rate negotiated_link_rate;
|
||||
|
||||
/**
|
||||
* This field indicates the protocols supported by the phy.
|
||||
*/
|
||||
struct sci_sas_identify_address_frame_protocols protocols;
|
||||
|
||||
/**
|
||||
* This field specifies the index of the phy in relation to other
|
||||
* phys within the controller. This index is zero relative.
|
||||
*/
|
||||
u8 index;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_sas_phy_properties - This structure defines the properties,
|
||||
* specific to a SAS phy, that can be retrieved.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_sas_phy_properties {
|
||||
/**
|
||||
* This field delineates the Identify Address Frame received
|
||||
* from the remote end point.
|
||||
*/
|
||||
struct sci_sas_identify_address_frame received_iaf;
|
||||
|
||||
/**
|
||||
* This field delineates the Phy capabilities structure received
|
||||
* from the remote end point.
|
||||
*/
|
||||
struct sas_capabilities received_capabilities;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_sata_phy_properties - This structure defines the properties,
|
||||
* specific to a SATA phy, that can be retrieved.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_sata_phy_properties {
|
||||
/**
|
||||
* This field delineates the signature FIS received from the
|
||||
* attached target.
|
||||
*/
|
||||
struct sata_fis_reg_d2h signature_fis;
|
||||
|
||||
/**
|
||||
* This field specifies to the user if a port selector is connected
|
||||
* on the specified phy.
|
||||
*/
|
||||
bool is_port_selector_present;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* enum scic_phy_counter_id - This enumeration depicts the various pieces of
|
||||
* optional information that can be retrieved for a specific phy.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum scic_phy_counter_id {
|
||||
/**
|
||||
* This PHY information field tracks the number of frames received.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_FRAME,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of frames transmitted.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_TRANSMITTED_FRAME,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of DWORDs received.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_FRAME_WORD,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of DWORDs transmitted.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of times DWORD
|
||||
* synchronization was lost.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of received DWORDs with
|
||||
* running disparity errors.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of received frames with a
|
||||
* CRC error (not including short or truncated frames).
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT)
|
||||
* primitives received.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT)
|
||||
* primitives transmitted.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of times the inactivity
|
||||
* timer for connections on the phy has been utilized.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of DONE (CREDIT TIMEOUT)
|
||||
* primitives received.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of DONE (CREDIT TIMEOUT)
|
||||
* primitives transmitted.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of CREDIT BLOCKED
|
||||
* primitives received.
|
||||
* @note Depending on remote device implementation, credit blocks
|
||||
* may occur regularly.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED,
|
||||
|
||||
/**
|
||||
* This PHY information field contains the number of short frames
|
||||
* received. A short frame is simply a frame smaller then what is
|
||||
* allowed by either the SAS or SATA specification.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME,
|
||||
|
||||
/**
|
||||
* This PHY information field contains the number of frames received after
|
||||
* credit has been exhausted.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT,
|
||||
|
||||
/**
|
||||
* This PHY information field contains the number of frames received after
|
||||
* a DONE has been received.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE,
|
||||
|
||||
/**
|
||||
* This PHY information field contains the number of times the phy
|
||||
* failed to achieve DWORD synchronization during speed negotiation.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* scic_sas_phy_get_properties() - This method will enable the user to retrieve
|
||||
* information specific to a SAS phy, such as: the received identify address
|
||||
* frame, received phy capabilities, etc.
|
||||
* @phy: this parameter specifies the phy for which to retrieve properties.
|
||||
* @properties: This parameter specifies the properties structure into which to
|
||||
* copy the requested information.
|
||||
*
|
||||
* This method returns an indication as to whether the SAS phy properties were
|
||||
* successfully retrieved. SCI_SUCCESS This value is returned if the SAS
|
||||
* properties are successfully retrieved. SCI_FAILURE This value is returned if
|
||||
* the SAS properties are not successfully retrieved (e.g. It's not a SAS Phy).
|
||||
*/
|
||||
enum sci_status scic_sas_phy_get_properties(
|
||||
struct scic_sds_phy *phy,
|
||||
struct scic_sas_phy_properties *properties);
|
||||
|
||||
/**
|
||||
* scic_sata_phy_get_properties() - This method will enable the user to
|
||||
* retrieve information specific to a SATA phy, such as: the received
|
||||
* signature FIS, if a port selector is present, etc.
|
||||
* @phy: this parameter specifies the phy for which to retrieve properties.
|
||||
* @properties: This parameter specifies the properties structure into which to
|
||||
* copy the requested information.
|
||||
*
|
||||
* This method returns an indication as to whether the SATA phy properties were
|
||||
* successfully retrieved. SCI_SUCCESS This value is returned if the SATA
|
||||
* properties are successfully retrieved. SCI_FAILURE This value is returned if
|
||||
* the SATA properties are not successfully retrieved (e.g. It's not a SATA
|
||||
* Phy).
|
||||
*/
|
||||
enum sci_status scic_sata_phy_get_properties(
|
||||
struct scic_sds_phy *phy,
|
||||
struct scic_sata_phy_properties *properties);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* _SCIC_PHY_H_ */
|
||||
|
||||
213
drivers/scsi/isci/core/scic_port.h
Normal file
213
drivers/scsi/isci/core/scic_port.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_PORT_H_
|
||||
#define _SCIC_PORT_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the interface methods that can be called by an SCI
|
||||
* Core user on a SAS or SATA port.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "sci_types.h"
|
||||
#include "sci_status.h"
|
||||
#include "intel_sas.h"
|
||||
|
||||
struct scic_sds_port;
|
||||
|
||||
enum SCIC_PORT_NOT_READY_REASON_CODE {
|
||||
SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS,
|
||||
SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED,
|
||||
SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION,
|
||||
SCIC_PORT_NOT_READY_RECONFIGURING,
|
||||
|
||||
SCIC_PORT_NOT_READY_REASON_CODE_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_port_end_point_properties - This structure defines the
|
||||
* properties that can be retrieved for each end-point local or remote
|
||||
* (attached) port in the controller.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_port_end_point_properties {
|
||||
/**
|
||||
* This field indicates the SAS address for the associated end
|
||||
* point in the port.
|
||||
*/
|
||||
struct sci_sas_address sas_address;
|
||||
|
||||
/**
|
||||
* This field indicates the protocols supported by the associated
|
||||
* end-point in the port.
|
||||
*/
|
||||
struct sci_sas_identify_address_frame_protocols protocols;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_port_properties - This structure defines the properties that can
|
||||
* be retrieved for each port in the controller.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_port_properties {
|
||||
/**
|
||||
* This field specifies the logical index of the port (0 relative).
|
||||
*/
|
||||
u32 index;
|
||||
|
||||
/**
|
||||
* This field indicates the local end-point properties for port.
|
||||
*/
|
||||
struct scic_port_end_point_properties local;
|
||||
|
||||
/**
|
||||
* This field indicates the remote (attached) end-point properties
|
||||
* for the port.
|
||||
*/
|
||||
struct scic_port_end_point_properties remote;
|
||||
|
||||
/**
|
||||
* This field specifies the phys contained inside the port.
|
||||
*/
|
||||
u32 phy_mask;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* scic_port_get_properties() - This method simply returns the properties
|
||||
* regarding the port, such as: physical index, protocols, sas address, etc.
|
||||
* @port: this parameter specifies the port for which to retrieve the physical
|
||||
* index.
|
||||
* @properties: This parameter specifies the properties structure into which to
|
||||
* copy the requested information.
|
||||
*
|
||||
* Indicate if the user specified a valid port. SCI_SUCCESS This value is
|
||||
* returned if the specified port was valid. SCI_FAILURE_INVALID_PORT This
|
||||
* value is returned if the specified port is not valid. When this value is
|
||||
* returned, no data is copied to the properties output parameter.
|
||||
*/
|
||||
enum sci_status scic_port_get_properties(
|
||||
struct scic_sds_port *port,
|
||||
struct scic_port_properties *properties);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* scic_port_start() - This method will make the port ready for operation.
|
||||
* Prior to calling the start method IO operation is not possible.
|
||||
* @port: This parameter specifies the port to be started.
|
||||
*
|
||||
* Indicate if the port was successfully started. SCI_SUCCESS This value is
|
||||
* returned if the port was successfully started. SCI_WARNING_ALREADY_IN_STATE
|
||||
* This value is returned if the port is in the process of starting.
|
||||
* SCI_FAILURE_INVALID_PORT This value is returned if the supplied port is not
|
||||
* valid. SCI_FAILURE_INVALID_STATE This value is returned if a start operation
|
||||
* can't be completed due to the state of port.
|
||||
*/
|
||||
enum sci_status scic_port_start(
|
||||
struct scic_sds_port *port);
|
||||
|
||||
/**
|
||||
* scic_port_stop() - This method will make the port no longer ready for
|
||||
* operation. After invoking this method IO operation is not possible.
|
||||
* @port: This parameter specifies the port to be stopped.
|
||||
*
|
||||
* Indicate if the port was successfully stopped. SCI_SUCCESS This value is
|
||||
* returned if the port was successfully stopped. SCI_WARNING_ALREADY_IN_STATE
|
||||
* This value is returned if the port is already stopped or in the process of
|
||||
* stopping. SCI_FAILURE_INVALID_PORT This value is returned if the supplied
|
||||
* port is not valid. SCI_FAILURE_INVALID_STATE This value is returned if a
|
||||
* stop operation can't be completed due to the state of port.
|
||||
*/
|
||||
enum sci_status scic_port_stop(
|
||||
struct scic_sds_port *port);
|
||||
|
||||
/**
|
||||
* scic_port_hard_reset() - This method will request the SCI implementation to
|
||||
* perform a HARD RESET on the SAS Port. If/When the HARD RESET completes
|
||||
* the SCI user will be notified via an SCI OS callback indicating a direct
|
||||
* attached device was found.
|
||||
* @port: a handle corresponding to the SAS port to be hard reset.
|
||||
* @reset_timeout: This parameter specifies the number of milliseconds in which
|
||||
* the port reset operation should complete.
|
||||
*
|
||||
* The SCI User callback in SCIC_USER_CALLBACKS_T will only be called once for
|
||||
* each phy in the SAS Port at completion of the hard reset sequence. Return a
|
||||
* status indicating whether the hard reset started successfully. SCI_SUCCESS
|
||||
* This value is returned if the hard reset operation started successfully.
|
||||
*/
|
||||
enum sci_status scic_port_hard_reset(
|
||||
struct scic_sds_port *port,
|
||||
u32 reset_timeout);
|
||||
|
||||
/**
|
||||
* scic_port_enable_broadcast_change_notification() - This API method enables
|
||||
* the broadcast change notification from underneath hardware.
|
||||
* @port: The port upon which broadcast change notifications (BCN) are to be
|
||||
* enabled.
|
||||
*
|
||||
*/
|
||||
void scic_port_enable_broadcast_change_notification(
|
||||
struct scic_sds_port *port);
|
||||
|
||||
|
||||
#endif /* _SCIC_PORT_H_ */
|
||||
|
||||
295
drivers/scsi/isci/core/scic_remote_device.h
Normal file
295
drivers/scsi/isci/core/scic_remote_device.h
Normal file
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_REMOTE_DEVICE_H_
|
||||
#define _SCIC_REMOTE_DEVICE_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the interface methods that can be called by an
|
||||
* SCIC user on the device object.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "sci_types.h"
|
||||
#include "sci_status.h"
|
||||
#include "intel_sas.h"
|
||||
|
||||
struct scic_sds_port;
|
||||
struct scic_sds_remote_device;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum scic_remote_device_not_ready_reason_code {
|
||||
SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED,
|
||||
SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED,
|
||||
SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED,
|
||||
SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED,
|
||||
SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED,
|
||||
|
||||
SCIC_REMOTE_DEVICE_NOT_READY_REASON_CODE_MAX
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* scic_remote_device_get_object_size() - This method simply returns the
|
||||
* maximum memory space needed to store a remote device object.
|
||||
*
|
||||
* a positive integer value indicating the size (in bytes) of the remote device
|
||||
* object.
|
||||
*/
|
||||
u32 scic_remote_device_get_object_size(
|
||||
void);
|
||||
|
||||
struct scic_sds_port;
|
||||
struct scic_sds_remote_device;
|
||||
/**
|
||||
* scic_remote_device_construct() - This method will perform the construction
|
||||
* common to all remote device objects.
|
||||
* @sci_port: SAS/SATA port through which this device is accessed.
|
||||
* @sci_dev: remote device to construct
|
||||
*
|
||||
* It isn't necessary to call scic_remote_device_destruct() for device objects
|
||||
* that have only called this method for construction. Once subsequent
|
||||
* construction methods have been invoked (e.g.
|
||||
* scic_remote_device_da_construct()), then destruction should occur. none
|
||||
*/
|
||||
void scic_remote_device_construct(struct scic_sds_port *sci_port,
|
||||
struct scic_sds_remote_device *sci_dev);
|
||||
|
||||
/**
|
||||
* scic_remote_device_da_construct() - This method will construct a
|
||||
* SCIC_REMOTE_DEVICE object for a direct attached (da) device. The
|
||||
* information (e.g. IAF, Signature FIS, etc.) necessary to build the device
|
||||
* is known to the SCI Core since it is contained in the scic_phy object.
|
||||
* @remote_device: This parameter specifies the remote device to be destructed.
|
||||
*
|
||||
* The user must have previously called scic_remote_device_construct() Remote
|
||||
* device objects are a limited resource. As such, they must be protected.
|
||||
* Thus calls to construct and destruct are mutually exclusive and
|
||||
* non-reentrant. Indicate if the remote device was successfully constructed.
|
||||
* SCI_SUCCESS Returned if the device was successfully constructed.
|
||||
* SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been
|
||||
* constructed. If it's an additional phy for the target, then call
|
||||
* scic_remote_device_da_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned
|
||||
* if the supplied parameters necessitate creation of a remote device for which
|
||||
* the protocol is not supported by the underlying controller hardware.
|
||||
* SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core
|
||||
* controller associated with the supplied parameters is unable to support
|
||||
* additional remote devices.
|
||||
*/
|
||||
enum sci_status scic_remote_device_da_construct(
|
||||
struct scic_sds_remote_device *remote_device);
|
||||
|
||||
/**
|
||||
* scic_remote_device_ea_construct() - This method will construct an
|
||||
* SCIC_REMOTE_DEVICE object for an expander attached (ea) device from an
|
||||
* SMP Discover Response.
|
||||
* @remote_device: This parameter specifies the remote device to be destructed.
|
||||
* @discover_response: This parameter specifies the SMP Discovery Response to
|
||||
* be used in device creation.
|
||||
*
|
||||
* The user must have previously called scic_remote_device_construct() Remote
|
||||
* device objects are a limited resource. As such, they must be protected.
|
||||
* Thus calls to construct and destruct are mutually exclusive and
|
||||
* non-reentrant. Indicate if the remote device was successfully constructed.
|
||||
* SCI_SUCCESS Returned if the device was successfully constructed.
|
||||
* SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been
|
||||
* constructed. If it's an additional phy for the target, then call
|
||||
* scic_ea_remote_device_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned
|
||||
* if the supplied parameters necessitate creation of a remote device for which
|
||||
* the protocol is not supported by the underlying controller hardware.
|
||||
* SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core
|
||||
* controller associated with the supplied parameters is unable to support
|
||||
* additional remote devices.
|
||||
*/
|
||||
enum sci_status scic_remote_device_ea_construct(
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
struct smp_response_discover *discover_response);
|
||||
|
||||
/**
|
||||
* scic_remote_device_destruct() - This method is utilized to free up a core's
|
||||
* remote device object.
|
||||
* @remote_device: This parameter specifies the remote device to be destructed.
|
||||
*
|
||||
* Remote device objects are a limited resource. As such, they must be
|
||||
* protected. Thus calls to construct and destruct are mutually exclusive and
|
||||
* non-reentrant. The return value shall indicate if the device was
|
||||
* successfully destructed or if some failure occurred. enum sci_status This value
|
||||
* is returned if the device is successfully destructed.
|
||||
* SCI_FAILURE_INVALID_REMOTE_DEVICE This value is returned if the supplied
|
||||
* device isn't valid (e.g. it's already been destoryed, the handle isn't
|
||||
* valid, etc.).
|
||||
*/
|
||||
enum sci_status scic_remote_device_destruct(
|
||||
struct scic_sds_remote_device *remote_device);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* scic_remote_device_start() - This method will start the supplied remote
|
||||
* device. This method enables normal IO requests to flow through to the
|
||||
* remote device.
|
||||
* @remote_device: This parameter specifies the device to be started.
|
||||
* @timeout: This parameter specifies the number of milliseconds in which the
|
||||
* start operation should complete.
|
||||
*
|
||||
* An indication of whether the device was successfully started. SCI_SUCCESS
|
||||
* This value is returned if the device was successfully started.
|
||||
* SCI_FAILURE_INVALID_PHY This value is returned if the user attempts to start
|
||||
* the device when there have been no phys added to it.
|
||||
*/
|
||||
enum sci_status scic_remote_device_start(
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
u32 timeout);
|
||||
|
||||
/**
|
||||
* scic_remote_device_stop() - This method will stop both transmission and
|
||||
* reception of link activity for the supplied remote device. This method
|
||||
* disables normal IO requests from flowing through to the remote device.
|
||||
* @remote_device: This parameter specifies the device to be stopped.
|
||||
* @timeout: This parameter specifies the number of milliseconds in which the
|
||||
* stop operation should complete.
|
||||
*
|
||||
* An indication of whether the device was successfully stopped. SCI_SUCCESS
|
||||
* This value is returned if the transmission and reception for the device was
|
||||
* successfully stopped.
|
||||
*/
|
||||
enum sci_status scic_remote_device_stop(
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
u32 timeout);
|
||||
|
||||
/**
|
||||
* scic_remote_device_reset() - This method will reset the device making it
|
||||
* ready for operation. This method must be called anytime the device is
|
||||
* reset either through a SMP phy control or a port hard reset request.
|
||||
* @remote_device: This parameter specifies the device to be reset.
|
||||
*
|
||||
* This method does not actually cause the device hardware to be reset. This
|
||||
* method resets the software object so that it will be operational after a
|
||||
* device hardware reset completes. An indication of whether the device reset
|
||||
* was accepted. SCI_SUCCESS This value is returned if the device reset is
|
||||
* started.
|
||||
*/
|
||||
enum sci_status scic_remote_device_reset(
|
||||
struct scic_sds_remote_device *remote_device);
|
||||
|
||||
/**
|
||||
* scic_remote_device_reset_complete() - This method informs the device object
|
||||
* that the reset operation is complete and the device can resume operation
|
||||
* again.
|
||||
* @remote_device: This parameter specifies the device which is to be informed
|
||||
* of the reset complete operation.
|
||||
*
|
||||
* An indication that the device is resuming operation. SCI_SUCCESS the device
|
||||
* is resuming operation.
|
||||
*/
|
||||
enum sci_status scic_remote_device_reset_complete(
|
||||
struct scic_sds_remote_device *remote_device);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* scic_remote_device_get_connection_rate() - This method simply returns the
|
||||
* link rate at which communications to the remote device occur.
|
||||
* @remote_device: This parameter specifies the device for which to get the
|
||||
* connection rate.
|
||||
*
|
||||
* Return the link rate at which we transfer for the supplied remote device.
|
||||
*/
|
||||
enum sci_sas_link_rate scic_remote_device_get_connection_rate(
|
||||
struct scic_sds_remote_device *remote_device);
|
||||
|
||||
/**
|
||||
* scic_remote_device_get_protocols() - This method will indicate which
|
||||
* protocols are supported by this remote device.
|
||||
* @remote_device: This parameter specifies the device for which to return the
|
||||
* protocol.
|
||||
* @protocols: This parameter specifies the output values, from the remote
|
||||
* device object, which indicate the protocols supported by the supplied
|
||||
* remote_device.
|
||||
*
|
||||
* The type of protocols supported by this device. The values are returned as
|
||||
* part of a bit mask in order to allow for multi-protocol support.
|
||||
*/
|
||||
void scic_remote_device_get_protocols(
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
struct smp_discover_response_protocols *protocols);
|
||||
|
||||
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
/**
|
||||
* scic_remote_device_is_atapi() -
|
||||
* @this_device: The device whose type is to be decided.
|
||||
*
|
||||
* This method first decide whether a device is a stp target, then decode the
|
||||
* signature fis of a DA STP device to tell whether it is a standard end disk
|
||||
* or an ATAPI device. bool Indicate a device is ATAPI device or not.
|
||||
*/
|
||||
bool scic_remote_device_is_atapi(
|
||||
struct scic_sds_remote_device *device_handle);
|
||||
#else /* !defined(DISABLE_ATAPI) */
|
||||
#define scic_remote_device_is_atapi(device_handle) false
|
||||
#endif /* !defined(DISABLE_ATAPI) */
|
||||
|
||||
|
||||
#endif /* _SCIC_REMOTE_DEVICE_H_ */
|
||||
|
||||
4147
drivers/scsi/isci/core/scic_sds_controller.c
Normal file
4147
drivers/scsi/isci/core/scic_sds_controller.c
Normal file
File diff suppressed because it is too large
Load Diff
706
drivers/scsi/isci/core/scic_sds_controller.h
Normal file
706
drivers/scsi/isci/core/scic_sds_controller.h
Normal file
@@ -0,0 +1,706 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_CONTROLLER_H_
|
||||
#define _SCIC_SDS_CONTROLLER_H_
|
||||
|
||||
/**
|
||||
* This file contains the structures, constants and prototypes used for the
|
||||
* core controller object.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci_pool.h"
|
||||
#include "sci_controller_constants.h"
|
||||
#include "sci_memory_descriptor_list.h"
|
||||
#include "sci_base_controller.h"
|
||||
#include "scic_config_parameters.h"
|
||||
#include "scic_sds_port.h"
|
||||
#include "scic_sds_phy.h"
|
||||
#include "scic_sds_remote_node_table.h"
|
||||
#include "scu_registers.h"
|
||||
#include "scu_constants.h"
|
||||
#include "scu_remote_node_context.h"
|
||||
#include "scu_task_context.h"
|
||||
#include "scu_unsolicited_frame.h"
|
||||
#include "scic_sds_unsolicited_frame_control.h"
|
||||
#include "scic_sds_port_configuration_agent.h"
|
||||
#include "scic_sds_pci.h"
|
||||
|
||||
struct scic_sds_remote_device;
|
||||
struct scic_sds_request;
|
||||
struct scic_sds_controller;
|
||||
|
||||
|
||||
#define SCU_COMPLETION_RAM_ALIGNMENT (64)
|
||||
|
||||
/**
|
||||
* enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS -
|
||||
*
|
||||
* This enumeration depects the types of MDEs that are going to be created for
|
||||
* the controller object.
|
||||
*/
|
||||
enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS {
|
||||
/**
|
||||
* Completion queue MDE entry
|
||||
*/
|
||||
SCU_MDE_COMPLETION_QUEUE,
|
||||
|
||||
/**
|
||||
* Remote node context MDE entry
|
||||
*/
|
||||
SCU_MDE_REMOTE_NODE_CONTEXT,
|
||||
|
||||
/**
|
||||
* Task context MDE entry
|
||||
*/
|
||||
SCU_MDE_TASK_CONTEXT,
|
||||
|
||||
/**
|
||||
* Unsolicited frame buffer MDE entrys this is the start of the unsolicited
|
||||
* frame buffer entries.
|
||||
*/
|
||||
SCU_MDE_UF_BUFFER,
|
||||
|
||||
SCU_MAX_MDES
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Allowed PORT configuration modes APC Automatic PORT configuration mode is
|
||||
* defined by the OEM configuration parameters providing no PHY_MASK parameters
|
||||
* for any PORT. i.e. There are no phys assigned to any of the ports at start.
|
||||
* MPC Manual PORT configuration mode is defined by the OEM configuration
|
||||
* parameters providing a PHY_MASK value for any PORT. It is assumed that any
|
||||
* PORT with no PHY_MASK is an invalid port and not all PHYs must be assigned.
|
||||
* A PORT_PHY mask that assigns just a single PHY to a port and no other PHYs
|
||||
* being assigned is sufficient to declare manual PORT configuration.
|
||||
*/
|
||||
enum SCIC_PORT_CONFIGURATION_MODE {
|
||||
SCIC_PORT_MANUAL_CONFIGURATION_MODE,
|
||||
SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_power_control -
|
||||
*
|
||||
* This structure defines the fields for managing power control for direct
|
||||
* attached disk devices.
|
||||
*/
|
||||
struct scic_power_control {
|
||||
/**
|
||||
* This field is set when the power control timer is running and cleared when
|
||||
* it is not.
|
||||
*/
|
||||
bool timer_started;
|
||||
|
||||
/**
|
||||
* This field is the handle to the driver timer object. This timer is used to
|
||||
* control when the directed attached disks can consume power.
|
||||
*/
|
||||
void *timer;
|
||||
|
||||
/**
|
||||
* This field is used to keep track of how many phys are put into the
|
||||
* requesters field.
|
||||
*/
|
||||
u8 phys_waiting;
|
||||
|
||||
/**
|
||||
* This field is an array of phys that we are waiting on. The phys are direct
|
||||
* mapped into requesters via struct scic_sds_phy.phy_index
|
||||
*/
|
||||
struct scic_sds_phy *requesters[SCI_MAX_PHYS];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_sds_controller -
|
||||
*
|
||||
* This structure represents the SCU contoller object.
|
||||
*/
|
||||
struct scic_sds_controller {
|
||||
/**
|
||||
* The struct sci_base_controller is the parent object for the struct scic_sds_controller
|
||||
* object.
|
||||
*/
|
||||
struct sci_base_controller parent;
|
||||
|
||||
/**
|
||||
* This field is the driver timer object handler used to time the controller
|
||||
* object start and stop requests.
|
||||
*/
|
||||
void *timeout_timer;
|
||||
|
||||
/**
|
||||
* This field contains the user parameters to be utilized for this
|
||||
* core controller object.
|
||||
*/
|
||||
union scic_user_parameters user_parameters;
|
||||
|
||||
/**
|
||||
* This field contains the OEM parameters to be utilized for this
|
||||
* core controller object.
|
||||
*/
|
||||
union scic_oem_parameters oem_parameters;
|
||||
|
||||
/**
|
||||
* This field contains the port configuration agent for this controller.
|
||||
*/
|
||||
struct scic_sds_port_configuration_agent port_agent;
|
||||
|
||||
/**
|
||||
* This field is the array of port objects that are controlled by this
|
||||
* controller object. There is one dummy port object also contained within
|
||||
* this controller object.
|
||||
*/
|
||||
struct scic_sds_port port_table[SCI_MAX_PORTS + 1];
|
||||
|
||||
/**
|
||||
* This field is the array of phy objects that are controlled by this
|
||||
* controller object.
|
||||
*/
|
||||
struct scic_sds_phy phy_table[SCI_MAX_PHYS];
|
||||
|
||||
/**
|
||||
* This field is the array of device objects that are currently constructed
|
||||
* for this controller object. This table is used as a fast lookup of device
|
||||
* objects that need to handle device completion notifications from the
|
||||
* hardware. The table is RNi based.
|
||||
*/
|
||||
struct scic_sds_remote_device *device_table[SCI_MAX_REMOTE_DEVICES];
|
||||
|
||||
/**
|
||||
* This field is the array of IO request objects that are currently active for
|
||||
* this controller object. This table is used as a fast lookup of the io
|
||||
* request object that need to handle completion queue notifications. The
|
||||
* table is TCi based.
|
||||
*/
|
||||
struct scic_sds_request *io_request_table[SCI_MAX_IO_REQUESTS];
|
||||
|
||||
/**
|
||||
* This field is the free RNi data structure
|
||||
*/
|
||||
struct scic_remote_node_table available_remote_nodes;
|
||||
|
||||
/**
|
||||
* This field is the TCi pool used to manage the task context index.
|
||||
*/
|
||||
SCI_POOL_CREATE(tci_pool, u16, SCI_MAX_IO_REQUESTS);
|
||||
|
||||
/**
|
||||
* This filed is the struct scic_power_control data used to controll when direct
|
||||
* attached devices can consume power.
|
||||
*/
|
||||
struct scic_power_control power_control;
|
||||
|
||||
/**
|
||||
* This field is the array of sequence values for the IO Tag fields. Even
|
||||
* though only 4 bits of the field is used for the sequence the sequence is 16
|
||||
* bits in size so the sequence can be bitwise or'd with the TCi to build the
|
||||
* IO Tag value.
|
||||
*/
|
||||
u16 io_request_sequence[SCI_MAX_IO_REQUESTS];
|
||||
|
||||
/**
|
||||
* This field in the array of sequence values for the RNi. These are used
|
||||
* to control io request build to io request start operations. The sequence
|
||||
* value is recorded into an io request when it is built and is checked on
|
||||
* the io request start operation to make sure that there was not a device
|
||||
* hot plug between the build and start operation.
|
||||
*/
|
||||
u8 remote_device_sequence[SCI_MAX_REMOTE_DEVICES];
|
||||
|
||||
/**
|
||||
* This field is a pointer to the memory allocated by the driver for the task
|
||||
* context table. This data is shared between the hardware and software.
|
||||
*/
|
||||
struct scu_task_context *task_context_table;
|
||||
|
||||
/**
|
||||
* This field is a pointer to the memory allocated by the driver for the
|
||||
* remote node context table. This table is shared between the hardware and
|
||||
* software.
|
||||
*/
|
||||
union scu_remote_node_context *remote_node_context_table;
|
||||
|
||||
/**
|
||||
* This field is the array of physical memory requiremets for this controller
|
||||
* object.
|
||||
*/
|
||||
struct sci_physical_memory_descriptor memory_descriptors[SCU_MAX_MDES];
|
||||
|
||||
/**
|
||||
* This field is a pointer to the completion queue. This memory is
|
||||
* written to by the hardware and read by the software.
|
||||
*/
|
||||
u32 *completion_queue;
|
||||
|
||||
/**
|
||||
* This field is the software copy of the completion queue get pointer. The
|
||||
* controller object writes this value to the hardware after processing the
|
||||
* completion entries.
|
||||
*/
|
||||
u32 completion_queue_get;
|
||||
|
||||
/**
|
||||
* This field is the minimum of the number of hardware supported port entries
|
||||
* and the software requested port entries.
|
||||
*/
|
||||
u32 logical_port_entries;
|
||||
|
||||
/**
|
||||
* This field is the minimum number of hardware supported completion queue
|
||||
* entries and the software requested completion queue entries.
|
||||
*/
|
||||
u32 completion_queue_entries;
|
||||
|
||||
/**
|
||||
* This field is the minimum number of hardware supported event entries and
|
||||
* the software requested event entries.
|
||||
*/
|
||||
u32 completion_event_entries;
|
||||
|
||||
/**
|
||||
* This field is the minimum number of devices supported by the hardware and
|
||||
* the number of devices requested by the software.
|
||||
*/
|
||||
u32 remote_node_entries;
|
||||
|
||||
/**
|
||||
* This field is the minimum number of IO requests supported by the hardware
|
||||
* and the number of IO requests requested by the software.
|
||||
*/
|
||||
u32 task_context_entries;
|
||||
|
||||
/**
|
||||
* This object contains all of the unsolicited frame specific
|
||||
* data utilized by the core controller.
|
||||
*/
|
||||
struct scic_sds_unsolicited_frame_control uf_control;
|
||||
|
||||
/**
|
||||
* This field records the fact that the controller has encountered a fatal
|
||||
* error and must be reset.
|
||||
*/
|
||||
bool encountered_fatal_error;
|
||||
|
||||
/**
|
||||
* This field specifies that the controller should ignore
|
||||
* completion processing for non-fastpath events. This will
|
||||
* cause the completions to be thrown away.
|
||||
*/
|
||||
bool restrict_completions;
|
||||
|
||||
/* Phy Startup Data */
|
||||
/**
|
||||
* This field is the driver timer handle for controller phy request startup.
|
||||
* On controller start the controller will start each PHY individually in
|
||||
* order of phy index.
|
||||
*/
|
||||
void *phy_startup_timer;
|
||||
|
||||
/**
|
||||
* This field is set when the phy_startup_timer is running and is cleared when
|
||||
* the phy_startup_timer is stopped.
|
||||
*/
|
||||
bool phy_startup_timer_pending;
|
||||
|
||||
/**
|
||||
* This field is the index of the next phy start. It is initialized to 0 and
|
||||
* increments for each phy index that is started.
|
||||
*/
|
||||
u32 next_phy_to_start;
|
||||
|
||||
/**
|
||||
* This field controlls the invalid link up notifications to the SCI_USER. If
|
||||
* an invalid_link_up notification is reported a bit for the PHY index is set
|
||||
* so further notifications are not made. Once the PHY object reports link up
|
||||
* and is made part of a port then this bit for the PHY index is cleared.
|
||||
*/
|
||||
u8 invalid_phy_mask;
|
||||
|
||||
/*
|
||||
* This field saves the current interrupt coalescing number of the controller.
|
||||
*/
|
||||
u16 interrupt_coalesce_number;
|
||||
|
||||
/*
|
||||
* This field saves the current interrupt coalescing timeout value in microseconds.
|
||||
*/
|
||||
u32 interrupt_coalesce_timeout;
|
||||
|
||||
/**
|
||||
* This field is a pointer to the memory mapped register space for the
|
||||
* struct smu_registers.
|
||||
*/
|
||||
struct smu_registers __iomem *smu_registers;
|
||||
|
||||
/**
|
||||
* This field is a pointer to the memory mapped register space for the
|
||||
* struct scu_registers.
|
||||
*/
|
||||
struct scu_registers __iomem *scu_registers;
|
||||
|
||||
};
|
||||
|
||||
typedef void (*scic_sds_controller_phy_handler_t)(struct scic_sds_controller *,
|
||||
struct scic_sds_port *,
|
||||
struct scic_sds_phy *);
|
||||
/**
|
||||
* struct scic_sds_controller_state_handler -
|
||||
*
|
||||
* This structure contains the SDS core specific definition for the state
|
||||
* handlers.
|
||||
*/
|
||||
struct scic_sds_controller_state_handler {
|
||||
struct sci_base_controller_state_handler base;
|
||||
|
||||
sci_base_controller_request_handler_t terminate_request;
|
||||
scic_sds_controller_phy_handler_t link_up;
|
||||
scic_sds_controller_phy_handler_t link_down;
|
||||
};
|
||||
|
||||
extern const struct scic_sds_controller_state_handler
|
||||
scic_sds_controller_state_handler_table[];
|
||||
extern const struct sci_base_state scic_sds_controller_state_table[];
|
||||
|
||||
/**
|
||||
* INCREMENT_QUEUE_GET() -
|
||||
*
|
||||
* This macro will increment the specified index to and if the index wraps to 0
|
||||
* it will toggel the cycle bit.
|
||||
*/
|
||||
#define INCREMENT_QUEUE_GET(index, cycle, entry_count, bit_toggle) \
|
||||
{ \
|
||||
if ((index) + 1 == entry_count) { \
|
||||
(index) = 0; \
|
||||
(cycle) = (cycle) ^ (bit_toggle); \
|
||||
} else { \
|
||||
index = index + 1; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_sds_controller_get_base_state_machine() -
|
||||
*
|
||||
* This is a helper macro that gets the base state machine for the controller
|
||||
* object
|
||||
*/
|
||||
#define scic_sds_controller_get_base_state_machine(this_controller) \
|
||||
(&(this_controller)->parent.state_machine)
|
||||
|
||||
/**
|
||||
* scic_sds_controller_get_port_configuration_agent() -
|
||||
*
|
||||
* This is a helper macro to get the port configuration agent from the
|
||||
* controller object.
|
||||
*/
|
||||
#define scic_sds_controller_get_port_configuration_agent(controller) \
|
||||
(&(controller)->port_agent)
|
||||
|
||||
/**
|
||||
* smu_register_write() -
|
||||
*
|
||||
* This macro writes to the smu_register for this controller
|
||||
*/
|
||||
#define smu_register_write(controller, reg, value) \
|
||||
scic_sds_pci_write_smu_dword((controller), &(reg), (value))
|
||||
|
||||
/**
|
||||
* smu_register_read() -
|
||||
*
|
||||
* This macro reads the smu_register for this controller
|
||||
*/
|
||||
#define smu_register_read(controller, reg) \
|
||||
scic_sds_pci_read_smu_dword((controller), &(reg))
|
||||
|
||||
/**
|
||||
* scu_register_write() -
|
||||
*
|
||||
* This mcaro writes the scu_register for this controller
|
||||
*/
|
||||
#define scu_register_write(controller, reg, value) \
|
||||
scic_sds_pci_write_scu_dword((controller), &(reg), (value))
|
||||
|
||||
/**
|
||||
* scu_register_read() -
|
||||
*
|
||||
* This macro reads the scu_register for this controller
|
||||
*/
|
||||
#define scu_register_read(controller, reg) \
|
||||
scic_sds_pci_read_scu_dword((controller), &(reg))
|
||||
|
||||
/**
|
||||
* scic_sds_controller_get_protocol_engine_group() -
|
||||
*
|
||||
* This macro returns the protocol engine group for this controller object.
|
||||
* Presently we only support protocol engine group 0 so just return that
|
||||
*/
|
||||
#define scic_sds_controller_get_protocol_engine_group(controller) 0
|
||||
|
||||
/**
|
||||
* scic_sds_io_tag_construct() -
|
||||
*
|
||||
* This macro constructs an IO tag from the sequence and index values.
|
||||
*/
|
||||
#define scic_sds_io_tag_construct(sequence, task_index) \
|
||||
((sequence) << 12 | (task_index))
|
||||
|
||||
/**
|
||||
* scic_sds_io_tag_get_sequence() -
|
||||
*
|
||||
* This macro returns the IO sequence from the IO tag value.
|
||||
*/
|
||||
#define scic_sds_io_tag_get_sequence(io_tag) \
|
||||
(((io_tag) & 0xF000) >> 12)
|
||||
|
||||
/**
|
||||
* scic_sds_io_tag_get_index() -
|
||||
*
|
||||
* This macro returns the TCi from the io tag value
|
||||
*/
|
||||
#define scic_sds_io_tag_get_index(io_tag) \
|
||||
((io_tag) & 0x0FFF)
|
||||
|
||||
/**
|
||||
* scic_sds_io_sequence_increment() -
|
||||
*
|
||||
* This is a helper macro to increment the io sequence count. We may find in
|
||||
* the future that it will be faster to store the sequence count in such a way
|
||||
* as we dont perform the shift operation to build io tag values so therefore
|
||||
* need a way to incrment them correctly
|
||||
*/
|
||||
#define scic_sds_io_sequence_increment(value) \
|
||||
((value) = (((value) + 1) & 0x000F))
|
||||
|
||||
#define scic_sds_remote_device_node_count(device) \
|
||||
(\
|
||||
(\
|
||||
(device)->target_protocols.u.bits.attached_stp_target \
|
||||
&& ((device)->is_direct_attached != true) \
|
||||
) \
|
||||
? SCU_STP_REMOTE_NODE_COUNT : SCU_SSP_REMOTE_NODE_COUNT \
|
||||
)
|
||||
|
||||
/**
|
||||
* scic_sds_controller_set_invalid_phy() -
|
||||
*
|
||||
* This macro will set the bit in the invalid phy mask for this controller
|
||||
* object. This is used to control messages reported for invalid link up
|
||||
* notifications.
|
||||
*/
|
||||
#define scic_sds_controller_set_invalid_phy(controller, phy) \
|
||||
((controller)->invalid_phy_mask |= (1 << (phy)->phy_index))
|
||||
|
||||
/**
|
||||
* scic_sds_controller_clear_invalid_phy() -
|
||||
*
|
||||
* This macro will clear the bit in the invalid phy mask for this controller
|
||||
* object. This is used to control messages reported for invalid link up
|
||||
* notifications.
|
||||
*/
|
||||
#define scic_sds_controller_clear_invalid_phy(controller, phy) \
|
||||
((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index))
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
u32 scic_sds_controller_get_object_size(void);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
void scic_sds_controller_post_request(
|
||||
struct scic_sds_controller *this_controller,
|
||||
u32 request);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
void scic_sds_controller_release_frame(
|
||||
struct scic_sds_controller *this_controller,
|
||||
u32 frame_index);
|
||||
|
||||
void scic_sds_controller_copy_sata_response(
|
||||
void *response_buffer,
|
||||
void *frame_header,
|
||||
void *frame_buffer);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
enum sci_status scic_sds_controller_allocate_remote_node_context(
|
||||
struct scic_sds_controller *this_controller,
|
||||
struct scic_sds_remote_device *the_device,
|
||||
u16 *node_id);
|
||||
|
||||
void scic_sds_controller_free_remote_node_context(
|
||||
struct scic_sds_controller *this_controller,
|
||||
struct scic_sds_remote_device *the_device,
|
||||
u16 node_id);
|
||||
|
||||
union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer(
|
||||
struct scic_sds_controller *this_controller,
|
||||
u16 node_id);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
struct scic_sds_request *scic_sds_controller_get_io_request_from_tag(
|
||||
struct scic_sds_controller *this_controller,
|
||||
u16 io_tag);
|
||||
|
||||
|
||||
struct scu_task_context *scic_sds_controller_get_task_context_buffer(
|
||||
struct scic_sds_controller *this_controller,
|
||||
u16 io_tag);
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * CORE CONTROLLER POWER CONTROL METHODS
|
||||
* ***************************************************************************** */
|
||||
|
||||
|
||||
void scic_sds_controller_power_control_queue_insert(
|
||||
struct scic_sds_controller *this_controller,
|
||||
struct scic_sds_phy *the_phy);
|
||||
|
||||
void scic_sds_controller_power_control_queue_remove(
|
||||
struct scic_sds_controller *this_controller,
|
||||
struct scic_sds_phy *the_phy);
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * CORE CONTROLLER PHY MESSAGE PROCESSING
|
||||
* ***************************************************************************** */
|
||||
|
||||
void scic_sds_controller_link_up(
|
||||
struct scic_sds_controller *this_controller,
|
||||
struct scic_sds_port *the_port,
|
||||
struct scic_sds_phy *the_phy);
|
||||
|
||||
void scic_sds_controller_link_down(
|
||||
struct scic_sds_controller *this_controller,
|
||||
struct scic_sds_port *the_port,
|
||||
struct scic_sds_phy *the_phy);
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * CORE CONTROLLER PRIVATE METHODS
|
||||
* ***************************************************************************** */
|
||||
|
||||
enum sci_status scic_sds_controller_validate_memory_descriptor_table(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
void scic_sds_controller_ram_initialization(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
void scic_sds_controller_assign_task_entries(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
void scic_sds_controller_afe_initialization(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
void scic_sds_controller_enable_port_task_scheduler(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
void scic_sds_controller_initialize_completion_queue(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
void scic_sds_controller_initialize_unsolicited_frame_queue(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
void scic_sds_controller_phy_timer_stop(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
enum sci_status scic_sds_controller_start_next_phy(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
enum sci_status scic_sds_controller_stop_phys(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
enum sci_status scic_sds_controller_stop_ports(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
enum sci_status scic_sds_controller_stop_devices(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
void scic_sds_controller_copy_task_context(
|
||||
struct scic_sds_controller *this_controller,
|
||||
struct scic_sds_request *this_request);
|
||||
|
||||
void scic_sds_controller_timeout_handler(
|
||||
struct scic_sds_controller *controller);
|
||||
|
||||
void scic_sds_controller_initialize_power_control(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
void scic_sds_controller_register_setup(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
void scic_sds_controller_reset_hardware(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
|
||||
void scic_sds_controller_initialize_phy_startup(
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
#endif /* _SCIC_SDS_CONTROLLER_H_ */
|
||||
463
drivers/scsi/isci/core/scic_sds_controller_registers.h
Normal file
463
drivers/scsi/isci/core/scic_sds_controller_registers.h
Normal file
@@ -0,0 +1,463 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_CONTROLLER_REGISTERS_H_
|
||||
#define _SCIC_SDS_CONTROLLER_REGISTERS_H_
|
||||
|
||||
/**
|
||||
* This file contains macros used to perform the register reads/writes to the
|
||||
* SCU hardware.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "scu_registers.h"
|
||||
#include "scic_sds_controller.h"
|
||||
|
||||
/**
|
||||
* scic_sds_controller_smu_register_read() -
|
||||
*
|
||||
* SMU_REGISTER_ACCESS_MACROS
|
||||
*/
|
||||
#define scic_sds_controller_smu_register_read(controller, reg) \
|
||||
smu_register_read(\
|
||||
(controller), \
|
||||
(controller)->smu_registers->reg \
|
||||
)
|
||||
|
||||
#define scic_sds_controller_smu_register_write(controller, reg, value) \
|
||||
smu_register_write(\
|
||||
(controller), \
|
||||
(controller)->smu_registers->reg, \
|
||||
(value) \
|
||||
)
|
||||
|
||||
/**
|
||||
* scu_afe_register_write() -
|
||||
*
|
||||
* AFE_REGISTER_ACCESS_MACROS
|
||||
*/
|
||||
#define scu_afe_register_write(controller, reg, value) \
|
||||
scu_register_write(\
|
||||
(controller), \
|
||||
(controller)->scu_registers->afe.reg, \
|
||||
(value) \
|
||||
)
|
||||
|
||||
#define scu_afe_txreg_write(controller, phy, reg, value) \
|
||||
scu_register_write(\
|
||||
(controller), \
|
||||
(controller)->scu_registers->afe.scu_afe_xcvr[phy].reg,\
|
||||
(value) \
|
||||
)
|
||||
|
||||
#define scu_afe_register_read(controller, reg) \
|
||||
scu_register_read(\
|
||||
(controller), \
|
||||
(controller)->scu_registers->afe.reg \
|
||||
)
|
||||
|
||||
/**
|
||||
* scu_controller_viit_register_write() -
|
||||
*
|
||||
* VIIT_REGISTER_ACCESS_MACROS
|
||||
*/
|
||||
#define scu_controller_viit_register_write(controller, index, reg, value) \
|
||||
scu_register_write(\
|
||||
(controller), \
|
||||
(controller)->scu_registers->peg0.viit[index].reg, \
|
||||
value \
|
||||
)
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * SMU REGISTERS
|
||||
* ***************************************************************************** */
|
||||
|
||||
/**
|
||||
* SMU_PCP_WRITE() -
|
||||
*
|
||||
* struct smu_registers
|
||||
*/
|
||||
#define SMU_PCP_WRITE(controller, value) \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, post_context_port, value \
|
||||
)
|
||||
|
||||
#define SMU_TCR_READ(controller, value) \
|
||||
scic_sds_controller_smu_register_read(\
|
||||
controller, task_context_range \
|
||||
)
|
||||
|
||||
#define SMU_TCR_WRITE(controller, value) \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, task_context_range, value \
|
||||
)
|
||||
|
||||
#define SMU_HTTBAR_WRITE(controller, address) \
|
||||
{ \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, \
|
||||
host_task_table_lower, \
|
||||
lower_32_bits(address) \
|
||||
); \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, \
|
||||
host_task_table_upper, \
|
||||
upper_32_bits(address) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define SMU_CQBAR_WRITE(controller, address) \
|
||||
{ \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, \
|
||||
completion_queue_lower, \
|
||||
lower_32_bits(address) \
|
||||
); \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, \
|
||||
completion_queue_upper, \
|
||||
upper_32_bits(address) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define SMU_CQGR_WRITE(controller, value) \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, completion_queue_get, value \
|
||||
)
|
||||
|
||||
#define SMU_CQGR_READ(controller, value) \
|
||||
scic_sds_controller_smu_register_read(\
|
||||
controller, completion_queue_get \
|
||||
)
|
||||
|
||||
#define SMU_CQPR_WRITE(controller, value) \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, completion_queue_put, value \
|
||||
)
|
||||
|
||||
#define SMU_RNCBAR_WRITE(controller, address) \
|
||||
{ \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, \
|
||||
remote_node_context_lower, \
|
||||
lower_32_bits(address) \
|
||||
); \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, \
|
||||
remote_node_context_upper, \
|
||||
upper_32_bits(address) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define SMU_AMR_READ(controller) \
|
||||
scic_sds_controller_smu_register_read(\
|
||||
controller, address_modifier \
|
||||
)
|
||||
|
||||
#define SMU_IMR_READ(controller) \
|
||||
scic_sds_controller_smu_register_read(\
|
||||
controller, interrupt_mask \
|
||||
)
|
||||
|
||||
#define SMU_IMR_WRITE(controller, mask) \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, interrupt_mask, mask \
|
||||
)
|
||||
|
||||
#define SMU_ISR_READ(controller) \
|
||||
scic_sds_controller_smu_register_read(\
|
||||
controller, interrupt_status \
|
||||
)
|
||||
|
||||
#define SMU_ISR_WRITE(controller, status) \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, interrupt_status, status \
|
||||
)
|
||||
|
||||
#define SMU_ICC_READ(controller) \
|
||||
scic_sds_controller_smu_register_read(\
|
||||
controller, interrupt_coalesce_control \
|
||||
)
|
||||
|
||||
#define SMU_ICC_WRITE(controller, value) \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, interrupt_coalesce_control, value \
|
||||
)
|
||||
|
||||
#define SMU_CQC_WRITE(controller, value) \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, completion_queue_control, value \
|
||||
)
|
||||
|
||||
#define SMU_SMUSRCR_WRITE(controller, value) \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, soft_reset_control, value \
|
||||
)
|
||||
|
||||
#define SMU_TCA_WRITE(controller, index, value) \
|
||||
scic_sds_controller_smu_register_write(\
|
||||
controller, task_context_assignment[index], value \
|
||||
)
|
||||
|
||||
#define SMU_TCA_READ(controller, index) \
|
||||
scic_sds_controller_smu_register_read(\
|
||||
controller, task_context_assignment[index] \
|
||||
)
|
||||
|
||||
#define SMU_DCC_READ(controller) \
|
||||
scic_sds_controller_smu_register_read(\
|
||||
controller, device_context_capacity \
|
||||
)
|
||||
|
||||
#define SMU_DFC_READ(controller) \
|
||||
scic_sds_controller_smu_register_read(\
|
||||
controller, device_function_capacity \
|
||||
)
|
||||
|
||||
#define SMU_SMUCSR_READ(controller) \
|
||||
scic_sds_controller_smu_register_read(\
|
||||
controller, control_status \
|
||||
)
|
||||
|
||||
#define SMU_CQPR_READ(controller) \
|
||||
scic_sds_controller_smu_register_read(\
|
||||
controller, completion_queue_put \
|
||||
)
|
||||
|
||||
|
||||
/**
|
||||
* scic_sds_controller_scu_register_read() -
|
||||
*
|
||||
* SCU_REGISTER_ACCESS_MACROS
|
||||
*/
|
||||
#define scic_sds_controller_scu_register_read(controller, reg) \
|
||||
scu_register_read(\
|
||||
(controller), \
|
||||
(controller)->scu_registers->reg \
|
||||
)
|
||||
|
||||
#define scic_sds_controller_scu_register_write(controller, reg, value) \
|
||||
scu_register_write(\
|
||||
(controller), \
|
||||
(controller)->scu_registers->reg, \
|
||||
(value) \
|
||||
)
|
||||
|
||||
|
||||
/*
|
||||
* ****************************************************************************
|
||||
* * SCU SDMA REGISTERS
|
||||
* **************************************************************************** */
|
||||
|
||||
/**
|
||||
* scu_sdma_register_read() -
|
||||
*
|
||||
* SCU_SDMA_REGISTER_ACCESS_MACROS
|
||||
*/
|
||||
#define scu_sdma_register_read(controller, reg) \
|
||||
scu_register_read(\
|
||||
(controller), \
|
||||
(controller)->scu_registers->sdma.reg \
|
||||
)
|
||||
|
||||
#define scu_sdma_register_write(controller, reg, value) \
|
||||
scu_register_write(\
|
||||
(controller), \
|
||||
(controller)->scu_registers->sdma.reg, \
|
||||
(value) \
|
||||
)
|
||||
|
||||
/**
|
||||
* SCU_PUFATHAR_WRITE() -
|
||||
*
|
||||
* struct scu_sdma_registers
|
||||
*/
|
||||
#define SCU_PUFATHAR_WRITE(controller, address) \
|
||||
{ \
|
||||
scu_sdma_register_write(\
|
||||
controller, \
|
||||
uf_address_table_lower, \
|
||||
lower_32_bits(address) \
|
||||
); \
|
||||
scu_sdma_register_write(\
|
||||
controller, \
|
||||
uf_address_table_upper, \
|
||||
upper_32_bits(address) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define SCU_UFHBAR_WRITE(controller, address) \
|
||||
{ \
|
||||
scu_sdma_register_write(\
|
||||
controller, \
|
||||
uf_header_base_address_lower, \
|
||||
lower_32_bits(address) \
|
||||
); \
|
||||
scu_sdma_register_write(\
|
||||
controller, \
|
||||
uf_header_base_address_upper, \
|
||||
upper_32_bits(address) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define SCU_UFQC_READ(controller) \
|
||||
scu_sdma_register_read(\
|
||||
controller, \
|
||||
unsolicited_frame_queue_control \
|
||||
)
|
||||
|
||||
#define SCU_UFQC_WRITE(controller, value) \
|
||||
scu_sdma_register_write(\
|
||||
controller, \
|
||||
unsolicited_frame_queue_control, \
|
||||
value \
|
||||
)
|
||||
|
||||
#define SCU_UFQPP_READ(controller) \
|
||||
scu_sdma_register_read(\
|
||||
controller, \
|
||||
unsolicited_frame_put_pointer \
|
||||
)
|
||||
|
||||
#define SCU_UFQPP_WRITE(controller, value) \
|
||||
scu_sdma_register_write(\
|
||||
controller, \
|
||||
unsolicited_frame_put_pointer, \
|
||||
value \
|
||||
)
|
||||
|
||||
#define SCU_UFQGP_WRITE(controller, value) \
|
||||
scu_sdma_register_write(\
|
||||
controller, \
|
||||
unsolicited_frame_get_pointer, \
|
||||
value \
|
||||
)
|
||||
|
||||
#define SCU_PDMACR_READ(controller) \
|
||||
scu_sdma_register_read(\
|
||||
controller, \
|
||||
pdma_configuration \
|
||||
)
|
||||
|
||||
#define SCU_PDMACR_WRITE(controller, value) \
|
||||
scu_sdma_register_write(\
|
||||
controller, \
|
||||
pdma_configuration, \
|
||||
value \
|
||||
)
|
||||
|
||||
#define SCU_CDMACR_READ(controller) \
|
||||
scu_sdma_register_read(\
|
||||
controller, \
|
||||
cdma_configuration \
|
||||
)
|
||||
|
||||
#define SCU_CDMACR_WRITE(controller, value) \
|
||||
scu_sdma_register_write(\
|
||||
controller, \
|
||||
cdma_configuration, \
|
||||
value \
|
||||
)
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * SCU Port Task Scheduler Group Registers
|
||||
* ***************************************************************************** */
|
||||
|
||||
/**
|
||||
* scu_ptsg_register_read() -
|
||||
*
|
||||
* SCU_PTSG_REGISTER_ACCESS_MACROS
|
||||
*/
|
||||
#define scu_ptsg_register_read(controller, reg) \
|
||||
scu_register_read(\
|
||||
(controller), \
|
||||
(controller)->scu_registers->peg0.ptsg.reg \
|
||||
)
|
||||
|
||||
#define scu_ptsg_register_write(controller, reg, value) \
|
||||
scu_register_write(\
|
||||
(controller), \
|
||||
(controller)->scu_registers->peg0.ptsg.reg, \
|
||||
(value) \
|
||||
)
|
||||
|
||||
/**
|
||||
* SCU_PTSGCR_READ() -
|
||||
*
|
||||
* SCU_PTSG_REGISTERS
|
||||
*/
|
||||
#define SCU_PTSGCR_READ(controller) \
|
||||
scu_ptsg_register_read(\
|
||||
(controller), \
|
||||
control \
|
||||
)
|
||||
|
||||
#define SCU_PTSGCR_WRITE(controller, value) \
|
||||
scu_ptsg_register_write(\
|
||||
(controller), \
|
||||
control, \
|
||||
value \
|
||||
)
|
||||
|
||||
#define SCU_PTSGRTC_READ(controller) \
|
||||
scu_ptsg_register_read(\
|
||||
contoller, \
|
||||
real_time_clock \
|
||||
)
|
||||
|
||||
#endif /* _SCIC_SDS_CONTROLLER_REGISTERS_H_ */
|
||||
95
drivers/scsi/isci/core/scic_sds_pci.h
Normal file
95
drivers/scsi/isci/core/scic_sds_pci.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_PCI_H_
|
||||
#define _SCIC_SDS_PCI_H_
|
||||
|
||||
/**
|
||||
* This file contains the prototypes/macros utilized in writing out PCI data
|
||||
* for the SCI core.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <asm/io.h>
|
||||
#include "sci_types.h"
|
||||
|
||||
struct scic_sds_controller;
|
||||
|
||||
void scic_sds_pci_bar_initialization(struct scic_sds_controller *scic);
|
||||
|
||||
/* for debug we separate scu and smu accesses and require a controller */
|
||||
static inline u32 scic_sds_pci_read_smu_dword(struct scic_sds_controller *scic, void __iomem *addr)
|
||||
{
|
||||
return readl(addr);
|
||||
}
|
||||
|
||||
static inline void scic_sds_pci_write_smu_dword(struct scic_sds_controller *scic, void __iomem *addr, u32 value)
|
||||
{
|
||||
writel(value, addr);
|
||||
}
|
||||
|
||||
static inline u32 scic_sds_pci_read_scu_dword(struct scic_sds_controller *scic, void __iomem *addr)
|
||||
{
|
||||
return readl(addr);
|
||||
}
|
||||
|
||||
static inline void scic_sds_pci_write_scu_dword(struct scic_sds_controller *scic, void __iomem *addr, u32 value)
|
||||
{
|
||||
writel(value, addr);
|
||||
}
|
||||
|
||||
|
||||
#endif /* _SCIC_SDS_PCI_H_ */
|
||||
2807
drivers/scsi/isci/core/scic_sds_phy.c
Normal file
2807
drivers/scsi/isci/core/scic_sds_phy.c
Normal file
File diff suppressed because it is too large
Load Diff
491
drivers/scsi/isci/core/scic_sds_phy.h
Normal file
491
drivers/scsi/isci/core/scic_sds_phy.h
Normal file
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_PHY_H_
|
||||
#define _SCIC_SDS_PHY_H_
|
||||
|
||||
/**
|
||||
* This file contains the structures, constants and prototypes for the
|
||||
* struct scic_sds_phy object.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "intel_sata.h"
|
||||
#include "intel_sas.h"
|
||||
#include "sci_base_phy.h"
|
||||
#include "scu_registers.h"
|
||||
|
||||
struct scic_sds_port;
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This is the timeout value for the SATA phy to wait for a SIGNATURE FIS
|
||||
* before restarting the starting state machine. Technically, the old parallel
|
||||
* ATA specification required up to 30 seconds for a device to issue its
|
||||
* signature FIS as a result of a soft reset. Now we see that devices respond
|
||||
* generally within 15 seconds, but we'll use 25 for now.
|
||||
*/
|
||||
#define SCIC_SDS_SIGNATURE_FIS_TIMEOUT 25000
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This is the timeout for the SATA OOB/SN because the hardware does not
|
||||
* recognize a hot plug after OOB signal but before the SN signals. We need to
|
||||
* make sure after a hotplug timeout if we have not received the speed event
|
||||
* notification from the hardware that we restart the hardware OOB state
|
||||
* machine.
|
||||
*/
|
||||
#define SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT 250
|
||||
|
||||
/**
|
||||
* enum SCIC_SDS_PHY_STARTING_SUBSTATES -
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum SCIC_SDS_PHY_STARTING_SUBSTATES {
|
||||
/**
|
||||
* Initial state
|
||||
*/
|
||||
SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL,
|
||||
|
||||
/**
|
||||
* Wait state for the hardware OSSP event type notification
|
||||
*/
|
||||
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN,
|
||||
|
||||
/**
|
||||
* Wait state for the PHY speed notification
|
||||
*/
|
||||
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN,
|
||||
|
||||
/**
|
||||
* Wait state for the IAF Unsolicited frame notification
|
||||
*/
|
||||
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF,
|
||||
|
||||
/**
|
||||
* Wait state for the request to consume power
|
||||
*/
|
||||
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER,
|
||||
|
||||
/**
|
||||
* Wait state for request to consume power
|
||||
*/
|
||||
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER,
|
||||
|
||||
/**
|
||||
* Wait state for the SATA PHY notification
|
||||
*/
|
||||
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN,
|
||||
|
||||
/**
|
||||
* Wait for the SATA PHY speed notification
|
||||
*/
|
||||
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN,
|
||||
|
||||
/**
|
||||
* Wait state for the SIGNATURE FIS unsolicited frame notification
|
||||
*/
|
||||
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF,
|
||||
|
||||
/**
|
||||
* Exit state for this state machine
|
||||
*/
|
||||
SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL,
|
||||
|
||||
/**
|
||||
* Maximum number of substates for the STARTING state machine
|
||||
*/
|
||||
SCIC_SDS_PHY_STARTING_MAX_SUBSTATES
|
||||
};
|
||||
|
||||
struct scic_sds_port;
|
||||
struct scic_sds_controller;
|
||||
|
||||
#ifdef SCIC_DEBUG_ENABLED
|
||||
#define MAX_STATE_TRANSITION_RECORD (256)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Debug code to record the state transitions for the phy object
|
||||
*/
|
||||
struct scic_sds_phy_state_record {
|
||||
struct sci_base_observer base_state_observer;
|
||||
struct sci_base_observer starting_state_observer;
|
||||
|
||||
u16 index;
|
||||
|
||||
u32 state_transition_table[MAX_STATE_TRANSITION_RECORD];
|
||||
|
||||
};
|
||||
#endif /* SCIC_DEBUG_ENABLED */
|
||||
|
||||
/**
|
||||
* This enumeration provides a named phy type for the state machine
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum SCIC_SDS_PHY_PROTOCOL {
|
||||
/**
|
||||
* This is an unknown phy type since there is either nothing on the other
|
||||
* end or we have not detected the phy type as yet.
|
||||
*/
|
||||
SCIC_SDS_PHY_PROTOCOL_UNKNOWN,
|
||||
|
||||
/**
|
||||
* This is a SAS PHY
|
||||
*/
|
||||
SCIC_SDS_PHY_PROTOCOL_SAS,
|
||||
|
||||
/**
|
||||
* This is a SATA PHY
|
||||
*/
|
||||
SCIC_SDS_PHY_PROTOCOL_SATA,
|
||||
|
||||
SCIC_SDS_MAX_PHY_PROTOCOLS
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_sds_phy - This structure contains or references all of the data
|
||||
* necessary to represent the core phy object and SCU harware protocol
|
||||
* engine.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_sds_phy {
|
||||
struct sci_base_phy parent;
|
||||
|
||||
/**
|
||||
* This field specifies the port object that owns/contains this phy.
|
||||
*/
|
||||
struct scic_sds_port *owning_port;
|
||||
|
||||
/**
|
||||
* This field indicates whether the phy supports 1.5 Gb/s, 3.0 Gb/s,
|
||||
* or 6.0 Gb/s operation.
|
||||
*/
|
||||
enum sci_sas_link_rate max_negotiated_speed;
|
||||
|
||||
/**
|
||||
* This member specifies the protocol being utilized on this phy. This
|
||||
* field contains a legitamite value once the PHY has link trained with
|
||||
* a remote phy.
|
||||
*/
|
||||
enum SCIC_SDS_PHY_PROTOCOL protocol;
|
||||
|
||||
/**
|
||||
* This field specifies the index with which this phy is associated (0-3).
|
||||
*/
|
||||
u8 phy_index;
|
||||
|
||||
/**
|
||||
* This member indicates if this particular PHY has received a BCN while
|
||||
* it had no port assignement. This BCN will be reported once the phy is
|
||||
* assigned to a port.
|
||||
*/
|
||||
bool bcn_received_while_port_unassigned;
|
||||
|
||||
/**
|
||||
* This field indicates if this PHY is currently in the process of
|
||||
* link training (i.e. it has started OOB, but has yet to perform
|
||||
* IAF exchange/Signature FIS reception).
|
||||
*/
|
||||
bool is_in_link_training;
|
||||
|
||||
union {
|
||||
struct {
|
||||
struct sci_sas_identify_address_frame identify_address_frame_buffer;
|
||||
|
||||
} sas;
|
||||
|
||||
struct {
|
||||
struct sata_fis_reg_d2h signature_fis_buffer;
|
||||
|
||||
} sata;
|
||||
|
||||
} phy_type;
|
||||
|
||||
/**
|
||||
* This field contains a reference to the timer utilized in detecting
|
||||
* when a signature FIS timeout has occurred. The signature FIS is the
|
||||
* first FIS sent by an attached SATA device after OOB/SN.
|
||||
*/
|
||||
void *sata_timeout_timer;
|
||||
|
||||
struct scic_sds_phy_state_handler *state_handlers;
|
||||
|
||||
struct sci_base_state_machine starting_substate_machine;
|
||||
|
||||
#ifdef SCIC_DEBUG_ENABLED
|
||||
struct scic_sds_phy_state_record state_record;
|
||||
#endif /* SCIC_DEBUG_ENABLED */
|
||||
|
||||
/**
|
||||
* This field points to the link layer register set within the SCU.
|
||||
*/
|
||||
struct scu_link_layer_registers *link_layer_registers;
|
||||
|
||||
};
|
||||
|
||||
|
||||
typedef enum sci_status (*SCIC_SDS_PHY_EVENT_HANDLER_T)(struct scic_sds_phy *, u32);
|
||||
typedef enum sci_status (*SCIC_SDS_PHY_FRAME_HANDLER_T)(struct scic_sds_phy *, u32);
|
||||
typedef enum sci_status (*SCIC_SDS_PHY_POWER_HANDLER_T)(struct scic_sds_phy *);
|
||||
|
||||
/**
|
||||
* struct scic_sds_phy_state_handler -
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_sds_phy_state_handler {
|
||||
/**
|
||||
* This is the struct sci_base_phy object state handlers.
|
||||
*/
|
||||
struct sci_base_phy_state_handler parent;
|
||||
|
||||
/**
|
||||
* The state handler for unsolicited frames received from the SCU hardware.
|
||||
*/
|
||||
SCIC_SDS_PHY_FRAME_HANDLER_T frame_handler;
|
||||
|
||||
/**
|
||||
* The state handler for events received from the SCU hardware.
|
||||
*/
|
||||
SCIC_SDS_PHY_EVENT_HANDLER_T event_handler;
|
||||
|
||||
/**
|
||||
* The state handler for staggered spinup.
|
||||
*/
|
||||
SCIC_SDS_PHY_POWER_HANDLER_T consume_power_handler;
|
||||
|
||||
};
|
||||
|
||||
extern struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[];
|
||||
extern const struct sci_base_state scic_sds_phy_state_table[];
|
||||
extern const struct sci_base_state scic_sds_phy_starting_substates[];
|
||||
extern struct scic_sds_phy_state_handler
|
||||
scic_sds_phy_starting_substate_handler_table[];
|
||||
|
||||
|
||||
/**
|
||||
* scic_sds_phy_get_index() -
|
||||
*
|
||||
* This macro returns the phy index for the specified phy
|
||||
*/
|
||||
#define scic_sds_phy_get_index(phy) \
|
||||
((phy)->phy_index)
|
||||
|
||||
/**
|
||||
* scic_sds_phy_get_controller() - This macro returns the controller for this
|
||||
* phy
|
||||
*
|
||||
*
|
||||
*/
|
||||
#define scic_sds_phy_get_controller(phy) \
|
||||
(scic_sds_port_get_controller((phy)->owning_port))
|
||||
|
||||
/**
|
||||
* scic_sds_phy_get_base_state_machine() - This macro returns the state machine
|
||||
* for the base phy
|
||||
*
|
||||
*
|
||||
*/
|
||||
#define scic_sds_phy_get_base_state_machine(phy) \
|
||||
(&(phy)->parent.state_machine)
|
||||
|
||||
/**
|
||||
* scic_sds_phy_get_starting_substate_machine() - This macro returns the
|
||||
* starting substate machine for this phy
|
||||
*
|
||||
*
|
||||
*/
|
||||
#define scic_sds_phy_get_starting_substate_machine(phy) \
|
||||
(&(phy)->starting_substate_machine)
|
||||
|
||||
/**
|
||||
* scic_sds_phy_set_state_handlers() - This macro sets the state handlers for
|
||||
* this phy object
|
||||
*
|
||||
*
|
||||
*/
|
||||
#define scic_sds_phy_set_state_handlers(phy, handlers) \
|
||||
((phy)->state_handlers = (handlers))
|
||||
|
||||
/**
|
||||
* scic_sds_phy_set_base_state_handlers() -
|
||||
*
|
||||
* This macro set the base state handlers for the phy object.
|
||||
*/
|
||||
#define scic_sds_phy_set_base_state_handlers(phy, state_id) \
|
||||
scic_sds_phy_set_state_handlers(\
|
||||
(phy), \
|
||||
&scic_sds_phy_state_handler_table[(state_id)] \
|
||||
)
|
||||
|
||||
/**
|
||||
* scic_sds_phy_is_ready() -
|
||||
*
|
||||
* This macro returns true if the current base state for this phy is
|
||||
* SCI_BASE_PHY_STATE_READY
|
||||
*/
|
||||
#define scic_sds_phy_is_ready(phy) \
|
||||
(\
|
||||
SCI_BASE_PHY_STATE_READY \
|
||||
== sci_base_state_machine_get_state(\
|
||||
scic_sds_phy_get_base_state_machine(phy) \
|
||||
) \
|
||||
)
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
void scic_sds_phy_construct(
|
||||
struct scic_sds_phy *this_phy,
|
||||
struct scic_sds_port *owning_port,
|
||||
u8 phy_index);
|
||||
|
||||
struct scic_sds_port *scic_sds_phy_get_port(
|
||||
struct scic_sds_phy *this_phy);
|
||||
|
||||
void scic_sds_phy_set_port(
|
||||
struct scic_sds_phy *this_phy,
|
||||
struct scic_sds_port *owning_port);
|
||||
|
||||
enum sci_status scic_sds_phy_initialize(
|
||||
struct scic_sds_phy *this_phy,
|
||||
struct scu_link_layer_registers *link_layer_registers);
|
||||
|
||||
enum sci_status scic_sds_phy_start(
|
||||
struct scic_sds_phy *this_phy);
|
||||
|
||||
enum sci_status scic_sds_phy_stop(
|
||||
struct scic_sds_phy *this_phy);
|
||||
|
||||
enum sci_status scic_sds_phy_reset(
|
||||
struct scic_sds_phy *this_phy);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
void scic_sds_phy_suspend(
|
||||
struct scic_sds_phy *this_phy);
|
||||
|
||||
void scic_sds_phy_resume(
|
||||
struct scic_sds_phy *this_phy);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
enum sci_status scic_sds_phy_event_handler(
|
||||
struct scic_sds_phy *this_phy,
|
||||
u32 event_code);
|
||||
|
||||
enum sci_status scic_sds_phy_frame_handler(
|
||||
struct scic_sds_phy *this_phy,
|
||||
u32 frame_index);
|
||||
|
||||
enum sci_status scic_sds_phy_consume_power_handler(
|
||||
struct scic_sds_phy *this_phy);
|
||||
|
||||
void scic_sds_phy_get_sas_address(
|
||||
struct scic_sds_phy *this_phy,
|
||||
struct sci_sas_address *sas_address);
|
||||
|
||||
void scic_sds_phy_get_attached_sas_address(
|
||||
struct scic_sds_phy *this_phy,
|
||||
struct sci_sas_address *sas_address);
|
||||
|
||||
void scic_sds_phy_get_protocols(
|
||||
struct scic_sds_phy *this_phy,
|
||||
struct sci_sas_identify_address_frame_protocols *protocols);
|
||||
|
||||
void scic_sds_phy_get_attached_phy_protocols(
|
||||
struct scic_sds_phy *this_phy,
|
||||
struct sci_sas_identify_address_frame_protocols *protocols);
|
||||
|
||||
/*
|
||||
* ****************************************************************************-
|
||||
* * SCIC SDS PHY Handler Methods
|
||||
* ****************************************************************************- */
|
||||
|
||||
enum sci_status scic_sds_phy_default_start_handler(
|
||||
struct sci_base_phy *phy);
|
||||
|
||||
enum sci_status scic_sds_phy_default_stop_handler(
|
||||
struct sci_base_phy *phy);
|
||||
|
||||
enum sci_status scic_sds_phy_default_reset_handler(
|
||||
struct sci_base_phy *phy);
|
||||
|
||||
enum sci_status scic_sds_phy_default_destroy_handler(
|
||||
struct sci_base_phy *phy);
|
||||
|
||||
enum sci_status scic_sds_phy_default_frame_handler(
|
||||
struct scic_sds_phy *phy,
|
||||
u32 frame_index);
|
||||
|
||||
enum sci_status scic_sds_phy_default_event_handler(
|
||||
struct scic_sds_phy *phy,
|
||||
u32 evnet_code);
|
||||
|
||||
enum sci_status scic_sds_phy_default_consume_power_handler(
|
||||
struct scic_sds_phy *phy);
|
||||
|
||||
#endif /* _SCIC_SDS_PHY_H_ */
|
||||
187
drivers/scsi/isci/core/scic_sds_phy_registers.h
Normal file
187
drivers/scsi/isci/core/scic_sds_phy_registers.h
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_PHY_REGISTERS_H_
|
||||
#define _SCIC_SDS_PHY_REGISTERS_H_
|
||||
|
||||
/**
|
||||
* This file contains the macros used by the phy object to read/write to the
|
||||
* SCU link layer registers.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "scic_sds_controller.h"
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * SCU LINK LAYER REGISTER OPERATIONS
|
||||
* ***************************************************************************** */
|
||||
|
||||
/**
|
||||
* scu_link_layer_register_read() -
|
||||
*
|
||||
* THis macro requests the SCU register write for the specified link layer
|
||||
* register.
|
||||
*/
|
||||
#define scu_link_layer_register_read(phy, reg) \
|
||||
scu_register_read(\
|
||||
scic_sds_phy_get_controller(phy), \
|
||||
(phy)->link_layer_registers->reg \
|
||||
)
|
||||
|
||||
/**
|
||||
* scu_link_layer_register_write() -
|
||||
*
|
||||
* This macro requests the SCU register read for the specified link layer
|
||||
* register.
|
||||
*/
|
||||
#define scu_link_layer_register_write(phy, reg, value) \
|
||||
scu_register_write(\
|
||||
scic_sds_phy_get_controller(phy), \
|
||||
(phy)->link_layer_registers->reg, \
|
||||
(value) \
|
||||
)
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * SCU LINK LAYER REGISTERS
|
||||
* ***************************************************************************** */
|
||||
|
||||
/* / This macro reads from the SAS Identify Frame PHY Identifier register */
|
||||
#define SCU_SAS_TIPID_READ(phy) \
|
||||
scu_link_layer_register_read(phy, identify_frame_phy_id)
|
||||
|
||||
/* / This macro writes to the SAS Identify Frame PHY Identifier register */
|
||||
#define SCU_SAS_TIPID_WRITE(phy, value) \
|
||||
scu_link_layer_register_write(phy, identify_frame_phy_id, value)
|
||||
|
||||
/* / This macro reads from the SAS Identification register */
|
||||
#define SCU_SAS_TIID_READ(phy) \
|
||||
scu_link_layer_register_read(phy, transmit_identification)
|
||||
|
||||
/* / This macro writes to the SAS Identification register */
|
||||
#define SCU_SAS_TIID_WRITE(phy, value) \
|
||||
scu_link_layer_register_write(phy, transmit_identification, value)
|
||||
|
||||
/* / This macro reads the SAS Device Name High register */
|
||||
#define SCU_SAS_TIDNH_READ(phy) \
|
||||
scu_link_layer_register_read(phy, sas_device_name_high)
|
||||
|
||||
/* / This macro writes the SAS Device Name High register */
|
||||
#define SCU_SAS_TIDNH_WRITE(phy, value) \
|
||||
scu_link_layer_register_write(phy, sas_device_name_high, value)
|
||||
|
||||
/* / This macro reads the SAS Device Name Low register */
|
||||
#define SCU_SAS_TIDNL_READ(phy) \
|
||||
scu_link_layer_register_read(phy, sas_device_name_low)
|
||||
|
||||
/* / This macro writes the SAS Device Name Low register */
|
||||
#define SCU_SAS_TIDNL_WRITE(phy, value) \
|
||||
scu_link_layer_register_write(phy, sas_device_name_low, value)
|
||||
|
||||
/* / This macro reads the Source SAS Address High register */
|
||||
#define SCU_SAS_TISSAH_READ(phy) \
|
||||
scu_link_layer_register_read(phy, source_sas_address_high)
|
||||
|
||||
/* / This macro writes the Source SAS Address High register */
|
||||
#define SCU_SAS_TISSAH_WRITE(phy, value) \
|
||||
scu_link_layer_register_write(phy, source_sas_address_high, value)
|
||||
|
||||
/* / This macro reads the Source SAS Address Low register */
|
||||
#define SCU_SAS_TISSAL_READ(phy) \
|
||||
scu_link_layer_register_read(phy, source_sas_address_low)
|
||||
|
||||
/* / This macro writes the Source SAS Address Low register */
|
||||
#define SCU_SAS_TISSAL_WRITE(phy, value) \
|
||||
scu_link_layer_register_write(phy, source_sas_address_low, value)
|
||||
|
||||
/* / This macro reads the PHY Configuration register */
|
||||
#define SCU_SAS_PCFG_READ(phy) \
|
||||
scu_link_layer_register_read(phy, phy_configuration);
|
||||
|
||||
/* / This macro writes the PHY Configuration register */
|
||||
#define SCU_SAS_PCFG_WRITE(phy, value) \
|
||||
scu_link_layer_register_write(phy, phy_configuration, value)
|
||||
|
||||
/* / This macro reads the PHY Enable Spinup register */
|
||||
#define SCU_SAS_ENSPINUP_READ(phy) \
|
||||
scu_link_layer_register_read(phy, notify_enable_spinup_control)
|
||||
|
||||
/* / This macro writes the PHY Enable Spinup register */
|
||||
#define SCU_SAS_ENSPINUP_WRITE(phy, value) \
|
||||
scu_link_layer_register_write(phy, notify_enable_spinup_control, value)
|
||||
|
||||
/* / This macro reads the PHY Capacity register */
|
||||
#define SCU_SAS_PHYCAP_READ(phy) \
|
||||
scu_link_layer_register_read(phy, phy_capabilities)
|
||||
|
||||
/* / This macro writes the PHY Capacity register */
|
||||
#define SCU_SAS_PHYCAP_WRITE(phy, value) \
|
||||
scu_link_layer_register_write(phy, phy_capabilities, value)
|
||||
|
||||
/* / This macro reads the Recieved PHY Capacity register */
|
||||
#define SCU_SAS_RECPHYCAP_READ(phy) \
|
||||
scu_link_layer_register_read(phy, receive_phycap)
|
||||
|
||||
/* / This macro reads the link layer control register */
|
||||
#define SCU_SAS_LLCTL_READ(phy) \
|
||||
scu_link_layer_register_read(phy, link_layer_control);
|
||||
|
||||
/* / This macro writes the link layer control register */
|
||||
#define SCU_SAS_LLCTL_WRITE(phy, value) \
|
||||
scu_link_layer_register_write(phy, link_layer_control, value);
|
||||
|
||||
#endif /* _SCIC_SDS_PHY_REGISTERS_H_ */
|
||||
2757
drivers/scsi/isci/core/scic_sds_port.c
Normal file
2757
drivers/scsi/isci/core/scic_sds_port.c
Normal file
File diff suppressed because it is too large
Load Diff
514
drivers/scsi/isci/core/scic_sds_port.h
Normal file
514
drivers/scsi/isci/core/scic_sds_port.h
Normal file
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_PORT_H_
|
||||
#define _SCIC_SDS_PORT_H_
|
||||
|
||||
/**
|
||||
* This file contains the structures, constants and prototypes for the
|
||||
* struct scic_sds_port object.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci_controller_constants.h"
|
||||
#include "intel_sas.h"
|
||||
#include "sci_base_port.h"
|
||||
#include "sci_base_phy.h"
|
||||
#include "scu_registers.h"
|
||||
|
||||
#define SCIC_SDS_DUMMY_PORT 0xFF
|
||||
|
||||
/**
|
||||
* enum SCIC_SDS_PORT_READY_SUBSTATES -
|
||||
*
|
||||
* This enumeration depicts all of the states for the core port ready substate
|
||||
* machine.
|
||||
*/
|
||||
enum SCIC_SDS_PORT_READY_SUBSTATES {
|
||||
/**
|
||||
* The substate where the port is started and ready but has no active phys.
|
||||
*/
|
||||
SCIC_SDS_PORT_READY_SUBSTATE_WAITING,
|
||||
|
||||
/**
|
||||
* The substate where the port is started and ready and there is at least one
|
||||
* phy operational.
|
||||
*/
|
||||
SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL,
|
||||
|
||||
/**
|
||||
* The substate where the port is started and there was an add/remove phy
|
||||
* event. This state is only used in Automatic Port Configuration Mode (APC)
|
||||
*/
|
||||
SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING,
|
||||
|
||||
SCIC_SDS_PORT_READY_MAX_SUBSTATES
|
||||
};
|
||||
|
||||
struct scic_sds_controller;
|
||||
struct scic_sds_phy;
|
||||
struct scic_sds_remote_device;
|
||||
struct scic_sds_request;
|
||||
|
||||
/**
|
||||
* struct scic_sds_port -
|
||||
*
|
||||
* The core port object provides the the abstraction for an SCU port.
|
||||
*/
|
||||
struct scic_sds_port {
|
||||
/**
|
||||
* This field is the oommon base port object.
|
||||
*/
|
||||
struct sci_base_port parent;
|
||||
|
||||
/**
|
||||
* This field is the port index that is reported to the SCI USER. This allows
|
||||
* the actual hardware physical port to change without the SCI USER getting a
|
||||
* different answer for the get port index.
|
||||
*/
|
||||
u8 logical_port_index;
|
||||
|
||||
/**
|
||||
* This field is the port index used to program the SCU hardware.
|
||||
*/
|
||||
u8 physical_port_index;
|
||||
|
||||
/**
|
||||
* This field contains the active phy mask for the port. This mask is used in
|
||||
* conjunction with the phy state to determine which phy to select for some
|
||||
* port operations.
|
||||
*/
|
||||
u8 active_phy_mask;
|
||||
|
||||
/**
|
||||
* This field contains the count of the io requests started on this port
|
||||
* object. It is used to control controller shutdown.
|
||||
*/
|
||||
u32 started_request_count;
|
||||
|
||||
/**
|
||||
* This field contains the number of devices assigned to this port. It is
|
||||
* used to control port start requests.
|
||||
*/
|
||||
u32 assigned_device_count;
|
||||
|
||||
/**
|
||||
* This field contains the reason for the port not going ready. It is
|
||||
* assigned in the state handlers and used in the state transition.
|
||||
*/
|
||||
u32 not_ready_reason;
|
||||
|
||||
/**
|
||||
* This field is the table of phys assigned to the port.
|
||||
*/
|
||||
struct scic_sds_phy *phy_table[SCI_MAX_PHYS];
|
||||
|
||||
/**
|
||||
* This field is a pointer back to the controller that owns this port object.
|
||||
*/
|
||||
struct scic_sds_controller *owning_controller;
|
||||
|
||||
/**
|
||||
* This field contains the port start/stop timer handle.
|
||||
*/
|
||||
void *timer_handle;
|
||||
|
||||
/**
|
||||
* This field points to the current set of state handlers for this port
|
||||
* object. These state handlers are assigned at each enter state of the state
|
||||
* machine.
|
||||
*/
|
||||
struct scic_sds_port_state_handler *state_handlers;
|
||||
|
||||
/**
|
||||
* This field is the ready substate machine for the port.
|
||||
*/
|
||||
struct sci_base_state_machine ready_substate_machine;
|
||||
|
||||
/* / Memory mapped hardware register space */
|
||||
/**
|
||||
* This field is the pointer to the transport layer register for the SCU
|
||||
* hardware.
|
||||
*/
|
||||
struct scu_transport_layer_registers *transport_layer_registers;
|
||||
|
||||
/**
|
||||
* This field is the pointer to the port task scheduler registers for the SCU
|
||||
* hardware.
|
||||
*/
|
||||
struct scu_port_task_scheduler_registers *port_task_scheduler_registers;
|
||||
|
||||
/**
|
||||
* This field is identical for all port objects and points to the port task
|
||||
* scheduler group PE configuration registers. It is used to assign PEs to a
|
||||
* port.
|
||||
*/
|
||||
SCU_PORT_PE_CONFIGURATION_REGISTER_T *port_pe_configuration_register;
|
||||
|
||||
/**
|
||||
* This field is the VIIT register space for ths port object.
|
||||
*/
|
||||
struct scu_viit_entry *viit_registers;
|
||||
|
||||
};
|
||||
|
||||
|
||||
typedef enum sci_status (*SCIC_SDS_PORT_EVENT_HANDLER_T)(struct scic_sds_port *, u32);
|
||||
|
||||
typedef enum sci_status (*SCIC_SDS_PORT_FRAME_HANDLER_T)(struct scic_sds_port *, u32);
|
||||
|
||||
typedef void (*SCIC_SDS_PORT_LINK_HANDLER_T)(struct scic_sds_port *, struct scic_sds_phy *);
|
||||
|
||||
typedef enum sci_status (*SCIC_SDS_PORT_IO_REQUEST_HANDLER_T)(
|
||||
struct scic_sds_port *,
|
||||
struct scic_sds_remote_device *,
|
||||
struct scic_sds_request *);
|
||||
|
||||
struct scic_sds_port_state_handler {
|
||||
struct sci_base_port_state_handler parent;
|
||||
|
||||
SCIC_SDS_PORT_FRAME_HANDLER_T frame_handler;
|
||||
SCIC_SDS_PORT_EVENT_HANDLER_T event_handler;
|
||||
|
||||
SCIC_SDS_PORT_LINK_HANDLER_T link_up_handler;
|
||||
SCIC_SDS_PORT_LINK_HANDLER_T link_down_handler;
|
||||
|
||||
SCIC_SDS_PORT_IO_REQUEST_HANDLER_T start_io_handler;
|
||||
SCIC_SDS_PORT_IO_REQUEST_HANDLER_T complete_io_handler;
|
||||
|
||||
};
|
||||
|
||||
extern const struct sci_base_state scic_sds_port_state_table[];
|
||||
extern const struct sci_base_state scic_sds_port_ready_substate_table[];
|
||||
|
||||
extern struct scic_sds_port_state_handler scic_sds_port_state_handler_table[];
|
||||
extern struct scic_sds_port_state_handler scic_sds_port_ready_substate_handler_table[];
|
||||
|
||||
/**
|
||||
* scic_sds_port_get_controller() -
|
||||
*
|
||||
* Helper macro to get the owning controller of this port
|
||||
*/
|
||||
#define scic_sds_port_get_controller(this_port) \
|
||||
((this_port)->owning_controller)
|
||||
|
||||
/**
|
||||
* scic_sds_port_get_base_state_machine() -
|
||||
*
|
||||
* Helper macro to get the base state machine for this port
|
||||
*/
|
||||
#define scic_sds_port_get_base_state_machine(this_port) \
|
||||
(&(this_port)->parent.state_machine)
|
||||
|
||||
/**
|
||||
* scic_sds_port_set_base_state_handlers() -
|
||||
*
|
||||
* This macro will change the state handlers to those of the specified state id
|
||||
*/
|
||||
#define scic_sds_port_set_base_state_handlers(this_port, state_id) \
|
||||
scic_sds_port_set_state_handlers(\
|
||||
(this_port), &scic_sds_port_state_handler_table[(state_id)])
|
||||
|
||||
/**
|
||||
* scic_sds_port_get_ready_substate_machine() -
|
||||
*
|
||||
* Helper macro to get the ready substate machine for this port
|
||||
*/
|
||||
#define scic_sds_port_get_ready_substate_machine(this_port) \
|
||||
(&(this_port)->ready_substate_machine)
|
||||
|
||||
/**
|
||||
* scic_sds_port_set_state_handlers() -
|
||||
*
|
||||
* Helper macro to set the port object state handlers
|
||||
*/
|
||||
#define scic_sds_port_set_state_handlers(this_port, handlers) \
|
||||
((this_port)->state_handlers = (handlers))
|
||||
|
||||
/**
|
||||
* scic_sds_port_get_index() -
|
||||
*
|
||||
* This macro returns the physical port index for this port object
|
||||
*/
|
||||
#define scic_sds_port_get_index(this_port) \
|
||||
((this_port)->physical_port_index)
|
||||
|
||||
/**
|
||||
* scic_sds_port_increment_request_count() -
|
||||
*
|
||||
* Helper macro to increment the started request count
|
||||
*/
|
||||
#define scic_sds_port_increment_request_count(this_port) \
|
||||
((this_port)->started_request_count++)
|
||||
|
||||
#ifdef SCIC_DEBUG_ENABLED
|
||||
/**
|
||||
* scic_sds_port_decrement_request_count() - This method decrements the started
|
||||
* io request count. The method will not decrment the started io request
|
||||
* count below 0 and will log a debug message if this is attempted.
|
||||
*
|
||||
*
|
||||
*/
|
||||
void scic_sds_port_decrement_request_count(
|
||||
struct scic_sds_port *this_port);
|
||||
#else
|
||||
/**
|
||||
* scic_sds_port_decrement_request_count() -
|
||||
*
|
||||
* Helper macro to decrement the started io request count. The macro will not
|
||||
* decrement the started io request count below 0.
|
||||
*/
|
||||
#define scic_sds_port_decrement_request_count(this_port) \
|
||||
(\
|
||||
(this_port)->started_request_count = (\
|
||||
((this_port)->started_request_count == 0) ? \
|
||||
(this_port)->started_request_count : \
|
||||
((this_port)->started_request_count - 1) \
|
||||
) \
|
||||
)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* scic_sds_port_write_phy_assignment() -
|
||||
*
|
||||
* Helper macro to write the phys port assignment
|
||||
*/
|
||||
#define scic_sds_port_write_phy_assignment(port, phy) \
|
||||
SCU_PCSPExCR_WRITE(\
|
||||
(port), \
|
||||
(phy)->phy_index, \
|
||||
(port)->physical_port_index \
|
||||
)
|
||||
|
||||
/**
|
||||
* scic_sds_port_read_phy_assignment() -
|
||||
*
|
||||
* Helper macro to read the phys port assignment
|
||||
*/
|
||||
#define scic_sds_port_read_phy_assignment(port, phy) \
|
||||
SCU_PCSPExCR_READ(\
|
||||
(port), \
|
||||
(phy)->phy_index \
|
||||
)
|
||||
|
||||
#define scic_sds_port_active_phy(port, phy) \
|
||||
(((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0)
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
void scic_sds_port_construct(
|
||||
struct scic_sds_port *this_port,
|
||||
u8 port_index,
|
||||
struct scic_sds_controller *owning_controller);
|
||||
|
||||
enum sci_status scic_sds_port_initialize(
|
||||
struct scic_sds_port *this_port,
|
||||
void *transport_layer_registers,
|
||||
void *port_task_scheduler_registers,
|
||||
void *port_configuration_regsiter,
|
||||
void *viit_registers);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
enum sci_status scic_sds_port_add_phy(
|
||||
struct scic_sds_port *this_port,
|
||||
struct scic_sds_phy *the_phy);
|
||||
|
||||
enum sci_status scic_sds_port_remove_phy(
|
||||
struct scic_sds_port *this_port,
|
||||
struct scic_sds_phy *the_phy);
|
||||
|
||||
void scic_sds_port_set_direct_attached_device_id(
|
||||
struct scic_sds_port *this_port,
|
||||
u32 device_id);
|
||||
|
||||
void scic_sds_port_activate_phy(
|
||||
struct scic_sds_port *this_port,
|
||||
struct scic_sds_phy *phy,
|
||||
bool do_notify_user);
|
||||
|
||||
void scic_sds_port_deactivate_phy(
|
||||
struct scic_sds_port *this_port,
|
||||
struct scic_sds_phy *phy,
|
||||
bool do_notify_user);
|
||||
|
||||
|
||||
|
||||
void scic_sds_port_general_link_up_handler(
|
||||
struct scic_sds_port *this_port,
|
||||
struct scic_sds_phy *the_phy,
|
||||
bool do_notify_user);
|
||||
|
||||
bool scic_sds_port_link_detected(
|
||||
struct scic_sds_port *this_port,
|
||||
struct scic_sds_phy *phy);
|
||||
|
||||
void scic_sds_port_link_up(
|
||||
struct scic_sds_port *this_port,
|
||||
struct scic_sds_phy *phy);
|
||||
|
||||
void scic_sds_port_link_down(
|
||||
struct scic_sds_port *this_port,
|
||||
struct scic_sds_phy *phy);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
enum sci_status scic_sds_port_start_io(
|
||||
struct scic_sds_port *this_port,
|
||||
struct scic_sds_remote_device *the_device,
|
||||
struct scic_sds_request *the_io_request);
|
||||
|
||||
enum sci_status scic_sds_port_complete_io(
|
||||
struct scic_sds_port *this_port,
|
||||
struct scic_sds_remote_device *the_device,
|
||||
struct scic_sds_request *the_io_request);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
void scic_sds_port_update_viit_entry(
|
||||
struct scic_sds_port *this_port);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
enum sci_status scic_sds_port_default_start_handler(
|
||||
struct sci_base_port *port);
|
||||
|
||||
|
||||
enum sci_status scic_sds_port_default_destruct_handler(
|
||||
struct sci_base_port *port);
|
||||
|
||||
enum sci_status scic_sds_port_default_reset_handler(
|
||||
struct sci_base_port *port,
|
||||
u32 timeout);
|
||||
|
||||
|
||||
enum sci_status scic_sds_port_default_remove_phy_handler(
|
||||
struct sci_base_port *port,
|
||||
struct sci_base_phy *phy);
|
||||
|
||||
enum sci_status scic_sds_port_default_frame_handler(
|
||||
struct scic_sds_port *port,
|
||||
u32 frame_index);
|
||||
|
||||
enum sci_status scic_sds_port_default_event_handler(
|
||||
struct scic_sds_port *port,
|
||||
u32 event_code);
|
||||
|
||||
void scic_sds_port_default_link_up_handler(
|
||||
struct scic_sds_port *this_port,
|
||||
struct scic_sds_phy *phy);
|
||||
|
||||
void scic_sds_port_default_link_down_handler(
|
||||
struct scic_sds_port *this_port,
|
||||
struct scic_sds_phy *phy);
|
||||
|
||||
enum sci_status scic_sds_port_default_start_io_handler(
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_remote_device *device,
|
||||
struct scic_sds_request *io_request);
|
||||
|
||||
|
||||
enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed(
|
||||
struct scic_sds_port *this_port);
|
||||
|
||||
void scic_sds_port_broadcast_change_received(
|
||||
struct scic_sds_port *this_port,
|
||||
struct scic_sds_phy *this_phy);
|
||||
|
||||
bool scic_sds_port_is_valid_phy_assignment(
|
||||
struct scic_sds_port *this_port,
|
||||
u32 phy_index);
|
||||
|
||||
bool scic_sds_port_is_phy_mask_valid(
|
||||
struct scic_sds_port *this_port,
|
||||
u32 phy_mask);
|
||||
|
||||
u32 scic_sds_port_get_phys(
|
||||
struct scic_sds_port *this_port);
|
||||
|
||||
void scic_sds_port_get_sas_address(
|
||||
struct scic_sds_port *this_port,
|
||||
struct sci_sas_address *sas_address);
|
||||
|
||||
void scic_sds_port_get_attached_sas_address(
|
||||
struct scic_sds_port *this_port,
|
||||
struct sci_sas_address *sas_address);
|
||||
|
||||
void scic_sds_port_get_attached_protocols(
|
||||
struct scic_sds_port *this_port,
|
||||
struct sci_sas_identify_address_frame_protocols *protocols);
|
||||
|
||||
enum sci_status scic_sds_port_set_phy(
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy);
|
||||
|
||||
enum sci_status scic_sds_port_clear_phy(
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy);
|
||||
|
||||
|
||||
|
||||
#endif /* _SCIC_SDS_PORT_H_ */
|
||||
851
drivers/scsi/isci/core/scic_sds_port_configuration_agent.c
Normal file
851
drivers/scsi/isci/core/scic_sds_port_configuration_agent.c
Normal file
@@ -0,0 +1,851 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the implementation for the public and protected methods
|
||||
* for the port configuration agent.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci_environment.h"
|
||||
#include "scic_controller.h"
|
||||
#include "scic_sds_controller.h"
|
||||
#include "scic_sds_port_configuration_agent.h"
|
||||
|
||||
#define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10)
|
||||
#define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10)
|
||||
#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (100)
|
||||
|
||||
enum SCIC_SDS_APC_ACTIVITY {
|
||||
SCIC_SDS_APC_SKIP_PHY,
|
||||
SCIC_SDS_APC_ADD_PHY,
|
||||
SCIC_SDS_APC_START_TIMER,
|
||||
|
||||
SCIC_SDS_APC_ACTIVITY_MAX
|
||||
};
|
||||
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* General port configuration agent routines
|
||||
* ****************************************************************************** */
|
||||
|
||||
/**
|
||||
*
|
||||
* @address_one: A SAS Address to be compared.
|
||||
* @address_two: A SAS Address to be compared.
|
||||
*
|
||||
* Compare the two SAS Address and if SAS Address One is greater than SAS
|
||||
* Address Two then return > 0 else if SAS Address One is less than SAS Address
|
||||
* Two return < 0 Otherwise they are the same return 0 A signed value of x > 0
|
||||
* > y where x is returned for Address One > Address Two y is returned for
|
||||
* Address One < Address Two 0 is returned ofr Address One = Address Two
|
||||
*/
|
||||
static s32 sci_sas_address_compare(
|
||||
struct sci_sas_address address_one,
|
||||
struct sci_sas_address address_two)
|
||||
{
|
||||
if (address_one.high > address_two.high) {
|
||||
return 1;
|
||||
} else if (address_one.high < address_two.high) {
|
||||
return -1;
|
||||
} else if (address_one.low > address_two.low) {
|
||||
return 1;
|
||||
} else if (address_one.low < address_two.low) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The two SAS Address must be identical */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @controller: The controller object used for the port search.
|
||||
* @phy: The phy object to match.
|
||||
*
|
||||
* This routine will find a matching port for the phy. This means that the
|
||||
* port and phy both have the same broadcast sas address and same received sas
|
||||
* address. The port address or the SCI_INVALID_HANDLE if there is no matching
|
||||
* port. port address if the port can be found to match the phy.
|
||||
* SCI_INVALID_HANDLE if there is no matching port for the phy.
|
||||
*/
|
||||
static struct scic_sds_port *scic_sds_port_configuration_agent_find_port(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_phy *phy)
|
||||
{
|
||||
u8 port_index;
|
||||
struct scic_sds_port *port_handle;
|
||||
struct sci_sas_address port_sas_address;
|
||||
struct sci_sas_address port_attached_device_address;
|
||||
struct sci_sas_address phy_sas_address;
|
||||
struct sci_sas_address phy_attached_device_address;
|
||||
|
||||
/*
|
||||
* Since this phy can be a member of a wide port check to see if one or
|
||||
* more phys match the sent and received SAS address as this phy in which
|
||||
* case it should participate in the same port. */
|
||||
scic_sds_phy_get_sas_address(phy, &phy_sas_address);
|
||||
scic_sds_phy_get_attached_sas_address(phy, &phy_attached_device_address);
|
||||
|
||||
for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) {
|
||||
if (scic_controller_get_port_handle(controller, port_index, &port_handle) == SCI_SUCCESS) {
|
||||
struct scic_sds_port *port = (struct scic_sds_port *)port_handle;
|
||||
|
||||
scic_sds_port_get_sas_address(port, &port_sas_address);
|
||||
scic_sds_port_get_attached_sas_address(port, &port_attached_device_address);
|
||||
|
||||
if (
|
||||
(sci_sas_address_compare(port_sas_address, phy_sas_address) == 0)
|
||||
&& (sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0)
|
||||
) {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SCI_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @controller: This is the controller object that contains the port agent
|
||||
* @port_agent: This is the port configruation agent for the controller.
|
||||
*
|
||||
* This routine will validate the port configuration is correct for the SCU
|
||||
* hardware. The SCU hardware allows for port configurations as follows. LP0
|
||||
* -> (PE0), (PE0, PE1), (PE0, PE1, PE2, PE3) LP1 -> (PE1) LP2 -> (PE2), (PE2,
|
||||
* PE3) LP3 -> (PE3) enum sci_status SCI_SUCCESS the port configuration is valid for
|
||||
* this port configuration agent. SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION
|
||||
* the port configuration is not valid for this port configuration agent.
|
||||
*/
|
||||
static enum sci_status scic_sds_port_configuration_agent_validate_ports(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port_configuration_agent *port_agent)
|
||||
{
|
||||
struct sci_sas_address first_address;
|
||||
struct sci_sas_address second_address;
|
||||
|
||||
/*
|
||||
* Sanity check the max ranges for all the phys the max index
|
||||
* is always equal to the port range index */
|
||||
if (
|
||||
(port_agent->phy_valid_port_range[0].max_index != 0)
|
||||
|| (port_agent->phy_valid_port_range[1].max_index != 1)
|
||||
|| (port_agent->phy_valid_port_range[2].max_index != 2)
|
||||
|| (port_agent->phy_valid_port_range[3].max_index != 3)
|
||||
) {
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a request to configure a single x4 port or at least attempt
|
||||
* to make all the phys into a single port */
|
||||
if (
|
||||
(port_agent->phy_valid_port_range[0].min_index == 0)
|
||||
&& (port_agent->phy_valid_port_range[1].min_index == 0)
|
||||
&& (port_agent->phy_valid_port_range[2].min_index == 0)
|
||||
&& (port_agent->phy_valid_port_range[3].min_index == 0)
|
||||
) {
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a degenerate case where phy 1 and phy 2 are assigned
|
||||
* to the same port this is explicitly disallowed by the hardware
|
||||
* unless they are part of the same x4 port and this condition was
|
||||
* already checked above. */
|
||||
if (port_agent->phy_valid_port_range[2].min_index == 1) {
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
|
||||
/*
|
||||
* PE0 and PE3 can never have the same SAS Address unless they
|
||||
* are part of the same x4 wide port and we have already checked
|
||||
* for this condition. */
|
||||
scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address);
|
||||
scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address);
|
||||
|
||||
if (sci_sas_address_compare(first_address, second_address) == 0) {
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
|
||||
/*
|
||||
* PE0 and PE1 are configured into a 2x1 ports make sure that the
|
||||
* SAS Address for PE0 and PE2 are different since they can not be
|
||||
* part of the same port. */
|
||||
if (
|
||||
(port_agent->phy_valid_port_range[0].min_index == 0)
|
||||
&& (port_agent->phy_valid_port_range[1].min_index == 1)
|
||||
) {
|
||||
scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address);
|
||||
scic_sds_phy_get_sas_address(&controller->phy_table[2], &second_address);
|
||||
|
||||
if (sci_sas_address_compare(first_address, second_address) == 0) {
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* PE2 and PE3 are configured into a 2x1 ports make sure that the
|
||||
* SAS Address for PE1 and PE3 are different since they can not be
|
||||
* part of the same port. */
|
||||
if (
|
||||
(port_agent->phy_valid_port_range[2].min_index == 2)
|
||||
&& (port_agent->phy_valid_port_range[3].min_index == 3)
|
||||
) {
|
||||
scic_sds_phy_get_sas_address(&controller->phy_table[1], &first_address);
|
||||
scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address);
|
||||
|
||||
if (sci_sas_address_compare(first_address, second_address) == 0) {
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
}
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* Manual port configuration agent routines
|
||||
* ****************************************************************************** */
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This routine will verify that all of the phys in the same port are using the
|
||||
* same SAS address.
|
||||
*/
|
||||
static enum sci_status scic_sds_mpc_agent_validate_phy_configuration(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port_configuration_agent *port_agent)
|
||||
{
|
||||
u32 phy_mask;
|
||||
u32 assigned_phy_mask;
|
||||
struct sci_sas_address sas_address;
|
||||
struct sci_sas_address phy_assigned_address;
|
||||
u8 port_index;
|
||||
u8 phy_index;
|
||||
|
||||
assigned_phy_mask = 0;
|
||||
sas_address.high = 0;
|
||||
sas_address.low = 0;
|
||||
|
||||
for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) {
|
||||
phy_mask = controller->oem_parameters.sds1.ports[port_index].phy_mask;
|
||||
|
||||
if (phy_mask != 0) {
|
||||
/*
|
||||
* Make sure that one or more of the phys were not already assinged to
|
||||
* a different port. */
|
||||
if ((phy_mask & ~assigned_phy_mask) == 0) {
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
|
||||
/* Find the starting phy index for this round through the loop */
|
||||
for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) {
|
||||
if ((1 << phy_index) & phy_mask) {
|
||||
scic_sds_phy_get_sas_address(
|
||||
&controller->phy_table[phy_index], &sas_address
|
||||
);
|
||||
|
||||
/*
|
||||
* The phy_index can be used as the starting point for the
|
||||
* port range since the hardware starts all logical ports
|
||||
* the same as the PE index. */
|
||||
port_agent->phy_valid_port_range[phy_index].min_index = port_index;
|
||||
port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
|
||||
|
||||
if (phy_index != port_index) {
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* See how many additional phys are being added to this logical port.
|
||||
* Note: We have not moved the current phy_index so we will actually
|
||||
* compare the startting phy with itself.
|
||||
* This is expected and required to add the phy to the port. */
|
||||
while (phy_index < SCI_MAX_PHYS) {
|
||||
if ((1 << phy_index) & phy_mask) {
|
||||
scic_sds_phy_get_sas_address(
|
||||
&controller->phy_table[phy_index], &phy_assigned_address
|
||||
);
|
||||
|
||||
if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) {
|
||||
/*
|
||||
* The phy mask specified that this phy is part of the same port
|
||||
* as the starting phy and it is not so fail this configuration */
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
|
||||
port_agent->phy_valid_port_range[phy_index].min_index = port_index;
|
||||
port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
|
||||
|
||||
scic_sds_port_add_phy(
|
||||
&controller->port_table[port_index],
|
||||
&controller->phy_table[phy_index]
|
||||
);
|
||||
|
||||
assigned_phy_mask |= (1 << phy_index);
|
||||
}
|
||||
|
||||
phy_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return scic_sds_port_configuration_agent_validate_ports(controller, port_agent);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This timer routine is used to allow the SCI User to rediscover or change
|
||||
* device objects before a new series of link up notifications because a link
|
||||
* down has allowed a better port configuration.
|
||||
*/
|
||||
static void scic_sds_mpc_agent_timeout_handler(
|
||||
void *object)
|
||||
{
|
||||
u8 index;
|
||||
struct scic_sds_controller *controller = (struct scic_sds_controller *)object;
|
||||
struct scic_sds_port_configuration_agent *port_agent = &controller->port_agent;
|
||||
u16 configure_phy_mask;
|
||||
|
||||
port_agent->timer_pending = false;
|
||||
|
||||
/* Find the mask of phys that are reported read but as yet unconfigured into a port */
|
||||
configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
|
||||
|
||||
for (index = 0; index < SCI_MAX_PHYS; index++) {
|
||||
if (configure_phy_mask & (1 << index)) {
|
||||
port_agent->link_up_handler(
|
||||
controller,
|
||||
port_agent,
|
||||
scic_sds_phy_get_port(&controller->phy_table[index]),
|
||||
&controller->phy_table[index]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @controller: This is the controller object that receives the link up
|
||||
* notification.
|
||||
* @port: This is the port object associated with the phy. If the is no
|
||||
* associated port this is an SCI_INVALID_HANDLE.
|
||||
* @phy: This is the phy object which has gone ready.
|
||||
*
|
||||
* This method handles the manual port configuration link up notifications.
|
||||
* Since all ports and phys are associate at initialization time we just turn
|
||||
* around and notifiy the port object that there is a link up. If this PHY is
|
||||
* not associated with a port there is no action taken. Is it possible to get a
|
||||
* link up notification from a phy that has no assocoated port?
|
||||
*/
|
||||
static void scic_sds_mpc_agent_link_up(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port_configuration_agent *port_agent,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy)
|
||||
{
|
||||
/*
|
||||
* If the port has an invalid handle then the phy was not assigned to
|
||||
* a port. This is because the phy was not given the same SAS Address
|
||||
* as the other PHYs in the port. */
|
||||
if (port != SCI_INVALID_HANDLE) {
|
||||
port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy));
|
||||
|
||||
scic_sds_port_link_up(port, phy);
|
||||
|
||||
if ((port->active_phy_mask & (1 << scic_sds_phy_get_index(phy))) != 0) {
|
||||
port_agent->phy_configured_mask |= (1 << scic_sds_phy_get_index(phy));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @controller: This is the controller object that receives the link down
|
||||
* notification.
|
||||
* @port: This is the port object associated with the phy. If the is no
|
||||
* associated port this is an SCI_INVALID_HANDLE. The port is an invalid
|
||||
* handle only if the phy was never port of this port. This happens when
|
||||
* the phy is not broadcasting the same SAS address as the other phys in the
|
||||
* assigned port.
|
||||
* @phy: This is the phy object which has gone link down.
|
||||
*
|
||||
* This method handles the manual port configuration link down notifications.
|
||||
* Since all ports and phys are associated at initialization time we just turn
|
||||
* around and notifiy the port object of the link down event. If this PHY is
|
||||
* not associated with a port there is no action taken. Is it possible to get a
|
||||
* link down notification from a phy that has no assocoated port?
|
||||
*/
|
||||
static void scic_sds_mpc_agent_link_down(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port_configuration_agent *port_agent,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy)
|
||||
{
|
||||
if (port != SCI_INVALID_HANDLE) {
|
||||
/*
|
||||
* If we can form a new port from the remainder of the phys then we want
|
||||
* to start the timer to allow the SCI User to cleanup old devices and
|
||||
* rediscover the port before rebuilding the port with the phys that
|
||||
* remain in the ready state. */
|
||||
port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy));
|
||||
port_agent->phy_configured_mask &= ~(1 << scic_sds_phy_get_index(phy));
|
||||
|
||||
/*
|
||||
* Check to see if there are more phys waiting to be configured into a port.
|
||||
* If there are allow the SCI User to tear down this port, if necessary, and
|
||||
* then reconstruc the port after the timeout. */
|
||||
if (
|
||||
(port_agent->phy_configured_mask == 0x0000)
|
||||
&& (port_agent->phy_ready_mask != 0x0000)
|
||||
&& !port_agent->timer_pending
|
||||
) {
|
||||
port_agent->timer_pending = true;
|
||||
|
||||
scic_cb_timer_start(
|
||||
controller,
|
||||
port_agent->timer,
|
||||
SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT
|
||||
);
|
||||
}
|
||||
|
||||
scic_sds_port_link_down(port, phy);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* Automatic port configuration agent routines
|
||||
* ****************************************************************************** */
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This routine will verify that the phys are assigned a valid SAS address for
|
||||
* automatic port configuration mode.
|
||||
*/
|
||||
static enum sci_status scic_sds_apc_agent_validate_phy_configuration(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port_configuration_agent *port_agent)
|
||||
{
|
||||
u8 phy_index;
|
||||
u8 port_index;
|
||||
struct sci_sas_address sas_address;
|
||||
struct sci_sas_address phy_assigned_address;
|
||||
|
||||
phy_index = 0;
|
||||
|
||||
while (phy_index < SCI_MAX_PHYS) {
|
||||
port_index = phy_index;
|
||||
|
||||
/* Get the assigned SAS Address for the first PHY on the controller. */
|
||||
scic_sds_phy_get_sas_address(
|
||||
&controller->phy_table[phy_index], &sas_address
|
||||
);
|
||||
|
||||
while (++phy_index < SCI_MAX_PHYS) {
|
||||
scic_sds_phy_get_sas_address(
|
||||
&controller->phy_table[phy_index], &phy_assigned_address
|
||||
);
|
||||
|
||||
/* Verify each of the SAS address are all the same for every PHY */
|
||||
if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0) {
|
||||
port_agent->phy_valid_port_range[phy_index].min_index = port_index;
|
||||
port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
|
||||
} else {
|
||||
port_agent->phy_valid_port_range[phy_index].min_index = phy_index;
|
||||
port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return scic_sds_port_configuration_agent_validate_ports(controller, port_agent);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @controller: This is the controller that to which the port agent is assigned.
|
||||
* @port_agent: This is the port agent that is requesting the timer start
|
||||
* operation.
|
||||
* @phy: This is the phy that has caused the timer operation to be scheduled.
|
||||
*
|
||||
* This routine will restart the automatic port configuration timeout timer for
|
||||
* the next time period. This could be caused by either a link down event or a
|
||||
* link up event where we can not yet tell to which port a phy belongs.
|
||||
*/
|
||||
static void scic_sds_apc_agent_start_timer(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port_configuration_agent *port_agent,
|
||||
struct scic_sds_phy *phy,
|
||||
u32 timeout)
|
||||
{
|
||||
if (port_agent->timer_pending) {
|
||||
scic_cb_timer_stop(controller, port_agent->timer);
|
||||
}
|
||||
|
||||
port_agent->timer_pending = true;
|
||||
|
||||
scic_cb_timer_start(controller, port_agent->timer, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @controller: This is the controller object that receives the link up
|
||||
* notification.
|
||||
* @phy: This is the phy object which has gone link up.
|
||||
*
|
||||
* This method handles the automatic port configuration for link up
|
||||
* notifications.
|
||||
*/
|
||||
static void scic_sds_apc_agent_configure_ports(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port_configuration_agent *port_agent,
|
||||
struct scic_sds_phy *phy,
|
||||
bool start_timer)
|
||||
{
|
||||
u8 port_index;
|
||||
enum sci_status status;
|
||||
struct scic_sds_port *port;
|
||||
struct scic_sds_port *port_handle;
|
||||
enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY;
|
||||
|
||||
port = scic_sds_port_configuration_agent_find_port(controller, phy);
|
||||
|
||||
if (port != SCI_INVALID_HANDLE) {
|
||||
if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index))
|
||||
apc_activity = SCIC_SDS_APC_ADD_PHY;
|
||||
else
|
||||
apc_activity = SCIC_SDS_APC_SKIP_PHY;
|
||||
} else {
|
||||
/*
|
||||
* There is no matching Port for this PHY so lets search through the
|
||||
* Ports and see if we can add the PHY to its own port or maybe start
|
||||
* the timer and wait to see if a wider port can be made.
|
||||
*
|
||||
* Note the break when we reach the condition of the port id == phy id */
|
||||
for (
|
||||
port_index = port_agent->phy_valid_port_range[phy->phy_index].min_index;
|
||||
port_index <= port_agent->phy_valid_port_range[phy->phy_index].max_index;
|
||||
port_index++
|
||||
) {
|
||||
scic_controller_get_port_handle(controller, port_index, &port_handle);
|
||||
|
||||
port = (struct scic_sds_port *)port_handle;
|
||||
|
||||
/* First we must make sure that this PHY can be added to this Port. */
|
||||
if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) {
|
||||
/*
|
||||
* Port contains a PHY with a greater PHY ID than the current
|
||||
* PHY that has gone link up. This phy can not be part of any
|
||||
* port so skip it and move on. */
|
||||
if (port->active_phy_mask > (1 << phy->phy_index)) {
|
||||
apc_activity = SCIC_SDS_APC_SKIP_PHY;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have reached the end of our Port list and have not found
|
||||
* any reason why we should not either add the PHY to the port
|
||||
* or wait for more phys to become active. */
|
||||
if (port->physical_port_index == phy->phy_index) {
|
||||
/*
|
||||
* The Port either has no active PHYs.
|
||||
* Consider that if the port had any active PHYs we would have
|
||||
* or active PHYs with
|
||||
* a lower PHY Id than this PHY. */
|
||||
if (apc_activity != SCIC_SDS_APC_START_TIMER) {
|
||||
apc_activity = SCIC_SDS_APC_ADD_PHY;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The current Port has no active PHYs and this PHY could be part
|
||||
* of this Port. Since we dont know as yet setup to start the
|
||||
* timer and see if there is a better configuration. */
|
||||
if (port->active_phy_mask == 0) {
|
||||
apc_activity = SCIC_SDS_APC_START_TIMER;
|
||||
}
|
||||
} else if (port->active_phy_mask != 0) {
|
||||
/*
|
||||
* The Port has an active phy and the current Phy can not
|
||||
* participate in this port so skip the PHY and see if
|
||||
* there is a better configuration. */
|
||||
apc_activity = SCIC_SDS_APC_SKIP_PHY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the start timer operations should instead map to an
|
||||
* add phy operation. This is caused because we have been waiting to
|
||||
* add a phy to a port but could not becuase the automatic port
|
||||
* configuration engine had a choice of possible ports for the phy.
|
||||
* Since we have gone through a timeout we are going to restrict the
|
||||
* choice to the smallest possible port. */
|
||||
if (
|
||||
(start_timer == false)
|
||||
&& (apc_activity == SCIC_SDS_APC_START_TIMER)
|
||||
) {
|
||||
apc_activity = SCIC_SDS_APC_ADD_PHY;
|
||||
}
|
||||
|
||||
switch (apc_activity) {
|
||||
case SCIC_SDS_APC_ADD_PHY:
|
||||
status = scic_sds_port_add_phy(port, phy);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
port_agent->phy_configured_mask |= (1 << phy->phy_index);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCIC_SDS_APC_START_TIMER:
|
||||
scic_sds_apc_agent_start_timer(
|
||||
controller, port_agent, phy, SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION
|
||||
);
|
||||
break;
|
||||
|
||||
case SCIC_SDS_APC_SKIP_PHY:
|
||||
default:
|
||||
/* do nothing the PHY can not be made part of a port at this time. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @controller: This is the controller object that receives the link up
|
||||
* notification.
|
||||
* @port: This is the port object associated with the phy. If the is no
|
||||
* associated port this is an SCI_INVALID_HANDLE.
|
||||
* @phy: This is the phy object which has gone link up.
|
||||
*
|
||||
* This method handles the automatic port configuration for link up
|
||||
* notifications. Is it possible to get a link down notification from a phy
|
||||
* that has no assocoated port?
|
||||
*/
|
||||
static void scic_sds_apc_agent_link_up(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port_configuration_agent *port_agent,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy)
|
||||
{
|
||||
BUG_ON(port != SCI_INVALID_HANDLE);
|
||||
|
||||
port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy));
|
||||
|
||||
scic_sds_apc_agent_configure_ports(controller, port_agent, phy, true);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @controller: This is the controller object that receives the link down
|
||||
* notification.
|
||||
* @port: This is the port object associated with the phy. If the is no
|
||||
* associated port this is an SCI_INVALID_HANDLE.
|
||||
* @phy: This is the phy object which has gone link down.
|
||||
*
|
||||
* This method handles the automatic port configuration link down
|
||||
* notifications. not associated with a port there is no action taken. Is it
|
||||
* possible to get a link down notification from a phy that has no assocoated
|
||||
* port?
|
||||
*/
|
||||
static void scic_sds_apc_agent_link_down(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port_configuration_agent *port_agent,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy)
|
||||
{
|
||||
port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy));
|
||||
|
||||
if (port != SCI_INVALID_HANDLE) {
|
||||
if (port_agent->phy_configured_mask & (1 << phy->phy_index)) {
|
||||
enum sci_status status;
|
||||
|
||||
status = scic_sds_port_remove_phy(port, phy);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
port_agent->phy_configured_mask &= ~(1 << phy->phy_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This routine will try to configure the phys into ports when the timer fires.
|
||||
*/
|
||||
static void scic_sds_apc_agent_timeout_handler(
|
||||
void *object)
|
||||
{
|
||||
u32 index;
|
||||
struct scic_sds_port_configuration_agent *port_agent;
|
||||
struct scic_sds_controller *controller = (struct scic_sds_controller *)object;
|
||||
u16 configure_phy_mask;
|
||||
|
||||
port_agent = scic_sds_controller_get_port_configuration_agent(controller);
|
||||
|
||||
port_agent->timer_pending = false;
|
||||
|
||||
configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
|
||||
|
||||
if (configure_phy_mask != 0x00) {
|
||||
for (index = 0; index < SCI_MAX_PHYS; index++) {
|
||||
if (configure_phy_mask & (1 << index)) {
|
||||
scic_sds_apc_agent_configure_ports(
|
||||
controller, port_agent, &controller->phy_table[index], false
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* Public port configuration agent routines
|
||||
* ****************************************************************************** */
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This method will construct the port configuration agent for operation. This
|
||||
* call is universal for both manual port configuration and automatic port
|
||||
* configuration modes.
|
||||
*/
|
||||
void scic_sds_port_configuration_agent_construct(
|
||||
struct scic_sds_port_configuration_agent *port_agent)
|
||||
{
|
||||
u32 index;
|
||||
|
||||
port_agent->phy_configured_mask = 0x00;
|
||||
port_agent->phy_ready_mask = 0x00;
|
||||
|
||||
port_agent->link_up_handler = NULL;
|
||||
port_agent->link_down_handler = NULL;
|
||||
|
||||
port_agent->timer_pending = false;
|
||||
port_agent->timer = NULL;
|
||||
|
||||
for (index = 0; index < SCI_MAX_PORTS; index++) {
|
||||
port_agent->phy_valid_port_range[index].min_index = 0;
|
||||
port_agent->phy_valid_port_range[index].max_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @controller: This is the controller object for which the port agent is being
|
||||
* initialized.
|
||||
*
|
||||
* This method will construct the port configuration agent for this controller.
|
||||
*/
|
||||
enum sci_status scic_sds_port_configuration_agent_initialize(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port_configuration_agent *port_agent)
|
||||
{
|
||||
enum sci_status status = SCI_SUCCESS;
|
||||
enum SCIC_PORT_CONFIGURATION_MODE mode;
|
||||
|
||||
mode = scic_sds_controller_get_port_configuration_mode(controller);
|
||||
|
||||
if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
|
||||
status = scic_sds_mpc_agent_validate_phy_configuration(controller, port_agent);
|
||||
|
||||
port_agent->link_up_handler = scic_sds_mpc_agent_link_up;
|
||||
port_agent->link_down_handler = scic_sds_mpc_agent_link_down;
|
||||
|
||||
port_agent->timer = scic_cb_timer_create(
|
||||
controller,
|
||||
scic_sds_mpc_agent_timeout_handler,
|
||||
controller
|
||||
);
|
||||
} else {
|
||||
status = scic_sds_apc_agent_validate_phy_configuration(controller, port_agent);
|
||||
|
||||
port_agent->link_up_handler = scic_sds_apc_agent_link_up;
|
||||
port_agent->link_down_handler = scic_sds_apc_agent_link_down;
|
||||
|
||||
port_agent->timer = scic_cb_timer_create(
|
||||
controller,
|
||||
scic_sds_apc_agent_timeout_handler,
|
||||
controller
|
||||
);
|
||||
}
|
||||
|
||||
/* Make sure we have actually gotten a timer */
|
||||
if ((status == SCI_SUCCESS) && (port_agent->timer == NULL)) {
|
||||
dev_err(scic_to_dev(controller),
|
||||
"%s: Controller 0x%p automatic port configuration "
|
||||
"agent could not get timer.\n",
|
||||
__func__,
|
||||
controller);
|
||||
|
||||
status = SCI_FAILURE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
108
drivers/scsi/isci/core/scic_sds_port_configuration_agent.h
Normal file
108
drivers/scsi/isci/core/scic_sds_port_configuration_agent.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_
|
||||
#define _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_
|
||||
|
||||
/**
|
||||
* This file contains the structures, constants and prototypes used for the
|
||||
* core controller automatic port configuration engine.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "scic_sds_port.h"
|
||||
#include "scic_sds_phy.h"
|
||||
|
||||
struct scic_sds_controller;
|
||||
struct scic_sds_port_configuration_agent;
|
||||
struct scic_sds_port;
|
||||
struct scic_sds_phy;
|
||||
|
||||
typedef void (*SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T)(
|
||||
struct scic_sds_controller *,
|
||||
struct scic_sds_port_configuration_agent *,
|
||||
struct scic_sds_port *,
|
||||
struct scic_sds_phy *
|
||||
);
|
||||
|
||||
struct SCIC_SDS_PORT_RANGE {
|
||||
u8 min_index;
|
||||
u8 max_index;
|
||||
};
|
||||
|
||||
struct scic_sds_port_configuration_agent {
|
||||
u16 phy_configured_mask;
|
||||
u16 phy_ready_mask;
|
||||
|
||||
struct SCIC_SDS_PORT_RANGE phy_valid_port_range[SCI_MAX_PHYS];
|
||||
|
||||
bool timer_pending;
|
||||
|
||||
SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T link_up_handler;
|
||||
SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T link_down_handler;
|
||||
|
||||
void *timer;
|
||||
|
||||
};
|
||||
|
||||
void scic_sds_port_configuration_agent_construct(
|
||||
struct scic_sds_port_configuration_agent *port_agent);
|
||||
|
||||
enum sci_status scic_sds_port_configuration_agent_initialize(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port_configuration_agent *port_agent);
|
||||
|
||||
#endif /* _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_ */
|
||||
223
drivers/scsi/isci/core/scic_sds_port_registers.h
Normal file
223
drivers/scsi/isci/core/scic_sds_port_registers.h
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_PORT_REGISTERS_H_
|
||||
#define _SCIC_SDS_PORT_REGISTERS_H_
|
||||
|
||||
/**
|
||||
* This file contains a set of macros that assist in reading the SCU hardware
|
||||
* registers.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* scu_transport_layer_read() -
|
||||
*
|
||||
* Macro to read the transport layer register associated with this port object.
|
||||
*/
|
||||
#define scu_transport_layer_read(port, reg) \
|
||||
scu_register_read(\
|
||||
scic_sds_port_get_controller(port), \
|
||||
(port)->transport_layer_registers->reg \
|
||||
)
|
||||
|
||||
/**
|
||||
* scu_transport_layer_write() -
|
||||
*
|
||||
* Macro to write the transport layer register associated with this port object.
|
||||
*/
|
||||
#define scu_transport_layer_write(port, reg, value) \
|
||||
scu_register_write(\
|
||||
scic_sds_port_get_controller(port), \
|
||||
(port)->transport_layer_registers->reg, \
|
||||
(value) \
|
||||
)
|
||||
|
||||
/**
|
||||
* scu_port_task_scheduler_read() -
|
||||
*
|
||||
* Macro to read the port task scheduler register associated with this port
|
||||
* object
|
||||
*/
|
||||
#define scu_port_task_scheduler_read(port, reg) \
|
||||
scu_register_read(\
|
||||
scic_sds_port_get_controller(port), \
|
||||
(port)->port_task_scheduler_registers->reg \
|
||||
)
|
||||
|
||||
/**
|
||||
* scu_port_task_scheduler_write() -
|
||||
*
|
||||
* Macro to write the port task scheduler register associated with this port
|
||||
* object
|
||||
*/
|
||||
#define scu_port_task_scheduler_write(port, reg, value) \
|
||||
scu_register_write(\
|
||||
scic_sds_port_get_controller(port), \
|
||||
(port)->port_task_scheduler_registers->reg, \
|
||||
(value) \
|
||||
)
|
||||
|
||||
#define scu_port_viit_register_write(port, reg, value) \
|
||||
scu_register_write(\
|
||||
scic_sds_port_get_controller(port), \
|
||||
(port)->viit_registers->reg, \
|
||||
(value) \
|
||||
)
|
||||
|
||||
/*
|
||||
* ****************************************************************************
|
||||
* * Transport Layer registers controlled by the port object
|
||||
* **************************************************************************** */
|
||||
|
||||
/**
|
||||
* SCU_TLCR_READ() -
|
||||
*
|
||||
* This macro reads the Transport layer control register
|
||||
*/
|
||||
#define SCU_TLCR_READ(port) \
|
||||
scu_transport_layer_read(port, control)
|
||||
|
||||
/**
|
||||
* SCU_TLCR_WRITE() -
|
||||
*
|
||||
* This macro writes the Transport layer control register
|
||||
*/
|
||||
#define SCU_TLCR_WRITE(port, value) \
|
||||
scu_transport_layer_write(port, control, value)
|
||||
|
||||
/**
|
||||
* SCU_TLADTR_READ() -
|
||||
*
|
||||
* This macro reads the Transport layer address translation register
|
||||
*/
|
||||
#define SCU_TLADTR_READ(port) \
|
||||
scu_transport_layer_read(port, address_translation)
|
||||
|
||||
/**
|
||||
* SCU_TLADTR_WRITE() -
|
||||
*
|
||||
* This macro writes the Transport layer address translation register
|
||||
*/
|
||||
#define SCU_TLADTR_WRITE(port) \
|
||||
scu_transport_layer_write(port, address_translation, value)
|
||||
|
||||
/**
|
||||
* SCU_STPTLDARNI_WRITE() -
|
||||
*
|
||||
* This macro writes the STP Transport Layer Direct Attached RNi register.
|
||||
*/
|
||||
#define SCU_STPTLDARNI_WRITE(port, index) \
|
||||
scu_transport_layer_write(port, stp_rni, index)
|
||||
|
||||
/**
|
||||
* SCU_STPTLDARNI_READ() -
|
||||
*
|
||||
* This macro reads the STP Transport Layer Direct Attached RNi register.
|
||||
*/
|
||||
#define SCU_STPTLDARNI_READ(port) \
|
||||
scu_transport_layer_read(port, stp_rni)
|
||||
|
||||
/*
|
||||
* ****************************************************************************
|
||||
* * Port Task Scheduler registers controlled by the port object
|
||||
* **************************************************************************** */
|
||||
|
||||
/**
|
||||
* SCU_PTSxCR_READ() -
|
||||
*
|
||||
* Macro to read the port task scheduler control register
|
||||
*/
|
||||
#define SCU_PTSxCR_READ(port) \
|
||||
scu_port_task_scheduler_read(port, control)
|
||||
|
||||
/**
|
||||
* SCU_PTSxCR_WRITE() -
|
||||
*
|
||||
* Macro to write the port task scheduler control regsister
|
||||
*/
|
||||
#define SCU_PTSxCR_WRITE(port, value) \
|
||||
scu_port_task_scheduler_write(port, control, value)
|
||||
|
||||
/*
|
||||
* ****************************************************************************
|
||||
* * Port PE Configuration registers
|
||||
* **************************************************************************** */
|
||||
|
||||
/**
|
||||
* SCU_PCSPExCR_WRITE() -
|
||||
*
|
||||
* Macro to write the PE Port Configuration Register
|
||||
*/
|
||||
#define SCU_PCSPExCR_WRITE(port, phy_id, value) \
|
||||
scu_register_write(\
|
||||
scic_sds_port_get_controller(port), \
|
||||
(port)->port_pe_configuration_register[phy_id], \
|
||||
(value) \
|
||||
)
|
||||
|
||||
/**
|
||||
* SCU_PCSPExCR_READ() -
|
||||
*
|
||||
* Macro to read the PE Port Configuration Regsiter
|
||||
*/
|
||||
#define SCU_PCSPExCR_READ(port, phy_id) \
|
||||
scu_register_read(\
|
||||
scic_sds_port_get_controller(port), \
|
||||
(port)->port_pe_configuration_register[phy_id] \
|
||||
)
|
||||
|
||||
#endif /* _SCIC_SDS_PORT_REGISTERS_H_ */
|
||||
2252
drivers/scsi/isci/core/scic_sds_remote_device.c
Normal file
2252
drivers/scsi/isci/core/scic_sds_remote_device.c
Normal file
File diff suppressed because it is too large
Load Diff
602
drivers/scsi/isci/core/scic_sds_remote_device.h
Normal file
602
drivers/scsi/isci/core/scic_sds_remote_device.h
Normal file
@@ -0,0 +1,602 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_REMOTE_DEVICE_H_
|
||||
#define _SCIC_SDS_REMOTE_DEVICE_H_
|
||||
|
||||
/**
|
||||
* This file contains the structures, constants, and prototypes for the
|
||||
* struct scic_sds_remote_device object.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "intel_sas.h"
|
||||
#include "sci_base_remote_device.h"
|
||||
#include "sci_base_request.h"
|
||||
#include "scu_remote_node_context.h"
|
||||
#include "scic_sds_remote_node_context.h"
|
||||
|
||||
struct scic_sds_controller;
|
||||
struct scic_sds_port;
|
||||
struct scic_sds_request;
|
||||
struct scic_sds_remote_device_state_handler;
|
||||
|
||||
/**
|
||||
* enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES -
|
||||
*
|
||||
* This is the enumeration of the ready substates for the
|
||||
* struct scic_sds_remote_device.
|
||||
*/
|
||||
enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES {
|
||||
/**
|
||||
* This is the initial state for the remote device ready substate.
|
||||
*/
|
||||
SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_INITIAL,
|
||||
|
||||
/**
|
||||
* This is the ready operational substate for the remote device. This is the
|
||||
* normal operational state for a remote device.
|
||||
*/
|
||||
SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL,
|
||||
|
||||
/**
|
||||
* This is the suspended state for the remote device. This is the state that
|
||||
* the device is placed in when a RNC suspend is received by the SCU hardware.
|
||||
*/
|
||||
SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED,
|
||||
|
||||
/**
|
||||
* This is the final state that the device is placed in before a change to the
|
||||
* base state machine.
|
||||
*/
|
||||
SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_FINAL,
|
||||
|
||||
SCIC_SDS_SSP_REMOTE_DEVICE_READY_MAX_SUBSTATES
|
||||
};
|
||||
|
||||
/**
|
||||
* enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES -
|
||||
*
|
||||
* This is the enumeration for the struct scic_sds_remote_device ready substates for
|
||||
* the STP remote device.
|
||||
*/
|
||||
enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES {
|
||||
/**
|
||||
* This is the idle substate for the stp remote device. When there are no
|
||||
* active IO for the device it is is in this state.
|
||||
*/
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE,
|
||||
|
||||
/**
|
||||
* This is the command state for for the STP remote device. This state is
|
||||
* entered when the device is processing a non-NCQ command. The device object
|
||||
* will fail any new start IO requests until this command is complete.
|
||||
*/
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD,
|
||||
|
||||
/**
|
||||
* This is the NCQ state for the STP remote device. This state is entered
|
||||
* when the device is processing an NCQ reuqest. It will remain in this state
|
||||
* so long as there is one or more NCQ requests being processed.
|
||||
*/
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ,
|
||||
|
||||
/**
|
||||
* This is the NCQ error state for the STP remote device. This state is
|
||||
* entered when an SDB error FIS is received by the device object while in the
|
||||
* NCQ state. The device object will only accept a READ LOG command while in
|
||||
* this state.
|
||||
*/
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR,
|
||||
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
/**
|
||||
* This is the ATAPI error state for the STP ATAPI remote device. This state is
|
||||
* entered when ATAPI device sends error status FIS without data while the device
|
||||
* object is in CMD state. A suspension event is expected in this state. The device
|
||||
* object will resume right away.
|
||||
*/
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR,
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This is the READY substate indicates the device is waiting for the RESET task
|
||||
* coming to be recovered from certain hardware specific error.
|
||||
*/
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET,
|
||||
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES -
|
||||
*
|
||||
* This is the enumeration of the ready substates for the SMP REMOTE DEVICE.
|
||||
*/
|
||||
|
||||
enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES {
|
||||
/**
|
||||
* This is the ready operational substate for the remote device. This is the
|
||||
* normal operational state for a remote device.
|
||||
*/
|
||||
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE,
|
||||
|
||||
/**
|
||||
* This is the suspended state for the remote device. This is the state that
|
||||
* the device is placed in when a RNC suspend is received by the SCU hardware.
|
||||
*/
|
||||
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD,
|
||||
|
||||
SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* struct scic_sds_remote_device - This structure contains the data for an SCU
|
||||
* implementation of the SCU Core device data.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_sds_remote_device {
|
||||
/**
|
||||
* This field is the common base for all remote device objects.
|
||||
*/
|
||||
struct sci_base_remote_device parent;
|
||||
|
||||
/**
|
||||
* This field is the programmed device port width. This value is written to
|
||||
* the RCN data structure to tell the SCU how many open connections this
|
||||
* device can have.
|
||||
*/
|
||||
u32 device_port_width;
|
||||
|
||||
/**
|
||||
* This field is the programmed connection rate for this remote device. It is
|
||||
* used to program the TC with the maximum allowed connection rate.
|
||||
*/
|
||||
enum sci_sas_link_rate connection_rate;
|
||||
|
||||
/**
|
||||
* This field contains the allowed target protocols for this remote device.
|
||||
*/
|
||||
struct smp_discover_response_protocols target_protocols;
|
||||
|
||||
/**
|
||||
* This field contains the device SAS address.
|
||||
*/
|
||||
struct sci_sas_address device_address;
|
||||
|
||||
/**
|
||||
* This filed is assinged the value of true if the device is directly attached
|
||||
* to the port.
|
||||
*/
|
||||
bool is_direct_attached;
|
||||
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
/**
|
||||
* This filed is assinged the value of true if the device is an ATAPI device.
|
||||
*/
|
||||
bool is_atapi;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This filed contains a pointer back to the port to which this device is
|
||||
* assigned.
|
||||
*/
|
||||
struct scic_sds_port *owning_port;
|
||||
|
||||
/**
|
||||
* This field contains the SCU silicon remote node context specific
|
||||
* information.
|
||||
*/
|
||||
struct scic_sds_remote_node_context *rnc;
|
||||
|
||||
/**
|
||||
* This field contains the stated request count for the remote device. The
|
||||
* device can not reach the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED until all
|
||||
* requests are complete and the rnc_posted value is false.
|
||||
*/
|
||||
u32 started_request_count;
|
||||
|
||||
/**
|
||||
* This field contains a pointer to the working request object. It is only
|
||||
* used only for SATA requests since the unsolicited frames we get from the
|
||||
* hardware have no Tag value to look up the io request object.
|
||||
*/
|
||||
struct scic_sds_request *working_request;
|
||||
|
||||
/**
|
||||
* This field contains the reason for the remote device going not_ready. It is
|
||||
* assigned in the state handlers and used in the state transition.
|
||||
*/
|
||||
u32 not_ready_reason;
|
||||
|
||||
/**
|
||||
* This field is true if this remote device has an initialzied ready substate
|
||||
* machine. SSP devices do not have a ready substate machine and STP devices
|
||||
* have a ready substate machine.
|
||||
*/
|
||||
bool has_ready_substate_machine;
|
||||
|
||||
/**
|
||||
* This field contains the state machine for the ready substate machine for
|
||||
* this struct scic_sds_remote_device object.
|
||||
*/
|
||||
struct sci_base_state_machine ready_substate_machine;
|
||||
|
||||
/**
|
||||
* This field maintains the set of state handlers for the remote device
|
||||
* object. These are changed each time the remote device enters a new state.
|
||||
*/
|
||||
struct scic_sds_remote_device_state_handler *state_handlers;
|
||||
};
|
||||
|
||||
|
||||
typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_HANDLER_T)(
|
||||
struct scic_sds_remote_device *this_device);
|
||||
|
||||
typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_SUSPEND_HANDLER_T)(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 suspend_type);
|
||||
|
||||
typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_RESUME_HANDLER_T)(
|
||||
struct scic_sds_remote_device *this_device);
|
||||
|
||||
typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_FRAME_HANDLER_T)(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 frame_index);
|
||||
|
||||
typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_EVENT_HANDLER_T)(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 event_code);
|
||||
|
||||
typedef void (*SCIC_SDS_REMOTE_DEVICE_READY_NOT_READY_HANDLER_T)(
|
||||
struct scic_sds_remote_device *this_device);
|
||||
|
||||
/**
|
||||
* struct scic_sds_remote_device_state_handler - This structure conains the
|
||||
* state handlers that are needed to process requests for the SCU remote
|
||||
* device objects.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_sds_remote_device_state_handler {
|
||||
struct sci_base_remote_device_state_handler parent;
|
||||
|
||||
SCIC_SDS_REMOTE_DEVICE_SUSPEND_HANDLER_T suspend_handler;
|
||||
SCIC_SDS_REMOTE_DEVICE_RESUME_HANDLER_T resume_handler;
|
||||
|
||||
SCIC_SDS_REMOTE_DEVICE_EVENT_HANDLER_T event_handler;
|
||||
SCIC_SDS_REMOTE_DEVICE_FRAME_HANDLER_T frame_handler;
|
||||
|
||||
};
|
||||
|
||||
|
||||
extern const struct sci_base_state scic_sds_remote_device_state_table[];
|
||||
extern const struct sci_base_state scic_sds_ssp_remote_device_ready_substate_table[];
|
||||
extern const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[];
|
||||
extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[];
|
||||
|
||||
extern struct scic_sds_remote_device_state_handler
|
||||
scic_sds_remote_device_state_handler_table[];
|
||||
extern struct scic_sds_remote_device_state_handler
|
||||
scic_sds_ssp_remote_device_ready_substate_handler_table[];
|
||||
extern struct scic_sds_remote_device_state_handler
|
||||
scic_sds_stp_remote_device_ready_substate_handler_table[];
|
||||
extern struct scic_sds_remote_device_state_handler
|
||||
scic_sds_smp_remote_device_ready_substate_handler_table[];
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_increment_request_count() -
|
||||
*
|
||||
* This macro incrments the request count for this device
|
||||
*/
|
||||
#define scic_sds_remote_device_increment_request_count(this_device) \
|
||||
((this_device)->started_request_count++)
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_decrement_request_count() -
|
||||
*
|
||||
* This macro decrements the request count for this device. This count will
|
||||
* never decrment past 0.
|
||||
*/
|
||||
#define scic_sds_remote_device_decrement_request_count(this_device) \
|
||||
((this_device)->started_request_count > 0 ? \
|
||||
(this_device)->started_request_count-- : 0)
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_get_request_count() -
|
||||
*
|
||||
* This is a helper macro to return the current device request count.
|
||||
*/
|
||||
#define scic_sds_remote_device_get_request_count(this_device) \
|
||||
((this_device)->started_request_count)
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_get_port() -
|
||||
*
|
||||
* This macro returns the owning port of this remote device obejct.
|
||||
*/
|
||||
#define scic_sds_remote_device_get_port(this_device) \
|
||||
((this_device)->owning_port)
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_get_controller() -
|
||||
*
|
||||
* This macro returns the controller object that contains this device object
|
||||
*/
|
||||
#define scic_sds_remote_device_get_controller(this_device) \
|
||||
scic_sds_port_get_controller(scic_sds_remote_device_get_port(this_device))
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_set_state_handlers() -
|
||||
*
|
||||
* This macro sets the remote device state handlers pointer and is set on entry
|
||||
* to each device state.
|
||||
*/
|
||||
#define scic_sds_remote_device_set_state_handlers(this_device, handlers) \
|
||||
((this_device)->state_handlers = (handlers))
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_get_base_state_machine() -
|
||||
*
|
||||
* This macro returns the base sate machine object for the remote device.
|
||||
*/
|
||||
#define scic_sds_remote_device_get_base_state_machine(this_device) \
|
||||
(&(this_device)->parent.state_machine)
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_get_ready_substate_machine() -
|
||||
*
|
||||
* This macro returns the remote device ready substate machine
|
||||
*/
|
||||
#define scic_sds_remote_device_get_ready_substate_machine(this_device) \
|
||||
(&(this_device)->ready_substate_machine)
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_get_port() -
|
||||
*
|
||||
* This macro returns the owning port of this device
|
||||
*/
|
||||
#define scic_sds_remote_device_get_port(this_device) \
|
||||
((this_device)->owning_port)
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_get_sequence() -
|
||||
*
|
||||
* This macro returns the remote device sequence value
|
||||
*/
|
||||
#define scic_sds_remote_device_get_sequence(this_device) \
|
||||
(\
|
||||
scic_sds_remote_device_get_controller(this_device)-> \
|
||||
remote_device_sequence[(this_device)->rnc->remote_node_index] \
|
||||
)
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_get_controller_peg() -
|
||||
*
|
||||
* This macro returns the controllers protocol engine group
|
||||
*/
|
||||
#define scic_sds_remote_device_get_controller_peg(this_device) \
|
||||
(\
|
||||
scic_sds_controller_get_protocol_engine_group(\
|
||||
scic_sds_port_get_controller(\
|
||||
scic_sds_remote_device_get_port(this_device) \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_get_port_index() -
|
||||
*
|
||||
* This macro returns the port index for the devices owning port
|
||||
*/
|
||||
#define scic_sds_remote_device_get_port_index(this_device) \
|
||||
(scic_sds_port_get_index(scic_sds_remote_device_get_port(this_device)))
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_get_index() -
|
||||
*
|
||||
* This macro returns the remote node index for this device object
|
||||
*/
|
||||
#define scic_sds_remote_device_get_index(this_device) \
|
||||
((this_device)->rnc->remote_node_index)
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_build_command_context() -
|
||||
*
|
||||
* This macro builds a remote device context for the SCU post request operation
|
||||
*/
|
||||
#define scic_sds_remote_device_build_command_context(device, command) \
|
||||
((command) \
|
||||
| (scic_sds_remote_device_get_controller_peg((device)) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) \
|
||||
| (scic_sds_remote_device_get_port_index((device)) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) \
|
||||
| (scic_sds_remote_device_get_index((device))) \
|
||||
)
|
||||
|
||||
/**
|
||||
* scic_sds_remote_device_set_working_request() -
|
||||
*
|
||||
* This macro makes the working request assingment for the remote device
|
||||
* object. To clear the working request use this macro with a NULL request
|
||||
* object.
|
||||
*/
|
||||
#define scic_sds_remote_device_set_working_request(device, request) \
|
||||
((device)->working_request = (request))
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
enum sci_status scic_sds_remote_device_frame_handler(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 frame_index);
|
||||
|
||||
enum sci_status scic_sds_remote_device_event_handler(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 event_code);
|
||||
|
||||
enum sci_status scic_sds_remote_device_start_io(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *this_device,
|
||||
struct scic_sds_request *io_request);
|
||||
|
||||
enum sci_status scic_sds_remote_device_complete_io(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *this_device,
|
||||
struct scic_sds_request *io_request);
|
||||
|
||||
enum sci_status scic_sds_remote_device_resume(
|
||||
struct scic_sds_remote_device *this_device);
|
||||
|
||||
enum sci_status scic_sds_remote_device_suspend(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 suspend_type);
|
||||
|
||||
enum sci_status scic_sds_remote_device_start_task(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *this_device,
|
||||
struct scic_sds_request *io_request);
|
||||
|
||||
void scic_sds_remote_device_post_request(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 request);
|
||||
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
bool scic_sds_remote_device_is_atapi(
|
||||
struct scic_sds_remote_device *this_device);
|
||||
#else /* !defined(DISABLE_ATAPI) */
|
||||
#define scic_sds_remote_device_is_atapi(this_device) false
|
||||
#endif /* !defined(DISABLE_ATAPI) */
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
void scic_sds_remote_device_start_request(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
struct scic_sds_request *the_request,
|
||||
enum sci_status status);
|
||||
|
||||
void scic_sds_remote_device_continue_request(
|
||||
struct scic_sds_remote_device *this_device);
|
||||
|
||||
enum sci_status scic_sds_remote_device_default_start_handler(
|
||||
struct sci_base_remote_device *this_device);
|
||||
|
||||
|
||||
enum sci_status scic_sds_remote_device_default_fail_handler(
|
||||
struct sci_base_remote_device *this_device);
|
||||
|
||||
enum sci_status scic_sds_remote_device_default_destruct_handler(
|
||||
struct sci_base_remote_device *this_device);
|
||||
|
||||
enum sci_status scic_sds_remote_device_default_reset_handler(
|
||||
struct sci_base_remote_device *device);
|
||||
|
||||
enum sci_status scic_sds_remote_device_default_reset_complete_handler(
|
||||
struct sci_base_remote_device *device);
|
||||
|
||||
enum sci_status scic_sds_remote_device_default_start_request_handler(
|
||||
struct sci_base_remote_device *device,
|
||||
struct sci_base_request *request);
|
||||
|
||||
enum sci_status scic_sds_remote_device_default_complete_request_handler(
|
||||
struct sci_base_remote_device *device,
|
||||
struct sci_base_request *request);
|
||||
|
||||
enum sci_status scic_sds_remote_device_default_continue_request_handler(
|
||||
struct sci_base_remote_device *device,
|
||||
struct sci_base_request *request);
|
||||
|
||||
enum sci_status scic_sds_remote_device_default_suspend_handler(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 suspend_type);
|
||||
|
||||
enum sci_status scic_sds_remote_device_default_resume_handler(
|
||||
struct scic_sds_remote_device *this_device);
|
||||
|
||||
|
||||
enum sci_status scic_sds_remote_device_default_frame_handler(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 frame_index);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
enum sci_status scic_sds_remote_device_ready_state_stop_handler(
|
||||
struct sci_base_remote_device *device);
|
||||
|
||||
enum sci_status scic_sds_remote_device_ready_state_reset_handler(
|
||||
struct sci_base_remote_device *device);
|
||||
|
||||
enum sci_status scic_sds_remote_device_general_frame_handler(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 frame_index);
|
||||
|
||||
enum sci_status scic_sds_remote_device_general_event_handler(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 event_code);
|
||||
|
||||
enum sci_status scic_sds_ssp_remote_device_ready_suspended_substate_resume_handler(
|
||||
struct scic_sds_remote_device *this_device);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#endif /* _SCIC_SDS_REMOTE_DEVICE_H_ */
|
||||
1244
drivers/scsi/isci/core/scic_sds_remote_node_context.c
Normal file
1244
drivers/scsi/isci/core/scic_sds_remote_node_context.c
Normal file
File diff suppressed because it is too large
Load Diff
342
drivers/scsi/isci/core/scic_sds_remote_node_context.h
Normal file
342
drivers/scsi/isci/core/scic_sds_remote_node_context.h
Normal file
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_REMOTE_NODE_CONTEXT_H_
|
||||
#define _SCIC_SDS_REMOTE_NODE_CONTEXT_H_
|
||||
|
||||
/**
|
||||
* This file contains the structures, constants, and prototypes associated with
|
||||
* the remote node context in the silicon. It exists to model and manage
|
||||
* the remote node context in the silicon.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci_types.h"
|
||||
#include "sci_base_state.h"
|
||||
#include "sci_base_state_machine.h"
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This constant represents an invalid remote device id, it is used to program
|
||||
* the STPDARNI register so the driver knows when it has received a SIGNATURE
|
||||
* FIS from the SCU.
|
||||
*/
|
||||
#define SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX 0x0FFF
|
||||
|
||||
#define SCU_HARDWARE_SUSPENSION (0)
|
||||
#define SCI_SOFTWARE_SUSPENSION (1)
|
||||
|
||||
struct scic_sds_request;
|
||||
struct scic_sds_remote_device;
|
||||
struct scic_sds_remote_node_context;
|
||||
|
||||
typedef void (*SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK)(void *);
|
||||
|
||||
typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION)(
|
||||
struct scic_sds_remote_node_context *this_rnc,
|
||||
SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
|
||||
void *callback_parameter
|
||||
);
|
||||
|
||||
typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_SUSPEND_OPERATION)(
|
||||
struct scic_sds_remote_node_context *this_rnc,
|
||||
u32 suspension_type,
|
||||
SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
|
||||
void *callback_parameter
|
||||
);
|
||||
|
||||
typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST)(
|
||||
struct scic_sds_remote_node_context *this_rnc,
|
||||
struct scic_sds_request *the_request
|
||||
);
|
||||
|
||||
typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_EVENT_HANDLER)(
|
||||
struct scic_sds_remote_node_context *this_rnc,
|
||||
u32 event_code
|
||||
);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
struct scic_sds_remote_node_context_handlers {
|
||||
/**
|
||||
* This handle is invoked to stop the RNC. The callback is invoked when after
|
||||
* the hardware notification that the RNC has been invalidated.
|
||||
*/
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION destruct_handler;
|
||||
|
||||
/**
|
||||
* This handler is invoked when there is a request to suspend the RNC. The
|
||||
* callback is invoked after the hardware notification that the remote node is
|
||||
* suspended.
|
||||
*/
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_SUSPEND_OPERATION suspend_handler;
|
||||
|
||||
/**
|
||||
* This handler is invoked when there is a request to resume the RNC. The
|
||||
* callback is invoked when after the RNC has reached the ready state.
|
||||
*/
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION resume_handler;
|
||||
|
||||
/**
|
||||
* This handler is invoked when there is a request to start an io request
|
||||
* operation.
|
||||
*/
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST start_io_handler;
|
||||
|
||||
/**
|
||||
* This handler is invoked when there is a request to start a task request
|
||||
* operation.
|
||||
*/
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST start_task_handler;
|
||||
|
||||
/**
|
||||
* This handler is invoked where there is an RNC event that must be processed.
|
||||
*/
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_EVENT_HANDLER event_handler;
|
||||
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This is the enumeration of the remote node context states.
|
||||
*/
|
||||
enum scis_sds_remote_node_context_states {
|
||||
/**
|
||||
* This state is the initial state for a remote node context. On a resume
|
||||
* request the remote node context will transition to the posting state.
|
||||
*/
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE,
|
||||
|
||||
/**
|
||||
* This is a transition state that posts the RNi to the hardware. Once the RNC
|
||||
* is posted the remote node context will be made ready.
|
||||
*/
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE,
|
||||
|
||||
/**
|
||||
* This is a transition state that will post an RNC invalidate to the
|
||||
* hardware. Once the invalidate is complete the remote node context will
|
||||
* transition to the posting state.
|
||||
*/
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE,
|
||||
|
||||
/**
|
||||
* This is a transition state that will post an RNC resume to the hardare.
|
||||
* Once the event notification of resume complete is received the remote node
|
||||
* context will transition to the ready state.
|
||||
*/
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE,
|
||||
|
||||
/**
|
||||
* This is the state that the remote node context must be in to accept io
|
||||
* request operations.
|
||||
*/
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE,
|
||||
|
||||
/**
|
||||
* This is the state that the remote node context transitions to when it gets
|
||||
* a TX suspend notification from the hardware.
|
||||
*/
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE,
|
||||
|
||||
/**
|
||||
* This is the state that the remote node context transitions to when it gets
|
||||
* a TX RX suspend notification from the hardware.
|
||||
*/
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE,
|
||||
|
||||
/**
|
||||
* This state is a wait state for the remote node context that waits for a
|
||||
* suspend notification from the hardware. This state is entered when either
|
||||
* there is a request to supend the remote node context or when there is a TC
|
||||
* completion where the remote node will be suspended by the hardware.
|
||||
*/
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE,
|
||||
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This enumeration is used to define the end destination state for the remote
|
||||
* node context.
|
||||
*/
|
||||
enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE {
|
||||
SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED,
|
||||
SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY,
|
||||
SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_sds_remote_node_context - This structure contains the data
|
||||
* associated with the remote node context object. The remote node context
|
||||
* (RNC) object models the the remote device information necessary to manage
|
||||
* the silicon RNC.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_sds_remote_node_context {
|
||||
/*
|
||||
* parent object
|
||||
*/
|
||||
struct sci_base_object parent;
|
||||
|
||||
/**
|
||||
* This pointer simply points to the remote device object containing
|
||||
* this RNC.
|
||||
*
|
||||
* @todo Consider making the device pointer the associated object of the
|
||||
* the parent object.
|
||||
*/
|
||||
struct scic_sds_remote_device *device;
|
||||
|
||||
/**
|
||||
* This field indicates the remote node index (RNI) associated with
|
||||
* this RNC.
|
||||
*/
|
||||
u16 remote_node_index;
|
||||
|
||||
/**
|
||||
* This field is the recored suspension code or the reason for the remote node
|
||||
* context suspension.
|
||||
*/
|
||||
u32 suspension_code;
|
||||
|
||||
/**
|
||||
* This field is true if the remote node context is resuming from its current
|
||||
* state. This can cause an automatic resume on receiving a suspension
|
||||
* notification.
|
||||
*/
|
||||
enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE destination_state;
|
||||
|
||||
/**
|
||||
* This field contains the callback function that the user requested to be
|
||||
* called when the requested state transition is complete.
|
||||
*/
|
||||
SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK user_callback;
|
||||
|
||||
/**
|
||||
* This field contains the parameter that is called when the user requested
|
||||
* state transition is completed.
|
||||
*/
|
||||
void *user_cookie;
|
||||
|
||||
/**
|
||||
* This field contains the data for the object's state machine.
|
||||
*/
|
||||
struct sci_base_state_machine state_machine;
|
||||
|
||||
struct scic_sds_remote_node_context_handlers *state_handlers;
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
extern const struct sci_base_state scic_sds_remote_node_context_state_table[];
|
||||
|
||||
extern struct scic_sds_remote_node_context_handlers
|
||||
scic_sds_remote_node_context_state_handler_table[
|
||||
SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES];
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
void scic_sds_remote_node_context_construct(
|
||||
struct scic_sds_remote_device *device,
|
||||
struct scic_sds_remote_node_context *rnc,
|
||||
u16 remote_node_index);
|
||||
|
||||
void scic_sds_remote_node_context_construct_buffer(
|
||||
struct scic_sds_remote_node_context *rnc);
|
||||
|
||||
|
||||
bool scic_sds_remote_node_context_is_ready(
|
||||
struct scic_sds_remote_node_context *this_rnc);
|
||||
|
||||
#define scic_sds_remote_node_context_set_remote_node_index(rnc, rni) \
|
||||
((rnc)->remote_node_index = (rni))
|
||||
|
||||
#define scic_sds_remote_node_context_get_remote_node_index(rcn) \
|
||||
((rnc)->remote_node_index)
|
||||
|
||||
#define scic_sds_remote_node_context_event_handler(rnc, event_code) \
|
||||
((rnc)->state_handlers->event_handler(rnc, event_code))
|
||||
|
||||
#define scic_sds_remote_node_context_resume(rnc, callback, parameter) \
|
||||
((rnc)->state_handlers->resume_handler(rnc, callback, parameter))
|
||||
|
||||
#define scic_sds_remote_node_context_suspend(rnc, suspend_type, callback, parameter) \
|
||||
((rnc)->state_handlers->suspend_handler(rnc, suspend_type, callback, parameter))
|
||||
|
||||
#define scic_sds_remote_node_context_destruct(rnc, callback, parameter) \
|
||||
((rnc)->state_handlers->destruct_handler(rnc, callback, parameter))
|
||||
|
||||
#define scic_sds_remote_node_context_start_io(rnc, request) \
|
||||
((rnc)->state_handlers->start_io_handler(rnc, request))
|
||||
|
||||
#define scic_sds_remote_node_context_start_task(rnc, task) \
|
||||
((rnc)->state_handlers->start_task_handler(rnc, task))
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
#endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */
|
||||
|
||||
600
drivers/scsi/isci/core/scic_sds_remote_node_table.c
Normal file
600
drivers/scsi/isci/core/scic_sds_remote_node_table.c
Normal file
@@ -0,0 +1,600 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the implementation of the SCIC_SDS_REMOTE_NODE_TABLE
|
||||
* public, protected, and private methods.
|
||||
*
|
||||
*
|
||||
*/
|
||||
#include "sci_util.h"
|
||||
#include "sci_environment.h"
|
||||
#include "scic_sds_remote_node_table.h"
|
||||
#include "scic_sds_remote_node_context.h"
|
||||
|
||||
/**
|
||||
*
|
||||
* @remote_node_table: This is the remote node index table from which the
|
||||
* selection will be made.
|
||||
* @group_table_index: This is the index to the group table from which to
|
||||
* search for an available selection.
|
||||
*
|
||||
* This routine will find the bit position in absolute bit terms of the next 32
|
||||
* + bit position. If there are available bits in the first u32 then it is
|
||||
* just bit position. u32 This is the absolute bit position for an available
|
||||
* group.
|
||||
*/
|
||||
static u32 scic_sds_remote_node_table_get_group_index(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 group_table_index)
|
||||
{
|
||||
u32 dword_index;
|
||||
u32 *group_table;
|
||||
u32 bit_index;
|
||||
|
||||
group_table = remote_node_table->remote_node_groups[group_table_index];
|
||||
|
||||
for (dword_index = 0; dword_index < remote_node_table->group_array_size; dword_index++) {
|
||||
if (group_table[dword_index] != 0) {
|
||||
for (bit_index = 0; bit_index < 32; bit_index++) {
|
||||
if ((group_table[dword_index] & (1 << bit_index)) != 0) {
|
||||
return (dword_index * 32) + bit_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @out]: remote_node_table This the remote node table in which to clear the
|
||||
* selector.
|
||||
* @set_index: This is the remote node selector in which the change will be
|
||||
* made.
|
||||
* @group_index: This is the bit index in the table to be modified.
|
||||
*
|
||||
* This method will clear the group index entry in the specified group index
|
||||
* table. none
|
||||
*/
|
||||
static void scic_sds_remote_node_table_clear_group_index(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 group_table_index,
|
||||
u32 group_index)
|
||||
{
|
||||
u32 dword_index;
|
||||
u32 bit_index;
|
||||
u32 *group_table;
|
||||
|
||||
BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT);
|
||||
BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32));
|
||||
|
||||
dword_index = group_index / 32;
|
||||
bit_index = group_index % 32;
|
||||
group_table = remote_node_table->remote_node_groups[group_table_index];
|
||||
|
||||
group_table[dword_index] = group_table[dword_index] & ~(1 << bit_index);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @out]: remote_node_table This the remote node table in which to set the
|
||||
* selector.
|
||||
* @group_table_index: This is the remote node selector in which the change
|
||||
* will be made.
|
||||
* @group_index: This is the bit position in the table to be modified.
|
||||
*
|
||||
* This method will set the group index bit entry in the specified gropu index
|
||||
* table. none
|
||||
*/
|
||||
static void scic_sds_remote_node_table_set_group_index(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 group_table_index,
|
||||
u32 group_index)
|
||||
{
|
||||
u32 dword_index;
|
||||
u32 bit_index;
|
||||
u32 *group_table;
|
||||
|
||||
BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT);
|
||||
BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32));
|
||||
|
||||
dword_index = group_index / 32;
|
||||
bit_index = group_index % 32;
|
||||
group_table = remote_node_table->remote_node_groups[group_table_index];
|
||||
|
||||
group_table[dword_index] = group_table[dword_index] | (1 << bit_index);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @out]: remote_node_table This is the remote node table in which to modify
|
||||
* the remote node availability.
|
||||
* @remote_node_index: This is the remote node index that is being returned to
|
||||
* the table.
|
||||
*
|
||||
* This method will set the remote to available in the remote node allocation
|
||||
* table. none
|
||||
*/
|
||||
static void scic_sds_remote_node_table_set_node_index(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 remote_node_index)
|
||||
{
|
||||
u32 dword_location;
|
||||
u32 dword_remainder;
|
||||
u32 slot_normalized;
|
||||
u32 slot_position;
|
||||
|
||||
BUG_ON(
|
||||
(remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
|
||||
<= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT)
|
||||
);
|
||||
|
||||
dword_location = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD;
|
||||
dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD;
|
||||
slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32);
|
||||
slot_position = remote_node_index % SCU_STP_REMOTE_NODE_COUNT;
|
||||
|
||||
remote_node_table->available_remote_nodes[dword_location] |=
|
||||
1 << (slot_normalized + slot_position);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @out]: remote_node_table This is the remote node table from which to clear
|
||||
* the available remote node bit.
|
||||
* @remote_node_index: This is the remote node index which is to be cleared
|
||||
* from the table.
|
||||
*
|
||||
* This method clears the remote node index from the table of available remote
|
||||
* nodes. none
|
||||
*/
|
||||
static void scic_sds_remote_node_table_clear_node_index(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 remote_node_index)
|
||||
{
|
||||
u32 dword_location;
|
||||
u32 dword_remainder;
|
||||
u32 slot_position;
|
||||
u32 slot_normalized;
|
||||
|
||||
BUG_ON(
|
||||
(remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
|
||||
<= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT)
|
||||
);
|
||||
|
||||
dword_location = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD;
|
||||
dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD;
|
||||
slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32);
|
||||
slot_position = remote_node_index % SCU_STP_REMOTE_NODE_COUNT;
|
||||
|
||||
remote_node_table->available_remote_nodes[dword_location] &=
|
||||
~(1 << (slot_normalized + slot_position));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @out]: remote_node_table The remote node table from which the slot will be
|
||||
* cleared.
|
||||
* @group_index: The index for the slot that is to be cleared.
|
||||
*
|
||||
* This method clears the entire table slot at the specified slot index. none
|
||||
*/
|
||||
static void scic_sds_remote_node_table_clear_group(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 group_index)
|
||||
{
|
||||
u32 dword_location;
|
||||
u32 dword_remainder;
|
||||
u32 dword_value;
|
||||
|
||||
BUG_ON(
|
||||
(remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
|
||||
<= (group_index / SCU_STP_REMOTE_NODE_COUNT)
|
||||
);
|
||||
|
||||
dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
|
||||
dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
|
||||
|
||||
dword_value = remote_node_table->available_remote_nodes[dword_location];
|
||||
dword_value &= ~(SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
|
||||
remote_node_table->available_remote_nodes[dword_location] = dword_value;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @remote_node_table:
|
||||
*
|
||||
* THis method sets an entire remote node group in the remote node table.
|
||||
*/
|
||||
static void scic_sds_remote_node_table_set_group(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 group_index)
|
||||
{
|
||||
u32 dword_location;
|
||||
u32 dword_remainder;
|
||||
u32 dword_value;
|
||||
|
||||
BUG_ON(
|
||||
(remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
|
||||
<= (group_index / SCU_STP_REMOTE_NODE_COUNT)
|
||||
);
|
||||
|
||||
dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
|
||||
dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
|
||||
|
||||
dword_value = remote_node_table->available_remote_nodes[dword_location];
|
||||
dword_value |= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
|
||||
remote_node_table->available_remote_nodes[dword_location] = dword_value;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @remote_node_table: This is the remote node table that for which the group
|
||||
* value is to be returned.
|
||||
* @group_index: This is the group index to use to find the group value.
|
||||
*
|
||||
* This method will return the group value for the specified group index. The
|
||||
* bit values at the specified remote node group index.
|
||||
*/
|
||||
static u8 scic_sds_remote_node_table_get_group_value(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 group_index)
|
||||
{
|
||||
u32 dword_location;
|
||||
u32 dword_remainder;
|
||||
u32 dword_value;
|
||||
|
||||
dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
|
||||
dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
|
||||
|
||||
dword_value = remote_node_table->available_remote_nodes[dword_location];
|
||||
dword_value &= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
|
||||
dword_value = dword_value >> (dword_remainder * 4);
|
||||
|
||||
return (u8)dword_value;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @out]: remote_node_table The remote that which is to be initialized.
|
||||
* @remote_node_entries: The number of entries to put in the table.
|
||||
*
|
||||
* This method will initialize the remote node table for use. none
|
||||
*/
|
||||
void scic_sds_remote_node_table_initialize(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 remote_node_entries)
|
||||
{
|
||||
u32 index;
|
||||
|
||||
/*
|
||||
* Initialize the raw data we could improve the speed by only initializing
|
||||
* those entries that we are actually going to be used */
|
||||
memset(
|
||||
remote_node_table->available_remote_nodes,
|
||||
0x00,
|
||||
sizeof(remote_node_table->available_remote_nodes)
|
||||
);
|
||||
|
||||
memset(
|
||||
remote_node_table->remote_node_groups,
|
||||
0x00,
|
||||
sizeof(remote_node_table->remote_node_groups)
|
||||
);
|
||||
|
||||
/* Initialize the available remote node sets */
|
||||
remote_node_table->available_nodes_array_size = (u16)
|
||||
(remote_node_entries / SCIC_SDS_REMOTE_NODES_PER_DWORD)
|
||||
+ ((remote_node_entries % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0);
|
||||
|
||||
|
||||
/* Initialize each full DWORD to a FULL SET of remote nodes */
|
||||
for (index = 0; index < remote_node_entries; index++) {
|
||||
scic_sds_remote_node_table_set_node_index(remote_node_table, index);
|
||||
}
|
||||
|
||||
remote_node_table->group_array_size = (u16)
|
||||
(remote_node_entries / (SCU_STP_REMOTE_NODE_COUNT * 32))
|
||||
+ ((remote_node_entries % (SCU_STP_REMOTE_NODE_COUNT * 32)) != 0);
|
||||
|
||||
for (index = 0; index < (remote_node_entries / SCU_STP_REMOTE_NODE_COUNT); index++) {
|
||||
/*
|
||||
* These are all guaranteed to be full slot values so fill them in the
|
||||
* available sets of 3 remote nodes */
|
||||
scic_sds_remote_node_table_set_group_index(remote_node_table, 2, index);
|
||||
}
|
||||
|
||||
/* Now fill in any remainders that we may find */
|
||||
if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 2) {
|
||||
scic_sds_remote_node_table_set_group_index(remote_node_table, 1, index);
|
||||
} else if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 1) {
|
||||
scic_sds_remote_node_table_set_group_index(remote_node_table, 0, index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @out]: remote_node_table The remote node table from which to allocate a
|
||||
* remote node.
|
||||
* @table_index: The group index that is to be used for the search.
|
||||
*
|
||||
* This method will allocate a single RNi from the remote node table. The
|
||||
* table index will determine from which remote node group table to search.
|
||||
* This search may fail and another group node table can be specified. The
|
||||
* function is designed to allow a serach of the available single remote node
|
||||
* group up to the triple remote node group. If an entry is found in the
|
||||
* specified table the remote node is removed and the remote node groups are
|
||||
* updated. The RNi value or an invalid remote node context if an RNi can not
|
||||
* be found.
|
||||
*/
|
||||
static u16 scic_sds_remote_node_table_allocate_single_remote_node(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 group_table_index)
|
||||
{
|
||||
u8 index;
|
||||
u8 group_value;
|
||||
u32 group_index;
|
||||
u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
|
||||
|
||||
group_index = scic_sds_remote_node_table_get_group_index(
|
||||
remote_node_table, group_table_index);
|
||||
|
||||
/* We could not find an available slot in the table selector 0 */
|
||||
if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) {
|
||||
group_value = scic_sds_remote_node_table_get_group_value(
|
||||
remote_node_table, group_index);
|
||||
|
||||
for (index = 0; index < SCU_STP_REMOTE_NODE_COUNT; index++) {
|
||||
if (((1 << index) & group_value) != 0) {
|
||||
/* We have selected a bit now clear it */
|
||||
remote_node_index = (u16)(group_index * SCU_STP_REMOTE_NODE_COUNT
|
||||
+ index);
|
||||
|
||||
scic_sds_remote_node_table_clear_group_index(
|
||||
remote_node_table, group_table_index, group_index
|
||||
);
|
||||
|
||||
scic_sds_remote_node_table_clear_node_index(
|
||||
remote_node_table, remote_node_index
|
||||
);
|
||||
|
||||
if (group_table_index > 0) {
|
||||
scic_sds_remote_node_table_set_group_index(
|
||||
remote_node_table, group_table_index - 1, group_index
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return remote_node_index;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @remote_node_table: This is the remote node table from which to allocate the
|
||||
* remote node entries.
|
||||
* @group_table_index: THis is the group table index which must equal two (2)
|
||||
* for this operation.
|
||||
*
|
||||
* This method will allocate three consecutive remote node context entries. If
|
||||
* there are no remaining triple entries the function will return a failure.
|
||||
* The remote node index that represents three consecutive remote node entries
|
||||
* or an invalid remote node context if none can be found.
|
||||
*/
|
||||
static u16 scic_sds_remote_node_table_allocate_triple_remote_node(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 group_table_index)
|
||||
{
|
||||
u32 group_index;
|
||||
u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
|
||||
|
||||
group_index = scic_sds_remote_node_table_get_group_index(
|
||||
remote_node_table, group_table_index);
|
||||
|
||||
if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) {
|
||||
remote_node_index = (u16)group_index * SCU_STP_REMOTE_NODE_COUNT;
|
||||
|
||||
scic_sds_remote_node_table_clear_group_index(
|
||||
remote_node_table, group_table_index, group_index
|
||||
);
|
||||
|
||||
scic_sds_remote_node_table_clear_group(
|
||||
remote_node_table, group_index
|
||||
);
|
||||
}
|
||||
|
||||
return remote_node_index;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @remote_node_table: This is the remote node table from which the remote node
|
||||
* allocation is to take place.
|
||||
* @remote_node_count: This is ther remote node count which is one of
|
||||
* SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3).
|
||||
*
|
||||
* This method will allocate a remote node that mataches the remote node count
|
||||
* specified by the caller. Valid values for remote node count is
|
||||
* SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3). u16 This is
|
||||
* the remote node index that is returned or an invalid remote node context.
|
||||
*/
|
||||
u16 scic_sds_remote_node_table_allocate_remote_node(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 remote_node_count)
|
||||
{
|
||||
u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
|
||||
|
||||
if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) {
|
||||
remote_node_index =
|
||||
scic_sds_remote_node_table_allocate_single_remote_node(
|
||||
remote_node_table, 0);
|
||||
|
||||
if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
|
||||
remote_node_index =
|
||||
scic_sds_remote_node_table_allocate_single_remote_node(
|
||||
remote_node_table, 1);
|
||||
}
|
||||
|
||||
if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
|
||||
remote_node_index =
|
||||
scic_sds_remote_node_table_allocate_single_remote_node(
|
||||
remote_node_table, 2);
|
||||
}
|
||||
} else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) {
|
||||
remote_node_index =
|
||||
scic_sds_remote_node_table_allocate_triple_remote_node(
|
||||
remote_node_table, 2);
|
||||
}
|
||||
|
||||
return remote_node_index;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @remote_node_table:
|
||||
*
|
||||
* This method will free a single remote node index back to the remote node
|
||||
* table. This routine will update the remote node groups
|
||||
*/
|
||||
static void scic_sds_remote_node_table_release_single_remote_node(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u16 remote_node_index)
|
||||
{
|
||||
u32 group_index;
|
||||
u8 group_value;
|
||||
|
||||
group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT;
|
||||
|
||||
group_value = scic_sds_remote_node_table_get_group_value(remote_node_table, group_index);
|
||||
|
||||
/*
|
||||
* Assert that we are not trying to add an entry to a slot that is already
|
||||
* full. */
|
||||
BUG_ON(group_value == SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE);
|
||||
|
||||
if (group_value == 0x00) {
|
||||
/*
|
||||
* There are no entries in this slot so it must be added to the single
|
||||
* slot table. */
|
||||
scic_sds_remote_node_table_set_group_index(remote_node_table, 0, group_index);
|
||||
} else if ((group_value & (group_value - 1)) == 0) {
|
||||
/*
|
||||
* There is only one entry in this slot so it must be moved from the
|
||||
* single slot table to the dual slot table */
|
||||
scic_sds_remote_node_table_clear_group_index(remote_node_table, 0, group_index);
|
||||
scic_sds_remote_node_table_set_group_index(remote_node_table, 1, group_index);
|
||||
} else {
|
||||
/*
|
||||
* There are two entries in the slot so it must be moved from the dual
|
||||
* slot table to the tripple slot table. */
|
||||
scic_sds_remote_node_table_clear_group_index(remote_node_table, 1, group_index);
|
||||
scic_sds_remote_node_table_set_group_index(remote_node_table, 2, group_index);
|
||||
}
|
||||
|
||||
scic_sds_remote_node_table_set_node_index(remote_node_table, remote_node_index);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @remote_node_table: This is the remote node table to which the remote node
|
||||
* index is to be freed.
|
||||
*
|
||||
* This method will release a group of three consecutive remote nodes back to
|
||||
* the free remote nodes.
|
||||
*/
|
||||
static void scic_sds_remote_node_table_release_triple_remote_node(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u16 remote_node_index)
|
||||
{
|
||||
u32 group_index;
|
||||
|
||||
group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT;
|
||||
|
||||
scic_sds_remote_node_table_set_group_index(
|
||||
remote_node_table, 2, group_index
|
||||
);
|
||||
|
||||
scic_sds_remote_node_table_set_group(remote_node_table, group_index);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @remote_node_table: The remote node table to which the remote node index is
|
||||
* to be freed.
|
||||
* @remote_node_count: This is the count of consecutive remote nodes that are
|
||||
* to be freed.
|
||||
*
|
||||
* This method will release the remote node index back into the remote node
|
||||
* table free pool.
|
||||
*/
|
||||
void scic_sds_remote_node_table_release_remote_node_index(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 remote_node_count,
|
||||
u16 remote_node_index)
|
||||
{
|
||||
if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) {
|
||||
scic_sds_remote_node_table_release_single_remote_node(
|
||||
remote_node_table, remote_node_index);
|
||||
} else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) {
|
||||
scic_sds_remote_node_table_release_triple_remote_node(
|
||||
remote_node_table, remote_node_index);
|
||||
}
|
||||
}
|
||||
|
||||
196
drivers/scsi/isci/core/scic_sds_remote_node_table.h
Normal file
196
drivers/scsi/isci/core/scic_sds_remote_node_table.h
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_REMOTE_NODE_TABLE_H_
|
||||
#define _SCIC_SDS_REMOTE_NODE_TABLE_H_
|
||||
|
||||
/**
|
||||
* This file contains the structures, constants and prototypes used for the
|
||||
* remote node table.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci_types.h"
|
||||
#include "sci_controller_constants.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Remote node sets are sets of remote node index in the remtoe node table The
|
||||
* SCU hardware requires that STP remote node entries take three consecutive
|
||||
* remote node index so the table is arranged in sets of three. The bits are
|
||||
* used as 0111 0111 to make a byte and the bits define the set of three remote
|
||||
* nodes to use as a sequence.
|
||||
*/
|
||||
#define SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE 2
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Since the remote node table is organized as DWORDS take the remote node sets
|
||||
* in bytes and represent them in DWORDs. The lowest ordered bits are the ones
|
||||
* used in case full DWORD is not being used. i.e. 0000 0000 0000 0000 0111
|
||||
* 0111 0111 0111 // if only a single WORD is in use in the DWORD.
|
||||
*/
|
||||
#define SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD \
|
||||
(sizeof(u32) * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE)
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This is a count of the numeber of remote nodes that can be represented in a
|
||||
* byte
|
||||
*/
|
||||
#define SCIC_SDS_REMOTE_NODES_PER_BYTE \
|
||||
(SCU_STP_REMOTE_NODE_COUNT * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This is a count of the number of remote nodes that can be represented in a
|
||||
* DWROD
|
||||
*/
|
||||
#define SCIC_SDS_REMOTE_NODES_PER_DWORD \
|
||||
(sizeof(u32) * SCIC_SDS_REMOTE_NODES_PER_BYTE)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This is the number of bits in a remote node group
|
||||
*/
|
||||
#define SCIC_SDS_REMOTE_NODES_BITS_PER_GROUP 4
|
||||
|
||||
#define SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX (0xFFFFFFFF)
|
||||
#define SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE (0x07)
|
||||
#define SCIC_SDS_REMOTE_NODE_TABLE_EMPTY_SLOT_VALUE (0x00)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Expander attached sata remote node count
|
||||
*/
|
||||
#define SCU_STP_REMOTE_NODE_COUNT 3
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Expander or direct attached ssp remote node count
|
||||
*/
|
||||
#define SCU_SSP_REMOTE_NODE_COUNT 1
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Direct attached STP remote node count
|
||||
*/
|
||||
#define SCU_SATA_REMOTE_NODE_COUNT 1
|
||||
|
||||
/**
|
||||
* struct scic_remote_node_table -
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_remote_node_table {
|
||||
/**
|
||||
* This field contains the array size in dwords
|
||||
*/
|
||||
u16 available_nodes_array_size;
|
||||
|
||||
/**
|
||||
* This field contains the array size of the
|
||||
*/
|
||||
u16 group_array_size;
|
||||
|
||||
/**
|
||||
* This field is the array of available remote node entries in bits.
|
||||
* Because of the way STP remote node data is allocated on the SCU hardware
|
||||
* the remote nodes must occupy three consecutive remote node context
|
||||
* entries. For ease of allocation and de-allocation we have broken the
|
||||
* sets of three into a single nibble. When the STP RNi is allocated all
|
||||
* of the bits in the nibble are cleared. This math results in a table size
|
||||
* of MAX_REMOTE_NODES / CONSECUTIVE RNi ENTRIES for STP / 2 entries per byte.
|
||||
*/
|
||||
u32 available_remote_nodes[
|
||||
(SCI_MAX_REMOTE_DEVICES / SCIC_SDS_REMOTE_NODES_PER_DWORD)
|
||||
+ ((SCI_MAX_REMOTE_DEVICES % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0)];
|
||||
|
||||
/**
|
||||
* This field is the nibble selector for the above table. There are three
|
||||
* possible selectors each for fast lookup when trying to find one, two or
|
||||
* three remote node entries.
|
||||
*/
|
||||
u32 remote_node_groups[
|
||||
SCU_STP_REMOTE_NODE_COUNT][
|
||||
(SCI_MAX_REMOTE_DEVICES / (32 * SCU_STP_REMOTE_NODE_COUNT))
|
||||
+ ((SCI_MAX_REMOTE_DEVICES % (32 * SCU_STP_REMOTE_NODE_COUNT)) != 0)];
|
||||
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
void scic_sds_remote_node_table_initialize(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 remote_node_entries);
|
||||
|
||||
u16 scic_sds_remote_node_table_allocate_remote_node(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 remote_node_count);
|
||||
|
||||
void scic_sds_remote_node_table_release_remote_node_index(
|
||||
struct scic_remote_node_table *remote_node_table,
|
||||
u32 remote_node_count,
|
||||
u16 remote_node_index);
|
||||
|
||||
#endif /* _SCIC_SDS_REMOTE_NODE_TABLE_H_ */
|
||||
2179
drivers/scsi/isci/core/scic_sds_request.c
Normal file
2179
drivers/scsi/isci/core/scic_sds_request.c
Normal file
File diff suppressed because it is too large
Load Diff
484
drivers/scsi/isci/core/scic_sds_request.h
Normal file
484
drivers/scsi/isci/core/scic_sds_request.h
Normal file
@@ -0,0 +1,484 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_IO_REQUEST_H_
|
||||
#define _SCIC_SDS_IO_REQUEST_H_
|
||||
|
||||
/**
|
||||
* This file contains the structures, constants and prototypes for the
|
||||
* SCIC_SDS_IO_REQUEST object.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "scic_io_request.h"
|
||||
|
||||
#include "sci_base_request.h"
|
||||
#include "scu_task_context.h"
|
||||
#include "intel_sas.h"
|
||||
|
||||
struct scic_sds_controller;
|
||||
struct scic_sds_remote_device;
|
||||
struct scic_sds_io_request_state_handler;
|
||||
|
||||
/**
|
||||
* enum _SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATES - This enumeration
|
||||
* depicts all of the substates for a task management request to be
|
||||
* performed in the STARTED super-state.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum scic_sds_raw_request_started_task_mgmt_substates {
|
||||
/**
|
||||
* The AWAIT_TC_COMPLETION sub-state indicates that the started raw
|
||||
* task management request is waiting for the transmission of the
|
||||
* initial frame (i.e. command, task, etc.).
|
||||
*/
|
||||
SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION,
|
||||
|
||||
/**
|
||||
* This sub-state indicates that the started task management request
|
||||
* is waiting for the reception of an unsolicited frame
|
||||
* (i.e. response IU).
|
||||
*/
|
||||
SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* enum _SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATES - This enumeration depicts all
|
||||
* of the substates for a SMP request to be performed in the STARTED
|
||||
* super-state.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum scic_sds_smp_request_started_substates {
|
||||
/**
|
||||
* This sub-state indicates that the started task management request
|
||||
* is waiting for the reception of an unsolicited frame
|
||||
* (i.e. response IU).
|
||||
*/
|
||||
SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE,
|
||||
|
||||
/**
|
||||
* The AWAIT_TC_COMPLETION sub-state indicates that the started SMP request is
|
||||
* waiting for the transmission of the initial frame (i.e. command, task, etc.).
|
||||
*/
|
||||
SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SCIC_SDS_IO_REQUEST - This structure contains or references all of
|
||||
* the data necessary to process a task management or normal IO request.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_sds_request {
|
||||
/**
|
||||
* This field indictes the parent object of the request.
|
||||
*/
|
||||
struct sci_base_request parent;
|
||||
|
||||
void *user_request;
|
||||
|
||||
/**
|
||||
* This field simply points to the controller to which this IO request
|
||||
* is associated.
|
||||
*/
|
||||
struct scic_sds_controller *owning_controller;
|
||||
|
||||
/**
|
||||
* This field simply points to the remote device to which this IO request
|
||||
* is associated.
|
||||
*/
|
||||
struct scic_sds_remote_device *target_device;
|
||||
|
||||
/**
|
||||
* This field is utilized to determine if the SCI user is managing
|
||||
* the IO tag for this request or if the core is managing it.
|
||||
*/
|
||||
bool was_tag_assigned_by_user;
|
||||
|
||||
/**
|
||||
* This field indicates the IO tag for this request. The IO tag is
|
||||
* comprised of the task_index and a sequence count. The sequence count
|
||||
* is utilized to help identify tasks from one life to another.
|
||||
*/
|
||||
u16 io_tag;
|
||||
|
||||
/**
|
||||
* This field specifies the protocol being utilized for this
|
||||
* IO request.
|
||||
*/
|
||||
SCIC_TRANSPORT_PROTOCOL protocol;
|
||||
|
||||
/**
|
||||
* This field indicates the completion status taken from the SCUs
|
||||
* completion code. It indicates the completion result for the SCU hardware.
|
||||
*/
|
||||
u32 scu_status;
|
||||
|
||||
/**
|
||||
* This field indicates the completion status returned to the SCI user. It
|
||||
* indicates the users view of the io request completion.
|
||||
*/
|
||||
u32 sci_status;
|
||||
|
||||
/**
|
||||
* This field contains the value to be utilized when posting (e.g. Post_TC,
|
||||
* Post_TC_Abort) this request to the silicon.
|
||||
*/
|
||||
u32 post_context;
|
||||
|
||||
void *command_buffer;
|
||||
void *response_buffer;
|
||||
struct scu_task_context *task_context_buffer;
|
||||
struct scu_sgl_element_pair *sgl_element_pair_buffer;
|
||||
|
||||
/**
|
||||
* This field indicates if this request is a task management request or
|
||||
* normal IO request.
|
||||
*/
|
||||
bool is_task_management_request;
|
||||
|
||||
/**
|
||||
* This field indicates that this request contains an initialized started
|
||||
* substate machine.
|
||||
*/
|
||||
bool has_started_substate_machine;
|
||||
|
||||
/**
|
||||
* This field is a pointer to the stored rx frame data. It is used in STP
|
||||
* internal requests and SMP response frames. If this field is non-NULL the
|
||||
* saved frame must be released on IO request completion.
|
||||
*
|
||||
* @todo In the future do we want to keep a list of RX frame buffers?
|
||||
*/
|
||||
u32 saved_rx_frame_index;
|
||||
|
||||
/**
|
||||
* This field specifies the data necessary to manage the sub-state
|
||||
* machine executed while in the SCI_BASE_REQUEST_STATE_STARTED state.
|
||||
*/
|
||||
struct sci_base_state_machine started_substate_machine;
|
||||
|
||||
/**
|
||||
* This field specifies the current state handlers in place for this
|
||||
* IO Request object. This field is updated each time the request
|
||||
* changes state.
|
||||
*/
|
||||
const struct scic_sds_io_request_state_handler *state_handlers;
|
||||
|
||||
/**
|
||||
* This field in the recorded device sequence for the io request. This is
|
||||
* recorded during the build operation and is compared in the start
|
||||
* operation. If the sequence is different then there was a change of
|
||||
* devices from the build to start operations.
|
||||
*/
|
||||
u8 device_sequence;
|
||||
|
||||
};
|
||||
|
||||
|
||||
typedef enum sci_status
|
||||
(*scic_sds_io_request_frame_handler_t)(struct scic_sds_request *req, u32 frame);
|
||||
|
||||
typedef enum sci_status
|
||||
(*scic_sds_io_request_event_handler_t)(struct scic_sds_request *req, u32 event);
|
||||
|
||||
typedef enum sci_status
|
||||
(*scic_sds_io_request_task_completion_handler_t)(struct scic_sds_request *req, u32 completion_code);
|
||||
|
||||
/**
|
||||
* struct scic_sds_io_request_state_handler - This is the SDS core definition
|
||||
* of the state handlers.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_sds_io_request_state_handler {
|
||||
struct sci_base_request_state_handler parent;
|
||||
|
||||
scic_sds_io_request_task_completion_handler_t tc_completion_handler;
|
||||
scic_sds_io_request_event_handler_t event_handler;
|
||||
scic_sds_io_request_frame_handler_t frame_handler;
|
||||
|
||||
};
|
||||
|
||||
extern const struct sci_base_state scic_sds_request_state_table[];
|
||||
extern const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[];
|
||||
|
||||
extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[];
|
||||
extern const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[];
|
||||
|
||||
extern const struct sci_base_state scic_sds_smp_request_started_substate_table[];
|
||||
extern const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[];
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This macro returns the maximum number of SGL element paris that we will
|
||||
* support in a single IO request.
|
||||
*/
|
||||
#define SCU_MAX_SGL_ELEMENT_PAIRS ((SCU_IO_REQUEST_SGE_COUNT + 1) / 2)
|
||||
|
||||
/**
|
||||
* scic_sds_request_get_controller() -
|
||||
*
|
||||
* This macro will return the controller for this io request object
|
||||
*/
|
||||
#define scic_sds_request_get_controller(this_request) \
|
||||
((this_request)->owning_controller)
|
||||
|
||||
/**
|
||||
* scic_sds_request_get_device() -
|
||||
*
|
||||
* This macro will return the device for this io request object
|
||||
*/
|
||||
#define scic_sds_request_get_device(this_request) \
|
||||
((this_request)->target_device)
|
||||
|
||||
/**
|
||||
* scic_sds_request_get_port() -
|
||||
*
|
||||
* This macro will return the port for this io request object
|
||||
*/
|
||||
#define scic_sds_request_get_port(this_request) \
|
||||
scic_sds_remote_device_get_port(scic_sds_request_get_device(this_request))
|
||||
|
||||
/**
|
||||
* scic_sds_request_get_post_context() -
|
||||
*
|
||||
* This macro returns the constructed post context result for the io request.
|
||||
*/
|
||||
#define scic_sds_request_get_post_context(this_request) \
|
||||
((this_request)->post_context)
|
||||
|
||||
/**
|
||||
* scic_sds_request_get_task_context() -
|
||||
*
|
||||
* This is a helper macro to return the os handle for this request object.
|
||||
*/
|
||||
#define scic_sds_request_get_task_context(request) \
|
||||
((request)->task_context_buffer)
|
||||
|
||||
#define CACHE_LINE_SIZE (64)
|
||||
#define scic_sds_request_align_task_context_buffer(address) \
|
||||
((struct scu_task_context *)(\
|
||||
(((unsigned long)(address)) + (CACHE_LINE_SIZE - 1)) \
|
||||
& ~(CACHE_LINE_SIZE - 1) \
|
||||
))
|
||||
|
||||
/**
|
||||
* scic_sds_request_align_sgl_element_buffer() -
|
||||
*
|
||||
* This macro will align the memory address so that it is correct for the SCU
|
||||
* hardware to DMA the SGL element pairs.
|
||||
*/
|
||||
#define scic_sds_request_align_sgl_element_buffer(address) \
|
||||
((struct scu_sgl_element_pair *)(\
|
||||
((char *)(address)) \
|
||||
+ (\
|
||||
((~(unsigned long)(address)) + 1) \
|
||||
& (sizeof(struct scu_sgl_element_pair) - 1) \
|
||||
) \
|
||||
))
|
||||
|
||||
/**
|
||||
* scic_sds_request_set_status() -
|
||||
*
|
||||
* This macro will set the scu hardware status and sci request completion
|
||||
* status for an io request.
|
||||
*/
|
||||
#define scic_sds_request_set_status(request, scu_status_code, sci_status_code) \
|
||||
{ \
|
||||
(request)->scu_status = (scu_status_code); \
|
||||
(request)->sci_status = (sci_status_code); \
|
||||
}
|
||||
|
||||
#define scic_sds_request_complete(a_request) \
|
||||
((a_request)->state_handlers->parent.complete_handler(&(a_request)->parent))
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* scic_sds_io_request_tc_completion() -
|
||||
*
|
||||
* This macro invokes the core state task completion handler for the
|
||||
* SCIC_SDS_IO_REQUEST_T object.
|
||||
*/
|
||||
#define scic_sds_io_request_tc_completion(this_request, completion_code) \
|
||||
{ \
|
||||
if (this_request->parent.state_machine.current_state_id \
|
||||
== SCI_BASE_REQUEST_STATE_STARTED \
|
||||
&& this_request->has_started_substate_machine \
|
||||
== false) \
|
||||
scic_sds_request_started_state_tc_completion_handler(this_request, completion_code); \
|
||||
else \
|
||||
this_request->state_handlers->tc_completion_handler(this_request, completion_code); \
|
||||
}
|
||||
|
||||
/**
|
||||
* SCU_SGL_ZERO() -
|
||||
*
|
||||
* This macro zeros the hardware SGL element data
|
||||
*/
|
||||
#define SCU_SGL_ZERO(scu_sge) \
|
||||
{ \
|
||||
(scu_sge).length = 0; \
|
||||
(scu_sge).address_lower = 0; \
|
||||
(scu_sge).address_upper = 0; \
|
||||
(scu_sge).address_modifier = 0; \
|
||||
}
|
||||
|
||||
/**
|
||||
* SCU_SGL_COPY() -
|
||||
*
|
||||
* This macro copys the SGL Element data from the host os to the hardware SGL
|
||||
* elment data
|
||||
*/
|
||||
#define SCU_SGL_COPY(os_handle, scu_sge, os_sge) \
|
||||
{ \
|
||||
(scu_sge).length = \
|
||||
scic_cb_sge_get_length_field(os_handle, os_sge); \
|
||||
(scu_sge).address_upper = \
|
||||
upper_32_bits(scic_cb_sge_get_address_field(os_handle, os_sge)); \
|
||||
(scu_sge).address_lower = \
|
||||
lower_32_bits(scic_cb_sge_get_address_field(os_handle, os_sge)); \
|
||||
(scu_sge).address_modifier = 0; \
|
||||
}
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * CORE REQUEST PROTOTYPES
|
||||
* ***************************************************************************** */
|
||||
|
||||
void scic_sds_request_build_sgl(
|
||||
struct scic_sds_request *this_request);
|
||||
|
||||
|
||||
|
||||
void scic_sds_stp_request_assign_buffers(
|
||||
struct scic_sds_request *this_request);
|
||||
|
||||
void scic_sds_smp_request_assign_buffers(
|
||||
struct scic_sds_request *this_request);
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
enum sci_status scic_sds_request_start(
|
||||
struct scic_sds_request *this_request);
|
||||
|
||||
enum sci_status scic_sds_io_request_terminate(
|
||||
struct scic_sds_request *this_request);
|
||||
|
||||
enum sci_status scic_sds_io_request_complete(
|
||||
struct scic_sds_request *this_request);
|
||||
|
||||
void scic_sds_io_request_copy_response(
|
||||
struct scic_sds_request *this_request);
|
||||
|
||||
enum sci_status scic_sds_io_request_event_handler(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 event_code);
|
||||
|
||||
enum sci_status scic_sds_io_request_frame_handler(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 frame_index);
|
||||
|
||||
|
||||
enum sci_status scic_sds_task_request_terminate(
|
||||
struct scic_sds_request *this_request);
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * DEFAULT STATE HANDLERS
|
||||
* ***************************************************************************** */
|
||||
|
||||
enum sci_status scic_sds_request_default_start_handler(
|
||||
struct sci_base_request *this_request);
|
||||
|
||||
|
||||
enum sci_status scic_sds_request_default_complete_handler(
|
||||
struct sci_base_request *this_request);
|
||||
|
||||
enum sci_status scic_sds_request_default_destruct_handler(
|
||||
struct sci_base_request *this_request);
|
||||
|
||||
enum sci_status scic_sds_request_default_tc_completion_handler(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 completion_code);
|
||||
|
||||
enum sci_status scic_sds_request_default_event_handler(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 event_code);
|
||||
|
||||
enum sci_status scic_sds_request_default_frame_handler(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 frame_index);
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STARTED STATE HANDLERS
|
||||
* ***************************************************************************** */
|
||||
|
||||
enum sci_status scic_sds_request_started_state_abort_handler(
|
||||
struct sci_base_request *this_request);
|
||||
|
||||
enum sci_status scic_sds_request_started_state_tc_completion_handler(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 completion_code);
|
||||
|
||||
#endif /* _SCIC_SDS_IO_REQUEST_H_ */
|
||||
410
drivers/scsi/isci/core/scic_sds_smp_remote_device.c
Normal file
410
drivers/scsi/isci/core/scic_sds_smp_remote_device.c
Normal file
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains This file contains the ready substate handlers for a SMP
|
||||
* device.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci_environment.h"
|
||||
#include "scic_user_callback.h"
|
||||
#include "scic_sds_remote_device.h"
|
||||
#include "scic_sds_controller.h"
|
||||
#include "scic_sds_port.h"
|
||||
#include "scic_sds_request.h"
|
||||
#include "scu_event_codes.h"
|
||||
#include "scu_task_context.h"
|
||||
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * SMP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS
|
||||
* ***************************************************************************** */
|
||||
|
||||
/**
|
||||
*
|
||||
* @[in]: device The device the io is sent to.
|
||||
* @[in]: request The io to start.
|
||||
*
|
||||
* This method will handle the start io operation for a SMP device that is in
|
||||
* the idle state. enum sci_status
|
||||
*/
|
||||
static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_handler(
|
||||
struct sci_base_remote_device *device,
|
||||
struct sci_base_request *request)
|
||||
{
|
||||
enum sci_status status;
|
||||
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
|
||||
struct scic_sds_request *io_request = (struct scic_sds_request *)request;
|
||||
|
||||
/* Will the port allow the io request to start? */
|
||||
status = this_device->owning_port->state_handlers->start_io_handler(
|
||||
this_device->owning_port,
|
||||
this_device,
|
||||
io_request
|
||||
);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
status =
|
||||
scic_sds_remote_node_context_start_io(this_device->rnc, io_request);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
status = scic_sds_request_start(io_request);
|
||||
}
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
this_device->working_request = io_request;
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_device->ready_substate_machine,
|
||||
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD
|
||||
);
|
||||
}
|
||||
|
||||
scic_sds_remote_device_start_request(this_device, io_request, status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* * SMP REMOTE DEVICE READY SUBSTATE CMD HANDLERS
|
||||
* ****************************************************************************** */
|
||||
/**
|
||||
*
|
||||
* @device: This is the device object that is receiving the IO.
|
||||
* @request: The io to start.
|
||||
*
|
||||
* This device is already handling a command it can not accept new commands
|
||||
* until this one is complete. enum sci_status
|
||||
*/
|
||||
static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler(
|
||||
struct sci_base_remote_device *device,
|
||||
struct sci_base_request *request)
|
||||
{
|
||||
return SCI_FAILURE_INVALID_STATE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* this is the complete_io_handler for smp device at ready cmd substate.
|
||||
* @device: This is the device object that is receiving the IO.
|
||||
* @request: The io to start.
|
||||
*
|
||||
* enum sci_status
|
||||
*/
|
||||
static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler(
|
||||
struct sci_base_remote_device *device,
|
||||
struct sci_base_request *request)
|
||||
{
|
||||
enum sci_status status;
|
||||
struct scic_sds_remote_device *this_device;
|
||||
struct scic_sds_request *the_request;
|
||||
|
||||
this_device = (struct scic_sds_remote_device *)device;
|
||||
the_request = (struct scic_sds_request *)request;
|
||||
|
||||
status = scic_sds_io_request_complete(the_request);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
status = scic_sds_port_complete_io(
|
||||
this_device->owning_port, this_device, the_request);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
scic_sds_remote_device_decrement_request_count(this_device);
|
||||
sci_base_state_machine_change_state(
|
||||
&this_device->ready_substate_machine,
|
||||
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
|
||||
);
|
||||
} else
|
||||
dev_err(scirdev_to_dev(this_device),
|
||||
"%s: SCIC SDS Remote Device 0x%p io request "
|
||||
"0x%p could not be completd on the port 0x%p "
|
||||
"failed with status %d.\n",
|
||||
__func__,
|
||||
this_device,
|
||||
the_request,
|
||||
this_device->owning_port,
|
||||
status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is frame handler for smp device ready cmd substate.
|
||||
* @this_device: This is the device object that is receiving the frame.
|
||||
* @frame_index: The index for the frame received.
|
||||
*
|
||||
* enum sci_status
|
||||
*/
|
||||
static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 frame_index)
|
||||
{
|
||||
enum sci_status status;
|
||||
|
||||
/*
|
||||
* / The device does not process any UF received from the hardware while
|
||||
* / in this state. All unsolicited frames are forwarded to the io request
|
||||
* / object. */
|
||||
status = scic_sds_io_request_frame_handler(
|
||||
this_device->working_request,
|
||||
frame_index
|
||||
);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
struct scic_sds_remote_device_state_handler
|
||||
scic_sds_smp_remote_device_ready_substate_handler_table[
|
||||
SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES] =
|
||||
{
|
||||
/* SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE */
|
||||
{
|
||||
{
|
||||
scic_sds_remote_device_default_start_handler,
|
||||
scic_sds_remote_device_ready_state_stop_handler,
|
||||
scic_sds_remote_device_default_fail_handler,
|
||||
scic_sds_remote_device_default_destruct_handler,
|
||||
scic_sds_remote_device_default_reset_handler,
|
||||
scic_sds_remote_device_default_reset_complete_handler,
|
||||
scic_sds_smp_remote_device_ready_idle_substate_start_io_handler,
|
||||
scic_sds_remote_device_default_complete_request_handler,
|
||||
scic_sds_remote_device_default_continue_request_handler,
|
||||
scic_sds_remote_device_default_start_request_handler,
|
||||
scic_sds_remote_device_default_complete_request_handler
|
||||
},
|
||||
scic_sds_remote_device_default_suspend_handler,
|
||||
scic_sds_remote_device_default_resume_handler,
|
||||
scic_sds_remote_device_general_event_handler,
|
||||
scic_sds_remote_device_default_frame_handler
|
||||
},
|
||||
/* SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD */
|
||||
{
|
||||
{
|
||||
scic_sds_remote_device_default_start_handler,
|
||||
scic_sds_remote_device_ready_state_stop_handler,
|
||||
scic_sds_remote_device_default_fail_handler,
|
||||
scic_sds_remote_device_default_destruct_handler,
|
||||
scic_sds_remote_device_default_reset_handler,
|
||||
scic_sds_remote_device_default_reset_complete_handler,
|
||||
scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler,
|
||||
scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler,
|
||||
scic_sds_remote_device_default_continue_request_handler,
|
||||
scic_sds_remote_device_default_start_request_handler,
|
||||
scic_sds_remote_device_default_complete_request_handler
|
||||
},
|
||||
scic_sds_remote_device_default_suspend_handler,
|
||||
scic_sds_remote_device_default_resume_handler,
|
||||
scic_sds_remote_device_general_event_handler,
|
||||
scic_sds_smp_remote_device_ready_cmd_substate_frame_handler
|
||||
}
|
||||
};
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the enter and exit functions for the
|
||||
* struct scic_sds_remote_device ready substate machine.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "scic_remote_device.h"
|
||||
#include "scic_user_callback.h"
|
||||
#include "scic_sds_remote_device.h"
|
||||
#include "scic_sds_controller.h"
|
||||
#include "scic_sds_port.h"
|
||||
#include "sci_util.h"
|
||||
#include "sci_environment.h"
|
||||
|
||||
/**
|
||||
*
|
||||
* @object: This is the struct sci_base_object which is cast into a
|
||||
* struct scic_sds_remote_device.
|
||||
*
|
||||
* This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE enter method.
|
||||
* This method sets the ready cmd substate handlers and reports the device as
|
||||
* ready. none
|
||||
*/
|
||||
static void scic_sds_smp_remote_device_ready_idle_substate_enter(
|
||||
struct sci_base_object *object)
|
||||
{
|
||||
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_device,
|
||||
scic_sds_smp_remote_device_ready_substate_handler_table,
|
||||
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
|
||||
);
|
||||
|
||||
scic_cb_remote_device_ready(
|
||||
scic_sds_remote_device_get_controller(this_device), this_device);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @object: This is the struct sci_base_object which is cast into a
|
||||
* struct scic_sds_remote_device.
|
||||
*
|
||||
* This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD enter method. This
|
||||
* method sets the remote device objects ready cmd substate handlers, and
|
||||
* notify core user that the device is not ready. none
|
||||
*/
|
||||
static void scic_sds_smp_remote_device_ready_cmd_substate_enter(
|
||||
struct sci_base_object *object)
|
||||
{
|
||||
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
|
||||
|
||||
BUG_ON(this_device->working_request == NULL);
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_device,
|
||||
scic_sds_smp_remote_device_ready_substate_handler_table,
|
||||
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD
|
||||
);
|
||||
|
||||
scic_cb_remote_device_not_ready(
|
||||
scic_sds_remote_device_get_controller(this_device),
|
||||
this_device,
|
||||
SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @object: This is the struct sci_base_object which is cast into a
|
||||
* struct scic_sds_remote_device.
|
||||
*
|
||||
* This is the SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_CMD exit method. none
|
||||
*/
|
||||
static void scic_sds_smp_remote_device_ready_cmd_substate_exit(
|
||||
struct sci_base_object *object)
|
||||
{
|
||||
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
|
||||
|
||||
this_device->working_request = NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[] = {
|
||||
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
|
||||
.enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter,
|
||||
},
|
||||
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
|
||||
.enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter,
|
||||
.exit_state = scic_sds_smp_remote_device_ready_cmd_substate_exit,
|
||||
},
|
||||
};
|
||||
669
drivers/scsi/isci/core/scic_sds_smp_request.c
Normal file
669
drivers/scsi/isci/core/scic_sds_smp_request.c
Normal file
@@ -0,0 +1,669 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "intel_sas.h"
|
||||
#include "sci_base_state_machine.h"
|
||||
#include "scic_controller.h"
|
||||
#include "scic_remote_device.h"
|
||||
#include "scic_sds_controller.h"
|
||||
#include "scic_sds_remote_device.h"
|
||||
#include "scic_sds_request.h"
|
||||
#include "scic_sds_smp_request.h"
|
||||
#include "sci_environment.h"
|
||||
#include "sci_util.h"
|
||||
#include "scu_completion_codes.h"
|
||||
#include "scu_task_context.h"
|
||||
|
||||
static void scu_smp_request_construct_task_context(
|
||||
struct scic_sds_request *this_request,
|
||||
struct smp_request *smp_request);
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This method return the memory space required for STP PIO requests. u32
|
||||
*/
|
||||
u32 scic_sds_smp_request_get_object_size(void)
|
||||
{
|
||||
return sizeof(struct scic_sds_request)
|
||||
+ sizeof(struct smp_request)
|
||||
+ sizeof(struct smp_response)
|
||||
+ sizeof(struct scu_task_context);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_sds_smp_request_get_command_buffer() -
|
||||
*
|
||||
* This macro returns the address of the smp command buffer in the smp request
|
||||
* memory. No need to cast to SMP request type.
|
||||
*/
|
||||
#define scic_sds_smp_request_get_command_buffer(memory) \
|
||||
(((char *)(memory)) + sizeof(struct scic_sds_request))
|
||||
|
||||
/**
|
||||
* scic_sds_smp_request_get_response_buffer() -
|
||||
*
|
||||
* This macro returns the address of the smp response buffer in the smp request
|
||||
* memory.
|
||||
*/
|
||||
#define scic_sds_smp_request_get_response_buffer(memory) \
|
||||
(((char *)(scic_sds_smp_request_get_command_buffer(memory))) \
|
||||
+ sizeof(struct smp_request))
|
||||
|
||||
/**
|
||||
* scic_sds_smp_request_get_task_context_buffer() -
|
||||
*
|
||||
* This macro returs the task context buffer for the SMP request.
|
||||
*/
|
||||
#define scic_sds_smp_request_get_task_context_buffer(memory) \
|
||||
((struct scu_task_context *)(\
|
||||
((char *)(scic_sds_smp_request_get_response_buffer(memory))) \
|
||||
+ sizeof(struct smp_response) \
|
||||
))
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This method build the remainder of the IO request object.
|
||||
* @this_request: This parameter specifies the request object being constructed.
|
||||
*
|
||||
* The scic_sds_general_request_construct() must be called before this call is
|
||||
* valid. none
|
||||
*/
|
||||
|
||||
void scic_sds_smp_request_assign_buffers(
|
||||
struct scic_sds_request *this_request)
|
||||
{
|
||||
/* Assign all of the buffer pointers */
|
||||
this_request->command_buffer =
|
||||
scic_sds_smp_request_get_command_buffer(this_request);
|
||||
this_request->response_buffer =
|
||||
scic_sds_smp_request_get_response_buffer(this_request);
|
||||
this_request->sgl_element_pair_buffer = NULL;
|
||||
|
||||
if (this_request->was_tag_assigned_by_user == false) {
|
||||
this_request->task_context_buffer =
|
||||
scic_sds_smp_request_get_task_context_buffer(this_request);
|
||||
this_request->task_context_buffer =
|
||||
scic_sds_request_align_task_context_buffer(this_request->task_context_buffer);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* This method is called by the SCI user to build an SMP IO request.
|
||||
*
|
||||
* - The user must have previously called scic_io_request_construct() on the
|
||||
* supplied IO request. Indicate if the controller successfully built the IO
|
||||
* request. SCI_SUCCESS This value is returned if the IO request was
|
||||
* successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned
|
||||
* if the remote_device does not support the SMP protocol.
|
||||
* SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not
|
||||
* properly set the association between the SCIC IO request and the user's IO
|
||||
* request. Please refer to the sci_object_set_association() routine for more
|
||||
* information.
|
||||
*/
|
||||
enum sci_status scic_io_request_construct_smp(
|
||||
struct scic_sds_request *sci_req)
|
||||
{
|
||||
struct smp_request *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL);
|
||||
|
||||
if (!smp_req)
|
||||
return SCI_FAILURE_INSUFFICIENT_RESOURCES;
|
||||
|
||||
sci_req->protocol = SCIC_SMP_PROTOCOL;
|
||||
sci_req->has_started_substate_machine = true;
|
||||
|
||||
/* Construct the started sub-state machine. */
|
||||
sci_base_state_machine_construct(
|
||||
&sci_req->started_substate_machine,
|
||||
&sci_req->parent.parent,
|
||||
scic_sds_smp_request_started_substate_table,
|
||||
SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
|
||||
);
|
||||
|
||||
/* Construct the SMP SCU Task Context */
|
||||
memcpy(smp_req, sci_req->command_buffer, sizeof(*smp_req));
|
||||
|
||||
/*
|
||||
* Look at the SMP requests' header fields; for certain SAS 1.x SMP
|
||||
* functions under SAS 2.0, a zero request length really indicates
|
||||
* a non-zero default length. */
|
||||
if (smp_req->header.request_length == 0) {
|
||||
switch (smp_req->header.function) {
|
||||
case SMP_FUNCTION_DISCOVER:
|
||||
case SMP_FUNCTION_REPORT_PHY_ERROR_LOG:
|
||||
case SMP_FUNCTION_REPORT_PHY_SATA:
|
||||
case SMP_FUNCTION_REPORT_ROUTE_INFORMATION:
|
||||
smp_req->header.request_length = 2;
|
||||
break;
|
||||
case SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION:
|
||||
case SMP_FUNCTION_PHY_CONTROL:
|
||||
case SMP_FUNCTION_PHY_TEST:
|
||||
smp_req->header.request_length = 9;
|
||||
break;
|
||||
/* Default - zero is a valid default for 2.0. */
|
||||
}
|
||||
}
|
||||
|
||||
scu_smp_request_construct_task_context(sci_req, smp_req);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&sci_req->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_CONSTRUCTED
|
||||
);
|
||||
|
||||
kfree(smp_req);
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by the SCI user to build an SMP pass-through IO
|
||||
* request.
|
||||
* @scic_smp_request: This parameter specifies the handle to the io request
|
||||
* object to be built.
|
||||
* @passthru_cb: This parameter specifies the pointer to the callback structure
|
||||
* that contains the function pointers
|
||||
*
|
||||
* - The user must have previously called scic_io_request_construct() on the
|
||||
* supplied IO request. Indicate if the controller successfully built the IO
|
||||
* request.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This method will fill in the SCU Task Context for a SMP request. The
|
||||
* following important settings are utilized: -# task_type ==
|
||||
* SCU_TASK_TYPE_SMP. This simply indicates that a normal request type
|
||||
* (i.e. non-raw frame) is being utilized to perform task management. -#
|
||||
* control_frame == 1. This ensures that the proper endianess is set so
|
||||
* that the bytes are transmitted in the right order for a smp request frame.
|
||||
* @this_request: This parameter specifies the smp request object being
|
||||
* constructed.
|
||||
*
|
||||
*/
|
||||
static void scu_smp_request_construct_task_context(
|
||||
struct scic_sds_request *this_request,
|
||||
struct smp_request *smp_request)
|
||||
{
|
||||
dma_addr_t physical_address;
|
||||
struct scic_sds_controller *owning_controller;
|
||||
struct scic_sds_remote_device *target_device;
|
||||
struct scic_sds_port *target_port;
|
||||
struct scu_task_context *task_context;
|
||||
|
||||
/* byte swap the smp request. */
|
||||
scic_word_copy_with_swap(
|
||||
this_request->command_buffer,
|
||||
(u32 *)smp_request,
|
||||
sizeof(struct smp_request) / sizeof(u32)
|
||||
);
|
||||
|
||||
task_context = scic_sds_request_get_task_context(this_request);
|
||||
|
||||
owning_controller = scic_sds_request_get_controller(this_request);
|
||||
target_device = scic_sds_request_get_device(this_request);
|
||||
target_port = scic_sds_request_get_port(this_request);
|
||||
|
||||
/*
|
||||
* Fill in the TC with the its required data
|
||||
* 00h */
|
||||
task_context->priority = 0;
|
||||
task_context->initiator_request = 1;
|
||||
task_context->connection_rate =
|
||||
scic_remote_device_get_connection_rate(target_device);
|
||||
task_context->protocol_engine_index =
|
||||
scic_sds_controller_get_protocol_engine_group(owning_controller);
|
||||
task_context->logical_port_index =
|
||||
scic_sds_port_get_index(target_port);
|
||||
task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP;
|
||||
task_context->abort = 0;
|
||||
task_context->valid = SCU_TASK_CONTEXT_VALID;
|
||||
task_context->context_type = SCU_TASK_CONTEXT_TYPE;
|
||||
|
||||
/* 04h */
|
||||
task_context->remote_node_index = this_request->target_device->rnc->remote_node_index;
|
||||
task_context->command_code = 0;
|
||||
task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST;
|
||||
|
||||
/* 08h */
|
||||
task_context->link_layer_control = 0;
|
||||
task_context->do_not_dma_ssp_good_response = 1;
|
||||
task_context->strict_ordering = 0;
|
||||
task_context->control_frame = 1;
|
||||
task_context->timeout_enable = 0;
|
||||
task_context->block_guard_enable = 0;
|
||||
|
||||
/* 0ch */
|
||||
task_context->address_modifier = 0;
|
||||
|
||||
/* 10h */
|
||||
task_context->ssp_command_iu_length = smp_request->header.request_length;
|
||||
|
||||
/* 14h */
|
||||
task_context->transfer_length_bytes = 0;
|
||||
|
||||
/*
|
||||
* 18h ~ 30h, protocol specific
|
||||
* since commandIU has been build by framework at this point, we just
|
||||
* copy the frist DWord from command IU to this location. */
|
||||
memcpy((void *)(&task_context->type.smp), this_request->command_buffer, sizeof(u32));
|
||||
|
||||
/*
|
||||
* 40h
|
||||
* "For SMP you could program it to zero. We would prefer that way so that
|
||||
* done code will be consistent." - Venki */
|
||||
task_context->task_phase = 0;
|
||||
|
||||
if (this_request->was_tag_assigned_by_user) {
|
||||
/* Build the task context now since we have already read the data */
|
||||
this_request->post_context = (
|
||||
SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
|
||||
| (
|
||||
scic_sds_controller_get_protocol_engine_group(owning_controller)
|
||||
<< SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
|
||||
)
|
||||
| (
|
||||
scic_sds_port_get_index(target_port)
|
||||
<< SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
|
||||
)
|
||||
| scic_sds_io_tag_get_index(this_request->io_tag)
|
||||
);
|
||||
} else {
|
||||
/* Build the task context now since we have already read the data */
|
||||
this_request->post_context = (
|
||||
SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
|
||||
| (
|
||||
scic_sds_controller_get_protocol_engine_group(owning_controller)
|
||||
<< SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
|
||||
)
|
||||
| (
|
||||
scic_sds_port_get_index(target_port)
|
||||
<< SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
|
||||
)
|
||||
/* This is not assigned because we have to wait until we get a TCi */
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the physical address for the command buffer to the SCU Task Context
|
||||
* command buffer should not contain command header. */
|
||||
scic_cb_io_request_get_physical_address(
|
||||
scic_sds_request_get_controller(this_request),
|
||||
this_request,
|
||||
((char *)(this_request->command_buffer) + sizeof(u32)),
|
||||
&physical_address
|
||||
);
|
||||
|
||||
task_context->command_iu_upper =
|
||||
upper_32_bits(physical_address);
|
||||
task_context->command_iu_lower =
|
||||
lower_32_bits(physical_address);
|
||||
|
||||
|
||||
/* SMP response comes as UF, so no need to set response IU address. */
|
||||
task_context->response_iu_upper = 0;
|
||||
task_context->response_iu_lower = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method processes an unsolicited frame while the SMP request is waiting
|
||||
* for a response frame. It will copy the response data, release the
|
||||
* unsolicited frame, and transition the request to the
|
||||
* SCI_BASE_REQUEST_STATE_COMPLETED state.
|
||||
* @this_request: This parameter specifies the request for which the
|
||||
* unsolicited frame was received.
|
||||
* @frame_index: This parameter indicates the unsolicited frame index that
|
||||
* should contain the response.
|
||||
*
|
||||
* This method returns an indication of whether the response frame was handled
|
||||
* successfully or not. SCI_SUCCESS Currently this value is always returned and
|
||||
* indicates successful processing of the TC response.
|
||||
*/
|
||||
static enum sci_status scic_sds_smp_request_await_response_frame_handler(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 frame_index)
|
||||
{
|
||||
enum sci_status status;
|
||||
void *frame_header;
|
||||
struct smp_response_header *this_frame_header;
|
||||
u8 *user_smp_buffer = this_request->response_buffer;
|
||||
|
||||
status = scic_sds_unsolicited_frame_control_get_header(
|
||||
&(scic_sds_request_get_controller(this_request)->uf_control),
|
||||
frame_index,
|
||||
&frame_header
|
||||
);
|
||||
|
||||
/* byte swap the header. */
|
||||
scic_word_copy_with_swap(
|
||||
(u32 *)user_smp_buffer,
|
||||
frame_header,
|
||||
sizeof(struct smp_response_header) / sizeof(u32)
|
||||
);
|
||||
this_frame_header = (struct smp_response_header *)user_smp_buffer;
|
||||
|
||||
if (this_frame_header->smp_frame_type == SMP_FRAME_TYPE_RESPONSE) {
|
||||
void *smp_response_buffer;
|
||||
|
||||
status = scic_sds_unsolicited_frame_control_get_buffer(
|
||||
&(scic_sds_request_get_controller(this_request)->uf_control),
|
||||
frame_index,
|
||||
&smp_response_buffer
|
||||
);
|
||||
|
||||
scic_word_copy_with_swap(
|
||||
(u32 *)(user_smp_buffer + sizeof(struct smp_response_header)),
|
||||
smp_response_buffer,
|
||||
sizeof(union smp_response_body) / sizeof(u32)
|
||||
);
|
||||
if (this_frame_header->function == SMP_FUNCTION_DISCOVER) {
|
||||
struct smp_response *this_smp_response;
|
||||
|
||||
this_smp_response = (struct smp_response *)user_smp_buffer;
|
||||
|
||||
/*
|
||||
* Some expanders only report an attached SATA device, and
|
||||
* not an STP target. Since the core depends on the STP
|
||||
* target attribute to correctly build I/O, set the bit now
|
||||
* if necessary. */
|
||||
if (this_smp_response->response.discover.protocols.u.bits.attached_sata_device
|
||||
&& !this_smp_response->response.discover.protocols.u.bits.attached_stp_target) {
|
||||
this_smp_response->response.discover.protocols.u.bits.attached_stp_target = 1;
|
||||
|
||||
dev_dbg(scic_to_dev(this_request->owning_controller),
|
||||
"%s: scic_sds_smp_request_await_response_frame_handler(0x%p) Found SATA dev, setting STP bit.\n",
|
||||
__func__, this_request);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't need to copy to user space. User instead will refer to
|
||||
* core request's response buffer. */
|
||||
|
||||
/*
|
||||
* copy the smp response to framework smp request's response buffer.
|
||||
* scic_sds_smp_request_copy_response(this_request); */
|
||||
|
||||
scic_sds_request_set_status(
|
||||
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->started_substate_machine,
|
||||
SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
|
||||
);
|
||||
} else {
|
||||
/* This was not a response frame why did it get forwarded? */
|
||||
dev_err(scic_to_dev(this_request->owning_controller),
|
||||
"%s: SCIC SMP Request 0x%p received unexpected frame "
|
||||
"%d type 0x%02x\n",
|
||||
__func__,
|
||||
this_request,
|
||||
frame_index,
|
||||
this_frame_header->smp_frame_type);
|
||||
|
||||
scic_sds_request_set_status(
|
||||
this_request,
|
||||
SCU_TASK_DONE_SMP_FRM_TYPE_ERR,
|
||||
SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
}
|
||||
|
||||
scic_sds_controller_release_frame(
|
||||
this_request->owning_controller, frame_index
|
||||
);
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method processes an abnormal TC completion while the SMP request is
|
||||
* waiting for a response frame. It decides what happened to the IO based
|
||||
* on TC completion status.
|
||||
* @this_request: This parameter specifies the request for which the TC
|
||||
* completion was received.
|
||||
* @completion_code: This parameter indicates the completion status information
|
||||
* for the TC.
|
||||
*
|
||||
* Indicate if the tc completion handler was successful. SCI_SUCCESS currently
|
||||
* this method always returns success.
|
||||
*/
|
||||
static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 completion_code)
|
||||
{
|
||||
switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
|
||||
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
|
||||
/*
|
||||
* In the AWAIT RESPONSE state, any TC completion is unexpected.
|
||||
* but if the TC has success status, we complete the IO anyway. */
|
||||
scic_sds_request_set_status(
|
||||
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
break;
|
||||
|
||||
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR):
|
||||
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR):
|
||||
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR):
|
||||
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR):
|
||||
/*
|
||||
* These status has been seen in a specific LSI expander, which sometimes
|
||||
* is not able to send smp response within 2 ms. This causes our hardware
|
||||
* break the connection and set TC completion with one of these SMP_XXX_XX_ERR
|
||||
* status. For these type of error, we ask scic user to retry the request. */
|
||||
scic_sds_request_set_status(
|
||||
this_request, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* All other completion status cause the IO to be complete. If a NAK
|
||||
* was received, then it is up to the user to retry the request. */
|
||||
scic_sds_request_set_status(
|
||||
this_request,
|
||||
SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
|
||||
SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method processes the completions transport layer (TL) status to
|
||||
* determine if the SMP request was sent successfully. If the SMP request
|
||||
* was sent successfully, then the state for the SMP request transits to
|
||||
* waiting for a response frame.
|
||||
* @this_request: This parameter specifies the request for which the TC
|
||||
* completion was received.
|
||||
* @completion_code: This parameter indicates the completion status information
|
||||
* for the TC.
|
||||
*
|
||||
* Indicate if the tc completion handler was successful. SCI_SUCCESS currently
|
||||
* this method always returns success.
|
||||
*/
|
||||
static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 completion_code)
|
||||
{
|
||||
switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
|
||||
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
|
||||
scic_sds_request_set_status(
|
||||
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* All other completion status cause the IO to be complete. If a NAK
|
||||
* was received, then it is up to the user to retry the request. */
|
||||
scic_sds_request_set_status(
|
||||
this_request,
|
||||
SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
|
||||
SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = {
|
||||
[SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = {
|
||||
.parent.start_handler = scic_sds_request_default_start_handler,
|
||||
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
|
||||
.parent.complete_handler = scic_sds_request_default_complete_handler,
|
||||
.parent.destruct_handler = scic_sds_request_default_destruct_handler,
|
||||
.tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler,
|
||||
.event_handler = scic_sds_request_default_event_handler,
|
||||
.frame_handler = scic_sds_smp_request_await_response_frame_handler,
|
||||
},
|
||||
[SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = {
|
||||
.parent.start_handler = scic_sds_request_default_start_handler,
|
||||
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
|
||||
.parent.complete_handler = scic_sds_request_default_complete_handler,
|
||||
.parent.destruct_handler = scic_sds_request_default_destruct_handler,
|
||||
.tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler,
|
||||
.event_handler = scic_sds_request_default_event_handler,
|
||||
.frame_handler = scic_sds_request_default_frame_handler,
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This method performs the actions required when entering the
|
||||
* SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This
|
||||
* includes setting the IO request state handlers for this sub-state.
|
||||
* @object: This parameter specifies the request object for which the sub-state
|
||||
* change is occuring.
|
||||
*
|
||||
* none.
|
||||
*/
|
||||
static void scic_sds_smp_request_started_await_response_substate_enter(
|
||||
struct sci_base_object *object)
|
||||
{
|
||||
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_request,
|
||||
scic_sds_smp_request_started_substate_handler_table,
|
||||
SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method performs the actions required when entering the
|
||||
* SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION sub-state.
|
||||
* This includes setting the SMP request state handlers for this sub-state.
|
||||
* @object: This parameter specifies the request object for which the sub-state
|
||||
* change is occuring.
|
||||
*
|
||||
* none.
|
||||
*/
|
||||
static void scic_sds_smp_request_started_await_tc_completion_substate_enter(
|
||||
struct sci_base_object *object)
|
||||
{
|
||||
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_request,
|
||||
scic_sds_smp_request_started_substate_handler_table,
|
||||
SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
|
||||
);
|
||||
}
|
||||
|
||||
const struct sci_base_state scic_sds_smp_request_started_substate_table[] = {
|
||||
[SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = {
|
||||
.enter_state = scic_sds_smp_request_started_await_response_substate_enter,
|
||||
},
|
||||
[SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = {
|
||||
.enter_state = scic_sds_smp_request_started_await_tc_completion_substate_enter,
|
||||
},
|
||||
};
|
||||
|
||||
70
drivers/scsi/isci/core/scic_sds_smp_request.h
Normal file
70
drivers/scsi/isci/core/scic_sds_smp_request.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _SCIC_SDS_SMP_REQUEST_T_
|
||||
#define _SCIC_SDS_SMP_REQUEST_T_
|
||||
|
||||
#include "intel_sas.h"
|
||||
#include "sci_types.h"
|
||||
#include "scic_sds_request.h"
|
||||
|
||||
|
||||
u32 scic_sds_smp_request_get_object_size(void);
|
||||
|
||||
|
||||
void scic_sds_smp_request_copy_response(
|
||||
struct scic_sds_request *this_request);
|
||||
|
||||
#endif /* _SCIC_SDS_SMP_REQUEST_T_ */
|
||||
|
||||
340
drivers/scsi/isci/core/scic_sds_ssp_request.c
Normal file
340
drivers/scsi/isci/core/scic_sds_ssp_request.c
Normal file
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the task management substate handlers for the
|
||||
* SCIC_SDS_IO_REQUEST object.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "intel_sas.h"
|
||||
#include "sci_environment.h"
|
||||
#include "scic_sds_request.h"
|
||||
#include "scic_controller.h"
|
||||
#include "scic_sds_controller.h"
|
||||
#include "scu_completion_codes.h"
|
||||
#include "scu_task_context.h"
|
||||
|
||||
/**
|
||||
* This method processes the completions transport layer (TL) status to
|
||||
* determine if the RAW task management frame was sent successfully. If the
|
||||
* raw frame was sent successfully, then the state for the task request
|
||||
* transitions to waiting for a response frame.
|
||||
* @this_request: This parameter specifies the request for which the TC
|
||||
* completion was received.
|
||||
* @completion_code: This parameter indicates the completion status information
|
||||
* for the TC.
|
||||
*
|
||||
* Indicate if the tc completion handler was successful. SCI_SUCCESS currently
|
||||
* this method always returns success.
|
||||
*/
|
||||
static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 completion_code)
|
||||
{
|
||||
switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
|
||||
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
|
||||
scic_sds_request_set_status(
|
||||
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->started_substate_machine,
|
||||
SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
|
||||
);
|
||||
break;
|
||||
|
||||
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO):
|
||||
/*
|
||||
* Currently, the decision is to simply allow the task request to
|
||||
* timeout if the task IU wasn't received successfully.
|
||||
* There is a potential for receiving multiple task responses if we
|
||||
* decide to send the task IU again. */
|
||||
dev_warn(scic_to_dev(this_request->owning_controller),
|
||||
"%s: TaskRequest:0x%p CompletionCode:%x - "
|
||||
"ACK/NAK timeout\n",
|
||||
__func__,
|
||||
this_request,
|
||||
completion_code);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->started_substate_machine,
|
||||
SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* All other completion status cause the IO to be complete. If a NAK
|
||||
* was received, then it is up to the user to retry the request. */
|
||||
scic_sds_request_set_status(
|
||||
this_request,
|
||||
SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
|
||||
SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is responsible for processing a terminate/abort request for this
|
||||
* TC while the request is waiting for the task management response
|
||||
* unsolicited frame.
|
||||
* @this_request: This parameter specifies the request for which the
|
||||
* termination was requested.
|
||||
*
|
||||
* This method returns an indication as to whether the abort request was
|
||||
* successfully handled. need to update to ensure the received UF doesn't cause
|
||||
* damage to subsequent requests (i.e. put the extended tag in a holding
|
||||
* pattern for this particular device).
|
||||
*/
|
||||
static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler(
|
||||
struct sci_base_request *request)
|
||||
{
|
||||
struct scic_sds_request *this_request = (struct scic_sds_request *)request;
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_ABORTING
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method processes an unsolicited frame while the task mgmt request is
|
||||
* waiting for a response frame. It will copy the response data, release
|
||||
* the unsolicited frame, and transition the request to the
|
||||
* SCI_BASE_REQUEST_STATE_COMPLETED state.
|
||||
* @this_request: This parameter specifies the request for which the
|
||||
* unsolicited frame was received.
|
||||
* @frame_index: This parameter indicates the unsolicited frame index that
|
||||
* should contain the response.
|
||||
*
|
||||
* This method returns an indication of whether the TC response frame was
|
||||
* handled successfully or not. SCI_SUCCESS Currently this value is always
|
||||
* returned and indicates successful processing of the TC response. Should
|
||||
* probably update to check frame type and make sure it is a response frame.
|
||||
*/
|
||||
static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 frame_index)
|
||||
{
|
||||
scic_sds_io_request_copy_response(this_request);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
|
||||
scic_sds_controller_release_frame(
|
||||
this_request->owning_controller, frame_index
|
||||
);
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[] = {
|
||||
[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = {
|
||||
.parent.start_handler = scic_sds_request_default_start_handler,
|
||||
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
|
||||
.parent.complete_handler = scic_sds_request_default_complete_handler,
|
||||
.parent.destruct_handler = scic_sds_request_default_destruct_handler,
|
||||
.tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler,
|
||||
.event_handler = scic_sds_request_default_event_handler,
|
||||
.frame_handler = scic_sds_request_default_frame_handler,
|
||||
},
|
||||
[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = {
|
||||
.parent.start_handler = scic_sds_request_default_start_handler,
|
||||
.parent.abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler,
|
||||
.parent.complete_handler = scic_sds_request_default_complete_handler,
|
||||
.parent.destruct_handler = scic_sds_request_default_destruct_handler,
|
||||
.tc_completion_handler = scic_sds_request_default_tc_completion_handler,
|
||||
.event_handler = scic_sds_request_default_event_handler,
|
||||
.frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler,
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the enter/exit methods associated with each of the task
|
||||
* management raw request states. For more information on the task
|
||||
* management request state machine please refer to scic_sds_io_request.h
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "scic_sds_request.h"
|
||||
#include "sci_base_state_machine.h"
|
||||
|
||||
/**
|
||||
* This method performs the actions required when entering the
|
||||
* SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
|
||||
* sub-state. This includes setting the IO request state handlers for this
|
||||
* sub-state.
|
||||
* @object: This parameter specifies the request object for which the sub-state
|
||||
* change is occuring.
|
||||
*
|
||||
* none.
|
||||
*/
|
||||
static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter(
|
||||
struct sci_base_object *object)
|
||||
{
|
||||
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_request,
|
||||
scic_sds_ssp_task_request_started_substate_handler_table,
|
||||
SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method performs the actions required when entering the
|
||||
* SCIC_SDS_IO_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This
|
||||
* includes setting the IO request state handlers for this sub-state.
|
||||
* @object: This parameter specifies the request object for which the sub-state
|
||||
* change is occuring.
|
||||
*
|
||||
* none.
|
||||
*/
|
||||
static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter(
|
||||
struct sci_base_object *object)
|
||||
{
|
||||
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_request,
|
||||
scic_sds_ssp_task_request_started_substate_handler_table,
|
||||
SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
|
||||
);
|
||||
}
|
||||
|
||||
const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[] = {
|
||||
[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = {
|
||||
.enter_state = scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter,
|
||||
},
|
||||
[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = {
|
||||
.enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter,
|
||||
},
|
||||
};
|
||||
|
||||
838
drivers/scsi/isci/core/scic_sds_stp_packet_request.c
Normal file
838
drivers/scsi/isci/core/scic_sds_stp_packet_request.c
Normal file
@@ -0,0 +1,838 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
|
||||
#include "intel_ata.h"
|
||||
#include "intel_sas.h"
|
||||
#include "intel_sata.h"
|
||||
#include "intel_sat.h"
|
||||
#include "sati_translator_sequence.h"
|
||||
#include "sci_base_state.h"
|
||||
#include "scic_controller.h"
|
||||
#include "scic_remote_device.h"
|
||||
#include "scic_sds_controller.h"
|
||||
#include "scic_sds_remote_device.h"
|
||||
#include "scic_sds_request.h"
|
||||
#include "scic_sds_stp_packet_request.h"
|
||||
#include "scic_user_callback.h"
|
||||
#include "sci_util.h"
|
||||
#include "scu_completion_codes.h"
|
||||
#include "scu_task_context.h"
|
||||
|
||||
|
||||
/**
|
||||
* This method will fill in the SCU Task Context for a PACKET fis. And
|
||||
* construct the request STARTED sub-state machine for Packet Protocol IO.
|
||||
* @this_request: This parameter specifies the stp packet request object being
|
||||
* constructed.
|
||||
*
|
||||
*/
|
||||
enum sci_status scic_sds_stp_packet_request_construct(
|
||||
struct scic_sds_request *this_request)
|
||||
{
|
||||
struct sata_fis_reg_h2d *h2d_fis =
|
||||
scic_stp_io_request_get_h2d_reg_address(
|
||||
this_request
|
||||
);
|
||||
|
||||
/*
|
||||
* Work around, we currently only support PACKET DMA protocol, so we
|
||||
* need to make change to Packet Fis features field. */
|
||||
h2d_fis->features = h2d_fis->features | ATA_PACKET_FEATURE_DMA;
|
||||
|
||||
scic_sds_stp_non_ncq_request_construct(this_request);
|
||||
|
||||
/* Build the Packet Fis task context structure */
|
||||
scu_stp_raw_request_construct_task_context(
|
||||
(struct scic_sds_stp_request *)this_request,
|
||||
this_request->task_context_buffer
|
||||
);
|
||||
|
||||
sci_base_state_machine_construct(
|
||||
&this_request->started_substate_machine,
|
||||
&this_request->parent.parent,
|
||||
scic_sds_stp_packet_request_started_substate_table,
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
|
||||
);
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method will fill in the SCU Task Context for a Packet request command
|
||||
* phase in PACKET DMA DATA (IN/OUT) type. The following important settings
|
||||
* are utilized: -# task_type == SCU_TASK_TYPE_PACKET_DMA. This simply
|
||||
* indicates that a normal request type (i.e. non-raw frame) is being
|
||||
* utilized to perform task management. -# control_frame == 1. This ensures
|
||||
* that the proper endianess is set so that the bytes are transmitted in the
|
||||
* right order for a smp request frame.
|
||||
* @this_request: This parameter specifies the smp request object being
|
||||
* constructed.
|
||||
* @task_context: The task_context to be reconstruct for packet request command
|
||||
* phase.
|
||||
*
|
||||
*/
|
||||
void scu_stp_packet_request_command_phase_construct_task_context(
|
||||
struct scic_sds_request *this_request,
|
||||
struct scu_task_context *task_context)
|
||||
{
|
||||
void *atapi_cdb;
|
||||
u32 atapi_cdb_length;
|
||||
struct scic_sds_stp_request *stp_request = (struct scic_sds_stp_request *)this_request;
|
||||
|
||||
/*
|
||||
* reference: SSTL 1.13.4.2
|
||||
* task_type, sata_direction */
|
||||
if (scic_cb_io_request_get_data_direction(this_request->user_request)
|
||||
== SCI_IO_REQUEST_DATA_OUT) {
|
||||
task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT;
|
||||
task_context->sata_direction = 0;
|
||||
} else { /* todo: for NO_DATA command, we need to send out raw frame. */
|
||||
task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN;
|
||||
task_context->sata_direction = 1;
|
||||
}
|
||||
|
||||
/* sata header */
|
||||
memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT));
|
||||
task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
|
||||
|
||||
/*
|
||||
* Copy in the command IU with CDB so that the commandIU address doesn't
|
||||
* change. */
|
||||
memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d));
|
||||
|
||||
atapi_cdb =
|
||||
scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request);
|
||||
|
||||
atapi_cdb_length =
|
||||
scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request);
|
||||
|
||||
memcpy(((u8 *)this_request->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length);
|
||||
|
||||
atapi_cdb_length =
|
||||
max(atapi_cdb_length, stp_request->type.packet.device_preferred_cdb_length);
|
||||
|
||||
task_context->ssp_command_iu_length =
|
||||
((atapi_cdb_length % 4) == 0) ?
|
||||
(atapi_cdb_length / 4) : ((atapi_cdb_length / 4) + 1);
|
||||
|
||||
/* task phase is set to TX_CMD */
|
||||
task_context->task_phase = 0x1;
|
||||
|
||||
/* retry counter */
|
||||
task_context->stp_retry_count = 0;
|
||||
|
||||
if (scic_cb_request_is_initial_construction(this_request->user_request)) {
|
||||
/* data transfer size. */
|
||||
task_context->transfer_length_bytes =
|
||||
scic_cb_io_request_get_transfer_length(this_request->user_request);
|
||||
|
||||
/* setup sgl */
|
||||
scic_sds_request_build_sgl(this_request);
|
||||
} else {
|
||||
/* data transfer size, need to be 4 bytes aligned. */
|
||||
task_context->transfer_length_bytes = (SCSI_FIXED_SENSE_DATA_BASE_LENGTH + 2);
|
||||
|
||||
scic_sds_stp_packet_internal_request_sense_build_sgl(this_request);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will fill in the SCU Task Context for a DATA fis containing CDB
|
||||
* in Raw Frame type. The TC for previous Packet fis was already there, we
|
||||
* only need to change the H2D fis content.
|
||||
* @this_request: This parameter specifies the smp request object being
|
||||
* constructed.
|
||||
* @task_context: The task_context to be reconstruct for packet request command
|
||||
* phase.
|
||||
*
|
||||
*/
|
||||
void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
|
||||
struct scic_sds_request *this_request,
|
||||
struct scu_task_context *task_context)
|
||||
{
|
||||
void *atapi_cdb =
|
||||
scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request);
|
||||
|
||||
u32 atapi_cdb_length =
|
||||
scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request);
|
||||
|
||||
memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d));
|
||||
memcpy(((u8 *)this_request->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length);
|
||||
|
||||
memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT));
|
||||
task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
|
||||
|
||||
/*
|
||||
* Note the data send out has to be 4 bytes aligned. Or else out hardware will
|
||||
* patch non-zero bytes and cause the target device unhappy. */
|
||||
task_context->transfer_length_bytes = 12;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* *@brief This methods decode the D2H status FIS and retrieve the sense data,
|
||||
* then pass the sense data to user request.
|
||||
*
|
||||
***@param[in] this_request The request receive D2H status FIS.
|
||||
***@param[in] status_fis The D2H status fis to be processed.
|
||||
*
|
||||
*/
|
||||
enum sci_status scic_sds_stp_packet_request_process_status_fis(
|
||||
struct scic_sds_request *this_request,
|
||||
struct sata_fis_reg_d2h *status_fis)
|
||||
{
|
||||
enum sci_status status = SCI_SUCCESS;
|
||||
|
||||
/* TODO: Process the error status fis, retrieve sense data. */
|
||||
if (status_fis->status & ATA_STATUS_REG_ERROR_BIT)
|
||||
status = SCI_FAILURE_IO_RESPONSE_VALID;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* *@brief This methods builds sgl for internal REQUEST SENSE stp packet
|
||||
* command using this request response buffer, only one sge is
|
||||
* needed.
|
||||
*
|
||||
***@param[in] this_request The request receive request sense data.
|
||||
*
|
||||
*/
|
||||
void scic_sds_stp_packet_internal_request_sense_build_sgl(
|
||||
struct scic_sds_request *this_request)
|
||||
{
|
||||
void *sge;
|
||||
struct scu_sgl_element_pair *scu_sgl_list = NULL;
|
||||
struct scu_task_context *task_context;
|
||||
dma_addr_t physical_address;
|
||||
|
||||
struct sci_ssp_response_iu *rsp_iu =
|
||||
(struct sci_ssp_response_iu *)this_request->response_buffer;
|
||||
|
||||
sge = (void *)&rsp_iu->data[0];
|
||||
|
||||
task_context = (struct scu_task_context *)this_request->task_context_buffer;
|
||||
scu_sgl_list = &task_context->sgl_pair_ab;
|
||||
|
||||
scic_cb_io_request_get_physical_address(
|
||||
scic_sds_request_get_controller(this_request),
|
||||
this_request,
|
||||
((char *)sge),
|
||||
&physical_address
|
||||
);
|
||||
|
||||
scu_sgl_list->A.address_upper = sci_cb_physical_address_upper(physical_address);
|
||||
scu_sgl_list->A.address_lower = sci_cb_physical_address_lower(physical_address);
|
||||
scu_sgl_list->A.length = task_context->transfer_length_bytes;
|
||||
scu_sgl_list->A.address_modifier = 0;
|
||||
|
||||
SCU_SGL_ZERO(scu_sgl_list->B);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method processes the completions transport layer (TL) status to
|
||||
* determine if the Packet FIS was sent successfully. If the Packet FIS was
|
||||
* sent successfully, then the state for the Packet request transits to
|
||||
* waiting for a PIO SETUP frame.
|
||||
* @this_request: This parameter specifies the request for which the TC
|
||||
* completion was received.
|
||||
* @completion_code: This parameter indicates the completion status information
|
||||
* for the TC.
|
||||
*
|
||||
* Indicate if the tc completion handler was successful. SCI_SUCCESS currently
|
||||
* this method always returns success.
|
||||
*/
|
||||
enum sci_status scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 completion_code)
|
||||
{
|
||||
enum sci_status status = SCI_SUCCESS;
|
||||
|
||||
switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
|
||||
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
|
||||
scic_sds_request_set_status(
|
||||
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->started_substate_machine,
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* All other completion status cause the IO to be complete. If a NAK
|
||||
* was received, then it is up to the user to retry the request. */
|
||||
scic_sds_request_set_status(
|
||||
this_request,
|
||||
SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
|
||||
SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method processes an unsolicited frame while the Packet request is
|
||||
* waiting for a PIO SETUP FIS. It will release the unsolicited frame, and
|
||||
* transition the request to the COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
|
||||
* state.
|
||||
* @this_request: This parameter specifies the request for which the
|
||||
* unsolicited frame was received.
|
||||
* @frame_index: This parameter indicates the unsolicited frame index that
|
||||
* should contain the response.
|
||||
*
|
||||
* This method returns an indication of whether the pio setup frame was handled
|
||||
* successfully or not. SCI_SUCCESS Currently this value is always returned and
|
||||
* indicates successful processing of the TC response.
|
||||
*/
|
||||
enum sci_status scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler(
|
||||
struct scic_sds_request *request,
|
||||
u32 frame_index)
|
||||
{
|
||||
enum sci_status status;
|
||||
struct sata_fis_header *frame_header;
|
||||
u32 *frame_buffer;
|
||||
struct scic_sds_stp_request *this_request;
|
||||
|
||||
this_request = (struct scic_sds_stp_request *)request;
|
||||
|
||||
status = scic_sds_unsolicited_frame_control_get_header(
|
||||
&(this_request->parent.owning_controller->uf_control),
|
||||
frame_index,
|
||||
(void **)&frame_header
|
||||
);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
BUG_ON(frame_header->fis_type != SATA_FIS_TYPE_PIO_SETUP);
|
||||
|
||||
/*
|
||||
* Get from the frame buffer the PIO Setup Data, although we don't need
|
||||
* any info from this pio setup fis. */
|
||||
scic_sds_unsolicited_frame_control_get_buffer(
|
||||
&(this_request->parent.owning_controller->uf_control),
|
||||
frame_index,
|
||||
(void **)&frame_buffer
|
||||
);
|
||||
|
||||
/*
|
||||
* Get the data from the PIO Setup
|
||||
* The SCU Hardware returns first word in the frame_header and the rest
|
||||
* of the data is in the frame buffer so we need to back up one dword */
|
||||
this_request->type.packet.device_preferred_cdb_length =
|
||||
(u16)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->transfter_count;
|
||||
|
||||
/* Frame has been decoded return it to the controller */
|
||||
scic_sds_controller_release_frame(
|
||||
this_request->parent.owning_controller, frame_index
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.started_substate_machine,
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
|
||||
);
|
||||
} else
|
||||
dev_err(scic_to_dev(request->owning_controller),
|
||||
"%s: SCIC IO Request 0x%p could not get frame header "
|
||||
"for frame index %d, status %x\n",
|
||||
__func__, this_request, frame_index, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method processes the completions transport layer (TL) status to
|
||||
* determine if the PACKET command data FIS was sent successfully. If
|
||||
* successfully, then the state for the packet request transits to COMPLETE
|
||||
* state. If not successfuly, the request transits to
|
||||
* COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE.
|
||||
* @this_request: This parameter specifies the request for which the TC
|
||||
* completion was received.
|
||||
* @completion_code: This parameter indicates the completion status information
|
||||
* for the TC.
|
||||
*
|
||||
* Indicate if the tc completion handler was successful. SCI_SUCCESS currently
|
||||
* this method always returns success.
|
||||
*/
|
||||
enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 completion_code)
|
||||
{
|
||||
enum sci_status status = SCI_SUCCESS;
|
||||
u8 sat_packet_protocol =
|
||||
scic_cb_request_get_sat_protocol(this_request->user_request);
|
||||
|
||||
switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
|
||||
case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
|
||||
scic_sds_request_set_status(
|
||||
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
|
||||
);
|
||||
|
||||
if (sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_IN
|
||||
|| sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_OUT
|
||||
)
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
else
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->started_substate_machine,
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
|
||||
);
|
||||
break;
|
||||
|
||||
case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT):
|
||||
if (scic_io_request_get_number_of_bytes_transferred(this_request) <
|
||||
scic_cb_io_request_get_transfer_length(this_request->user_request)) {
|
||||
scic_sds_request_set_status(
|
||||
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
|
||||
status = this_request->sci_status;
|
||||
}
|
||||
break;
|
||||
|
||||
case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT):
|
||||
/* In this case, there is no UF coming after. compelte the IO now. */
|
||||
scic_sds_request_set_status(
|
||||
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if (this_request->sci_status != SCI_SUCCESS) { /* The io status was set already. This means an UF for the status
|
||||
* fis was received already.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A device suspension event is expected, we need to have the device
|
||||
* coming out of suspension, then complete the IO. */
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->started_substate_machine,
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
|
||||
);
|
||||
|
||||
/* change the device state to ATAPI_ERROR. */
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->target_device->ready_substate_machine,
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
|
||||
);
|
||||
|
||||
status = this_request->sci_status;
|
||||
} else { /* If receiving any non-sucess TC status, no UF received yet, then an UF for
|
||||
* the status fis is coming after.
|
||||
*/
|
||||
scic_sds_request_set_status(
|
||||
this_request,
|
||||
SCU_TASK_DONE_CHECK_RESPONSE,
|
||||
SCI_FAILURE_IO_RESPONSE_VALID
|
||||
);
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->started_substate_machine,
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method processes an unsolicited frame.
|
||||
* @this_request: This parameter specifies the request for which the
|
||||
* unsolicited frame was received.
|
||||
* @frame_index: This parameter indicates the unsolicited frame index that
|
||||
* should contain the response.
|
||||
*
|
||||
* This method returns an indication of whether the UF frame was handled
|
||||
* successfully or not. SCI_SUCCESS Currently this value is always returned and
|
||||
* indicates successful processing of the TC response.
|
||||
*/
|
||||
enum sci_status scic_sds_stp_packet_request_command_phase_common_frame_handler(
|
||||
struct scic_sds_request *request,
|
||||
u32 frame_index)
|
||||
{
|
||||
enum sci_status status;
|
||||
struct sata_fis_header *frame_header;
|
||||
u32 *frame_buffer;
|
||||
struct scic_sds_stp_request *this_request;
|
||||
|
||||
this_request = (struct scic_sds_stp_request *)request;
|
||||
|
||||
status = scic_sds_unsolicited_frame_control_get_header(
|
||||
&(this_request->parent.owning_controller->uf_control),
|
||||
frame_index,
|
||||
(void **)&frame_header
|
||||
);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
BUG_ON(frame_header->fis_type != SATA_FIS_TYPE_REGD2H);
|
||||
|
||||
/*
|
||||
* Get from the frame buffer the PIO Setup Data, although we don't need
|
||||
* any info from this pio setup fis. */
|
||||
scic_sds_unsolicited_frame_control_get_buffer(
|
||||
&(this_request->parent.owning_controller->uf_control),
|
||||
frame_index,
|
||||
(void **)&frame_buffer
|
||||
);
|
||||
|
||||
scic_sds_controller_copy_sata_response(
|
||||
&this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer
|
||||
);
|
||||
|
||||
/* Frame has been decoded return it to the controller */
|
||||
scic_sds_controller_release_frame(
|
||||
this_request->parent.owning_controller, frame_index
|
||||
);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method processes an unsolicited frame while the packet request is
|
||||
* expecting TC completion. It will process the FIS and construct sense data.
|
||||
* @this_request: This parameter specifies the request for which the
|
||||
* unsolicited frame was received.
|
||||
* @frame_index: This parameter indicates the unsolicited frame index that
|
||||
* should contain the response.
|
||||
*
|
||||
* This method returns an indication of whether the UF frame was handled
|
||||
* successfully or not. SCI_SUCCESS Currently this value is always returned and
|
||||
* indicates successful processing of the TC response.
|
||||
*/
|
||||
enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler(
|
||||
struct scic_sds_request *request,
|
||||
u32 frame_index)
|
||||
{
|
||||
struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request;
|
||||
|
||||
enum sci_status status =
|
||||
scic_sds_stp_packet_request_command_phase_common_frame_handler(
|
||||
request, frame_index);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
/* The command has completed with error status from target device. */
|
||||
status = scic_sds_stp_packet_request_process_status_fis(
|
||||
request, &this_request->d2h_reg_fis);
|
||||
|
||||
if (status != SCI_SUCCESS) {
|
||||
scic_sds_request_set_status(
|
||||
&this_request->parent,
|
||||
SCU_TASK_DONE_CHECK_RESPONSE,
|
||||
status
|
||||
);
|
||||
} else
|
||||
scic_sds_request_set_status(
|
||||
&this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS
|
||||
);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method processes an unsolicited frame while the packet request is
|
||||
* expecting TC completion. It will process the FIS and construct sense data.
|
||||
* @this_request: This parameter specifies the request for which the
|
||||
* unsolicited frame was received.
|
||||
* @frame_index: This parameter indicates the unsolicited frame index that
|
||||
* should contain the response.
|
||||
*
|
||||
* This method returns an indication of whether the UF frame was handled
|
||||
* successfully or not. SCI_SUCCESS Currently this value is always returned and
|
||||
* indicates successful processing of the TC response.
|
||||
*/
|
||||
enum sci_status scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler(
|
||||
struct scic_sds_request *request,
|
||||
u32 frame_index)
|
||||
{
|
||||
enum sci_status status =
|
||||
scic_sds_stp_packet_request_command_phase_common_frame_handler(
|
||||
request, frame_index);
|
||||
|
||||
struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request;
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
/* The command has completed with error status from target device. */
|
||||
status = scic_sds_stp_packet_request_process_status_fis(
|
||||
request, &this_request->d2h_reg_fis);
|
||||
|
||||
if (status != SCI_SUCCESS) {
|
||||
scic_sds_request_set_status(
|
||||
request,
|
||||
SCU_TASK_DONE_CHECK_RESPONSE,
|
||||
status
|
||||
);
|
||||
} else
|
||||
scic_sds_request_set_status(
|
||||
request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
|
||||
);
|
||||
|
||||
/*
|
||||
* Always complete the NON_DATA command right away, no need to delay completion
|
||||
* even an error status fis came from target device. */
|
||||
sci_base_state_machine_change_state(
|
||||
&request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
enum sci_status scic_sds_stp_packet_request_started_completion_delay_complete_handler(
|
||||
struct sci_base_request *request)
|
||||
{
|
||||
struct scic_sds_request *this_request = (struct scic_sds_request *)request;
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_request->parent.state_machine,
|
||||
SCI_BASE_REQUEST_STATE_COMPLETED
|
||||
);
|
||||
|
||||
return this_request->sci_status;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
const struct scic_sds_io_request_state_handler scic_sds_stp_packet_request_started_substate_handler_table[] = {
|
||||
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = {
|
||||
.parent.start_handler = scic_sds_request_default_start_handler,
|
||||
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
|
||||
.parent.complete_handler = scic_sds_request_default_complete_handler,
|
||||
.parent.destruct_handler = scic_sds_request_default_destruct_handler
|
||||
.tc_completion_handler = scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler,
|
||||
.event_handler = scic_sds_request_default_event_handler,
|
||||
.frame_handler = scic_sds_request_default_frame_handler
|
||||
},
|
||||
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE] = {
|
||||
.parent.start_handler = scic_sds_request_default_start_handler,
|
||||
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
|
||||
.parent.complete_handler = scic_sds_request_default_complete_handler,
|
||||
.parent.destruct_handler = scic_sds_request_default_destruct_handler
|
||||
.tc_completion_handler = scic_sds_request_default_tc_completion_handler,
|
||||
.event_handler = scic_sds_request_default_event_handler,
|
||||
.frame_handler = scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler
|
||||
},
|
||||
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = {
|
||||
.parent.start_handler = scic_sds_request_default_start_handler,
|
||||
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
|
||||
.parent.complete_handler = scic_sds_request_default_complete_handler,
|
||||
.parent.destruct_handler = scic_sds_request_default_destruct_handler
|
||||
.tc_completion_handler = scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler,
|
||||
.event_handler = scic_sds_request_default_event_handler,
|
||||
.frame_handler = scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler
|
||||
},
|
||||
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE] = {
|
||||
.parent.start_handler = scic_sds_request_default_start_handler,
|
||||
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
|
||||
.parent.complete_handler = scic_sds_request_default_complete_handler,
|
||||
.parent.destruct_handler = scic_sds_request_default_destruct_handler
|
||||
.tc_completion_handler = scic_sds_request_default_tc_completion_handler,
|
||||
.event_handler = scic_sds_request_default_event_handler,
|
||||
.frame_handler = scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler
|
||||
},
|
||||
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE] = {
|
||||
.parent.start_handler = scic_sds_request_default_start_handler,
|
||||
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
|
||||
.parent.complete_handler = scic_sds_stp_packet_request_started_completion_delay_complete_handler,
|
||||
.parent.destruct_handler = scic_sds_request_default_destruct_handler
|
||||
.tc_completion_handler = scic_sds_request_default_tc_completion_handler,
|
||||
.event_handler = scic_sds_request_default_event_handler,
|
||||
.frame_handler = scic_sds_request_default_frame_handler
|
||||
},
|
||||
};
|
||||
|
||||
void scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter(
|
||||
struct sci_base_object *object)
|
||||
{
|
||||
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_request,
|
||||
scic_sds_stp_packet_request_started_substate_handler_table,
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
|
||||
);
|
||||
|
||||
scic_sds_remote_device_set_working_request(
|
||||
this_request->target_device, this_request
|
||||
);
|
||||
}
|
||||
|
||||
void scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter(
|
||||
struct sci_base_object *object)
|
||||
{
|
||||
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_request,
|
||||
scic_sds_stp_packet_request_started_substate_handler_table,
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
|
||||
);
|
||||
}
|
||||
|
||||
void scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter(
|
||||
struct sci_base_object *object)
|
||||
{
|
||||
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
|
||||
u8 sat_packet_protocol =
|
||||
scic_cb_request_get_sat_protocol(this_request->user_request);
|
||||
|
||||
struct scu_task_context *task_context;
|
||||
enum sci_status status;
|
||||
|
||||
/*
|
||||
* Recycle the TC and reconstruct it for sending out data fis containing
|
||||
* CDB. */
|
||||
task_context = scic_sds_controller_get_task_context_buffer(
|
||||
this_request->owning_controller, this_request->io_tag);
|
||||
|
||||
if (sat_packet_protocol == SAT_PROTOCOL_PACKET_NON_DATA)
|
||||
scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
|
||||
this_request, task_context);
|
||||
else
|
||||
scu_stp_packet_request_command_phase_construct_task_context(
|
||||
this_request, task_context);
|
||||
|
||||
/* send the new TC out. */
|
||||
status = this_request->owning_controller->state_handlers->parent.continue_io_handler(
|
||||
&this_request->owning_controller->parent,
|
||||
&this_request->target_device->parent,
|
||||
&this_request->parent
|
||||
);
|
||||
|
||||
if (status == SCI_SUCCESS)
|
||||
SET_STATE_HANDLER(
|
||||
this_request,
|
||||
scic_sds_stp_packet_request_started_substate_handler_table,
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
|
||||
);
|
||||
}
|
||||
|
||||
void scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter(
|
||||
struct sci_base_object *object)
|
||||
{
|
||||
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_request,
|
||||
scic_sds_stp_packet_request_started_substate_handler_table,
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
|
||||
);
|
||||
}
|
||||
|
||||
void scic_sds_stp_packet_request_started_completion_delay_enter(
|
||||
struct sci_base_object *object)
|
||||
{
|
||||
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_request,
|
||||
scic_sds_stp_packet_request_started_substate_handler_table,
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
const struct sci_base_state scic_sds_stp_packet_request_started_substate_table[] = {
|
||||
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = {
|
||||
.enter_state = scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter,
|
||||
},
|
||||
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE] = {
|
||||
.enter_state = scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter,
|
||||
},
|
||||
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = {
|
||||
.enter_state = scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter,
|
||||
},
|
||||
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE] = {
|
||||
.enter_state = scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter,
|
||||
},
|
||||
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE] = {
|
||||
.enter_state scic_sds_stp_packet_request_started_completion_delay_enter,
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* !defined(DISABLE_ATAPI) */
|
||||
154
drivers/scsi/isci/core/scic_sds_stp_packet_request.h
Normal file
154
drivers/scsi/isci/core/scic_sds_stp_packet_request.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _SCIC_SDS_STP_PACKET_REQUEST_H_
|
||||
#define _SCIC_SDS_STP_PACKET_REQUEST_H_
|
||||
|
||||
#include "intel_sas.h"
|
||||
#include "sci_types.h"
|
||||
#include "scic_sds_stp_request.h"
|
||||
|
||||
/**
|
||||
* This file contains the structures and constants for PACKET protocol requests.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This is the enumeration of the SATA PIO DATA IN started substate machine.
|
||||
*/
|
||||
enum _SCIC_SDS_STP_PACKET_REQUEST_STARTED_SUBSTATES {
|
||||
/**
|
||||
* While in this state the IO request object is waiting for the TC completion
|
||||
* notification for the H2D Register FIS
|
||||
*/
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
|
||||
|
||||
/**
|
||||
* While in this state the IO request object is waiting for either a PIO Setup.
|
||||
*/
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE,
|
||||
|
||||
/**
|
||||
* While in this state the IO request object is waiting for TC completion for
|
||||
* the Packet DMA DATA fis or Raw Frame.
|
||||
*/
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
|
||||
|
||||
/**
|
||||
* The non-data IO transit to this state in this state after receiving TC
|
||||
* completion. While in this state IO request object is waiting for D2H status
|
||||
* frame as UF.
|
||||
*/
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE,
|
||||
|
||||
/**
|
||||
* The IO transit to this state in this state if the previous TC completion status
|
||||
* is not success and the atapi device is suspended due to target device failed the IO.
|
||||
* While in this state IO request object is waiting for device coming out of the
|
||||
* suspension state then complete the IO.
|
||||
*/
|
||||
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE,
|
||||
};
|
||||
|
||||
|
||||
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
extern const struct sci_base_state scic_sds_stp_packet_request_started_substate_table[];
|
||||
extern const struct scic_sds_io_request_state_handler scic_sds_stp_packet_request_started_substate_handler_table[];
|
||||
#endif /* !defined(DISABLE_ATAPI) */
|
||||
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
enum sci_status scic_sds_stp_packet_request_construct(
|
||||
struct scic_sds_request *this_request);
|
||||
#else /* !defined(DISABLE_ATAPI) */
|
||||
#define scic_sds_stp_packet_request_construct(request) SCI_FAILURE
|
||||
#endif /* !defined(DISABLE_ATAPI) */
|
||||
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
void scu_stp_packet_request_command_phase_construct_task_context(
|
||||
struct scic_sds_request *this_request,
|
||||
struct scu_task_context *task_context);
|
||||
#else /* !defined(DISABLE_ATAPI) */
|
||||
#define scu_stp_packet_request_command_phase_construct_task_context(reqeust, tc)
|
||||
#endif /* !defined(DISABLE_ATAPI) */
|
||||
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
|
||||
struct scic_sds_request *this_request,
|
||||
struct scu_task_context *task_context);
|
||||
#else /* !defined(DISABLE_ATAPI) */
|
||||
#define scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(reqeust, tc)
|
||||
#endif /* !defined(DISABLE_ATAPI) */
|
||||
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
enum sci_status scic_sds_stp_packet_request_process_status_fis(
|
||||
struct scic_sds_request *this_request,
|
||||
struct sata_fis_reg_d2h *status_fis);
|
||||
#else /* !defined(DISABLE_ATAPI) */
|
||||
#define scic_sds_stp_packet_request_process_status_fis(reqeust, fis) SCI_FAILURE
|
||||
#endif /* !defined(DISABLE_ATAPI) */
|
||||
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
void scic_sds_stp_packet_internal_request_sense_build_sgl(
|
||||
struct scic_sds_request *this_request);
|
||||
#else /* !defined(DISABLE_ATAPI) */
|
||||
#define scic_sds_stp_packet_internal_request_sense_build_sgl(request)
|
||||
#endif /* !defined(DISABLE_ATAPI) */
|
||||
|
||||
#endif /* _SCIC_SDS_STP_PACKET_REQUEST_H_ */
|
||||
|
||||
116
drivers/scsi/isci/core/scic_sds_stp_pio_request.h
Normal file
116
drivers/scsi/isci/core/scic_sds_stp_pio_request.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_SATA_PIO_REQUEST_H_
|
||||
#define _SCIC_SDS_SATA_PIO_REQUEST_H_
|
||||
|
||||
#include "sci_base_state.h"
|
||||
#include "scic_sds_request.h"
|
||||
#include "scu_task_context.h"
|
||||
|
||||
/**
|
||||
* This file contains the structures and constants for SATA PIO requests.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This is the enumeration of the SATA PIO DATA IN started substate machine.
|
||||
*/
|
||||
enum _SCIC_SDS_STP_REQUEST_STARTED_PIO_SUBSTATES {
|
||||
/**
|
||||
* While in this state the IO request object is waiting for the TC completion
|
||||
* notification for the H2D Register FIS
|
||||
*/
|
||||
SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE,
|
||||
|
||||
/**
|
||||
* While in this state the IO request object is waiting for either a PIO Setup
|
||||
* FIS or a D2H register FIS. The type of frame received is based on the
|
||||
* result of the prior frame and line conditions.
|
||||
*/
|
||||
SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE,
|
||||
|
||||
/**
|
||||
* While in this state the IO request object is waiting for a DATA frame from
|
||||
* the device.
|
||||
*/
|
||||
SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE,
|
||||
|
||||
/**
|
||||
* While in this state the IO request object is waiting to transmit the next data
|
||||
* frame to the device.
|
||||
*/
|
||||
SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE,
|
||||
};
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[];
|
||||
|
||||
extern const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[];
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
struct scic_sds_stp_request;
|
||||
|
||||
struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(
|
||||
struct scic_sds_stp_request *this_request);
|
||||
|
||||
#endif /* _SCIC_SDS_SATA_PIO_REQUEST_H_ */
|
||||
975
drivers/scsi/isci/core/scic_sds_stp_remote_device.c
Normal file
975
drivers/scsi/isci/core/scic_sds_stp_remote_device.c
Normal file
@@ -0,0 +1,975 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the ready substate handlers for an STP device.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "intel_sat.h"
|
||||
#include "intel_ata.h"
|
||||
#include "intel_sata.h"
|
||||
#include "sci_environment.h"
|
||||
#include "scic_remote_device.h"
|
||||
#include "scic_user_callback.h"
|
||||
#include "scic_sds_controller.h"
|
||||
#include "scic_sds_port.h"
|
||||
#include "scic_sds_remote_device.h"
|
||||
#include "scic_sds_request.h"
|
||||
#include "scu_event_codes.h"
|
||||
|
||||
/**
|
||||
* This method will perform the STP request completion processing common to IO
|
||||
* requests and task requests of all types
|
||||
* @device: This parameter specifies the device for which the request is being
|
||||
* completed.
|
||||
* @request: This parameter specifies the request being completed.
|
||||
*
|
||||
* This method returns an indication as to whether the request processing
|
||||
* completed successfully.
|
||||
*/
|
||||
static enum sci_status scic_sds_stp_remote_device_complete_request(
|
||||
struct sci_base_remote_device *device,
|
||||
struct sci_base_request *request)
|
||||
{
|
||||
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
|
||||
struct scic_sds_request *the_request = (struct scic_sds_request *)request;
|
||||
enum sci_status status;
|
||||
|
||||
status = scic_sds_io_request_complete(the_request);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
status = scic_sds_port_complete_io(
|
||||
this_device->owning_port, this_device, the_request
|
||||
);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
scic_sds_remote_device_decrement_request_count(this_device);
|
||||
if (the_request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) {
|
||||
/*
|
||||
* This request causes hardware error, device needs to be Lun Reset.
|
||||
* So here we force the state machine to IDLE state so the rest IOs
|
||||
* can reach RNC state handler, these IOs will be completed by RNC with
|
||||
* status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */
|
||||
sci_base_state_machine_change_state(
|
||||
&this_device->ready_substate_machine,
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
|
||||
);
|
||||
} else if (scic_sds_remote_device_get_request_count(this_device) == 0) {
|
||||
sci_base_state_machine_change_state(
|
||||
&this_device->ready_substate_machine,
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (status != SCI_SUCCESS)
|
||||
dev_err(scirdev_to_dev(this_device),
|
||||
"%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x "
|
||||
"could not complete\n",
|
||||
__func__,
|
||||
this_device->owning_port,
|
||||
this_device,
|
||||
the_request,
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY COMMON SUBSTATE HANDLERS
|
||||
* ***************************************************************************** */
|
||||
|
||||
/**
|
||||
* This is the READY NCQ substate handler to start task management request. In
|
||||
* this routine, we suspend and resume the RNC.
|
||||
* @device: The target device a task management request towards to.
|
||||
* @request: The task request.
|
||||
*
|
||||
* enum sci_status Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status to
|
||||
* let controller_start_task_handler know that the controller can't post TC for
|
||||
* task request yet, instead, when RNC gets resumed, a controller_continue_task
|
||||
* callback will be called.
|
||||
*/
|
||||
static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler(
|
||||
struct sci_base_remote_device *device,
|
||||
struct sci_base_request *request)
|
||||
{
|
||||
enum sci_status status;
|
||||
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
|
||||
struct scic_sds_request *this_request = (struct scic_sds_request *)request;
|
||||
|
||||
/* Will the port allow the io request to start? */
|
||||
status = this_device->owning_port->state_handlers->start_io_handler(
|
||||
this_device->owning_port,
|
||||
this_device,
|
||||
this_request
|
||||
);
|
||||
|
||||
if (SCI_SUCCESS == status) {
|
||||
status =
|
||||
scic_sds_remote_node_context_start_task(this_device->rnc, this_request);
|
||||
|
||||
if (SCI_SUCCESS == status) {
|
||||
status = this_request->state_handlers->parent.start_handler(request);
|
||||
}
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
/*
|
||||
* / @note If the remote device state is not IDLE this will replace
|
||||
* / the request that probably resulted in the task management
|
||||
* / request. */
|
||||
this_device->working_request = this_request;
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_device->ready_substate_machine,
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
|
||||
);
|
||||
|
||||
/*
|
||||
* The remote node context must cleanup the TCi to NCQ mapping table.
|
||||
* The only way to do this correctly is to either write to the TLCR
|
||||
* register or to invalidate and repost the RNC. In either case the
|
||||
* remote node context state machine will take the correct action when
|
||||
* the remote node context is suspended and later resumed. */
|
||||
scic_sds_remote_node_context_suspend(
|
||||
this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL);
|
||||
|
||||
scic_sds_remote_node_context_resume(
|
||||
this_device->rnc,
|
||||
(SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK)
|
||||
scic_sds_remote_device_continue_request,
|
||||
this_device);
|
||||
}
|
||||
|
||||
scic_sds_remote_device_start_request(this_device, this_request, status);
|
||||
|
||||
/*
|
||||
* We need to let the controller start request handler know that it can't
|
||||
* post TC yet. We will provide a callback function to post TC when RNC gets
|
||||
* resumed. */
|
||||
return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS
|
||||
* ***************************************************************************** */
|
||||
|
||||
/**
|
||||
* This method will handle the start io operation for a sata device that is in
|
||||
* the command idle state. - Evalute the type of IO request to be started -
|
||||
* If its an NCQ request change to NCQ substate - If its any other command
|
||||
* change to the CMD substate
|
||||
* @device:
|
||||
* @request:
|
||||
*
|
||||
* If this is a softreset we may want to have a different substate. enum sci_status
|
||||
*/
|
||||
static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler(
|
||||
struct sci_base_remote_device *device,
|
||||
struct sci_base_request *request)
|
||||
{
|
||||
enum sci_status status;
|
||||
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
|
||||
struct scic_sds_request *io_request = (struct scic_sds_request *)request;
|
||||
|
||||
|
||||
/* Will the port allow the io request to start? */
|
||||
status = this_device->owning_port->state_handlers->start_io_handler(
|
||||
this_device->owning_port,
|
||||
this_device,
|
||||
io_request
|
||||
);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
status =
|
||||
scic_sds_remote_node_context_start_io(this_device->rnc, io_request);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
status = io_request->state_handlers->parent.start_handler(request);
|
||||
}
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
if (
|
||||
scic_cb_request_get_sat_protocol(io_request->user_request)
|
||||
== SAT_PROTOCOL_FPDMA
|
||||
) {
|
||||
sci_base_state_machine_change_state(
|
||||
&this_device->ready_substate_machine,
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ
|
||||
);
|
||||
} else {
|
||||
this_device->working_request = io_request;
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_device->ready_substate_machine,
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
scic_sds_remote_device_start_request(this_device, io_request, status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @[in]: device The device received event.
|
||||
* @[in]: event_code The event code.
|
||||
*
|
||||
* This method will handle the event for a sata device that is in the idle
|
||||
* state. We pick up suspension events to handle specifically to this state. We
|
||||
* resume the RNC right away. enum sci_status
|
||||
*/
|
||||
static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 event_code)
|
||||
{
|
||||
enum sci_status status;
|
||||
|
||||
status = scic_sds_remote_device_general_event_handler(this_device, event_code);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX
|
||||
|| scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) {
|
||||
status = scic_sds_remote_node_context_resume(
|
||||
this_device->rnc, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS
|
||||
* ***************************************************************************** */
|
||||
|
||||
static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler(
|
||||
struct sci_base_remote_device *device,
|
||||
struct sci_base_request *request)
|
||||
{
|
||||
enum sci_status status;
|
||||
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
|
||||
struct scic_sds_request *io_request = (struct scic_sds_request *)request;
|
||||
|
||||
if (
|
||||
scic_cb_request_get_sat_protocol(io_request->user_request)
|
||||
== SAT_PROTOCOL_FPDMA
|
||||
) {
|
||||
status = this_device->owning_port->state_handlers->start_io_handler(
|
||||
this_device->owning_port,
|
||||
this_device,
|
||||
io_request
|
||||
);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
status = scic_sds_remote_node_context_start_io(this_device->rnc, io_request);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
status = io_request->state_handlers->parent.start_handler(request);
|
||||
}
|
||||
|
||||
scic_sds_remote_device_start_request(this_device, io_request, status);
|
||||
}
|
||||
} else {
|
||||
status = SCI_FAILURE_INVALID_STATE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method will handle events received while the STP device is in the ready
|
||||
* command substate.
|
||||
* @this_device: This is the device object that is receiving the event.
|
||||
* @event_code: The event code to process.
|
||||
*
|
||||
* enum sci_status
|
||||
*/
|
||||
|
||||
static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 frame_index)
|
||||
{
|
||||
enum sci_status status;
|
||||
struct sata_fis_header *frame_header;
|
||||
|
||||
status = scic_sds_unsolicited_frame_control_get_header(
|
||||
&(scic_sds_remote_device_get_controller(this_device)->uf_control),
|
||||
frame_index,
|
||||
(void **)&frame_header
|
||||
);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
if (
|
||||
(frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS)
|
||||
&& (frame_header->status & ATA_STATUS_REG_ERROR_BIT)
|
||||
) {
|
||||
this_device->not_ready_reason =
|
||||
SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
|
||||
|
||||
sci_base_state_machine_change_state(
|
||||
&this_device->ready_substate_machine,
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
|
||||
);
|
||||
} else {
|
||||
status = SCI_FAILURE;
|
||||
}
|
||||
|
||||
scic_sds_controller_release_frame(
|
||||
scic_sds_remote_device_get_controller(this_device), frame_index
|
||||
);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS
|
||||
* ***************************************************************************** */
|
||||
|
||||
/**
|
||||
* This device is already handling a command it can not accept new commands
|
||||
* until this one is complete.
|
||||
* @device:
|
||||
* @request:
|
||||
*
|
||||
* enum sci_status
|
||||
*/
|
||||
static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler(
|
||||
struct sci_base_remote_device *device,
|
||||
struct sci_base_request *request)
|
||||
{
|
||||
return SCI_FAILURE_INVALID_STATE;
|
||||
}
|
||||
|
||||
static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 suspend_type)
|
||||
{
|
||||
enum sci_status status;
|
||||
|
||||
status = scic_sds_remote_node_context_suspend(
|
||||
this_device->rnc, suspend_type, NULL, NULL
|
||||
);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 frame_index)
|
||||
{
|
||||
enum sci_status status;
|
||||
|
||||
/*
|
||||
* / The device doe not process any UF received from the hardware while
|
||||
* / in this state. All unsolicited frames are forwarded to the io request
|
||||
* / object. */
|
||||
status = scic_sds_io_request_frame_handler(
|
||||
this_device->working_request,
|
||||
frame_index
|
||||
);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS
|
||||
* ***************************************************************************** */
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE HANDLERS
|
||||
* ***************************************************************************** */
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS
|
||||
* ***************************************************************************** */
|
||||
static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler(
|
||||
struct sci_base_remote_device *device,
|
||||
struct sci_base_request *request)
|
||||
{
|
||||
return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This method will perform the STP request (both io or task) completion
|
||||
* processing for await reset state.
|
||||
* @device: This parameter specifies the device for which the request is being
|
||||
* completed.
|
||||
* @request: This parameter specifies the request being completed.
|
||||
*
|
||||
* This method returns an indication as to whether the request processing
|
||||
* completed successfully.
|
||||
*/
|
||||
static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler(
|
||||
struct sci_base_remote_device *device,
|
||||
struct sci_base_request *request)
|
||||
{
|
||||
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
|
||||
struct scic_sds_request *the_request = (struct scic_sds_request *)request;
|
||||
enum sci_status status;
|
||||
|
||||
status = scic_sds_io_request_complete(the_request);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
status = scic_sds_port_complete_io(
|
||||
this_device->owning_port, this_device, the_request
|
||||
);
|
||||
|
||||
if (status == SCI_SUCCESS)
|
||||
scic_sds_remote_device_decrement_request_count(this_device);
|
||||
}
|
||||
|
||||
if (status != SCI_SUCCESS)
|
||||
dev_err(scirdev_to_dev(this_device),
|
||||
"%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x "
|
||||
"could not complete\n",
|
||||
__func__,
|
||||
this_device->owning_port,
|
||||
this_device,
|
||||
the_request,
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE HANDLERS
|
||||
* ***************************************************************************** */
|
||||
|
||||
/**
|
||||
*
|
||||
* @[in]: device The device received event.
|
||||
* @[in]: event_code The event code.
|
||||
*
|
||||
* This method will handle the event for a ATAPI device that is in the ATAPI
|
||||
* ERROR state. We pick up suspension events to handle specifically to this
|
||||
* state. We resume the RNC right away. We then complete the outstanding IO to
|
||||
* this device. enum sci_status
|
||||
*/
|
||||
enum sci_status scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler(
|
||||
struct scic_sds_remote_device *this_device,
|
||||
u32 event_code)
|
||||
{
|
||||
enum sci_status status;
|
||||
|
||||
status = scic_sds_remote_device_general_event_handler(this_device, event_code);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX
|
||||
|| scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) {
|
||||
status = scic_sds_remote_node_context_resume(
|
||||
this_device->rnc,
|
||||
this_device->working_request->state_handlers->parent.complete_handler,
|
||||
(void *)this_device->working_request
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* !defined(DISABLE_ATAPI) */
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
struct scic_sds_remote_device_state_handler
|
||||
scic_sds_stp_remote_device_ready_substate_handler_table[
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES] =
|
||||
{
|
||||
/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE */
|
||||
{
|
||||
{
|
||||
scic_sds_remote_device_default_start_handler,
|
||||
scic_sds_remote_device_ready_state_stop_handler,
|
||||
scic_sds_remote_device_default_fail_handler,
|
||||
scic_sds_remote_device_default_destruct_handler,
|
||||
scic_sds_remote_device_ready_state_reset_handler,
|
||||
scic_sds_remote_device_default_reset_complete_handler,
|
||||
scic_sds_stp_remote_device_ready_idle_substate_start_io_handler,
|
||||
scic_sds_remote_device_default_complete_request_handler,
|
||||
scic_sds_remote_device_default_continue_request_handler,
|
||||
scic_sds_stp_remote_device_ready_substate_start_request_handler,
|
||||
scic_sds_remote_device_default_complete_request_handler
|
||||
},
|
||||
scic_sds_remote_device_default_suspend_handler,
|
||||
scic_sds_remote_device_default_resume_handler,
|
||||
scic_sds_stp_remote_device_ready_idle_substate_event_handler,
|
||||
scic_sds_remote_device_default_frame_handler
|
||||
},
|
||||
/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD */
|
||||
{
|
||||
{
|
||||
scic_sds_remote_device_default_start_handler,
|
||||
scic_sds_remote_device_ready_state_stop_handler,
|
||||
scic_sds_remote_device_default_fail_handler,
|
||||
scic_sds_remote_device_default_destruct_handler,
|
||||
scic_sds_remote_device_ready_state_reset_handler,
|
||||
scic_sds_remote_device_default_reset_complete_handler,
|
||||
scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler,
|
||||
scic_sds_stp_remote_device_complete_request,
|
||||
scic_sds_remote_device_default_continue_request_handler,
|
||||
scic_sds_stp_remote_device_ready_substate_start_request_handler,
|
||||
scic_sds_stp_remote_device_complete_request,
|
||||
},
|
||||
scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler,
|
||||
scic_sds_remote_device_default_resume_handler,
|
||||
scic_sds_remote_device_general_event_handler,
|
||||
scic_sds_stp_remote_device_ready_cmd_substate_frame_handler
|
||||
},
|
||||
/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ */
|
||||
{
|
||||
{
|
||||
scic_sds_remote_device_default_start_handler,
|
||||
scic_sds_remote_device_ready_state_stop_handler,
|
||||
scic_sds_remote_device_default_fail_handler,
|
||||
scic_sds_remote_device_default_destruct_handler,
|
||||
scic_sds_remote_device_ready_state_reset_handler,
|
||||
scic_sds_remote_device_default_reset_complete_handler,
|
||||
scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler,
|
||||
scic_sds_stp_remote_device_complete_request,
|
||||
scic_sds_remote_device_default_continue_request_handler,
|
||||
scic_sds_stp_remote_device_ready_substate_start_request_handler,
|
||||
scic_sds_stp_remote_device_complete_request
|
||||
},
|
||||
scic_sds_remote_device_default_suspend_handler,
|
||||
scic_sds_remote_device_default_resume_handler,
|
||||
scic_sds_remote_device_general_event_handler,
|
||||
scic_sds_stp_remote_device_ready_ncq_substate_frame_handler
|
||||
},
|
||||
/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR */
|
||||
{
|
||||
{
|
||||
scic_sds_remote_device_default_start_handler,
|
||||
scic_sds_remote_device_ready_state_stop_handler,
|
||||
scic_sds_remote_device_default_fail_handler,
|
||||
scic_sds_remote_device_default_destruct_handler,
|
||||
scic_sds_remote_device_ready_state_reset_handler,
|
||||
scic_sds_remote_device_default_reset_complete_handler,
|
||||
scic_sds_remote_device_default_start_request_handler,
|
||||
scic_sds_stp_remote_device_complete_request,
|
||||
scic_sds_remote_device_default_continue_request_handler,
|
||||
scic_sds_stp_remote_device_ready_substate_start_request_handler,
|
||||
scic_sds_stp_remote_device_complete_request
|
||||
},
|
||||
scic_sds_remote_device_default_suspend_handler,
|
||||
scic_sds_remote_device_default_resume_handler,
|
||||
scic_sds_remote_device_general_event_handler,
|
||||
scic_sds_remote_device_general_frame_handler
|
||||
},
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR */
|
||||
{
|
||||
{
|
||||
scic_sds_remote_device_default_start_handler,
|
||||
scic_sds_remote_device_ready_state_stop_handler,
|
||||
scic_sds_remote_device_default_fail_handler,
|
||||
scic_sds_remote_device_default_destruct_handler,
|
||||
scic_sds_remote_device_ready_state_reset_handler,
|
||||
scic_sds_remote_device_default_reset_complete_handler,
|
||||
scic_sds_remote_device_default_start_request_handler,
|
||||
scic_sds_stp_remote_device_complete_request,
|
||||
scic_sds_remote_device_default_continue_request_handler,
|
||||
scic_sds_stp_remote_device_ready_substate_start_request_handler,
|
||||
scic_sds_stp_remote_device_complete_request
|
||||
},
|
||||
scic_sds_remote_device_default_suspend_handler,
|
||||
scic_sds_remote_device_default_resume_handler,
|
||||
scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler,
|
||||
scic_sds_remote_device_general_frame_handler
|
||||
},
|
||||
#endif
|
||||
/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET */
|
||||
{
|
||||
{
|
||||
scic_sds_remote_device_default_start_handler,
|
||||
scic_sds_remote_device_ready_state_stop_handler,
|
||||
scic_sds_remote_device_default_fail_handler,
|
||||
scic_sds_remote_device_default_destruct_handler,
|
||||
scic_sds_remote_device_ready_state_reset_handler,
|
||||
scic_sds_remote_device_default_reset_complete_handler,
|
||||
scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler,
|
||||
scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler,
|
||||
scic_sds_remote_device_default_continue_request_handler,
|
||||
scic_sds_stp_remote_device_ready_substate_start_request_handler,
|
||||
scic_sds_stp_remote_device_complete_request
|
||||
},
|
||||
scic_sds_remote_device_default_suspend_handler,
|
||||
scic_sds_remote_device_default_resume_handler,
|
||||
scic_sds_remote_device_general_event_handler,
|
||||
scic_sds_remote_device_general_frame_handler
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "sci_base_state.h"
|
||||
#include "scic_remote_device.h"
|
||||
#include "scic_user_callback.h"
|
||||
#include "scic_sds_controller.h"
|
||||
#include "scic_sds_port.h"
|
||||
#include "scic_sds_remote_device.h"
|
||||
#include "sci_util.h"
|
||||
#include "sci_environment.h"
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS
|
||||
* ***************************************************************************** */
|
||||
|
||||
static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(
|
||||
void *user_cookie)
|
||||
{
|
||||
struct scic_sds_remote_device *this_device;
|
||||
|
||||
this_device = (struct scic_sds_remote_device *)user_cookie;
|
||||
|
||||
/*
|
||||
* For NCQ operation we do not issue a
|
||||
* scic_cb_remote_device_not_ready(). As a result, avoid sending
|
||||
* the ready notification. */
|
||||
if (this_device->ready_substate_machine.previous_state_id
|
||||
!= SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) {
|
||||
scic_cb_remote_device_ready(
|
||||
scic_sds_remote_device_get_controller(this_device), this_device
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY IDLE SUBSTATE
|
||||
* ***************************************************************************** */
|
||||
|
||||
/**
|
||||
*
|
||||
* @device: This is the SCI base object which is cast into a
|
||||
* struct scic_sds_remote_device object.
|
||||
*
|
||||
*/
|
||||
static void scic_sds_stp_remote_device_ready_idle_substate_enter(
|
||||
struct sci_base_object *device)
|
||||
{
|
||||
struct scic_sds_remote_device *this_device;
|
||||
|
||||
this_device = (struct scic_sds_remote_device *)device;
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_device,
|
||||
scic_sds_stp_remote_device_ready_substate_handler_table,
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
|
||||
);
|
||||
|
||||
this_device->working_request = NULL;
|
||||
|
||||
if (scic_sds_remote_node_context_is_ready(this_device->rnc)) {
|
||||
/*
|
||||
* Since the RNC is ready, it's alright to finish completion
|
||||
* processing (e.g. signal the remote device is ready). */
|
||||
scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(
|
||||
this_device
|
||||
);
|
||||
} else {
|
||||
scic_sds_remote_node_context_resume(
|
||||
this_device->rnc,
|
||||
scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler,
|
||||
this_device
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY CMD SUBSTATE
|
||||
* ***************************************************************************** */
|
||||
|
||||
/**
|
||||
*
|
||||
* @device: This is the SCI base object which is cast into a
|
||||
* struct scic_sds_remote_device object.
|
||||
*
|
||||
*/
|
||||
static void scic_sds_stp_remote_device_ready_cmd_substate_enter(
|
||||
struct sci_base_object *device)
|
||||
{
|
||||
struct scic_sds_remote_device *this_device;
|
||||
|
||||
this_device = (struct scic_sds_remote_device *)device;
|
||||
|
||||
BUG_ON(this_device->working_request == NULL);
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_device,
|
||||
scic_sds_stp_remote_device_ready_substate_handler_table,
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
|
||||
);
|
||||
|
||||
scic_cb_remote_device_not_ready(
|
||||
scic_sds_remote_device_get_controller(this_device),
|
||||
this_device,
|
||||
SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY NCQ SUBSTATE
|
||||
* ***************************************************************************** */
|
||||
|
||||
/**
|
||||
*
|
||||
* @device: This is the SCI base object which is cast into a
|
||||
* struct scic_sds_remote_device object.
|
||||
*
|
||||
*/
|
||||
static void scic_sds_stp_remote_device_ready_ncq_substate_enter(
|
||||
struct sci_base_object *device)
|
||||
{
|
||||
struct scic_sds_remote_device *this_device;
|
||||
|
||||
this_device = (struct scic_sds_remote_device *)device;
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_device,
|
||||
scic_sds_stp_remote_device_ready_substate_handler_table,
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE
|
||||
* ***************************************************************************** */
|
||||
|
||||
/**
|
||||
*
|
||||
* @device: This is the SCI base object which is cast into a
|
||||
* struct scic_sds_remote_device object.
|
||||
*
|
||||
*/
|
||||
static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(
|
||||
struct sci_base_object *device)
|
||||
{
|
||||
struct scic_sds_remote_device *this_device;
|
||||
|
||||
this_device = (struct scic_sds_remote_device *)device;
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_device,
|
||||
scic_sds_stp_remote_device_ready_substate_handler_table,
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
|
||||
);
|
||||
|
||||
if (this_device->not_ready_reason ==
|
||||
SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) {
|
||||
scic_cb_remote_device_not_ready(
|
||||
scic_sds_remote_device_get_controller(this_device),
|
||||
this_device,
|
||||
this_device->not_ready_reason
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE
|
||||
* ***************************************************************************** */
|
||||
|
||||
/**
|
||||
* The enter routine to READY AWAIT RESET substate.
|
||||
* @device: This is the SCI base object which is cast into a
|
||||
* struct scic_sds_remote_device object.
|
||||
*
|
||||
*/
|
||||
static void scic_sds_stp_remote_device_ready_await_reset_substate_enter(
|
||||
struct sci_base_object *device)
|
||||
{
|
||||
struct scic_sds_remote_device *this_device;
|
||||
|
||||
this_device = (struct scic_sds_remote_device *)device;
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_device,
|
||||
scic_sds_stp_remote_device_ready_substate_handler_table,
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
|
||||
);
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE
|
||||
* ***************************************************************************** */
|
||||
|
||||
/**
|
||||
* The enter routine to READY ATAPI ERROR substate.
|
||||
* @device: This is the SCI base object which is cast into a
|
||||
* struct scic_sds_remote_device object.
|
||||
*
|
||||
*/
|
||||
void scic_sds_stp_remote_device_ready_atapi_error_substate_enter(
|
||||
struct sci_base_object *device)
|
||||
{
|
||||
struct scic_sds_remote_device *this_device;
|
||||
|
||||
this_device = (struct scic_sds_remote_device *)device;
|
||||
|
||||
SET_STATE_HANDLER(
|
||||
this_device,
|
||||
scic_sds_stp_remote_device_ready_substate_handler_table,
|
||||
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
|
||||
);
|
||||
}
|
||||
#endif /* !defined(DISABLE_ATAPI) */
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[] = {
|
||||
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
|
||||
.enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter,
|
||||
},
|
||||
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
|
||||
.enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter,
|
||||
},
|
||||
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = {
|
||||
.enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter,
|
||||
},
|
||||
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = {
|
||||
.enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter,
|
||||
},
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = {
|
||||
.enter_state = scic_sds_stp_remote_device_ready_atapi_error_substate_enter,
|
||||
},
|
||||
#endif
|
||||
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = {
|
||||
.enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter,
|
||||
},
|
||||
};
|
||||
2004
drivers/scsi/isci/core/scic_sds_stp_request.c
Normal file
2004
drivers/scsi/isci/core/scic_sds_stp_request.c
Normal file
File diff suppressed because it is too large
Load Diff
221
drivers/scsi/isci/core/scic_sds_stp_request.h
Normal file
221
drivers/scsi/isci/core/scic_sds_stp_request.h
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_STP_REQUEST_T_
|
||||
#define _SCIC_SDS_STP_REQUEST_T_
|
||||
|
||||
#include "intel_sata.h"
|
||||
#include "sci_types.h"
|
||||
#include "scic_sds_request.h"
|
||||
|
||||
/**
|
||||
* This structure represents the additional information that is required to
|
||||
* handle SATA PIO requests.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scic_sds_stp_request {
|
||||
struct scic_sds_request parent;
|
||||
|
||||
struct sata_fis_reg_d2h d2h_reg_fis;
|
||||
|
||||
union {
|
||||
u32 ncq;
|
||||
|
||||
u32 udma;
|
||||
|
||||
struct {
|
||||
/**
|
||||
* Total transfer for the entire PIO request recorded at request constuction
|
||||
* time.
|
||||
*
|
||||
* @todo Should we just decrement this value for each byte of data transitted
|
||||
* or received to elemenate the current_transfer_bytes field?
|
||||
*/
|
||||
u32 total_transfer_bytes;
|
||||
|
||||
/**
|
||||
* Total number of bytes received/transmitted in data frames since the start
|
||||
* of the IO request. At the end of the IO request this should equal the
|
||||
* total_transfer_bytes.
|
||||
*/
|
||||
u32 current_transfer_bytes;
|
||||
|
||||
/**
|
||||
* The number of bytes requested in the in the PIO setup.
|
||||
*/
|
||||
u32 pio_transfer_bytes;
|
||||
|
||||
/**
|
||||
* PIO Setup ending status value to tell us if we need to wait for another FIS
|
||||
* or if the transfer is complete. On the receipt of a D2H FIS this will be
|
||||
* the status field of that FIS.
|
||||
*/
|
||||
u8 ending_status;
|
||||
|
||||
/**
|
||||
* On receipt of a D2H FIS this will be the ending error field if the
|
||||
* ending_status has the SATA_STATUS_ERR bit set.
|
||||
*/
|
||||
u8 ending_error;
|
||||
|
||||
/**
|
||||
* Protocol Type. This is filled in by core during IO Request construction type.
|
||||
*/
|
||||
u8 sat_protocol;
|
||||
|
||||
struct {
|
||||
struct scu_sgl_element_pair *sgl_pair;
|
||||
u8 sgl_set;
|
||||
u32 sgl_offset;
|
||||
} request_current;
|
||||
} pio;
|
||||
|
||||
struct {
|
||||
/**
|
||||
* The number of bytes requested in the PIO setup before CDB data frame.
|
||||
*/
|
||||
u32 device_preferred_cdb_length;
|
||||
} packet;
|
||||
} type;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* enum SCIC_SDS_STP_REQUEST_STARTED_UDMA_SUBSTATES - This enumeration depicts
|
||||
* the various sub-states associated with a SATA/STP UDMA protocol operation.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum SCIC_SDS_STP_REQUEST_STARTED_UDMA_SUBSTATES {
|
||||
SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE,
|
||||
SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES - This enumeration
|
||||
* depicts the various sub-states associated with a SATA/STP non-data
|
||||
* protocol operation.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES {
|
||||
SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE,
|
||||
SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES - THis enumeration
|
||||
* depicts the various sub-states associated with a SATA/STP soft reset
|
||||
* operation.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES {
|
||||
SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE,
|
||||
SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE,
|
||||
SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE,
|
||||
};
|
||||
|
||||
extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[];
|
||||
|
||||
extern const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[];
|
||||
|
||||
extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[];
|
||||
|
||||
extern const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[];
|
||||
|
||||
extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[];
|
||||
|
||||
extern const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[];
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
u32 scic_sds_stp_request_get_object_size(void);
|
||||
|
||||
|
||||
void scic_sds_stp_non_ncq_request_construct(
|
||||
struct scic_sds_request *this_request);
|
||||
|
||||
enum sci_status scic_sds_stp_pio_request_construct(
|
||||
struct scic_sds_request *scic_io_request,
|
||||
u8 sat_protocol,
|
||||
bool copy_rx_frame);
|
||||
|
||||
enum sci_status scic_sds_stp_pio_request_construct_pass_through(
|
||||
struct scic_sds_request *scic_io_request,
|
||||
struct scic_stp_passthru_request_callbacks *passthru_cb);
|
||||
|
||||
enum sci_status scic_sds_stp_udma_request_construct(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 transfer_length,
|
||||
SCI_IO_REQUEST_DATA_DIRECTION data_direction);
|
||||
|
||||
enum sci_status scic_sds_stp_non_data_request_construct(
|
||||
struct scic_sds_request *this_request);
|
||||
|
||||
enum sci_status scic_sds_stp_soft_reset_request_construct(
|
||||
struct scic_sds_request *this_request);
|
||||
|
||||
enum sci_status scic_sds_stp_ncq_request_construct(
|
||||
struct scic_sds_request *this_request,
|
||||
u32 transfer_length,
|
||||
SCI_IO_REQUEST_DATA_DIRECTION data_direction);
|
||||
|
||||
void scu_stp_raw_request_construct_task_context(
|
||||
struct scic_sds_stp_request *this_request,
|
||||
struct scu_task_context *task_context);
|
||||
|
||||
#endif /* _SCIC_SDS_STP_REQUEST_T_ */
|
||||
379
drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c
Normal file
379
drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c
Normal file
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the implementation of the
|
||||
* struct scic_sds_unsolicited_frame_control object and it's public, protected, and
|
||||
* private methods.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "scic_sds_unsolicited_frame_control.h"
|
||||
#include "scu_registers.h"
|
||||
#include "scic_sds_controller.h"
|
||||
#include "scic_user_callback.h"
|
||||
#include "sci_util.h"
|
||||
#include "sci_environment.h"
|
||||
|
||||
/**
|
||||
* The UF buffer address table size must be programmed to a power of 2. Find
|
||||
* the first power of 2 that is equal to or greater then the number of
|
||||
* unsolicited frame buffers to be utilized.
|
||||
* @uf_control: This parameter specifies the UF control object for which to
|
||||
* update the address table count.
|
||||
*
|
||||
*/
|
||||
void scic_sds_unsolicited_frame_control_set_address_table_count(
|
||||
struct scic_sds_unsolicited_frame_control *uf_control)
|
||||
{
|
||||
uf_control->address_table.count = SCU_MIN_UF_TABLE_ENTRIES;
|
||||
while (
|
||||
(uf_control->address_table.count < uf_control->buffers.count)
|
||||
&& (uf_control->address_table.count < SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES)
|
||||
) {
|
||||
uf_control->address_table.count <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will program the unsolicited frames (UFs) into the UF address
|
||||
* table and construct the UF frame structure being modeled in the core. It
|
||||
* will handle the case where some of the UFs are not being used and thus
|
||||
* should have entries programmed to zero in the address table.
|
||||
* @uf_control: This parameter specifies the unsolicted frame control object
|
||||
* for which to construct the unsolicited frames objects.
|
||||
* @uf_buffer_phys_address: This parameter specifies the physical address for
|
||||
* the first unsolicited frame buffer.
|
||||
* @uf_buffer_virt_address: This parameter specifies the virtual address for
|
||||
* the first unsolicited frame buffer.
|
||||
* @unused_uf_header_entries: This parameter specifies the number of unused UF
|
||||
* headers. This value can be non-zero when there are a non-power of 2
|
||||
* number of unsolicited frames being supported.
|
||||
* @used_uf_header_entries: This parameter specifies the number of actually
|
||||
* utilized UF headers.
|
||||
*
|
||||
*/
|
||||
static void scic_sds_unsolicited_frame_control_construct_frames(
|
||||
struct scic_sds_unsolicited_frame_control *uf_control,
|
||||
dma_addr_t uf_buffer_phys_address,
|
||||
unsigned long uf_buffer_virt_address,
|
||||
u32 unused_uf_header_entries,
|
||||
u32 used_uf_header_entries)
|
||||
{
|
||||
u32 index;
|
||||
struct scic_sds_unsolicited_frame *uf;
|
||||
|
||||
/*
|
||||
* Program the unused buffers into the UF address table and the
|
||||
* controller's array of UFs. */
|
||||
for (index = 0; index < unused_uf_header_entries; index++) {
|
||||
uf = &uf_control->buffers.array[index];
|
||||
|
||||
sci_cb_make_physical_address(
|
||||
uf_control->address_table.array[index], 0, 0
|
||||
);
|
||||
uf->buffer = NULL;
|
||||
uf->header = &uf_control->headers.array[index];
|
||||
uf->state = UNSOLICITED_FRAME_EMPTY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Program the actual used UF buffers into the UF address table and
|
||||
* the controller's array of UFs. */
|
||||
for (index = unused_uf_header_entries;
|
||||
index < unused_uf_header_entries + used_uf_header_entries;
|
||||
index++) {
|
||||
uf = &uf_control->buffers.array[index];
|
||||
|
||||
uf_control->address_table.array[index] = uf_buffer_phys_address;
|
||||
|
||||
uf->buffer = (void *)uf_buffer_virt_address;
|
||||
uf->header = &uf_control->headers.array[index];
|
||||
uf->state = UNSOLICITED_FRAME_EMPTY;
|
||||
|
||||
/*
|
||||
* Increment the address of the physical and virtual memory pointers
|
||||
* Everything is aligned on 1k boundary with an increment of 1k */
|
||||
uf_buffer_virt_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
|
||||
sci_physical_address_add(
|
||||
uf_buffer_phys_address, SCU_UNSOLICITED_FRAME_BUFFER_SIZE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method constructs the various members of the unsolicted frame control
|
||||
* object (buffers, headers, address, table, etc).
|
||||
* @uf_control: This parameter specifies the unsolicited frame control object
|
||||
* to construct.
|
||||
* @mde: This parameter specifies the memory descriptor from which to derive
|
||||
* all of the address information needed to get the unsolicited frame
|
||||
* functionality working.
|
||||
* @controller: This parameter specifies the controller object associated with
|
||||
* the uf_control being constructed.
|
||||
*
|
||||
*/
|
||||
void scic_sds_unsolicited_frame_control_construct(
|
||||
struct scic_sds_unsolicited_frame_control *uf_control,
|
||||
struct sci_physical_memory_descriptor *mde,
|
||||
struct scic_sds_controller *controller)
|
||||
{
|
||||
u32 unused_uf_header_entries;
|
||||
u32 used_uf_header_entries;
|
||||
u32 used_uf_buffer_bytes;
|
||||
u32 unused_uf_header_bytes;
|
||||
u32 used_uf_header_bytes;
|
||||
dma_addr_t uf_buffer_phys_address;
|
||||
|
||||
/*
|
||||
* Prepare all of the memory sizes for the UF headers, UF address
|
||||
* table, and UF buffers themselves. */
|
||||
used_uf_buffer_bytes = uf_control->buffers.count
|
||||
* SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
|
||||
unused_uf_header_entries = uf_control->address_table.count
|
||||
- uf_control->buffers.count;
|
||||
used_uf_header_entries = uf_control->buffers.count;
|
||||
unused_uf_header_bytes = unused_uf_header_entries
|
||||
* sizeof(struct scu_unsolicited_frame_header);
|
||||
used_uf_header_bytes = used_uf_header_entries
|
||||
* sizeof(struct scu_unsolicited_frame_header);
|
||||
|
||||
/*
|
||||
* The Unsolicited Frame buffers are set at the start of the UF
|
||||
* memory descriptor entry. The headers and address table will be
|
||||
* placed after the buffers. */
|
||||
uf_buffer_phys_address = mde->physical_address;
|
||||
|
||||
/*
|
||||
* Program the location of the UF header table into the SCU.
|
||||
* Notes:
|
||||
* - The address must align on a 64-byte boundary. Guaranteed to be
|
||||
* on 64-byte boundary already 1KB boundary for unsolicited frames.
|
||||
* - Program unused header entries to overlap with the last
|
||||
* unsolicited frame. The silicon will never DMA to these unused
|
||||
* headers, since we program the UF address table pointers to
|
||||
* NULL. */
|
||||
uf_control->headers.physical_address = uf_buffer_phys_address;
|
||||
sci_physical_address_add(
|
||||
uf_control->headers.physical_address, used_uf_buffer_bytes);
|
||||
sci_physical_address_subtract(
|
||||
uf_control->headers.physical_address, unused_uf_header_bytes);
|
||||
uf_control->headers.array
|
||||
= (struct scu_unsolicited_frame_header *)
|
||||
scic_cb_get_virtual_address(
|
||||
controller, uf_control->headers.physical_address
|
||||
);
|
||||
|
||||
/*
|
||||
* Program the location of the UF address table into the SCU.
|
||||
* Notes:
|
||||
* - The address must align on a 64-bit boundary. Guaranteed to be on 64
|
||||
* byte boundary already due to above programming headers being on a
|
||||
* 64-bit boundary and headers are on a 64-bytes in size. */
|
||||
uf_control->address_table.physical_address = uf_buffer_phys_address;
|
||||
sci_physical_address_add(
|
||||
uf_control->address_table.physical_address, used_uf_buffer_bytes);
|
||||
sci_physical_address_add(
|
||||
uf_control->address_table.physical_address, used_uf_header_bytes);
|
||||
uf_control->address_table.array
|
||||
= (dma_addr_t *)
|
||||
scic_cb_get_virtual_address(
|
||||
controller, uf_control->address_table.physical_address
|
||||
);
|
||||
|
||||
uf_control->get = 0;
|
||||
|
||||
/*
|
||||
* UF buffer requirements are:
|
||||
* - The last entry in the UF queue is not NULL.
|
||||
* - There is a power of 2 number of entries (NULL or not-NULL)
|
||||
* programmed into the queue.
|
||||
* - Aligned on a 1KB boundary. */
|
||||
|
||||
/*
|
||||
* If the user provided less then the maximum amount of memory,
|
||||
* then be sure that we programm the first entries in the UF
|
||||
* address table to NULL. */
|
||||
scic_sds_unsolicited_frame_control_construct_frames(
|
||||
uf_control,
|
||||
uf_buffer_phys_address,
|
||||
(unsigned long)mde->virtual_address,
|
||||
unused_uf_header_entries,
|
||||
used_uf_header_entries
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the frame header for the specified frame index.
|
||||
* @uf_control:
|
||||
* @frame_index:
|
||||
* @frame_header:
|
||||
*
|
||||
* enum sci_status
|
||||
*/
|
||||
enum sci_status scic_sds_unsolicited_frame_control_get_header(
|
||||
struct scic_sds_unsolicited_frame_control *uf_control,
|
||||
u32 frame_index,
|
||||
void **frame_header)
|
||||
{
|
||||
if (frame_index < uf_control->address_table.count) {
|
||||
/*
|
||||
* Skip the first word in the frame since this is a controll word used
|
||||
* by the hardware. */
|
||||
*frame_header = &uf_control->buffers.array[frame_index].header->data;
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the frame buffer for the specified frame index.
|
||||
* @uf_control:
|
||||
* @frame_index:
|
||||
* @frame_buffer:
|
||||
*
|
||||
* enum sci_status
|
||||
*/
|
||||
enum sci_status scic_sds_unsolicited_frame_control_get_buffer(
|
||||
struct scic_sds_unsolicited_frame_control *uf_control,
|
||||
u32 frame_index,
|
||||
void **frame_buffer)
|
||||
{
|
||||
if (frame_index < uf_control->address_table.count) {
|
||||
*frame_buffer = uf_control->buffers.array[frame_index].buffer;
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method releases the frame once this is done the frame is available for
|
||||
* re-use by the hardware. The data contained in the frame header and frame
|
||||
* buffer is no longer valid.
|
||||
* @uf_control: This parameter specifies the UF control object
|
||||
* @frame_index: This parameter specifies the frame index to attempt to release.
|
||||
*
|
||||
* This method returns an indication to the caller as to whether the
|
||||
* unsolicited frame get pointer should be updated. true This value indicates
|
||||
* the unsolicited frame get pointer should be updated (i.e. write
|
||||
* SCU_UFQGP_WRITE). false This value indicates the get pointer should not be
|
||||
* updated.
|
||||
*/
|
||||
bool scic_sds_unsolicited_frame_control_release_frame(
|
||||
struct scic_sds_unsolicited_frame_control *uf_control,
|
||||
u32 frame_index)
|
||||
{
|
||||
u32 frame_get;
|
||||
u32 frame_cycle;
|
||||
|
||||
frame_get = uf_control->get & (uf_control->address_table.count - 1);
|
||||
frame_cycle = uf_control->get & uf_control->address_table.count;
|
||||
|
||||
/*
|
||||
* In the event there are NULL entries in the UF table, we need to
|
||||
* advance the get pointer in order to find out if this frame should
|
||||
* be released (i.e. update the get pointer). */
|
||||
while (((lower_32_bits(uf_control->address_table.array[frame_get])
|
||||
== 0) &&
|
||||
(upper_32_bits(uf_control->address_table.array[frame_get])
|
||||
== 0)) &&
|
||||
(frame_get < uf_control->address_table.count))
|
||||
frame_get++;
|
||||
|
||||
/*
|
||||
* The table has a NULL entry as it's last element. This is
|
||||
* illegal. */
|
||||
BUG_ON(frame_get >= uf_control->address_table.count);
|
||||
|
||||
if (frame_index < uf_control->address_table.count) {
|
||||
uf_control->buffers.array[frame_index].state = UNSOLICITED_FRAME_RELEASED;
|
||||
|
||||
/*
|
||||
* The frame index is equal to the current get pointer so we
|
||||
* can now free up all of the frame entries that */
|
||||
if (frame_get == frame_index) {
|
||||
while (
|
||||
uf_control->buffers.array[frame_get].state
|
||||
== UNSOLICITED_FRAME_RELEASED
|
||||
) {
|
||||
uf_control->buffers.array[frame_get].state = UNSOLICITED_FRAME_EMPTY;
|
||||
|
||||
INCREMENT_QUEUE_GET(
|
||||
frame_get,
|
||||
frame_cycle,
|
||||
uf_control->address_table.count - 1,
|
||||
uf_control->address_table.count
|
||||
);
|
||||
}
|
||||
|
||||
uf_control->get =
|
||||
(SCU_UFQGP_GEN_BIT(ENABLE_BIT) | frame_cycle | frame_get);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
/*
|
||||
* Frames remain in use until we advance the get pointer
|
||||
* so there is nothing we can do here */
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
286
drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h
Normal file
286
drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h
Normal file
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains all of the unsolicited frame related management for the
|
||||
* address table, the headers, and actual payload buffers.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_
|
||||
#define _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_
|
||||
|
||||
#include "scu_unsolicited_frame.h"
|
||||
#include "sci_memory_descriptor_list.h"
|
||||
#include "scu_constants.h"
|
||||
#include "sci_status.h"
|
||||
|
||||
/**
|
||||
* enum UNSOLICITED_FRAME_STATE -
|
||||
*
|
||||
* This enumeration represents the current unsolicited frame state. The
|
||||
* controller object can not updtate the hardware unsolicited frame put pointer
|
||||
* unless it has already processed the priror unsolicited frames.
|
||||
*/
|
||||
enum UNSOLICITED_FRAME_STATE {
|
||||
/**
|
||||
* This state is when the frame is empty and not in use. It is
|
||||
* different from the released state in that the hardware could DMA
|
||||
* data to this frame buffer.
|
||||
*/
|
||||
UNSOLICITED_FRAME_EMPTY,
|
||||
|
||||
/**
|
||||
* This state is set when the frame buffer is in use by by some
|
||||
* object in the system.
|
||||
*/
|
||||
UNSOLICITED_FRAME_IN_USE,
|
||||
|
||||
/**
|
||||
* This state is set when the frame is returned to the free pool
|
||||
* but one or more frames prior to this one are still in use.
|
||||
* Once all of the frame before this one are freed it will go to
|
||||
* the empty state.
|
||||
*/
|
||||
UNSOLICITED_FRAME_RELEASED,
|
||||
|
||||
UNSOLICITED_FRAME_MAX_STATES
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_sds_unsolicited_frame -
|
||||
*
|
||||
* This is the unsolicited frame data structure it acts as the container for
|
||||
* the current frame state, frame header and frame buffer.
|
||||
*/
|
||||
struct scic_sds_unsolicited_frame {
|
||||
/**
|
||||
* This field contains the current frame state
|
||||
*/
|
||||
enum UNSOLICITED_FRAME_STATE state;
|
||||
|
||||
/**
|
||||
* This field points to the frame header data.
|
||||
*/
|
||||
struct scu_unsolicited_frame_header *header;
|
||||
|
||||
/**
|
||||
* This field points to the frame buffer data.
|
||||
*/
|
||||
void *buffer;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_sds_uf_header_array -
|
||||
*
|
||||
* This structure contains all of the unsolicited frame header information.
|
||||
*/
|
||||
struct scic_sds_uf_header_array {
|
||||
/**
|
||||
* This field is represents a virtual pointer to the start
|
||||
* address of the UF address table. The table contains
|
||||
* 64-bit pointers as required by the hardware.
|
||||
*/
|
||||
struct scu_unsolicited_frame_header *array;
|
||||
|
||||
/**
|
||||
* This field specifies the physical address location for the UF
|
||||
* buffer array.
|
||||
*/
|
||||
dma_addr_t physical_address;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Determine the size of the unsolicited frame array including
|
||||
* unused buffers. */
|
||||
#if SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES
|
||||
#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MIN_UF_TABLE_ENTRIES
|
||||
#else
|
||||
#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MAX_UNSOLICITED_FRAMES
|
||||
#endif /* SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES */
|
||||
|
||||
/**
|
||||
* struct scic_sds_uf_buffer_array -
|
||||
*
|
||||
* This structure contains all of the unsolicited frame buffer (actual payload)
|
||||
* information.
|
||||
*/
|
||||
struct scic_sds_uf_buffer_array {
|
||||
/**
|
||||
* This field is the minimum number of unsolicited frames supported by the
|
||||
* hardware and the number of unsolicited frames requested by the software.
|
||||
*/
|
||||
u32 count;
|
||||
|
||||
/**
|
||||
* This field is the SCIC_UNSOLICITED_FRAME data its used to manage
|
||||
* the data for the unsolicited frame requests. It also represents
|
||||
* the virtual address location that corresponds to the
|
||||
* physical_address field.
|
||||
*/
|
||||
struct scic_sds_unsolicited_frame array[SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE];
|
||||
|
||||
/**
|
||||
* This field specifies the physical address location for the UF
|
||||
* buffer array.
|
||||
*/
|
||||
dma_addr_t physical_address;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_sds_uf_address_table_array -
|
||||
*
|
||||
* This object maintains all of the unsolicited frame address table specific
|
||||
* data. The address table is a collection of 64-bit pointers that point to
|
||||
* 1KB buffers into which the silicon will DMA unsolicited frames.
|
||||
*/
|
||||
struct scic_sds_uf_address_table_array {
|
||||
/**
|
||||
* This field specifies the actual programmed size of the
|
||||
* unsolicited frame buffer address table. The size of the table
|
||||
* can be larger than the actual number of UF buffers, but it must
|
||||
* be a power of 2 and the last entry in the table is not allowed
|
||||
* to be NULL.
|
||||
*/
|
||||
u32 count;
|
||||
|
||||
/**
|
||||
* This field represents a virtual pointer that refers to the
|
||||
* starting address of the UF address table.
|
||||
* 64-bit pointers are required by the hardware.
|
||||
*/
|
||||
dma_addr_t *array;
|
||||
|
||||
/**
|
||||
* This field specifies the physical address location for the UF
|
||||
* address table.
|
||||
*/
|
||||
dma_addr_t physical_address;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scic_sds_unsolicited_frame_control -
|
||||
*
|
||||
* This object contains all of the data necessary to handle unsolicited frames.
|
||||
*/
|
||||
struct scic_sds_unsolicited_frame_control {
|
||||
/**
|
||||
* This field is the software copy of the unsolicited frame queue
|
||||
* get pointer. The controller object writes this value to the
|
||||
* hardware to let the hardware put more unsolicited frame entries.
|
||||
*/
|
||||
u32 get;
|
||||
|
||||
/**
|
||||
* This field contains all of the unsolicited frame header
|
||||
* specific fields.
|
||||
*/
|
||||
struct scic_sds_uf_header_array headers;
|
||||
|
||||
/**
|
||||
* This field contains all of the unsolicited frame buffer
|
||||
* specific fields.
|
||||
*/
|
||||
struct scic_sds_uf_buffer_array buffers;
|
||||
|
||||
/**
|
||||
* This field contains all of the unsolicited frame address table
|
||||
* specific fields.
|
||||
*/
|
||||
struct scic_sds_uf_address_table_array address_table;
|
||||
|
||||
};
|
||||
|
||||
void scic_sds_unsolicited_frame_control_set_address_table_count(
|
||||
struct scic_sds_unsolicited_frame_control *uf_control);
|
||||
|
||||
struct scic_sds_controller;
|
||||
void scic_sds_unsolicited_frame_control_construct(
|
||||
struct scic_sds_unsolicited_frame_control *uf_control,
|
||||
struct sci_physical_memory_descriptor *mde,
|
||||
struct scic_sds_controller *this_controller);
|
||||
|
||||
enum sci_status scic_sds_unsolicited_frame_control_get_header(
|
||||
struct scic_sds_unsolicited_frame_control *uf_control,
|
||||
u32 frame_index,
|
||||
void **frame_header);
|
||||
|
||||
enum sci_status scic_sds_unsolicited_frame_control_get_buffer(
|
||||
struct scic_sds_unsolicited_frame_control *uf_control,
|
||||
u32 frame_index,
|
||||
void **frame_buffer);
|
||||
|
||||
bool scic_sds_unsolicited_frame_control_release_frame(
|
||||
struct scic_sds_unsolicited_frame_control *uf_control,
|
||||
u32 frame_index);
|
||||
|
||||
/**
|
||||
* scic_sds_unsolicited_frame_control_get_mde_size() -
|
||||
*
|
||||
* This macro simply calculates the size of the memory descriptor entry that
|
||||
* relates to unsolicited frames and the surrounding silicon memory required to
|
||||
* utilize it.
|
||||
*/
|
||||
#define scic_sds_unsolicited_frame_control_get_mde_size(uf_control) \
|
||||
(((uf_control).buffers.count * SCU_UNSOLICITED_FRAME_BUFFER_SIZE) \
|
||||
+ ((uf_control).address_table.count * sizeof(dma_addr_t)) \
|
||||
+ ((uf_control).buffers.count * sizeof(struct scu_unsolicited_frame_header)))
|
||||
|
||||
#endif /* _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ */
|
||||
148
drivers/scsi/isci/core/scic_task_request.h
Normal file
148
drivers/scsi/isci/core/scic_task_request.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_TASK_REQUEST_H_
|
||||
#define _SCIC_TASK_REQUEST_H_
|
||||
|
||||
/**
|
||||
* This file contains the structures and interface methods that can be
|
||||
* referenced and used by the SCI user for to utilize task management
|
||||
* requests.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "sci_types.h"
|
||||
#include "sci_status.h"
|
||||
|
||||
struct scic_sds_request;
|
||||
struct scic_sds_remote_device;
|
||||
struct scic_sds_controller;
|
||||
|
||||
|
||||
/**
|
||||
* scic_task_request_construct() - This method is called by the SCI user to
|
||||
* construct all SCI Core task management requests, regardless of protocol.
|
||||
* Memory initialization and functionality common to all task request types
|
||||
* is performed in this method.
|
||||
* @scic_controller: the handle to the core controller object for which to
|
||||
* build the task managmement request.
|
||||
* @scic_remote_device: the handle to the core remote device object for which
|
||||
* to build the task management request. passed, then a copy of the request
|
||||
* is built internally. The request will be copied into the actual
|
||||
* controller request memory when the task is allocated internally during
|
||||
* the scic_controller_start_task() method.
|
||||
* @io_tag: This parameter specifies the IO tag to be associated with this
|
||||
* request. If SCI_CONTROLLER_INVALID_IO_TAG is passed, then a copy of the
|
||||
* request is built internally. The request will be copied into the actual
|
||||
* controller request memory when the IO tag is allocated internally during
|
||||
* the scic_controller_start_io() method.
|
||||
* @user_task_request_object: This parameter specifies the user task request to
|
||||
* be utilized during construction. This task pointer will become the
|
||||
* associated object for the core task request object.
|
||||
* @scic_task_request_memory: This parameter specifies the memory location to
|
||||
* be utilized when building the core request.
|
||||
* @new_scic_task_request_handle: This parameter specifies a pointer to the
|
||||
* handle the core will expect in further interactions with the core task
|
||||
* request object.
|
||||
*
|
||||
* The SCI core implementation will create an association between the user task
|
||||
* request object and the core task request object. Indicate if the controller
|
||||
* successfully built the task request. SCI_SUCCESS This value is returned if
|
||||
* the task request was successfully built.
|
||||
*/
|
||||
enum sci_status scic_task_request_construct(
|
||||
struct scic_sds_controller *scic_controller,
|
||||
struct scic_sds_remote_device *scic_remote_device,
|
||||
u16 io_tag,
|
||||
void *user_task_request_object,
|
||||
void *scic_task_request_memory,
|
||||
struct scic_sds_request **new_scic_task_request_handle);
|
||||
|
||||
/**
|
||||
* scic_task_request_construct_ssp() - This method is called by the SCI user to
|
||||
* construct all SCI Core SSP task management requests. Memory
|
||||
* initialization and functionality common to all task request types is
|
||||
* performed in this method.
|
||||
* @scic_task_request: This parameter specifies the handle to the core task
|
||||
* request object for which to construct a SATA specific task management
|
||||
* request.
|
||||
*
|
||||
* Indicate if the controller successfully built the task request. SCI_SUCCESS
|
||||
* This value is returned if the task request was successfully built.
|
||||
*/
|
||||
enum sci_status scic_task_request_construct_ssp(
|
||||
struct scic_sds_request *scic_task_request);
|
||||
|
||||
/**
|
||||
* scic_task_request_construct_sata() - This method is called by the SCI user
|
||||
* to construct all SCI Core SATA task management requests. Memory
|
||||
* initialization and functionality common to all task request types is
|
||||
* performed in this method.
|
||||
* @scic_task_request_handle: This parameter specifies the handle to the core
|
||||
* task request object for which to construct a SATA specific task
|
||||
* management request.
|
||||
*
|
||||
* Indicate if the controller successfully built the task request. SCI_SUCCESS
|
||||
* This value is returned if the task request was successfully built.
|
||||
*/
|
||||
enum sci_status scic_task_request_construct_sata(
|
||||
struct scic_sds_request *scic_task_request_handle);
|
||||
|
||||
|
||||
|
||||
#endif /* _SCIC_TASK_REQUEST_H_ */
|
||||
|
||||
740
drivers/scsi/isci/core/scic_user_callback.h
Normal file
740
drivers/scsi/isci/core/scic_user_callback.h
Normal file
@@ -0,0 +1,740 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCIC_USER_CALLBACK_H_
|
||||
#define _SCIC_USER_CALLBACK_H_
|
||||
|
||||
/**
|
||||
* This file contains all of the interface methods/macros that must be
|
||||
* implemented by an SCI Core user.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "sci_types.h"
|
||||
#include "sci_status.h"
|
||||
|
||||
struct scic_sds_request;
|
||||
struct scic_sds_phy;
|
||||
struct scic_sds_port;
|
||||
struct scic_sds_remote_device;
|
||||
struct scic_sds_controller;
|
||||
|
||||
/**
|
||||
* scic_cb_timer_create() - This callback method asks the user to create a
|
||||
* timer and provide a handle for this timer for use in further timer
|
||||
* interactions.
|
||||
* @controller: This parameter specifies the controller with which this timer
|
||||
* is to be associated.
|
||||
* @timer_callback: This parameter specifies the callback method to be invoked
|
||||
* whenever the timer expires.
|
||||
* @cookie: This parameter specifies a piece of information that the user must
|
||||
* retain. This cookie is to be supplied by the user anytime a timeout
|
||||
* occurs for the created timer.
|
||||
*
|
||||
* The "timer_callback" method should be executed in a mutually exlusive manner
|
||||
* from the controller completion handler handler (refer to
|
||||
* scic_controller_get_handler_methods()). This method returns a handle to a
|
||||
* timer object created by the user. The handle will be utilized for all
|
||||
* further interactions relating to this timer.
|
||||
*/
|
||||
void *scic_cb_timer_create(
|
||||
struct scic_sds_controller *controller,
|
||||
void (*timer_callback)(void *),
|
||||
void *cookie);
|
||||
|
||||
|
||||
/**
|
||||
* scic_cb_timer_start() - This callback method asks the user to start the
|
||||
* supplied timer.
|
||||
* @controller: This parameter specifies the controller with which this timer
|
||||
* is to associated.
|
||||
* @timer: This parameter specifies the timer to be started.
|
||||
* @milliseconds: This parameter specifies the number of milliseconds for which
|
||||
* to stall. The operating system driver is allowed to round this value up
|
||||
* where necessary.
|
||||
*
|
||||
* All timers in the system started by the SCI Core are one shot timers.
|
||||
* Therefore, the SCI user should make sure that it removes the timer from it's
|
||||
* list when a timer actually fires. Additionally, SCI Core user's should be
|
||||
* able to handle calls from the SCI Core to stop a timer that may already be
|
||||
* stopped. none
|
||||
*/
|
||||
void scic_cb_timer_start(
|
||||
struct scic_sds_controller *controller,
|
||||
void *timer,
|
||||
u32 milliseconds);
|
||||
|
||||
/**
|
||||
* scic_cb_timer_stop() - This callback method asks the user to stop the
|
||||
* supplied timer.
|
||||
* @controller: This parameter specifies the controller with which this timer
|
||||
* is to associated.
|
||||
* @timer: This parameter specifies the timer to be stopped.
|
||||
*
|
||||
*/
|
||||
void scic_cb_timer_stop(
|
||||
struct scic_sds_controller *controller,
|
||||
void *timer);
|
||||
|
||||
/**
|
||||
* scic_cb_stall_execution() - This method is called when the core requires the
|
||||
* OS driver to stall execution. This method is utilized during
|
||||
* initialization or non-performance paths only.
|
||||
* @microseconds: This parameter specifies the number of microseconds for which
|
||||
* to stall. The operating system driver is allowed to round this value up
|
||||
* where necessary.
|
||||
*
|
||||
* none.
|
||||
*/
|
||||
void scic_cb_stall_execution(
|
||||
u32 microseconds);
|
||||
|
||||
/**
|
||||
* scic_cb_controller_start_complete() - This user callback will inform the
|
||||
* user that the controller has finished the start process.
|
||||
* @controller: This parameter specifies the controller that was started.
|
||||
* @completion_status: This parameter specifies the results of the start
|
||||
* operation. SCI_SUCCESS indicates successful completion.
|
||||
*
|
||||
*/
|
||||
void scic_cb_controller_start_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
enum sci_status completion_status);
|
||||
|
||||
/**
|
||||
* scic_cb_controller_stop_complete() - This user callback will inform the user
|
||||
* that the controller has finished the stop process.
|
||||
* @controller: This parameter specifies the controller that was stopped.
|
||||
* @completion_status: This parameter specifies the results of the stop
|
||||
* operation. SCI_SUCCESS indicates successful completion.
|
||||
*
|
||||
*/
|
||||
void scic_cb_controller_stop_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
enum sci_status completion_status);
|
||||
|
||||
/**
|
||||
* scic_cb_io_request_complete() - This user callback will inform the user that
|
||||
* an IO request has completed.
|
||||
* @controller: This parameter specifies the controller on which the IO is
|
||||
* completing.
|
||||
* @remote_device: This parameter specifies the remote device on which this IO
|
||||
* request is completing.
|
||||
* @io_request: This parameter specifies the IO request that has completed.
|
||||
* @completion_status: This parameter specifies the results of the IO request
|
||||
* operation. SCI_SUCCESS indicates successful completion.
|
||||
*
|
||||
*/
|
||||
void scic_cb_io_request_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
struct scic_sds_request *io_request,
|
||||
enum sci_io_status completion_status);
|
||||
|
||||
/**
|
||||
* scic_cb_task_request_complete() - This user callback will inform the user
|
||||
* that a task management request completed.
|
||||
* @controller: This parameter specifies the controller on which the task
|
||||
* management request is completing.
|
||||
* @remote_device: This parameter specifies the remote device on which this
|
||||
* task management request is completing.
|
||||
* @task_request: This parameter specifies the task management request that has
|
||||
* completed.
|
||||
* @completion_status: This parameter specifies the results of the IO request
|
||||
* operation. SCI_SUCCESS indicates successful completion.
|
||||
*
|
||||
*/
|
||||
void scic_cb_task_request_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
struct scic_sds_request *task_request,
|
||||
enum sci_task_status completion_status);
|
||||
|
||||
#ifndef SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED
|
||||
/**
|
||||
* scic_cb_io_request_get_physical_address() - This callback method asks the
|
||||
* user to provide the physical address for the supplied virtual address
|
||||
* when building an io request object.
|
||||
* @controller: This parameter is the core controller object handle.
|
||||
* @io_request: This parameter is the io request object handle for which the
|
||||
* physical address is being requested.
|
||||
* @virtual_address: This paramter is the virtual address which is to be
|
||||
* returned as a physical address.
|
||||
* @physical_address: The physical address for the supplied virtual address.
|
||||
*
|
||||
* None.
|
||||
*/
|
||||
void scic_cb_io_request_get_physical_address(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_request *io_request,
|
||||
void *virtual_address,
|
||||
dma_addr_t *physical_address);
|
||||
#endif /* SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED */
|
||||
|
||||
/**
|
||||
* scic_cb_io_request_get_transfer_length() - This callback method asks the
|
||||
* user to provide the number of bytes to be transfered as part of this
|
||||
* request.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the number of payload data bytes to be transfered for
|
||||
* this IO request.
|
||||
*/
|
||||
u32 scic_cb_io_request_get_transfer_length(
|
||||
void *scic_user_io_request);
|
||||
|
||||
/**
|
||||
* scic_cb_io_request_get_data_direction() - This callback method asks the user
|
||||
* to provide the data direction for this request.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the value of SCI_IO_REQUEST_DATA_OUT or
|
||||
* SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA.
|
||||
*/
|
||||
SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction(
|
||||
void *scic_user_io_request);
|
||||
|
||||
#ifndef SCI_SGL_OPTIMIZATION_ENABLED
|
||||
/**
|
||||
* scic_cb_io_request_get_next_sge() - This callback method asks the user to
|
||||
* provide the address to where the next Scatter-Gather Element is located.
|
||||
* Details regarding usage: - Regarding the first SGE: the user should
|
||||
* initialize an index, or a pointer, prior to construction of the request
|
||||
* that will reference the very first scatter-gather element. This is
|
||||
* important since this method is called for every scatter-gather element,
|
||||
* including the first element. - Regarding the last SGE: the user should
|
||||
* return NULL from this method when this method is called and the SGL has
|
||||
* exhausted all elements.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
* @current_sge_address: This parameter specifies the address for the current
|
||||
* SGE (i.e. the one that has just processed).
|
||||
* @next_sge: An address specifying the location for the next scatter gather
|
||||
* element to be processed.
|
||||
*
|
||||
* None
|
||||
*/
|
||||
void scic_cb_io_request_get_next_sge(
|
||||
void *scic_user_io_request,
|
||||
void *current_sge_address,
|
||||
void **next_sge);
|
||||
#endif /* SCI_SGL_OPTIMIZATION_ENABLED */
|
||||
|
||||
/**
|
||||
* scic_cb_sge_get_address_field() - This callback method asks the user to
|
||||
* provide the contents of the "address" field in the Scatter-Gather Element.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
* @sge_address: This parameter specifies the address for the SGE from which to
|
||||
* retrieve the address field.
|
||||
*
|
||||
* A physical address specifying the contents of the SGE's address field.
|
||||
*/
|
||||
dma_addr_t scic_cb_sge_get_address_field(
|
||||
void *scic_user_io_request,
|
||||
void *sge_address);
|
||||
|
||||
/**
|
||||
* scic_cb_sge_get_length_field() - This callback method asks the user to
|
||||
* provide the contents of the "length" field in the Scatter-Gather Element.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
* @sge_address: This parameter specifies the address for the SGE from which to
|
||||
* retrieve the address field.
|
||||
*
|
||||
* This method returns the length field specified inside the SGE referenced by
|
||||
* the sge_address parameter.
|
||||
*/
|
||||
u32 scic_cb_sge_get_length_field(
|
||||
void *scic_user_io_request,
|
||||
void *sge_address);
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_io_request_get_cdb_address() - This callback method asks the
|
||||
* user to provide the address for the command descriptor block (CDB)
|
||||
* associated with this IO request.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the virtual address of the CDB.
|
||||
*/
|
||||
void *scic_cb_ssp_io_request_get_cdb_address(
|
||||
void *scic_user_io_request);
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_io_request_get_cdb_length() - This callback method asks the user
|
||||
* to provide the length of the command descriptor block (CDB) associated
|
||||
* with this IO request.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the length of the CDB.
|
||||
*/
|
||||
u32 scic_cb_ssp_io_request_get_cdb_length(
|
||||
void *scic_user_io_request);
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_io_request_get_lun() - This callback method asks the user to
|
||||
* provide the Logical Unit (LUN) associated with this IO request.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* The contents of the value returned from this callback are defined by the
|
||||
* protocol standard (e.g. T10 SAS specification). Please refer to the
|
||||
* transport command information unit description in the associated standard.
|
||||
* This method returns the LUN associated with this request. This should be u64?
|
||||
*/
|
||||
u32 scic_cb_ssp_io_request_get_lun(
|
||||
void *scic_user_io_request);
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_io_request_get_task_attribute() - This callback method asks the
|
||||
* user to provide the task attribute associated with this IO request.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* The contents of the value returned from this callback are defined by the
|
||||
* protocol standard (e.g. T10 SAS specification). Please refer to the
|
||||
* transport command information unit description in the associated standard.
|
||||
* This method returns the task attribute associated with this IO request.
|
||||
*/
|
||||
u32 scic_cb_ssp_io_request_get_task_attribute(
|
||||
void *scic_user_io_request);
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_io_request_get_command_priority() - This callback method asks
|
||||
* the user to provide the command priority associated with this IO request.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* The contents of the value returned from this callback are defined by the
|
||||
* protocol standard (e.g. T10 SAS specification). Please refer to the
|
||||
* transport command information unit description in the associated standard.
|
||||
* This method returns the command priority associated with this IO request.
|
||||
*/
|
||||
u32 scic_cb_ssp_io_request_get_command_priority(
|
||||
void *scic_user_io_request);
|
||||
|
||||
/**
|
||||
* scic_cb_io_request_do_copy_rx_frames() - This callback method asks the user
|
||||
* if the received RX frame data is to be copied to the SGL or should be
|
||||
* stored by the SCI core to be retrieved later with the
|
||||
* scic_io_request_get_rx_frame().
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns true if the SCI core should copy the received frame data
|
||||
* to the SGL location or false if the SCI user wants to retrieve the frame
|
||||
* data at a later time.
|
||||
*/
|
||||
bool scic_cb_io_request_do_copy_rx_frames(
|
||||
void *scic_user_io_request);
|
||||
|
||||
/**
|
||||
* scic_cb_request_get_sat_protocol() - This callback method asks the user to
|
||||
* return the SAT protocol definition for this IO request. This method is
|
||||
* only called by the SCI core if the request type constructed is SATA.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns one of the sat.h defined protocols for the given io
|
||||
* request.
|
||||
*/
|
||||
u8 scic_cb_request_get_sat_protocol(
|
||||
void *scic_user_io_request);
|
||||
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_task_request_get_lun() - This method returns the Logical Unit to
|
||||
* be utilized for this task management request.
|
||||
* @scic_user_task_request: This parameter points to the user's task request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* The contents of the value returned from this callback are defined by the
|
||||
* protocol standard (e.g. T10 SAS specification). Please refer to the
|
||||
* transport task information unit description in the associated standard. This
|
||||
* method returns the LUN associated with this request. This should be u64?
|
||||
*/
|
||||
u32 scic_cb_ssp_task_request_get_lun(
|
||||
void *scic_user_task_request);
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_task_request_get_function() - This method returns the task
|
||||
* management function to be utilized for this task request.
|
||||
* @scic_user_task_request: This parameter points to the user's task request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* The contents of the value returned from this callback are defined by the
|
||||
* protocol standard (e.g. T10 SAS specification). Please refer to the
|
||||
* transport task information unit description in the associated standard. This
|
||||
* method returns an unsigned byte representing the task management function to
|
||||
* be performed.
|
||||
*/
|
||||
u8 scic_cb_ssp_task_request_get_function(
|
||||
void *scic_user_task_request);
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_task_request_get_io_tag_to_manage() - This method returns the
|
||||
* task management IO tag to be managed. Depending upon the task management
|
||||
* function the value returned from this method may be ignored.
|
||||
* @scic_user_task_request: This parameter points to the user's task request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns an unsigned 16-bit word depicting the IO tag to be
|
||||
* managed.
|
||||
*/
|
||||
u16 scic_cb_ssp_task_request_get_io_tag_to_manage(
|
||||
void *scic_user_task_request);
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_task_request_get_response_data_address() - This callback method
|
||||
* asks the user to provide the virtual address of the response data buffer
|
||||
* for the supplied IO request.
|
||||
* @scic_user_task_request: This parameter points to the user's task request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the virtual address for the response data buffer
|
||||
* associated with this IO request.
|
||||
*/
|
||||
void *scic_cb_ssp_task_request_get_response_data_address(
|
||||
void *scic_user_task_request);
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_task_request_get_response_data_length() - This callback method
|
||||
* asks the user to provide the length of the response data buffer for the
|
||||
* supplied IO request.
|
||||
* @scic_user_task_request: This parameter points to the user's task request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the length of the response buffer data associated with
|
||||
* this IO request.
|
||||
*/
|
||||
u32 scic_cb_ssp_task_request_get_response_data_length(
|
||||
void *scic_user_task_request);
|
||||
|
||||
/**
|
||||
* scic_cb_pci_get_bar() - In this method the user must return the base address
|
||||
* register (BAR) value for the supplied base address register number.
|
||||
* @controller: The controller for which to retrieve the bar number.
|
||||
* @bar_number: This parameter depicts the BAR index/number to be read.
|
||||
*
|
||||
* Return a pointer value indicating the contents of the BAR. NULL indicates an
|
||||
* invalid BAR index/number was specified. All other values indicate a valid
|
||||
* VIRTUAL address from the BAR.
|
||||
*/
|
||||
void *scic_cb_pci_get_bar(
|
||||
struct scic_sds_controller *controller,
|
||||
u16 bar_number);
|
||||
|
||||
/**
|
||||
* scic_cb_get_virtual_address() - This callback method asks the user to
|
||||
* provide the virtual address for the supplied physical address.
|
||||
* @controller: This parameter is the core controller object handle.
|
||||
* @physical_address: This parameter is the physical address which is to be
|
||||
* returned as a virtual address.
|
||||
*
|
||||
* The method returns the virtual address for the supplied physical address.
|
||||
*/
|
||||
void *scic_cb_get_virtual_address(
|
||||
struct scic_sds_controller *controller,
|
||||
dma_addr_t physical_address);
|
||||
|
||||
/**
|
||||
* scic_cb_port_stop_complete() - This method informs the user when a stop
|
||||
* operation on the port has completed.
|
||||
* @controller: This parameter represents the controller which contains the
|
||||
* port.
|
||||
* @port: This parameter specifies the SCI port object for which the callback
|
||||
* is being invoked.
|
||||
* @completion_status: This parameter specifies the status for the operation
|
||||
* being completed.
|
||||
*
|
||||
*/
|
||||
void scic_cb_port_stop_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port,
|
||||
enum sci_status completion_status);
|
||||
|
||||
/**
|
||||
* scic_cb_port_hard_reset_complete() - This method informs the user when a
|
||||
* hard reset on the port has completed. This hard reset could have been
|
||||
* initiated by the user or by the remote port.
|
||||
* @controller: This parameter represents the controller which contains the
|
||||
* port.
|
||||
* @port: This parameter specifies the SCI port object for which the callback
|
||||
* is being invoked.
|
||||
* @completion_status: This parameter specifies the status for the operation
|
||||
* being completed.
|
||||
*
|
||||
*/
|
||||
void scic_cb_port_hard_reset_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port,
|
||||
enum sci_status completion_status);
|
||||
|
||||
/**
|
||||
* scic_cb_port_ready() - This method informs the user that the port is now in
|
||||
* a ready state and can be utilized to issue IOs.
|
||||
* @controller: This parameter represents the controller which contains the
|
||||
* port.
|
||||
* @port: This parameter specifies the SCI port object for which the callback
|
||||
* is being invoked.
|
||||
*
|
||||
*/
|
||||
void scic_cb_port_ready(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port);
|
||||
|
||||
/**
|
||||
* scic_cb_port_not_ready() - This method informs the user that the port is now
|
||||
* not in a ready (i.e. busy) state and can't be utilized to issue IOs.
|
||||
* @controller: This parameter represents the controller which contains the
|
||||
* port.
|
||||
* @port: This parameter specifies the SCI port object for which the callback
|
||||
* is being invoked.
|
||||
* @reason_code: This parameter specifies the reason for the port not ready
|
||||
* callback.
|
||||
*
|
||||
*/
|
||||
void scic_cb_port_not_ready(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port,
|
||||
u32 reason_code);
|
||||
|
||||
/**
|
||||
* scic_cb_port_invalid_link_up() - This method informs the SCI Core user that
|
||||
* a phy/link became ready, but the phy is not allowed in the port. In some
|
||||
* situations the underlying hardware only allows for certain phy to port
|
||||
* mappings. If these mappings are violated, then this API is invoked.
|
||||
* @controller: This parameter represents the controller which contains the
|
||||
* port.
|
||||
* @port: This parameter specifies the SCI port object for which the callback
|
||||
* is being invoked.
|
||||
* @phy: This parameter specifies the phy that came ready, but the phy can't be
|
||||
* a valid member of the port.
|
||||
*
|
||||
*/
|
||||
void scic_cb_port_invalid_link_up(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy);
|
||||
|
||||
/**
|
||||
* scic_cb_port_bc_change_primitive_received() - This callback method informs
|
||||
* the user that a broadcast change primitive was received.
|
||||
* @controller: This parameter represents the controller which contains the
|
||||
* port.
|
||||
* @port: This parameter specifies the SCI port object for which the callback
|
||||
* is being invoked. For instances where the phy on which the primitive was
|
||||
* received is not part of a port, this parameter will be
|
||||
* SCI_INVALID_HANDLE_T.
|
||||
* @phy: This parameter specifies the phy on which the primitive was received.
|
||||
*
|
||||
*/
|
||||
void scic_cb_port_bc_change_primitive_received(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* scic_cb_port_link_up() - This callback method informs the user that a phy
|
||||
* has become operational and is capable of communicating with the remote
|
||||
* end point.
|
||||
* @controller: This parameter represents the controller associated with the
|
||||
* phy.
|
||||
* @port: This parameter specifies the port object for which the user callback
|
||||
* is being invoked. There may be conditions where this parameter can be
|
||||
* SCI_INVALID_HANDLE
|
||||
* @phy: This parameter specifies the phy object for which the user callback is
|
||||
* being invoked.
|
||||
*
|
||||
*/
|
||||
void scic_cb_port_link_up(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy);
|
||||
|
||||
/**
|
||||
* scic_cb_port_link_down() - This callback method informs the user that a phy
|
||||
* is no longer operational and is not capable of communicating with the
|
||||
* remote end point.
|
||||
* @controller: This parameter represents the controller associated with the
|
||||
* phy.
|
||||
* @port: This parameter specifies the port object for which the user callback
|
||||
* is being invoked. There may be conditions where this parameter can be
|
||||
* SCI_INVALID_HANDLE
|
||||
* @phy: This parameter specifies the phy object for which the user callback is
|
||||
* being invoked.
|
||||
*
|
||||
*/
|
||||
void scic_cb_port_link_down(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy);
|
||||
|
||||
/**
|
||||
* scic_cb_remote_device_start_complete() - This user callback method will
|
||||
* inform the user that a start operation has completed.
|
||||
* @controller: This parameter specifies the core controller associated with
|
||||
* the completion callback.
|
||||
* @remote_device: This parameter specifies the remote device associated with
|
||||
* the completion callback.
|
||||
* @completion_status: This parameter specifies the completion status for the
|
||||
* operation.
|
||||
*
|
||||
*/
|
||||
void scic_cb_remote_device_start_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
enum sci_status completion_status);
|
||||
|
||||
/**
|
||||
* scic_cb_remote_device_stop_complete() - This user callback method will
|
||||
* inform the user that a stop operation has completed.
|
||||
* @controller: This parameter specifies the core controller associated with
|
||||
* the completion callback.
|
||||
* @remote_device: This parameter specifies the remote device associated with
|
||||
* the completion callback.
|
||||
* @completion_status: This parameter specifies the completion status for the
|
||||
* operation.
|
||||
*
|
||||
*/
|
||||
void scic_cb_remote_device_stop_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
enum sci_status completion_status);
|
||||
|
||||
/**
|
||||
* scic_cb_remote_device_ready() - This user callback method will inform the
|
||||
* user that a remote device is now capable of handling IO requests.
|
||||
* @controller: This parameter specifies the core controller associated with
|
||||
* the completion callback.
|
||||
* @remote_device: This parameter specifies the remote device associated with
|
||||
* the callback.
|
||||
*
|
||||
*/
|
||||
void scic_cb_remote_device_ready(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device);
|
||||
|
||||
/**
|
||||
* scic_cb_remote_device_not_ready() - This user callback method will inform
|
||||
* the user that a remote device is no longer capable of handling IO
|
||||
* requests (until a ready callback is invoked).
|
||||
* @controller: This parameter specifies the core controller associated with
|
||||
* the completion callback.
|
||||
* @remote_device: This parameter specifies the remote device associated with
|
||||
* the callback.
|
||||
* @reason_code: This paramete specifies the reason the remote device is not
|
||||
* ready.
|
||||
*
|
||||
*/
|
||||
void scic_cb_remote_device_not_ready(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
u32 reason_code);
|
||||
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
/**
|
||||
* scic_cb_stp_packet_io_request_get_cdb_address() - This user callback gets
|
||||
* from stp packet io's user request the CDB address.
|
||||
* @scic_user_io_request:
|
||||
*
|
||||
* The cdb adress.
|
||||
*/
|
||||
void *scic_cb_stp_packet_io_request_get_cdb_address(
|
||||
void *scic_user_io_request);
|
||||
|
||||
/**
|
||||
* scic_cb_stp_packet_io_request_get_cdb_length() - This user callback gets
|
||||
* from stp packet io's user request the CDB length.
|
||||
* @scic_user_io_request:
|
||||
*
|
||||
* The cdb length.
|
||||
*/
|
||||
u32 scic_cb_stp_packet_io_request_get_cdb_length(
|
||||
void *scic_user_io_request);
|
||||
#else /* !defined(DISABLE_ATAPI) */
|
||||
#define scic_cb_stp_packet_io_request_get_cdb_address(scic_user_io_request) NULL
|
||||
#define scic_cb_stp_packet_io_request_get_cdb_length(scic_user_io_request) 0
|
||||
#endif /* !defined(DISABLE_ATAPI) */
|
||||
|
||||
|
||||
#endif /* _SCIC_USER_CALLBACK_H_ */
|
||||
|
||||
280
drivers/scsi/isci/core/scu_completion_codes.h
Normal file
280
drivers/scsi/isci/core/scu_completion_codes.h
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCU_COMPLETION_CODES_HEADER_
|
||||
#define _SCU_COMPLETION_CODES_HEADER_
|
||||
|
||||
/**
|
||||
* This file contains the constants and macros for the SCU hardware completion
|
||||
* codes.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#define SCU_COMPLETION_TYPE_SHIFT 28
|
||||
#define SCU_COMPLETION_TYPE_MASK 0x70000000
|
||||
|
||||
/**
|
||||
* SCU_COMPLETION_TYPE() -
|
||||
*
|
||||
* This macro constructs an SCU completion type
|
||||
*/
|
||||
#define SCU_COMPLETION_TYPE(type) \
|
||||
((u32)(type) << SCU_COMPLETION_TYPE_SHIFT)
|
||||
|
||||
/**
|
||||
* SCU_COMPLETION_TYPE() -
|
||||
*
|
||||
* These macros contain the SCU completion types SCU_COMPLETION_TYPE
|
||||
*/
|
||||
#define SCU_COMPLETION_TYPE_TASK SCU_COMPLETION_TYPE(0)
|
||||
#define SCU_COMPLETION_TYPE_SDMA SCU_COMPLETION_TYPE(1)
|
||||
#define SCU_COMPLETION_TYPE_UFI SCU_COMPLETION_TYPE(2)
|
||||
#define SCU_COMPLETION_TYPE_EVENT SCU_COMPLETION_TYPE(3)
|
||||
#define SCU_COMPLETION_TYPE_NOTIFY SCU_COMPLETION_TYPE(4)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* These constants provide the shift and mask values for the various parts of
|
||||
* an SCU completion code.
|
||||
*/
|
||||
#define SCU_COMPLETION_STATUS_MASK 0x0FFC0000
|
||||
#define SCU_COMPLETION_TL_STATUS_MASK 0x0FC00000
|
||||
#define SCU_COMPLETION_TL_STATUS_SHIFT 22
|
||||
#define SCU_COMPLETION_SDMA_STATUS_MASK 0x003C0000
|
||||
#define SCU_COMPLETION_PEG_MASK 0x00010000
|
||||
#define SCU_COMPLETION_PORT_MASK 0x00007000
|
||||
#define SCU_COMPLETION_PE_MASK SCU_COMPLETION_PORT_MASK
|
||||
#define SCU_COMPLETION_PE_SHIFT 12
|
||||
#define SCU_COMPLETION_INDEX_MASK 0x00000FFF
|
||||
|
||||
/**
|
||||
* SCU_GET_COMPLETION_TYPE() -
|
||||
*
|
||||
* This macro returns the SCU completion type.
|
||||
*/
|
||||
#define SCU_GET_COMPLETION_TYPE(completion_code) \
|
||||
((completion_code) & SCU_COMPLETION_TYPE_MASK)
|
||||
|
||||
/**
|
||||
* SCU_GET_COMPLETION_STATUS() -
|
||||
*
|
||||
* This macro returns the SCU completion status.
|
||||
*/
|
||||
#define SCU_GET_COMPLETION_STATUS(completion_code) \
|
||||
((completion_code) & SCU_COMPLETION_STATUS_MASK)
|
||||
|
||||
/**
|
||||
* SCU_GET_COMPLETION_TL_STATUS() -
|
||||
*
|
||||
* This macro returns the transport layer completion status.
|
||||
*/
|
||||
#define SCU_GET_COMPLETION_TL_STATUS(completion_code) \
|
||||
((completion_code) & SCU_COMPLETION_TL_STATUS_MASK)
|
||||
|
||||
/**
|
||||
* SCU_MAKE_COMPLETION_STATUS() -
|
||||
*
|
||||
* This macro takes a completion code and performs the shift and mask
|
||||
* operations to turn it into a completion code that can be compared to a
|
||||
* SCU_GET_COMPLETION_TL_STATUS.
|
||||
*/
|
||||
#define SCU_MAKE_COMPLETION_STATUS(completion_code) \
|
||||
((u32)(completion_code) << SCU_COMPLETION_TL_STATUS_SHIFT)
|
||||
|
||||
/**
|
||||
* SCU_NORMALIZE_COMPLETION_STATUS() -
|
||||
*
|
||||
* This macro takes a SCU_GET_COMPLETION_TL_STATUS and normalizes it for a
|
||||
* return code.
|
||||
*/
|
||||
#define SCU_NORMALIZE_COMPLETION_STATUS(completion_code) \
|
||||
(\
|
||||
((completion_code) & SCU_COMPLETION_TL_STATUS_MASK) \
|
||||
>> SCU_COMPLETION_TL_STATUS_SHIFT \
|
||||
)
|
||||
|
||||
/**
|
||||
* SCU_GET_COMPLETION_SDMA_STATUS() -
|
||||
*
|
||||
* This macro returns the SDMA completion status.
|
||||
*/
|
||||
#define SCU_GET_COMPLETION_SDMA_STATUS(completion_code) \
|
||||
((completion_code) & SCU_COMPLETION_SDMA_STATUS_MASK)
|
||||
|
||||
/**
|
||||
* SCU_GET_COMPLETION_PEG() -
|
||||
*
|
||||
* This macro returns the Protocol Engine Group from the completion code.
|
||||
*/
|
||||
#define SCU_GET_COMPLETION_PEG(completion_code) \
|
||||
((completion_code) & SCU_COMPLETION_PEG_MASK)
|
||||
|
||||
/**
|
||||
* SCU_GET_COMPLETION_PORT() -
|
||||
*
|
||||
* This macro reuturns the logical port index from the completion code.
|
||||
*/
|
||||
#define SCU_GET_COMPLETION_PORT(completion_code) \
|
||||
((completion_code) & SCU_COMPLETION_PORT_MASK)
|
||||
|
||||
/**
|
||||
* SCU_GET_PROTOCOL_ENGINE_INDEX() -
|
||||
*
|
||||
* This macro returns the PE index from the completion code.
|
||||
*/
|
||||
#define SCU_GET_PROTOCOL_ENGINE_INDEX(completion_code) \
|
||||
(((completion_code) & SCU_COMPLETION_PE_MASK) >> SCU_COMPLETION_PE_SHIFT)
|
||||
|
||||
/**
|
||||
* SCU_GET_COMPLETION_INDEX() -
|
||||
*
|
||||
* This macro returns the index of the completion which is either a TCi or an
|
||||
* RNi depending on the completion type.
|
||||
*/
|
||||
#define SCU_GET_COMPLETION_INDEX(completion_code) \
|
||||
((completion_code) & SCU_COMPLETION_INDEX_MASK)
|
||||
|
||||
#define SCU_UNSOLICITED_FRAME_MASK 0x0FFF0000
|
||||
#define SCU_UNSOLICITED_FRAME_SHIFT 16
|
||||
|
||||
/**
|
||||
* SCU_GET_FRAME_INDEX() -
|
||||
*
|
||||
* This macro returns a normalized frame index from an unsolicited frame
|
||||
* completion.
|
||||
*/
|
||||
#define SCU_GET_FRAME_INDEX(completion_code) \
|
||||
(\
|
||||
((completion_code) & SCU_UNSOLICITED_FRAME_MASK) \
|
||||
>> SCU_UNSOLICITED_FRAME_SHIFT \
|
||||
)
|
||||
|
||||
#define SCU_UNSOLICITED_FRAME_ERROR_MASK 0x00008000
|
||||
|
||||
/**
|
||||
* SCU_GET_FRAME_ERROR() -
|
||||
*
|
||||
* This macro returns a zero (0) value if there is no frame error otherwise it
|
||||
* returns non-zero (!0).
|
||||
*/
|
||||
#define SCU_GET_FRAME_ERROR(completion_code) \
|
||||
((completion_code) & SCU_UNSOLICITED_FRAME_ERROR_MASK)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* These constants represent normalized completion codes which must be shifted
|
||||
* 18 bits to match it with the hardware completion code. In a 16-bit compiler,
|
||||
* immediate constants are 16-bit values (the size of an int). If we shift
|
||||
* those by 18 bits, we completely lose the value. To ensure the value is a
|
||||
* 32-bit value like we want, each immediate value must be cast to a u32.
|
||||
*/
|
||||
#define SCU_TASK_DONE_GOOD ((u32)0x00)
|
||||
#define SCU_TASK_DONE_CRC_ERR ((u32)0x14)
|
||||
#define SCU_TASK_DONE_CHECK_RESPONSE ((u32)0x14)
|
||||
#define SCU_TASK_DONE_GEN_RESPONSE ((u32)0x15)
|
||||
#define SCU_TASK_DONE_NAK_CMD_ERR ((u32)0x16)
|
||||
#define SCU_TASK_DONE_LL_R_ERR ((u32)0x17)
|
||||
#define SCU_TASK_DONE_ACK_NAK_TO ((u32)0x17)
|
||||
#define SCU_TASK_DONE_LL_PERR ((u32)0x18)
|
||||
#define SCU_TASK_DONE_LL_SY_TERM ((u32)0x19)
|
||||
#define SCU_TASK_DONE_NAK_ERR ((u32)0x19)
|
||||
#define SCU_TASK_DONE_LL_LF_TERM ((u32)0x1A)
|
||||
#define SCU_TASK_DONE_DATA_LEN_ERR ((u32)0x1A)
|
||||
#define SCU_TASK_DONE_LL_CL_TERM ((u32)0x1B)
|
||||
#define SCU_TASK_DONE_LL_ABORT_ERR ((u32)0x1B)
|
||||
#define SCU_TASK_DONE_SEQ_INV_TYPE ((u32)0x1C)
|
||||
#define SCU_TASK_DONE_UNEXP_XR ((u32)0x1C)
|
||||
#define SCU_TASK_DONE_INV_FIS_TYPE ((u32)0x1D)
|
||||
#define SCU_TASK_DONE_XR_IU_LEN_ERR ((u32)0x1D)
|
||||
#define SCU_TASK_DONE_INV_FIS_LEN ((u32)0x1E)
|
||||
#define SCU_TASK_DONE_XR_WD_LEN ((u32)0x1E)
|
||||
#define SCU_TASK_DONE_SDMA_ERR ((u32)0x1F)
|
||||
#define SCU_TASK_DONE_OFFSET_ERR ((u32)0x20)
|
||||
#define SCU_TASK_DONE_MAX_PLD_ERR ((u32)0x21)
|
||||
#define SCU_TASK_DONE_EXCESS_DATA ((u32)0x22)
|
||||
#define SCU_TASK_DONE_LF_ERR ((u32)0x23)
|
||||
#define SCU_TASK_DONE_UNEXP_FIS ((u32)0x24)
|
||||
#define SCU_TASK_DONE_UNEXP_RESP ((u32)0x24)
|
||||
#define SCU_TASK_DONE_EARLY_RESP ((u32)0x25)
|
||||
#define SCU_TASK_DONE_SMP_RESP_TO_ERR ((u32)0x26)
|
||||
#define SCU_TASK_DONE_DMASETUP_DIRERR ((u32)0x27)
|
||||
#define SCU_TASK_DONE_SMP_UFI_ERR ((u32)0x27)
|
||||
#define SCU_TASK_DONE_XFERCNT_ERR ((u32)0x28)
|
||||
#define SCU_TASK_DONE_SMP_FRM_TYPE_ERR ((u32)0x28)
|
||||
#define SCU_TASK_DONE_SMP_LL_RX_ERR ((u32)0x29)
|
||||
#define SCU_TASK_DONE_RESP_LEN_ERR ((u32)0x2A)
|
||||
#define SCU_TASK_DONE_UNEXP_DATA ((u32)0x2B)
|
||||
#define SCU_TASK_DONE_OPEN_FAIL ((u32)0x2C)
|
||||
#define SCU_TASK_DONE_UNEXP_SDBFIS ((u32)0x2D)
|
||||
#define SCU_TASK_DONE_REG_ERR ((u32)0x2E)
|
||||
#define SCU_TASK_DONE_SDB_ERR ((u32)0x2F)
|
||||
#define SCU_TASK_DONE_TASK_ABORT ((u32)0x30)
|
||||
#define SCU_TASK_OPEN_REJECT_WRONG_DESTINATION ((u32)0x34)
|
||||
#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1 ((u32)0x35)
|
||||
#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2 ((u32)0x36)
|
||||
#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3 ((u32)0x37)
|
||||
#define SCU_TASK_OPEN_REJECT_BAD_DESTINATION ((u32)0x38)
|
||||
#define SCU_TASK_OPEN_REJECT_ZONE_VIOLATION ((u32)0x39)
|
||||
#define SCU_TASK_DONE_VIIT_ENTRY_NV ((u32)0x3A)
|
||||
#define SCU_TASK_DONE_IIT_ENTRY_NV ((u32)0x3B)
|
||||
#define SCU_TASK_DONE_RNCNV_OUTBOUND ((u32)0x3C)
|
||||
#define SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY ((u32)0x3D)
|
||||
#define SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED ((u32)0x3E)
|
||||
#define SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED ((u32)0x3F)
|
||||
|
||||
#endif /* _SCU_COMPLETION_CODES_HEADER_ */
|
||||
151
drivers/scsi/isci/core/scu_constants.h
Normal file
151
drivers/scsi/isci/core/scu_constants.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCU_CONSTANTS_H_
|
||||
#define _SCU_CONSTANTS_H_
|
||||
|
||||
/**
|
||||
* This file contains the SCU hardware constants.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci_controller_constants.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* 2 indicates the maximum number of UFs that can occur for a given IO request.
|
||||
* The hardware handles reception of additional unsolicited frames while all
|
||||
* UFs are in use, by holding off the transmitting device. This number could
|
||||
* be theoretically reduced to 1, but 2 provides for more reliable operation.
|
||||
* During SATA PIO operation, it is possible under some conditions for there to
|
||||
* be 3 separate FISes received, back to back to back (PIO Setup, Data, D2H
|
||||
* Register). It is unlikely to have all 3 pending all at once without some of
|
||||
* them already being processed.
|
||||
*/
|
||||
#define SCU_MIN_UNSOLICITED_FRAMES (1)
|
||||
#define SCU_MIN_CRITICAL_NOTIFICATIONS (24)
|
||||
#define SCU_MIN_EVENTS (4)
|
||||
#define SCU_MIN_COMPLETION_QUEUE_SCRATCH (2)
|
||||
#define SCU_MIN_COMPLETION_QUEUE_ENTRIES (SCU_MIN_CRITICAL_NOTIFICATIONS \
|
||||
+ SCU_MIN_EVENTS \
|
||||
+ SCU_MIN_UNSOLICITED_FRAMES \
|
||||
+ SCI_MIN_IO_REQUESTS \
|
||||
+ SCU_MIN_COMPLETION_QUEUE_SCRATCH)
|
||||
|
||||
#define SCU_MAX_CRITICAL_NOTIFICATIONS (384)
|
||||
#define SCU_MAX_EVENTS (128)
|
||||
#define SCU_MAX_UNSOLICITED_FRAMES (128)
|
||||
#define SCU_MAX_COMPLETION_QUEUE_SCRATCH (128)
|
||||
#define SCU_MAX_COMPLETION_QUEUE_ENTRIES (SCU_MAX_CRITICAL_NOTIFICATIONS \
|
||||
+ SCU_MAX_EVENTS \
|
||||
+ SCU_MAX_UNSOLICITED_FRAMES \
|
||||
+ SCI_MAX_IO_REQUESTS \
|
||||
+ SCU_MAX_COMPLETION_QUEUE_SCRATCH)
|
||||
|
||||
#if !defined(ENABLE_MINIMUM_MEMORY_MODE)
|
||||
#define SCU_UNSOLICITED_FRAME_COUNT SCU_MAX_UNSOLICITED_FRAMES
|
||||
#define SCU_CRITICAL_NOTIFICATION_COUNT SCU_MAX_CRITICAL_NOTIFICATIONS
|
||||
#define SCU_EVENT_COUNT SCU_MAX_EVENTS
|
||||
#define SCU_COMPLETION_QUEUE_SCRATCH SCU_MAX_COMPLETION_QUEUE_SCRATCH
|
||||
#define SCU_IO_REQUEST_COUNT SCI_MAX_IO_REQUESTS
|
||||
#define SCU_IO_REQUEST_SGE_COUNT SCI_MAX_SCATTER_GATHER_ELEMENTS
|
||||
#define SCU_COMPLETION_QUEUE_COUNT SCU_MAX_COMPLETION_QUEUE_ENTRIES
|
||||
#else
|
||||
#define SCU_UNSOLICITED_FRAME_COUNT SCU_MIN_UNSOLICITED_FRAMES
|
||||
#define SCU_CRITICAL_NOTIFICATION_COUNT SCU_MIN_CRITICAL_NOTIFICATIONS
|
||||
#define SCU_EVENT_COUNT SCU_MIN_EVENTS
|
||||
#define SCU_COMPLETION_QUEUE_SCRATCH SCU_MIN_COMPLETION_QUEUE_SCRATCH
|
||||
#define SCU_IO_REQUEST_COUNT SCI_MIN_IO_REQUESTS
|
||||
#define SCU_IO_REQUEST_SGE_COUNT SCI_MIN_SCATTER_GATHER_ELEMENTS
|
||||
#define SCU_COMPLETION_QUEUE_COUNT SCU_MIN_COMPLETION_QUEUE_ENTRIES
|
||||
#endif /* !defined(ENABLE_MINIMUM_MEMORY_OPERATION) */
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* The SCU_COMPLETION_QUEUE_COUNT constant indicates the size of the completion
|
||||
* queue into which the hardware DMAs 32-bit quantas (completion entries).
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This queue must be programmed to a power of 2 size (e.g. 32, 64, 1024, etc.).
|
||||
*/
|
||||
#if (SCU_COMPLETION_QUEUE_COUNT != 16) && \
|
||||
(SCU_COMPLETION_QUEUE_COUNT != 32) && \
|
||||
(SCU_COMPLETION_QUEUE_COUNT != 64) && \
|
||||
(SCU_COMPLETION_QUEUE_COUNT != 128) && \
|
||||
(SCU_COMPLETION_QUEUE_COUNT != 256) && \
|
||||
(SCU_COMPLETION_QUEUE_COUNT != 512) && \
|
||||
(SCU_COMPLETION_QUEUE_COUNT != 1024)
|
||||
#error "SCU_COMPLETION_QUEUE_COUNT must be set to a power of 2."
|
||||
#endif
|
||||
|
||||
#if SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES
|
||||
#error "Invalid configuration of unsolicited frame constants"
|
||||
#endif /* SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES */
|
||||
|
||||
#define SCU_MIN_UF_TABLE_ENTRIES (8)
|
||||
#define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096)
|
||||
#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024)
|
||||
#define SCU_INVALID_FRAME_INDEX (0xFFFF)
|
||||
|
||||
#define SCU_IO_REQUEST_MAX_SGE_SIZE (0x00FFFFFF)
|
||||
#define SCU_IO_REQUEST_MAX_TRANSFER_LENGTH (0x00FFFFFF)
|
||||
|
||||
#endif /* _SCU_CONSTANTS_H_ */
|
||||
336
drivers/scsi/isci/core/scu_event_codes.h
Normal file
336
drivers/scsi/isci/core/scu_event_codes.h
Normal file
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __SCU_EVENT_CODES_HEADER__
|
||||
#define __SCU_EVENT_CODES_HEADER__
|
||||
|
||||
/**
|
||||
* This file contains the constants and macros for the SCU event codes.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#define SCU_EVENT_TYPE_CODE_SHIFT 24
|
||||
#define SCU_EVENT_TYPE_CODE_MASK 0x0F000000
|
||||
|
||||
#define SCU_EVENT_SPECIFIC_CODE_SHIFT 18
|
||||
#define SCU_EVENT_SPECIFIC_CODE_MASK 0x00FC0000
|
||||
|
||||
#define SCU_EVENT_CODE_MASK \
|
||||
(SCU_EVENT_TYPE_CODE_MASK | SCU_EVENT_SPECIFIC_CODE_MASK)
|
||||
|
||||
/**
|
||||
* SCU_EVENT_TYPE() -
|
||||
*
|
||||
* This macro constructs an SCU event type from the type value.
|
||||
*/
|
||||
#define SCU_EVENT_TYPE(type) \
|
||||
((u32)(type) << SCU_EVENT_TYPE_CODE_SHIFT)
|
||||
|
||||
/**
|
||||
* SCU_EVENT_SPECIFIC() -
|
||||
*
|
||||
* This macro constructs an SCU event specifier from the code value.
|
||||
*/
|
||||
#define SCU_EVENT_SPECIFIC(code) \
|
||||
((u32)(code) << SCU_EVENT_SPECIFIC_CODE_SHIFT)
|
||||
|
||||
/**
|
||||
* SCU_EVENT_MESSAGE() -
|
||||
*
|
||||
* This macro constructs a combines an SCU event type and SCU event specifier
|
||||
* from the type and code values.
|
||||
*/
|
||||
#define SCU_EVENT_MESSAGE(type, code) \
|
||||
((type) | SCU_EVENT_SPECIFIC(code))
|
||||
|
||||
/**
|
||||
* SCU_EVENT_TYPE() -
|
||||
*
|
||||
* SCU_EVENT_TYPES
|
||||
*/
|
||||
#define SCU_EVENT_TYPE_SMU_COMMAND_ERROR SCU_EVENT_TYPE(0x08)
|
||||
#define SCU_EVENT_TYPE_SMU_PCQ_ERROR SCU_EVENT_TYPE(0x09)
|
||||
#define SCU_EVENT_TYPE_SMU_ERROR SCU_EVENT_TYPE(0x00)
|
||||
#define SCU_EVENT_TYPE_TRANSPORT_ERROR SCU_EVENT_TYPE(0x01)
|
||||
#define SCU_EVENT_TYPE_BROADCAST_CHANGE SCU_EVENT_TYPE(0x02)
|
||||
#define SCU_EVENT_TYPE_OSSP_EVENT SCU_EVENT_TYPE(0x03)
|
||||
#define SCU_EVENT_TYPE_FATAL_MEMORY_ERROR SCU_EVENT_TYPE(0x0F)
|
||||
#define SCU_EVENT_TYPE_RNC_SUSPEND_TX SCU_EVENT_TYPE(0x04)
|
||||
#define SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX SCU_EVENT_TYPE(0x05)
|
||||
#define SCU_EVENT_TYPE_RNC_OPS_MISC SCU_EVENT_TYPE(0x06)
|
||||
#define SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT SCU_EVENT_TYPE(0x07)
|
||||
#define SCU_EVENT_TYPE_ERR_CNT_EVENT SCU_EVENT_TYPE(0x0A)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCU_EVENT_SPECIFIERS
|
||||
*/
|
||||
#define SCU_EVENT_SPECIFIER_DRIVER_SUSPEND 0x20
|
||||
#define SCU_EVENT_SPECIFIER_RNC_RELEASE 0x00
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SMU_COMMAND_EVENTS
|
||||
*/
|
||||
#define SCU_EVENT_INVALID_CONTEXT_COMMAND \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_COMMAND_ERROR, 0x00)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SMU_PCQ_EVENTS
|
||||
*/
|
||||
#define SCU_EVENT_UNCORRECTABLE_PCQ_ERROR \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_PCQ_ERROR, 0x00)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SMU_EVENTS
|
||||
*/
|
||||
#define SCU_EVENT_UNCORRECTABLE_REGISTER_WRITE \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x02)
|
||||
#define SCU_EVENT_UNCORRECTABLE_REGISTER_READ \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x03)
|
||||
#define SCU_EVENT_PCIE_INTERFACE_ERROR \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x04)
|
||||
#define SCU_EVENT_FUNCTION_LEVEL_RESET \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x05)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* TRANSPORT_LEVEL_ERRORS
|
||||
*/
|
||||
#define SCU_EVENT_ACK_NAK_TIMEOUT_ERROR \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_TRANSPORT_ERROR, 0x00)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* BROADCAST_CHANGE_EVENTS
|
||||
*/
|
||||
#define SCU_EVENT_BROADCAST_CHANGE \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x01)
|
||||
#define SCU_EVENT_BROADCAST_RESERVED0 \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x02)
|
||||
#define SCU_EVENT_BROADCAST_RESERVED1 \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x03)
|
||||
#define SCU_EVENT_BROADCAST_SES \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x04)
|
||||
#define SCU_EVENT_BROADCAST_EXPANDER \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x05)
|
||||
#define SCU_EVENT_BROADCAST_AEN \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x06)
|
||||
#define SCU_EVENT_BROADCAST_RESERVED3 \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x07)
|
||||
#define SCU_EVENT_BROADCAST_RESERVED4 \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x08)
|
||||
#define SCU_EVENT_PE_SUSPENDED \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x09)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* OSSP_EVENTS
|
||||
*/
|
||||
#define SCU_EVENT_PORT_SELECTOR_DETECTED \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x10)
|
||||
#define SCU_EVENT_SENT_PORT_SELECTION \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x11)
|
||||
#define SCU_EVENT_HARD_RESET_TRANSMITTED \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x12)
|
||||
#define SCU_EVENT_HARD_RESET_RECEIVED \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x13)
|
||||
#define SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x15)
|
||||
#define SCU_EVENT_LINK_FAILURE \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x16)
|
||||
#define SCU_EVENT_SATA_SPINUP_HOLD \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x17)
|
||||
#define SCU_EVENT_SAS_15_SSC \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x18)
|
||||
#define SCU_EVENT_SAS_15 \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x19)
|
||||
#define SCU_EVENT_SAS_30_SSC \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1A)
|
||||
#define SCU_EVENT_SAS_30 \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1B)
|
||||
#define SCU_EVENT_SAS_60_SSC \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1C)
|
||||
#define SCU_EVENT_SAS_60 \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1D)
|
||||
#define SCU_EVENT_SATA_15_SSC \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1E)
|
||||
#define SCU_EVENT_SATA_15 \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1F)
|
||||
#define SCU_EVENT_SATA_30_SSC \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x20)
|
||||
#define SCU_EVENT_SATA_30 \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x21)
|
||||
#define SCU_EVENT_SATA_60_SSC \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x22)
|
||||
#define SCU_EVENT_SATA_60 \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x23)
|
||||
#define SCU_EVENT_SAS_PHY_DETECTED \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x24)
|
||||
#define SCU_EVENT_SATA_PHY_DETECTED \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x25)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* FATAL_INTERNAL_MEMORY_ERROR_EVENTS
|
||||
*/
|
||||
#define SCU_EVENT_TSC_RNSC_UNCORRECTABLE_ERROR \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x00)
|
||||
#define SCU_EVENT_TC_RNC_UNCORRECTABLE_ERROR \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x01)
|
||||
#define SCU_EVENT_ZPT_UNCORRECTABLE_ERROR \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x02)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* REMOTE_NODE_SUSPEND_EVENTS
|
||||
*/
|
||||
#define SCU_EVENT_TL_RNC_SUSPEND_TX \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x00)
|
||||
#define SCU_EVENT_TL_RNC_SUSPEND_TX_RX \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x00)
|
||||
#define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x20)
|
||||
#define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX_RX \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x20)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* REMOTE_NODE_MISC_EVENTS
|
||||
*/
|
||||
#define SCU_EVENT_POST_RCN_RELEASE \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, SCU_EVENT_SPECIFIER_RNC_RELEASE)
|
||||
#define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_ENABLE \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x01)
|
||||
#define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_DISABLE \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x02)
|
||||
#define SCU_EVENT_POST_RNC_COMPLETE \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x03)
|
||||
#define SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x04)
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ERROR_COUNT_EVENT
|
||||
*/
|
||||
#define SCU_EVENT_RX_CREDIT_BLOCKED_RECEIVED \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x00)
|
||||
#define SCU_EVENT_TX_DONE_CREDIT_TIMEOUT \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x01)
|
||||
#define SCU_EVENT_RX_DONE_CREDIT_TIMEOUT \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x02)
|
||||
|
||||
/**
|
||||
* scu_get_event_type() -
|
||||
*
|
||||
* This macro returns the SCU event type from the event code.
|
||||
*/
|
||||
#define scu_get_event_type(event_code) \
|
||||
((event_code) & SCU_EVENT_TYPE_CODE_MASK)
|
||||
|
||||
/**
|
||||
* scu_get_event_specifier() -
|
||||
*
|
||||
* This macro returns the SCU event specifier from the event code.
|
||||
*/
|
||||
#define scu_get_event_specifier(event_code) \
|
||||
((event_code) & SCU_EVENT_SPECIFIC_CODE_MASK)
|
||||
|
||||
/**
|
||||
* scu_get_event_code() -
|
||||
*
|
||||
* This macro returns the combined SCU event type and SCU event specifier from
|
||||
* the event code.
|
||||
*/
|
||||
#define scu_get_event_code(event_code) \
|
||||
((event_code) & SCU_EVENT_CODE_MASK)
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* PTS_SCHEDULE_EVENT
|
||||
*/
|
||||
#define SCU_EVENT_SMP_RESPONSE_NO_PE \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x00)
|
||||
#define SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE \
|
||||
scu_get_event_specifier(SCU_EVENT_SMP_RESPONSE_NO_PE)
|
||||
|
||||
#define SCU_EVENT_TASK_TIMEOUT \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x01)
|
||||
#define SCU_EVENT_SPECIFIC_TASK_TIMEOUT \
|
||||
scu_get_event_specifier(SCU_EVENT_TASK_TIMEOUT)
|
||||
|
||||
#define SCU_EVENT_IT_NEXUS_TIMEOUT \
|
||||
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x02)
|
||||
#define SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT \
|
||||
scu_get_event_specifier(SCU_EVENT_IT_NEXUS_TIMEOUT)
|
||||
|
||||
|
||||
#endif /* __SCU_EVENT_CODES_HEADER__ */
|
||||
1824
drivers/scsi/isci/core/scu_registers.h
Normal file
1824
drivers/scsi/isci/core/scu_registers.h
Normal file
File diff suppressed because it is too large
Load Diff
230
drivers/scsi/isci/core/scu_remote_node_context.h
Normal file
230
drivers/scsi/isci/core/scu_remote_node_context.h
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __SCU_REMOTE_NODE_CONTEXT_HEADER__
|
||||
#define __SCU_REMOTE_NODE_CONTEXT_HEADER__
|
||||
|
||||
/**
|
||||
* This file contains the structures and constatns used by the SCU hardware to
|
||||
* describe a remote node context.
|
||||
*
|
||||
*
|
||||
*/
|
||||
#include "sci_types.h"
|
||||
|
||||
/**
|
||||
* struct ssp_remote_node_context - This structure contains the SCU hardware
|
||||
* definition for an SSP remote node.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct ssp_remote_node_context {
|
||||
/* WORD 0 */
|
||||
|
||||
/**
|
||||
* This field is the remote node index assigned for this remote node. All
|
||||
* remote nodes must have a unique remote node index. The value of the remote
|
||||
* node index can not exceed the maximum number of remote nodes reported in
|
||||
* the SCU device context capacity register.
|
||||
*/
|
||||
u32 remote_node_index:12;
|
||||
u32 reserved0_1:4;
|
||||
|
||||
/**
|
||||
* This field tells the SCU hardware how many simultaneous connections that
|
||||
* this remote node will support.
|
||||
*/
|
||||
u32 remote_node_port_width:4;
|
||||
|
||||
/**
|
||||
* This field tells the SCU hardware which logical port to associate with this
|
||||
* remote node.
|
||||
*/
|
||||
u32 logical_port_index:3;
|
||||
u32 reserved0_2:5;
|
||||
|
||||
/**
|
||||
* This field will enable the I_T nexus loss timer for this remote node.
|
||||
*/
|
||||
u32 nexus_loss_timer_enable:1;
|
||||
|
||||
/**
|
||||
* This field is the for driver debug only and is not used.
|
||||
*/
|
||||
u32 check_bit:1;
|
||||
|
||||
/**
|
||||
* This field must be set to true when the hardware DMAs the remote node
|
||||
* context to the hardware SRAM. When the remote node is being invalidated
|
||||
* this field must be set to false.
|
||||
*/
|
||||
u32 is_valid:1;
|
||||
|
||||
/**
|
||||
* This field must be set to true.
|
||||
*/
|
||||
u32 is_remote_node_context:1;
|
||||
|
||||
/* WORD 1 - 2 */
|
||||
|
||||
/**
|
||||
* This is the low word of the remote device SAS Address
|
||||
*/
|
||||
u32 remote_sas_address_lo;
|
||||
|
||||
/**
|
||||
* This field is the high word of the remote device SAS Address
|
||||
*/
|
||||
u32 remote_sas_address_hi;
|
||||
|
||||
/* WORD 3 */
|
||||
/**
|
||||
* This field reprensets the function number assigned to this remote device.
|
||||
* This value must match the virtual function number that is being used to
|
||||
* communicate to the device.
|
||||
*/
|
||||
u32 function_number:8;
|
||||
u32 reserved3_1:8;
|
||||
|
||||
/**
|
||||
* This field provides the driver a way to cheat on the arbitration wait time
|
||||
* for this remote node.
|
||||
*/
|
||||
u32 arbitration_wait_time:16;
|
||||
|
||||
/* WORD 4 */
|
||||
/**
|
||||
* This field tells the SCU hardware how long this device may occupy the
|
||||
* connection before it must be closed.
|
||||
*/
|
||||
u32 connection_occupancy_timeout:16;
|
||||
|
||||
/**
|
||||
* This field tells the SCU hardware how long to maintain a connection when
|
||||
* there are no frames being transmitted on the link.
|
||||
*/
|
||||
u32 connection_inactivity_timeout:16;
|
||||
|
||||
/* WORD 5 */
|
||||
/**
|
||||
* This field allows the driver to cheat on the arbitration wait time for this
|
||||
* remote node.
|
||||
*/
|
||||
u32 initial_arbitration_wait_time:16;
|
||||
|
||||
/**
|
||||
* This field is tells the hardware what to program for the connection rate in
|
||||
* the open address frame. See the SAS spec for valid values.
|
||||
*/
|
||||
u32 oaf_connection_rate:4;
|
||||
|
||||
/**
|
||||
* This field tells the SCU hardware what to program for the features in the
|
||||
* open address frame. See the SAS spec for valid values.
|
||||
*/
|
||||
u32 oaf_features:4;
|
||||
|
||||
/**
|
||||
* This field tells the SCU hardware what to use for the source zone group in
|
||||
* the open address frame. See the SAS spec for more details on zoning.
|
||||
*/
|
||||
u32 oaf_source_zone_group:8;
|
||||
|
||||
/* WORD 6 */
|
||||
/**
|
||||
* This field tells the SCU hardware what to use as the more capibilities in
|
||||
* the open address frame. See the SAS Spec for details.
|
||||
*/
|
||||
u32 oaf_more_compatibility_features;
|
||||
|
||||
/* WORD 7 */
|
||||
u32 reserved7;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct stp_remote_node_context - This structure contains the SCU hardware
|
||||
* definition for a STP remote node.
|
||||
*
|
||||
* STP Targets are not yet supported so this definition is a placeholder until
|
||||
* we do support them.
|
||||
*/
|
||||
struct stp_remote_node_context {
|
||||
/**
|
||||
* Placeholder data for the STP remote node.
|
||||
*/
|
||||
u32 data[8];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* This union combines the SAS and SATA remote node definitions.
|
||||
*
|
||||
* union scu_remote_node_context
|
||||
*/
|
||||
union scu_remote_node_context {
|
||||
/**
|
||||
* SSP Remote Node
|
||||
*/
|
||||
struct ssp_remote_node_context ssp;
|
||||
|
||||
/**
|
||||
* STP Remote Node
|
||||
*/
|
||||
struct stp_remote_node_context stp;
|
||||
|
||||
};
|
||||
|
||||
#endif /* __SCU_REMOTE_NODE_CONTEXT_HEADER__ */
|
||||
943
drivers/scsi/isci/core/scu_task_context.h
Normal file
943
drivers/scsi/isci/core/scu_task_context.h
Normal file
@@ -0,0 +1,943 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCU_TASK_CONTEXT_H_
|
||||
#define _SCU_TASK_CONTEXT_H_
|
||||
|
||||
/**
|
||||
* This file contains the structures and constants for the SCU hardware task
|
||||
* context.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci_types.h"
|
||||
|
||||
/**
|
||||
* enum SCU_SSP_TASK_TYPE - This enumberation defines the various SSP task
|
||||
* types the SCU hardware will accept. The definition for the various task
|
||||
* types the SCU hardware will accept can be found in the DS specification.
|
||||
*
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SCU_TASK_TYPE_IOREAD, /* /< IO READ direction or no direction */
|
||||
SCU_TASK_TYPE_IOWRITE, /* /< IO Write direction */
|
||||
SCU_TASK_TYPE_SMP_REQUEST, /* /< SMP Request type */
|
||||
SCU_TASK_TYPE_RESPONSE, /* /< Driver generated response frame (targt mode) */
|
||||
SCU_TASK_TYPE_RAW_FRAME, /* /< Raw frame request type */
|
||||
SCU_TASK_TYPE_PRIMITIVE /* /< Request for a primitive to be transmitted */
|
||||
} SCU_SSP_TASK_TYPE;
|
||||
|
||||
/**
|
||||
* enum SCU_SATA_TASK_TYPE - This enumeration defines the various SATA task
|
||||
* types the SCU hardware will accept. The definition for the various task
|
||||
* types the SCU hardware will accept can be found in the DS specification.
|
||||
*
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SCU_TASK_TYPE_DMA_IN, /* /< Read request */
|
||||
SCU_TASK_TYPE_FPDMAQ_READ, /* /< NCQ read request */
|
||||
SCU_TASK_TYPE_PACKET_DMA_IN, /* /< Packet read request */
|
||||
SCU_TASK_TYPE_SATA_RAW_FRAME, /* /< Raw frame request */
|
||||
RESERVED_4,
|
||||
RESERVED_5,
|
||||
RESERVED_6,
|
||||
RESERVED_7,
|
||||
SCU_TASK_TYPE_DMA_OUT, /* /< Write request */
|
||||
SCU_TASK_TYPE_FPDMAQ_WRITE, /* /< NCQ write Request */
|
||||
SCU_TASK_TYPE_PACKET_DMA_OUT /* /< Packet write request */
|
||||
} SCU_SATA_TASK_TYPE;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCU_CONTEXT_TYPE
|
||||
*/
|
||||
#define SCU_TASK_CONTEXT_TYPE 0
|
||||
#define SCU_RNC_CONTEXT_TYPE 1
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCU_TASK_CONTEXT_VALIDITY
|
||||
*/
|
||||
#define SCU_TASK_CONTEXT_INVALID 0
|
||||
#define SCU_TASK_CONTEXT_VALID 1
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCU_COMMAND_CODE
|
||||
*/
|
||||
#define SCU_COMMAND_CODE_INITIATOR_NEW_TASK 0
|
||||
#define SCU_COMMAND_CODE_ACTIVE_TASK 1
|
||||
#define SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK 2
|
||||
#define SCU_COMMAND_CODE_TARGET_RAW_FRAMES 3
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCU_TASK_PRIORITY
|
||||
*/
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This priority is used when there is no priority request for this request.
|
||||
*/
|
||||
#define SCU_TASK_PRIORITY_NORMAL 0
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This priority indicates that the task should be scheduled to the head of the
|
||||
* queue. The task will NOT be executed if the TX is suspended for the remote
|
||||
* node.
|
||||
*/
|
||||
#define SCU_TASK_PRIORITY_HEAD_OF_Q 1
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This priority indicates that the task will be executed before all
|
||||
* SCU_TASK_PRIORITY_NORMAL and SCU_TASK_PRIORITY_HEAD_OF_Q tasks. The task
|
||||
* WILL be executed if the TX is suspended for the remote node.
|
||||
*/
|
||||
#define SCU_TASK_PRIORITY_HIGH 2
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This task priority is reserved and should not be used.
|
||||
*/
|
||||
#define SCU_TASK_PRIORITY_RESERVED 3
|
||||
|
||||
#define SCU_TASK_INITIATOR_MODE 1
|
||||
#define SCU_TASK_TARGET_MODE 0
|
||||
|
||||
#define SCU_TASK_REGULAR 0
|
||||
#define SCU_TASK_ABORTED 1
|
||||
|
||||
/* direction bit defintion */
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SATA_DIRECTION
|
||||
*/
|
||||
#define SCU_SATA_WRITE_DATA_DIRECTION 0
|
||||
#define SCU_SATA_READ_DATA_DIRECTION 1
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCU_COMMAND_CONTEXT_MACROS These macros provide the mask and shift
|
||||
* operations to construct the various SCU commands
|
||||
*/
|
||||
#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT 21
|
||||
#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK 0x00E00000
|
||||
#define scu_get_command_request_type(x) \
|
||||
((x) & SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK)
|
||||
|
||||
#define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT 18
|
||||
#define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK 0x001C0000
|
||||
#define scu_get_command_request_subtype(x) \
|
||||
((x) & SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK)
|
||||
|
||||
#define SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK \
|
||||
(\
|
||||
SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK \
|
||||
| SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK \
|
||||
)
|
||||
#define scu_get_command_request_full_type(x) \
|
||||
((x) & SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK)
|
||||
|
||||
#define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT 16
|
||||
#define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK 0x00010000
|
||||
#define scu_get_command_protocl_engine_group(x) \
|
||||
((x) & SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK)
|
||||
|
||||
#define SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT 12
|
||||
#define SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK 0x00007000
|
||||
#define scu_get_command_reqeust_logical_port(x) \
|
||||
((x) & SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK)
|
||||
|
||||
|
||||
#define MAKE_SCU_CONTEXT_COMMAND_TYPE(type) \
|
||||
((u32)(type) << SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT)
|
||||
|
||||
/**
|
||||
* MAKE_SCU_CONTEXT_COMMAND_TYPE() -
|
||||
*
|
||||
* SCU_COMMAND_TYPES These constants provide the grouping of the different SCU
|
||||
* command types.
|
||||
*/
|
||||
#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC MAKE_SCU_CONTEXT_COMMAND_TYPE(0)
|
||||
#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC MAKE_SCU_CONTEXT_COMMAND_TYPE(1)
|
||||
#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(2)
|
||||
#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(3)
|
||||
#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(6)
|
||||
|
||||
#define MAKE_SCU_CONTEXT_COMMAND_REQUEST(type, command) \
|
||||
((type) | ((command) << SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT))
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCU_REQUEST_TYPES These constants are the various request types that can be
|
||||
* posted to the SCU hardware.
|
||||
*/
|
||||
#define SCU_CONTEXT_COMMAND_REQUST_POST_TC \
|
||||
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 0))
|
||||
|
||||
#define SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT \
|
||||
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 1))
|
||||
|
||||
#define SCU_CONTEXT_COMMAND_REQUST_DUMP_TC \
|
||||
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC, 0))
|
||||
|
||||
#define SCU_CONTEXT_COMMAND_POST_RNC_32 \
|
||||
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 0))
|
||||
|
||||
#define SCU_CONTEXT_COMMAND_POST_RNC_96 \
|
||||
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 1))
|
||||
|
||||
#define SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE \
|
||||
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 2))
|
||||
|
||||
#define SCU_CONTEXT_COMMAND_DUMP_RNC_32 \
|
||||
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 0))
|
||||
|
||||
#define SCU_CONTEXT_COMMAND_DUMP_RNC_96 \
|
||||
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 1))
|
||||
|
||||
#define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX \
|
||||
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 0))
|
||||
|
||||
#define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX \
|
||||
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 1))
|
||||
|
||||
#define SCU_CONTEXT_COMMAND_POST_RNC_RESUME \
|
||||
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 2))
|
||||
|
||||
#define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_ENABLE \
|
||||
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 3))
|
||||
|
||||
#define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_DISABLE \
|
||||
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 4))
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* SCU_TASK_CONTEXT_PROTOCOL SCU Task context protocol types this is uesd to
|
||||
* program the SCU Task context protocol field in word 0x00.
|
||||
*/
|
||||
#define SCU_TASK_CONTEXT_PROTOCOL_SMP 0x00
|
||||
#define SCU_TASK_CONTEXT_PROTOCOL_SSP 0x01
|
||||
#define SCU_TASK_CONTEXT_PROTOCOL_STP 0x02
|
||||
#define SCU_TASK_CONTEXT_PROTOCOL_NONE 0x07
|
||||
|
||||
/**
|
||||
* struct SSP_TASK_CONTEXT - This is the SCU hardware definition for an SSP
|
||||
* request.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct SSP_TASK_CONTEXT {
|
||||
/* OFFSET 0x18 */
|
||||
u32 reserved00:24;
|
||||
u32 frame_type:8;
|
||||
|
||||
/* OFFSET 0x1C */
|
||||
u32 reserved01;
|
||||
|
||||
/* OFFSET 0x20 */
|
||||
u32 fill_bytes:2;
|
||||
u32 reserved02:6;
|
||||
u32 changing_data_pointer:1;
|
||||
u32 retransmit:1;
|
||||
u32 retry_data_frame:1;
|
||||
u32 tlr_control:2;
|
||||
u32 reserved03:19;
|
||||
|
||||
/* OFFSET 0x24 */
|
||||
u32 uiRsvd4;
|
||||
|
||||
/* OFFSET 0x28 */
|
||||
u32 target_port_transfer_tag:16;
|
||||
u32 tag:16;
|
||||
|
||||
/* OFFSET 0x2C */
|
||||
u32 data_offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct STP_TASK_CONTEXT - This is the SCU hardware definition for an STP
|
||||
* request.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct STP_TASK_CONTEXT {
|
||||
/* OFFSET 0x18 */
|
||||
u32 fis_type:8;
|
||||
u32 pm_port:4;
|
||||
u32 reserved0:3;
|
||||
u32 control:1;
|
||||
u32 command:8;
|
||||
u32 features:8;
|
||||
|
||||
/* OFFSET 0x1C */
|
||||
u32 reserved1;
|
||||
|
||||
/* OFFSET 0x20 */
|
||||
u32 reserved2;
|
||||
|
||||
/* OFFSET 0x24 */
|
||||
u32 reserved3;
|
||||
|
||||
/* OFFSET 0x28 */
|
||||
u32 ncq_tag:5;
|
||||
u32 reserved4:27;
|
||||
|
||||
/* OFFSET 0x2C */
|
||||
u32 data_offset; /* TODO: What is this used for? */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct SMP_TASK_CONTEXT - This is the SCU hardware definition for an SMP
|
||||
* request.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct SMP_TASK_CONTEXT {
|
||||
/* OFFSET 0x18 */
|
||||
u32 response_length:8;
|
||||
u32 function_result:8;
|
||||
u32 function:8;
|
||||
u32 frame_type:8;
|
||||
|
||||
/* OFFSET 0x1C */
|
||||
u32 smp_response_ufi:12;
|
||||
u32 reserved1:20;
|
||||
|
||||
/* OFFSET 0x20 */
|
||||
u32 reserved2;
|
||||
|
||||
/* OFFSET 0x24 */
|
||||
u32 reserved3;
|
||||
|
||||
/* OFFSET 0x28 */
|
||||
u32 reserved4;
|
||||
|
||||
/* OFFSET 0x2C */
|
||||
u32 reserved5;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct PRIMITIVE_TASK_CONTEXT - This is the SCU hardware definition used
|
||||
* when the driver wants to send a primitive on the link.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct PRIMITIVE_TASK_CONTEXT {
|
||||
/* OFFSET 0x18 */
|
||||
/**
|
||||
* This field is the control word and it must be 0.
|
||||
*/
|
||||
u32 control; /* /< must be set to 0 */
|
||||
|
||||
/* OFFSET 0x1C */
|
||||
/**
|
||||
* This field specifies the primitive that is to be transmitted.
|
||||
*/
|
||||
u32 sequence;
|
||||
|
||||
/* OFFSET 0x20 */
|
||||
u32 reserved0;
|
||||
|
||||
/* OFFSET 0x24 */
|
||||
u32 reserved1;
|
||||
|
||||
/* OFFSET 0x28 */
|
||||
u32 reserved2;
|
||||
|
||||
/* OFFSET 0x2C */
|
||||
u32 reserved3;
|
||||
};
|
||||
|
||||
/**
|
||||
* The union of the protocols that can be selected in the SCU task context
|
||||
* field.
|
||||
*
|
||||
* PROTOCOL_CONTEXT
|
||||
*/
|
||||
union PROTOCOL_CONTEXT {
|
||||
struct SSP_TASK_CONTEXT ssp;
|
||||
struct STP_TASK_CONTEXT stp;
|
||||
struct SMP_TASK_CONTEXT smp;
|
||||
struct PRIMITIVE_TASK_CONTEXT primitive;
|
||||
u32 words[6];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scu_sgl_element - This structure represents a single SCU defined SGL
|
||||
* element. SCU SGLs contain a 64 bit address with the maximum data transfer
|
||||
* being 24 bits in size. The SGL can not cross a 4GB boundary.
|
||||
*
|
||||
* struct scu_sgl_element
|
||||
*/
|
||||
struct scu_sgl_element {
|
||||
/**
|
||||
* This field is the upper 32 bits of the 64 bit physical address.
|
||||
*/
|
||||
u32 address_upper;
|
||||
|
||||
/**
|
||||
* This field is the lower 32 bits of the 64 bit physical address.
|
||||
*/
|
||||
u32 address_lower;
|
||||
|
||||
/**
|
||||
* This field is the number of bytes to transfer.
|
||||
*/
|
||||
u32 length:24;
|
||||
|
||||
/**
|
||||
* This field is the address modifier to be used when a virtual function is
|
||||
* requesting a data transfer.
|
||||
*/
|
||||
u32 address_modifier:8;
|
||||
|
||||
};
|
||||
|
||||
#define SCU_SGL_ELEMENT_PAIR_A 0
|
||||
#define SCU_SGL_ELEMENT_PAIR_B 1
|
||||
|
||||
/**
|
||||
* struct scu_sgl_element_pair - This structure is the SCU hardware definition
|
||||
* of a pair of SGL elements. The SCU hardware always works on SGL pairs.
|
||||
* They are refered to in the DS specification as SGL A and SGL B. Each SGL
|
||||
* pair is followed by the address of the next pair.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scu_sgl_element_pair {
|
||||
/* OFFSET 0x60-0x68 */
|
||||
/**
|
||||
* This field is the SGL element A of the SGL pair.
|
||||
*/
|
||||
struct scu_sgl_element A;
|
||||
|
||||
/* OFFSET 0x6C-0x74 */
|
||||
/**
|
||||
* This field is the SGL element B of the SGL pair.
|
||||
*/
|
||||
struct scu_sgl_element B;
|
||||
|
||||
/* OFFSET 0x78-0x7C */
|
||||
/**
|
||||
* This field is the upper 32 bits of the 64 bit address to the next SGL
|
||||
* element pair.
|
||||
*/
|
||||
u32 next_pair_upper;
|
||||
|
||||
/**
|
||||
* This field is the lower 32 bits of the 64 bit address to the next SGL
|
||||
* element pair.
|
||||
*/
|
||||
u32 next_pair_lower;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct TRANSPORT_SNAPSHOT - This structure is the SCU hardware scratch area
|
||||
* for the task context. This is set to 0 by the driver but can be read by
|
||||
* issuing a dump TC request to the SCU.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct TRANSPORT_SNAPSHOT {
|
||||
/* OFFSET 0x48 */
|
||||
u32 xfer_rdy_write_data_length;
|
||||
|
||||
/* OFFSET 0x4C */
|
||||
u32 data_offset;
|
||||
|
||||
/* OFFSET 0x50 */
|
||||
u32 data_transfer_size:24;
|
||||
u32 reserved_50_0:8;
|
||||
|
||||
/* OFFSET 0x54 */
|
||||
u32 next_initiator_write_data_offset;
|
||||
|
||||
/* OFFSET 0x58 */
|
||||
u32 next_initiator_write_data_xfer_size:24;
|
||||
u32 reserved_58_0:8;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct scu_task_context - This structure defines the contents of the SCU
|
||||
* silicon task context. It lays out all of the fields according to the
|
||||
* expected order and location for the Storage Controller unit.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scu_task_context {
|
||||
/* OFFSET 0x00 ------ */
|
||||
/**
|
||||
* This field must be encoded to one of the valid SCU task priority values
|
||||
* - SCU_TASK_PRIORITY_NORMAL
|
||||
* - SCU_TASK_PRIORITY_HEAD_OF_Q
|
||||
* - SCU_TASK_PRIORITY_HIGH
|
||||
*/
|
||||
u32 priority:2;
|
||||
|
||||
/**
|
||||
* This field must be set to true if this is an initiator generated request.
|
||||
* Until target mode is supported all task requests are initiator requests.
|
||||
*/
|
||||
u32 initiator_request:1;
|
||||
|
||||
/**
|
||||
* This field must be set to one of the valid connection rates valid values
|
||||
* are 0x8, 0x9, and 0xA.
|
||||
*/
|
||||
u32 connection_rate:4;
|
||||
|
||||
/**
|
||||
* This field muse be programed when generating an SMP response since the SMP
|
||||
* connection remains open until the SMP response is generated.
|
||||
*/
|
||||
u32 protocol_engine_index:3;
|
||||
|
||||
/**
|
||||
* This field must contain the logical port for the task request.
|
||||
*/
|
||||
u32 logical_port_index:3;
|
||||
|
||||
/**
|
||||
* This field must be set to one of the SCU_TASK_CONTEXT_PROTOCOL values
|
||||
* - SCU_TASK_CONTEXT_PROTOCOL_SMP
|
||||
* - SCU_TASK_CONTEXT_PROTOCOL_SSP
|
||||
* - SCU_TASK_CONTEXT_PROTOCOL_STP
|
||||
* - SCU_TASK_CONTEXT_PROTOCOL_NONE
|
||||
*/
|
||||
u32 protocol_type:3;
|
||||
|
||||
/**
|
||||
* This filed must be set to the TCi allocated for this task
|
||||
*/
|
||||
u32 task_index:12;
|
||||
|
||||
/**
|
||||
* This field is reserved and must be set to 0x00
|
||||
*/
|
||||
u32 reserved_00_0:1;
|
||||
|
||||
/**
|
||||
* For a normal task request this must be set to 0. If this is an abort of
|
||||
* this task request it must be set to 1.
|
||||
*/
|
||||
u32 abort:1;
|
||||
|
||||
/**
|
||||
* This field must be set to true for the SCU hardware to process the task.
|
||||
*/
|
||||
u32 valid:1;
|
||||
|
||||
/**
|
||||
* This field must be set to SCU_TASK_CONTEXT_TYPE
|
||||
*/
|
||||
u32 context_type:1;
|
||||
|
||||
/* OFFSET 0x04 */
|
||||
/**
|
||||
* This field contains the RNi that is the target of this request.
|
||||
*/
|
||||
u32 remote_node_index:12;
|
||||
|
||||
/**
|
||||
* This field is programmed if this is a mirrored request, which we are not
|
||||
* using, in which case it is the RNi for the mirrored target.
|
||||
*/
|
||||
u32 mirrored_node_index:12;
|
||||
|
||||
/**
|
||||
* This field is programmed with the direction of the SATA reqeust
|
||||
* - SCU_SATA_WRITE_DATA_DIRECTION
|
||||
* - SCU_SATA_READ_DATA_DIRECTION
|
||||
*/
|
||||
u32 sata_direction:1;
|
||||
|
||||
/**
|
||||
* This field is programmsed with one of the following SCU_COMMAND_CODE
|
||||
* - SCU_COMMAND_CODE_INITIATOR_NEW_TASK
|
||||
* - SCU_COMMAND_CODE_ACTIVE_TASK
|
||||
* - SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK
|
||||
* - SCU_COMMAND_CODE_TARGET_RAW_FRAMES
|
||||
*/
|
||||
u32 command_code:2;
|
||||
|
||||
/**
|
||||
* This field is set to true if the remote node should be suspended.
|
||||
* This bit is only valid for SSP & SMP target devices.
|
||||
*/
|
||||
u32 suspend_node:1;
|
||||
|
||||
/**
|
||||
* This field is programmed with one of the following command type codes
|
||||
*
|
||||
* For SAS requests use the SCU_SSP_TASK_TYPE
|
||||
* - SCU_TASK_TYPE_IOREAD
|
||||
* - SCU_TASK_TYPE_IOWRITE
|
||||
* - SCU_TASK_TYPE_SMP_REQUEST
|
||||
* - SCU_TASK_TYPE_RESPONSE
|
||||
* - SCU_TASK_TYPE_RAW_FRAME
|
||||
* - SCU_TASK_TYPE_PRIMITIVE
|
||||
*
|
||||
* For SATA requests use the SCU_SATA_TASK_TYPE
|
||||
* - SCU_TASK_TYPE_DMA_IN
|
||||
* - SCU_TASK_TYPE_FPDMAQ_READ
|
||||
* - SCU_TASK_TYPE_PACKET_DMA_IN
|
||||
* - SCU_TASK_TYPE_SATA_RAW_FRAME
|
||||
* - SCU_TASK_TYPE_DMA_OUT
|
||||
* - SCU_TASK_TYPE_FPDMAQ_WRITE
|
||||
* - SCU_TASK_TYPE_PACKET_DMA_OUT
|
||||
*/
|
||||
u32 task_type:4;
|
||||
|
||||
/* OFFSET 0x08 */
|
||||
/**
|
||||
* This field is reserved and the must be set to 0x00
|
||||
*/
|
||||
u32 link_layer_control:8; /* presently all reserved */
|
||||
|
||||
/**
|
||||
* This field is set to true when TLR is to be enabled
|
||||
*/
|
||||
u32 ssp_tlr_enable:1;
|
||||
|
||||
/**
|
||||
* This is field specifies if the SCU DMAs a response frame to host
|
||||
* memory for good response frames when operating in target mode.
|
||||
*/
|
||||
u32 dma_ssp_target_good_response:1;
|
||||
|
||||
/**
|
||||
* This field indicates if the SCU should DMA the response frame to
|
||||
* host memory.
|
||||
*/
|
||||
u32 do_not_dma_ssp_good_response:1;
|
||||
|
||||
/**
|
||||
* This field is set to true when strict ordering is to be enabled
|
||||
*/
|
||||
u32 strict_ordering:1;
|
||||
|
||||
/**
|
||||
* This field indicates the type of endianess to be utilized for the
|
||||
* frame. command, task, and response frames utilized control_frame
|
||||
* set to 1.
|
||||
*/
|
||||
u32 control_frame:1;
|
||||
|
||||
/**
|
||||
* This field is reserved and the driver should set to 0x00
|
||||
*/
|
||||
u32 tl_control_reserved:3;
|
||||
|
||||
/**
|
||||
* This field is set to true when the SCU hardware task timeout control is to
|
||||
* be enabled
|
||||
*/
|
||||
u32 timeout_enable:1;
|
||||
|
||||
/**
|
||||
* This field is reserved and the driver should set it to 0x00
|
||||
*/
|
||||
u32 pts_control_reserved:7;
|
||||
|
||||
/**
|
||||
* This field should be set to true when block guard is to be enabled
|
||||
*/
|
||||
u32 block_guard_enable:1;
|
||||
|
||||
/**
|
||||
* This field is reserved and the driver should set to 0x00
|
||||
*/
|
||||
u32 sdma_control_reserved:7;
|
||||
|
||||
/* OFFSET 0x0C */
|
||||
/**
|
||||
* This field is the address modifier for this io request it should be
|
||||
* programmed with the virtual function that is making the request.
|
||||
*/
|
||||
u32 address_modifier:16;
|
||||
|
||||
/**
|
||||
* @todo What we support mirrored SMP response frame?
|
||||
*/
|
||||
u32 mirrored_protocol_engine:3; /* mirrored protocol Engine Index */
|
||||
|
||||
/**
|
||||
* If this is a mirrored request the logical port index for the mirrored RNi
|
||||
* must be programmed.
|
||||
*/
|
||||
u32 mirrored_logical_port:4; /* mirrored local port index */
|
||||
|
||||
/**
|
||||
* This field is reserved and the driver must set it to 0x00
|
||||
*/
|
||||
u32 reserved_0C_0:8;
|
||||
|
||||
/**
|
||||
* This field must be set to true if the mirrored request processing is to be
|
||||
* enabled.
|
||||
*/
|
||||
u32 mirror_request_enable:1; /* Mirrored request Enable */
|
||||
|
||||
/* OFFSET 0x10 */
|
||||
/**
|
||||
* This field is the command iu length in dwords
|
||||
*/
|
||||
u32 ssp_command_iu_length:8;
|
||||
|
||||
/**
|
||||
* This is the target TLR enable bit it must be set to 0 when creatning the
|
||||
* task context.
|
||||
*/
|
||||
u32 xfer_ready_tlr_enable:1;
|
||||
|
||||
/**
|
||||
* This field is reserved and the driver must set it to 0x00
|
||||
*/
|
||||
u32 reserved_10_0:7;
|
||||
|
||||
/**
|
||||
* This is the maximum burst size that the SCU hardware will send in one
|
||||
* connection its value is (N x 512) and N must be a multiple of 2. If the
|
||||
* value is 0x00 then maximum burst size is disabled.
|
||||
*/
|
||||
u32 ssp_max_burst_size:16;
|
||||
|
||||
/* OFFSET 0x14 */
|
||||
/**
|
||||
* This filed is set to the number of bytes to be transfered in the request.
|
||||
*/
|
||||
u32 transfer_length_bytes:24; /* In terms of bytes */
|
||||
|
||||
/**
|
||||
* This field is reserved and the driver should set it to 0x00
|
||||
*/
|
||||
u32 reserved_14_0:8;
|
||||
|
||||
/* OFFSET 0x18-0x2C */
|
||||
/**
|
||||
* This union provides for the protocol specif part of the SCU Task Context.
|
||||
*/
|
||||
union PROTOCOL_CONTEXT type;
|
||||
|
||||
/* OFFSET 0x30-0x34 */
|
||||
/**
|
||||
* This field is the upper 32 bits of the 64 bit physical address of the
|
||||
* command iu buffer
|
||||
*/
|
||||
u32 command_iu_upper;
|
||||
|
||||
/**
|
||||
* This field is the lower 32 bits of the 64 bit physical address of the
|
||||
* command iu buffer
|
||||
*/
|
||||
u32 command_iu_lower;
|
||||
|
||||
/* OFFSET 0x38-0x3C */
|
||||
/**
|
||||
* This field is the upper 32 bits of the 64 bit physical address of the
|
||||
* response iu buffer
|
||||
*/
|
||||
u32 response_iu_upper;
|
||||
|
||||
/**
|
||||
* This field is the lower 32 bits of the 64 bit physical address of the
|
||||
* response iu buffer
|
||||
*/
|
||||
u32 response_iu_lower;
|
||||
|
||||
/* OFFSET 0x40 */
|
||||
/**
|
||||
* This field is set to the task phase of the SCU hardware. The driver must
|
||||
* set this to 0x01
|
||||
*/
|
||||
u32 task_phase:8;
|
||||
|
||||
/**
|
||||
* This field is set to the transport layer task status. The driver must set
|
||||
* this to 0x00
|
||||
*/
|
||||
u32 task_status:8;
|
||||
|
||||
/**
|
||||
* This field is used during initiator write TLR
|
||||
*/
|
||||
u32 previous_extended_tag:4;
|
||||
|
||||
/**
|
||||
* This field is set the maximum number of retries for a STP non-data FIS
|
||||
*/
|
||||
u32 stp_retry_count:2;
|
||||
|
||||
/**
|
||||
* This field is reserved and the driver must set it to 0x00
|
||||
*/
|
||||
u32 reserved_40_1:2;
|
||||
|
||||
/**
|
||||
* This field is used by the SCU TL to determine when to take a snapshot when
|
||||
* tranmitting read data frames.
|
||||
* - 0x00 The entire IO
|
||||
* - 0x01 32k
|
||||
* - 0x02 64k
|
||||
* - 0x04 128k
|
||||
* - 0x08 256k
|
||||
*/
|
||||
u32 ssp_tlr_threshold:4;
|
||||
|
||||
/**
|
||||
* This field is reserved and the driver must set it to 0x00
|
||||
*/
|
||||
u32 reserved_40_2:4;
|
||||
|
||||
/* OFFSET 0x44 */
|
||||
u32 write_data_length; /* read only set to 0 */
|
||||
|
||||
/* OFFSET 0x48-0x58 */
|
||||
struct TRANSPORT_SNAPSHOT snapshot; /* read only set to 0 */
|
||||
|
||||
/* OFFSET 0x5C */
|
||||
u32 block_protection_enable:1;
|
||||
u32 block_size:2;
|
||||
u32 block_protection_function:2;
|
||||
u32 reserved_5C_0:9;
|
||||
u32 active_sgl_element:2; /* read only set to 0 */
|
||||
u32 sgl_exhausted:1; /* read only set to 0 */
|
||||
u32 payload_data_transfer_error:4; /* read only set to 0 */
|
||||
u32 frame_buffer_offset:11; /* read only set to 0 */
|
||||
|
||||
/* OFFSET 0x60-0x7C */
|
||||
/**
|
||||
* This field is the first SGL element pair found in the TC data structure.
|
||||
*/
|
||||
struct scu_sgl_element_pair sgl_pair_ab;
|
||||
/* OFFSET 0x80-0x9C */
|
||||
/**
|
||||
* This field is the second SGL element pair found in the TC data structure.
|
||||
*/
|
||||
struct scu_sgl_element_pair sgl_pair_cd;
|
||||
|
||||
/* OFFSET 0xA0-BC */
|
||||
struct scu_sgl_element_pair sgl_snapshot_ac;
|
||||
|
||||
/* OFFSET 0xC0 */
|
||||
u32 active_sgl_element_pair; /* read only set to 0 */
|
||||
|
||||
/* OFFSET 0xC4-0xCC */
|
||||
u32 reserved_C4_CC[3];
|
||||
|
||||
/* OFFSET 0xD0 */
|
||||
u32 intermediate_crc_value:16;
|
||||
u32 initial_crc_seed:16;
|
||||
|
||||
/* OFFSET 0xD4 */
|
||||
u32 application_tag_for_verify:16;
|
||||
u32 application_tag_for_generate:16;
|
||||
|
||||
/* OFFSET 0xD8 */
|
||||
u32 reference_tag_seed_for_verify_function;
|
||||
|
||||
/* OFFSET 0xDC */
|
||||
u32 reserved_DC;
|
||||
|
||||
/* OFFSET 0xE0 */
|
||||
u32 reserved_E0_0:16;
|
||||
u32 application_tag_mask_for_generate:16;
|
||||
|
||||
/* OFFSET 0xE4 */
|
||||
u32 block_protection_control:16;
|
||||
u32 application_tag_mask_for_verify:16;
|
||||
|
||||
/* OFFSET 0xE8 */
|
||||
u32 block_protection_error:8;
|
||||
u32 reserved_E8_0:24;
|
||||
|
||||
/* OFFSET 0xEC */
|
||||
u32 reference_tag_seed_for_verify;
|
||||
|
||||
/* OFFSET 0xF0 */
|
||||
u32 intermediate_crc_valid_snapshot:16;
|
||||
u32 reserved_F0_0:16;
|
||||
|
||||
/* OFFSET 0xF4 */
|
||||
u32 reference_tag_seed_for_verify_function_snapshot;
|
||||
|
||||
/* OFFSET 0xF8 */
|
||||
u32 snapshot_of_reserved_dword_DC_of_tc;
|
||||
|
||||
/* OFFSET 0xFC */
|
||||
u32 reference_tag_seed_for_generate_function_snapshot;
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SCU_TASK_CONTEXT_H_ */
|
||||
117
drivers/scsi/isci/core/scu_unsolicited_frame.h
Normal file
117
drivers/scsi/isci/core/scu_unsolicited_frame.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This field defines the SCU format of an unsolicited frame (UF). A UF is a
|
||||
* frame received by the SCU for which there is no known corresponding task
|
||||
* context (TC).
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SCU_UNSOLICITED_FRAME_H_
|
||||
#define _SCU_UNSOLICITED_FRAME_H_
|
||||
|
||||
#include "sci_types.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This constant defines the number of DWORDS found the unsolicited frame
|
||||
* header data member.
|
||||
*/
|
||||
#define SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS 15
|
||||
|
||||
/**
|
||||
* struct scu_unsolicited_frame_header -
|
||||
*
|
||||
* This structure delineates the format of an unsolicited frame header. The
|
||||
* first DWORD are UF attributes defined by the silicon architecture. The data
|
||||
* depicts actual header information received on the link.
|
||||
*/
|
||||
struct scu_unsolicited_frame_header {
|
||||
/**
|
||||
* This field indicates if there is an Initiator Index Table entry with
|
||||
* which this header is associated.
|
||||
*/
|
||||
u32 iit_exists:1;
|
||||
|
||||
/**
|
||||
* This field simply indicates the protocol type (i.e. SSP, STP, SMP).
|
||||
*/
|
||||
u32 protocol_type:3;
|
||||
|
||||
/**
|
||||
* This field indicates if the frame is an address frame (IAF or OAF)
|
||||
* or if it is a information unit frame.
|
||||
*/
|
||||
u32 is_address_frame:1;
|
||||
|
||||
/**
|
||||
* This field simply indicates the connection rate at which the frame
|
||||
* was received.
|
||||
*/
|
||||
u32 connection_rate:4;
|
||||
|
||||
u32 reserved:23;
|
||||
|
||||
/**
|
||||
* This field represents the actual header data received on the link.
|
||||
*/
|
||||
u32 data[SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS];
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SCU_UNSOLICITED_FRAME_H_ */
|
||||
179
drivers/scsi/isci/core/scu_viit_data.h
Normal file
179
drivers/scsi/isci/core/scu_viit_data.h
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCU_VIIT_DATA_HEADER_
|
||||
#define _SCU_VIIT_DATA_HEADER_
|
||||
|
||||
/**
|
||||
* This file contains the constants and structures for the SCU hardware VIIT
|
||||
* table entries.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci_types.h"
|
||||
|
||||
#define SCU_VIIT_ENTRY_ID_MASK (0xC0000000)
|
||||
#define SCU_VIIT_ENTRY_ID_SHIFT (30)
|
||||
|
||||
#define SCU_VIIT_ENTRY_FUNCTION_MASK (0x0FF00000)
|
||||
#define SCU_VIIT_ENTRY_FUNCTION_SHIFT (20)
|
||||
|
||||
#define SCU_VIIT_ENTRY_IPPTMODE_MASK (0x0001F800)
|
||||
#define SCU_VIIT_ENTRY_IPPTMODE_SHIFT (12)
|
||||
|
||||
#define SCU_VIIT_ENTRY_LPVIE_MASK (0x00000F00)
|
||||
#define SCU_VIIT_ENTRY_LPVIE_SHIFT (8)
|
||||
|
||||
#define SCU_VIIT_ENTRY_STATUS_MASK (0x000000FF)
|
||||
#define SCU_VIIT_ENTRY_STATUS_SHIFT (0)
|
||||
|
||||
#define SCU_VIIT_ENTRY_ID_INVALID (0 << SCU_VIIT_ENTRY_ID_SHIFT)
|
||||
#define SCU_VIIT_ENTRY_ID_VIIT (1 << SCU_VIIT_ENTRY_ID_SHIFT)
|
||||
#define SCU_VIIT_ENTRY_ID_IIT (2 << SCU_VIIT_ENTRY_ID_SHIFT)
|
||||
#define SCU_VIIT_ENTRY_ID_VIRT_EXP (3 << SCU_VIIT_ENTRY_ID_SHIFT)
|
||||
|
||||
#define SCU_VIIT_IPPT_SSP_INITIATOR (0x01 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
|
||||
#define SCU_VIIT_IPPT_SMP_INITIATOR (0x02 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
|
||||
#define SCU_VIIT_IPPT_STP_INITIATOR (0x04 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
|
||||
#define SCU_VIIT_IPPT_INITIATOR \
|
||||
(\
|
||||
SCU_VIIT_IPPT_SSP_INITIATOR \
|
||||
| SCU_VIIT_IPPT_SMP_INITIATOR \
|
||||
| SCU_VIIT_IPPT_STP_INITIATOR \
|
||||
)
|
||||
|
||||
#define SCU_VIIT_STATUS_RNC_VALID (0x01 << SCU_VIIT_ENTRY_STATUS_SHIFT)
|
||||
#define SCU_VIIT_STATUS_ADDRESS_VALID (0x02 << SCU_VIIT_ENTRY_STATUS_SHIFT)
|
||||
#define SCU_VIIT_STATUS_RNI_VALID (0x04 << SCU_VIIT_ENTRY_STATUS_SHIFT)
|
||||
#define SCU_VIIT_STATUS_ALL_VALID \
|
||||
(\
|
||||
SCU_VIIT_STATUS_RNC_VALID \
|
||||
| SCU_VIIT_STATUS_ADDRESS_VALID \
|
||||
| SCU_VIIT_STATUS_RNI_VALID \
|
||||
)
|
||||
|
||||
#define SCU_VIIT_IPPT_SMP_TARGET (0x10 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
|
||||
|
||||
/**
|
||||
* struct scu_viit_entry - This is the SCU Virtual Initiator Table Entry
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scu_viit_entry {
|
||||
/**
|
||||
* This must be encoded as to the type of initiator that is being constructed
|
||||
* for this port.
|
||||
*/
|
||||
u32 status;
|
||||
|
||||
/**
|
||||
* Virtual initiator high SAS Address
|
||||
*/
|
||||
u32 initiator_sas_address_hi;
|
||||
|
||||
/**
|
||||
* Virtual initiator low SAS Address
|
||||
*/
|
||||
u32 initiator_sas_address_lo;
|
||||
|
||||
/**
|
||||
* This must be 0
|
||||
*/
|
||||
u32 reserved;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/* IIT Status Defines */
|
||||
#define SCU_IIT_ENTRY_ID_MASK (0xC0000000)
|
||||
#define SCU_IIT_ENTRY_ID_SHIFT (30)
|
||||
|
||||
#define SCU_IIT_ENTRY_STATUS_UPDATE_MASK (0x20000000)
|
||||
#define SCU_IIT_ENTRY_STATUS_UPDATE_SHIFT (29)
|
||||
|
||||
#define SCU_IIT_ENTRY_LPI_MASK (0x00000F00)
|
||||
#define SCU_IIT_ENTRY_LPI_SHIFT (8)
|
||||
|
||||
#define SCU_IIT_ENTRY_STATUS_MASK (0x000000FF)
|
||||
#define SCU_IIT_ENTRY_STATUS_SHIFT (0)
|
||||
|
||||
/* IIT Remote Initiator Defines */
|
||||
#define SCU_IIT_ENTRY_REMOTE_TAG_MASK (0x0000FFFF)
|
||||
#define SCU_IIT_ENTRY_REMOTE_TAG_SHIFT (0)
|
||||
|
||||
#define SCU_IIT_ENTRY_REMOTE_RNC_MASK (0x0FFF0000)
|
||||
#define SCU_IIT_ENTRY_REMOTE_RNC_SHIFT (16)
|
||||
|
||||
#define SCU_IIT_ENTRY_ID_INVALID (0 << SCU_IIT_ENTRY_ID_SHIFT)
|
||||
#define SCU_IIT_ENTRY_ID_VIIT (1 << SCU_IIT_ENTRY_ID_SHIFT)
|
||||
#define SCU_IIT_ENTRY_ID_IIT (2 << SCU_IIT_ENTRY_ID_SHIFT)
|
||||
#define SCU_IIT_ENTRY_ID_VIRT_EXP (3 << SCU_IIT_ENTRY_ID_SHIFT)
|
||||
|
||||
/**
|
||||
* struct scu_iit_entry - This will be implemented later when we support
|
||||
* virtual functions
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct scu_iit_entry {
|
||||
u32 status;
|
||||
u32 remote_initiator_sas_address_hi;
|
||||
u32 remote_initiator_sas_address_lo;
|
||||
u32 remote_initiator;
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SCU_VIIT_DATA_HEADER_ */
|
||||
491
drivers/scsi/isci/deprecated.c
Normal file
491
drivers/scsi/isci/deprecated.c
Normal file
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* This file contains isci module object implementation.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "isci.h"
|
||||
#include "request.h"
|
||||
#include "sata.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
/**
|
||||
* scic_cb_stall_execution() - This method is called when the core requires the
|
||||
* OS driver to stall execution. This method is utilized during
|
||||
* initialization or non-performance paths only.
|
||||
* @microseconds: This parameter specifies the number of microseconds for which
|
||||
* to stall. The operating system driver is allowed to round this value up
|
||||
* where necessary.
|
||||
*
|
||||
* none.
|
||||
*/
|
||||
void scic_cb_stall_execution(
|
||||
u32 microseconds)
|
||||
{
|
||||
udelay(microseconds);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* scic_cb_io_request_get_physical_address() - This callback method asks the
|
||||
* user to provide the physical address for the supplied virtual address
|
||||
* when building an io request object.
|
||||
* @controller: This parameter is the core controller object handle.
|
||||
* @io_request: This parameter is the io request object handle for which the
|
||||
* physical address is being requested.
|
||||
*
|
||||
*
|
||||
*/
|
||||
void scic_cb_io_request_get_physical_address(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_request *io_request,
|
||||
void *virtual_address,
|
||||
dma_addr_t *physical_address)
|
||||
{
|
||||
struct isci_request *request =
|
||||
(struct isci_request *)sci_object_get_association(io_request);
|
||||
|
||||
char *requested_address = (char *)virtual_address;
|
||||
char *base_address = (char *)request;
|
||||
|
||||
BUG_ON(requested_address < base_address);
|
||||
BUG_ON((requested_address - base_address) >=
|
||||
request->request_alloc_size);
|
||||
|
||||
*physical_address = request->request_daddr +
|
||||
(requested_address - base_address);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_io_request_get_transfer_length() - This callback method asks the
|
||||
* user to provide the number of bytes to be transfered as part of this
|
||||
* request.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the number of payload data bytes to be transfered for
|
||||
* this IO request.
|
||||
*/
|
||||
u32 scic_cb_io_request_get_transfer_length(
|
||||
void *scic_user_io_request)
|
||||
{
|
||||
return isci_request_io_request_get_transfer_length(
|
||||
scic_user_io_request
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* scic_cb_io_request_get_data_direction() - This callback method asks the user
|
||||
* to provide the data direction for this request.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the value of SCI_IO_REQUEST_DATA_OUT or
|
||||
* SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA.
|
||||
*/
|
||||
SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction(
|
||||
void *scic_user_io_request)
|
||||
{
|
||||
return isci_request_io_request_get_data_direction(
|
||||
scic_user_io_request
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* scic_cb_io_request_get_next_sge() - This callback method asks the user to
|
||||
* provide the address to where the next Scatter-Gather Element is located.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
* @current_sge_address: This parameter specifies the address for the current
|
||||
* SGE (i.e. the one that has just processed).
|
||||
*
|
||||
* An address specifying the location for the next scatter gather element to be
|
||||
* processed.
|
||||
*/
|
||||
void scic_cb_io_request_get_next_sge(
|
||||
void *scic_user_io_request,
|
||||
void *current_sge_address,
|
||||
void **next_sge)
|
||||
{
|
||||
*next_sge = isci_request_io_request_get_next_sge(
|
||||
scic_user_io_request,
|
||||
current_sge_address
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_sge_get_address_field() - This callback method asks the user to
|
||||
* provide the contents of the "address" field in the Scatter-Gather Element.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
* @sge_address: This parameter specifies the address for the SGE from which to
|
||||
* retrieve the address field.
|
||||
*
|
||||
* A physical address specifying the contents of the SGE's address field.
|
||||
*/
|
||||
dma_addr_t scic_cb_sge_get_address_field(
|
||||
void *scic_user_io_request,
|
||||
void *sge_address)
|
||||
{
|
||||
return isci_request_sge_get_address_field(
|
||||
scic_user_io_request,
|
||||
sge_address
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_sge_get_length_field() - This callback method asks the user to
|
||||
* provide the contents of the "length" field in the Scatter-Gather Element.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
* @sge_address: This parameter specifies the address for the SGE from which to
|
||||
* retrieve the address field.
|
||||
*
|
||||
* This method returns the length field specified inside the SGE referenced by
|
||||
* the sge_address parameter.
|
||||
*/
|
||||
u32 scic_cb_sge_get_length_field(
|
||||
void *scic_user_io_request,
|
||||
void *sge_address)
|
||||
{
|
||||
return isci_request_sge_get_length_field(
|
||||
scic_user_io_request,
|
||||
sge_address
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_io_request_get_cdb_address() - This callback method asks the
|
||||
* user to provide the address for the command descriptor block (CDB)
|
||||
* associated with this IO request.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the virtual address of the CDB.
|
||||
*/
|
||||
void *scic_cb_ssp_io_request_get_cdb_address(
|
||||
void *scic_user_io_request)
|
||||
{
|
||||
return isci_request_ssp_io_request_get_cdb_address(
|
||||
scic_user_io_request
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_io_request_get_cdb_length() - This callback method asks the user
|
||||
* to provide the length of the command descriptor block (CDB) associated
|
||||
* with this IO request.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the length of the CDB.
|
||||
*/
|
||||
u32 scic_cb_ssp_io_request_get_cdb_length(
|
||||
void *scic_user_io_request)
|
||||
{
|
||||
return isci_request_ssp_io_request_get_cdb_length(
|
||||
scic_user_io_request
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_io_request_get_lun() - This callback method asks the user to
|
||||
* provide the Logical Unit (LUN) associated with this IO request.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the LUN associated with this request. This should be u64?
|
||||
*/
|
||||
u32 scic_cb_ssp_io_request_get_lun(
|
||||
void *scic_user_io_request)
|
||||
{
|
||||
return isci_request_ssp_io_request_get_lun(scic_user_io_request);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_io_request_get_task_attribute() - This callback method asks the
|
||||
* user to provide the task attribute associated with this IO request.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the task attribute associated with this IO request.
|
||||
*/
|
||||
u32 scic_cb_ssp_io_request_get_task_attribute(
|
||||
void *scic_user_io_request)
|
||||
{
|
||||
return isci_request_ssp_io_request_get_task_attribute(
|
||||
scic_user_io_request
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_io_request_get_command_priority() - This callback method asks
|
||||
* the user to provide the command priority associated with this IO request.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the command priority associated with this IO request.
|
||||
*/
|
||||
u32 scic_cb_ssp_io_request_get_command_priority(
|
||||
void *scic_user_io_request)
|
||||
{
|
||||
return isci_request_ssp_io_request_get_command_priority(
|
||||
scic_user_io_request
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_task_request_get_lun() - This method returns the Logical Unit to
|
||||
* be utilized for this task management request.
|
||||
* @scic_user_task_request: This parameter points to the user's task request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the LUN associated with this request. This should be u64?
|
||||
*/
|
||||
u32 scic_cb_ssp_task_request_get_lun(
|
||||
void *scic_user_task_request)
|
||||
{
|
||||
return isci_task_ssp_request_get_lun(
|
||||
(struct isci_request *)scic_user_task_request
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_task_request_get_function() - This method returns the task
|
||||
* management function to be utilized for this task request.
|
||||
* @scic_user_task_request: This parameter points to the user's task request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns an unsigned byte representing the task management
|
||||
* function to be performed.
|
||||
*/
|
||||
u8 scic_cb_ssp_task_request_get_function(
|
||||
void *scic_user_task_request)
|
||||
{
|
||||
return isci_task_ssp_request_get_function(
|
||||
(struct isci_request *)scic_user_task_request
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_task_request_get_io_tag_to_manage() - This method returns the
|
||||
* task management IO tag to be managed. Depending upon the task management
|
||||
* function the value returned from this method may be ignored.
|
||||
* @scic_user_task_request: This parameter points to the user's task request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns an unsigned 16-bit word depicting the IO tag to be
|
||||
* managed.
|
||||
*/
|
||||
u16 scic_cb_ssp_task_request_get_io_tag_to_manage(
|
||||
void *scic_user_task_request)
|
||||
{
|
||||
return isci_task_ssp_request_get_io_tag_to_manage(
|
||||
(struct isci_request *)scic_user_task_request
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_task_request_get_response_data_address() - This callback method
|
||||
* asks the user to provide the virtual address of the response data buffer
|
||||
* for the supplied IO request.
|
||||
* @scic_user_task_request: This parameter points to the user's task request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the virtual address for the response data buffer
|
||||
* associated with this IO request.
|
||||
*/
|
||||
void *scic_cb_ssp_task_request_get_response_data_address(
|
||||
void *scic_user_task_request)
|
||||
{
|
||||
return isci_task_ssp_request_get_response_data_address(
|
||||
(struct isci_request *)scic_user_task_request
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_ssp_task_request_get_response_data_length() - This callback method
|
||||
* asks the user to provide the length of the response data buffer for the
|
||||
* supplied IO request.
|
||||
* @scic_user_task_request: This parameter points to the user's task request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns the length of the response buffer data associated with
|
||||
* this IO request.
|
||||
*/
|
||||
u32 scic_cb_ssp_task_request_get_response_data_length(
|
||||
void *scic_user_task_request)
|
||||
{
|
||||
return isci_task_ssp_request_get_response_data_length(
|
||||
(struct isci_request *)scic_user_task_request
|
||||
);
|
||||
}
|
||||
|
||||
#if !defined(DISABLE_ATAPI)
|
||||
/**
|
||||
* scic_cb_stp_packet_io_request_get_cdb_address() - This user callback asks
|
||||
* the user to provide stp packet io's the CDB address.
|
||||
* @scic_user_io_request:
|
||||
*
|
||||
* The packet IO's cdb adress.
|
||||
*/
|
||||
void *scic_cb_stp_packet_io_request_get_cdb_address(
|
||||
void *scic_user_io_request)
|
||||
{
|
||||
return isci_request_stp_packet_io_request_get_cdb_address(
|
||||
scic_user_io_request
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* scic_cb_stp_packet_io_request_get_cdb_length() - This user callback asks the
|
||||
* user to provide stp packet io's the CDB length.
|
||||
* @scic_user_io_request:
|
||||
*
|
||||
* The packet IO's cdb length.
|
||||
*/
|
||||
u32 scic_cb_stp_packet_io_request_get_cdb_length(
|
||||
void *scic_user_io_request)
|
||||
{
|
||||
return isci_request_stp_packet_io_request_get_cdb_length(
|
||||
scic_user_io_request
|
||||
);
|
||||
}
|
||||
#endif /* #if !defined(DISABLE_ATAPI) */
|
||||
|
||||
|
||||
/**
|
||||
* scic_cb_io_request_do_copy_rx_frames() - This callback method asks the user
|
||||
* if the received RX frame data is to be copied to the SGL or should be
|
||||
* stored by the SCI core to be retrieved later with the
|
||||
* scic_io_request_get_rx_frame().
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns true if the SCI core should copy the received frame data
|
||||
* to the SGL location or false if the SCI user wants to retrieve the frame
|
||||
* data at a later time.
|
||||
*/
|
||||
bool scic_cb_io_request_do_copy_rx_frames(
|
||||
void *scic_user_io_request)
|
||||
{
|
||||
struct sas_task *task
|
||||
= isci_request_access_task(
|
||||
(struct isci_request *)scic_user_io_request
|
||||
);
|
||||
|
||||
return (task->data_dir == DMA_NONE) ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_get_virtual_address() - This callback method asks the user to
|
||||
* provide the virtual address for the supplied physical address.
|
||||
* @controller: This parameter is the core controller object handle.
|
||||
* @physical_address: This parameter is the physical address which is to be
|
||||
* returned as a virtual address.
|
||||
*
|
||||
* The method returns the virtual address for the supplied physical address.
|
||||
*/
|
||||
void *scic_cb_get_virtual_address(
|
||||
struct scic_sds_controller *controller,
|
||||
dma_addr_t physical_address)
|
||||
{
|
||||
void *virt_addr = (void *)phys_to_virt(physical_address);
|
||||
|
||||
return virt_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_request_get_sat_protocol() - This callback method asks the user to
|
||||
* return the SAT protocol definition for this IO request. This method is
|
||||
* only called by the SCI core if the request type constructed is SATA.
|
||||
* @scic_user_io_request: This parameter points to the user's IO request
|
||||
* object. It is a cookie that allows the user to provide the necessary
|
||||
* information for this callback.
|
||||
*
|
||||
* This method returns one of the sat.h defined protocols for the given io
|
||||
* request.
|
||||
*/
|
||||
u8 scic_cb_request_get_sat_protocol(
|
||||
void *scic_user_io_request)
|
||||
{
|
||||
return isci_sata_get_sat_protocol(
|
||||
(struct isci_request *)scic_user_io_request
|
||||
);
|
||||
}
|
||||
619
drivers/scsi/isci/events.c
Normal file
619
drivers/scsi/isci/events.c
Normal file
@@ -0,0 +1,619 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* This file contains isci module object implementation.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "isci.h"
|
||||
#include "request.h"
|
||||
#include "sata.h"
|
||||
#include "task.h"
|
||||
|
||||
/**
|
||||
* scic_cb_timer_create() - This callback method asks the user to create a
|
||||
* timer and provide a handle for this timer for use in further timer
|
||||
* interactions. The appropriate isci timer object function is called to
|
||||
* create a timer object.
|
||||
* @timer_callback: This parameter specifies the callback method to be invoked
|
||||
* whenever the timer expires.
|
||||
* @controller: This parameter specifies the controller with which this timer
|
||||
* is to be associated.
|
||||
* @cookie: This parameter specifies a piece of information that the user must
|
||||
* retain. This cookie is to be supplied by the user anytime a timeout
|
||||
* occurs for the created timer.
|
||||
*
|
||||
* This method returns a handle to a timer object created by the user. The
|
||||
* handle will be utilized for all further interactions relating to this timer.
|
||||
*/
|
||||
void *scic_cb_timer_create(
|
||||
struct scic_sds_controller *controller,
|
||||
void (*timer_callback)(void *),
|
||||
void *cookie)
|
||||
{
|
||||
struct isci_host *isci_host;
|
||||
struct isci_timer *timer = NULL;
|
||||
|
||||
isci_host = (struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_host = %p",
|
||||
__func__, isci_host);
|
||||
|
||||
timer = isci_timer_create(&isci_host->timer_list_struct,
|
||||
isci_host,
|
||||
cookie,
|
||||
timer_callback);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev, "%s: timer = %p\n", __func__, timer);
|
||||
|
||||
return (void *)timer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* scic_cb_timer_start() - This callback method asks the user to start the
|
||||
* supplied timer. The appropriate isci timer object function is called to
|
||||
* start the timer.
|
||||
* @controller: This parameter specifies the controller with which this timer
|
||||
* is to associated.
|
||||
* @timer: This parameter specifies the timer to be started.
|
||||
* @milliseconds: This parameter specifies the number of milliseconds for which
|
||||
* to stall. The operating system driver is allowed to round this value up
|
||||
* where necessary.
|
||||
*
|
||||
*/
|
||||
void scic_cb_timer_start(
|
||||
struct scic_sds_controller *controller,
|
||||
void *timer,
|
||||
u32 milliseconds)
|
||||
{
|
||||
struct isci_host *isci_host;
|
||||
|
||||
isci_host =
|
||||
(struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_host = %p, timer = %p, milliseconds = %d\n",
|
||||
__func__, isci_host, timer, milliseconds);
|
||||
|
||||
isci_timer_start((struct isci_timer *)timer, milliseconds);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_timer_stop() - This callback method asks the user to stop the
|
||||
* supplied timer. The appropriate isci timer object function is called to
|
||||
* stop the timer.
|
||||
* @controller: This parameter specifies the controller with which this timer
|
||||
* is to associated.
|
||||
* @timer: This parameter specifies the timer to be stopped.
|
||||
*
|
||||
*/
|
||||
void scic_cb_timer_stop(
|
||||
struct scic_sds_controller *controller,
|
||||
void *timer)
|
||||
{
|
||||
struct isci_host *isci_host;
|
||||
|
||||
isci_host =
|
||||
(struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_host = %p, timer = %p\n",
|
||||
__func__, isci_host, timer);
|
||||
|
||||
isci_timer_stop((struct isci_timer *)timer);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_controller_start_complete() - This user callback will inform the
|
||||
* user that the controller has finished the start process. The associated
|
||||
* isci host adapter's start_complete function is called.
|
||||
* @controller: This parameter specifies the controller that was started.
|
||||
* @completion_status: This parameter specifies the results of the start
|
||||
* operation. SCI_SUCCESS indicates successful completion.
|
||||
*
|
||||
*/
|
||||
void scic_cb_controller_start_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
enum sci_status completion_status)
|
||||
{
|
||||
struct isci_host *isci_host =
|
||||
(struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_host = %p\n", __func__, isci_host);
|
||||
|
||||
isci_host_start_complete(isci_host, completion_status);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_controller_stop_complete() - This user callback will inform the user
|
||||
* that the controller has finished the stop process. The associated isci
|
||||
* host adapter's start_complete function is called.
|
||||
* @controller: This parameter specifies the controller that was stopped.
|
||||
* @completion_status: This parameter specifies the results of the stop
|
||||
* operation. SCI_SUCCESS indicates successful completion.
|
||||
*
|
||||
*/
|
||||
void scic_cb_controller_stop_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
enum sci_status completion_status)
|
||||
{
|
||||
struct isci_host *isci_host =
|
||||
(struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: status = 0x%x\n", __func__, completion_status);
|
||||
isci_host_stop_complete(isci_host, completion_status);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_io_request_complete() - This user callback will inform the user that
|
||||
* an IO request has completed.
|
||||
* @controller: This parameter specifies the controller on which the IO is
|
||||
* completing.
|
||||
* @remote_device: This parameter specifies the remote device on which this IO
|
||||
* request is completing.
|
||||
* @io_request: This parameter specifies the IO request that has completed.
|
||||
* @completion_status: This parameter specifies the results of the IO request
|
||||
* operation. SCI_SUCCESS indicates successful completion.
|
||||
*
|
||||
*/
|
||||
void scic_cb_io_request_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
struct scic_sds_request *scic_io_request,
|
||||
enum sci_io_status completion_status)
|
||||
{
|
||||
struct isci_request *request;
|
||||
struct isci_host *isci_host;
|
||||
|
||||
isci_host =
|
||||
(struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
request =
|
||||
(struct isci_request *)sci_object_get_association(
|
||||
scic_io_request
|
||||
);
|
||||
|
||||
isci_request_io_request_complete(isci_host,
|
||||
request,
|
||||
completion_status);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_task_request_complete() - This user callback will inform the user
|
||||
* that a task management request completed.
|
||||
* @controller: This parameter specifies the controller on which the task
|
||||
* management request is completing.
|
||||
* @remote_device: This parameter specifies the remote device on which this
|
||||
* task management request is completing.
|
||||
* @task_request: This parameter specifies the task management request that has
|
||||
* completed.
|
||||
* @completion_status: This parameter specifies the results of the IO request
|
||||
* operation. SCI_SUCCESS indicates successful completion.
|
||||
*
|
||||
*/
|
||||
void scic_cb_task_request_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
struct scic_sds_request *scic_task_request,
|
||||
enum sci_task_status completion_status)
|
||||
{
|
||||
struct isci_request *request;
|
||||
struct isci_host *isci_host;
|
||||
|
||||
isci_host =
|
||||
(struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
request =
|
||||
(struct isci_request *)sci_object_get_association(
|
||||
scic_task_request);
|
||||
|
||||
isci_task_request_complete(isci_host, request, completion_status);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_port_stop_complete() - This method informs the user when a stop
|
||||
* operation on the port has completed.
|
||||
* @controller: This parameter represents the controller which contains the
|
||||
* port.
|
||||
* @port: This parameter specifies the SCI port object for which the callback
|
||||
* is being invoked.
|
||||
* @completion_status: This parameter specifies the status for the operation
|
||||
* being completed.
|
||||
*
|
||||
*/
|
||||
void scic_cb_port_stop_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port,
|
||||
enum sci_status completion_status)
|
||||
{
|
||||
pr_warn("%s:************************************************\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_port_hard_reset_complete() - This method informs the user when a
|
||||
* hard reset on the port has completed. This hard reset could have been
|
||||
* initiated by the user or by the remote port.
|
||||
* @controller: This parameter represents the controller which contains the
|
||||
* port.
|
||||
* @port: This parameter specifies the SCI port object for which the callback
|
||||
* is being invoked.
|
||||
* @completion_status: This parameter specifies the status for the operation
|
||||
* being completed.
|
||||
*
|
||||
*/
|
||||
void scic_cb_port_hard_reset_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port,
|
||||
enum sci_status completion_status)
|
||||
{
|
||||
struct isci_port *isci_port
|
||||
= (struct isci_port *)sci_object_get_association(port);
|
||||
|
||||
isci_port_hard_reset_complete(isci_port, completion_status);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_port_ready() - This method informs the user that the port is now in
|
||||
* a ready state and can be utilized to issue IOs.
|
||||
* @controller: This parameter represents the controller which contains the
|
||||
* port.
|
||||
* @port: This parameter specifies the SCI port object for which the callback
|
||||
* is being invoked.
|
||||
*
|
||||
*/
|
||||
void scic_cb_port_ready(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port)
|
||||
{
|
||||
struct isci_port *isci_port;
|
||||
struct isci_host *isci_host;
|
||||
|
||||
isci_host =
|
||||
(struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
isci_port =
|
||||
(struct isci_port *)sci_object_get_association(port);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_port = %p\n", __func__, isci_port);
|
||||
|
||||
isci_port_ready(isci_host, isci_port);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_port_not_ready() - This method informs the user that the port is now
|
||||
* not in a ready (i.e. busy) state and can't be utilized to issue IOs.
|
||||
* @controller: This parameter represents the controller which contains the
|
||||
* port.
|
||||
* @port: This parameter specifies the SCI port object for which the callback
|
||||
* is being invoked.
|
||||
*
|
||||
*/
|
||||
void scic_cb_port_not_ready(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port,
|
||||
u32 reason_code)
|
||||
{
|
||||
struct isci_port *isci_port;
|
||||
struct isci_host *isci_host;
|
||||
|
||||
isci_host =
|
||||
(struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
isci_port =
|
||||
(struct isci_port *)sci_object_get_association(port);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_port = %p\n", __func__, isci_port);
|
||||
|
||||
isci_port_not_ready(isci_host, isci_port);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_port_invalid_link_up() - This method informs the SCI Core user that
|
||||
* a phy/link became ready, but the phy is not allowed in the port. In some
|
||||
* situations the underlying hardware only allows for certain phy to port
|
||||
* mappings. If these mappings are violated, then this API is invoked.
|
||||
* @controller: This parameter represents the controller which contains the
|
||||
* port.
|
||||
* @port: This parameter specifies the SCI port object for which the callback
|
||||
* is being invoked.
|
||||
* @phy: This parameter specifies the phy that came ready, but the phy can't be
|
||||
* a valid member of the port.
|
||||
*
|
||||
*/
|
||||
void scic_cb_port_invalid_link_up(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy)
|
||||
{
|
||||
pr_warn("%s:************************************************\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_port_bc_change_primitive_received() - This callback method informs
|
||||
* the user that a broadcast change primitive was received.
|
||||
* @controller: This parameter represents the controller which contains the
|
||||
* port.
|
||||
* @port: This parameter specifies the SCI port object for which the callback
|
||||
* is being invoked. For instances where the phy on which the primitive was
|
||||
* received is not part of a port, this parameter will be
|
||||
* SCI_INVALID_HANDLE_T.
|
||||
* @phy: This parameter specifies the phy on which the primitive was received.
|
||||
*
|
||||
*/
|
||||
void scic_cb_port_bc_change_primitive_received(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy)
|
||||
{
|
||||
struct isci_host *isci_host;
|
||||
|
||||
isci_host =
|
||||
(struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: port = %p, phy = %p\n", __func__, port, phy);
|
||||
isci_port_bc_change_received(isci_host, port, phy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* scic_cb_port_link_up() - This callback method informs the user that a phy
|
||||
* has become operational and is capable of communicating with the remote
|
||||
* end point.
|
||||
* @controller: This parameter represents the controller associated with the
|
||||
* phy.
|
||||
* @port: This parameter specifies the port object for which the user callback
|
||||
* is being invoked. There may be conditions where this parameter can be
|
||||
* SCI_INVALID_HANDLE
|
||||
* @phy: This parameter specifies the phy object for which the user callback is
|
||||
* being invoked.
|
||||
*
|
||||
* none.
|
||||
*/
|
||||
void scic_cb_port_link_up(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy)
|
||||
{
|
||||
struct isci_host *isci_host;
|
||||
|
||||
isci_host =
|
||||
(struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: phy = %p\n", __func__, phy);
|
||||
|
||||
isci_port_link_up(isci_host, port, phy);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_port_link_down() - This callback method informs the user that a phy
|
||||
* is no longer operational and is not capable of communicating with the
|
||||
* remote end point.
|
||||
* @controller: This parameter represents the controller associated with the
|
||||
* phy.
|
||||
* @port: This parameter specifies the port object for which the user callback
|
||||
* is being invoked. There may be conditions where this parameter can be
|
||||
* SCI_INVALID_HANDLE
|
||||
* @phy: This parameter specifies the phy object for which the user callback is
|
||||
* being invoked.
|
||||
*
|
||||
* none.
|
||||
*/
|
||||
void scic_cb_port_link_down(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy)
|
||||
{
|
||||
struct isci_host *isci_host;
|
||||
struct isci_phy *isci_phy;
|
||||
struct isci_port *isci_port;
|
||||
|
||||
isci_host =
|
||||
(struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
isci_phy =
|
||||
(struct isci_phy *)sci_object_get_association(phy);
|
||||
|
||||
isci_port =
|
||||
(struct isci_port *)sci_object_get_association(port);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_port = %p\n", __func__, isci_port);
|
||||
|
||||
isci_port_link_down(isci_host, isci_phy, isci_port);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_remote_device_start_complete() - This user callback method will
|
||||
* inform the user that a start operation has completed.
|
||||
* @controller: This parameter specifies the core controller associated with
|
||||
* the completion callback.
|
||||
* @remote_device: This parameter specifies the remote device associated with
|
||||
* the completion callback.
|
||||
* @completion_status: This parameter specifies the completion status for the
|
||||
* operation.
|
||||
*
|
||||
*/
|
||||
void scic_cb_remote_device_start_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
enum sci_status completion_status)
|
||||
{
|
||||
struct isci_host *isci_host;
|
||||
struct isci_remote_device *isci_device;
|
||||
|
||||
isci_host =
|
||||
(struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
isci_device =
|
||||
(struct isci_remote_device *)sci_object_get_association(
|
||||
remote_device
|
||||
);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_device = %p\n", __func__, isci_device);
|
||||
|
||||
isci_remote_device_start_complete(
|
||||
isci_host, isci_device, completion_status);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_remote_device_stop_complete() - This user callback method will
|
||||
* inform the user that a stop operation has completed.
|
||||
* @controller: This parameter specifies the core controller associated with
|
||||
* the completion callback.
|
||||
* @remote_device: This parameter specifies the remote device associated with
|
||||
* the completion callback.
|
||||
* @completion_status: This parameter specifies the completion status for the
|
||||
* operation.
|
||||
*
|
||||
*/
|
||||
void scic_cb_remote_device_stop_complete(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
enum sci_status completion_status)
|
||||
{
|
||||
struct isci_host *isci_host;
|
||||
struct isci_remote_device *isci_device;
|
||||
|
||||
isci_host =
|
||||
(struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
isci_device =
|
||||
(struct isci_remote_device *)sci_object_get_association(
|
||||
remote_device
|
||||
);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_device = %p\n", __func__, isci_device);
|
||||
|
||||
isci_remote_device_stop_complete(
|
||||
isci_host, isci_device, completion_status);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_remote_device_ready() - This user callback method will inform the
|
||||
* user that a remote device is now capable of handling IO requests.
|
||||
* @controller: This parameter specifies the core controller associated with
|
||||
* the completion callback.
|
||||
* @remote_device: This parameter specifies the remote device associated with
|
||||
* the callback.
|
||||
*
|
||||
*/
|
||||
void scic_cb_remote_device_ready(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device)
|
||||
{
|
||||
struct isci_remote_device *isci_device =
|
||||
(struct isci_remote_device *)
|
||||
sci_object_get_association(remote_device);
|
||||
|
||||
dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
|
||||
"%s: isci_device = %p\n", __func__, isci_device);
|
||||
|
||||
isci_remote_device_ready(isci_device);
|
||||
}
|
||||
|
||||
/**
|
||||
* scic_cb_remote_device_not_ready() - This user callback method will inform
|
||||
* the user that a remote device is no longer capable of handling IO
|
||||
* requests (until a ready callback is invoked).
|
||||
* @controller: This parameter specifies the core controller associated with
|
||||
* the completion callback.
|
||||
* @remote_device: This parameter specifies the remote device associated with
|
||||
* the callback.
|
||||
* @reason_code: This parameter specifies the reason for the remote device
|
||||
* going to a not ready state.
|
||||
*
|
||||
*/
|
||||
void scic_cb_remote_device_not_ready(
|
||||
struct scic_sds_controller *controller,
|
||||
struct scic_sds_remote_device *remote_device,
|
||||
u32 reason_code)
|
||||
{
|
||||
struct isci_remote_device *isci_device =
|
||||
(struct isci_remote_device *)
|
||||
sci_object_get_association(remote_device);
|
||||
|
||||
struct isci_host *isci_host;
|
||||
|
||||
isci_host =
|
||||
(struct isci_host *)sci_object_get_association(controller);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_device = %p, reason_code = %x\n",
|
||||
__func__, isci_device, reason_code);
|
||||
|
||||
isci_remote_device_not_ready(isci_device, reason_code);
|
||||
}
|
||||
|
||||
|
||||
19
drivers/scsi/isci/firmware/Makefile
Normal file
19
drivers/scsi/isci/firmware/Makefile
Normal file
@@ -0,0 +1,19 @@
|
||||
# Makefile for create_fw
|
||||
#
|
||||
CC=gcc
|
||||
CFLAGS=-c -Wall -O2 -g
|
||||
LDFLAGS=
|
||||
SOURCES=create_fw.c
|
||||
OBJECTS=$(SOURCES:.cpp=.o)
|
||||
EXECUTABLE=create_fw
|
||||
|
||||
all: $(SOURCES) $(EXECUTABLE)
|
||||
|
||||
$(EXECUTABLE): $(OBJECTS)
|
||||
$(CC) $(LDFLAGS) $(OBJECTS) -o $@
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $< -O $@
|
||||
|
||||
clean:
|
||||
rm -f *.o $(EXECUTABLE)
|
||||
36
drivers/scsi/isci/firmware/README
Normal file
36
drivers/scsi/isci/firmware/README
Normal file
@@ -0,0 +1,36 @@
|
||||
This defines the temporary binary blow we are to pass to the SCU
|
||||
driver to emulate the binary firmware that we will eventually be
|
||||
able to access via NVRAM on the SCU controller.
|
||||
|
||||
The current size of the binary blob is expected to be 149 bytes or larger
|
||||
|
||||
Header Types:
|
||||
0x1: Phy Masks
|
||||
0x2: Phy Gens
|
||||
0x3: SAS Addrs
|
||||
0xff: End of Data
|
||||
|
||||
ID string - u8[12]: "#SCU MAGIC#\0"
|
||||
Version - u8: 1
|
||||
SubVersion - u8: 0
|
||||
|
||||
Header Type - u8: 0x1
|
||||
Size - u8: 8
|
||||
Phy Mask - u32[8]
|
||||
|
||||
Header Type - u8: 0x2
|
||||
Size - u8: 8
|
||||
Phy Gen - u32[8]
|
||||
|
||||
Header Type - u8: 0x3
|
||||
Size - u8: 8
|
||||
Sas Addr - u64[8]
|
||||
|
||||
Header Type - u8: 0xf
|
||||
|
||||
|
||||
==============================================================================
|
||||
|
||||
Place isci_firmware.bin in /lib/firmware
|
||||
Be sure to recreate the initramfs image to include the firmware.
|
||||
|
||||
177
drivers/scsi/isci/firmware/create_fw.c
Normal file
177
drivers/scsi/isci/firmware/create_fw.c
Normal file
@@ -0,0 +1,177 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
char blob_name[] = "isci_firmware.bin";
|
||||
char id[] = "#SCU MAGIC#";
|
||||
unsigned char version = 1;
|
||||
unsigned char sub_version = 0;
|
||||
|
||||
|
||||
/*
|
||||
* For all defined arrays:
|
||||
* elements 0-3 are for SCU0, ports 0-3
|
||||
* elements 4-7 are for SCU1, ports 0-3
|
||||
*
|
||||
* valid configurations for one SCU are:
|
||||
* P0 P1 P2 P3
|
||||
* ----------------
|
||||
* 0xF,0x0,0x0,0x0 # 1 x4 port
|
||||
* 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1
|
||||
* # ports
|
||||
* 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2
|
||||
* # port
|
||||
* 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port
|
||||
* 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration)
|
||||
*
|
||||
* if there is a port/phy on which you do not wish to override the default
|
||||
* values, use the value assigned to UNINIT_PARAM (255).
|
||||
*/
|
||||
unsigned int phy_mask[] = { 1, 2, 4, 8, 1, 2, 4, 8 };
|
||||
|
||||
|
||||
/* denotes SAS generation. i.e. 3: SAS Gen 3 6G */
|
||||
unsigned int phy_gen[] = { 3, 3, 3, 3, 3, 3, 3, 3 };
|
||||
|
||||
/*
|
||||
* if there is a port/phy on which you do not wish to override the default
|
||||
* values, use the value "0000000000000000". SAS address of zero's is
|
||||
* considered invalid and will not be used.
|
||||
*/
|
||||
unsigned long long sas_addr[] = { 0x5FCFFFFFF0000000ULL,
|
||||
0x5FCFFFFFF1000000ULL,
|
||||
0x5FCFFFFFF2000000ULL,
|
||||
0x5FCFFFFFF3000000ULL,
|
||||
0x5FCFFFFFF4000000ULL,
|
||||
0x5FCFFFFFF5000000ULL,
|
||||
0x5FCFFFFFF6000000ULL,
|
||||
0x5FCFFFFFF7000000ULL };
|
||||
|
||||
int write_blob(void)
|
||||
{
|
||||
FILE *fd;
|
||||
int err;
|
||||
|
||||
fd = fopen(blob_name, "w+");
|
||||
if (!fd) {
|
||||
perror("Open file for write failed");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* write id */
|
||||
err = fwrite((void *)id, sizeof(char), strlen(id)+1, fd);
|
||||
if (err == 0) {
|
||||
perror("write id failed");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* write version */
|
||||
err = fwrite((void *)&version, sizeof(version), 1, fd);
|
||||
if (err == 0) {
|
||||
perror("write version failed");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* write sub version */
|
||||
err = fwrite((void *)&sub_version, sizeof(sub_version), 1, fd);
|
||||
if (err == 0) {
|
||||
perror("write subversion failed");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* write phy mask header */
|
||||
err = fputc(0x1, fd);
|
||||
if (err == EOF) {
|
||||
perror("write phy mask header failed");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* write size */
|
||||
err = fputc(8, fd);
|
||||
if (err == EOF) {
|
||||
perror("write phy mask size failed");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* write phy masks */
|
||||
err = fwrite((void *)phy_mask, 1, sizeof(phy_mask), fd);
|
||||
if (err == 0) {
|
||||
perror("write phy_mask failed");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* write phy gen header */
|
||||
err = fputc(0x2, fd);
|
||||
if (err == EOF) {
|
||||
perror("write phy gen header failed");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* write size */
|
||||
err = fputc(8, fd);
|
||||
if (err == EOF) {
|
||||
perror("write phy gen size failed");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* write phy_gen */
|
||||
err = fwrite((void *)phy_gen,
|
||||
1,
|
||||
sizeof(phy_gen),
|
||||
fd);
|
||||
if (err == 0) {
|
||||
perror("write phy_gen failed");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* write phy gen header */
|
||||
err = fputc(0x3, fd);
|
||||
if (err == EOF) {
|
||||
perror("write sas addr header failed");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* write size */
|
||||
err = fputc(8, fd);
|
||||
if (err == EOF) {
|
||||
perror("write sas addr size failed");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* write sas_addr */
|
||||
err = fwrite((void *)sas_addr,
|
||||
1,
|
||||
sizeof(sas_addr),
|
||||
fd);
|
||||
if (err == 0) {
|
||||
perror("write sas_addr failed");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* write end header */
|
||||
err = fputc(0xff, fd);
|
||||
if (err == EOF) {
|
||||
perror("write end header failed");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = write_blob();
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
781
drivers/scsi/isci/host.c
Normal file
781
drivers/scsi/isci/host.c
Normal file
@@ -0,0 +1,781 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "isci.h"
|
||||
#include "scic_io_request.h"
|
||||
#include "scic_remote_device.h"
|
||||
#include "scic_port.h"
|
||||
|
||||
#include "port.h"
|
||||
#include "request.h"
|
||||
#include "host.h"
|
||||
|
||||
/**
|
||||
* isci_isr() - This function is the interrupt service routine for the
|
||||
* controller. It schedules the tasklet and returns.
|
||||
* @vec: This parameter specifies the interrupt vector.
|
||||
* @data: This parameter specifies the ISCI host object.
|
||||
*
|
||||
* IRQ_HANDLED if out interrupt otherwise, IRQ_NONE
|
||||
*/
|
||||
irqreturn_t isci_isr(int vec, void *data)
|
||||
{
|
||||
struct isci_host *isci_host
|
||||
= (struct isci_host *)data;
|
||||
struct scic_controller_handler_methods *handlers
|
||||
= &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR];
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
if (isci_host_get_state(isci_host) != isci_starting
|
||||
&& handlers->interrupt_handler) {
|
||||
|
||||
if (handlers->interrupt_handler(isci_host->core_controller)) {
|
||||
if (isci_host_get_state(isci_host) != isci_stopped) {
|
||||
tasklet_schedule(
|
||||
&isci_host->completion_tasklet);
|
||||
} else
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: controller stopped\n",
|
||||
__func__);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
} else
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"%s: get_handler_methods failed, "
|
||||
"isci_host->status = 0x%x\n",
|
||||
__func__,
|
||||
isci_host_get_state(isci_host));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
irqreturn_t isci_legacy_isr(int vec, void *data)
|
||||
{
|
||||
struct pci_dev *pdev = data;
|
||||
struct isci_host *isci_host;
|
||||
struct scic_controller_handler_methods *handlers;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
/*
|
||||
* Since this is a legacy interrupt, either or both
|
||||
* controllers could have triggered it. Thus, we have to call
|
||||
* the legacy interrupt handler for all controllers on the
|
||||
* PCI function.
|
||||
*/
|
||||
for_each_isci_host(isci_host, pdev) {
|
||||
handlers = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR];
|
||||
|
||||
if (isci_host_get_state(isci_host) != isci_starting
|
||||
&& handlers->interrupt_handler) {
|
||||
|
||||
if (handlers->interrupt_handler(isci_host->core_controller)) {
|
||||
if (isci_host_get_state(isci_host) != isci_stopped) {
|
||||
tasklet_schedule(
|
||||
&isci_host->completion_tasklet);
|
||||
} else
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: controller stopped\n",
|
||||
__func__);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
} else
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"%s: get_handler_methods failed, "
|
||||
"isci_host->status = 0x%x\n",
|
||||
__func__,
|
||||
isci_host_get_state(isci_host));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* isci_host_start_complete() - This function is called by the core library,
|
||||
* through the ISCI Module, to indicate controller start status.
|
||||
* @isci_host: This parameter specifies the ISCI host object
|
||||
* @completion_status: This parameter specifies the completion status from the
|
||||
* core library.
|
||||
*
|
||||
*/
|
||||
void isci_host_start_complete(
|
||||
struct isci_host *isci_host,
|
||||
enum sci_status completion_status)
|
||||
{
|
||||
if (completion_status == SCI_SUCCESS) {
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: completion_status: SCI_SUCCESS\n", __func__);
|
||||
isci_host_change_state(isci_host, isci_ready);
|
||||
complete_all(&isci_host->start_complete);
|
||||
} else
|
||||
dev_err(&isci_host->pdev->dev,
|
||||
"controller start failed with "
|
||||
"completion_status = 0x%x;",
|
||||
completion_status);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* isci_host_scan_finished() - This function is one of the SCSI Host Template
|
||||
* functions. The SCSI midlayer calls this function during a target scan,
|
||||
* approx. once every 10 millisecs.
|
||||
* @shost: This parameter specifies the SCSI host being scanned
|
||||
* @time: This parameter specifies the number of ticks since the scan started.
|
||||
*
|
||||
* scan status, zero indicates the SCSI midlayer should continue to poll,
|
||||
* otherwise assume controller is ready.
|
||||
*/
|
||||
int isci_host_scan_finished(
|
||||
struct Scsi_Host *shost,
|
||||
unsigned long time)
|
||||
{
|
||||
struct isci_host *isci_host
|
||||
= isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost));
|
||||
|
||||
struct scic_controller_handler_methods *handlers
|
||||
= &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR];
|
||||
|
||||
if (handlers->interrupt_handler == NULL) {
|
||||
dev_err(&isci_host->pdev->dev,
|
||||
"%s: scic_controller_get_handler_methods failed\n",
|
||||
__func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* check interrupt_handler's status and call completion_handler if true,
|
||||
* link_up events should be coming from the scu core lib, as phy's come
|
||||
* online. for each link_up from the core, call
|
||||
* get_received_identify_address_frame, copy the frame into the
|
||||
* sas_phy object and call libsas notify_port_event(PORTE_BYTES_DMAED).
|
||||
* continue to return zero from thee scan_finished routine until
|
||||
* the scic_cb_controller_start_complete() call comes from the core.
|
||||
**/
|
||||
if (handlers->interrupt_handler(isci_host->core_controller))
|
||||
handlers->completion_handler(isci_host->core_controller);
|
||||
|
||||
if (isci_starting == isci_host_get_state(isci_host)
|
||||
&& time < (HZ * 10)) {
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_host->status = %d, time = %ld\n",
|
||||
__func__, isci_host_get_state(isci_host), time);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_host->status = %d, time = %ld\n",
|
||||
__func__, isci_host_get_state(isci_host), time);
|
||||
|
||||
scic_controller_enable_interrupts(isci_host->core_controller);
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* isci_host_scan_start() - This function is one of the SCSI Host Template
|
||||
* function, called by the SCSI mid layer berfore a target scan begins. The
|
||||
* core library controller start routine is called from here.
|
||||
* @shost: This parameter specifies the SCSI host to be scanned
|
||||
*
|
||||
*/
|
||||
void isci_host_scan_start(struct Scsi_Host *shost)
|
||||
{
|
||||
struct isci_host *isci_host;
|
||||
|
||||
isci_host = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost));
|
||||
isci_host_change_state(isci_host, isci_starting);
|
||||
|
||||
scic_controller_disable_interrupts(isci_host->core_controller);
|
||||
init_completion(&isci_host->start_complete);
|
||||
scic_controller_start(
|
||||
isci_host->core_controller,
|
||||
scic_controller_get_suggested_start_timeout(
|
||||
isci_host->core_controller)
|
||||
);
|
||||
}
|
||||
|
||||
void isci_host_stop_complete(
|
||||
struct isci_host *isci_host,
|
||||
enum sci_status completion_status)
|
||||
{
|
||||
isci_host_change_state(isci_host, isci_stopped);
|
||||
scic_controller_disable_interrupts(
|
||||
isci_host->core_controller
|
||||
);
|
||||
complete(&isci_host->stop_complete);
|
||||
}
|
||||
|
||||
static struct coherent_memory_info *isci_host_alloc_mdl_struct(
|
||||
struct isci_host *isci_host,
|
||||
u32 size)
|
||||
{
|
||||
struct coherent_memory_info *mdl_struct;
|
||||
void *uncached_address = NULL;
|
||||
|
||||
|
||||
mdl_struct = devm_kzalloc(&isci_host->pdev->dev,
|
||||
sizeof(*mdl_struct),
|
||||
GFP_KERNEL);
|
||||
if (!mdl_struct)
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&mdl_struct->node);
|
||||
|
||||
uncached_address = dmam_alloc_coherent(&isci_host->pdev->dev,
|
||||
size,
|
||||
&mdl_struct->dma_handle,
|
||||
GFP_KERNEL);
|
||||
if (!uncached_address)
|
||||
return NULL;
|
||||
|
||||
/* memset the whole memory area. */
|
||||
memset((char *)uncached_address, 0, size);
|
||||
mdl_struct->vaddr = uncached_address;
|
||||
mdl_struct->size = (size_t)size;
|
||||
|
||||
return mdl_struct;
|
||||
}
|
||||
|
||||
static void isci_host_build_mde(
|
||||
struct sci_physical_memory_descriptor *mde_struct,
|
||||
struct coherent_memory_info *mdl_struct)
|
||||
{
|
||||
unsigned long address = 0;
|
||||
dma_addr_t dma_addr = 0;
|
||||
|
||||
address = (unsigned long)mdl_struct->vaddr;
|
||||
dma_addr = mdl_struct->dma_handle;
|
||||
|
||||
/* to satisfy the alignment. */
|
||||
if ((address % mde_struct->constant_memory_alignment) != 0) {
|
||||
int align_offset
|
||||
= (mde_struct->constant_memory_alignment
|
||||
- (address % mde_struct->constant_memory_alignment));
|
||||
address += align_offset;
|
||||
dma_addr += align_offset;
|
||||
}
|
||||
|
||||
mde_struct->virtual_address = (void *)address;
|
||||
mde_struct->physical_address = dma_addr;
|
||||
mdl_struct->mde = mde_struct;
|
||||
}
|
||||
|
||||
static int isci_host_mdl_allocate_coherent(
|
||||
struct isci_host *isci_host)
|
||||
{
|
||||
struct sci_physical_memory_descriptor *current_mde;
|
||||
struct coherent_memory_info *mdl_struct;
|
||||
u32 size = 0;
|
||||
|
||||
struct sci_base_memory_descriptor_list *mdl_handle
|
||||
= sci_controller_get_memory_descriptor_list_handle(
|
||||
isci_host->core_controller);
|
||||
|
||||
sci_mdl_first_entry(mdl_handle);
|
||||
|
||||
current_mde = sci_mdl_get_current_entry(mdl_handle);
|
||||
|
||||
while (current_mde != NULL) {
|
||||
|
||||
size = (current_mde->constant_memory_size
|
||||
+ current_mde->constant_memory_alignment);
|
||||
|
||||
mdl_struct = isci_host_alloc_mdl_struct(isci_host, size);
|
||||
if (!mdl_struct)
|
||||
return -ENOMEM;
|
||||
|
||||
list_add_tail(&mdl_struct->node, &isci_host->mdl_struct_list);
|
||||
|
||||
isci_host_build_mde(current_mde, mdl_struct);
|
||||
|
||||
sci_mdl_next_entry(mdl_handle);
|
||||
current_mde = sci_mdl_get_current_entry(mdl_handle);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* isci_host_completion_routine() - This function is the delayed service
|
||||
* routine that calls the sci core library's completion handler. It's
|
||||
* scheduled as a tasklet from the interrupt service routine when interrupts
|
||||
* in use, or set as the timeout function in polled mode.
|
||||
* @data: This parameter specifies the ISCI host object
|
||||
*
|
||||
*/
|
||||
static void isci_host_completion_routine(unsigned long data)
|
||||
{
|
||||
struct isci_host *isci_host = (struct isci_host *)data;
|
||||
struct scic_controller_handler_methods *handlers
|
||||
= &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR];
|
||||
struct list_head completed_request_list;
|
||||
struct list_head aborted_request_list;
|
||||
struct list_head *current_position;
|
||||
struct list_head *next_position;
|
||||
struct isci_request *request;
|
||||
struct isci_request *next_request;
|
||||
struct sas_task *task;
|
||||
|
||||
INIT_LIST_HEAD(&completed_request_list);
|
||||
INIT_LIST_HEAD(&aborted_request_list);
|
||||
|
||||
spin_lock_irq(&isci_host->scic_lock);
|
||||
|
||||
if (handlers->completion_handler) {
|
||||
handlers->completion_handler(
|
||||
isci_host->core_controller
|
||||
);
|
||||
}
|
||||
/* Take the lists of completed I/Os from the host. */
|
||||
list_splice_init(&isci_host->requests_to_complete,
|
||||
&completed_request_list);
|
||||
|
||||
list_splice_init(&isci_host->requests_to_abort,
|
||||
&aborted_request_list);
|
||||
|
||||
spin_unlock_irq(&isci_host->scic_lock);
|
||||
|
||||
/* Process any completions in the lists. */
|
||||
list_for_each_safe(current_position, next_position,
|
||||
&completed_request_list) {
|
||||
|
||||
request = list_entry(current_position, struct isci_request,
|
||||
completed_node);
|
||||
task = isci_request_access_task(request);
|
||||
|
||||
/* Normal notification (task_done) */
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: Normal - request/task = %p/%p\n",
|
||||
__func__,
|
||||
request,
|
||||
task);
|
||||
|
||||
task->task_done(task);
|
||||
task->lldd_task = NULL;
|
||||
|
||||
/* Free the request object. */
|
||||
isci_request_free(isci_host, request);
|
||||
}
|
||||
list_for_each_entry_safe(request, next_request, &aborted_request_list,
|
||||
completed_node) {
|
||||
|
||||
task = isci_request_access_task(request);
|
||||
|
||||
/* Use sas_task_abort */
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"%s: Error - request/task = %p/%p\n",
|
||||
__func__,
|
||||
request,
|
||||
task);
|
||||
|
||||
/* Put the task into the abort path. */
|
||||
sas_task_abort(task);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void isci_host_deinit(
|
||||
struct isci_host *isci_host)
|
||||
{
|
||||
int i;
|
||||
|
||||
isci_host_change_state(isci_host, isci_stopping);
|
||||
for (i = 0; i < SCI_MAX_PORTS; i++) {
|
||||
struct isci_port *port = &isci_host->isci_ports[i];
|
||||
struct isci_remote_device *device, *tmpdev;
|
||||
list_for_each_entry_safe(device, tmpdev,
|
||||
&port->remote_dev_list, node) {
|
||||
isci_remote_device_change_state(device, isci_stopping);
|
||||
isci_remote_device_stop(device);
|
||||
}
|
||||
}
|
||||
|
||||
/* stop the comtroller and wait for completion. */
|
||||
init_completion(&isci_host->stop_complete);
|
||||
scic_controller_stop(
|
||||
isci_host->core_controller,
|
||||
SCIC_CONTROLLER_STOP_TIMEOUT
|
||||
);
|
||||
wait_for_completion(&isci_host->stop_complete);
|
||||
/* next, reset the controller. */
|
||||
scic_controller_reset(isci_host->core_controller);
|
||||
}
|
||||
|
||||
static int isci_verify_firmware(const struct firmware *fw,
|
||||
struct isci_firmware *isci_fw)
|
||||
{
|
||||
const u8 *tmp;
|
||||
|
||||
if (fw->size < ISCI_FIRMWARE_MIN_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
tmp = fw->data;
|
||||
|
||||
/* 12th char should be the NULL terminate for the ID string */
|
||||
if (tmp[11] != '\0')
|
||||
return -EINVAL;
|
||||
|
||||
if (strncmp("#SCU MAGIC#", tmp, 11) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
isci_fw->id = tmp;
|
||||
isci_fw->version = fw->data[ISCI_FW_VER_OFS];
|
||||
isci_fw->subversion = fw->data[ISCI_FW_SUBVER_OFS];
|
||||
|
||||
tmp = fw->data + ISCI_FW_DATA_OFS;
|
||||
|
||||
while (*tmp != ISCI_FW_HDR_EOF) {
|
||||
switch (*tmp) {
|
||||
case ISCI_FW_HDR_PHYMASK:
|
||||
tmp++;
|
||||
isci_fw->phy_masks_size = *tmp;
|
||||
tmp++;
|
||||
isci_fw->phy_masks = (const u32 *)tmp;
|
||||
tmp += sizeof(u32) * isci_fw->phy_masks_size;
|
||||
break;
|
||||
|
||||
case ISCI_FW_HDR_PHYGEN:
|
||||
tmp++;
|
||||
isci_fw->phy_gens_size = *tmp;
|
||||
tmp++;
|
||||
isci_fw->phy_gens = (const u32 *)tmp;
|
||||
tmp += sizeof(u32) * isci_fw->phy_gens_size;
|
||||
break;
|
||||
|
||||
case ISCI_FW_HDR_SASADDR:
|
||||
tmp++;
|
||||
isci_fw->sas_addrs_size = *tmp;
|
||||
tmp++;
|
||||
isci_fw->sas_addrs = (const u64 *)tmp;
|
||||
tmp += sizeof(u64) * isci_fw->sas_addrs_size;
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_err("bad field in firmware binary blob\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
pr_info("isci firmware v%u.%u loaded.\n",
|
||||
isci_fw->version, isci_fw->subversion);
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
static void __iomem *scu_base(struct isci_host *isci_host)
|
||||
{
|
||||
struct pci_dev *pdev = isci_host->pdev;
|
||||
int id = isci_host->id;
|
||||
|
||||
return pcim_iomap_table(pdev)[SCI_SCU_BAR * 2] + SCI_SCU_BAR_SIZE * id;
|
||||
}
|
||||
|
||||
static void __iomem *smu_base(struct isci_host *isci_host)
|
||||
{
|
||||
struct pci_dev *pdev = isci_host->pdev;
|
||||
int id = isci_host->id;
|
||||
|
||||
return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id;
|
||||
}
|
||||
|
||||
#define SCI_MAX_TIMER_COUNT 25
|
||||
|
||||
int isci_host_init(struct isci_host *isci_host)
|
||||
{
|
||||
int err = 0;
|
||||
int index = 0;
|
||||
enum sci_status status;
|
||||
struct scic_sds_controller *controller;
|
||||
struct scic_sds_port *scic_port;
|
||||
struct scic_controller_handler_methods *handlers
|
||||
= &isci_host->scic_irq_handlers[0];
|
||||
union scic_oem_parameters scic_oem_params;
|
||||
union scic_user_parameters scic_user_params;
|
||||
const struct firmware *fw = NULL;
|
||||
struct isci_firmware *isci_fw = NULL;
|
||||
|
||||
INIT_LIST_HEAD(&isci_host->timer_list_struct.timers);
|
||||
isci_timer_list_construct(
|
||||
&isci_host->timer_list_struct,
|
||||
SCI_MAX_TIMER_COUNT
|
||||
);
|
||||
|
||||
controller = scic_controller_alloc(&isci_host->pdev->dev);
|
||||
|
||||
if (!controller) {
|
||||
err = -ENOMEM;
|
||||
dev_err(&isci_host->pdev->dev, "%s: failed (%d)\n", __func__, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
isci_host->core_controller = controller;
|
||||
spin_lock_init(&isci_host->state_lock);
|
||||
spin_lock_init(&isci_host->scic_lock);
|
||||
spin_lock_init(&isci_host->queue_lock);
|
||||
|
||||
isci_host_change_state(isci_host, isci_starting);
|
||||
isci_host->can_queue = ISCI_CAN_QUEUE_VAL;
|
||||
|
||||
status = scic_controller_construct(controller, scu_base(isci_host),
|
||||
smu_base(isci_host));
|
||||
|
||||
if (status != SCI_SUCCESS) {
|
||||
dev_err(&isci_host->pdev->dev,
|
||||
"%s: scic_controller_construct failed - status = %x\n",
|
||||
__func__,
|
||||
status);
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
isci_host->sas_ha.dev = &isci_host->pdev->dev;
|
||||
isci_host->sas_ha.lldd_ha = isci_host;
|
||||
|
||||
/*----------- SCIC controller Initialization Stuff ------------------
|
||||
* set association host adapter struct in core controller.
|
||||
*/
|
||||
sci_object_set_association(isci_host->core_controller,
|
||||
(void *)isci_host
|
||||
);
|
||||
|
||||
/* grab initial values stored in the controller object for OEM and USER
|
||||
* parameters */
|
||||
scic_oem_parameters_get(controller, &scic_oem_params);
|
||||
scic_user_parameters_get(controller, &scic_user_params);
|
||||
|
||||
isci_fw = devm_kzalloc(&isci_host->pdev->dev,
|
||||
sizeof(struct isci_firmware),
|
||||
GFP_KERNEL);
|
||||
if (!isci_fw) {
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"allocating firmware struct failed\n");
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"Default OEM configuration being used:"
|
||||
" 4 narrow ports, and default SAS Addresses\n");
|
||||
goto set_default_params;
|
||||
}
|
||||
|
||||
status = request_firmware(&fw, ISCI_FW_NAME, &isci_host->pdev->dev);
|
||||
if (status) {
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"Loading firmware failed, using default values\n");
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"Default OEM configuration being used:"
|
||||
" 4 narrow ports, and default SAS Addresses\n");
|
||||
goto set_default_params;
|
||||
}
|
||||
else {
|
||||
status = isci_verify_firmware(fw, isci_fw);
|
||||
if (status != SCI_SUCCESS) {
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"firmware verification failed\n");
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"Default OEM configuration being used:"
|
||||
" 4 narrow ports, and default SAS "
|
||||
"Addresses\n");
|
||||
goto set_default_params;
|
||||
}
|
||||
|
||||
/* grab any OEM and USER parameters specified at module load */
|
||||
status = isci_parse_oem_parameters(&scic_oem_params,
|
||||
isci_host->id, isci_fw);
|
||||
if (status != SCI_SUCCESS) {
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"parsing firmware oem parameters failed\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = isci_parse_user_parameters(&scic_user_params,
|
||||
isci_host->id, isci_fw);
|
||||
if (status != SCI_SUCCESS) {
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"%s: isci_parse_user_parameters"
|
||||
" failed\n", __func__);
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
set_default_params:
|
||||
|
||||
status = scic_oem_parameters_set(isci_host->core_controller,
|
||||
&scic_oem_params
|
||||
);
|
||||
|
||||
if (status != SCI_SUCCESS) {
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"%s: scic_oem_parameters_set failed\n",
|
||||
__func__);
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
status = scic_user_parameters_set(isci_host->core_controller,
|
||||
&scic_user_params
|
||||
);
|
||||
|
||||
if (status != SCI_SUCCESS) {
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"%s: scic_user_parameters_set failed\n",
|
||||
__func__);
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = scic_controller_initialize(isci_host->core_controller);
|
||||
if (status != SCI_SUCCESS) {
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"%s: scic_controller_initialize failed -"
|
||||
" status = 0x%x\n",
|
||||
__func__, status);
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* @todo: use both MSI-X interrupts, and don't do indirect
|
||||
* calls to the handlers just register direct calls
|
||||
*/
|
||||
if (isci_host->pdev->msix_enabled) {
|
||||
status = scic_controller_get_handler_methods(
|
||||
SCIC_MSIX_INTERRUPT_TYPE,
|
||||
SCI_MSIX_DOUBLE_VECTOR,
|
||||
handlers
|
||||
);
|
||||
} else {
|
||||
status = scic_controller_get_handler_methods(
|
||||
SCIC_LEGACY_LINE_INTERRUPT_TYPE,
|
||||
0,
|
||||
handlers
|
||||
);
|
||||
}
|
||||
|
||||
if (status != SCI_SUCCESS) {
|
||||
handlers->interrupt_handler = NULL;
|
||||
handlers->completion_handler = NULL;
|
||||
dev_err(&isci_host->pdev->dev,
|
||||
"%s: scic_controller_get_handler_methods failed\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
tasklet_init(&isci_host->completion_tasklet,
|
||||
isci_host_completion_routine,
|
||||
(unsigned long)isci_host
|
||||
);
|
||||
|
||||
INIT_LIST_HEAD(&(isci_host->mdl_struct_list));
|
||||
|
||||
INIT_LIST_HEAD(&isci_host->requests_to_complete);
|
||||
INIT_LIST_HEAD(&isci_host->requests_to_abort);
|
||||
|
||||
/* populate mdl with dma memory. scu_mdl_allocate_coherent() */
|
||||
err = isci_host_mdl_allocate_coherent(isci_host);
|
||||
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
/*
|
||||
* keep the pool alloc size around, will use it for a bounds checking
|
||||
* when trying to convert virtual addresses to physical addresses
|
||||
*/
|
||||
isci_host->dma_pool_alloc_size = sizeof(struct isci_request) +
|
||||
scic_io_request_get_object_size();
|
||||
isci_host->dma_pool = dmam_pool_create(DRV_NAME, &isci_host->pdev->dev,
|
||||
isci_host->dma_pool_alloc_size,
|
||||
SLAB_HWCACHE_ALIGN, 0);
|
||||
|
||||
if (!isci_host->dma_pool) {
|
||||
err = -ENOMEM;
|
||||
goto req_obj_err_out;
|
||||
}
|
||||
|
||||
for (index = 0; index < SCI_MAX_PORTS; index++) {
|
||||
isci_port_init(&isci_host->isci_ports[index],
|
||||
isci_host, index);
|
||||
}
|
||||
|
||||
for (index = 0; index < SCI_MAX_PHYS; index++)
|
||||
isci_phy_init(&isci_host->phys[index], isci_host, index);
|
||||
|
||||
/* Why are we doing this? Is this even necessary? */
|
||||
memcpy(&isci_host->sas_addr[0], &isci_host->phys[0].sas_addr[0],
|
||||
SAS_ADDR_SIZE);
|
||||
|
||||
/* Start the ports */
|
||||
for (index = 0; index < SCI_MAX_PORTS; index++) {
|
||||
|
||||
scic_controller_get_port_handle(controller, index, &scic_port);
|
||||
scic_port_start(scic_port);
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
||||
/* SPB_Debug: destroy request object cache */
|
||||
req_obj_err_out:
|
||||
/* SPB_Debug: destroy remote object cache */
|
||||
err_out:
|
||||
/* SPB_Debug: undo controller init, construct and alloc, remove from parent
|
||||
* controller list. */
|
||||
out:
|
||||
if (fw)
|
||||
release_firmware(fw);
|
||||
return err;
|
||||
}
|
||||
283
drivers/scsi/isci/host.h
Normal file
283
drivers/scsi/isci/host.h
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the isci_module initialization routines.
|
||||
*
|
||||
* host.h
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#if !defined(_SCI_HOST_H_)
|
||||
#define _SCI_HOST_H_
|
||||
|
||||
#include "phy.h"
|
||||
/*#include "task.h"*/
|
||||
#include "timers.h"
|
||||
#include "remote_device.h"
|
||||
#include "scic_user_callback.h"
|
||||
|
||||
#define DRV_NAME "isci"
|
||||
#define SCI_PCI_BAR_COUNT 2
|
||||
#define SCI_NUM_MSI_X_INT 2
|
||||
#define SCI_SMU_BAR 0
|
||||
#define SCI_SMU_BAR_SIZE (16*1024)
|
||||
#define SCI_SCU_BAR 1
|
||||
#define SCI_SCU_BAR_SIZE (4*1024*1024)
|
||||
#define SCI_IO_SPACE_BAR0 2
|
||||
#define SCI_IO_SPACE_BAR1 3
|
||||
#define SCI_MSIX_NORMAL_VECTOR 0
|
||||
#define SCI_MSIX_ERROR_VECTOR 1
|
||||
#define SCI_MSIX_SINGLE_VECTOR 1
|
||||
#define SCI_MSIX_DOUBLE_VECTOR 2
|
||||
#define ISCI_CAN_QUEUE_VAL 250 /* < SCI_MAX_IO_REQUESTS ? */
|
||||
#define SCIC_CONTROLLER_STOP_TIMEOUT 5000
|
||||
|
||||
struct coherent_memory_info {
|
||||
struct list_head node;
|
||||
dma_addr_t dma_handle;
|
||||
void *vaddr;
|
||||
size_t size;
|
||||
struct sci_physical_memory_descriptor *mde;
|
||||
};
|
||||
|
||||
struct isci_host {
|
||||
struct scic_sds_controller *core_controller;
|
||||
struct scic_controller_handler_methods scic_irq_handlers[SCI_NUM_MSI_X_INT];
|
||||
union scic_oem_parameters oem_parameters;
|
||||
|
||||
int id; /* unique within a given pci device */
|
||||
struct isci_timer_list timer_list_struct;
|
||||
void *core_ctrl_memory;
|
||||
struct dma_pool *dma_pool;
|
||||
unsigned int dma_pool_alloc_size;
|
||||
struct isci_phy phys[SCI_MAX_PHYS];
|
||||
|
||||
/* isci_ports and sas_ports are implicitly parallel to the
|
||||
* ports maintained by the core
|
||||
*/
|
||||
struct isci_port isci_ports[SCI_MAX_PORTS];
|
||||
struct asd_sas_port sas_ports[SCI_MAX_PORTS];
|
||||
struct sas_ha_struct sas_ha;
|
||||
|
||||
int can_queue;
|
||||
spinlock_t queue_lock;
|
||||
spinlock_t state_lock;
|
||||
|
||||
struct pci_dev *pdev;
|
||||
u8 sas_addr[SAS_ADDR_SIZE];
|
||||
|
||||
enum isci_status status;
|
||||
struct Scsi_Host *shost;
|
||||
struct tasklet_struct completion_tasklet;
|
||||
struct list_head mdl_struct_list;
|
||||
struct list_head requests_to_complete;
|
||||
struct list_head requests_to_abort;
|
||||
struct completion stop_complete;
|
||||
struct completion start_complete;
|
||||
spinlock_t scic_lock;
|
||||
struct isci_host *next;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct isci_pci_info - This class represents the pci function containing the
|
||||
* controllers. Depending on PCI SKU, there could be up to 2 controllers in
|
||||
* the PCI function.
|
||||
*/
|
||||
#define SCI_MAX_MSIX_INT (SCI_NUM_MSI_X_INT*SCI_MAX_CONTROLLERS)
|
||||
|
||||
struct isci_pci_info {
|
||||
struct msix_entry msix_entries[SCI_MAX_MSIX_INT];
|
||||
int core_lib_array_index;
|
||||
SCI_LIBRARY_HANDLE_T core_lib_handle;
|
||||
struct isci_host *hosts;
|
||||
};
|
||||
|
||||
static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev)
|
||||
{
|
||||
return pci_get_drvdata(pdev);
|
||||
}
|
||||
|
||||
#define for_each_isci_host(isci_host, pdev) \
|
||||
for (isci_host = to_pci_info(pdev)->hosts;\
|
||||
isci_host; isci_host = isci_host->next)
|
||||
|
||||
static inline
|
||||
enum isci_status isci_host_get_state(
|
||||
struct isci_host *isci_host)
|
||||
{
|
||||
return isci_host->status;
|
||||
}
|
||||
|
||||
|
||||
static inline void isci_host_change_state(
|
||||
struct isci_host *isci_host,
|
||||
enum isci_status status)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_host = %p, state = 0x%x",
|
||||
__func__,
|
||||
isci_host,
|
||||
status);
|
||||
spin_lock_irqsave(&isci_host->state_lock, flags);
|
||||
isci_host->status = status;
|
||||
spin_unlock_irqrestore(&isci_host->state_lock, flags);
|
||||
|
||||
}
|
||||
|
||||
static inline int isci_host_can_queue(
|
||||
struct isci_host *isci_host,
|
||||
int num)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&isci_host->queue_lock, flags);
|
||||
if ((isci_host->can_queue - num) < 0) {
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_host->can_queue = %d\n",
|
||||
__func__,
|
||||
isci_host->can_queue);
|
||||
ret = -SAS_QUEUE_FULL;
|
||||
|
||||
} else
|
||||
isci_host->can_queue -= num;
|
||||
|
||||
spin_unlock_irqrestore(&isci_host->queue_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void isci_host_can_dequeue(
|
||||
struct isci_host *isci_host,
|
||||
int num)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&isci_host->queue_lock, flags);
|
||||
isci_host->can_queue += num;
|
||||
spin_unlock_irqrestore(&isci_host->queue_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_host_from_sas_ha() - This accessor retrieves the isci_host object
|
||||
* reference from the Linux sas_ha_struct reference.
|
||||
* @ha_struct,: This parameter points to the Linux sas_ha_struct object
|
||||
*
|
||||
* A reference to the associated isci_host structure.
|
||||
*/
|
||||
#define isci_host_from_sas_ha(ha_struct) \
|
||||
((struct isci_host *)(ha_struct)->lldd_ha)
|
||||
|
||||
/**
|
||||
* isci_host_scan_finished() -
|
||||
*
|
||||
* This function is one of the SCSI Host Template functions. The SCSI midlayer
|
||||
* calls this function during a target scan, approx. once every 10 millisecs.
|
||||
*/
|
||||
int isci_host_scan_finished(
|
||||
struct Scsi_Host *,
|
||||
unsigned long);
|
||||
|
||||
|
||||
/**
|
||||
* isci_host_scan_start() -
|
||||
*
|
||||
* This function is one of the SCSI Host Template function, called by the SCSI
|
||||
* mid layer berfore a target scan begins. The core library controller start
|
||||
* routine is called from here.
|
||||
*/
|
||||
void isci_host_scan_start(
|
||||
struct Scsi_Host *);
|
||||
|
||||
/**
|
||||
* isci_host_start_complete() -
|
||||
*
|
||||
* This function is called by the core library, through the ISCI Module, to
|
||||
* indicate controller start status.
|
||||
*/
|
||||
void isci_host_start_complete(
|
||||
struct isci_host *,
|
||||
enum sci_status);
|
||||
|
||||
void isci_host_stop_complete(
|
||||
struct isci_host *isci_host,
|
||||
enum sci_status completion_status);
|
||||
|
||||
int isci_host_init(struct isci_host *);
|
||||
|
||||
void isci_host_init_controller_names(
|
||||
struct isci_host *isci_host,
|
||||
unsigned int controller_idx);
|
||||
|
||||
void isci_host_deinit(
|
||||
struct isci_host *);
|
||||
|
||||
void isci_host_port_link_up(
|
||||
struct isci_host *,
|
||||
struct scic_sds_port *,
|
||||
struct scic_sds_phy *);
|
||||
int isci_host_dev_found(struct domain_device *);
|
||||
|
||||
void isci_host_remote_device_start_complete(
|
||||
struct isci_host *,
|
||||
struct isci_remote_device *,
|
||||
enum sci_status);
|
||||
|
||||
#endif /* !defined(_SCI_HOST_H_) */
|
||||
613
drivers/scsi/isci/init.c
Normal file
613
drivers/scsi/isci/init.c
Normal file
@@ -0,0 +1,613 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/string.h>
|
||||
#include "isci.h"
|
||||
#include "task.h"
|
||||
#include "sci_controller_constants.h"
|
||||
#include "scic_remote_device.h"
|
||||
#include "sci_environment.h"
|
||||
|
||||
static struct scsi_transport_template *isci_transport_template;
|
||||
struct kmem_cache *isci_kmem_cache;
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = {
|
||||
{ PCI_VDEVICE(INTEL, 0x1D61),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D63),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D65),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D67),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D69),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D6B),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D60),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D62),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D64),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D66),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D68),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D6A),},
|
||||
{}
|
||||
};
|
||||
|
||||
static int __devinit isci_pci_probe(
|
||||
struct pci_dev *pdev,
|
||||
const struct pci_device_id *device_id_p);
|
||||
|
||||
static void __devexit isci_pci_remove(struct pci_dev *pdev);
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, isci_id_table);
|
||||
|
||||
static struct pci_driver isci_pci_driver = {
|
||||
.name = DRV_NAME,
|
||||
.id_table = isci_id_table,
|
||||
.probe = isci_pci_probe,
|
||||
.remove = __devexit_p(isci_pci_remove),
|
||||
};
|
||||
|
||||
/* linux isci specific settings */
|
||||
int loglevel = 3;
|
||||
module_param(loglevel, int, S_IRUGO | S_IWUSR);
|
||||
|
||||
#if defined(CONFIG_PBG_HBA_A0)
|
||||
int isci_si_rev = ISCI_SI_REVA0;
|
||||
#elif defined(CONFIG_PBG_HBA_A2)
|
||||
int isci_si_rev = ISCI_SI_REVA2;
|
||||
#else
|
||||
int isci_si_rev = ISCI_SI_REVB0;
|
||||
#endif
|
||||
module_param(isci_si_rev, int, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(isci_si_rev, "override default si rev (0: A0 1: A2 2: B0)");
|
||||
|
||||
static struct scsi_host_template isci_sht = {
|
||||
|
||||
.module = THIS_MODULE,
|
||||
.name = DRV_NAME,
|
||||
.queuecommand = sas_queuecommand,
|
||||
.target_alloc = sas_target_alloc,
|
||||
.slave_configure = sas_slave_configure,
|
||||
.slave_destroy = sas_slave_destroy,
|
||||
.scan_finished = isci_host_scan_finished,
|
||||
.scan_start = isci_host_scan_start,
|
||||
.change_queue_depth = sas_change_queue_depth,
|
||||
.change_queue_type = sas_change_queue_type,
|
||||
.bios_param = sas_bios_param,
|
||||
.can_queue = ISCI_CAN_QUEUE_VAL,
|
||||
.cmd_per_lun = 1,
|
||||
.this_id = -1,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.max_sectors = SCSI_DEFAULT_MAX_SECTORS,
|
||||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.eh_device_reset_handler = sas_eh_device_reset_handler,
|
||||
.eh_bus_reset_handler = isci_bus_reset_handler,
|
||||
.slave_alloc = sas_slave_alloc,
|
||||
.target_destroy = sas_target_destroy,
|
||||
.ioctl = sas_ioctl,
|
||||
};
|
||||
|
||||
static struct sas_domain_function_template isci_transport_ops = {
|
||||
|
||||
/* The class calls these to notify the LLDD of an event. */
|
||||
.lldd_port_formed = isci_port_formed,
|
||||
.lldd_port_deformed = isci_port_deformed,
|
||||
|
||||
/* The class calls these when a device is found or gone. */
|
||||
.lldd_dev_found = isci_remote_device_found,
|
||||
.lldd_dev_gone = isci_remote_device_gone,
|
||||
|
||||
.lldd_execute_task = isci_task_execute_task,
|
||||
/* Task Management Functions. Must be called from process context. */
|
||||
.lldd_abort_task = isci_task_abort_task,
|
||||
.lldd_abort_task_set = isci_task_abort_task_set,
|
||||
.lldd_clear_aca = isci_task_clear_aca,
|
||||
.lldd_clear_task_set = isci_task_clear_task_set,
|
||||
.lldd_I_T_nexus_reset = isci_task_I_T_nexus_reset,
|
||||
.lldd_lu_reset = isci_task_lu_reset,
|
||||
.lldd_query_task = isci_task_query_task,
|
||||
|
||||
/* Port and Adapter management */
|
||||
.lldd_clear_nexus_port = isci_task_clear_nexus_port,
|
||||
.lldd_clear_nexus_ha = isci_task_clear_nexus_ha,
|
||||
|
||||
/* Phy management */
|
||||
.lldd_control_phy = isci_phy_control,
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* P R O T E C T E D M E T H O D S
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* isci_register_sas_ha() - This method initializes various lldd
|
||||
* specific members of the sas_ha struct and calls the libsas
|
||||
* sas_register_ha() function.
|
||||
* @isci_host: This parameter specifies the lldd specific wrapper for the
|
||||
* libsas sas_ha struct.
|
||||
*
|
||||
* This method returns an error code indicating sucess or failure. The user
|
||||
* should check for possible memory allocation error return otherwise, a zero
|
||||
* indicates success.
|
||||
*/
|
||||
static int isci_register_sas_ha(struct isci_host *isci_host)
|
||||
{
|
||||
int i;
|
||||
struct sas_ha_struct *sas_ha = &(isci_host->sas_ha);
|
||||
struct asd_sas_phy **sas_phys;
|
||||
struct asd_sas_port **sas_ports;
|
||||
|
||||
sas_phys = devm_kzalloc(&isci_host->pdev->dev,
|
||||
SCI_MAX_PHYS * sizeof(void *),
|
||||
GFP_KERNEL);
|
||||
if (!sas_phys)
|
||||
return -ENOMEM;
|
||||
|
||||
sas_ports = devm_kzalloc(&isci_host->pdev->dev,
|
||||
SCI_MAX_PORTS * sizeof(void *),
|
||||
GFP_KERNEL);
|
||||
if (!sas_ports)
|
||||
return -ENOMEM;
|
||||
|
||||
/*----------------- Libsas Initialization Stuff----------------------
|
||||
* Set various fields in the sas_ha struct:
|
||||
*/
|
||||
|
||||
sas_ha->sas_ha_name = DRV_NAME;
|
||||
sas_ha->lldd_module = THIS_MODULE;
|
||||
sas_ha->sas_addr = &(isci_host->sas_addr[0]);
|
||||
|
||||
/* set the array of phy and port structs. */
|
||||
for (i = 0; i < SCI_MAX_PHYS; i++) {
|
||||
sas_phys[i] = &(isci_host->phys[i].sas_phy);
|
||||
sas_ports[i] = &(isci_host->sas_ports[i]);
|
||||
}
|
||||
|
||||
sas_ha->sas_phy = sas_phys;
|
||||
sas_ha->sas_port = sas_ports;
|
||||
sas_ha->num_phys = SCI_MAX_PHYS;
|
||||
|
||||
sas_ha->lldd_queue_size = ISCI_CAN_QUEUE_VAL;
|
||||
sas_ha->lldd_max_execute_num = 1;
|
||||
sas_ha->strict_wide_ports = 1;
|
||||
|
||||
sas_register_ha(sas_ha);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void isci_unregister_sas_ha(struct isci_host *isci_host)
|
||||
{
|
||||
if (!isci_host)
|
||||
return;
|
||||
|
||||
sas_unregister_ha(&(isci_host->sas_ha));
|
||||
|
||||
sas_remove_host(isci_host->shost);
|
||||
scsi_remove_host(isci_host->shost);
|
||||
scsi_host_put(isci_host->shost);
|
||||
}
|
||||
|
||||
static int __devinit isci_pci_init(struct pci_dev *pdev)
|
||||
{
|
||||
int err, bar_num, bar_mask;
|
||||
void __iomem * const *iomap;
|
||||
|
||||
err = pcim_enable_device(pdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed enable PCI device %s!\n",
|
||||
pci_name(pdev));
|
||||
return err;
|
||||
}
|
||||
|
||||
for (bar_num = 0; bar_num < SCI_PCI_BAR_COUNT; bar_num++)
|
||||
bar_mask |= 1 << (bar_num * 2);
|
||||
|
||||
err = pcim_iomap_regions(pdev, bar_mask, DRV_NAME);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
iomap = pcim_iomap_table(pdev);
|
||||
if (!iomap)
|
||||
return -ENOMEM;
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
|
||||
if (err) {
|
||||
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
|
||||
if (err) {
|
||||
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct isci_host *isci_host_by_id(struct pci_dev *pdev, int id)
|
||||
{
|
||||
struct isci_host *h;
|
||||
|
||||
for_each_isci_host(h, pdev)
|
||||
if (h->id == id)
|
||||
return h;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int num_controllers(struct pci_dev *pdev)
|
||||
{
|
||||
/* bar size alone can tell us if we are running with a dual controller
|
||||
* part, no need to trust revision ids that might be under broken firmware
|
||||
* control
|
||||
*/
|
||||
resource_size_t scu_bar_size = pci_resource_len(pdev, SCI_SCU_BAR*2);
|
||||
resource_size_t smu_bar_size = pci_resource_len(pdev, SCI_SMU_BAR*2);
|
||||
|
||||
if (scu_bar_size >= SCI_SCU_BAR_SIZE*SCI_MAX_CONTROLLERS &&
|
||||
smu_bar_size >= SCI_SMU_BAR_SIZE*SCI_MAX_CONTROLLERS)
|
||||
return SCI_MAX_CONTROLLERS;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int isci_setup_interrupts(struct pci_dev *pdev)
|
||||
{
|
||||
int err, i, num_msix;
|
||||
struct isci_pci_info *pci_info = to_pci_info(pdev);
|
||||
|
||||
/*
|
||||
* Determine the number of vectors associated with this
|
||||
* PCI function.
|
||||
*/
|
||||
num_msix = num_controllers(pdev) * SCI_NUM_MSI_X_INT;
|
||||
|
||||
for (i = 0; i < num_msix; i++)
|
||||
pci_info->msix_entries[i].entry = i;
|
||||
|
||||
err = pci_enable_msix(pdev, pci_info->msix_entries, num_msix);
|
||||
if (err)
|
||||
goto intx;
|
||||
|
||||
for (i = 0; i < num_msix; i++) {
|
||||
int id = i / SCI_NUM_MSI_X_INT;
|
||||
struct msix_entry *msix = &pci_info->msix_entries[i];
|
||||
struct isci_host *isci_host = isci_host_by_id(pdev, id);
|
||||
|
||||
BUG_ON(!isci_host);
|
||||
|
||||
/* @todo: need to handle error case. */
|
||||
err = devm_request_irq(&pdev->dev, msix->vector, isci_isr, 0,
|
||||
DRV_NAME"-msix", isci_host);
|
||||
if (!err)
|
||||
continue;
|
||||
|
||||
dev_info(&pdev->dev, "msix setup failed falling back to intx\n");
|
||||
while (i--) {
|
||||
id = i / SCI_NUM_MSI_X_INT;
|
||||
isci_host = isci_host_by_id(pdev, id);
|
||||
msix = &pci_info->msix_entries[i];
|
||||
devm_free_irq(&pdev->dev, msix->vector, isci_host);
|
||||
}
|
||||
pci_disable_msix(pdev);
|
||||
goto intx;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
intx:
|
||||
err = devm_request_irq(&pdev->dev, pdev->irq, isci_legacy_isr,
|
||||
IRQF_SHARED, DRV_NAME"-intx", pdev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_parse_oem_parameters() - This method will take OEM parameters
|
||||
* from the module init parameters and copy them to oem_params. This will
|
||||
* only copy values that are not set to the module parameter default values
|
||||
* @oem_parameters: This parameter specifies the controller default OEM
|
||||
* parameters. It is expected that this has been initialized to the default
|
||||
* parameters for the controller
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params,
|
||||
int scu_index,
|
||||
struct isci_firmware *fw)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* check for valid inputs */
|
||||
if (!(scu_index >= 0
|
||||
&& scu_index < SCI_MAX_CONTROLLERS
|
||||
&& oem_params != NULL)) {
|
||||
return SCI_FAILURE;
|
||||
}
|
||||
|
||||
for (i = 0; i < SCI_MAX_PHYS; i++) {
|
||||
int array_idx = i + (SCI_MAX_PHYS * scu_index);
|
||||
u64 sas_addr = fw->sas_addrs[array_idx];
|
||||
|
||||
if (sas_addr != 0) {
|
||||
oem_params->sds1.phys[i].sas_address.low =
|
||||
(u32)(sas_addr & 0xffffffff);
|
||||
oem_params->sds1.phys[i].sas_address.high =
|
||||
(u32)((sas_addr >> 32) & 0xffffffff);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < SCI_MAX_PORTS; i++) {
|
||||
int array_idx = i + (SCI_MAX_PORTS * scu_index);
|
||||
u32 pmask = fw->phy_masks[array_idx];
|
||||
|
||||
oem_params->sds1.ports[i].phy_mask = pmask;
|
||||
}
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_parse_user_parameters() - This method will take user parameters
|
||||
* from the module init parameters and copy them to user_params. This will
|
||||
* only copy values that are not set to the module parameter default values
|
||||
* @user_parameters: This parameter specifies the controller default user
|
||||
* parameters. It is expected that this has been initialized to the default
|
||||
* parameters for the controller
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_status isci_parse_user_parameters(
|
||||
union scic_user_parameters *user_params,
|
||||
int scu_index,
|
||||
struct isci_firmware *fw)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!(scu_index >= 0
|
||||
&& scu_index < SCI_MAX_CONTROLLERS
|
||||
&& user_params != NULL)) {
|
||||
return SCI_FAILURE;
|
||||
}
|
||||
|
||||
for (i = 0; i < SCI_MAX_PORTS; i++) {
|
||||
int array_idx = i + (SCI_MAX_PORTS * scu_index);
|
||||
u32 gen = fw->phy_gens[array_idx];
|
||||
|
||||
user_params->sds1.phys[i].max_speed_generation = gen;
|
||||
|
||||
}
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
|
||||
{
|
||||
struct isci_host *isci_host;
|
||||
struct Scsi_Host *shost;
|
||||
int err;
|
||||
|
||||
isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL);
|
||||
if (!isci_host)
|
||||
return NULL;
|
||||
|
||||
isci_host->pdev = pdev;
|
||||
isci_host->id = id;
|
||||
|
||||
shost = scsi_host_alloc(&isci_sht, sizeof(void *));
|
||||
if (!shost)
|
||||
return NULL;
|
||||
isci_host->shost = shost;
|
||||
|
||||
err = isci_host_init(isci_host);
|
||||
if (err)
|
||||
goto err_shost;
|
||||
|
||||
SHOST_TO_SAS_HA(shost) = &isci_host->sas_ha;
|
||||
isci_host->sas_ha.core.shost = shost;
|
||||
shost->transportt = isci_transport_template;
|
||||
|
||||
shost->max_id = ~0;
|
||||
shost->max_lun = ~0;
|
||||
shost->max_cmd_len = MAX_COMMAND_SIZE;
|
||||
|
||||
err = scsi_add_host(shost, &pdev->dev);
|
||||
if (err)
|
||||
goto err_shost;
|
||||
|
||||
err = isci_register_sas_ha(isci_host);
|
||||
if (err)
|
||||
goto err_shost_remove;
|
||||
|
||||
return isci_host;
|
||||
|
||||
err_shost_remove:
|
||||
scsi_remove_host(shost);
|
||||
err_shost:
|
||||
scsi_host_put(shost);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void check_si_rev(struct pci_dev *pdev)
|
||||
{
|
||||
if (num_controllers(pdev) > 1)
|
||||
isci_si_rev = ISCI_SI_REVB0;
|
||||
else {
|
||||
switch (pdev->revision) {
|
||||
case 0:
|
||||
case 1:
|
||||
/* if the id is ambiguous don't update isci_si_rev */
|
||||
break;
|
||||
case 3:
|
||||
isci_si_rev = ISCI_SI_REVA2;
|
||||
break;
|
||||
default:
|
||||
case 4:
|
||||
isci_si_rev = ISCI_SI_REVB0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "driver configured for %s silicon (rev: %d)\n",
|
||||
isci_si_rev == ISCI_SI_REVA0 ? "A0" :
|
||||
isci_si_rev == ISCI_SI_REVA2 ? "A2" : "B0", pdev->revision);
|
||||
|
||||
}
|
||||
|
||||
static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
struct isci_pci_info *pci_info;
|
||||
int err, i;
|
||||
struct isci_host *isci_host;
|
||||
|
||||
check_si_rev(pdev);
|
||||
|
||||
pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL);
|
||||
if (!pci_info)
|
||||
return -ENOMEM;
|
||||
pci_set_drvdata(pdev, pci_info);
|
||||
|
||||
err = isci_pci_init(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < num_controllers(pdev); i++) {
|
||||
struct isci_host *h = isci_host_alloc(pdev, i);
|
||||
|
||||
if (!h) {
|
||||
err = -ENOMEM;
|
||||
goto err_host_alloc;
|
||||
}
|
||||
|
||||
h->next = pci_info->hosts;
|
||||
pci_info->hosts = h;
|
||||
}
|
||||
|
||||
err = isci_setup_interrupts(pdev);
|
||||
if (err)
|
||||
goto err_host_alloc;
|
||||
|
||||
for_each_isci_host(isci_host, pdev)
|
||||
scsi_scan_host(isci_host->shost);
|
||||
|
||||
return 0;
|
||||
|
||||
err_host_alloc:
|
||||
for_each_isci_host(isci_host, pdev)
|
||||
isci_unregister_sas_ha(isci_host);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __devexit isci_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct isci_host *isci_host;
|
||||
|
||||
for_each_isci_host(isci_host, pdev) {
|
||||
isci_unregister_sas_ha(isci_host);
|
||||
isci_host_deinit(isci_host);
|
||||
scic_controller_disable_interrupts(isci_host->core_controller);
|
||||
}
|
||||
}
|
||||
|
||||
static __init int isci_init(void)
|
||||
{
|
||||
int err = -ENOMEM;
|
||||
|
||||
pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME);
|
||||
|
||||
isci_kmem_cache = kmem_cache_create(DRV_NAME,
|
||||
sizeof(struct isci_remote_device) +
|
||||
scic_remote_device_get_object_size(),
|
||||
0, 0, NULL);
|
||||
if (!isci_kmem_cache)
|
||||
return err;
|
||||
|
||||
isci_transport_template = sas_domain_attach_transport(&isci_transport_ops);
|
||||
if (!isci_transport_template)
|
||||
goto err_kmem;
|
||||
|
||||
err = pci_register_driver(&isci_pci_driver);
|
||||
if (err)
|
||||
goto err_sas;
|
||||
|
||||
return 0;
|
||||
|
||||
err_sas:
|
||||
sas_release_transport(isci_transport_template);
|
||||
err_kmem:
|
||||
kmem_cache_destroy(isci_kmem_cache);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static __exit void isci_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&isci_pci_driver);
|
||||
sas_release_transport(isci_transport_template);
|
||||
kmem_cache_destroy(isci_kmem_cache);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_FIRMWARE(ISCI_FW_NAME);
|
||||
module_init(isci_init);
|
||||
module_exit(isci_exit);
|
||||
138
drivers/scsi/isci/isci.h
Normal file
138
drivers/scsi/isci/isci.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the isci_module object definition.
|
||||
*
|
||||
* isci.h
|
||||
*/
|
||||
|
||||
#if !defined(_SCI_MODULE_H_)
|
||||
#define _SCI_MODULE_H_
|
||||
|
||||
/**
|
||||
* This file contains the SCI low level driver interface to the SCI and Libsas
|
||||
* Libraries.
|
||||
*
|
||||
* isci.h
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/bug.h>
|
||||
#include <scsi/libsas.h>
|
||||
#include <scsi/scsi.h>
|
||||
|
||||
#include "sci_types.h"
|
||||
#include "sci_base_controller.h"
|
||||
#include "scic_controller.h"
|
||||
#include "host.h"
|
||||
#include "timers.h"
|
||||
#include "sci_status.h"
|
||||
|
||||
extern int loglevel;
|
||||
extern struct kmem_cache *isci_kmem_cache;
|
||||
|
||||
#define ISCI_FW_NAME "isci/isci_firmware.bin"
|
||||
|
||||
#define ISCI_FIRMWARE_MIN_SIZE 149
|
||||
|
||||
#define ISCI_FW_IDSIZE 12
|
||||
#define ISCI_FW_VER_OFS ISCI_FW_IDSIZE
|
||||
#define ISCI_FW_SUBVER_OFS ISCI_FW_VER_OFS + 1
|
||||
#define ISCI_FW_DATA_OFS ISCI_FW_SUBVER_OFS + 1
|
||||
|
||||
#define ISCI_FW_HDR_PHYMASK 0x1
|
||||
#define ISCI_FW_HDR_PHYGEN 0x2
|
||||
#define ISCI_FW_HDR_SASADDR 0x3
|
||||
#define ISCI_FW_HDR_EOF 0xff
|
||||
|
||||
struct isci_firmware {
|
||||
const u8 *id;
|
||||
u8 version;
|
||||
u8 subversion;
|
||||
const u32 *phy_masks;
|
||||
u8 phy_masks_size;
|
||||
const u32 *phy_gens;
|
||||
u8 phy_gens_size;
|
||||
const u64 *sas_addrs;
|
||||
u8 sas_addrs_size;
|
||||
};
|
||||
|
||||
irqreturn_t isci_isr(int vec, void *data);
|
||||
irqreturn_t isci_legacy_isr(int vec, void *data);
|
||||
|
||||
enum sci_status isci_parse_oem_parameters(
|
||||
union scic_oem_parameters *oem_params,
|
||||
int scu_index,
|
||||
struct isci_firmware *fw);
|
||||
|
||||
enum sci_status isci_parse_user_parameters(
|
||||
union scic_user_parameters *user_params,
|
||||
int scu_index,
|
||||
struct isci_firmware *fw);
|
||||
|
||||
#ifdef ISCI_SLAVE_ALLOC
|
||||
extern int ISCI_SLAVE_ALLOC(struct scsi_device *scsi_dev);
|
||||
#endif /* ISCI_SLAVE_ALLOC */
|
||||
|
||||
#ifdef ISCI_SLAVE_DESTROY
|
||||
extern void ISCI_SLAVE_DESTROY(struct scsi_device *scsi_dev);
|
||||
#endif /* ISCI_SLAVE_DESTROY */
|
||||
#endif /* !defined(_SCI_MODULE_H_) */
|
||||
179
drivers/scsi/isci/phy.c
Normal file
179
drivers/scsi/isci/phy.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "isci.h"
|
||||
#include "phy.h"
|
||||
#include "scic_port.h"
|
||||
#include "scic_config_parameters.h"
|
||||
|
||||
|
||||
/**
|
||||
* isci_phy_init() - This function is called by the probe function to
|
||||
* initialize the phy objects. This func assumes that the isci_port objects
|
||||
* associated with the SCU have been initialized.
|
||||
* @isci_phy: This parameter specifies the isci_phy object to initialize
|
||||
* @isci_host: This parameter specifies the parent SCU host object for this
|
||||
* isci_phy
|
||||
* @index: This parameter specifies which SCU phy associates with this
|
||||
* isci_phy. Generally, SCU phy 0 relates isci_phy 0, etc.
|
||||
*
|
||||
*/
|
||||
void isci_phy_init(
|
||||
struct isci_phy *phy,
|
||||
struct isci_host *isci_host,
|
||||
int index)
|
||||
{
|
||||
struct scic_sds_controller *controller = isci_host->core_controller;
|
||||
struct scic_sds_phy *scic_phy;
|
||||
union scic_oem_parameters oem_parameters;
|
||||
enum sci_status status = SCI_SUCCESS;
|
||||
|
||||
/*--------------- SCU_Phy Initialization Stuff -----------------------*/
|
||||
|
||||
status = scic_controller_get_phy_handle(controller, index, &scic_phy);
|
||||
if (status == SCI_SUCCESS) {
|
||||
sci_object_set_association(scic_phy, (void *)phy);
|
||||
phy->sci_phy_handle = scic_phy;
|
||||
} else
|
||||
dev_err(&isci_host->pdev->dev,
|
||||
"failed scic_controller_get_phy_handle\n");
|
||||
|
||||
scic_oem_parameters_get(controller, &oem_parameters);
|
||||
|
||||
phy->sas_addr[0] = oem_parameters.sds1.phys[index].sas_address.low
|
||||
& 0xFF;
|
||||
phy->sas_addr[1] = (oem_parameters.sds1.phys[index].sas_address.low
|
||||
>> 8) & 0xFF;
|
||||
phy->sas_addr[2] = (oem_parameters.sds1.phys[index].sas_address.low
|
||||
>> 16) & 0xFF;
|
||||
phy->sas_addr[3] = (oem_parameters.sds1.phys[index].sas_address.low
|
||||
>> 24) & 0xFF;
|
||||
phy->sas_addr[4] = oem_parameters.sds1.phys[index].sas_address.high
|
||||
& 0xFF;
|
||||
phy->sas_addr[5] = (oem_parameters.sds1.phys[index].sas_address.high
|
||||
>> 8) & 0xFF;
|
||||
phy->sas_addr[6] = (oem_parameters.sds1.phys[index].sas_address.high
|
||||
>> 16) & 0xFF;
|
||||
phy->sas_addr[7] = (oem_parameters.sds1.phys[index].sas_address.high
|
||||
>> 24) & 0xFF;
|
||||
|
||||
phy->isci_port = NULL;
|
||||
phy->sas_phy.enabled = 0;
|
||||
phy->sas_phy.id = index;
|
||||
phy->sas_phy.sas_addr = &phy->sas_addr[0];
|
||||
phy->sas_phy.frame_rcvd = (u8 *)&phy->frame_rcvd;
|
||||
phy->sas_phy.ha = &isci_host->sas_ha;
|
||||
phy->sas_phy.lldd_phy = phy;
|
||||
phy->sas_phy.enabled = 1;
|
||||
phy->sas_phy.class = SAS;
|
||||
phy->sas_phy.iproto = SAS_PROTOCOL_ALL;
|
||||
phy->sas_phy.tproto = 0;
|
||||
phy->sas_phy.type = PHY_TYPE_PHYSICAL;
|
||||
phy->sas_phy.role = PHY_ROLE_INITIATOR;
|
||||
phy->sas_phy.oob_mode = OOB_NOT_CONNECTED;
|
||||
phy->sas_phy.linkrate = SAS_LINK_RATE_UNKNOWN;
|
||||
memset((u8 *)&phy->frame_rcvd, 0, sizeof(phy->frame_rcvd));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* isci_phy_control() - This function is one of the SAS Domain Template
|
||||
* functions. This is a phy management function.
|
||||
* @phy: This parameter specifies the sphy being controlled.
|
||||
* @func: This parameter specifies the phy control function being invoked.
|
||||
* @buf: This parameter is specific to the phy function being invoked.
|
||||
*
|
||||
* status, zero indicates success.
|
||||
*/
|
||||
int isci_phy_control(
|
||||
struct asd_sas_phy *phy,
|
||||
enum phy_func func,
|
||||
void *buf)
|
||||
{
|
||||
int ret = TMF_RESP_FUNC_COMPLETE;
|
||||
struct isci_phy *isci_phy_ptr = (struct isci_phy *)phy->lldd_phy;
|
||||
struct isci_port *isci_port_ptr = NULL;
|
||||
|
||||
if (isci_phy_ptr != NULL)
|
||||
isci_port_ptr = isci_phy_ptr->isci_port;
|
||||
|
||||
if ((isci_phy_ptr == NULL) || (isci_port_ptr == NULL)) {
|
||||
pr_err("%s: asd_sas_phy %p: lldd_phy %p or "
|
||||
"isci_port %p == NULL!\n",
|
||||
__func__, phy, isci_phy_ptr, isci_port_ptr);
|
||||
return TMF_RESP_FUNC_FAILED;
|
||||
}
|
||||
|
||||
pr_debug("%s: phy %p; func %d; buf %p; isci phy %p, port %p\n",
|
||||
__func__, phy, func, buf, isci_phy_ptr, isci_port_ptr);
|
||||
|
||||
switch (func) {
|
||||
case PHY_FUNC_HARD_RESET:
|
||||
case PHY_FUNC_LINK_RESET:
|
||||
|
||||
/* Perform the port reset. */
|
||||
ret = isci_port_perform_hard_reset(isci_port_ptr, isci_phy_ptr);
|
||||
|
||||
break;
|
||||
|
||||
case PHY_FUNC_DISABLE:
|
||||
default:
|
||||
pr_debug("%s: phy %p; func %d NOT IMPLEMENTED!\n",
|
||||
__func__, phy, func);
|
||||
ret = TMF_RESP_FUNC_FAILED;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
104
drivers/scsi/isci/phy.h
Normal file
104
drivers/scsi/isci/phy.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(_ISCI_PHY_H_)
|
||||
#define _ISCI_PHY_H_
|
||||
|
||||
#include "port.h"
|
||||
#include "host.h"
|
||||
#include <scsi/libsas.h>
|
||||
|
||||
|
||||
/**
|
||||
* struct isci_phy - This class implements the ISCI specific representation of
|
||||
* the phy object.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
struct isci_phy {
|
||||
|
||||
struct scic_sds_phy *sci_phy_handle;
|
||||
|
||||
struct asd_sas_phy sas_phy;
|
||||
struct sas_identify_frame *frame;
|
||||
struct isci_port *isci_port;
|
||||
u8 sas_addr[SAS_ADDR_SIZE];
|
||||
|
||||
union {
|
||||
|
||||
u8 aif[sizeof(struct sci_sas_identify_address_frame)];
|
||||
u8 fis[sizeof(struct sata_fis_reg_d2h)];
|
||||
|
||||
} frame_rcvd;
|
||||
};
|
||||
|
||||
#define to_isci_phy(p) \
|
||||
container_of(p, struct isci_phy, sas_phy);
|
||||
|
||||
struct isci_host;
|
||||
|
||||
void isci_phy_init(
|
||||
struct isci_phy *phy,
|
||||
struct isci_host *isci_host,
|
||||
int index);
|
||||
|
||||
int isci_phy_control(
|
||||
struct asd_sas_phy *phy,
|
||||
enum phy_func func,
|
||||
void *buf);
|
||||
|
||||
#endif /* !defined(_ISCI_PHY_H_) */
|
||||
484
drivers/scsi/isci/port.c
Normal file
484
drivers/scsi/isci/port.c
Normal file
@@ -0,0 +1,484 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the isci port implementation.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
#include "isci.h"
|
||||
#include "scic_io_request.h"
|
||||
#include "scic_remote_device.h"
|
||||
#include "scic_phy.h"
|
||||
#include "scic_sds_phy.h"
|
||||
#include "scic_port.h"
|
||||
#include "port.h"
|
||||
#include "request.h"
|
||||
|
||||
static void isci_port_change_state(
|
||||
struct isci_port *isci_port,
|
||||
enum isci_status status);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* isci_port_init() - This function initializes the given isci_port object.
|
||||
* @isci_port: This parameter specifies the port object to be initialized.
|
||||
* @isci_host: This parameter specifies parent controller object for the port.
|
||||
* @index: This parameter specifies which SCU port the isci_port associates
|
||||
* with. Generally, SCU port 0 relates to isci_port 0, etc.
|
||||
*
|
||||
*/
|
||||
void isci_port_init(
|
||||
struct isci_port *isci_port,
|
||||
struct isci_host *isci_host,
|
||||
int index)
|
||||
{
|
||||
struct scic_sds_port *scic_port;
|
||||
struct scic_sds_controller *controller = isci_host->core_controller;
|
||||
|
||||
INIT_LIST_HEAD(&isci_port->remote_dev_list);
|
||||
INIT_LIST_HEAD(&isci_port->domain_dev_list);
|
||||
spin_lock_init(&isci_port->remote_device_lock);
|
||||
spin_lock_init(&isci_port->state_lock);
|
||||
init_completion(&isci_port->start_complete);
|
||||
isci_port->isci_host = isci_host;
|
||||
isci_port_change_state(isci_port, isci_freed);
|
||||
|
||||
(void)scic_controller_get_port_handle(controller, index, &scic_port);
|
||||
sci_object_set_association(scic_port, isci_port);
|
||||
isci_port->sci_port_handle = scic_port;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* isci_port_get_state() - This function gets the status of the port object.
|
||||
* @isci_port: This parameter points to the isci_port object
|
||||
*
|
||||
* status of the object as a isci_status enum.
|
||||
*/
|
||||
enum isci_status isci_port_get_state(
|
||||
struct isci_port *isci_port)
|
||||
{
|
||||
return isci_port->status;
|
||||
}
|
||||
|
||||
static void isci_port_change_state(
|
||||
struct isci_port *isci_port,
|
||||
enum isci_status status)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(&isci_port->isci_host->pdev->dev,
|
||||
"%s: isci_port = %p, state = 0x%x\n",
|
||||
__func__, isci_port, status);
|
||||
|
||||
spin_lock_irqsave(&isci_port->state_lock, flags);
|
||||
isci_port->status = status;
|
||||
spin_unlock_irqrestore(&isci_port->state_lock, flags);
|
||||
}
|
||||
|
||||
void isci_port_bc_change_received(
|
||||
struct isci_host *isci_host,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy)
|
||||
{
|
||||
struct isci_phy *isci_phy =
|
||||
(struct isci_phy *)sci_object_get_association(phy);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_phy = %p, sas_phy = %p\n",
|
||||
__func__,
|
||||
isci_phy,
|
||||
&isci_phy->sas_phy);
|
||||
|
||||
isci_host->sas_ha.notify_port_event(
|
||||
&isci_phy->sas_phy,
|
||||
PORTE_BROADCAST_RCVD
|
||||
);
|
||||
|
||||
scic_port_enable_broadcast_change_notification(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_port_link_up() - This function is called by the sci core when a link
|
||||
* becomes active. the identify address frame is retrieved from the core and
|
||||
* a notify port event is sent to libsas.
|
||||
* @isci_host: This parameter specifies the isci host object.
|
||||
* @port: This parameter specifies the sci port with the active link.
|
||||
* @phy: This parameter specifies the sci phy with the active link.
|
||||
*
|
||||
*/
|
||||
void isci_port_link_up(
|
||||
struct isci_host *isci_host,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct scic_port_properties properties;
|
||||
struct isci_phy *isci_phy
|
||||
= (struct isci_phy *)sci_object_get_association(phy);
|
||||
struct isci_port *isci_port
|
||||
= (struct isci_port *)sci_object_get_association(port);
|
||||
enum sci_status call_status;
|
||||
unsigned long success = true;
|
||||
|
||||
BUG_ON(isci_phy->isci_port != NULL);
|
||||
isci_phy->isci_port = isci_port;
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_port = %p\n",
|
||||
__func__, isci_port);
|
||||
|
||||
spin_lock_irqsave(&isci_phy->sas_phy.frame_rcvd_lock, flags);
|
||||
|
||||
isci_port_change_state(isci_phy->isci_port, isci_starting);
|
||||
|
||||
scic_port_get_properties(port, &properties);
|
||||
|
||||
if (properties.remote.protocols.u.bits.stp_target) {
|
||||
|
||||
struct scic_sata_phy_properties sata_phy_properties;
|
||||
|
||||
isci_phy->sas_phy.oob_mode = SATA_OOB_MODE;
|
||||
|
||||
/* Get a copy of the signature fis for libsas */
|
||||
call_status = scic_sata_phy_get_properties(phy,
|
||||
&sata_phy_properties);
|
||||
|
||||
/*
|
||||
* XXX I am concerned about this "assert". shouldn't we
|
||||
* handle the return appropriately?
|
||||
*/
|
||||
BUG_ON(call_status != SCI_SUCCESS);
|
||||
|
||||
memcpy(isci_phy->frame_rcvd.fis,
|
||||
&sata_phy_properties.signature_fis,
|
||||
sizeof(struct sata_fis_reg_d2h));
|
||||
|
||||
isci_phy->sas_phy.frame_rcvd_size = sizeof(struct sata_fis_reg_d2h);
|
||||
|
||||
/*
|
||||
* For direct-attached SATA devices, the SCI core will
|
||||
* automagically assign a SAS address to the end device
|
||||
* for the purpose of creating a port. This SAS address
|
||||
* will not be the same as assigned to the PHY and needs
|
||||
* to be obtained from struct scic_port_properties properties.
|
||||
*/
|
||||
|
||||
BUG_ON(((size_t)SAS_ADDR_SIZE / 2)
|
||||
!= sizeof(properties.remote.sas_address.low));
|
||||
|
||||
memcpy(&isci_phy->sas_phy.attached_sas_addr[0],
|
||||
&properties.remote.sas_address.low,
|
||||
SAS_ADDR_SIZE / 2);
|
||||
|
||||
memcpy(&isci_phy->sas_phy.attached_sas_addr[4],
|
||||
&properties.remote.sas_address.high,
|
||||
SAS_ADDR_SIZE / 2);
|
||||
|
||||
} else if (properties.remote.protocols.u.bits.ssp_target ||
|
||||
properties.remote.protocols.u.bits.smp_target) {
|
||||
|
||||
struct scic_sas_phy_properties sas_phy_properties;
|
||||
|
||||
isci_phy->sas_phy.oob_mode = SAS_OOB_MODE;
|
||||
|
||||
/* Get a copy of the identify address frame for libsas */
|
||||
call_status = scic_sas_phy_get_properties(phy,
|
||||
&sas_phy_properties);
|
||||
|
||||
BUG_ON(call_status != SCI_SUCCESS);
|
||||
|
||||
memcpy(isci_phy->frame_rcvd.aif,
|
||||
&(sas_phy_properties.received_iaf),
|
||||
sizeof(struct sci_sas_identify_address_frame));
|
||||
|
||||
isci_phy->sas_phy.frame_rcvd_size
|
||||
= sizeof(struct sci_sas_identify_address_frame);
|
||||
|
||||
/* Copy the attached SAS address from the IAF */
|
||||
memcpy(isci_phy->sas_phy.attached_sas_addr,
|
||||
((struct sas_identify_frame *)
|
||||
(&isci_phy->frame_rcvd.aif))->sas_addr,
|
||||
SAS_ADDR_SIZE);
|
||||
|
||||
} else {
|
||||
dev_err(&isci_host->pdev->dev, "%s: unkown target\n", __func__);
|
||||
success = false;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&isci_phy->sas_phy.frame_rcvd_lock, flags);
|
||||
|
||||
/* Notify libsas that we have an address frame, if indeed
|
||||
* we've found an SSP, SMP, or STP target */
|
||||
if (success)
|
||||
isci_host->sas_ha.notify_port_event(&isci_phy->sas_phy,
|
||||
PORTE_BYTES_DMAED);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* isci_port_link_down() - This function is called by the sci core when a link
|
||||
* becomes inactive.
|
||||
* @isci_host: This parameter specifies the isci host object.
|
||||
* @phy: This parameter specifies the isci phy with the active link.
|
||||
* @port: This parameter specifies the isci port with the active link.
|
||||
*
|
||||
*/
|
||||
void isci_port_link_down(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_phy *isci_phy,
|
||||
struct isci_port *isci_port)
|
||||
{
|
||||
struct isci_remote_device *isci_device;
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_port = %p\n", __func__, isci_port);
|
||||
|
||||
if (isci_port) {
|
||||
|
||||
/* check to see if this is the last phy on this port. */
|
||||
if (isci_phy->sas_phy.port
|
||||
&& isci_phy->sas_phy.port->num_phys == 1) {
|
||||
|
||||
/* change the state for all devices on this port.
|
||||
* The next task sent to this device will be returned
|
||||
* as SAS_TASK_UNDELIVERED, and the scsi mid layer
|
||||
* will remove the target
|
||||
*/
|
||||
list_for_each_entry(isci_device,
|
||||
&isci_port->remote_dev_list,
|
||||
node) {
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_device = %p\n",
|
||||
__func__, isci_device);
|
||||
isci_remote_device_change_state(isci_device,
|
||||
isci_stopping);
|
||||
}
|
||||
}
|
||||
isci_port_change_state(isci_port, isci_stopping);
|
||||
}
|
||||
|
||||
/* Notify libsas of the borken link, this will trigger calls to our
|
||||
* isci_port_deformed and isci_dev_gone functions.
|
||||
*/
|
||||
sas_phy_disconnected(&isci_phy->sas_phy);
|
||||
isci_host->sas_ha.notify_phy_event(&isci_phy->sas_phy,
|
||||
PHYE_LOSS_OF_SIGNAL);
|
||||
|
||||
isci_phy->isci_port = NULL;
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_port = %p - Done\n", __func__, isci_port);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* isci_port_deformed() - This function is called by libsas when a port becomes
|
||||
* inactive.
|
||||
* @phy: This parameter specifies the libsas phy with the inactive port.
|
||||
*
|
||||
*/
|
||||
void isci_port_deformed(
|
||||
struct asd_sas_phy *phy)
|
||||
{
|
||||
pr_debug("%s: sas_phy = %p\n", __func__, phy);
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_port_formed() - This function is called by libsas when a port becomes
|
||||
* active.
|
||||
* @phy: This parameter specifies the libsas phy with the active port.
|
||||
*
|
||||
*/
|
||||
void isci_port_formed(
|
||||
struct asd_sas_phy *phy)
|
||||
{
|
||||
pr_debug("%s: sas_phy = %p, sas_port = %p\n", __func__, phy, phy->port);
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_port_ready() - This function is called by the sci core when a link
|
||||
* becomes ready.
|
||||
* @isci_host: This parameter specifies the isci host object.
|
||||
* @port: This parameter specifies the sci port with the active link.
|
||||
*
|
||||
*/
|
||||
void isci_port_ready(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_port *isci_port)
|
||||
{
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_port = %p\n", __func__, isci_port);
|
||||
|
||||
complete_all(&isci_port->start_complete);
|
||||
isci_port_change_state(isci_port, isci_ready);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_port_not_ready() - This function is called by the sci core when a link
|
||||
* is not ready. All remote devices on this link will be removed if they are
|
||||
* in the stopping state.
|
||||
* @isci_host: This parameter specifies the isci host object.
|
||||
* @port: This parameter specifies the sci port with the active link.
|
||||
*
|
||||
*/
|
||||
void isci_port_not_ready(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_port *isci_port)
|
||||
{
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_port = %p\n", __func__, isci_port);
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_port_hard_reset_complete() - This function is called by the sci core
|
||||
* when the hard reset complete notification has been received.
|
||||
* @port: This parameter specifies the sci port with the active link.
|
||||
* @completion_status: This parameter specifies the core status for the reset
|
||||
* process.
|
||||
*
|
||||
*/
|
||||
void isci_port_hard_reset_complete(
|
||||
struct isci_port *isci_port,
|
||||
enum sci_status completion_status)
|
||||
{
|
||||
dev_dbg(&isci_port->isci_host->pdev->dev,
|
||||
"%s: isci_port = %p, completion_status=%x\n",
|
||||
__func__, isci_port, completion_status);
|
||||
|
||||
/* Save the status of the hard reset from the port. */
|
||||
isci_port->hard_reset_status = completion_status;
|
||||
|
||||
complete_all(&isci_port->hard_reset_complete);
|
||||
}
|
||||
/**
|
||||
* isci_port_perform_hard_reset() - This function is one of the SAS Domain
|
||||
* Template functions. This is a phy management function.
|
||||
* @isci_port:
|
||||
* @isci_phy:
|
||||
*
|
||||
* status, TMF_RESP_FUNC_COMPLETE indicates success.
|
||||
*/
|
||||
int isci_port_perform_hard_reset(
|
||||
struct isci_port *isci_port,
|
||||
struct isci_phy *isci_phy)
|
||||
{
|
||||
enum sci_status status;
|
||||
int ret = TMF_RESP_FUNC_COMPLETE;
|
||||
unsigned long flags;
|
||||
|
||||
|
||||
dev_dbg(&isci_port->isci_host->pdev->dev,
|
||||
"%s: isci_port = %p\n",
|
||||
__func__, isci_port);
|
||||
|
||||
BUG_ON(isci_port == NULL);
|
||||
|
||||
init_completion(&isci_port->hard_reset_complete);
|
||||
|
||||
spin_lock_irqsave(&isci_port->isci_host->scic_lock, flags);
|
||||
|
||||
#define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT
|
||||
status = scic_port_hard_reset(isci_port->sci_port_handle,
|
||||
ISCI_PORT_RESET_TIMEOUT);
|
||||
|
||||
spin_unlock_irqrestore(&isci_port->isci_host->scic_lock, flags);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
wait_for_completion(&isci_port->hard_reset_complete);
|
||||
|
||||
dev_dbg(&isci_port->isci_host->pdev->dev,
|
||||
"%s: isci_port = %p; hard reset completion\n",
|
||||
__func__, isci_port);
|
||||
|
||||
if (isci_port->hard_reset_status != SCI_SUCCESS)
|
||||
ret = TMF_RESP_FUNC_FAILED;
|
||||
} else {
|
||||
ret = TMF_RESP_FUNC_FAILED;
|
||||
|
||||
dev_err(&isci_port->isci_host->pdev->dev,
|
||||
"%s: isci_port = %p; scic_port_hard_reset call"
|
||||
" failed 0x%x\n",
|
||||
__func__, isci_port, status);
|
||||
|
||||
}
|
||||
|
||||
/* If the hard reset for the port has failed, consider this
|
||||
* the same as link failures on all phys in the port.
|
||||
*/
|
||||
if (ret != TMF_RESP_FUNC_COMPLETE) {
|
||||
BUG_ON(isci_port->isci_host == NULL);
|
||||
|
||||
dev_err(&isci_port->isci_host->pdev->dev,
|
||||
"%s: isci_port = %p; hard reset failed "
|
||||
"(0x%x) - sending link down to libsas for phy %p\n",
|
||||
__func__,
|
||||
isci_port,
|
||||
isci_port->hard_reset_status,
|
||||
isci_phy);
|
||||
|
||||
isci_port_link_down(isci_port->isci_host,
|
||||
isci_phy,
|
||||
isci_port);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
153
drivers/scsi/isci/port.h
Normal file
153
drivers/scsi/isci/port.h
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the isci_port object definition.
|
||||
*
|
||||
* port.h
|
||||
*/
|
||||
|
||||
#if !defined(_ISCI_PORT_H_)
|
||||
#define _ISCI_PORT_H_
|
||||
|
||||
struct isci_phy;
|
||||
struct isci_host;
|
||||
|
||||
|
||||
enum isci_status {
|
||||
isci_freed = 0x00,
|
||||
isci_starting = 0x01,
|
||||
isci_ready = 0x02,
|
||||
isci_ready_for_io = 0x03,
|
||||
isci_stopping = 0x04,
|
||||
isci_stopped = 0x05,
|
||||
isci_host_quiesce = 0x06
|
||||
};
|
||||
|
||||
/**
|
||||
* struct isci_port - This class represents the port object used to internally
|
||||
* represent libsas port objects. It also keeps a list of remote device
|
||||
* objects.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct isci_port {
|
||||
|
||||
struct scic_sds_port *sci_port_handle;
|
||||
|
||||
enum isci_status status;
|
||||
struct isci_host *isci_host;
|
||||
struct asd_sas_port sas_port;
|
||||
struct list_head remote_dev_list;
|
||||
spinlock_t remote_device_lock;
|
||||
spinlock_t state_lock;
|
||||
struct list_head domain_dev_list;
|
||||
struct completion start_complete;
|
||||
struct completion hard_reset_complete;
|
||||
enum sci_status hard_reset_status;
|
||||
};
|
||||
|
||||
#define to_isci_port(p) \
|
||||
container_of(p, struct isci_port, sas_port);
|
||||
|
||||
enum isci_status isci_port_get_state(
|
||||
struct isci_port *isci_port);
|
||||
|
||||
|
||||
|
||||
void isci_port_formed(
|
||||
struct asd_sas_phy *);
|
||||
|
||||
void isci_port_deformed(
|
||||
struct asd_sas_phy *);
|
||||
|
||||
void isci_port_bc_change_received(
|
||||
struct isci_host *isci_host,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy);
|
||||
|
||||
void isci_port_link_up(
|
||||
struct isci_host *isci_host,
|
||||
struct scic_sds_port *port,
|
||||
struct scic_sds_phy *phy);
|
||||
|
||||
void isci_port_link_down(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_phy *isci_phy,
|
||||
struct isci_port *port);
|
||||
|
||||
void isci_port_ready(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_port *isci_port);
|
||||
|
||||
void isci_port_not_ready(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_port *port);
|
||||
|
||||
void isci_port_init(
|
||||
struct isci_port *port,
|
||||
struct isci_host *host,
|
||||
int index);
|
||||
|
||||
void isci_port_hard_reset_complete(
|
||||
struct isci_port *isci_port,
|
||||
enum sci_status completion_status);
|
||||
|
||||
int isci_port_perform_hard_reset(
|
||||
struct isci_port *isci_port_ptr,
|
||||
struct isci_phy *isci_phy_ptr);
|
||||
|
||||
#endif /* !defined(_ISCI_PORT_H_) */
|
||||
|
||||
698
drivers/scsi/isci/remote_device.c
Normal file
698
drivers/scsi/isci/remote_device.c
Normal file
@@ -0,0 +1,698 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "isci.h"
|
||||
#include "scic_io_request.h"
|
||||
#include "scic_remote_device.h"
|
||||
#include "scic_phy.h"
|
||||
#include "scic_port.h"
|
||||
#include "port.h"
|
||||
#include "remote_device.h"
|
||||
#include "request.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* isci_remote_device_deconstruct() - This function frees an isci_remote_device.
|
||||
* @isci_host: This parameter specifies the isci host object.
|
||||
* @isci_device: This parameter specifies the remote device to be freed.
|
||||
*
|
||||
*/
|
||||
static void isci_remote_device_deconstruct(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_remote_device *isci_device)
|
||||
{
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_device = %p\n", __func__, isci_device);
|
||||
|
||||
/* There should not be any outstanding io's. All paths to
|
||||
* here should go through isci_remote_device_nuke_requests.
|
||||
* If we hit this condition, we will need a way to complete
|
||||
* io requests in process */
|
||||
while (!list_empty(&isci_device->reqs_in_process)) {
|
||||
|
||||
dev_err(&isci_host->pdev->dev,
|
||||
"%s: ** request list not empty! **\n", __func__);
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Remove all related references to this device and free
|
||||
* the cache object.
|
||||
*/
|
||||
scic_remote_device_destruct(isci_device->sci_device_handle);
|
||||
isci_device->domain_dev->lldd_dev = NULL;
|
||||
list_del(&isci_device->node);
|
||||
kmem_cache_free(isci_kmem_cache, isci_device);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* isci_remote_device_construct() - This function calls the scic remote device
|
||||
* construct and start functions, it waits on the remote device start
|
||||
* completion.
|
||||
* @port: This parameter specifies the isci port with the remote device.
|
||||
* @isci_device: This parameter specifies the isci remote device
|
||||
*
|
||||
* status from the scic calls, the caller to this function should clean up
|
||||
* resources as appropriate.
|
||||
*/
|
||||
static enum sci_status isci_remote_device_construct(
|
||||
struct isci_port *port,
|
||||
struct isci_remote_device *isci_device)
|
||||
{
|
||||
enum sci_status status = SCI_SUCCESS;
|
||||
|
||||
/* let the core do it's common constuction. */
|
||||
scic_remote_device_construct(port->sci_port_handle,
|
||||
isci_device->sci_device_handle);
|
||||
|
||||
/* let the core do it's device specific constuction. */
|
||||
if (isci_device->domain_dev->parent &&
|
||||
(isci_device->domain_dev->parent->dev_type == EDGE_DEV)) {
|
||||
int i;
|
||||
|
||||
/* struct smp_response_discover discover_response; */
|
||||
struct discover_resp discover_response;
|
||||
struct domain_device *parent =
|
||||
isci_device->domain_dev->parent;
|
||||
|
||||
struct expander_device *parent_ex = &parent->ex_dev;
|
||||
|
||||
for (i = 0; i < parent_ex->num_phys; i++) {
|
||||
|
||||
struct ex_phy *phy = &parent_ex->ex_phy[i];
|
||||
|
||||
if ((phy->phy_state == PHY_VACANT) ||
|
||||
(phy->phy_state == PHY_NOT_PRESENT))
|
||||
continue;
|
||||
|
||||
if (SAS_ADDR(phy->attached_sas_addr)
|
||||
== SAS_ADDR(isci_device->domain_dev->sas_addr)) {
|
||||
|
||||
discover_response.attached_dev_type
|
||||
= phy->attached_dev_type;
|
||||
discover_response.linkrate
|
||||
= phy->linkrate;
|
||||
discover_response.attached_sata_host
|
||||
= phy->attached_sata_host;
|
||||
discover_response.attached_sata_dev
|
||||
= phy->attached_sata_dev;
|
||||
discover_response.attached_sata_ps
|
||||
= phy->attached_sata_ps;
|
||||
discover_response.iproto
|
||||
= phy->attached_iproto >> 1;
|
||||
discover_response.tproto
|
||||
= phy->attached_tproto >> 1;
|
||||
memcpy(
|
||||
discover_response.attached_sas_addr,
|
||||
phy->attached_sas_addr,
|
||||
SAS_ADDR_SIZE
|
||||
);
|
||||
discover_response.attached_phy_id
|
||||
= phy->attached_phy_id;
|
||||
discover_response.change_count
|
||||
= phy->phy_change_count;
|
||||
discover_response.routing_attr
|
||||
= phy->routing_attr;
|
||||
discover_response.hmin_linkrate
|
||||
= phy->phy->minimum_linkrate_hw;
|
||||
discover_response.hmax_linkrate
|
||||
= phy->phy->maximum_linkrate_hw;
|
||||
discover_response.pmin_linkrate
|
||||
= phy->phy->minimum_linkrate;
|
||||
discover_response.pmax_linkrate
|
||||
= phy->phy->maximum_linkrate;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dev_dbg(&port->isci_host->pdev->dev,
|
||||
"%s: parent->dev_type = EDGE_DEV\n",
|
||||
__func__);
|
||||
|
||||
status = scic_remote_device_ea_construct(
|
||||
isci_device->sci_device_handle,
|
||||
(struct smp_response_discover *)&discover_response
|
||||
);
|
||||
|
||||
} else
|
||||
status = scic_remote_device_da_construct(
|
||||
isci_device->sci_device_handle
|
||||
);
|
||||
|
||||
|
||||
if (status != SCI_SUCCESS) {
|
||||
dev_dbg(&port->isci_host->pdev->dev,
|
||||
"%s: scic_remote_device_da_construct failed - "
|
||||
"isci_device = %p\n",
|
||||
__func__,
|
||||
isci_device);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
sci_object_set_association(
|
||||
isci_device->sci_device_handle,
|
||||
isci_device
|
||||
);
|
||||
|
||||
BUG_ON(port->isci_host == NULL);
|
||||
|
||||
/* start the device. */
|
||||
status = scic_remote_device_start(
|
||||
isci_device->sci_device_handle,
|
||||
ISCI_REMOTE_DEVICE_START_TIMEOUT
|
||||
);
|
||||
|
||||
if (status != SCI_SUCCESS) {
|
||||
dev_warn(&port->isci_host->pdev->dev,
|
||||
"%s: scic_remote_device_start failed\n",
|
||||
__func__);
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* isci_remote_device_nuke_requests() - This function terminates all requests
|
||||
* for a given remote device.
|
||||
* @isci_device: This parameter specifies the remote device
|
||||
*
|
||||
*/
|
||||
void isci_remote_device_nuke_requests(
|
||||
struct isci_remote_device *isci_device)
|
||||
{
|
||||
DECLARE_COMPLETION_ONSTACK(aborted_task_completion);
|
||||
struct isci_host *isci_host;
|
||||
|
||||
isci_host = isci_device->isci_port->isci_host;
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_device = %p\n", __func__, isci_device);
|
||||
|
||||
/* Cleanup all requests pending for this device. */
|
||||
isci_terminate_pending_requests(isci_host, isci_device, terminating);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_device = %p, done\n", __func__, isci_device);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This function builds the isci_remote_device when a libsas dev_found message
|
||||
* is received.
|
||||
* @isci_host: This parameter specifies the isci host object.
|
||||
* @port: This parameter specifies the isci_port conected to this device.
|
||||
*
|
||||
* pointer to new isci_remote_device.
|
||||
*/
|
||||
static struct isci_remote_device *
|
||||
isci_remote_device_alloc(struct isci_host *isci_host, struct isci_port *port)
|
||||
{
|
||||
struct isci_remote_device *isci_device;
|
||||
struct scic_sds_remote_device *sci_dev;
|
||||
|
||||
isci_device = kmem_cache_zalloc(isci_kmem_cache, GFP_KERNEL);
|
||||
|
||||
if (!isci_device) {
|
||||
dev_warn(&isci_host->pdev->dev, "%s: failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sci_dev = (struct scic_sds_remote_device *) &isci_device[1];
|
||||
isci_device->sci_device_handle = sci_dev;
|
||||
INIT_LIST_HEAD(&isci_device->reqs_in_process);
|
||||
INIT_LIST_HEAD(&isci_device->node);
|
||||
isci_device->host_quiesce = false;
|
||||
|
||||
spin_lock_init(&isci_device->state_lock);
|
||||
spin_lock_init(&isci_device->host_quiesce_lock);
|
||||
isci_remote_device_change_state(isci_device, isci_freed);
|
||||
|
||||
return isci_device;
|
||||
|
||||
}
|
||||
/**
|
||||
* isci_device_set_host_quiesce_lock_state() - This function sets the host I/O
|
||||
* quiesce lock state for the remote_device object.
|
||||
* @isci_device,: This parameter points to the isci_remote_device object
|
||||
* @isci_device: This parameter specifies the new quiesce state.
|
||||
*
|
||||
*/
|
||||
void isci_device_set_host_quiesce_lock_state(
|
||||
struct isci_remote_device *isci_device,
|
||||
bool lock_state)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
|
||||
"%s: isci_device=%p, lock_state=%d\n",
|
||||
__func__, isci_device, lock_state);
|
||||
|
||||
spin_lock_irqsave(&isci_device->host_quiesce_lock, flags);
|
||||
isci_device->host_quiesce = lock_state;
|
||||
spin_unlock_irqrestore(&isci_device->host_quiesce_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_remote_device_ready() - This function is called by the scic when the
|
||||
* remote device is ready. We mark the isci device as ready and signal the
|
||||
* waiting proccess.
|
||||
* @isci_host: This parameter specifies the isci host object.
|
||||
* @isci_device: This parameter specifies the remote device
|
||||
*
|
||||
*/
|
||||
void isci_remote_device_ready(struct isci_remote_device *isci_device)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
|
||||
"%s: isci_device = %p\n", __func__, isci_device);
|
||||
|
||||
/* device ready is actually a "ready for io" state. */
|
||||
if ((isci_starting == isci_remote_device_get_state(isci_device)) ||
|
||||
(isci_ready == isci_remote_device_get_state(isci_device))) {
|
||||
spin_lock_irqsave(&isci_device->isci_port->remote_device_lock,
|
||||
flags);
|
||||
isci_remote_device_change_state(isci_device, isci_ready_for_io);
|
||||
if (isci_device->completion)
|
||||
complete(isci_device->completion);
|
||||
spin_unlock_irqrestore(
|
||||
&isci_device->isci_port->remote_device_lock,
|
||||
flags);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_remote_device_not_ready() - This function is called by the scic when
|
||||
* the remote device is not ready. We mark the isci device as ready (not
|
||||
* "ready_for_io") and signal the waiting proccess.
|
||||
* @isci_host: This parameter specifies the isci host object.
|
||||
* @isci_device: This parameter specifies the remote device
|
||||
*
|
||||
*/
|
||||
void isci_remote_device_not_ready(
|
||||
struct isci_remote_device *isci_device,
|
||||
u32 reason_code)
|
||||
{
|
||||
dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
|
||||
"%s: isci_device = %p\n", __func__, isci_device);
|
||||
|
||||
if (reason_code == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED)
|
||||
isci_remote_device_change_state(isci_device, isci_stopping);
|
||||
else
|
||||
/* device ready is actually a "not ready for io" state. */
|
||||
isci_remote_device_change_state(isci_device, isci_ready);
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_remote_device_stop_complete() - This function is called by the scic
|
||||
* when the remote device stop has completed. We mark the isci device as not
|
||||
* ready and remove the isci remote device.
|
||||
* @isci_host: This parameter specifies the isci host object.
|
||||
* @isci_device: This parameter specifies the remote device.
|
||||
* @status: This parameter specifies status of the completion.
|
||||
*
|
||||
*/
|
||||
void isci_remote_device_stop_complete(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_remote_device *isci_device,
|
||||
enum sci_status status)
|
||||
{
|
||||
struct completion *completion = isci_device->completion;
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: complete isci_device = %p, status = 0x%x\n",
|
||||
__func__,
|
||||
isci_device,
|
||||
status);
|
||||
|
||||
isci_remote_device_change_state(isci_device, isci_stopped);
|
||||
|
||||
/* after stop, we can tear down resources. */
|
||||
isci_remote_device_deconstruct(isci_host, isci_device);
|
||||
|
||||
/* notify interested parties. */
|
||||
if (completion)
|
||||
complete(completion);
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_remote_device_start_complete() - This function is called by the scic
|
||||
* when the remote device start has completed
|
||||
* @isci_host: This parameter specifies the isci host object.
|
||||
* @isci_device: This parameter specifies the remote device.
|
||||
* @status: This parameter specifies status of the completion.
|
||||
*
|
||||
*/
|
||||
void isci_remote_device_start_complete(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_remote_device *isci_device,
|
||||
enum sci_status status)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* isci_remote_device_stop() - This function is called internally to stop the
|
||||
* remote device.
|
||||
* @isci_host: This parameter specifies the isci host object.
|
||||
* @isci_device: This parameter specifies the remote device.
|
||||
*
|
||||
* The status of the scic request to stop.
|
||||
*/
|
||||
enum sci_status isci_remote_device_stop(
|
||||
struct isci_remote_device *isci_device)
|
||||
{
|
||||
enum sci_status status;
|
||||
unsigned long flags;
|
||||
|
||||
DECLARE_COMPLETION_ONSTACK(completion);
|
||||
|
||||
dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
|
||||
"%s: isci_device = %p\n", __func__, isci_device);
|
||||
|
||||
isci_remote_device_change_state(isci_device, isci_stopping);
|
||||
|
||||
/* We need comfirmation that stop completed. */
|
||||
isci_device->completion = &completion;
|
||||
|
||||
BUG_ON(isci_device->isci_port == NULL);
|
||||
BUG_ON(isci_device->isci_port->isci_host == NULL);
|
||||
|
||||
spin_lock_irqsave(&isci_device->isci_port->isci_host->scic_lock, flags);
|
||||
|
||||
status = scic_remote_device_stop(
|
||||
isci_device->sci_device_handle,
|
||||
50
|
||||
);
|
||||
|
||||
spin_unlock_irqrestore(&isci_device->isci_port->isci_host->scic_lock, flags);
|
||||
|
||||
/* Wait for the stop complete callback. */
|
||||
if (status == SCI_SUCCESS)
|
||||
wait_for_completion(&completion);
|
||||
|
||||
dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
|
||||
"%s: isci_device = %p - after completion wait\n",
|
||||
__func__, isci_device);
|
||||
|
||||
isci_device->completion = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_remote_device_gone() - This function is called by libsas when a domain
|
||||
* device is removed.
|
||||
* @domain_device: This parameter specifies the libsas domain device.
|
||||
*
|
||||
*/
|
||||
void isci_remote_device_gone(
|
||||
struct domain_device *domain_dev)
|
||||
{
|
||||
struct isci_remote_device *isci_device = isci_dev_from_domain_dev(
|
||||
domain_dev);
|
||||
|
||||
dev_err(&isci_device->isci_port->isci_host->pdev->dev,
|
||||
"%s: domain_device = %p, isci_device = %p, isci_port = %p\n",
|
||||
__func__, domain_dev, isci_device, isci_device->isci_port);
|
||||
|
||||
if (isci_device != NULL)
|
||||
isci_remote_device_stop(isci_device);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* isci_remote_device_found() - This function is called by libsas when a remote
|
||||
* device is discovered. A remote device object is created and started. the
|
||||
* function then sleeps until the sci core device started message is
|
||||
* received.
|
||||
* @domain_device: This parameter specifies the libsas domain device.
|
||||
*
|
||||
* status, zero indicates success.
|
||||
*/
|
||||
int isci_remote_device_found(struct domain_device *domain_dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct isci_host *isci_host;
|
||||
struct isci_port *isci_port;
|
||||
struct isci_phy *isci_phy;
|
||||
struct asd_sas_port *sas_port;
|
||||
struct asd_sas_phy *sas_phy;
|
||||
struct isci_remote_device *isci_device;
|
||||
enum sci_status status;
|
||||
DECLARE_COMPLETION_ONSTACK(completion);
|
||||
|
||||
isci_host = isci_host_from_sas_ha(domain_dev->port->ha);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: domain_device = %p\n", __func__, domain_dev);
|
||||
|
||||
sas_port = domain_dev->port;
|
||||
sas_phy = list_first_entry(&sas_port->phy_list, struct asd_sas_phy,
|
||||
port_phy_el);
|
||||
isci_phy = to_isci_phy(sas_phy);
|
||||
isci_port = isci_phy->isci_port;
|
||||
|
||||
/* we are being called for a device on this port,
|
||||
* so it has to come up eventually
|
||||
*/
|
||||
wait_for_completion(&isci_port->start_complete);
|
||||
|
||||
if ((isci_stopping == isci_port_get_state(isci_port)) ||
|
||||
(isci_stopped == isci_port_get_state(isci_port)))
|
||||
return -ENODEV;
|
||||
|
||||
isci_device = isci_remote_device_alloc(isci_host, isci_port);
|
||||
|
||||
INIT_LIST_HEAD(&isci_device->node);
|
||||
domain_dev->lldd_dev = isci_device;
|
||||
isci_device->domain_dev = domain_dev;
|
||||
isci_device->isci_port = isci_port;
|
||||
isci_remote_device_change_state(isci_device, isci_starting);
|
||||
|
||||
|
||||
spin_lock_irqsave(&isci_port->remote_device_lock, flags);
|
||||
list_add_tail(&isci_device->node, &isci_port->remote_dev_list);
|
||||
|
||||
/* for the device ready event. */
|
||||
isci_device->completion = &completion;
|
||||
|
||||
status = isci_remote_device_construct(isci_port, isci_device);
|
||||
|
||||
spin_unlock_irqrestore(&isci_port->remote_device_lock, flags);
|
||||
|
||||
/* wait for the device ready callback. */
|
||||
wait_for_completion(isci_device->completion);
|
||||
isci_device->completion = NULL;
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_device = %p\n",
|
||||
__func__, isci_device);
|
||||
|
||||
if (status != SCI_SUCCESS) {
|
||||
|
||||
spin_lock_irqsave(&isci_port->remote_device_lock, flags);
|
||||
isci_remote_device_deconstruct(
|
||||
isci_host,
|
||||
isci_device
|
||||
);
|
||||
spin_unlock_irqrestore(&isci_port->remote_device_lock, flags);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
wait_for_completion(&isci_host->start_complete);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* isci_device_is_reset_pending() - This function will check if there is any
|
||||
* pending reset condition on the device.
|
||||
* @request: This parameter is the isci_device object.
|
||||
*
|
||||
* true if there is a reset pending for the device.
|
||||
*/
|
||||
bool isci_device_is_reset_pending(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_remote_device *isci_device)
|
||||
{
|
||||
struct isci_request *isci_request;
|
||||
struct isci_request *tmp_req;
|
||||
bool reset_is_pending = false;
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_device = %p\n", __func__, isci_device);
|
||||
|
||||
spin_lock_irqsave(&isci_host->scic_lock, flags);
|
||||
|
||||
/* Check for reset on all pending requests. */
|
||||
list_for_each_entry_safe(isci_request, tmp_req,
|
||||
&isci_device->reqs_in_process, dev_node) {
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_device = %p request = %p\n",
|
||||
__func__, isci_device, isci_request);
|
||||
|
||||
if (isci_request->ttype == io_task) {
|
||||
|
||||
unsigned long flags;
|
||||
struct sas_task *task = isci_request_access_task(
|
||||
isci_request);
|
||||
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET)
|
||||
reset_is_pending = true;
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&isci_host->scic_lock, flags);
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_device = %p reset_is_pending = %d\n",
|
||||
__func__, isci_device, reset_is_pending);
|
||||
|
||||
return reset_is_pending;
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_device_clear_reset_pending() - This function will clear if any pending
|
||||
* reset condition flags on the device.
|
||||
* @request: This parameter is the isci_device object.
|
||||
*
|
||||
* true if there is a reset pending for the device.
|
||||
*/
|
||||
void isci_device_clear_reset_pending(struct isci_remote_device *isci_device)
|
||||
{
|
||||
struct isci_request *isci_request;
|
||||
struct isci_request *tmp_req;
|
||||
struct isci_host *isci_host = NULL;
|
||||
unsigned long flags = 0;
|
||||
|
||||
/* FIXME more port gone confusion, and this time it makes the
|
||||
* locking "fun"
|
||||
*/
|
||||
if (isci_device->isci_port != NULL)
|
||||
isci_host = isci_device->isci_port->isci_host;
|
||||
|
||||
/*
|
||||
* FIXME when the isci_host gets sorted out
|
||||
* use dev_dbg()
|
||||
*/
|
||||
pr_debug("%s: isci_device=%p, isci_host=%p\n",
|
||||
__func__, isci_device, isci_host);
|
||||
|
||||
if (isci_host != NULL)
|
||||
spin_lock_irqsave(&isci_host->scic_lock, flags);
|
||||
else
|
||||
pr_err("%s: isci_device %p; isci_host == NULL!\n",
|
||||
__func__, isci_device);
|
||||
|
||||
/* Clear reset pending on all pending requests. */
|
||||
list_for_each_entry_safe(isci_request, tmp_req,
|
||||
&isci_device->reqs_in_process, dev_node) {
|
||||
/*
|
||||
* FIXME when the conditional spinlock is gone
|
||||
* change to dev_dbg()
|
||||
*/
|
||||
pr_debug("%s: isci_device = %p request = %p\n",
|
||||
__func__, isci_device, isci_request);
|
||||
|
||||
if (isci_request->ttype == io_task) {
|
||||
|
||||
unsigned long flags2;
|
||||
struct sas_task *task = isci_request_access_task(
|
||||
isci_request);
|
||||
|
||||
spin_lock_irqsave(&task->task_state_lock, flags2);
|
||||
task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags2);
|
||||
}
|
||||
}
|
||||
|
||||
if (isci_host != NULL)
|
||||
spin_unlock_irqrestore(&isci_host->scic_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_remote_device_change_state() - This function gets the status of the
|
||||
* remote_device object.
|
||||
* @isci_device: This parameter points to the isci_remote_device object
|
||||
*
|
||||
* status of the object as a isci_status enum.
|
||||
*/
|
||||
void isci_remote_device_change_state(
|
||||
struct isci_remote_device *isci_device,
|
||||
enum isci_status status)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
|
||||
"%s: isci_device = %p, state = 0x%x",
|
||||
__func__,
|
||||
isci_device,
|
||||
status);
|
||||
|
||||
spin_lock_irqsave(&isci_device->state_lock, flags);
|
||||
isci_device->status = status;
|
||||
spin_unlock_irqrestore(&isci_device->state_lock, flags);
|
||||
}
|
||||
154
drivers/scsi/isci/remote_device.h
Normal file
154
drivers/scsi/isci/remote_device.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(_ISCI_REMOTE_DEVICE_H_)
|
||||
#define _ISCI_REMOTE_DEVICE_H_
|
||||
#include "scic_user_callback.h"
|
||||
|
||||
struct isci_host;
|
||||
struct scic_sds_remote_device;
|
||||
|
||||
struct isci_remote_device {
|
||||
struct scic_sds_remote_device *sci_device_handle;
|
||||
enum isci_status status;
|
||||
struct isci_port *isci_port;
|
||||
struct domain_device *domain_dev;
|
||||
struct completion *completion;
|
||||
struct list_head node;
|
||||
struct list_head reqs_in_process;
|
||||
struct work_struct stop_work;
|
||||
spinlock_t state_lock;
|
||||
spinlock_t host_quiesce_lock;
|
||||
bool host_quiesce;
|
||||
};
|
||||
|
||||
#define to_isci_remote_device(p) \
|
||||
container_of(p, struct isci_remote_device, sci_remote_device);
|
||||
|
||||
#define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000
|
||||
|
||||
|
||||
/**
|
||||
* This function gets the status of the remote_device object.
|
||||
* @isci_device: This parameter points to the isci_remote_device object
|
||||
*
|
||||
* status of the object as a isci_status enum.
|
||||
*/
|
||||
static inline
|
||||
enum isci_status isci_remote_device_get_state(
|
||||
struct isci_remote_device *isci_device)
|
||||
{
|
||||
return (isci_device->host_quiesce)
|
||||
? isci_host_quiesce
|
||||
: isci_device->status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* isci_dev_from_domain_dev() - This accessor retrieves the remote_device
|
||||
* object reference from the Linux domain_device reference.
|
||||
* @domdev,: This parameter points to the Linux domain_device object .
|
||||
*
|
||||
* A reference to the associated isci remote device.
|
||||
*/
|
||||
#define isci_dev_from_domain_dev(domdev) \
|
||||
((struct isci_remote_device *)(domdev)->lldd_dev)
|
||||
|
||||
void isci_remote_device_start_complete(
|
||||
struct isci_host *,
|
||||
struct isci_remote_device *,
|
||||
enum sci_status);
|
||||
|
||||
void isci_remote_device_stop_complete(
|
||||
struct isci_host *,
|
||||
struct isci_remote_device *,
|
||||
enum sci_status);
|
||||
|
||||
enum sci_status isci_remote_device_stop(
|
||||
struct isci_remote_device *isci_device);
|
||||
|
||||
void isci_remote_device_nuke_requests(
|
||||
struct isci_remote_device *isci_device);
|
||||
|
||||
void isci_remote_device_ready(
|
||||
struct isci_remote_device *);
|
||||
|
||||
void isci_remote_device_not_ready(
|
||||
struct isci_remote_device *,
|
||||
u32);
|
||||
|
||||
void isci_remote_device_gone(
|
||||
struct domain_device *domain_dev);
|
||||
|
||||
int isci_remote_device_found(
|
||||
struct domain_device *domain_dev);
|
||||
|
||||
bool isci_device_is_reset_pending(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_remote_device *isci_device);
|
||||
|
||||
void isci_device_clear_reset_pending(
|
||||
struct isci_remote_device *isci_device);
|
||||
|
||||
void isci_device_set_host_quiesce_lock_state(
|
||||
struct isci_remote_device *isci_device,
|
||||
bool lock_state);
|
||||
|
||||
void isci_remote_device_change_state(
|
||||
struct isci_remote_device *isci_device,
|
||||
enum isci_status status);
|
||||
|
||||
#endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */
|
||||
|
||||
1472
drivers/scsi/isci/request.c
Normal file
1472
drivers/scsi/isci/request.c
Normal file
File diff suppressed because it is too large
Load Diff
429
drivers/scsi/isci/request.h
Normal file
429
drivers/scsi/isci/request.h
Normal file
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(_ISCI_REQUEST_H_)
|
||||
#define _ISCI_REQUEST_H_
|
||||
|
||||
#include "isci.h"
|
||||
|
||||
/**
|
||||
* struct isci_request_status - This enum defines the possible states of an I/O
|
||||
* request.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum isci_request_status {
|
||||
unallocated = 0x00,
|
||||
allocated = 0x01,
|
||||
started = 0x02,
|
||||
completed = 0x03,
|
||||
aborting = 0x04,
|
||||
aborted = 0x05,
|
||||
terminating = 0x06
|
||||
};
|
||||
|
||||
enum task_type {
|
||||
io_task = 0,
|
||||
tmf_task = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* struct isci_request - This class represents the request object used to track
|
||||
* IO, smp and TMF request internal. It wraps the SCIC request object.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct isci_request {
|
||||
|
||||
struct scic_sds_request *sci_request_handle;
|
||||
|
||||
enum isci_request_status status;
|
||||
enum task_type ttype;
|
||||
unsigned short io_tag;
|
||||
bool complete_in_target;
|
||||
|
||||
union ttype_ptr_union {
|
||||
struct sas_task *io_task_ptr; /* When ttype==io_task */
|
||||
struct isci_tmf *tmf_task_ptr; /* When ttype==tmf_task */
|
||||
} ttype_ptr;
|
||||
struct isci_host *isci_host;
|
||||
struct isci_remote_device *isci_device;
|
||||
/* For use in the requests_to_{complete|abort} lists: */
|
||||
struct list_head completed_node;
|
||||
/* For use in the reqs_in_process list: */
|
||||
struct list_head dev_node;
|
||||
void *sci_request_mem_ptr;
|
||||
spinlock_t state_lock;
|
||||
dma_addr_t request_daddr;
|
||||
dma_addr_t zero_scatter_daddr;
|
||||
|
||||
unsigned int num_sg_entries; /* returned by pci_alloc_sg */
|
||||
unsigned int request_alloc_size; /* size of block from dma_pool_alloc */
|
||||
|
||||
/** Note: "io_request_completion" is completed in two different ways
|
||||
* depending on whether this is a TMF or regular request.
|
||||
* - TMF requests are completed in the thread that started them;
|
||||
* - regular requests are completed in the request completion callback
|
||||
* function.
|
||||
* This difference in operation allows the aborter of a TMF request
|
||||
* to be sure that once the TMF request completes, the I/O that the
|
||||
* TMF was aborting is guaranteed to have completed.
|
||||
*/
|
||||
struct completion *io_request_completion;
|
||||
};
|
||||
|
||||
/**
|
||||
* This function gets the status of the request object.
|
||||
* @request: This parameter points to the isci_request object
|
||||
*
|
||||
* status of the object as a isci_request_status enum.
|
||||
*/
|
||||
static inline
|
||||
enum isci_request_status isci_request_get_state(
|
||||
struct isci_request *isci_request)
|
||||
{
|
||||
BUG_ON(isci_request == NULL);
|
||||
|
||||
/*probably a bad sign... */
|
||||
if (isci_request->status == unallocated)
|
||||
dev_warn(&isci_request->isci_host->pdev->dev,
|
||||
"%s: isci_request->status == unallocated\n",
|
||||
__func__);
|
||||
|
||||
return isci_request->status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* isci_request_change_state() - This function sets the status of the request
|
||||
* object.
|
||||
* @request: This parameter points to the isci_request object
|
||||
* @status: This Parameter is the new status of the object
|
||||
*
|
||||
*/
|
||||
static inline enum isci_request_status isci_request_change_state(
|
||||
struct isci_request *isci_request,
|
||||
enum isci_request_status status)
|
||||
{
|
||||
enum isci_request_status old_state;
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(&isci_request->isci_host->pdev->dev,
|
||||
"%s: isci_request = %p, state = 0x%x\n",
|
||||
__func__,
|
||||
isci_request,
|
||||
status);
|
||||
|
||||
BUG_ON(isci_request == NULL);
|
||||
|
||||
spin_lock_irqsave(&isci_request->state_lock, flags);
|
||||
old_state = isci_request->status;
|
||||
isci_request->status = status;
|
||||
spin_unlock_irqrestore(&isci_request->state_lock, flags);
|
||||
|
||||
return old_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_request_change_started_to_newstate() - This function sets the status of
|
||||
* the request object.
|
||||
* @request: This parameter points to the isci_request object
|
||||
* @status: This Parameter is the new status of the object
|
||||
*
|
||||
* state previous to any change.
|
||||
*/
|
||||
static inline enum isci_request_status isci_request_change_started_to_newstate(
|
||||
struct isci_request *isci_request,
|
||||
struct completion *completion_ptr,
|
||||
enum isci_request_status newstate)
|
||||
{
|
||||
enum isci_request_status old_state;
|
||||
unsigned long flags;
|
||||
|
||||
BUG_ON(isci_request == NULL);
|
||||
|
||||
spin_lock_irqsave(&isci_request->state_lock, flags);
|
||||
|
||||
old_state = isci_request->status;
|
||||
|
||||
if (old_state == started) {
|
||||
BUG_ON(isci_request->io_request_completion != NULL);
|
||||
|
||||
isci_request->io_request_completion = completion_ptr;
|
||||
isci_request->status = newstate;
|
||||
}
|
||||
spin_unlock_irqrestore(&isci_request->state_lock, flags);
|
||||
|
||||
dev_dbg(&isci_request->isci_host->pdev->dev,
|
||||
"%s: isci_request = %p, old_state = 0x%x\n",
|
||||
__func__,
|
||||
isci_request,
|
||||
old_state);
|
||||
|
||||
return old_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_request_change_started_to_aborted() - This function sets the status of
|
||||
* the request object.
|
||||
* @request: This parameter points to the isci_request object
|
||||
* @completion_ptr: This parameter is saved as the kernel completion structure
|
||||
* signalled when the old request completes.
|
||||
*
|
||||
* state previous to any change.
|
||||
*/
|
||||
static inline enum isci_request_status isci_request_change_started_to_aborted(
|
||||
struct isci_request *isci_request,
|
||||
struct completion *completion_ptr)
|
||||
{
|
||||
return isci_request_change_started_to_newstate(
|
||||
isci_request, completion_ptr, aborted
|
||||
);
|
||||
}
|
||||
/**
|
||||
* isci_request_free() - This function frees the request object.
|
||||
* @isci_host: This parameter specifies the ISCI host object
|
||||
* @isci_request: This parameter points to the isci_request object
|
||||
*
|
||||
*/
|
||||
static inline void isci_request_free(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_request *isci_request)
|
||||
{
|
||||
BUG_ON(isci_request == NULL);
|
||||
|
||||
/* release the dma memory if we fail. */
|
||||
dma_pool_free(isci_host->dma_pool, isci_request,
|
||||
isci_request->request_daddr);
|
||||
}
|
||||
|
||||
|
||||
/* #define ISCI_REQUEST_VALIDATE_ACCESS
|
||||
*/
|
||||
|
||||
#ifdef ISCI_REQUEST_VALIDATE_ACCESS
|
||||
|
||||
static inline
|
||||
struct sas_task *isci_request_access_task(struct isci_request *isci_request)
|
||||
{
|
||||
BUG_ON(isci_request->ttype != io_task);
|
||||
return isci_request->ttype_ptr.io_task_ptr;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct isci_tmf *isci_request_access_tmf(struct isci_request *isci_request)
|
||||
{
|
||||
BUG_ON(isci_request->ttype != tmf_task);
|
||||
return isci_request->ttype_ptr.tmf_task_ptr;
|
||||
}
|
||||
|
||||
#else /* not ISCI_REQUEST_VALIDATE_ACCESS */
|
||||
|
||||
#define isci_request_access_task(RequestPtr) \
|
||||
((RequestPtr)->ttype_ptr.io_task_ptr)
|
||||
|
||||
#define isci_request_access_tmf(RequestPtr) \
|
||||
((RequestPtr)->ttype_ptr.tmf_task_ptr)
|
||||
|
||||
#endif /* not ISCI_REQUEST_VALIDATE_ACCESS */
|
||||
|
||||
|
||||
int isci_request_alloc_tmf(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_tmf *isci_tmf,
|
||||
struct isci_request **isci_request,
|
||||
struct isci_remote_device *isci_device,
|
||||
gfp_t gfp_flags);
|
||||
|
||||
|
||||
int isci_request_execute(
|
||||
struct isci_host *isci_host,
|
||||
struct sas_task *task,
|
||||
struct isci_request **request,
|
||||
gfp_t gfp_flags);
|
||||
|
||||
/**
|
||||
* isci_request_unmap_sgl() - This function unmaps the DMA address of a given
|
||||
* sgl
|
||||
* @request: This parameter points to the isci_request object
|
||||
* @*pdev: This Parameter is the pci_device struct for the controller
|
||||
*
|
||||
*/
|
||||
static inline void isci_request_unmap_sgl(
|
||||
struct isci_request *request,
|
||||
struct pci_dev *pdev)
|
||||
{
|
||||
struct sas_task *task = isci_request_access_task(request);
|
||||
|
||||
dev_dbg(&request->isci_host->pdev->dev,
|
||||
"%s: request = %p, task = %p,\n"
|
||||
"task->data_dir = %d, is_sata = %d\n ",
|
||||
__func__,
|
||||
request,
|
||||
task,
|
||||
task->data_dir,
|
||||
sas_protocol_ata(task->task_proto));
|
||||
|
||||
if ((task->data_dir != PCI_DMA_NONE) &&
|
||||
!sas_protocol_ata(task->task_proto)) {
|
||||
if (task->num_scatter == 0)
|
||||
/* 0 indicates a single dma address */
|
||||
dma_unmap_single(
|
||||
&pdev->dev,
|
||||
request->zero_scatter_daddr,
|
||||
task->total_xfer_len,
|
||||
task->data_dir
|
||||
);
|
||||
|
||||
else /* unmap the sgl dma addresses */
|
||||
dma_unmap_sg(
|
||||
&pdev->dev,
|
||||
task->scatter,
|
||||
request->num_sg_entries,
|
||||
task->data_dir
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void isci_request_io_request_complete(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_request *request,
|
||||
enum sci_io_status completion_status);
|
||||
|
||||
u32 isci_request_io_request_get_transfer_length(
|
||||
struct isci_request *request);
|
||||
|
||||
SCI_IO_REQUEST_DATA_DIRECTION isci_request_io_request_get_data_direction(
|
||||
struct isci_request *request);
|
||||
|
||||
/**
|
||||
* isci_request_io_request_get_next_sge() - This function is called by the sci
|
||||
* core to retrieve the next sge for a given request.
|
||||
* @request: This parameter is the isci_request object.
|
||||
* @current_sge_address: This parameter is the last sge retrieved by the sci
|
||||
* core for this request.
|
||||
*
|
||||
* pointer to the next sge for specified request.
|
||||
*/
|
||||
static inline void *isci_request_io_request_get_next_sge(
|
||||
struct isci_request *request,
|
||||
void *current_sge_address)
|
||||
{
|
||||
struct sas_task *task = isci_request_access_task(request);
|
||||
void *ret = NULL;
|
||||
|
||||
dev_dbg(&request->isci_host->pdev->dev,
|
||||
"%s: request = %p, "
|
||||
"current_sge_address = %p, "
|
||||
"num_scatter = %d\n",
|
||||
__func__,
|
||||
request,
|
||||
current_sge_address,
|
||||
task->num_scatter);
|
||||
|
||||
if (!current_sge_address) /* First time through.. */
|
||||
ret = task->scatter; /* always task->scatter */
|
||||
else if (task->num_scatter == 0) /* Next element, if num_scatter == 0 */
|
||||
ret = NULL; /* there is only one element. */
|
||||
else
|
||||
ret = sg_next(current_sge_address); /* sg_next returns NULL
|
||||
* for the last element
|
||||
*/
|
||||
|
||||
dev_dbg(&request->isci_host->pdev->dev,
|
||||
"%s: next sge address = %p\n",
|
||||
__func__,
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
dma_addr_t isci_request_sge_get_address_field(
|
||||
struct isci_request *request,
|
||||
void *sge_address);
|
||||
|
||||
u32 isci_request_sge_get_length_field(
|
||||
struct isci_request *request,
|
||||
void *sge_address);
|
||||
|
||||
void *isci_request_ssp_io_request_get_cdb_address(
|
||||
struct isci_request *request);
|
||||
|
||||
u32 isci_request_ssp_io_request_get_cdb_length(
|
||||
struct isci_request *request);
|
||||
|
||||
u32 isci_request_ssp_io_request_get_lun(
|
||||
struct isci_request *request);
|
||||
|
||||
u32 isci_request_ssp_io_request_get_task_attribute(
|
||||
struct isci_request *request);
|
||||
|
||||
u32 isci_request_ssp_io_request_get_command_priority(
|
||||
struct isci_request *request);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void isci_terminate_pending_requests(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_remote_device *isci_device,
|
||||
enum isci_request_status new_request_state);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* !defined(_ISCI_REQUEST_H_) */
|
||||
356
drivers/scsi/isci/sata.c
Normal file
356
drivers/scsi/isci/sata.c
Normal file
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "isci.h"
|
||||
#include "scic_remote_device.h"
|
||||
#include "scic_sds_remote_device.h"
|
||||
#include "scic_io_request.h"
|
||||
#include "scic_task_request.h"
|
||||
#include "task.h"
|
||||
#include "request.h"
|
||||
#include "sata.h"
|
||||
#include "intel_sat.h"
|
||||
#include "intel_ata.h"
|
||||
|
||||
static u8 isci_sata_get_management_task_protocol(struct isci_tmf *tmf);
|
||||
|
||||
|
||||
/**
|
||||
* isci_sata_task_to_fis_copy() - This function gets the host_to_dev_fis from
|
||||
* the core and copies the fis from the task into it.
|
||||
* @task: This parameter is a pointer to the task struct from libsas.
|
||||
*
|
||||
* pointer to the host_to_dev_fis from the core request object.
|
||||
*/
|
||||
struct host_to_dev_fis *isci_sata_task_to_fis_copy(struct sas_task *task)
|
||||
{
|
||||
struct isci_request *request = task->lldd_task;
|
||||
struct host_to_dev_fis *register_fis =
|
||||
scic_stp_io_request_get_h2d_reg_address(
|
||||
request->sci_request_handle
|
||||
);
|
||||
|
||||
memcpy(
|
||||
(u8 *)register_fis,
|
||||
(u8 *)&task->ata_task.fis,
|
||||
sizeof(struct host_to_dev_fis)
|
||||
);
|
||||
|
||||
if (!task->ata_task.device_control_reg_update)
|
||||
register_fis->flags |= 0x80;
|
||||
|
||||
register_fis->flags &= 0xF0;
|
||||
|
||||
return register_fis;
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_sata_is_task_ncq() - This function determines if the given stp task is
|
||||
* a ncq request.
|
||||
* @task: This parameter is a pointer to the task struct from libsas.
|
||||
*
|
||||
* true if the task is ncq
|
||||
*/
|
||||
bool isci_sata_is_task_ncq(struct sas_task *task)
|
||||
{
|
||||
struct ata_queued_cmd *qc = task->uldd_task;
|
||||
|
||||
bool ret = (qc &&
|
||||
(qc->tf.command == ATA_CMD_FPDMA_WRITE ||
|
||||
qc->tf.command == ATA_CMD_FPDMA_READ));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_sata_set_ncq_tag() - This function sets the ncq tag field in the
|
||||
* host_to_dev_fis equal to the tag in the queue command in the task.
|
||||
* @task: This parameter is a pointer to the task struct from libsas.
|
||||
* @register_fis: This parameter is a pointer to the host_to_dev_fis from the
|
||||
* core request object.
|
||||
*
|
||||
*/
|
||||
void isci_sata_set_ncq_tag(
|
||||
struct host_to_dev_fis *register_fis,
|
||||
struct sas_task *task)
|
||||
{
|
||||
struct ata_queued_cmd *qc = task->uldd_task;
|
||||
struct isci_request *request = task->lldd_task;
|
||||
|
||||
register_fis->sector_count = qc->tag << 3;
|
||||
scic_stp_io_request_set_ncq_tag(request->sci_request_handle, qc->tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_request_process_stp_response() - This function sets the status and
|
||||
* response, in the task struct, from the request object for the upper layer
|
||||
* driver.
|
||||
* @sas_task: This parameter is the task struct from the upper layer driver.
|
||||
* @response_buffer: This parameter points to the response of the completed
|
||||
* request.
|
||||
*
|
||||
* none.
|
||||
*/
|
||||
void isci_request_process_stp_response(
|
||||
struct sas_task *task,
|
||||
void *response_buffer)
|
||||
{
|
||||
struct sata_fis_reg_d2h *d2h_reg_fis = (struct sata_fis_reg_d2h *)response_buffer;
|
||||
struct task_status_struct *ts = &task->task_status;
|
||||
struct ata_task_resp *resp = (void *)&ts->buf[0];
|
||||
|
||||
resp->frame_len = le16_to_cpu(*(__le16 *)(response_buffer + 6));
|
||||
memcpy(&resp->ending_fis[0], response_buffer + 16, 24);
|
||||
ts->buf_valid_size = sizeof(*resp);
|
||||
|
||||
/**
|
||||
* If the device fault bit is set in the status register, then
|
||||
* set the sense data and return.
|
||||
*/
|
||||
if (d2h_reg_fis->status & ATA_STATUS_REG_DEVICE_FAULT_BIT)
|
||||
ts->stat = SAS_PROTO_RESPONSE;
|
||||
else
|
||||
ts->stat = SAM_STAT_GOOD;
|
||||
|
||||
ts->resp = SAS_TASK_COMPLETE;
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_sata_get_sat_protocol() - retrieve the sat protocol for the request
|
||||
* @isci_request: ata request
|
||||
*
|
||||
* Note: temporary implementation until expert mode removes the callback
|
||||
*
|
||||
*/
|
||||
u8 isci_sata_get_sat_protocol(struct isci_request *isci_request)
|
||||
{
|
||||
struct sas_task *task;
|
||||
struct domain_device *dev;
|
||||
|
||||
dev_dbg(&isci_request->isci_host->pdev->dev,
|
||||
"%s: isci_request = %p, ttype = %d\n",
|
||||
__func__, isci_request, isci_request->ttype);
|
||||
|
||||
if (tmf_task == isci_request->ttype) {
|
||||
struct isci_tmf *tmf = isci_request_access_tmf(isci_request);
|
||||
|
||||
return isci_sata_get_management_task_protocol(tmf);
|
||||
}
|
||||
|
||||
task = isci_request_access_task(isci_request);
|
||||
dev = task->dev;
|
||||
|
||||
if (!sas_protocol_ata(task->task_proto)) {
|
||||
WARN(1, "unhandled task protocol\n");
|
||||
return SAT_PROTOCOL_NON_DATA;
|
||||
}
|
||||
|
||||
if (task->data_dir == DMA_NONE)
|
||||
return SAT_PROTOCOL_NON_DATA;
|
||||
|
||||
/* the "_IN" protocol types are equivalent to their "_OUT"
|
||||
* analogs as far as the core is concerned
|
||||
*/
|
||||
if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) {
|
||||
if (task->ata_task.dma_xfer)
|
||||
return SAT_PROTOCOL_PACKET_DMA_DATA_IN;
|
||||
else
|
||||
return SAT_PROTOCOL_PACKET_PIO_DATA_IN;
|
||||
}
|
||||
|
||||
if (task->ata_task.use_ncq)
|
||||
return SAT_PROTOCOL_FPDMA;
|
||||
|
||||
if (task->ata_task.dma_xfer)
|
||||
return SAT_PROTOCOL_UDMA_DATA_IN;
|
||||
else
|
||||
return SAT_PROTOCOL_PIO_DATA_IN;
|
||||
}
|
||||
|
||||
static u8 isci_sata_get_management_task_protocol(
|
||||
struct isci_tmf *tmf)
|
||||
{
|
||||
u8 ret = 0;
|
||||
|
||||
pr_warn("tmf = %p, func = %d\n", tmf, tmf->tmf_code);
|
||||
|
||||
if ((tmf->tmf_code == isci_tmf_sata_srst_high) ||
|
||||
(tmf->tmf_code == isci_tmf_sata_srst_low)) {
|
||||
pr_warn("%s: tmf->tmf_code == TMF_LU_RESET\n", __func__);
|
||||
ret = SAT_PROTOCOL_SOFT_RESET;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum sci_status isci_sata_management_task_request_build(
|
||||
struct isci_request *isci_request)
|
||||
{
|
||||
struct isci_tmf *isci_tmf;
|
||||
enum sci_status status;
|
||||
|
||||
if (tmf_task != isci_request->ttype)
|
||||
return SCI_FAILURE;
|
||||
|
||||
isci_tmf = isci_request_access_tmf(isci_request);
|
||||
|
||||
switch (isci_tmf->tmf_code) {
|
||||
|
||||
case isci_tmf_sata_srst_high:
|
||||
case isci_tmf_sata_srst_low:
|
||||
{
|
||||
struct host_to_dev_fis *register_fis =
|
||||
scic_stp_io_request_get_h2d_reg_address(
|
||||
isci_request->sci_request_handle
|
||||
);
|
||||
|
||||
memset(register_fis, 0, sizeof(*register_fis));
|
||||
|
||||
register_fis->fis_type = 0x27;
|
||||
register_fis->flags &= ~0x80;
|
||||
register_fis->flags &= 0xF0;
|
||||
if (isci_tmf->tmf_code == isci_tmf_sata_srst_high)
|
||||
register_fis->control |= ATA_SRST;
|
||||
else
|
||||
register_fis->control &= ~ATA_SRST;
|
||||
break;
|
||||
}
|
||||
/* other management commnd go here... */
|
||||
default:
|
||||
return SCI_FAILURE;
|
||||
}
|
||||
|
||||
/* core builds the protocol specific request
|
||||
* based on the h2d fis.
|
||||
*/
|
||||
status = scic_task_request_construct_sata(
|
||||
isci_request->sci_request_handle
|
||||
);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_task_send_lu_reset_sata() - This function is called by of the SAS
|
||||
* Domain Template functions. This is one of the Task Management functoins
|
||||
* called by libsas, to reset the given SAS lun. Note the assumption that
|
||||
* while this call is executing, no I/O will be sent by the host to the
|
||||
* device.
|
||||
* @lun: This parameter specifies the lun to be reset.
|
||||
*
|
||||
* status, zero indicates success.
|
||||
*/
|
||||
int isci_task_send_lu_reset_sata(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_remote_device *isci_device,
|
||||
u8 *lun)
|
||||
{
|
||||
struct isci_tmf tmf;
|
||||
int ret = TMF_RESP_FUNC_FAILED;
|
||||
unsigned long flags;
|
||||
|
||||
/* Send the initial SRST to the target */
|
||||
#define ISCI_SRST_TIMEOUT_MS 20 /* 20 ms timeout. */
|
||||
isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_high,
|
||||
NULL, NULL
|
||||
);
|
||||
|
||||
ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_SRST_TIMEOUT_MS);
|
||||
|
||||
if (ret != TMF_RESP_FUNC_COMPLETE) {
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"%s: Assert SRST failed (%p) = %x",
|
||||
__func__,
|
||||
isci_device,
|
||||
ret);
|
||||
|
||||
/* Return the failure so that the LUN reset is escalated
|
||||
* to a target reset.
|
||||
*/
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Leave SRST high for a bit. */
|
||||
#define ISCI_SRST_ASSERT_DELAY 100 /* usecs */
|
||||
scic_cb_stall_execution(ISCI_SRST_ASSERT_DELAY);
|
||||
|
||||
/* Deassert SRST. */
|
||||
isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_low,
|
||||
NULL, NULL
|
||||
);
|
||||
ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_SRST_TIMEOUT_MS);
|
||||
|
||||
if (ret == TMF_RESP_FUNC_COMPLETE)
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: SATA LUN reset passed (%p)\n",
|
||||
__func__,
|
||||
isci_device);
|
||||
else
|
||||
dev_warn(&isci_host->pdev->dev,
|
||||
"%s: Deassert SRST failed (%p)=%x\n",
|
||||
__func__,
|
||||
isci_device,
|
||||
ret);
|
||||
|
||||
out:
|
||||
spin_lock_irqsave(&isci_host->scic_lock, flags);
|
||||
|
||||
/* Resume the device. */
|
||||
scic_sds_remote_device_resume(isci_device->sci_device_handle);
|
||||
|
||||
spin_unlock_irqrestore(&isci_host->scic_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
83
drivers/scsi/isci/sata.h
Normal file
83
drivers/scsi/isci/sata.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "intel_sat.h"
|
||||
|
||||
|
||||
|
||||
struct host_to_dev_fis *isci_sata_task_to_fis_copy(
|
||||
struct sas_task *task);
|
||||
|
||||
bool isci_sata_is_task_ncq(
|
||||
struct sas_task *task);
|
||||
|
||||
void isci_sata_set_ncq_tag(
|
||||
struct host_to_dev_fis *register_fis,
|
||||
struct sas_task *task);
|
||||
|
||||
void isci_request_process_stp_response(
|
||||
struct sas_task *task,
|
||||
void *response_buffer);
|
||||
|
||||
u8 isci_sata_get_sat_protocol(
|
||||
struct isci_request *isci_request);
|
||||
|
||||
enum sci_status isci_sata_management_task_request_build(
|
||||
struct isci_request *isci_request);
|
||||
|
||||
int isci_task_send_lu_reset_sata(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_remote_device *isci_device,
|
||||
u8 *lun);
|
||||
112
drivers/scsi/isci/sci_environment.h
Normal file
112
drivers/scsi/isci/sci_environment.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SCI_ENVIRONMENT_H_
|
||||
#define _SCI_ENVIRONMENT_H_
|
||||
|
||||
#include "isci.h"
|
||||
|
||||
struct scic_sds_controller;
|
||||
struct scic_sds_phy;
|
||||
struct scic_sds_port;
|
||||
struct scic_sds_remote_device;
|
||||
|
||||
static inline struct device *scic_to_dev(struct scic_sds_controller *scic)
|
||||
{
|
||||
struct isci_host *isci_host = sci_object_get_association(scic);
|
||||
|
||||
return &isci_host->pdev->dev;
|
||||
}
|
||||
|
||||
static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy)
|
||||
{
|
||||
struct isci_phy *iphy = sci_object_get_association(sci_phy);
|
||||
|
||||
if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host)
|
||||
return NULL;
|
||||
|
||||
return &iphy->isci_port->isci_host->pdev->dev;
|
||||
}
|
||||
|
||||
static inline struct device *sciport_to_dev(struct scic_sds_port *sci_port)
|
||||
{
|
||||
struct isci_port *iport = sci_object_get_association(sci_port);
|
||||
|
||||
if (!iport || !iport->isci_host)
|
||||
return NULL;
|
||||
|
||||
return &iport->isci_host->pdev->dev;
|
||||
}
|
||||
|
||||
static inline struct device *scirdev_to_dev(struct scic_sds_remote_device *sci_dev)
|
||||
{
|
||||
struct isci_remote_device *idev = sci_object_get_association(sci_dev);
|
||||
|
||||
if (!idev || !idev->isci_port || !idev->isci_port->isci_host)
|
||||
return NULL;
|
||||
|
||||
return &idev->isci_port->isci_host->pdev->dev;
|
||||
}
|
||||
|
||||
enum {
|
||||
ISCI_SI_REVA0,
|
||||
ISCI_SI_REVA2,
|
||||
ISCI_SI_REVB0,
|
||||
};
|
||||
|
||||
extern int isci_si_rev;
|
||||
|
||||
|
||||
#endif
|
||||
1691
drivers/scsi/isci/task.c
Normal file
1691
drivers/scsi/isci/task.c
Normal file
File diff suppressed because it is too large
Load Diff
368
drivers/scsi/isci/task.h
Normal file
368
drivers/scsi/isci/task.h
Normal file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(_ISCI_TASK_H_)
|
||||
#define _ISCI_TASK_H_
|
||||
|
||||
struct isci_request;
|
||||
struct isci_host;
|
||||
|
||||
/**
|
||||
* enum isci_tmf_cb_state - This enum defines the possible states in which the
|
||||
* TMF callback function is invoked during the TMF execution process.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum isci_tmf_cb_state {
|
||||
|
||||
isci_tmf_init_state = 0,
|
||||
isci_tmf_started,
|
||||
isci_tmf_timed_out
|
||||
};
|
||||
|
||||
/**
|
||||
* enum isci_tmf_function_codes - This enum defines the possible preparations
|
||||
* of task management requests.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum isci_tmf_function_codes {
|
||||
|
||||
isci_tmf_func_none = 0,
|
||||
isci_tmf_ssp_task_abort = TMF_ABORT_TASK,
|
||||
isci_tmf_ssp_lun_reset = TMF_LU_RESET,
|
||||
isci_tmf_sata_srst_high = TMF_LU_RESET + 0x100, /* Non SCSI */
|
||||
isci_tmf_sata_srst_low = TMF_LU_RESET + 0x101 /* Non SCSI */
|
||||
};
|
||||
/**
|
||||
* struct isci_tmf - This class represents the task management object which
|
||||
* acts as an interface to libsas for processing task management requests
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct isci_tmf {
|
||||
|
||||
struct completion *complete;
|
||||
enum sas_protocol proto;
|
||||
union {
|
||||
struct sci_ssp_response_iu resp_iu;
|
||||
struct dev_to_host_fis d2h_fis;
|
||||
} resp;
|
||||
unsigned char lun[8];
|
||||
u16 io_tag;
|
||||
struct isci_remote_device *device;
|
||||
enum isci_tmf_function_codes tmf_code;
|
||||
int status;
|
||||
|
||||
struct isci_timer *timeout_timer;
|
||||
|
||||
/* The optional callback function allows the user process to
|
||||
* track the TMF transmit / timeout conditions.
|
||||
*/
|
||||
void (*cb_state_func)(
|
||||
enum isci_tmf_cb_state,
|
||||
struct isci_tmf *, void *);
|
||||
void *cb_data;
|
||||
|
||||
};
|
||||
|
||||
static inline void isci_print_tmf(
|
||||
struct isci_tmf *tmf)
|
||||
{
|
||||
if (SAS_PROTOCOL_SATA == tmf->proto)
|
||||
dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev,
|
||||
"%s: status = %x\n"
|
||||
"tmf->resp.d2h_fis.status = %x\n"
|
||||
"tmf->resp.d2h_fis.error = %x\n",
|
||||
__func__,
|
||||
tmf->status,
|
||||
tmf->resp.d2h_fis.status,
|
||||
tmf->resp.d2h_fis.error);
|
||||
else
|
||||
dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev,
|
||||
"%s: status = %x\n"
|
||||
"tmf->resp.resp_iu.data_present = %x\n"
|
||||
"tmf->resp.resp_iu.status = %x\n"
|
||||
"tmf->resp.resp_iu.data_length = %x\n"
|
||||
"tmf->resp.resp_iu.data[0] = %x\n"
|
||||
"tmf->resp.resp_iu.data[1] = %x\n"
|
||||
"tmf->resp.resp_iu.data[2] = %x\n"
|
||||
"tmf->resp.resp_iu.data[3] = %x\n",
|
||||
__func__,
|
||||
tmf->status,
|
||||
tmf->resp.resp_iu.data_present,
|
||||
tmf->resp.resp_iu.status,
|
||||
(tmf->resp.resp_iu.response_data_length[0] << 24) +
|
||||
(tmf->resp.resp_iu.response_data_length[1] << 16) +
|
||||
(tmf->resp.resp_iu.response_data_length[2] << 8) +
|
||||
tmf->resp.resp_iu.response_data_length[3],
|
||||
tmf->resp.resp_iu.data[0],
|
||||
tmf->resp.resp_iu.data[1],
|
||||
tmf->resp.resp_iu.data[2],
|
||||
tmf->resp.resp_iu.data[3]);
|
||||
}
|
||||
|
||||
|
||||
int isci_task_execute_task(
|
||||
struct sas_task *task,
|
||||
int num,
|
||||
gfp_t gfp_flags);
|
||||
|
||||
int isci_task_abort_task(
|
||||
struct sas_task *task);
|
||||
|
||||
int isci_task_abort_task_set(
|
||||
struct domain_device *d_device,
|
||||
u8 *lun);
|
||||
|
||||
int isci_task_clear_aca(
|
||||
struct domain_device *d_device,
|
||||
u8 *lun);
|
||||
|
||||
int isci_task_clear_task_set(
|
||||
struct domain_device *d_device,
|
||||
u8 *lun);
|
||||
|
||||
int isci_task_query_task(
|
||||
struct sas_task *task);
|
||||
|
||||
int isci_task_lu_reset(
|
||||
struct domain_device *d_device,
|
||||
u8 *lun);
|
||||
|
||||
int isci_task_clear_nexus_port(
|
||||
struct asd_sas_port *port);
|
||||
|
||||
int isci_task_clear_nexus_ha(
|
||||
struct sas_ha_struct *ha);
|
||||
|
||||
int isci_task_I_T_nexus_reset(
|
||||
struct domain_device *d_device);
|
||||
|
||||
void isci_task_request_complete(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_request *request,
|
||||
enum sci_task_status completion_status);
|
||||
|
||||
u16 isci_task_ssp_request_get_io_tag_to_manage(
|
||||
struct isci_request *request);
|
||||
|
||||
u8 isci_task_ssp_request_get_function(
|
||||
struct isci_request *request);
|
||||
|
||||
u32 isci_task_ssp_request_get_lun(
|
||||
struct isci_request *request);
|
||||
|
||||
void *isci_task_ssp_request_get_response_data_address(
|
||||
struct isci_request *request);
|
||||
|
||||
u32 isci_task_ssp_request_get_response_data_length(
|
||||
struct isci_request *request);
|
||||
|
||||
int isci_queuecommand(
|
||||
struct scsi_cmnd *scsi_cmd,
|
||||
void (*donefunc)(struct scsi_cmnd *));
|
||||
|
||||
int isci_bus_reset_handler(struct scsi_cmnd *cmd);
|
||||
|
||||
void isci_task_build_tmf(
|
||||
struct isci_tmf *tmf,
|
||||
struct isci_remote_device *isci_device,
|
||||
enum isci_tmf_function_codes code,
|
||||
void (*tmf_sent_cb)(
|
||||
enum isci_tmf_cb_state,
|
||||
struct isci_tmf *, void *),
|
||||
void *cb_data);
|
||||
|
||||
int isci_task_execute_tmf(
|
||||
struct isci_host *isci_host,
|
||||
struct isci_tmf *tmf,
|
||||
unsigned long timeout_ms);
|
||||
|
||||
/**
|
||||
* enum isci_completion_selection - This enum defines the possible actions to
|
||||
* take with respect to a given request's notification back to libsas.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum isci_completion_selection {
|
||||
|
||||
isci_perform_normal_io_completion, /* Normal notify (task_done) */
|
||||
isci_perform_aborted_io_completion, /* No notification. */
|
||||
isci_perform_error_io_completion /* Use sas_task_abort */
|
||||
};
|
||||
|
||||
static inline void isci_set_task_doneflags(
|
||||
struct sas_task *task)
|
||||
{
|
||||
/* Since no futher action will be taken on this task,
|
||||
* make sure to mark it complete from the lldd perspective.
|
||||
*/
|
||||
task->task_state_flags |= SAS_TASK_STATE_DONE;
|
||||
task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
|
||||
task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
|
||||
}
|
||||
/**
|
||||
* isci_task_all_done() - This function clears the task bits to indicate the
|
||||
* LLDD is done with the task.
|
||||
*
|
||||
*
|
||||
*/
|
||||
static inline void isci_task_all_done(
|
||||
struct sas_task *task)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/* Since no futher action will be taken on this task,
|
||||
* make sure to mark it complete from the lldd perspective.
|
||||
*/
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
isci_set_task_doneflags(task);
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* isci_task_set_completion_status() - This function sets the completion status
|
||||
* for the request.
|
||||
* @task: This parameter is the completed request.
|
||||
* @response: This parameter is the response code for the completed task.
|
||||
* @status: This parameter is the status code for the completed task.
|
||||
*
|
||||
* none.
|
||||
*/
|
||||
static inline void isci_task_set_completion_status(
|
||||
struct sas_task *task,
|
||||
enum service_response response,
|
||||
enum exec_status status,
|
||||
enum isci_completion_selection task_notification_selection)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
|
||||
task->task_status.resp = response;
|
||||
task->task_status.stat = status;
|
||||
|
||||
/* Don't set DONE (or clear AT_INITIATOR) for any task going into the
|
||||
* error path, because the EH interprets that as a handled error condition.
|
||||
* Also don't take action if there is a reset pending.
|
||||
*/
|
||||
if ((task_notification_selection != isci_perform_error_io_completion)
|
||||
&& !(task->task_state_flags & SAS_TASK_NEED_DEV_RESET))
|
||||
isci_set_task_doneflags(task);
|
||||
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
}
|
||||
/**
|
||||
* isci_task_complete_for_upper_layer() - This function completes the request
|
||||
* to the upper layer driver.
|
||||
* @host: This parameter is a pointer to the host on which the the request
|
||||
* should be queued (either as an error or success).
|
||||
* @request: This parameter is the completed request.
|
||||
* @response: This parameter is the response code for the completed task.
|
||||
* @status: This parameter is the status code for the completed task.
|
||||
*
|
||||
* none.
|
||||
*/
|
||||
static inline void isci_task_complete_for_upper_layer(
|
||||
struct sas_task *task,
|
||||
enum service_response response,
|
||||
enum exec_status status,
|
||||
enum isci_completion_selection task_notification_selection)
|
||||
{
|
||||
isci_task_set_completion_status(task, response, status,
|
||||
task_notification_selection);
|
||||
|
||||
|
||||
/* Tasks aborted specifically by a call to the lldd_abort_task
|
||||
* function should not be completed to the host in the regular path.
|
||||
*/
|
||||
switch (task_notification_selection) {
|
||||
case isci_perform_normal_io_completion:
|
||||
/* Normal notification (task_done) */
|
||||
dev_dbg(task->dev->port->ha->dev,
|
||||
"%s: Normal - task = %p, response=%d, status=%d\n",
|
||||
__func__, task, response, status);
|
||||
task->task_done(task);
|
||||
task->lldd_task = NULL;
|
||||
break;
|
||||
|
||||
case isci_perform_aborted_io_completion:
|
||||
/* No notification because this request is already in the
|
||||
* abort path.
|
||||
*/
|
||||
dev_warn(task->dev->port->ha->dev,
|
||||
"%s: Aborted - task = %p, response=%d, status=%d\n",
|
||||
__func__, task, response, status);
|
||||
break;
|
||||
|
||||
case isci_perform_error_io_completion:
|
||||
/* Use sas_task_abort */
|
||||
dev_warn(task->dev->port->ha->dev,
|
||||
"%s: Error - task = %p, response=%d, status=%d\n",
|
||||
__func__, task, response, status);
|
||||
sas_task_abort(task);
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_warn(task->dev->port->ha->dev,
|
||||
"%s: isci task notification default case!",
|
||||
__func__);
|
||||
sas_task_abort(task);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !defined(_SCI_TASK_H_) */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user