// SPDX-License-Identifier: GPL-2.0-or-later /* * Linux MegaRAID driver for SAS based RAID controllers * * Copyright (c) 2009-2013 LSI Corporation * Copyright (c) 2013-2016 Avago Technologies * Copyright (c) 2016-2018 Broadcom Inc. * * FILE: megaraid_sas_fusion.c * * Authors: Broadcom Inc. * Sumant Patro * Adam Radford * Kashyap Desai <[email protected]> * Sumit Saxena <[email protected]> * * Send feedback to: [email protected] */ #include <linux/kernel.h> #include <linux/types.h> #include <linux/pci.h> #include <linux/list.h> #include <linux/moduleparam.h> #include <linux/module.h> #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/uio.h> #include <linux/uaccess.h> #include <linux/fs.h> #include <linux/compat.h> #include <linux/blkdev.h> #include <linux/mutex.h> #include <linux/poll.h> #include <linux/vmalloc.h> #include <linux/workqueue.h> #include <linux/irq_poll.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> #include <scsi/scsi_dbg.h> #include <linux/dmi.h> #include "megaraid_sas_fusion.h" #include "megaraid_sas.h" extern void megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, u8 alt_status); int wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd, int seconds); int megasas_clear_intr_fusion(struct megasas_instance *instance); int megasas_transition_to_ready(struct megasas_instance *instance, int ocr); extern u32 megasas_dbg_lvl; int megasas_sriov_start_heartbeat(struct megasas_instance *instance, int initial); extern struct megasas_mgmt_info megasas_mgmt_info; extern unsigned int resetwaittime; extern unsigned int dual_qdepth_disable; static void megasas_free_rdpq_fusion(struct megasas_instance *instance); static void megasas_free_reply_fusion(struct megasas_instance *instance); static inline void megasas_configure_queue_sizes(struct megasas_instance *instance); static void megasas_fusion_crash_dump(struct megasas_instance *instance); /** * megasas_adp_reset_wait_for_ready - initiate chip reset and wait for * controller to come to ready state * @instance: adapter's soft state * @do_adp_reset: If true, do a chip reset * @ocr_context: If called from OCR context this will * be set to 1, else 0 * * This function initiates a chip reset followed by a wait for controller to * transition to ready state. * During this, driver will block all access to PCI config space from userspace */ int megasas_adp_reset_wait_for_ready(struct megasas_instance *instance, bool do_adp_reset, int ocr_context) { … } /** * megasas_check_same_4gb_region - check if allocation * crosses same 4GB boundary or not * @instance: adapter's soft instance * @start_addr: start address of DMA allocation * @size: size of allocation in bytes * @return: true : allocation does not cross same * 4GB boundary * false: allocation crosses same * 4GB boundary */ static inline bool megasas_check_same_4gb_region (struct megasas_instance *instance, dma_addr_t start_addr, size_t size) { … } /** * megasas_enable_intr_fusion - Enables interrupts * @instance: adapter's soft instance */ static void megasas_enable_intr_fusion(struct megasas_instance *instance) { … } /** * megasas_disable_intr_fusion - Disables interrupt * @instance: adapter's soft instance */ static void megasas_disable_intr_fusion(struct megasas_instance *instance) { … } int megasas_clear_intr_fusion(struct megasas_instance *instance) { … } static inline void megasas_sdev_busy_inc(struct megasas_instance *instance, struct scsi_cmnd *scmd) { … } static inline void megasas_sdev_busy_dec(struct megasas_instance *instance, struct scsi_cmnd *scmd) { … } static inline int megasas_sdev_busy_read(struct megasas_instance *instance, struct scsi_cmnd *scmd) { … } /** * megasas_get_cmd_fusion - Get a command from the free pool * @instance: Adapter soft state * @blk_tag: Command tag * * Returns a blk_tag indexed mpt frame */ inline struct megasas_cmd_fusion *megasas_get_cmd_fusion(struct megasas_instance *instance, u32 blk_tag) { … } /** * megasas_return_cmd_fusion - Return a cmd to free command pool * @instance: Adapter soft state * @cmd: Command packet to be returned to free command pool */ inline void megasas_return_cmd_fusion(struct megasas_instance *instance, struct megasas_cmd_fusion *cmd) { … } /** * megasas_write_64bit_req_desc - PCI writes 64bit request descriptor * @instance: Adapter soft state * @req_desc: 64bit Request descriptor */ static void megasas_write_64bit_req_desc(struct megasas_instance *instance, union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc) { … } /** * megasas_fire_cmd_fusion - Sends command to the FW * @instance: Adapter soft state * @req_desc: 32bit or 64bit Request descriptor * * Perform PCI Write. AERO SERIES supports 32 bit Descriptor. * Prior to AERO_SERIES support 64 bit Descriptor. */ static void megasas_fire_cmd_fusion(struct megasas_instance *instance, union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc) { … } /** * megasas_fusion_update_can_queue - Do all Adapter Queue depth related calculations here * @instance: Adapter soft state * @fw_boot_context: Whether this function called during probe or after OCR * * This function is only for fusion controllers. * Update host can queue, if firmware downgrade max supported firmware commands. * Firmware upgrade case will be skipped because underlying firmware has * more resource than exposed to the OS. * */ static void megasas_fusion_update_can_queue(struct megasas_instance *instance, int fw_boot_context) { … } static inline void megasas_get_msix_index(struct megasas_instance *instance, struct scsi_cmnd *scmd, struct megasas_cmd_fusion *cmd, u8 data_arms) { … } /** * megasas_free_cmds_fusion - Free all the cmds in the free cmd pool * @instance: Adapter soft state */ void megasas_free_cmds_fusion(struct megasas_instance *instance) { … } /** * megasas_create_sg_sense_fusion - Creates DMA pool for cmd frames * @instance: Adapter soft state * */ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance) { … } static int megasas_alloc_cmdlist_fusion(struct megasas_instance *instance) { … } static int megasas_alloc_request_fusion(struct megasas_instance *instance) { … } static int megasas_alloc_reply_fusion(struct megasas_instance *instance) { … } static int megasas_alloc_rdpq_fusion(struct megasas_instance *instance) { … } static void megasas_free_rdpq_fusion(struct megasas_instance *instance) { … } static void megasas_free_reply_fusion(struct megasas_instance *instance) { … } /** * megasas_alloc_cmds_fusion - Allocates the command packets * @instance: Adapter soft state * * * Each frame has a 32-bit field called context. This context is used to get * back the megasas_cmd_fusion from the frame when a frame gets completed * In this driver, the 32 bit values are the indices into an array cmd_list. * This array is used only to look up the megasas_cmd_fusion given the context. * The free commands themselves are maintained in a linked list called cmd_pool. * * cmds are formed in the io_request and sg_frame members of the * megasas_cmd_fusion. The context field is used to get a request descriptor * and is used as SMID of the cmd. * SMID value range is from 1 to max_fw_cmds. */ static int megasas_alloc_cmds_fusion(struct megasas_instance *instance) { … } /** * wait_and_poll - Issues a polling command * @instance: Adapter soft state * @cmd: Command packet to be issued * @seconds: Maximum poll time * * For polling, MFI requires the cmd_status to be set to 0xFF before posting. */ int wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd, int seconds) { … } /** * megasas_ioc_init_fusion - Initializes the FW * @instance: Adapter soft state * * Issues the IOC Init cmd */ int megasas_ioc_init_fusion(struct megasas_instance *instance) { … } /** * megasas_sync_pd_seq_num - JBOD SEQ MAP * @instance: Adapter soft state * @pend: set to 1, if it is pended jbod map. * * Issue Jbod map to the firmware. If it is pended command, * issue command and return. If it is first instance of jbod map * issue and receive command. */ int megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend) { … } /* * megasas_get_ld_map_info - Returns FW's ld_map structure * @instance: Adapter soft state * @pend: Pend the command or not * Issues an internal command (DCMD) to get the FW's controller PD * list structure. This information is mainly used to find out SYSTEM * supported by the FW. * dcmd.mbox value setting for MR_DCMD_LD_MAP_GET_INFO * dcmd.mbox.b[0] - number of LDs being sync'd * dcmd.mbox.b[1] - 0 - complete command immediately. * - 1 - pend till config change * dcmd.mbox.b[2] - 0 - supports max 64 lds and uses legacy MR_FW_RAID_MAP * - 1 - supports max MAX_LOGICAL_DRIVES_EXT lds and * uses extended struct MR_FW_RAID_MAP_EXT */ static int megasas_get_ld_map_info(struct megasas_instance *instance) { … } u8 megasas_get_map_info(struct megasas_instance *instance) { … } /* * megasas_sync_map_info - Returns FW's ld_map structure * @instance: Adapter soft state * * Issues an internal command (DCMD) to get the FW's controller PD * list structure. This information is mainly used to find out SYSTEM * supported by the FW. */ int megasas_sync_map_info(struct megasas_instance *instance) { … } /* * meagasas_display_intel_branding - Display branding string * @instance: per adapter object * * Return nothing. */ static void megasas_display_intel_branding(struct megasas_instance *instance) { … } /** * megasas_allocate_raid_maps - Allocate memory for RAID maps * @instance: Adapter soft state * * return: if success: return 0 * failed: return -ENOMEM */ static inline int megasas_allocate_raid_maps(struct megasas_instance *instance) { … } /** * megasas_configure_queue_sizes - Calculate size of request desc queue, * reply desc queue, * IO request frame queue, set can_queue. * @instance: Adapter soft state * @return: void */ static inline void megasas_configure_queue_sizes(struct megasas_instance *instance) { … } static int megasas_alloc_ioc_init_frame(struct megasas_instance *instance) { … } /** * megasas_free_ioc_init_cmd - Free IOC INIT command frame * @instance: Adapter soft state */ static inline void megasas_free_ioc_init_cmd(struct megasas_instance *instance) { … } /** * megasas_init_adapter_fusion - Initializes the FW * @instance: Adapter soft state * * This is the main function for initializing firmware. */ static u32 megasas_init_adapter_fusion(struct megasas_instance *instance) { … } /** * megasas_fault_detect_work - Worker function of * FW fault handling workqueue. * @work: FW fault work struct */ static void megasas_fault_detect_work(struct work_struct *work) { … } int megasas_fusion_start_watchdog(struct megasas_instance *instance) { … } void megasas_fusion_stop_watchdog(struct megasas_instance *instance) { … } /** * map_cmd_status - Maps FW cmd status to OS cmd status * @fusion: fusion context * @scmd: Pointer to cmd * @status: status of cmd returned by FW * @ext_status: ext status of cmd returned by FW * @data_length: command data length * @sense: command sense data */ static void map_cmd_status(struct fusion_context *fusion, struct scsi_cmnd *scmd, u8 status, u8 ext_status, u32 data_length, u8 *sense) { … } /** * megasas_is_prp_possible - * Checks if native NVMe PRPs can be built for the IO * * @instance: Adapter soft state * @scmd: SCSI command from the mid-layer * @sge_count: scatter gather element count. * * Returns: true: PRPs can be built * false: IEEE SGLs needs to be built */ static bool megasas_is_prp_possible(struct megasas_instance *instance, struct scsi_cmnd *scmd, int sge_count) { … } /** * megasas_make_prp_nvme - * Prepare PRPs(Physical Region Page)- SGLs specific to NVMe drives only * * @instance: Adapter soft state * @scmd: SCSI command from the mid-layer * @sgl_ptr: SGL to be filled in * @cmd: Fusion command frame * @sge_count: scatter gather element count. * * Returns: true: PRPs are built * false: IEEE SGLs needs to be built */ static bool megasas_make_prp_nvme(struct megasas_instance *instance, struct scsi_cmnd *scmd, struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr, struct megasas_cmd_fusion *cmd, int sge_count) { … } /** * megasas_make_sgl_fusion - Prepares 32-bit SGL * @instance: Adapter soft state * @scp: SCSI command from the mid-layer * @sgl_ptr: SGL to be filled in * @cmd: cmd we are working on * @sge_count: sge count * */ static void megasas_make_sgl_fusion(struct megasas_instance *instance, struct scsi_cmnd *scp, struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr, struct megasas_cmd_fusion *cmd, int sge_count) { … } /** * megasas_make_sgl - Build Scatter Gather List(SGLs) * @scp: SCSI command pointer * @instance: Soft instance of controller * @cmd: Fusion command pointer * * This function will build sgls based on device type. * For nvme drives, there is different way of building sgls in nvme native * format- PRPs(Physical Region Page). * * Returns the number of sg lists actually used, zero if the sg lists * is NULL, or -ENOMEM if the mapping failed */ static int megasas_make_sgl(struct megasas_instance *instance, struct scsi_cmnd *scp, struct megasas_cmd_fusion *cmd) { … } /** * megasas_set_pd_lba - Sets PD LBA * @io_request: IO request * @cdb_len: cdb length * @io_info: IO information * @scp: SCSI command * @local_map_ptr: Raid map * @ref_tag: Primary reference tag * * Used to set the PD LBA in CDB for FP IOs */ static void megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len, struct IO_REQUEST_INFO *io_info, struct scsi_cmnd *scp, struct MR_DRV_RAID_MAP_ALL *local_map_ptr, u32 ref_tag) { … } /** * megasas_stream_detect - stream detection on read and and write IOs * @instance: Adapter soft state * @cmd: Command to be prepared * @io_info: IO Request info * */ /** stream detection on read and and write IOs */ static void megasas_stream_detect(struct megasas_instance *instance, struct megasas_cmd_fusion *cmd, struct IO_REQUEST_INFO *io_info) { … } /** * megasas_set_raidflag_cpu_affinity - This function sets the cpu * affinity (cpu of the controller) and raid_flags in the raid context * based on IO type. * * @fusion: Fusion context * @praid_context: IO RAID context * @raid: LD raid map * @fp_possible: Is fast path possible? * @is_read: Is read IO? * @scsi_buff_len: SCSI command buffer length * */ static void megasas_set_raidflag_cpu_affinity(struct fusion_context *fusion, union RAID_CONTEXT_UNION *praid_context, struct MR_LD_RAID *raid, bool fp_possible, u8 is_read, u32 scsi_buff_len) { … } /** * megasas_build_ldio_fusion - Prepares IOs to devices * @instance: Adapter soft state * @scp: SCSI command * @cmd: Command to be prepared * * Prepares the io_request and chain elements (sg_frame) for IO * The IO can be for PD (Fast Path) or LD */ static void megasas_build_ldio_fusion(struct megasas_instance *instance, struct scsi_cmnd *scp, struct megasas_cmd_fusion *cmd) { … } /** * megasas_build_ld_nonrw_fusion - prepares non rw ios for virtual disk * @instance: Adapter soft state * @scmd: SCSI command * @cmd: Command to be prepared * * Prepares the io_request frame for non-rw io cmds for vd. */ static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance, struct scsi_cmnd *scmd, struct megasas_cmd_fusion *cmd) { … } /** * megasas_build_syspd_fusion - prepares rw/non-rw ios for syspd * @instance: Adapter soft state * @scmd: SCSI command * @cmd: Command to be prepared * @fp_possible: parameter to detect fast path or firmware path io. * * Prepares the io_request frame for rw/non-rw io cmds for syspds */ static void megasas_build_syspd_fusion(struct megasas_instance *instance, struct scsi_cmnd *scmd, struct megasas_cmd_fusion *cmd, bool fp_possible) { … } /** * megasas_build_io_fusion - Prepares IOs to devices * @instance: Adapter soft state * @scp: SCSI command * @cmd: Command to be prepared * * Invokes helper functions to prepare request frames * and sets flags appropriate for IO/Non-IO cmd */ static int megasas_build_io_fusion(struct megasas_instance *instance, struct scsi_cmnd *scp, struct megasas_cmd_fusion *cmd) { … } static union MEGASAS_REQUEST_DESCRIPTOR_UNION * megasas_get_request_descriptor(struct megasas_instance *instance, u16 index) { … } /* megasas_prepate_secondRaid1_IO * It prepares the raid 1 second IO */ static void megasas_prepare_secondRaid1_IO(struct megasas_instance *instance, struct megasas_cmd_fusion *cmd, struct megasas_cmd_fusion *r1_cmd) { … } /** * megasas_build_and_issue_cmd_fusion -Main routine for building and * issuing non IOCTL cmd * @instance: Adapter soft state * @scmd: pointer to scsi cmd from OS */ static u32 megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance, struct scsi_cmnd *scmd) { … } /** * megasas_complete_r1_command - * completes R1 FP write commands which has valid peer smid * @instance: Adapter soft state * @cmd: MPT command frame * */ static inline void megasas_complete_r1_command(struct megasas_instance *instance, struct megasas_cmd_fusion *cmd) { … } /** * access_irq_context: Access to reply processing * @irq_context: IRQ context * * Synchronize access to reply processing. * * Return: true on success, false on failure. */ static inline bool access_irq_context(struct megasas_irq_context *irq_context) { … } /** * release_irq_context: Release reply processing * @irq_context: IRQ context * * Release access of reply processing. * * Return: Nothing. */ static inline void release_irq_context(struct megasas_irq_context *irq_context) { … } /** * complete_cmd_fusion - Completes command * @instance: Adapter soft state * @MSIxIndex: MSI number * @irq_context: IRQ context * * Completes all commands that is in reply descriptor queue */ static int complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex, struct megasas_irq_context *irq_context) { … } int megasas_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num) { … } /** * megasas_enable_irq_poll() - enable irqpoll * @instance: Adapter soft state */ static void megasas_enable_irq_poll(struct megasas_instance *instance) { … } /** * megasas_sync_irqs - Synchronizes all IRQs owned by adapter * @instance_addr: Adapter soft state address */ static void megasas_sync_irqs(unsigned long instance_addr) { … } /** * megasas_irqpoll() - process a queue for completed reply descriptors * @irqpoll: IRQ poll structure associated with queue to poll. * @budget: Threshold of reply descriptors to process per poll. * * Return: The number of entries processed. */ int megasas_irqpoll(struct irq_poll *irqpoll, int budget) { … } /** * megasas_complete_cmd_dpc_fusion - Completes command * @instance_addr: Adapter soft state address * * Tasklet to complete cmds */ static void megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) { … } /** * megasas_isr_fusion - isr entry point * @irq: IRQ number * @devp: IRQ context */ static irqreturn_t megasas_isr_fusion(int irq, void *devp) { … } /** * build_mpt_mfi_pass_thru - builds a cmd fo MFI Pass thru * @instance: Adapter soft state * @mfi_cmd: megasas_cmd pointer * */ static void build_mpt_mfi_pass_thru(struct megasas_instance *instance, struct megasas_cmd *mfi_cmd) { … } /** * build_mpt_cmd - Calls helper function to build a cmd MFI Pass thru cmd * @instance: Adapter soft state * @cmd: mfi cmd to build * */ static union MEGASAS_REQUEST_DESCRIPTOR_UNION * build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) { … } /** * megasas_issue_dcmd_fusion - Issues a MFI Pass thru cmd * @instance: Adapter soft state * @cmd: mfi cmd pointer * */ static void megasas_issue_dcmd_fusion(struct megasas_instance *instance, struct megasas_cmd *cmd) { … } /** * megasas_release_fusion - Reverses the FW initialization * @instance: Adapter soft state */ void megasas_release_fusion(struct megasas_instance *instance) { … } /** * megasas_read_fw_status_reg_fusion - returns the current FW status value * @instance: Adapter soft state */ static u32 megasas_read_fw_status_reg_fusion(struct megasas_instance *instance) { … } /** * megasas_alloc_host_crash_buffer - Host buffers for Crash dump collection from Firmware * @instance: Controller's soft instance * @return: Number of allocated host crash buffers */ static void megasas_alloc_host_crash_buffer(struct megasas_instance *instance) { … } /** * megasas_free_host_crash_buffer - Host buffers for Crash dump collection from Firmware * @instance: Controller's soft instance */ void megasas_free_host_crash_buffer(struct megasas_instance *instance) { … } /** * megasas_adp_reset_fusion - For controller reset * @instance: Controller's soft instance * @regs: MFI register set */ static int megasas_adp_reset_fusion(struct megasas_instance *instance, struct megasas_register_set __iomem *regs) { … } /** * megasas_check_reset_fusion - For controller reset check * @instance: Controller's soft instance * @regs: MFI register set */ static int megasas_check_reset_fusion(struct megasas_instance *instance, struct megasas_register_set __iomem *regs) { … } /** * megasas_trigger_snap_dump - Trigger snap dump in FW * @instance: Soft instance of adapter */ static inline void megasas_trigger_snap_dump(struct megasas_instance *instance) { … } /* This function waits for outstanding commands on fusion to complete */ static int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance, int reason, int *convert) { … } void megasas_reset_reply_desc(struct megasas_instance *instance) { … } /* * megasas_refire_mgmt_cmd : Re-fire management commands * @instance: Controller's soft instance */ static void megasas_refire_mgmt_cmd(struct megasas_instance *instance, bool return_ioctl) { … } /* * megasas_return_polled_cmds: Return polled mode commands back to the pool * before initiating an OCR. * @instance: Controller's soft instance */ static void megasas_return_polled_cmds(struct megasas_instance *instance) { … } /* * megasas_track_scsiio : Track SCSI IOs outstanding to a SCSI device * @instance: per adapter struct * @channel: the channel assigned by the OS * @id: the id assigned by the OS * * Returns SUCCESS if no IOs pending to SCSI device, else return FAILED */ static int megasas_track_scsiio(struct megasas_instance *instance, int id, int channel) { … } /** * megasas_tm_response_code - translation of device response code * @instance: Controller's soft instance * @mpi_reply: MPI reply returned by firmware * * Return nothing. */ static void megasas_tm_response_code(struct megasas_instance *instance, struct MPI2_SCSI_TASK_MANAGE_REPLY *mpi_reply) { … } /** * megasas_issue_tm - main routine for sending tm requests * @instance: per adapter struct * @device_handle: device handle * @channel: the channel assigned by the OS * @id: the id assigned by the OS * @smid_task: smid assigned to the task * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in megaraid_sas_fusion.c) * @mr_device_priv_data: private data * Context: user * * MegaRaid use MPT interface for Task Magement request. * A generic API for sending task management requests to firmware. * * Return SUCCESS or FAILED. */ static int megasas_issue_tm(struct megasas_instance *instance, u16 device_handle, uint channel, uint id, u16 smid_task, u8 type, struct MR_PRIV_DEVICE *mr_device_priv_data) { … } /* * megasas_fusion_smid_lookup : Look for fusion command corresponding to SCSI * @instance: per adapter struct * * Return Non Zero index, if SMID found in outstanding commands */ static u16 megasas_fusion_smid_lookup(struct scsi_cmnd *scmd) { … } /* * megasas_get_tm_devhandle - Get devhandle for TM request * @sdev- OS provided scsi device * * Returns- devhandle/targetID of SCSI device */ static u16 megasas_get_tm_devhandle(struct scsi_device *sdev) { … } /* * megasas_task_abort_fusion : SCSI task abort function for fusion adapters * @scmd : pointer to scsi command object * * Return SUCCESS, if command aborted else FAILED */ int megasas_task_abort_fusion(struct scsi_cmnd *scmd) { … } /* * megasas_reset_target_fusion : target reset function for fusion adapters * scmd: SCSI command pointer * * Returns SUCCESS if all commands associated with target aborted else FAILED */ int megasas_reset_target_fusion(struct scsi_cmnd *scmd) { … } /*SRIOV get other instance in cluster if any*/ static struct megasas_instance *megasas_get_peer_instance(struct megasas_instance *instance) { … } /* Check for a second path that is currently UP */ int megasas_check_mpio_paths(struct megasas_instance *instance, struct scsi_cmnd *scmd) { … } /* Core fusion reset function */ int megasas_reset_fusion(struct Scsi_Host *shost, int reason) { … } /* Fusion Crash dump collection */ static void megasas_fusion_crash_dump(struct megasas_instance *instance) { … } /* Fusion OCR work queue */ void megasas_fusion_ocr_wq(struct work_struct *work) { … } /* Allocate fusion context */ int megasas_alloc_fusion_context(struct megasas_instance *instance) { … } void megasas_free_fusion_context(struct megasas_instance *instance) { … } struct megasas_instance_template megasas_instance_template_fusion = …;