/* * This is the Fusion MPT base driver providing common API layer interface * for access to MPT (Message Passing Technology) firmware. * * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.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/kernel.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/pci.h> #include <linux/kdev_t.h> #include <linux/blkdev.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/time.h> #include <linux/ktime.h> #include <linux/kthread.h> #include <asm/page.h> /* To get host page size per arch */ #include "mpt3sas_base.h" static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS]; #define FAULT_POLLING_INTERVAL … /* maximum controller queue depth */ #define MAX_HBA_QUEUE_DEPTH … #define MAX_CHAIN_DEPTH … static int max_queue_depth = …; module_param(max_queue_depth, int, 0444); MODULE_PARM_DESC(…) …; static int max_sgl_entries = …; module_param(max_sgl_entries, int, 0444); MODULE_PARM_DESC(…) …; static int msix_disable = …; module_param(msix_disable, int, 0444); MODULE_PARM_DESC(…) …; static int smp_affinity_enable = …; module_param(smp_affinity_enable, int, 0444); MODULE_PARM_DESC(…) …; static int max_msix_vectors = …; module_param(max_msix_vectors, int, 0444); MODULE_PARM_DESC(…) …; static int irqpoll_weight = …; module_param(irqpoll_weight, int, 0444); MODULE_PARM_DESC(…) …; static int mpt3sas_fwfault_debug; MODULE_PARM_DESC(…) …; static int perf_mode = …; module_param(perf_mode, int, 0444); MODULE_PARM_DESC(…) …; static int poll_queues; module_param(poll_queues, int, 0444); MODULE_PARM_DESC(…) …; enum mpt3sas_perf_mode { … }; static int _base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout); static int _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc); static void _base_clear_outstanding_commands(struct MPT3SAS_ADAPTER *ioc); static u32 _base_readl_ext_retry(const void __iomem *addr); /** * mpt3sas_base_check_cmd_timeout - Function * to check timeout and command termination due * to Host reset. * * @ioc: per adapter object. * @status: Status of issued command. * @mpi_request:mf request pointer. * @sz: size of buffer. * * Return: 1/0 Reset to be done or Not */ u8 mpt3sas_base_check_cmd_timeout(struct MPT3SAS_ADAPTER *ioc, u8 status, void *mpi_request, int sz) { … } /** * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. * @val: ? * @kp: ? * * Return: ? */ static int _scsih_set_fwfault_debug(const char *val, const struct kernel_param *kp) { … } module_param_call(…); /** * _base_readl_aero - retry readl for max three times. * @addr: MPT Fusion system interface register address * * Retry the readl() for max three times if it gets zero value * while reading the system interface register. */ static inline u32 _base_readl_aero(const void __iomem *addr) { … } static u32 _base_readl_ext_retry(const void __iomem *addr) { … } static inline u32 _base_readl(const void __iomem *addr) { … } /** * _base_clone_reply_to_sys_mem - copies reply to reply free iomem * in BAR0 space. * * @ioc: per adapter object * @reply: reply message frame(lower 32bit addr) * @index: System request message index. */ static void _base_clone_reply_to_sys_mem(struct MPT3SAS_ADAPTER *ioc, u32 reply, u32 index) { … } /** * _base_clone_mpi_to_sys_mem - Writes/copies MPI frames * to system/BAR0 region. * * @dst_iomem: Pointer to the destination location in BAR0 space. * @src: Pointer to the Source data. * @size: Size of data to be copied. */ static void _base_clone_mpi_to_sys_mem(void *dst_iomem, void *src, u32 size) { … } /** * _base_clone_to_sys_mem - Writes/copies data to system/BAR0 region * * @dst_iomem: Pointer to the destination location in BAR0 space. * @src: Pointer to the Source data. * @size: Size of data to be copied. */ static void _base_clone_to_sys_mem(void __iomem *dst_iomem, void *src, u32 size) { … } /** * _base_get_chain - Calculates and Returns virtual chain address * for the provided smid in BAR0 space. * * @ioc: per adapter object * @smid: system request message index * @sge_chain_count: Scatter gather chain count. * * Return: the chain address. */ static inline void __iomem* _base_get_chain(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 sge_chain_count) { … } /** * _base_get_chain_phys - Calculates and Returns physical address * in BAR0 for scatter gather chains, for * the provided smid. * * @ioc: per adapter object * @smid: system request message index * @sge_chain_count: Scatter gather chain count. * * Return: Physical chain address. */ static inline phys_addr_t _base_get_chain_phys(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 sge_chain_count) { … } /** * _base_get_buffer_bar0 - Calculates and Returns BAR0 mapped Host * buffer address for the provided smid. * (Each smid can have 64K starts from 17024) * * @ioc: per adapter object * @smid: system request message index * * Return: Pointer to buffer location in BAR0. */ static void __iomem * _base_get_buffer_bar0(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * _base_get_buffer_phys_bar0 - Calculates and Returns BAR0 mapped * Host buffer Physical address for the provided smid. * (Each smid can have 64K starts from 17024) * * @ioc: per adapter object * @smid: system request message index * * Return: Pointer to buffer location in BAR0. */ static phys_addr_t _base_get_buffer_phys_bar0(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * _base_get_chain_buffer_dma_to_chain_buffer - Iterates chain * lookup list and Provides chain_buffer * address for the matching dma address. * (Each smid can have 64K starts from 17024) * * @ioc: per adapter object * @chain_buffer_dma: Chain buffer dma address. * * Return: Pointer to chain buffer. Or Null on Failure. */ static void * _base_get_chain_buffer_dma_to_chain_buffer(struct MPT3SAS_ADAPTER *ioc, dma_addr_t chain_buffer_dma) { … } /** * _clone_sg_entries - MPI EP's scsiio and config requests * are handled here. Base function for * double buffering, before submitting * the requests. * * @ioc: per adapter object. * @mpi_request: mf request pointer. * @smid: system request message index. */ static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc, void *mpi_request, u16 smid) { … } /** * mpt3sas_remove_dead_ioc_func - kthread context to remove dead ioc * @arg: input argument, used to derive ioc * * Return: * 0 if controller is removed from pci subsystem. * -1 for other case. */ static int mpt3sas_remove_dead_ioc_func(void *arg) { … } /** * _base_sync_drv_fw_timestamp - Sync Drive-Fw TimeStamp. * @ioc: Per Adapter Object * * Return: nothing. */ static void _base_sync_drv_fw_timestamp(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_fault_reset_work - workq handling ioc fault conditions * @work: input argument, used to derive ioc * * Context: sleep. */ static void _base_fault_reset_work(struct work_struct *work) { … } /** * mpt3sas_base_start_watchdog - start the fault_reset_work_q * @ioc: per adapter object * * Context: sleep. */ void mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_stop_watchdog - stop the fault_reset_work_q * @ioc: per adapter object * * Context: sleep. */ void mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_fault_info - verbose translation of firmware FAULT code * @ioc: per adapter object * @fault_code: fault code */ void mpt3sas_base_fault_info(struct MPT3SAS_ADAPTER *ioc, u16 fault_code) { … } /** * mpt3sas_base_coredump_info - verbose translation of firmware CoreDump state * @ioc: per adapter object * @fault_code: fault code * * Return: nothing. */ void mpt3sas_base_coredump_info(struct MPT3SAS_ADAPTER *ioc, u16 fault_code) { … } /** * mpt3sas_base_wait_for_coredump_completion - Wait until coredump * completes or times out * @ioc: per adapter object * @caller: caller function name * * Return: 0 for success, non-zero for failure. */ int mpt3sas_base_wait_for_coredump_completion(struct MPT3SAS_ADAPTER *ioc, const char *caller) { … } /** * mpt3sas_halt_firmware - halt's mpt controller firmware * @ioc: per adapter object * * For debugging timeout related issues. Writing 0xCOFFEE00 * to the doorbell register will halt controller firmware. With * the purpose to stop both driver and firmware, the enduser can * obtain a ring buffer from controller UART. */ void mpt3sas_halt_firmware(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_sas_ioc_info - verbose translation of the ioc status * @ioc: per adapter object * @mpi_reply: reply mf payload returned from firmware * @request_hdr: request mf */ static void _base_sas_ioc_info(struct MPT3SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply, MPI2RequestHeader_t *request_hdr) { … } /** * _base_display_event_data - verbose translation of firmware asyn events * @ioc: per adapter object * @mpi_reply: reply mf payload returned from firmware */ static void _base_display_event_data(struct MPT3SAS_ADAPTER *ioc, Mpi2EventNotificationReply_t *mpi_reply) { … } /** * _base_sas_log_info - verbose translation of firmware log info * @ioc: per adapter object * @log_info: log info */ static void _base_sas_log_info(struct MPT3SAS_ADAPTER *ioc, u32 log_info) { … } /** * _base_display_reply_info - handle reply descriptors depending on IOC Status * @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) */ static void _base_display_reply_info(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) { … } /** * mpt3sas_base_done - base internal command 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) * * Return: * 1 meaning mf should be freed from _base_interrupt * 0 means the mf is freed from this function. */ u8 mpt3sas_base_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) { … } /** * _base_async_event - main callback handler for firmware asyn events * @ioc: per adapter object * @msix_index: MSIX table index supplied by the OS * @reply: reply message frame(lower 32bit addr) * * Return: * 1 meaning mf should be freed from _base_interrupt * 0 means the mf is freed from this function. */ static u8 _base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply) { … } static struct scsiio_tracker * _get_st_from_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * _base_get_cb_idx - obtain the callback index * @ioc: per adapter object * @smid: system request message index * * Return: callback index. */ static u8 _base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * mpt3sas_base_pause_mq_polling - pause polling on the mq poll queues * when driver is flushing out the IOs. * @ioc: per adapter object * * Pause polling on the mq poll (io uring) queues when driver is flushing * out the IOs. Otherwise we may see the race condition of completing the same * IO from two paths. * * Returns nothing. */ void mpt3sas_base_pause_mq_polling(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_resume_mq_polling - Resume polling on mq poll queues. * @ioc: per adapter object * * Returns nothing. */ void mpt3sas_base_resume_mq_polling(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_mask_interrupts - disable interrupts * @ioc: per adapter object * * Disabling ResetIRQ, Reply and Doorbell Interrupts */ void mpt3sas_base_mask_interrupts(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_unmask_interrupts - enable interrupts * @ioc: per adapter object * * Enabling only Reply Interrupts */ void mpt3sas_base_unmask_interrupts(struct MPT3SAS_ADAPTER *ioc) { … } reply_descriptor; static u32 base_mod64(u64 dividend, u32 divisor) { … } /** * _base_process_reply_queue - Process reply descriptors from reply * descriptor post queue. * @reply_q: per IRQ's reply queue object. * * Return: number of reply descriptors processed from reply * descriptor queue. */ static int _base_process_reply_queue(struct adapter_reply_queue *reply_q) { … } /** * mpt3sas_blk_mq_poll - poll the blk mq poll queue * @shost: Scsi_Host object * @queue_num: hw ctx queue number * * Return number of entries that has been processed from poll queue. */ int mpt3sas_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num) { … } /** * _base_interrupt - MPT adapter (IOC) specific interrupt handler. * @irq: irq number (not used) * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure * * Return: IRQ_HANDLED if processed, else IRQ_NONE. */ static irqreturn_t _base_interrupt(int irq, void *bus_id) { … } /** * _base_irqpoll - IRQ poll callback handler * @irqpoll: irq_poll object * @budget: irq poll weight * * Return: number of reply descriptors processed */ static int _base_irqpoll(struct irq_poll *irqpoll, int budget) { … } /** * _base_init_irqpolls - initliaze IRQ polls * @ioc: per adapter object * * Return: nothing */ static void _base_init_irqpolls(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_is_controller_msix_enabled - is controller support muli-reply queues * @ioc: per adapter object * * Return: Whether or not MSI/X is enabled. */ static inline int _base_is_controller_msix_enabled(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_sync_reply_irqs - flush pending MSIX interrupts * @ioc: per adapter object * @poll: poll over reply descriptor pools incase interrupt for * timed-out SCSI command got delayed * Context: non-ISR context * * Called when a Task Management request has completed. */ void mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc, u8 poll) { … } /** * mpt3sas_base_release_callback_handler - clear interrupt callback handler * @cb_idx: callback index */ void mpt3sas_base_release_callback_handler(u8 cb_idx) { … } /** * mpt3sas_base_register_callback_handler - obtain index for the interrupt callback handler * @cb_func: callback function * * Return: Index of @cb_func. */ u8 mpt3sas_base_register_callback_handler(MPT_CALLBACK cb_func) { … } /** * mpt3sas_base_initialize_callback_handler - initialize the interrupt callback handler */ void mpt3sas_base_initialize_callback_handler(void) { … } /** * _base_build_zero_len_sge - build zero length sg entry * @ioc: per adapter object * @paddr: virtual address for SGE * * Create a zero length scatter gather entry to insure the IOCs hardware has * something to use if the target device goes brain dead and tries * to send data even when none is asked for. */ static void _base_build_zero_len_sge(struct MPT3SAS_ADAPTER *ioc, void *paddr) { … } /** * _base_add_sg_single_32 - Place a simple 32 bit SGE at address pAddr. * @paddr: virtual address for SGE * @flags_length: SGE flags and data transfer length * @dma_addr: Physical address */ static void _base_add_sg_single_32(void *paddr, u32 flags_length, dma_addr_t dma_addr) { … } /** * _base_add_sg_single_64 - Place a simple 64 bit SGE at address pAddr. * @paddr: virtual address for SGE * @flags_length: SGE flags and data transfer length * @dma_addr: Physical address */ static void _base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr) { … } /** * _base_get_chain_buffer_tracker - obtain chain tracker * @ioc: per adapter object * @scmd: SCSI commands of the IO request * * Return: chain tracker from chain_lookup table using key as * smid and smid's chain_offset. */ static struct chain_tracker * _base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) { … } /** * _base_build_sg - build generic sg * @ioc: per adapter object * @psge: virtual address for SGE * @data_out_dma: physical address for WRITES * @data_out_sz: data xfer size for WRITES * @data_in_dma: physical address for READS * @data_in_sz: data xfer size for READS */ static void _base_build_sg(struct MPT3SAS_ADAPTER *ioc, void *psge, dma_addr_t data_out_dma, size_t data_out_sz, dma_addr_t data_in_dma, size_t data_in_sz) { … } /* IEEE format sgls */ /** * _base_build_nvme_prp - This function is called for NVMe end devices to build * a native SGL (NVMe PRP). * @ioc: per adapter object * @smid: system request message index for getting asscociated SGL * @nvme_encap_request: the NVMe request msg frame pointer * @data_out_dma: physical address for WRITES * @data_out_sz: data xfer size for WRITES * @data_in_dma: physical address for READS * @data_in_sz: data xfer size for READS * * The native SGL is built starting in the first PRP * entry of the NVMe message (PRP1). If the data buffer is small enough to be * described entirely using PRP1, then PRP2 is not used. If needed, PRP2 is * used to describe a larger data buffer. If the data buffer is too large to * describe using the two PRP entriess inside the NVMe message, then PRP1 * describes the first data memory segment, and PRP2 contains a pointer to a PRP * list located elsewhere in memory to describe the remaining data memory * segments. The PRP list will be contiguous. * * The native SGL for NVMe devices is a Physical Region Page (PRP). A PRP * consists of a list of PRP entries to describe a number of noncontigous * physical memory segments as a single memory buffer, just as a SGL does. Note * however, that this function is only used by the IOCTL call, so the memory * given will be guaranteed to be contiguous. There is no need to translate * non-contiguous SGL into a PRP in this case. All PRPs will describe * contiguous space that is one page size each. * * Each NVMe message contains two PRP entries. The first (PRP1) either contains * a PRP list pointer or a PRP element, depending upon the command. PRP2 * contains the second PRP element if the memory being described fits within 2 * PRP entries, or a PRP list pointer if the PRP spans more than two entries. * * A PRP list pointer contains the address of a PRP list, structured as a linear * array of PRP entries. Each PRP entry in this list describes a segment of * physical memory. * * Each 64-bit PRP entry comprises an address and an offset field. The address * always points at the beginning of a 4KB physical memory page, and the offset * describes where within that 4KB page the memory segment begins. Only the * first element in a PRP list may contain a non-zero offset, implying that all * memory segments following the first begin at the start of a 4KB page. * * Each PRP element normally describes 4KB of physical memory, with exceptions * for the first and last elements in the list. If the memory being described * by the list begins at a non-zero offset within the first 4KB page, then the * first PRP element will contain a non-zero offset indicating where the region * begins within the 4KB page. The last memory segment may end before the end * of the 4KB segment, depending upon the overall size of the memory being * described by the PRP list. * * Since PRP entries lack any indication of size, the overall data buffer length * is used to determine where the end of the data memory buffer is located, and * how many PRP entries are required to describe it. */ static void _base_build_nvme_prp(struct MPT3SAS_ADAPTER *ioc, u16 smid, Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request, dma_addr_t data_out_dma, size_t data_out_sz, dma_addr_t data_in_dma, size_t data_in_sz) { … } /** * base_make_prp_nvme - Prepare PRPs (Physical Region Page) - * SGLs specific to NVMe drives only * * @ioc: per adapter object * @scmd: SCSI command from the mid-layer * @mpi_request: mpi request * @smid: msg Index * @sge_count: scatter gather element count. * * Return: true: PRPs are built * false: IEEE SGLs needs to be built */ static void base_make_prp_nvme(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, Mpi25SCSIIORequest_t *mpi_request, u16 smid, int sge_count) { … } static bool base_is_prp_possible(struct MPT3SAS_ADAPTER *ioc, struct _pcie_device *pcie_device, struct scsi_cmnd *scmd, int sge_count) { … } /** * _base_check_pcie_native_sgl - This function is called for PCIe end devices to * determine if the driver needs to build a native SGL. If so, that native * SGL is built in the special contiguous buffers allocated especially for * PCIe SGL creation. If the driver will not build a native SGL, return * TRUE and a normal IEEE SGL will be built. Currently this routine * supports NVMe. * @ioc: per adapter object * @mpi_request: mf request pointer * @smid: system request message index * @scmd: scsi command * @pcie_device: points to the PCIe device's info * * Return: 0 if native SGL was built, 1 if no SGL was built */ static int _base_check_pcie_native_sgl(struct MPT3SAS_ADAPTER *ioc, Mpi25SCSIIORequest_t *mpi_request, u16 smid, struct scsi_cmnd *scmd, struct _pcie_device *pcie_device) { … } /** * _base_add_sg_single_ieee - add sg element for IEEE format * @paddr: virtual address for SGE * @flags: SGE flags * @chain_offset: number of 128 byte elements from start of segment * @length: data transfer length * @dma_addr: Physical address */ static void _base_add_sg_single_ieee(void *paddr, u8 flags, u8 chain_offset, u32 length, dma_addr_t dma_addr) { … } /** * _base_build_zero_len_sge_ieee - build zero length sg entry for IEEE format * @ioc: per adapter object * @paddr: virtual address for SGE * * Create a zero length scatter gather entry to insure the IOCs hardware has * something to use if the target device goes brain dead and tries * to send data even when none is asked for. */ static void _base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr) { … } static inline int _base_scsi_dma_map(struct scsi_cmnd *cmd) { … } /** * _base_build_sg_scmd - main sg creation routine * pcie_device is unused here! * @ioc: per adapter object * @scmd: scsi command * @smid: system request message index * @unused: unused pcie_device pointer * Context: none. * * The main routine that builds scatter gather table from a given * scsi request sent via the .queuecommand main handler. * * Return: 0 success, anything else error */ static int _base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, u16 smid, struct _pcie_device *unused) { … } /** * _base_build_sg_scmd_ieee - main sg creation routine for IEEE format * @ioc: per adapter object * @scmd: scsi command * @smid: system request message index * @pcie_device: Pointer to pcie_device. If set, the pcie native sgl will be * constructed on need. * Context: none. * * The main routine that builds scatter gather table from a given * scsi request sent via the .queuecommand main handler. * * Return: 0 success, anything else error */ static int _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, u16 smid, struct _pcie_device *pcie_device) { … } /** * _base_build_sg_ieee - build generic sg for IEEE format * @ioc: per adapter object * @psge: virtual address for SGE * @data_out_dma: physical address for WRITES * @data_out_sz: data xfer size for WRITES * @data_in_dma: physical address for READS * @data_in_sz: data xfer size for READS */ static void _base_build_sg_ieee(struct MPT3SAS_ADAPTER *ioc, void *psge, dma_addr_t data_out_dma, size_t data_out_sz, dma_addr_t data_in_dma, size_t data_in_sz) { … } #define convert_to_kb(x) … /** * _base_config_dma_addressing - set dma addressing * @ioc: per adapter object * @pdev: PCI device struct * * Return: 0 for success, non-zero for failure. */ static int _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev) { … } /** * _base_check_enable_msix - checks MSIX capabable. * @ioc: per adapter object * * Check to see if card is capable of MSIX, and set number * of available msix vectors */ static int _base_check_enable_msix(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_free_irq - free irq * @ioc: per adapter object * * Freeing respective reply_queue from the list. */ void mpt3sas_base_free_irq(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_request_irq - request irq * @ioc: per adapter object * @index: msix index into vector table * * Inserting respective reply_queue into the list. */ static int _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index) { … } /** * _base_assign_reply_queues - assigning msix index for each cpu * @ioc: per adapter object * * The enduser would need to set the affinity via /proc/irq/#/smp_affinity */ static void _base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_check_and_enable_high_iops_queues - enable high iops mode * @ioc: per adapter object * @hba_msix_vector_count: msix vectors supported by HBA * * Enable high iops queues only if * - HBA is a SEA/AERO controller and * - MSI-Xs vector supported by the HBA is 128 and * - total CPU count in the system >=16 and * - loaded driver with default max_msix_vectors module parameter and * - system booted in non kdump mode * * Return: nothing. */ static void _base_check_and_enable_high_iops_queues(struct MPT3SAS_ADAPTER *ioc, int hba_msix_vector_count) { … } /** * mpt3sas_base_disable_msix - disables msix * @ioc: per adapter object * */ void mpt3sas_base_disable_msix(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_alloc_irq_vectors - allocate msix vectors * @ioc: per adapter object * */ static int _base_alloc_irq_vectors(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_enable_msix - enables msix, failback to io_apic * @ioc: per adapter object * */ static int _base_enable_msix(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_unmap_resources - free controller resources * @ioc: per adapter object */ static void mpt3sas_base_unmap_resources(struct MPT3SAS_ADAPTER *ioc) { … } static int _base_diag_reset(struct MPT3SAS_ADAPTER *ioc); /** * mpt3sas_base_check_for_fault_and_issue_reset - check if IOC is in fault state * and if it is in fault state then issue diag reset. * @ioc: per adapter object * * Return: 0 for success, non-zero for failure. */ int mpt3sas_base_check_for_fault_and_issue_reset(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_map_resources - map in controller resources (io/irq/memap) * @ioc: per adapter object * * Return: 0 for success, non-zero for failure. */ int mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_get_msg_frame - obtain request mf pointer * @ioc: per adapter object * @smid: system request message index(smid zero is invalid) * * Return: virt pointer to message frame. */ void * mpt3sas_base_get_msg_frame(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * mpt3sas_base_get_sense_buffer - obtain a sense buffer virt addr * @ioc: per adapter object * @smid: system request message index * * Return: virt pointer to sense buffer. */ void * mpt3sas_base_get_sense_buffer(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * mpt3sas_base_get_sense_buffer_dma - obtain a sense buffer dma addr * @ioc: per adapter object * @smid: system request message index * * Return: phys pointer to the low 32bit address of the sense buffer. */ __le32 mpt3sas_base_get_sense_buffer_dma(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * mpt3sas_base_get_pcie_sgl - obtain a PCIe SGL virt addr * @ioc: per adapter object * @smid: system request message index * * Return: virt pointer to a PCIe SGL. */ void * mpt3sas_base_get_pcie_sgl(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * mpt3sas_base_get_pcie_sgl_dma - obtain a PCIe SGL dma addr * @ioc: per adapter object * @smid: system request message index * * Return: phys pointer to the address of the PCIe buffer. */ dma_addr_t mpt3sas_base_get_pcie_sgl_dma(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * mpt3sas_base_get_reply_virt_addr - obtain reply frames virt address * @ioc: per adapter object * @phys_addr: lower 32 physical addr of the reply * * Converts 32bit lower physical addr into a virt address. */ void * mpt3sas_base_get_reply_virt_addr(struct MPT3SAS_ADAPTER *ioc, u32 phys_addr) { … } /** * _base_get_msix_index - get the msix index * @ioc: per adapter object * @scmd: scsi_cmnd object * * Return: msix index of general reply queues, * i.e. reply queue on which IO request's reply * should be posted by the HBA firmware. */ static inline u8 _base_get_msix_index(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) { … } /** * _base_get_high_iops_msix_index - get the msix index of * high iops queues * @ioc: per adapter object * @scmd: scsi_cmnd object * * Return: msix index of high iops reply queues. * i.e. high iops reply queue on which IO request's * reply should be posted by the HBA firmware. */ static inline u8 _base_get_high_iops_msix_index(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) { … } /** * mpt3sas_base_get_smid - obtain a free smid from internal queue * @ioc: per adapter object * @cb_idx: callback index * * Return: smid (zero is invalid) */ u16 mpt3sas_base_get_smid(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx) { … } /** * mpt3sas_base_get_smid_scsiio - obtain a free smid from scsiio queue * @ioc: per adapter object * @cb_idx: callback index * @scmd: pointer to scsi command object * * Return: smid (zero is invalid) */ u16 mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx, struct scsi_cmnd *scmd) { … } /** * mpt3sas_base_get_smid_hpr - obtain a free smid from hi-priority queue * @ioc: per adapter object * @cb_idx: callback index * * Return: smid (zero is invalid) */ u16 mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx) { … } static void _base_recovery_check(struct MPT3SAS_ADAPTER *ioc) { … } void mpt3sas_base_clear_st(struct MPT3SAS_ADAPTER *ioc, struct scsiio_tracker *st) { … } /** * mpt3sas_base_free_smid - put smid back on free_list * @ioc: per adapter object * @smid: system request message index */ void mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * _base_mpi_ep_writeq - 32 bit write to MMIO * @b: data payload * @addr: address in MMIO space * @writeq_lock: spin lock * * This special handling for MPI EP to take care of 32 bit * environment where its not quarenteed to send the entire word * in one transfer. */ static inline void _base_mpi_ep_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock) { … } /** * _base_writeq - 64 bit write to MMIO * @b: data payload * @addr: address in MMIO space * @writeq_lock: spin lock * * Glue for handling an atomic 64 bit word to MMIO. This special handling takes * care of 32 bit environment where its not quarenteed to send the entire word * in one transfer. */ #if defined(writeq) && defined(CONFIG_64BIT) static inline void _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock) { … } #else static inline void _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock) { _base_mpi_ep_writeq(b, addr, writeq_lock); } #endif /** * _base_set_and_get_msix_index - get the msix index and assign to msix_io * variable of scsi tracker * @ioc: per adapter object * @smid: system request message index * * Return: msix index. */ static u8 _base_set_and_get_msix_index(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * _base_put_smid_mpi_ep_scsi_io - send SCSI_IO request to firmware * @ioc: per adapter object * @smid: system request message index * @handle: device handle */ static void _base_put_smid_mpi_ep_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) { … } /** * _base_put_smid_scsi_io - send SCSI_IO request to firmware * @ioc: per adapter object * @smid: system request message index * @handle: device handle */ static void _base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) { … } /** * _base_put_smid_fast_path - send fast path request to firmware * @ioc: per adapter object * @smid: system request message index * @handle: device handle */ static void _base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) { … } /** * _base_put_smid_hi_priority - send Task Management request to firmware * @ioc: per adapter object * @smid: system request message index * @msix_task: msix_task will be same as msix of IO in case of task abort else 0 */ static void _base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 msix_task) { … } /** * mpt3sas_base_put_smid_nvme_encap - send NVMe encapsulated request to * firmware * @ioc: per adapter object * @smid: system request message index */ void mpt3sas_base_put_smid_nvme_encap(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * _base_put_smid_default - Default, primarily used for config pages * @ioc: per adapter object * @smid: system request message index */ static void _base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * _base_put_smid_scsi_io_atomic - send SCSI_IO request to firmware using * Atomic Request Descriptor * @ioc: per adapter object * @smid: system request message index * @handle: device handle, unused in this function, for function type match * * Return: nothing. */ static void _base_put_smid_scsi_io_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) { … } /** * _base_put_smid_fast_path_atomic - send fast path request to firmware * using Atomic Request Descriptor * @ioc: per adapter object * @smid: system request message index * @handle: device handle, unused in this function, for function type match * Return: nothing */ static void _base_put_smid_fast_path_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) { … } /** * _base_put_smid_hi_priority_atomic - send Task Management request to * firmware using Atomic Request Descriptor * @ioc: per adapter object * @smid: system request message index * @msix_task: msix_task will be same as msix of IO in case of task abort else 0 * * Return: nothing. */ static void _base_put_smid_hi_priority_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 msix_task) { … } /** * _base_put_smid_default_atomic - Default, primarily used for config pages * use Atomic Request Descriptor * @ioc: per adapter object * @smid: system request message index * * Return: nothing. */ static void _base_put_smid_default_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid) { … } /** * _base_display_OEMs_branding - Display branding string * @ioc: per adapter object */ static void _base_display_OEMs_branding(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_display_fwpkg_version - sends FWUpload request to pull FWPkg * version from FW Image Header. * @ioc: per adapter object * * Return: 0 for success, non-zero for failure. */ static int _base_display_fwpkg_version(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_display_ioc_capabilities - Display IOC's capabilities. * @ioc: per adapter object */ static void _base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_update_missing_delay - change the missing delay timers * @ioc: per adapter object * @device_missing_delay: amount of time till device is reported missing * @io_missing_delay: interval IO is returned when there is a missing device * * Passed on the command line, this function will modify the device missing * delay, as well as the io missing delay. This should be called at driver * load time. */ void mpt3sas_base_update_missing_delay(struct MPT3SAS_ADAPTER *ioc, u16 device_missing_delay, u8 io_missing_delay) { … } /** * _base_update_ioc_page1_inlinewith_perf_mode - Update IOC Page1 fields * according to performance mode. * @ioc : per adapter object * * Return: zero on success; otherwise return EAGAIN error code asking the * caller to retry. */ static int _base_update_ioc_page1_inlinewith_perf_mode(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_get_event_diag_triggers - get event diag trigger values from * persistent pages * @ioc : per adapter object * * Return: nothing. */ static int _base_get_event_diag_triggers(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_get_scsi_diag_triggers - get scsi diag trigger values from * persistent pages * @ioc : per adapter object * * Return: 0 on success; otherwise return failure status. */ static int _base_get_scsi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_get_mpi_diag_triggers - get mpi diag trigger values from * persistent pages * @ioc : per adapter object * * Return: 0 on success; otherwise return failure status. */ static int _base_get_mpi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_get_master_diag_triggers - get master diag trigger values from * persistent pages * @ioc : per adapter object * * Return: nothing. */ static int _base_get_master_diag_triggers(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_check_for_trigger_pages_support - checks whether HBA FW supports * driver trigger pages or not * @ioc : per adapter object * @trigger_flags : address where trigger page0's TriggerFlags value is copied * * Return: trigger flags mask if HBA FW supports driver trigger pages; * otherwise returns %-EFAULT if driver trigger pages are not supported by FW or * return EAGAIN if diag reset occurred due to FW fault and asking the * caller to retry the command. * */ static int _base_check_for_trigger_pages_support(struct MPT3SAS_ADAPTER *ioc, u32 *trigger_flags) { … } /** * _base_get_diag_triggers - Retrieve diag trigger values from * persistent pages. * @ioc : per adapter object * * Return: zero on success; otherwise return EAGAIN error codes * asking the caller to retry. */ static int _base_get_diag_triggers(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_update_diag_trigger_pages - Update the driver trigger pages after * online FW update, in case updated FW supports driver * trigger pages. * @ioc : per adapter object * * Return: nothing. */ static void _base_update_diag_trigger_pages(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_assign_fw_reported_qd - Get FW reported QD for SAS/SATA devices. * - On failure set default QD values. * @ioc : per adapter object * * Returns 0 for success, non-zero for failure. * */ static int _base_assign_fw_reported_qd(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_atto_validate_nvram - validate the ATTO nvram read from mfg pg1 * * @ioc : per adapter object * @n : ptr to the ATTO nvram structure * Return: 0 for success, non-zero for failure. */ static int mpt3sas_atto_validate_nvram(struct MPT3SAS_ADAPTER *ioc, struct ATTO_SAS_NVRAM *n) { … } /** * mpt3sas_atto_get_sas_addr - get the ATTO SAS address from mfg page 1 * * @ioc : per adapter object * @sas_addr : return sas address * Return: 0 for success, non-zero for failure. */ static int mpt3sas_atto_get_sas_addr(struct MPT3SAS_ADAPTER *ioc, union ATTO_SAS_ADDRESS *sas_addr) { … } /** * mpt3sas_atto_init - perform initializaion for ATTO branded * adapter. * @ioc : per adapter object *5 * Return: 0 for success, non-zero for failure. */ static int mpt3sas_atto_init(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_static_config_pages - static start of day config pages * @ioc: per adapter object */ static int _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_free_enclosure_list - release memory * @ioc: per adapter object * * Free memory allocated during enclosure add. */ void mpt3sas_free_enclosure_list(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_release_memory_pools - release memory * @ioc: per adapter object * * Free memory allocated from _base_allocate_memory_pools. */ static void _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_check_same_4gb_region - checks whether all reply queues in a set are * having same upper 32bits in their base memory address. * @start_address: Base address of a reply queue set * @pool_sz: Size of single Reply Descriptor Post Queues pool size * * Return: 1 if reply queues in a set have a same upper 32bits in their base * memory address, else 0. */ static int mpt3sas_check_same_4gb_region(dma_addr_t start_address, u32 pool_sz) { … } /** * _base_reduce_hba_queue_depth- Retry with reduced queue depth * @ioc: Adapter object * * Return: 0 for success, non-zero for failure. **/ static inline int _base_reduce_hba_queue_depth(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_allocate_pcie_sgl_pool - Allocating DMA'able memory * for pcie sgl pools. * @ioc: Adapter object * @sz: DMA Pool size * * Return: 0 for success, non-zero for failure. */ static int _base_allocate_pcie_sgl_pool(struct MPT3SAS_ADAPTER *ioc, u32 sz) { … } /** * _base_allocate_chain_dma_pool - Allocating DMA'able memory * for chain dma pool. * @ioc: Adapter object * @sz: DMA Pool size * * Return: 0 for success, non-zero for failure. */ static int _base_allocate_chain_dma_pool(struct MPT3SAS_ADAPTER *ioc, u32 sz) { … } /** * _base_allocate_sense_dma_pool - Allocating DMA'able memory * for sense dma pool. * @ioc: Adapter object * @sz: DMA Pool size * Return: 0 for success, non-zero for failure. */ static int _base_allocate_sense_dma_pool(struct MPT3SAS_ADAPTER *ioc, u32 sz) { … } /** * _base_allocate_reply_pool - Allocating DMA'able memory * for reply pool. * @ioc: Adapter object * @sz: DMA Pool size * Return: 0 for success, non-zero for failure. */ static int _base_allocate_reply_pool(struct MPT3SAS_ADAPTER *ioc, u32 sz) { … } /** * _base_allocate_reply_free_dma_pool - Allocating DMA'able memory * for reply free dma pool. * @ioc: Adapter object * @sz: DMA Pool size * Return: 0 for success, non-zero for failure. */ static int _base_allocate_reply_free_dma_pool(struct MPT3SAS_ADAPTER *ioc, u32 sz) { … } /** * _base_allocate_reply_post_free_array - Allocating DMA'able memory * for reply post free array. * @ioc: Adapter object * @reply_post_free_array_sz: DMA Pool size * Return: 0 for success, non-zero for failure. */ static int _base_allocate_reply_post_free_array(struct MPT3SAS_ADAPTER *ioc, u32 reply_post_free_array_sz) { … } /** * base_alloc_rdpq_dma_pool - Allocating DMA'able memory * for reply queues. * @ioc: per adapter object * @sz: DMA Pool size * Return: 0 for success, non-zero for failure. */ static int base_alloc_rdpq_dma_pool(struct MPT3SAS_ADAPTER *ioc, int sz) { … } /** * _base_allocate_memory_pools - allocate start of day memory pools * @ioc: per adapter object * * Return: 0 success, anything else error. */ static int _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_get_iocstate - Get the current state of a MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @cooked: Request raw or cooked IOC state * * Return: all IOC Doorbell register bits if cooked==0, else just the * Doorbell bits in MPI_IOC_STATE_MASK. */ u32 mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, int cooked) { … } /** * _base_wait_on_iocstate - waiting on a particular ioc state * @ioc: ? * @ioc_state: controller state { READY, OPERATIONAL, or RESET } * @timeout: timeout in second * * Return: 0 for success, non-zero for failure. */ static int _base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout) { … } /** * _base_dump_reg_set - This function will print hexdump of register set. * @ioc: per adapter object * * Return: nothing. */ static inline void _base_dump_reg_set(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by * a write to the doorbell) * @ioc: per adapter object * @timeout: timeout in seconds * * Return: 0 for success, non-zero for failure. * * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell. */ static int _base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout) { … } static int _base_spin_on_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout) { … } /** * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell. * @ioc: per adapter object * @timeout: timeout in second * * Return: 0 for success, non-zero for failure. * * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to * doorbell. */ static int _base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout) { … } /** * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use * @ioc: per adapter object * @timeout: timeout in second * * Return: 0 for success, non-zero for failure. */ static int _base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout) { … } /** * _base_send_ioc_reset - send doorbell reset * @ioc: per adapter object * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET * @timeout: timeout in second * * Return: 0 for success, non-zero for failure. */ static int _base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout) { … } /** * mpt3sas_wait_for_ioc - IOC's operational state is checked here. * @ioc: per adapter object * @timeout: timeout in seconds * * Return: Waits up to timeout seconds for the IOC to * become operational. Returns 0 if IOC is present * and operational; otherwise returns %-EFAULT. */ int mpt3sas_wait_for_ioc(struct MPT3SAS_ADAPTER *ioc, int timeout) { … } /** * _base_handshake_req_reply_wait - send request thru doorbell interface * @ioc: per adapter object * @request_bytes: request length * @request: pointer having request payload * @reply_bytes: reply length * @reply: pointer to reply payload * @timeout: timeout in second * * Return: 0 for success, non-zero for failure. */ static int _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, u32 *request, int reply_bytes, u16 *reply, int timeout) { … } /** * mpt3sas_base_sas_iounit_control - send sas iounit control to FW * @ioc: per adapter object * @mpi_reply: the reply payload from FW * @mpi_request: the request payload sent to FW * * The SAS IO Unit Control Request message allows the host to perform low-level * operations, such as resets on the PHYs of the IO Unit, also allows the host * to obtain the IOC assigned device handles for a device if it has other * identifying information about the device, in addition allows the host to * remove IOC resources associated with the device. * * Return: 0 for success, non-zero for failure. */ int mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc, Mpi2SasIoUnitControlReply_t *mpi_reply, Mpi2SasIoUnitControlRequest_t *mpi_request) { … } /** * mpt3sas_base_scsi_enclosure_processor - sending request to sep device * @ioc: per adapter object * @mpi_reply: the reply payload from FW * @mpi_request: the request payload sent to FW * * The SCSI Enclosure Processor request message causes the IOC to * communicate with SES devices to control LED status signals. * * Return: 0 for success, non-zero for failure. */ int mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request) { … } /** * _base_get_port_facts - obtain port facts reply and save in ioc * @ioc: per adapter object * @port: ? * * Return: 0 for success, non-zero for failure. */ static int _base_get_port_facts(struct MPT3SAS_ADAPTER *ioc, int port) { … } /** * _base_wait_for_iocstate - Wait until the card is in READY or OPERATIONAL * @ioc: per adapter object * @timeout: * * Return: 0 for success, non-zero for failure. */ static int _base_wait_for_iocstate(struct MPT3SAS_ADAPTER *ioc, int timeout) { … } /** * _base_get_ioc_facts - obtain ioc facts reply and save in ioc * @ioc: per adapter object * * Return: 0 for success, non-zero for failure. */ static int _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_send_ioc_init - send ioc_init to firmware * @ioc: per adapter object * * Return: 0 for success, non-zero for failure. */ static int _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_port_enable_done - command completion routine for port enable * @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) * * Return: 1 meaning mf should be freed from _base_interrupt * 0 means the mf is freed from this function. */ u8 mpt3sas_port_enable_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) { … } /** * _base_send_port_enable - send port_enable(discovery stuff) to firmware * @ioc: per adapter object * * Return: 0 for success, non-zero for failure. */ static int _base_send_port_enable(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_port_enable - initiate firmware discovery (don't wait for reply) * @ioc: per adapter object * * Return: 0 for success, non-zero for failure. */ int mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_determine_wait_on_discovery - desposition * @ioc: per adapter object * * Decide whether to wait on discovery to complete. Used to either * locate boot device, or report volumes ahead of physical devices. * * Return: 1 for wait, 0 for don't wait. */ static int _base_determine_wait_on_discovery(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_unmask_events - turn on notification for this event * @ioc: per adapter object * @event: firmware event * * The mask is stored in ioc->event_masks. */ static void _base_unmask_events(struct MPT3SAS_ADAPTER *ioc, u16 event) { … } /** * _base_event_notification - send event notification * @ioc: per adapter object * * Return: 0 for success, non-zero for failure. */ static int _base_event_notification(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_validate_event_type - validating event types * @ioc: per adapter object * @event_type: firmware event * * This will turn on firmware event notification when application * ask for that event. We don't mask events that are already enabled. */ void mpt3sas_base_validate_event_type(struct MPT3SAS_ADAPTER *ioc, u32 *event_type) { … } /** * mpt3sas_base_unlock_and_get_host_diagnostic- enable Host Diagnostic Register writes * @ioc: per adapter object * @host_diagnostic: host diagnostic register content * * Return: 0 for success, non-zero for failure. */ int mpt3sas_base_unlock_and_get_host_diagnostic(struct MPT3SAS_ADAPTER *ioc, u32 *host_diagnostic) { … } /** * mpt3sas_base_lock_host_diagnostic: Disable Host Diagnostic Register writes * @ioc: per adapter object */ void mpt3sas_base_lock_host_diagnostic(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_diag_reset - the "big hammer" start of day reset * @ioc: per adapter object * * Return: 0 for success, non-zero for failure. */ static int _base_diag_reset(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_make_ioc_ready - put controller in READY state * @ioc: per adapter object * @type: FORCE_BIG_HAMMER or SOFT_RESET * * Return: 0 for success, non-zero for failure. */ int mpt3sas_base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, enum reset_type type) { … } /** * _base_make_ioc_operational - put controller in OPERATIONAL state * @ioc: per adapter object * * Return: 0 for success, non-zero for failure. */ static int _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_free_resources - free resources controller resources * @ioc: per adapter object */ void mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_attach - attach controller instance * @ioc: per adapter object * * Return: 0 for success, non-zero for failure. */ int mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_detach - remove controller instance * @ioc: per adapter object */ void mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_pre_reset_handler - pre reset handler * @ioc: per adapter object */ static void _base_pre_reset_handler(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_clear_outstanding_mpt_commands - clears outstanding mpt commands * @ioc: per adapter object */ static void _base_clear_outstanding_mpt_commands(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_clear_outstanding_commands - clear all outstanding commands * @ioc: per adapter object */ static void _base_clear_outstanding_commands(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_reset_done_handler - reset done handler * @ioc: per adapter object */ static void _base_reset_done_handler(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_wait_for_commands_to_complete - reset controller * @ioc: Pointer to MPT_ADAPTER structure * * This function is waiting 10s for all pending commands to complete * prior to putting controller in reset. */ void mpt3sas_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc) { … } /** * _base_check_ioc_facts_changes - Look for increase/decrease of IOCFacts * attributes during online firmware upgrade and update the corresponding * IOC variables accordingly. * * @ioc: Pointer to MPT_ADAPTER structure */ static int _base_check_ioc_facts_changes(struct MPT3SAS_ADAPTER *ioc) { … } /** * mpt3sas_base_hard_reset_handler - reset controller * @ioc: Pointer to MPT_ADAPTER structure * @type: FORCE_BIG_HAMMER or SOFT_RESET * * Return: 0 for success, non-zero for failure. */ int mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, enum reset_type type) { … }