/* * Scsi Host Layer for MPT (Message Passing Technology) based controllers * * This code is based on drivers/scsi/mpt3sas/mpt3sas_scsih.c * Copyright (C) 2012-2014 LSI Corporation * Copyright (C) 2013-2014 Avago Technologies * (mailto: [email protected]) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * NO WARRANTY * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is * solely responsible for determining the appropriateness of using and * distributing the Program and assumes all risks associated with its * exercise of rights under this Agreement, including but not limited to * the risks and costs of program errors, damage to or loss of data, * programs or equipment, and unavailability or interruption of operations. * DISCLAIMER OF LIABILITY * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/errno.h> #include <linux/blkdev.h> #include <linux/sched.h> #include <linux/workqueue.h> #include <linux/delay.h> #include <linux/pci.h> #include <linux/interrupt.h> #include <linux/raid_class.h> #include <linux/blk-mq-pci.h> #include <linux/unaligned.h> #include "mpt3sas_base.h" #define RAID_CHANNEL … #define PCIE_CHANNEL … /* forward proto's */ static void _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_expander); static void _firmware_event_work(struct work_struct *work); static void _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc, struct _sas_device *sas_device); static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 retry_count, u8 is_pd); static int _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle); static void _scsih_pcie_device_remove_from_sml(struct MPT3SAS_ADAPTER *ioc, struct _pcie_device *pcie_device); static void _scsih_pcie_check_device(struct MPT3SAS_ADAPTER *ioc, u16 handle); static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid); static void _scsih_complete_devices_scanning(struct MPT3SAS_ADAPTER *ioc); /* global parameters */ LIST_HEAD(…); /* global ioc lock for list operations */ DEFINE_SPINLOCK(…); MODULE_AUTHOR(…); MODULE_DESCRIPTION(…); MODULE_LICENSE(…) …; MODULE_VERSION(…); MODULE_ALIAS(…) …; /* local parameters */ static u8 scsi_io_cb_idx = …; static u8 tm_cb_idx = …; static u8 ctl_cb_idx = …; static u8 base_cb_idx = …; static u8 port_enable_cb_idx = …; static u8 transport_cb_idx = …; static u8 scsih_cb_idx = …; static u8 config_cb_idx = …; static int mpt2_ids; static int mpt3_ids; static u8 tm_tr_cb_idx = … ; static u8 tm_tr_volume_cb_idx = … ; static u8 tm_sas_control_cb_idx = …; /* command line options */ static u32 logging_level; MODULE_PARM_DESC(…) …; static ushort max_sectors = …; module_param(max_sectors, ushort, 0444); MODULE_PARM_DESC(…) …; static int missing_delay[2] = …; module_param_array(…); MODULE_PARM_DESC(…) …; /* scsi-mid layer global parmeter is max_report_luns, which is 511 */ #define MPT3SAS_MAX_LUN … static u64 max_lun = …; module_param(max_lun, ullong, 0444); MODULE_PARM_DESC(…) …; static ushort hbas_to_enumerate; module_param(hbas_to_enumerate, ushort, 0444); MODULE_PARM_DESC(…) …; /* diag_buffer_enable is bitwise * bit 0 set = TRACE * bit 1 set = SNAPSHOT * bit 2 set = EXTENDED * * Either bit can be set, or both */ static int diag_buffer_enable = …; module_param(diag_buffer_enable, int, 0444); MODULE_PARM_DESC(…) …; static int disable_discovery = …; module_param(disable_discovery, int, 0444); MODULE_PARM_DESC(…) …; /* permit overriding the host protection capabilities mask (EEDP/T10 PI) */ static int prot_mask = …; module_param(prot_mask, int, 0444); MODULE_PARM_DESC(…) …; static bool enable_sdev_max_qd; module_param(enable_sdev_max_qd, bool, 0444); MODULE_PARM_DESC(…) …; static int multipath_on_hba = …; module_param(multipath_on_hba, int, 0); MODULE_PARM_DESC(…) …; static int host_tagset_enable = …; module_param(host_tagset_enable, int, 0444); MODULE_PARM_DESC(…) …; /* raid transport support */ static struct raid_template *mpt3sas_raid_template; static struct raid_template *mpt2sas_raid_template; /** * struct sense_info - common structure for obtaining sense keys * @skey: sense key * @asc: additional sense code * @ascq: additional sense code qualifier */ struct sense_info { … }; #define MPT3SAS_PROCESS_TRIGGER_DIAG … #define MPT3SAS_TURN_ON_PFA_LED … #define MPT3SAS_PORT_ENABLE_COMPLETE … #define MPT3SAS_ABRT_TASK_SET … #define MPT3SAS_REMOVE_UNRESPONDING_DEVICES … /** * struct fw_event_work - firmware event struct * @list: link list framework * @work: work object (ioc->fault_reset_work_q) * @ioc: per adapter object * @device_handle: device handle * @VF_ID: virtual function id * @VP_ID: virtual port id * @ignore: flag meaning this event has been marked to ignore * @event: firmware event MPI2_EVENT_XXX defined in mpi2_ioc.h * @refcount: kref for this event * @event_data: reply event data payload follows * * This object stored on ioc->fw_event_list. */ struct fw_event_work { … }; static void fw_event_work_free(struct kref *r) { … } static void fw_event_work_get(struct fw_event_work *fw_work) { … } static void fw_event_work_put(struct fw_event_work *fw_work) { … } static struct fw_event_work *alloc_fw_event_work(int len) { … } /** * struct _scsi_io_transfer - scsi io transfer * @handle: sas device handle (assigned by firmware) * @is_raid: flag set for hidden raid components * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE, * @data_length: data transfer length * @data_dma: dma pointer to data * @sense: sense data * @lun: lun number * @cdb_length: cdb length * @cdb: cdb contents * @timeout: timeout for this command * @VF_ID: virtual function id * @VP_ID: virtual port id * @valid_reply: flag set for reply message * @sense_length: sense length * @ioc_status: ioc status * @scsi_state: scsi state * @scsi_status: scsi staus * @log_info: log information * @transfer_length: data length transfer when there is a reply message * * Used for sending internal scsi commands to devices within this module. * Refer to _scsi_send_scsi_io(). */ struct _scsi_io_transfer { … }; /** * _scsih_set_debug_level - global setting of ioc->logging_level. * @val: value of the parameter to be set * @kp: pointer to kernel_param structure * * Note: The logging levels are defined in mpt3sas_debug.h. */ static int _scsih_set_debug_level(const char *val, const struct kernel_param *kp) { … } module_param_call(…); /** * _scsih_srch_boot_sas_address - search based on sas_address * @sas_address: sas address * @boot_device: boot device object from bios page 2 * * Return: 1 when there's a match, 0 means no match. */ static inline int _scsih_srch_boot_sas_address(u64 sas_address, Mpi2BootDeviceSasWwid_t *boot_device) { … } /** * _scsih_srch_boot_device_name - search based on device name * @device_name: device name specified in INDENTIFY fram * @boot_device: boot device object from bios page 2 * * Return: 1 when there's a match, 0 means no match. */ static inline int _scsih_srch_boot_device_name(u64 device_name, Mpi2BootDeviceDeviceName_t *boot_device) { … } /** * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot * @enclosure_logical_id: enclosure logical id * @slot_number: slot number * @boot_device: boot device object from bios page 2 * * Return: 1 when there's a match, 0 means no match. */ static inline int _scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number, Mpi2BootDeviceEnclosureSlot_t *boot_device) { … } /** * mpt3sas_get_port_by_id - get hba port entry corresponding to provided * port number from port list * @ioc: per adapter object * @port_id: port number * @bypass_dirty_port_flag: when set look the matching hba port entry even * if hba port entry is marked as dirty. * * Search for hba port entry corresponding to provided port number, * if available return port object otherwise return NULL. */ struct hba_port * mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port_id, u8 bypass_dirty_port_flag) { … } /** * mpt3sas_get_vphy_by_phy - get virtual_phy object corresponding to phy number * @ioc: per adapter object * @port: hba_port object * @phy: phy number * * Return virtual_phy object corresponding to phy number. */ struct virtual_phy * mpt3sas_get_vphy_by_phy(struct MPT3SAS_ADAPTER *ioc, struct hba_port *port, u32 phy) { … } /** * _scsih_is_boot_device - search for matching boot device. * @sas_address: sas address * @device_name: device name specified in INDENTIFY fram * @enclosure_logical_id: enclosure logical id * @slot: slot number * @form: specifies boot device form * @boot_device: boot device object from bios page 2 * * Return: 1 when there's a match, 0 means no match. */ static int _scsih_is_boot_device(u64 sas_address, u64 device_name, u64 enclosure_logical_id, u16 slot, u8 form, Mpi2BiosPage2BootDevice_t *boot_device) { … } /** * _scsih_get_sas_address - set the sas_address for given device handle * @ioc: ? * @handle: device handle * @sas_address: sas address * * Return: 0 success, non-zero when failure */ static int _scsih_get_sas_address(struct MPT3SAS_ADAPTER *ioc, u16 handle, u64 *sas_address) { … } /** * _scsih_determine_boot_device - determine boot device. * @ioc: per adapter object * @device: sas_device or pcie_device object * @channel: SAS or PCIe channel * * Determines whether this device should be first reported device to * to scsi-ml or sas transport, this purpose is for persistent boot device. * There are primary, alternate, and current entries in bios page 2. The order * priority is primary, alternate, then current. This routine saves * the corresponding device object. * The saved data to be used later in _scsih_probe_boot_devices(). */ static void _scsih_determine_boot_device(struct MPT3SAS_ADAPTER *ioc, void *device, u32 channel) { … } static struct _sas_device * __mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc, struct MPT3SAS_TARGET *tgt_priv) { … } static struct _sas_device * mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc, struct MPT3SAS_TARGET *tgt_priv) { … } static struct _pcie_device * __mpt3sas_get_pdev_from_target(struct MPT3SAS_ADAPTER *ioc, struct MPT3SAS_TARGET *tgt_priv) { … } /** * mpt3sas_get_pdev_from_target - pcie device search * @ioc: per adapter object * @tgt_priv: starget private object * * Context: This function will acquire ioc->pcie_device_lock and will release * before returning the pcie_device object. * * This searches for pcie_device from target, then return pcie_device object. */ static struct _pcie_device * mpt3sas_get_pdev_from_target(struct MPT3SAS_ADAPTER *ioc, struct MPT3SAS_TARGET *tgt_priv) { … } /** * __mpt3sas_get_sdev_by_rphy - sas device search * @ioc: per adapter object * @rphy: sas_rphy pointer * * Context: This function will acquire ioc->sas_device_lock and will release * before returning the sas_device object. * * This searches for sas_device from rphy object * then return sas_device object. */ struct _sas_device * __mpt3sas_get_sdev_by_rphy(struct MPT3SAS_ADAPTER *ioc, struct sas_rphy *rphy) { … } /** * __mpt3sas_get_sdev_by_addr - get _sas_device object corresponding to provided * sas address from sas_device_list list * @ioc: per adapter object * @sas_address: device sas address * @port: port number * * Search for _sas_device object corresponding to provided sas address, * if available return _sas_device object address otherwise return NULL. */ struct _sas_device * __mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, struct hba_port *port) { … } /** * mpt3sas_get_sdev_by_addr - sas device search * @ioc: per adapter object * @sas_address: sas address * @port: hba port entry * Context: Calling function should acquire ioc->sas_device_lock * * This searches for sas_device based on sas_address & port number, * then return sas_device object. */ struct _sas_device * mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, struct hba_port *port) { … } static struct _sas_device * __mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * mpt3sas_get_sdev_by_handle - sas device search * @ioc: per adapter object * @handle: sas device handle (assigned by firmware) * Context: Calling function should acquire ioc->sas_device_lock * * This searches for sas_device based on sas_address, then return sas_device * object. */ struct _sas_device * mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * _scsih_display_enclosure_chassis_info - display device location info * @ioc: per adapter object * @sas_device: per sas device object * @sdev: scsi device struct * @starget: scsi target struct */ static void _scsih_display_enclosure_chassis_info(struct MPT3SAS_ADAPTER *ioc, struct _sas_device *sas_device, struct scsi_device *sdev, struct scsi_target *starget) { … } /** * _scsih_sas_device_remove - remove sas_device from list. * @ioc: per adapter object * @sas_device: the sas_device object * Context: This function will acquire ioc->sas_device_lock. * * If sas_device is on the list, remove it and decrement its reference count. */ static void _scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc, struct _sas_device *sas_device) { … } /** * _scsih_device_remove_by_handle - removing device object by handle * @ioc: per adapter object * @handle: device handle */ static void _scsih_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * mpt3sas_device_remove_by_sas_address - removing device object by * sas address & port number * @ioc: per adapter object * @sas_address: device sas_address * @port: hba port entry * * Return nothing. */ void mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, struct hba_port *port) { … } /** * _scsih_sas_device_add - insert sas_device to the list. * @ioc: per adapter object * @sas_device: the sas_device object * Context: This function will acquire ioc->sas_device_lock. * * Adding new object to the ioc->sas_device_list. */ static void _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc, struct _sas_device *sas_device) { … } /** * _scsih_sas_device_init_add - insert sas_device to the list. * @ioc: per adapter object * @sas_device: the sas_device object * Context: This function will acquire ioc->sas_device_lock. * * Adding new object at driver load time to the ioc->sas_device_init_list. */ static void _scsih_sas_device_init_add(struct MPT3SAS_ADAPTER *ioc, struct _sas_device *sas_device) { … } static struct _pcie_device * __mpt3sas_get_pdev_by_wwid(struct MPT3SAS_ADAPTER *ioc, u64 wwid) { … } /** * mpt3sas_get_pdev_by_wwid - pcie device search * @ioc: per adapter object * @wwid: wwid * * Context: This function will acquire ioc->pcie_device_lock and will release * before returning the pcie_device object. * * This searches for pcie_device based on wwid, then return pcie_device object. */ static struct _pcie_device * mpt3sas_get_pdev_by_wwid(struct MPT3SAS_ADAPTER *ioc, u64 wwid) { … } static struct _pcie_device * __mpt3sas_get_pdev_by_idchannel(struct MPT3SAS_ADAPTER *ioc, int id, int channel) { … } static struct _pcie_device * __mpt3sas_get_pdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * mpt3sas_get_pdev_by_handle - pcie device search * @ioc: per adapter object * @handle: Firmware device handle * * Context: This function will acquire ioc->pcie_device_lock and will release * before returning the pcie_device object. * * This searches for pcie_device based on handle, then return pcie_device * object. */ struct _pcie_device * mpt3sas_get_pdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * _scsih_set_nvme_max_shutdown_latency - Update max_shutdown_latency. * @ioc: per adapter object * Context: This function will acquire ioc->pcie_device_lock * * Update ioc->max_shutdown_latency to that NVMe drives RTD3 Entry Latency * which has reported maximum among all available NVMe drives. * Minimum max_shutdown_latency will be six seconds. */ static void _scsih_set_nvme_max_shutdown_latency(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_pcie_device_remove - remove pcie_device from list. * @ioc: per adapter object * @pcie_device: the pcie_device object * Context: This function will acquire ioc->pcie_device_lock. * * If pcie_device is on the list, remove it and decrement its reference count. */ static void _scsih_pcie_device_remove(struct MPT3SAS_ADAPTER *ioc, struct _pcie_device *pcie_device) { … } /** * _scsih_pcie_device_remove_by_handle - removing pcie device object by handle * @ioc: per adapter object * @handle: device handle */ static void _scsih_pcie_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * _scsih_pcie_device_add - add pcie_device object * @ioc: per adapter object * @pcie_device: pcie_device object * * This is added to the pcie_device_list link list. */ static void _scsih_pcie_device_add(struct MPT3SAS_ADAPTER *ioc, struct _pcie_device *pcie_device) { … } /* * _scsih_pcie_device_init_add - insert pcie_device to the init list. * @ioc: per adapter object * @pcie_device: the pcie_device object * Context: This function will acquire ioc->pcie_device_lock. * * Adding new object at driver load time to the ioc->pcie_device_init_list. */ static void _scsih_pcie_device_init_add(struct MPT3SAS_ADAPTER *ioc, struct _pcie_device *pcie_device) { … } /** * _scsih_raid_device_find_by_id - raid device search * @ioc: per adapter object * @id: sas device target id * @channel: sas device channel * Context: Calling function should acquire ioc->raid_device_lock * * This searches for raid_device based on target id, then return raid_device * object. */ static struct _raid_device * _scsih_raid_device_find_by_id(struct MPT3SAS_ADAPTER *ioc, int id, int channel) { … } /** * mpt3sas_raid_device_find_by_handle - raid device search * @ioc: per adapter object * @handle: sas device handle (assigned by firmware) * Context: Calling function should acquire ioc->raid_device_lock * * This searches for raid_device based on handle, then return raid_device * object. */ struct _raid_device * mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * _scsih_raid_device_find_by_wwid - raid device search * @ioc: per adapter object * @wwid: ? * Context: Calling function should acquire ioc->raid_device_lock * * This searches for raid_device based on wwid, then return raid_device * object. */ static struct _raid_device * _scsih_raid_device_find_by_wwid(struct MPT3SAS_ADAPTER *ioc, u64 wwid) { … } /** * _scsih_raid_device_add - add raid_device object * @ioc: per adapter object * @raid_device: raid_device object * * This is added to the raid_device_list link list. */ static void _scsih_raid_device_add(struct MPT3SAS_ADAPTER *ioc, struct _raid_device *raid_device) { … } /** * _scsih_raid_device_remove - delete raid_device object * @ioc: per adapter object * @raid_device: raid_device object * */ static void _scsih_raid_device_remove(struct MPT3SAS_ADAPTER *ioc, struct _raid_device *raid_device) { … } /** * mpt3sas_scsih_expander_find_by_handle - expander device search * @ioc: per adapter object * @handle: expander handle (assigned by firmware) * Context: Calling function should acquire ioc->sas_device_lock * * This searches for expander device based on handle, then returns the * sas_node object. */ struct _sas_node * mpt3sas_scsih_expander_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * mpt3sas_scsih_enclosure_find_by_handle - exclosure device search * @ioc: per adapter object * @handle: enclosure handle (assigned by firmware) * Context: Calling function should acquire ioc->sas_device_lock * * This searches for enclosure device based on handle, then returns the * enclosure object. */ static struct _enclosure_node * mpt3sas_scsih_enclosure_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * mpt3sas_scsih_expander_find_by_sas_address - expander device search * @ioc: per adapter object * @sas_address: sas address * @port: hba port entry * Context: Calling function should acquire ioc->sas_node_lock. * * This searches for expander device based on sas_address & port number, * then returns the sas_node object. */ struct _sas_node * mpt3sas_scsih_expander_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, struct hba_port *port) { … } /** * _scsih_expander_node_add - insert expander device to the list. * @ioc: per adapter object * @sas_expander: the sas_device object * Context: This function will acquire ioc->sas_node_lock. * * Adding new object to the ioc->sas_expander_list. */ static void _scsih_expander_node_add(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_expander) { … } /** * _scsih_is_end_device - determines if device is an end device * @device_info: bitfield providing information about the device. * Context: none * * Return: 1 if end device. */ static int _scsih_is_end_device(u32 device_info) { … } /** * _scsih_is_nvme_pciescsi_device - determines if * device is an pcie nvme/scsi device * @device_info: bitfield providing information about the device. * Context: none * * Returns 1 if device is pcie device type nvme/scsi. */ static int _scsih_is_nvme_pciescsi_device(u32 device_info) { … } /** * _scsih_scsi_lookup_find_by_target - search for matching channel:id * @ioc: per adapter object * @id: target id * @channel: channel * Context: This function will acquire ioc->scsi_lookup_lock. * * This will search for a matching channel:id in the scsi_lookup array, * returning 1 if found. */ static u8 _scsih_scsi_lookup_find_by_target(struct MPT3SAS_ADAPTER *ioc, int id, int channel) { … } /** * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun * @ioc: per adapter object * @id: target id * @lun: lun number * @channel: channel * Context: This function will acquire ioc->scsi_lookup_lock. * * This will search for a matching channel:id:lun in the scsi_lookup array, * returning 1 if found. */ static u8 _scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id, unsigned int lun, int channel) { … } /** * mpt3sas_scsih_scsi_lookup_get - returns scmd entry * @ioc: per adapter object * @smid: system request message index * * Return: the smid stored scmd pointer. * Then will dereference the stored scmd pointer. */ struct scsi_cmnd * mpt3sas_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * scsih_change_queue_depth - setting device queue depth * @sdev: scsi device struct * @qdepth: requested queue depth * * Return: queue depth. */ static int scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) { … } /** * mpt3sas_scsih_change_queue_depth - setting device queue depth * @sdev: scsi device struct * @qdepth: requested queue depth * * Returns nothing. */ void mpt3sas_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) { … } /** * scsih_target_alloc - target add routine * @starget: scsi target struct * * Return: 0 if ok. Any other return is assumed to be an error and * the device is ignored. */ static int scsih_target_alloc(struct scsi_target *starget) { … } /** * scsih_target_destroy - target destroy routine * @starget: scsi target struct */ static void scsih_target_destroy(struct scsi_target *starget) { … } /** * scsih_slave_alloc - device add routine * @sdev: scsi device struct * * Return: 0 if ok. Any other return is assumed to be an error and * the device is ignored. */ static int scsih_slave_alloc(struct scsi_device *sdev) { … } /** * scsih_slave_destroy - device destroy routine * @sdev: scsi device struct */ static void scsih_slave_destroy(struct scsi_device *sdev) { … } /** * _scsih_display_sata_capabilities - sata capabilities * @ioc: per adapter object * @handle: device handle * @sdev: scsi device struct */ static void _scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc, u16 handle, struct scsi_device *sdev) { … } /* * raid transport support - * Enabled for SLES11 and newer, in older kernels the driver will panic when * unloading the driver followed by a load - I believe that the subroutine * raid_class_release() is not cleaning up properly. */ /** * scsih_is_raid - return boolean indicating device is raid volume * @dev: the device struct object */ static int scsih_is_raid(struct device *dev) { … } static int scsih_is_nvme(struct device *dev) { … } /** * scsih_get_resync - get raid volume resync percent complete * @dev: the device struct object */ static void scsih_get_resync(struct device *dev) { … } /** * scsih_get_state - get raid volume level * @dev: the device struct object */ static void scsih_get_state(struct device *dev) { … } /** * _scsih_set_level - set raid level * @ioc: ? * @sdev: scsi device struct * @volume_type: volume type */ static void _scsih_set_level(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev, u8 volume_type) { … } /** * _scsih_get_volume_capabilities - volume capabilities * @ioc: per adapter object * @raid_device: the raid_device object * * Return: 0 for success, else 1 */ static int _scsih_get_volume_capabilities(struct MPT3SAS_ADAPTER *ioc, struct _raid_device *raid_device) { … } /** * _scsih_enable_tlr - setting TLR flags * @ioc: per adapter object * @sdev: scsi device struct * * Enabling Transaction Layer Retries for tape devices when * vpd page 0x90 is present * */ static void _scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev) { … } /** * scsih_device_configure - device configure routine. * @sdev: scsi device struct * @lim: queue limits * * Return: 0 if ok. Any other return is assumed to be an error and * the device is ignored. */ static int scsih_device_configure(struct scsi_device *sdev, struct queue_limits *lim) { … } /** * scsih_bios_param - fetch head, sector, cylinder info for a disk * @sdev: scsi device struct * @bdev: pointer to block device context * @capacity: device size (in 512 byte sectors) * @params: three element array to place output: * params[0] number of heads (max 255) * params[1] number of sectors (max 63) * params[2] number of cylinders */ static int scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int params[]) { … } /** * _scsih_response_code - translation of device response code * @ioc: per adapter object * @response_code: response code returned by the device */ static void _scsih_response_code(struct MPT3SAS_ADAPTER *ioc, u8 response_code) { … } /** * _scsih_tm_done - tm completion routine * @ioc: per adapter object * @smid: system request message index * @msix_index: MSIX table index supplied by the OS * @reply: reply message frame(lower 32bit addr) * Context: none. * * The callback handler when using scsih_issue_tm. * * Return: 1 meaning mf should be freed from _base_interrupt * 0 means the mf is freed from this function. */ static u8 _scsih_tm_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) { … } /** * mpt3sas_scsih_set_tm_flag - set per target tm_busy * @ioc: per adapter object * @handle: device handle * * During taskmangement request, we need to freeze the device queue. */ void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * mpt3sas_scsih_clear_tm_flag - clear per target tm_busy * @ioc: per adapter object * @handle: device handle * * During taskmangement request, we need to freeze the device queue. */ void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * scsih_tm_cmd_map_status - map the target reset & LUN reset TM status * @ioc: per adapter object * @channel: the channel assigned by the OS * @id: the id assigned by the OS * @lun: lun number * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h) * @smid_task: smid assigned to the task * * Look whether TM has aborted the timed out SCSI command, if * TM has aborted the IO then return SUCCESS else return FAILED. */ static int scsih_tm_cmd_map_status(struct MPT3SAS_ADAPTER *ioc, uint channel, uint id, uint lun, u8 type, u16 smid_task) { … } /** * scsih_tm_post_processing - post processing of target & LUN reset * @ioc: per adapter object * @handle: device handle * @channel: the channel assigned by the OS * @id: the id assigned by the OS * @lun: lun number * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h) * @smid_task: smid assigned to the task * * Post processing of target & LUN reset. Due to interrupt latency * issue it possible that interrupt for aborted IO might not be * received yet. So before returning failure status, poll the * reply descriptor pools for the reply of timed out SCSI command. * Return FAILED status if reply for timed out is not received * otherwise return SUCCESS. */ static int scsih_tm_post_processing(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel, uint id, uint lun, u8 type, u16 smid_task) { … } /** * mpt3sas_scsih_issue_tm - main routine for sending tm requests * @ioc: per adapter struct * @handle: device handle * @channel: the channel assigned by the OS * @id: the id assigned by the OS * @lun: lun number * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h) * @smid_task: smid assigned to the task * @msix_task: MSIX table index supplied by the OS * @timeout: timeout in seconds * @tr_method: Target Reset Method * Context: user * * A generic API for sending task management requests to firmware. * * The callback index is set inside `ioc->tm_cb_idx`. * The caller is responsible to check for outstanding commands. * * Return: SUCCESS or FAILED. */ int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel, uint id, u64 lun, u8 type, u16 smid_task, u16 msix_task, u8 timeout, u8 tr_method) { … } int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel, uint id, u64 lun, u8 type, u16 smid_task, u16 msix_task, u8 timeout, u8 tr_method) { … } /** * _scsih_tm_display_info - displays info about the device * @ioc: per adapter struct * @scmd: pointer to scsi command object * * Called by task management callback handlers. */ static void _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) { … } /** * scsih_abort - eh threads main abort routine * @scmd: pointer to scsi command object * * Return: SUCCESS if command aborted else FAILED */ static int scsih_abort(struct scsi_cmnd *scmd) { … } /** * scsih_dev_reset - eh threads main device reset routine * @scmd: pointer to scsi command object * * Return: SUCCESS if command aborted else FAILED */ static int scsih_dev_reset(struct scsi_cmnd *scmd) { … } /** * scsih_target_reset - eh threads main target reset routine * @scmd: pointer to scsi command object * * Return: SUCCESS if command aborted else FAILED */ static int scsih_target_reset(struct scsi_cmnd *scmd) { … } /** * scsih_host_reset - eh threads main host reset routine * @scmd: pointer to scsi command object * * Return: SUCCESS if command aborted else FAILED */ static int scsih_host_reset(struct scsi_cmnd *scmd) { … } /** * _scsih_fw_event_add - insert and queue up fw_event * @ioc: per adapter object * @fw_event: object describing the event * Context: This function will acquire ioc->fw_event_lock. * * This adds the firmware event object into link list, then queues it up to * be processed from user context. */ static void _scsih_fw_event_add(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * _scsih_fw_event_del_from_list - delete fw_event from the list * @ioc: per adapter object * @fw_event: object describing the event * Context: This function will acquire ioc->fw_event_lock. * * If the fw_event is on the fw_event_list, remove it and do a put. */ static void _scsih_fw_event_del_from_list(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * mpt3sas_send_trigger_data_event - send event for processing trigger data * @ioc: per adapter object * @event_data: trigger event data */ void mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc, struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data) { … } /** * _scsih_error_recovery_delete_devices - remove devices not responding * @ioc: per adapter object */ static void _scsih_error_recovery_delete_devices(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_port_enable_complete - port enable completed (fake event) * @ioc: per adapter object */ void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc) { … } static struct fw_event_work *dequeue_next_fw_event(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_fw_event_cleanup_queue - cleanup event queue * @ioc: per adapter object * * Walk the firmware event queue, either killing timers, or waiting * for outstanding events to complete * * Context: task, can sleep */ static void _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_internal_device_block - block the sdev device * @sdev: per device object * @sas_device_priv_data : per device driver private data * * make sure device is blocked without error, if not * print an error */ static void _scsih_internal_device_block(struct scsi_device *sdev, struct MPT3SAS_DEVICE *sas_device_priv_data) { … } /** * _scsih_internal_device_unblock - unblock the sdev device * @sdev: per device object * @sas_device_priv_data : per device driver private data * make sure device is unblocked without error, if not retry * by blocking and then unblocking */ static void _scsih_internal_device_unblock(struct scsi_device *sdev, struct MPT3SAS_DEVICE *sas_device_priv_data) { … } /** * _scsih_ublock_io_all_device - unblock every device * @ioc: per adapter object * * change the device state from block to running */ static void _scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_ublock_io_device - prepare device to be deleted * @ioc: per adapter object * @sas_address: sas address * @port: hba port entry * * unblock then put device in offline state */ static void _scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, struct hba_port *port) { … } /** * _scsih_block_io_all_device - set the device state to SDEV_BLOCK * @ioc: per adapter object * * During device pull we need to appropriately set the sdev state. */ static void _scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_block_io_device - set the device state to SDEV_BLOCK * @ioc: per adapter object * @handle: device handle * * During device pull we need to appropriately set the sdev state. */ static void _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * _scsih_block_io_to_children_attached_to_ex * @ioc: per adapter object * @sas_expander: the sas_device object * * This routine set sdev state to SDEV_BLOCK for all devices * attached to this expander. This function called when expander is * pulled. */ static void _scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_expander) { … } /** * _scsih_block_io_to_children_attached_directly * @ioc: per adapter object * @event_data: topology change event data * * This routine set sdev state to SDEV_BLOCK for all devices * direct attached during device pull. */ static void _scsih_block_io_to_children_attached_directly(struct MPT3SAS_ADAPTER *ioc, Mpi2EventDataSasTopologyChangeList_t *event_data) { … } /** * _scsih_block_io_to_pcie_children_attached_directly * @ioc: per adapter object * @event_data: topology change event data * * This routine set sdev state to SDEV_BLOCK for all devices * direct attached during device pull/reconnect. */ static void _scsih_block_io_to_pcie_children_attached_directly(struct MPT3SAS_ADAPTER *ioc, Mpi26EventDataPCIeTopologyChangeList_t *event_data) { … } /** * _scsih_tm_tr_send - send task management request * @ioc: per adapter object * @handle: device handle * Context: interrupt time. * * This code is to initiate the device removal handshake protocol * with controller firmware. This function will issue target reset * using high priority request queue. It will send a sas iounit * control request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion. * * This is designed to send muliple task management request at the same * time to the fifo. If the fifo is full, we will append the request, * and process it in a future completion. */ static void _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * _scsih_tm_tr_complete - * @ioc: per adapter object * @smid: system request message index * @msix_index: MSIX table index supplied by the OS * @reply: reply message frame(lower 32bit addr) * Context: interrupt time. * * This is the target reset completion routine. * This code is part of the code to initiate the device removal * handshake protocol with controller firmware. * It will send a sas iounit control request (MPI2_SAS_OP_REMOVE_DEVICE) * * Return: 1 meaning mf should be freed from _base_interrupt * 0 means the mf is freed from this function. */ static u8 _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) { … } /** _scsih_allow_scmd_to_device - check whether scmd needs to * issue to IOC or not. * @ioc: per adapter object * @scmd: pointer to scsi command object * * Returns true if scmd can be issued to IOC otherwise returns false. */ inline bool _scsih_allow_scmd_to_device(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) { … } /** * _scsih_sas_control_complete - completion routine * @ioc: per adapter object * @smid: system request message index * @msix_index: MSIX table index supplied by the OS * @reply: reply message frame(lower 32bit addr) * Context: interrupt time. * * This is the sas iounit control completion routine. * This code is part of the code to initiate the device removal * handshake protocol with controller firmware. * * Return: 1 meaning mf should be freed from _base_interrupt * 0 means the mf is freed from this function. */ static u8 _scsih_sas_control_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) { … } /** * _scsih_tm_tr_volume_send - send target reset request for volumes * @ioc: per adapter object * @handle: device handle * Context: interrupt time. * * This is designed to send muliple task management request at the same * time to the fifo. If the fifo is full, we will append the request, * and process it in a future completion. */ static void _scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * _scsih_tm_volume_tr_complete - target reset completion * @ioc: per adapter object * @smid: system request message index * @msix_index: MSIX table index supplied by the OS * @reply: reply message frame(lower 32bit addr) * Context: interrupt time. * * Return: 1 meaning mf should be freed from _base_interrupt * 0 means the mf is freed from this function. */ static u8 _scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) { … } /** * _scsih_issue_delayed_event_ack - issue delayed Event ACK messages * @ioc: per adapter object * @smid: system request message index * @event: Event ID * @event_context: used to track events uniquely * * Context - processed in interrupt context. */ static void _scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, U16 event, U32 event_context) { … } /** * _scsih_issue_delayed_sas_io_unit_ctrl - issue delayed * sas_io_unit_ctrl messages * @ioc: per adapter object * @smid: system request message index * @handle: device handle * * Context - processed in interrupt context. */ static void _scsih_issue_delayed_sas_io_unit_ctrl(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) { … } /** * mpt3sas_check_for_pending_internal_cmds - check for pending internal messages * @ioc: per adapter object * @smid: system request message index * * Context: Executed in interrupt context * * This will check delayed internal messages list, and process the * next request. * * Return: 1 meaning mf should be freed from _base_interrupt * 0 means the mf is freed from this function. */ u8 mpt3sas_check_for_pending_internal_cmds(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * _scsih_check_for_pending_tm - check for pending task management * @ioc: per adapter object * @smid: system request message index * * This will check delayed target reset list, and feed the * next reqeust. * * Return: 1 meaning mf should be freed from _base_interrupt * 0 means the mf is freed from this function. */ static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * _scsih_check_topo_delete_events - sanity check on topo events * @ioc: per adapter object * @event_data: the event data payload * * This routine added to better handle cable breaker. * * This handles the case where driver receives multiple expander * add and delete events in a single shot. When there is a delete event * the routine will void any pending add events waiting in the event queue. */ static void _scsih_check_topo_delete_events(struct MPT3SAS_ADAPTER *ioc, Mpi2EventDataSasTopologyChangeList_t *event_data) { … } /** * _scsih_check_pcie_topo_remove_events - sanity check on topo * events * @ioc: per adapter object * @event_data: the event data payload * * This handles the case where driver receives multiple switch * or device add and delete events in a single shot. When there * is a delete event the routine will void any pending add * events waiting in the event queue. */ static void _scsih_check_pcie_topo_remove_events(struct MPT3SAS_ADAPTER *ioc, Mpi26EventDataPCIeTopologyChangeList_t *event_data) { … } /** * _scsih_set_volume_delete_flag - setting volume delete flag * @ioc: per adapter object * @handle: device handle * * This returns nothing. */ static void _scsih_set_volume_delete_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * _scsih_set_volume_handle_for_tr - set handle for target reset to volume * @handle: input handle * @a: handle for volume a * @b: handle for volume b * * IR firmware only supports two raid volumes. The purpose of this * routine is to set the volume handle in either a or b. When the given * input handle is non-zero, or when a and b have not been set before. */ static void _scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b) { … } /** * _scsih_check_ir_config_unhide_events - check for UNHIDE events * @ioc: per adapter object * @event_data: the event data payload * Context: interrupt time. * * This routine will send target reset to volume, followed by target * resets to the PDs. This is called when a PD has been removed, or * volume has been deleted or removed. When the target reset is sent * to volume, the PD target resets need to be queued to start upon * completion of the volume target reset. */ static void _scsih_check_ir_config_unhide_events(struct MPT3SAS_ADAPTER *ioc, Mpi2EventDataIrConfigChangeList_t *event_data) { … } /** * _scsih_check_volume_delete_events - set delete flag for volumes * @ioc: per adapter object * @event_data: the event data payload * Context: interrupt time. * * This will handle the case when the cable connected to entire volume is * pulled. We will take care of setting the deleted flag so normal IO will * not be sent. */ static void _scsih_check_volume_delete_events(struct MPT3SAS_ADAPTER *ioc, Mpi2EventDataIrVolume_t *event_data) { … } /** * _scsih_temp_threshold_events - display temperature threshold exceeded events * @ioc: per adapter object * @event_data: the temp threshold event data * Context: interrupt time. */ static void _scsih_temp_threshold_events(struct MPT3SAS_ADAPTER *ioc, Mpi2EventDataTemperature_t *event_data) { … } static int _scsih_set_satl_pending(struct scsi_cmnd *scmd, bool pending) { … } /** * _scsih_flush_running_cmds - completing outstanding commands. * @ioc: per adapter object * * The flushing out of all pending scmd commands following host reset, * where all IO is dropped to the floor. */ static void _scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_setup_eedp - setup MPI request for EEDP transfer * @ioc: per adapter object * @scmd: pointer to scsi command object * @mpi_request: pointer to the SCSI_IO request message frame * * Supporting protection 1 and 3. */ static void _scsih_setup_eedp(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, Mpi25SCSIIORequest_t *mpi_request) { … } /** * _scsih_eedp_error_handling - return sense code for EEDP errors * @scmd: pointer to scsi command object * @ioc_status: ioc status */ static void _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status) { … } /** * scsih_qcmd - main scsi request entry point * @shost: SCSI host pointer * @scmd: pointer to scsi command object * * The callback index is set inside `ioc->scsi_io_cb_idx`. * * Return: 0 on success. If there's a failure, return either: * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full */ static int scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) { … } /** * _scsih_normalize_sense - normalize descriptor and fixed format sense data * @sense_buffer: sense data returned by target * @data: normalized skey/asc/ascq */ static void _scsih_normalize_sense(char *sense_buffer, struct sense_info *data) { … } /** * _scsih_scsi_ioc_info - translated non-successful SCSI_IO request * @ioc: per adapter object * @scmd: pointer to scsi command object * @mpi_reply: reply mf payload returned from firmware * @smid: ? * * scsi_status - SCSI Status code returned from target device * scsi_state - state info associated with SCSI_IO determined by ioc * ioc_status - ioc supplied status info */ static void _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, Mpi2SCSIIOReply_t *mpi_reply, u16 smid) { … } /** * _scsih_turn_on_pfa_led - illuminate PFA LED * @ioc: per adapter object * @handle: device handle * Context: process */ static void _scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * _scsih_turn_off_pfa_led - turn off Fault LED * @ioc: per adapter object * @sas_device: sas device whose PFA LED has to turned off * Context: process */ static void _scsih_turn_off_pfa_led(struct MPT3SAS_ADAPTER *ioc, struct _sas_device *sas_device) { … } /** * _scsih_send_event_to_turn_on_pfa_led - fire delayed event * @ioc: per adapter object * @handle: device handle * Context: interrupt. */ static void _scsih_send_event_to_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * _scsih_smart_predicted_fault - process smart errors * @ioc: per adapter object * @handle: device handle * Context: interrupt. */ static void _scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * _scsih_io_done - scsi request callback * @ioc: per adapter object * @smid: system request message index * @msix_index: MSIX table index supplied by the OS * @reply: reply message frame(lower 32bit addr) * * Callback handler when using _scsih_qcmd. * * Return: 1 meaning mf should be freed from _base_interrupt * 0 means the mf is freed from this function. */ static u8 _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) { … } /** * _scsih_update_vphys_after_reset - update the Port's * vphys_list after reset * @ioc: per adapter object * * Returns nothing. */ static void _scsih_update_vphys_after_reset(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_get_port_table_after_reset - Construct temporary port table * @ioc: per adapter object * @port_table: address where port table needs to be constructed * * return number of HBA port entries available after reset. */ static int _scsih_get_port_table_after_reset(struct MPT3SAS_ADAPTER *ioc, struct hba_port *port_table) { … } enum hba_port_matched_codes { … }; /** * _scsih_look_and_get_matched_port_entry - Get matched hba port entry * from HBA port table * @ioc: per adapter object * @port_entry: hba port entry from temporary port table which needs to be * searched for matched entry in the HBA port table * @matched_port_entry: save matched hba port entry here * @count: count of matched entries * * return type of matched entry found. */ static enum hba_port_matched_codes _scsih_look_and_get_matched_port_entry(struct MPT3SAS_ADAPTER *ioc, struct hba_port *port_entry, struct hba_port **matched_port_entry, int *count) { … } /** * _scsih_del_phy_part_of_anther_port - remove phy if it * is a part of anther port *@ioc: per adapter object *@port_table: port table after reset *@index: hba port entry index *@port_count: number of ports available after host reset *@offset: HBA phy bit offset * */ static void _scsih_del_phy_part_of_anther_port(struct MPT3SAS_ADAPTER *ioc, struct hba_port *port_table, int index, u8 port_count, int offset) { … } /** * _scsih_add_or_del_phys_from_existing_port - add/remove phy to/from * right port *@ioc: per adapter object *@hba_port_entry: hba port table entry *@port_table: temporary port table *@index: hba port entry index *@port_count: number of ports available after host reset * */ static void _scsih_add_or_del_phys_from_existing_port(struct MPT3SAS_ADAPTER *ioc, struct hba_port *hba_port_entry, struct hba_port *port_table, int index, int port_count) { … } /** * _scsih_del_dirty_vphy - delete virtual_phy objects marked as dirty. * @ioc: per adapter object * * Returns nothing. */ static void _scsih_del_dirty_vphy(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_del_dirty_port_entries - delete dirty port entries from port list * after host reset *@ioc: per adapter object * */ static void _scsih_del_dirty_port_entries(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_sas_port_refresh - Update HBA port table after host reset * @ioc: per adapter object */ static void _scsih_sas_port_refresh(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_alloc_vphy - allocate virtual_phy object * @ioc: per adapter object * @port_id: Port ID number * @phy_num: HBA Phy number * * Returns allocated virtual_phy object. */ static struct virtual_phy * _scsih_alloc_vphy(struct MPT3SAS_ADAPTER *ioc, u8 port_id, u8 phy_num) { … } /** * _scsih_sas_host_refresh - refreshing sas host object contents * @ioc: per adapter object * Context: user * * During port enable, fw will send topology events for every device. Its * possible that the handles may change from the previous setting, so this * code keeping handles updating if changed. */ static void _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_sas_host_add - create sas host object * @ioc: per adapter object * * Creating host side data object, stored in ioc->sas_hba */ static void _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_expander_add - creating expander object * @ioc: per adapter object * @handle: expander handle * * Creating expander object, stored in ioc->sas_expander_list. * * Return: 0 for success, else error. */ static int _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * mpt3sas_expander_remove - removing expander object * @ioc: per adapter object * @sas_address: expander sas_address * @port: hba port entry */ void mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, struct hba_port *port) { … } /** * _scsih_done - internal SCSI_IO callback handler. * @ioc: per adapter object * @smid: system request message index * @msix_index: MSIX table index supplied by the OS * @reply: reply message frame(lower 32bit addr) * * Callback handler when sending internal generated SCSI_IO. * The callback index passed is `ioc->scsih_cb_idx` * * Return: 1 meaning mf should be freed from _base_interrupt * 0 means the mf is freed from this function. */ static u8 _scsih_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) { … } #define MPT3_MAX_LUNS … /** * _scsih_check_access_status - check access flags * @ioc: per adapter object * @sas_address: sas address * @handle: sas device handle * @access_status: errors returned during discovery of the device * * Return: 0 for success, else failure */ static u8 _scsih_check_access_status(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, u16 handle, u8 access_status) { … } /** * _scsih_check_device - checking device responsiveness * @ioc: per adapter object * @parent_sas_address: sas address of parent expander or sas host * @handle: attached device handle * @phy_number: phy number * @link_rate: new link rate */ static void _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, u64 parent_sas_address, u16 handle, u8 phy_number, u8 link_rate) { … } /** * _scsih_add_device - creating sas device object * @ioc: per adapter object * @handle: sas device handle * @phy_num: phy number end device attached to * @is_pd: is this hidden raid component * * Creating end device object, stored in ioc->sas_device_list. * * Return: 0 for success, non-zero for failure. */ static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) { … } /** * _scsih_remove_device - removing sas device object * @ioc: per adapter object * @sas_device: the sas_device object */ static void _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc, struct _sas_device *sas_device) { … } /** * _scsih_sas_topology_change_event_debug - debug for topology event * @ioc: per adapter object * @event_data: event data payload * Context: user. */ static void _scsih_sas_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc, Mpi2EventDataSasTopologyChangeList_t *event_data) { … } /** * _scsih_sas_topology_change_event - handle topology changes * @ioc: per adapter object * @fw_event: The fw_event_work object * Context: user. * */ static int _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * _scsih_sas_device_status_change_event_debug - debug for device event * @ioc: ? * @event_data: event data payload * Context: user. */ static void _scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc, Mpi2EventDataSasDeviceStatusChange_t *event_data) { … } /** * _scsih_sas_device_status_change_event - handle device status change * @ioc: per adapter object * @event_data: The fw event * Context: user. */ static void _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc, Mpi2EventDataSasDeviceStatusChange_t *event_data) { … } /** * _scsih_check_pcie_access_status - check access flags * @ioc: per adapter object * @wwid: wwid * @handle: sas device handle * @access_status: errors returned during discovery of the device * * Return: 0 for success, else failure */ static u8 _scsih_check_pcie_access_status(struct MPT3SAS_ADAPTER *ioc, u64 wwid, u16 handle, u8 access_status) { … } /** * _scsih_pcie_device_remove_from_sml - removing pcie device * from SML and free up associated memory * @ioc: per adapter object * @pcie_device: the pcie_device object */ static void _scsih_pcie_device_remove_from_sml(struct MPT3SAS_ADAPTER *ioc, struct _pcie_device *pcie_device) { … } /** * _scsih_pcie_check_device - checking device responsiveness * @ioc: per adapter object * @handle: attached device handle */ static void _scsih_pcie_check_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * _scsih_pcie_add_device - creating pcie device object * @ioc: per adapter object * @handle: pcie device handle * * Creating end device object, stored in ioc->pcie_device_list. * * Return: 1 means queue the event later, 0 means complete the event */ static int _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * _scsih_pcie_topology_change_event_debug - debug for topology * event * @ioc: per adapter object * @event_data: event data payload * Context: user. */ static void _scsih_pcie_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc, Mpi26EventDataPCIeTopologyChangeList_t *event_data) { … } /** * _scsih_pcie_topology_change_event - handle PCIe topology * changes * @ioc: per adapter object * @fw_event: The fw_event_work object * Context: user. * */ static void _scsih_pcie_topology_change_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * _scsih_pcie_device_status_change_event_debug - debug for device event * @ioc: ? * @event_data: event data payload * Context: user. */ static void _scsih_pcie_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc, Mpi26EventDataPCIeDeviceStatusChange_t *event_data) { … } /** * _scsih_pcie_device_status_change_event - handle device status * change * @ioc: per adapter object * @fw_event: The fw_event_work object * Context: user. */ static void _scsih_pcie_device_status_change_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure * event * @ioc: per adapter object * @event_data: event data payload * Context: user. */ static void _scsih_sas_enclosure_dev_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc, Mpi2EventDataSasEnclDevStatusChange_t *event_data) { … } /** * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events * @ioc: per adapter object * @fw_event: The fw_event_work object * Context: user. */ static void _scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * _scsih_sas_broadcast_primitive_event - handle broadcast events * @ioc: per adapter object * @fw_event: The fw_event_work object * Context: user. */ static void _scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * _scsih_sas_discovery_event - handle discovery events * @ioc: per adapter object * @fw_event: The fw_event_work object * Context: user. */ static void _scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * _scsih_sas_device_discovery_error_event - display SAS device discovery error * events * @ioc: per adapter object * @fw_event: The fw_event_work object * Context: user. */ static void _scsih_sas_device_discovery_error_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * _scsih_pcie_enumeration_event - handle enumeration events * @ioc: per adapter object * @fw_event: The fw_event_work object * Context: user. */ static void _scsih_pcie_enumeration_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * _scsih_ir_fastpath - turn on fastpath for IR physdisk * @ioc: per adapter object * @handle: device handle for physical disk * @phys_disk_num: physical disk number * * Return: 0 for success, else failure. */ static int _scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num) { … } /** * _scsih_reprobe_lun - reprobing lun * @sdev: scsi device struct * @no_uld_attach: sdev->no_uld_attach flag setting * **/ static void _scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach) { … } /** * _scsih_sas_volume_add - add new volume * @ioc: per adapter object * @element: IR config element data * Context: user. */ static void _scsih_sas_volume_add(struct MPT3SAS_ADAPTER *ioc, Mpi2EventIrConfigElement_t *element) { … } /** * _scsih_sas_volume_delete - delete volume * @ioc: per adapter object * @handle: volume device handle * Context: user. */ static void _scsih_sas_volume_delete(struct MPT3SAS_ADAPTER *ioc, u16 handle) { … } /** * _scsih_sas_pd_expose - expose pd component to /dev/sdX * @ioc: per adapter object * @element: IR config element data * Context: user. */ static void _scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc, Mpi2EventIrConfigElement_t *element) { … } /** * _scsih_sas_pd_hide - hide pd component from /dev/sdX * @ioc: per adapter object * @element: IR config element data * Context: user. */ static void _scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc, Mpi2EventIrConfigElement_t *element) { … } /** * _scsih_sas_pd_delete - delete pd component * @ioc: per adapter object * @element: IR config element data * Context: user. */ static void _scsih_sas_pd_delete(struct MPT3SAS_ADAPTER *ioc, Mpi2EventIrConfigElement_t *element) { … } /** * _scsih_sas_pd_add - remove pd component * @ioc: per adapter object * @element: IR config element data * Context: user. */ static void _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc, Mpi2EventIrConfigElement_t *element) { … } /** * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events * @ioc: per adapter object * @event_data: event data payload * Context: user. */ static void _scsih_sas_ir_config_change_event_debug(struct MPT3SAS_ADAPTER *ioc, Mpi2EventDataIrConfigChangeList_t *event_data) { … } /** * _scsih_sas_ir_config_change_event - handle ir configuration change events * @ioc: per adapter object * @fw_event: The fw_event_work object * Context: user. */ static void _scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * _scsih_sas_ir_volume_event - IR volume event * @ioc: per adapter object * @fw_event: The fw_event_work object * Context: user. */ static void _scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * _scsih_sas_ir_physical_disk_event - PD event * @ioc: per adapter object * @fw_event: The fw_event_work object * Context: user. */ static void _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * _scsih_sas_ir_operation_status_event_debug - debug for IR op event * @ioc: per adapter object * @event_data: event data payload * Context: user. */ static void _scsih_sas_ir_operation_status_event_debug(struct MPT3SAS_ADAPTER *ioc, Mpi2EventDataIrOperationStatus_t *event_data) { … } /** * _scsih_sas_ir_operation_status_event - handle RAID operation events * @ioc: per adapter object * @fw_event: The fw_event_work object * Context: user. */ static void _scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * _scsih_prep_device_scan - initialize parameters prior to device scan * @ioc: per adapter object * * Set the deleted flag prior to device scan. If the device is found during * the scan, then we clear the deleted flag. */ static void _scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_update_device_qdepth - Update QD during Reset. * @ioc: per adapter object * */ static void _scsih_update_device_qdepth(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_mark_responding_sas_device - mark a sas_devices as responding * @ioc: per adapter object * @sas_device_pg0: SAS Device page 0 * * After host reset, find out whether devices are still responding. * Used in _scsih_remove_unresponsive_sas_devices. */ static void _scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc, Mpi2SasDevicePage0_t *sas_device_pg0) { … } /** * _scsih_create_enclosure_list_after_reset - Free Existing list, * And create enclosure list by scanning all Enclosure Page(0)s * @ioc: per adapter object */ static void _scsih_create_enclosure_list_after_reset(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_search_responding_sas_devices - * @ioc: per adapter object * * After host reset, find out whether devices are still responding. * If not remove. */ static void _scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_mark_responding_pcie_device - mark a pcie_device as responding * @ioc: per adapter object * @pcie_device_pg0: PCIe Device page 0 * * After host reset, find out whether devices are still responding. * Used in _scsih_remove_unresponding_devices. */ static void _scsih_mark_responding_pcie_device(struct MPT3SAS_ADAPTER *ioc, Mpi26PCIeDevicePage0_t *pcie_device_pg0) { … } /** * _scsih_search_responding_pcie_devices - * @ioc: per adapter object * * After host reset, find out whether devices are still responding. * If not remove. */ static void _scsih_search_responding_pcie_devices(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_mark_responding_raid_device - mark a raid_device as responding * @ioc: per adapter object * @wwid: world wide identifier for raid volume * @handle: device handle * * After host reset, find out whether devices are still responding. * Used in _scsih_remove_unresponsive_raid_devices. */ static void _scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid, u16 handle) { … } /** * _scsih_search_responding_raid_devices - * @ioc: per adapter object * * After host reset, find out whether devices are still responding. * If not remove. */ static void _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_mark_responding_expander - mark a expander as responding * @ioc: per adapter object * @expander_pg0:SAS Expander Config Page0 * * After host reset, find out whether devices are still responding. * Used in _scsih_remove_unresponsive_expanders. */ static void _scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, Mpi2ExpanderPage0_t *expander_pg0) { … } /** * _scsih_search_responding_expanders - * @ioc: per adapter object * * After host reset, find out whether devices are still responding. * If not remove. */ static void _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_remove_unresponding_devices - removing unresponding devices * @ioc: per adapter object */ static void _scsih_remove_unresponding_devices(struct MPT3SAS_ADAPTER *ioc) { … } static void _scsih_refresh_expander_links(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_expander, u16 handle) { … } /** * _scsih_scan_for_devices_after_reset - scan for devices after host reset * @ioc: per adapter object */ static void _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_scsih_pre_reset_handler - reset callback handler (for scsih) * @ioc: per adapter object * * The handler for doing any required cleanup or initialization. */ void mpt3sas_scsih_pre_reset_handler(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_scsih_clear_outstanding_scsi_tm_commands - clears outstanding * scsi & tm cmds. * @ioc: per adapter object * * The handler for doing any required cleanup or initialization. */ void mpt3sas_scsih_clear_outstanding_scsi_tm_commands(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_scsih_reset_done_handler - reset callback handler (for scsih) * @ioc: per adapter object * * The handler for doing any required cleanup or initialization. */ void mpt3sas_scsih_reset_done_handler(struct MPT3SAS_ADAPTER *ioc) { … } /** * _mpt3sas_fw_work - delayed task for processing firmware events * @ioc: per adapter object * @fw_event: The fw_event_work object * Context: user. */ static void _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { … } /** * _firmware_event_work * @work: The fw_event_work object * Context: user. * * wrappers for the work thread handling firmware events */ static void _firmware_event_work(struct work_struct *work) { … } /** * mpt3sas_scsih_event_callback - firmware event handler (called at ISR time) * @ioc: per adapter object * @msix_index: MSIX table index supplied by the OS * @reply: reply message frame(lower 32bit addr) * Context: interrupt. * * This function merely adds a new work task into ioc->firmware_event_thread. * The tasks are worked from _firmware_event_work in user context. * * Return: 1 meaning mf should be freed from _base_interrupt * 0 means the mf is freed from this function. */ u8 mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply) { … } /** * _scsih_expander_node_remove - removing expander device from list. * @ioc: per adapter object * @sas_expander: the sas_device object * * Removing object and freeing associated memory from the * ioc->sas_expander_list. */ static void _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_expander) { … } /** * _scsih_nvme_shutdown - NVMe shutdown notification * @ioc: per adapter object * * Sending IoUnitControl request with shutdown operation code to alert IOC that * the host system is shutting down so that IOC can issue NVMe shutdown to * NVMe drives attached to it. */ static void _scsih_nvme_shutdown(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_ir_shutdown - IR shutdown notification * @ioc: per adapter object * * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that * the host system is shutting down. */ static void _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_get_shost_and_ioc - get shost and ioc * and verify whether they are NULL or not * @pdev: PCI device struct * @shost: address of scsi host pointer * @ioc: address of HBA adapter pointer * * Return zero if *shost and *ioc are not NULL otherwise return error number. */ static int _scsih_get_shost_and_ioc(struct pci_dev *pdev, struct Scsi_Host **shost, struct MPT3SAS_ADAPTER **ioc) { … } /** * scsih_remove - detach and remove add host * @pdev: PCI device struct * * Routine called when unloading the driver. */ static void scsih_remove(struct pci_dev *pdev) { … } /** * scsih_shutdown - routine call during system shutdown * @pdev: PCI device struct */ static void scsih_shutdown(struct pci_dev *pdev) { … } /** * _scsih_probe_boot_devices - reports 1st device * @ioc: per adapter object * * If specified in bios page 2, this routine reports the 1st * device scsi-ml or sas transport for persistent boot device * purposes. Please refer to function _scsih_determine_boot_device() */ static void _scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_probe_raid - reporting raid volumes to scsi-ml * @ioc: per adapter object * * Called during initial loading of the driver. */ static void _scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc) { … } static struct _sas_device *get_next_sas_device(struct MPT3SAS_ADAPTER *ioc) { … } static void sas_device_make_active(struct MPT3SAS_ADAPTER *ioc, struct _sas_device *sas_device) { … } /** * _scsih_probe_sas - reporting sas devices to sas transport * @ioc: per adapter object * * Called during initial loading of the driver. */ static void _scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc) { … } /** * get_next_pcie_device - Get the next pcie device * @ioc: per adapter object * * Get the next pcie device from pcie_device_init_list list. * * Return: pcie device structure if pcie_device_init_list list is not empty * otherwise returns NULL */ static struct _pcie_device *get_next_pcie_device(struct MPT3SAS_ADAPTER *ioc) { … } /** * pcie_device_make_active - Add pcie device to pcie_device_list list * @ioc: per adapter object * @pcie_device: pcie device object * * Add the pcie device which has registered with SCSI Transport Later to * pcie_device_list list */ static void pcie_device_make_active(struct MPT3SAS_ADAPTER *ioc, struct _pcie_device *pcie_device) { … } /** * _scsih_probe_pcie - reporting PCIe devices to scsi-ml * @ioc: per adapter object * * Called during initial loading of the driver. */ static void _scsih_probe_pcie(struct MPT3SAS_ADAPTER *ioc) { … } /** * _scsih_probe_devices - probing for devices * @ioc: per adapter object * * Called during initial loading of the driver. */ static void _scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc) { … } /** * scsih_scan_start - scsi lld callback for .scan_start * @shost: SCSI host pointer * * The shost has the ability to discover targets on its own instead * of scanning the entire bus. In our implemention, we will kick off * firmware discovery. */ static void scsih_scan_start(struct Scsi_Host *shost) { … } /** * _scsih_complete_devices_scanning - add the devices to sml and * complete ioc initialization. * @ioc: per adapter object * * Return nothing. */ static void _scsih_complete_devices_scanning(struct MPT3SAS_ADAPTER *ioc) { … } /** * scsih_scan_finished - scsi lld callback for .scan_finished * @shost: SCSI host pointer * @time: elapsed time of the scan in jiffies * * This function will be called periodicallyn until it returns 1 with the * scsi_host and the elapsed time of the scan in jiffies. In our implemention, * we wait for firmware discovery to complete, then return 1. */ static int scsih_scan_finished(struct Scsi_Host *shost, unsigned long time) { … } /** * scsih_map_queues - map reply queues with request queues * @shost: SCSI host pointer */ static void scsih_map_queues(struct Scsi_Host *shost) { … } /* shost template for SAS 2.0 HBA devices */ static const struct scsi_host_template mpt2sas_driver_template = …; /* raid transport support for SAS 2.0 HBA devices */ static struct raid_function_template mpt2sas_raid_functions = …; /* shost template for SAS 3.0 HBA devices */ static const struct scsi_host_template mpt3sas_driver_template = …; /* raid transport support for SAS 3.0 HBA devices */ static struct raid_function_template mpt3sas_raid_functions = …; /** * _scsih_determine_hba_mpi_version - determine in which MPI version class * this device belongs to. * @pdev: PCI device struct * * return MPI2_VERSION for SAS 2.0 HBA devices, * MPI25_VERSION for SAS 3.0 HBA devices, and * MPI26 VERSION for Cutlass & Invader SAS 3.0 HBA devices */ static u16 _scsih_determine_hba_mpi_version(struct pci_dev *pdev) { … } /** * _scsih_probe - attach and add scsi host * @pdev: PCI device struct * @id: pci device id * * Return: 0 success, anything else error. */ static int _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) { … } /** * scsih_suspend - power management suspend main entry point * @dev: Device struct * * Return: 0 success, anything else error. */ static int __maybe_unused scsih_suspend(struct device *dev) { … } /** * scsih_resume - power management resume main entry point * @dev: Device struct * * Return: 0 success, anything else error. */ static int __maybe_unused scsih_resume(struct device *dev) { … } /** * scsih_pci_error_detected - Called when a PCI error is detected. * @pdev: PCI device struct * @state: PCI channel state * * Description: Called when a PCI error is detected. * * Return: PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT. */ static pci_ers_result_t scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { … } /** * scsih_pci_slot_reset - Called when PCI slot has been reset. * @pdev: PCI device struct * * Description: This routine is called by the pci error recovery * code after the PCI slot has been reset, just before we * should resume normal operations. */ static pci_ers_result_t scsih_pci_slot_reset(struct pci_dev *pdev) { … } /** * scsih_pci_resume() - resume normal ops after PCI reset * @pdev: pointer to PCI device * * Called when the error recovery driver tells us that its * OK to resume normal operation. Use completion to allow * halted scsi ops to resume. */ static void scsih_pci_resume(struct pci_dev *pdev) { … } /** * scsih_pci_mmio_enabled - Enable MMIO and dump debug registers * @pdev: pointer to PCI device */ static pci_ers_result_t scsih_pci_mmio_enabled(struct pci_dev *pdev) { … } /* * The pci device ids are defined in mpi/mpi2_cnfg.h. */ static const struct pci_device_id mpt3sas_pci_table[] = …; MODULE_DEVICE_TABLE(pci, mpt3sas_pci_table); static struct pci_error_handlers _mpt3sas_err_handler = …; static SIMPLE_DEV_PM_OPS(scsih_pm_ops, scsih_suspend, scsih_resume); static struct pci_driver mpt3sas_driver = …; /** * scsih_init - main entry point for this driver. * * Return: 0 success, anything else error. */ static int scsih_init(void) { … } /** * scsih_exit - exit point for this driver (when it is a module). * * Return: 0 success, anything else error. */ static void scsih_exit(void) { … } /** * _mpt3sas_init - main entry point for this driver. * * Return: 0 success, anything else error. */ static int __init _mpt3sas_init(void) { … } /** * _mpt3sas_exit - exit point for this driver (when it is a module). * */ static void __exit _mpt3sas_exit(void) { … } module_init(…) …; module_exit(_mpt3sas_exit);