/* * linux/drivers/message/fusion/mptbase.c * This is the Fusion MPT base driver which supports multiple * (SCSI + LAN) specialized protocol drivers. * For use with LSI PCI chip/adapter(s) * running LSI Fusion MPT (Message Passing Technology) firmware. * * Copyright (c) 1999-2008 LSI Corporation * (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; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. NO WARRANTY THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. DISCLAIMER OF LIABILITY NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #include <linux/kernel.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/seq_file.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/kthread.h> #include <scsi/scsi_host.h> #include "mptbase.h" #include "lsi/mpi_log_fc.h" /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #define my_NAME … #define my_VERSION … #define MYNAM … MODULE_AUTHOR(…); MODULE_DESCRIPTION(…); MODULE_LICENSE(…) …; MODULE_VERSION(…); /* * cmd line parameters */ static int mpt_msi_enable_spi; module_param(mpt_msi_enable_spi, int, 0); MODULE_PARM_DESC(…) …; static int mpt_msi_enable_fc; module_param(mpt_msi_enable_fc, int, 0); MODULE_PARM_DESC(…) …; static int mpt_msi_enable_sas; module_param(mpt_msi_enable_sas, int, 0); MODULE_PARM_DESC(…) …; static int mpt_channel_mapping; module_param(mpt_channel_mapping, int, 0); MODULE_PARM_DESC(…) …; static int mpt_debug_level; static int mpt_set_debug_level(const char *val, const struct kernel_param *kp); module_param_call(…); MODULE_PARM_DESC(…) …; int mpt_fwfault_debug; EXPORT_SYMBOL(…); module_param(mpt_fwfault_debug, int, 0600); MODULE_PARM_DESC(…) …; static char MptCallbacksName[MPT_MAX_PROTOCOL_DRIVERS] [MPT_MAX_CALLBACKNAME_LEN+1]; #ifdef MFCNT static int mfcounter = 0; #define PRINT_MF_COUNT … #endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Public data... */ #define WHOINIT_UNKNOWN … /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Private data... */ /* Adapter link list */ LIST_HEAD(…); /* Callback lookup table */ static MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS]; /* Protocol driver class lookup table */ static int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS]; /* Event handler lookup table */ static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS]; /* Reset handler lookup table */ static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS]; static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS]; #ifdef CONFIG_PROC_FS static struct proc_dir_entry *mpt_proc_root_dir; #endif /* * Driver Callback Index's */ static u8 mpt_base_index = …; static u8 last_drv_idx; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Forward protos... */ static irqreturn_t mpt_interrupt(int irq, void *bus_id); static int mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait, int sleepFlag); static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag); static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev); static void mpt_adapter_disable(MPT_ADAPTER *ioc); static void mpt_adapter_dispose(MPT_ADAPTER *ioc); static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc); static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag); static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason); static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag); static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag); static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag); static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag); static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag); static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag); static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag); static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag); static int PrimeIocFifos(MPT_ADAPTER *ioc); static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag); static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag); static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag); static int GetLanConfigPages(MPT_ADAPTER *ioc); static int GetIoUnitPage2(MPT_ADAPTER *ioc); int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum); static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc); static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, int sleepFlag); static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag); static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init); #ifdef CONFIG_PROC_FS static int mpt_summary_proc_show(struct seq_file *m, void *v); static int mpt_version_proc_show(struct seq_file *m, void *v); static int mpt_iocinfo_proc_show(struct seq_file *m, void *v); #endif static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc); static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers); static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info , u8 cb_idx); static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc); /* module entry point */ static int __init fusion_init (void); static void __exit fusion_exit (void); #define CHIPREG_READ32(addr) … #define CHIPREG_READ32_dmasync(addr) … #define CHIPREG_WRITE32(addr,val) … #define CHIPREG_PIO_WRITE32(addr,val) … #define CHIPREG_PIO_READ32(addr) … static void pci_disable_io_access(struct pci_dev *pdev) { … } static void pci_enable_io_access(struct pci_dev *pdev) { … } static int mpt_set_debug_level(const char *val, const struct kernel_param *kp) { … } /** * mpt_get_cb_idx - obtain cb_idx for registered driver * @dclass: class driver enum * * Returns cb_idx, or zero means it wasn't found **/ static u8 mpt_get_cb_idx(MPT_DRIVER_CLASS dclass) { … } /** * mpt_is_discovery_complete - determine if discovery has completed * @ioc: per adatper instance * * Returns 1 when discovery completed, else zero. */ static int mpt_is_discovery_complete(MPT_ADAPTER *ioc) { … } /** * mpt_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. * Return -1 for other case. */ static int mpt_remove_dead_ioc_func(void *arg) { … } /** * mpt_fault_reset_work - work performed on workq after ioc fault * @work: input argument, used to derive ioc * **/ static void mpt_fault_reset_work(struct work_struct *work) { … } /* * Process turbo (context) reply... */ static void mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa) { … } static void mpt_reply(MPT_ADAPTER *ioc, u32 pa) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_interrupt - MPT adapter (IOC) specific interrupt handler. * @irq: irq number (not used) * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure * * This routine is registered via the request_irq() kernel API call, * and handles all interrupts generated from a specific MPT adapter * (also referred to as a IO Controller or IOC). * This routine must clear the interrupt from the adapter and does * so by reading the reply FIFO. Multiple replies may be processed * per single call to this routine. * * This routine handles register-level access of the adapter but * dispatches (calls) a protocol-specific callback routine to handle * the protocol-specific details of the MPT request completion. */ static irqreturn_t mpt_interrupt(int irq, void *bus_id) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptbase_reply - MPT base driver's callback routine * @ioc: Pointer to MPT_ADAPTER structure * @req: Pointer to original MPT request frame * @reply: Pointer to MPT reply frame (NULL if TurboReply) * * MPT base driver's callback routine; all base driver * "internal" request/reply processing is routed here. * Currently used for EventNotification and EventAck handling. * * Returns 1 indicating original alloc'd request frame ptr * should be freed, or 0 if it shouldn't. */ static int mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_register - Register protocol-specific main callback handler. * @cbfunc: callback function pointer * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value) * @func_name: call function's name * * This routine is called by a protocol-specific driver (SCSI host, * LAN, SCSI target) to register its reply callback routine. Each * protocol-specific driver must do this before it will be able to * use any IOC resources, such as obtaining request frames. * * NOTES: The SCSI protocol driver currently calls this routine thrice * in order to register separate callbacks; one for "normal" SCSI IO; * one for MptScsiTaskMgmt requests; one for Scan/DV requests. * * Returns u8 valued "handle" in the range (and S.O.D. order) * {N,...,7,6,5,...,1} if successful. * A return value of MPT_MAX_PROTOCOL_DRIVERS (including zero!) should be * considered an error by the caller. */ u8 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass, char *func_name) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_deregister - Deregister a protocol drivers resources. * @cb_idx: previously registered callback handle * * Each protocol-specific driver should call this routine when its * module is unloaded. */ void mpt_deregister(u8 cb_idx) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_event_register - Register protocol-specific event callback handler. * @cb_idx: previously registered (via mpt_register) callback handle * @ev_cbfunc: callback function * * This routine can be called by one or more protocol-specific drivers * if/when they choose to be notified of MPT events. * * Returns 0 for success. */ int mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_event_deregister - Deregister protocol-specific event callback handler * @cb_idx: previously registered callback handle * * Each protocol-specific driver should call this routine * when it does not (or can no longer) handle events, * or when its module is unloaded. */ void mpt_event_deregister(u8 cb_idx) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_reset_register - Register protocol-specific IOC reset handler. * @cb_idx: previously registered (via mpt_register) callback handle * @reset_func: reset function * * This routine can be called by one or more protocol-specific drivers * if/when they choose to be notified of IOC resets. * * Returns 0 for success. */ int mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_reset_deregister - Deregister protocol-specific IOC reset handler. * @cb_idx: previously registered callback handle * * Each protocol-specific driver should call this routine * when it does not (or can no longer) handle IOC reset handling, * or when its module is unloaded. */ void mpt_reset_deregister(u8 cb_idx) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_device_driver_register - Register device driver hooks * @dd_cbfunc: driver callbacks struct * @cb_idx: MPT protocol driver index */ int mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_device_driver_deregister - DeRegister device driver hooks * @cb_idx: MPT protocol driver index */ void mpt_device_driver_deregister(u8 cb_idx) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_get_msg_frame - Obtain an MPT request frame from the pool * @cb_idx: Handle of registered MPT protocol driver * @ioc: Pointer to MPT adapter structure * * Obtain an MPT request frame from the pool (of 1024) that are * allocated per MPT adapter. * * Returns pointer to a MPT request frame or %NULL if none are available * or IOC is not active. */ MPT_FRAME_HDR* mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_put_msg_frame - Send a protocol-specific MPT request frame to an IOC * @cb_idx: Handle of registered MPT protocol driver * @ioc: Pointer to MPT adapter structure * @mf: Pointer to MPT request frame * * This routine posts an MPT request frame to the request post FIFO of a * specific MPT adapter. */ void mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) { … } /** * mpt_put_msg_frame_hi_pri - Send a hi-pri protocol-specific MPT request frame * @cb_idx: Handle of registered MPT protocol driver * @ioc: Pointer to MPT adapter structure * @mf: Pointer to MPT request frame * * Send a protocol-specific MPT request frame to an IOC using * hi-priority request queue. * * This routine posts an MPT request frame to the request post FIFO of a * specific MPT adapter. **/ void mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_free_msg_frame - Place MPT request frame back on FreeQ. * @ioc: Pointer to MPT adapter structure * @mf: Pointer to MPT request frame * * This routine places a MPT request frame back on the MPT adapter's * FreeQ. */ void mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_add_sge - Place a simple 32 bit SGE at address pAddr. * @pAddr: virtual address for SGE * @flagslength: SGE flags and data transfer length * @dma_addr: Physical address * * This routine places a MPT request frame back on the MPT adapter's * FreeQ. */ static void mpt_add_sge(void *pAddr, u32 flagslength, dma_addr_t dma_addr) { … } /** * mpt_add_sge_64bit - Place a simple 64 bit SGE at address pAddr. * @pAddr: virtual address for SGE * @flagslength: SGE flags and data transfer length * @dma_addr: Physical address * * This routine places a MPT request frame back on the MPT adapter's * FreeQ. **/ static void mpt_add_sge_64bit(void *pAddr, u32 flagslength, dma_addr_t dma_addr) { … } /** * mpt_add_sge_64bit_1078 - Place a simple 64 bit SGE at address pAddr (1078 workaround). * @pAddr: virtual address for SGE * @flagslength: SGE flags and data transfer length * @dma_addr: Physical address * * This routine places a MPT request frame back on the MPT adapter's * FreeQ. **/ static void mpt_add_sge_64bit_1078(void *pAddr, u32 flagslength, dma_addr_t dma_addr) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_add_chain - Place a 32 bit chain SGE at address pAddr. * @pAddr: virtual address for SGE * @next: nextChainOffset value (u32's) * @length: length of next SGL segment * @dma_addr: Physical address * */ static void mpt_add_chain(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_add_chain_64bit - Place a 64 bit chain SGE at address pAddr. * @pAddr: virtual address for SGE * @next: nextChainOffset value (u32's) * @length: length of next SGL segment * @dma_addr: Physical address * */ static void mpt_add_chain_64bit(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_send_handshake_request - Send MPT request via doorbell handshake method. * @cb_idx: Handle of registered MPT protocol driver * @ioc: Pointer to MPT adapter structure * @reqBytes: Size of the request in bytes * @req: Pointer to MPT request frame * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. * * This routine is used exclusively to send MptScsiTaskMgmt * requests since they are required to be sent via doorbell handshake. * * NOTE: It is the callers responsibility to byte-swap fields in the * request which are greater than 1 byte in size. * * Returns 0 for success, non-zero for failure. */ int mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_host_page_access_control - control the IOC's Host Page Buffer access * @ioc: Pointer to MPT adapter structure * @access_control_value: define bits below * @sleepFlag: Specifies whether the process can sleep * * Provides mechanism for the host driver to control the IOC's * Host Page Buffer access. * * Access Control Value - bits[15:12] * 0h Reserved * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS } * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS } * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER } * * Returns 0 for success, non-zero for failure. */ static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_host_page_alloc - allocate system memory for the fw * @ioc: Pointer to pointer to IOC adapter * @ioc_init: Pointer to ioc init config page * * If we already allocated memory in past, then resend the same pointer. * Returns 0 for success, non-zero for failure. */ static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure. * @iocid: IOC unique identifier (integer) * @iocpp: Pointer to pointer to IOC adapter * * Given a unique IOC identifier, set pointer to the associated MPT * adapter structure. * * Returns iocid and sets iocpp if iocid is found. * Returns -1 if iocid is not found. */ int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) { … } /** * mpt_get_product_name - returns product string * @vendor: pci vendor id * @device: pci device id * @revision: pci revision id * * Returns product string displayed when driver loads, * in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product * **/ static const char* mpt_get_product_name(u16 vendor, u16 device, u8 revision) { … } /** * mpt_mapresources - map in memory mapped io * @ioc: Pointer to pointer to IOC adapter * **/ static int mpt_mapresources(MPT_ADAPTER *ioc) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_attach - Install a PCI intelligent MPT adapter. * @pdev: Pointer to pci_dev structure * @id: PCI device ID information * * This routine performs all the steps necessary to bring the IOC of * a MPT adapter to a OPERATIONAL state. This includes registering * memory regions, registering the interrupt, and allocating request * and reply memory pools. * * This routine also pre-fetches the LAN MAC address of a Fibre Channel * MPT adapter. * * Returns 0 for success, non-zero for failure. * * TODO: Add support for polled controllers */ int mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_detach - Remove a PCI intelligent MPT adapter. * @pdev: Pointer to pci_dev structure */ void mpt_detach(struct pci_dev *pdev) { … } /************************************************************************** * Power Management */ #ifdef CONFIG_PM /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_suspend - Fusion MPT base driver suspend routine. * @pdev: Pointer to pci_dev structure * @state: new state to enter */ int mpt_suspend(struct pci_dev *pdev, pm_message_t state) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_resume - Fusion MPT base driver resume routine. * @pdev: Pointer to pci_dev structure */ int mpt_resume(struct pci_dev *pdev) { … } #endif static int mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_do_ioc_recovery - Initialize or recover MPT adapter. * @ioc: Pointer to MPT adapter structure * @reason: Event word / reason * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. * * This routine performs all the steps necessary to bring the IOC * to a OPERATIONAL state. * * This routine also pre-fetches the LAN MAC address of a Fibre Channel * MPT adapter. * * Returns: * 0 for success * -1 if failed to get board READY * -2 if READY but IOCFacts Failed * -3 if READY but PrimeIOCFifos Failed * -4 if READY but IOCInit Failed * -5 if failed to enable_device and/or request_selected_regions * -6 if failed to upload firmware */ static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_detect_bound_ports - Search for matching PCI bus/dev_function * @ioc: Pointer to MPT adapter structure * @pdev: Pointer to (struct pci_dev) structure * * Search for PCI bus/dev_function which matches * PCI bus/dev_function (+/-1) for newly discovered 929, * 929X, 1030 or 1035. * * If match on PCI dev_function +/-1 is found, bind the two MPT adapters * using alt_ioc pointer fields in their %MPT_ADAPTER structures. */ static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_adapter_disable - Disable misbehaving MPT adapter. * @ioc: Pointer to MPT adapter structure */ static void mpt_adapter_disable(MPT_ADAPTER *ioc) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_adapter_dispose - Free all resources associated with an MPT adapter * @ioc: Pointer to MPT adapter structure * * This routine unregisters h/w resources and frees all alloc'd memory * associated with a MPT adapter structure. */ static void mpt_adapter_dispose(MPT_ADAPTER *ioc) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * MptDisplayIocCapabilities - Disply IOC's capabilities. * @ioc: Pointer to MPT adapter structure */ static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * MakeIocReady - Get IOC to a READY state, using KickStart if needed. * @ioc: Pointer to MPT_ADAPTER structure * @force: Force hard KickStart of IOC * @sleepFlag: Specifies whether the process can sleep * * Returns: * 1 - DIAG reset and READY * 0 - READY initially OR soft reset and READY * -1 - Any failure on KickStart * -2 - Msg Unit Reset Failed * -3 - IO Unit Reset Failed * -4 - IOC owned by a PEER */ static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_GetIocState - Get the current state of a MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @cooked: Request raw or cooked IOC state * * Returns all IOC Doorbell register bits if cooked==0, else just the * Doorbell bits in MPI_IOC_STATE_MASK. */ u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * GetIocFacts - Send IOCFacts request to MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @sleepFlag: Specifies whether the process can sleep * @reason: If recovery, only update facts. * * Returns 0 for success, non-zero for failure. */ static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * GetPortFacts - Send PortFacts request to MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @portnum: Port number * @sleepFlag: Specifies whether the process can sleep * * Returns 0 for success, non-zero for failure. */ static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * SendIocInit - Send IOCInit request to MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @sleepFlag: Specifies whether the process can sleep * * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state. * * Returns 0 for success, non-zero for failure. */ static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * SendPortEnable - Send PortEnable request to MPT adapter port. * @ioc: Pointer to MPT_ADAPTER structure * @portnum: Port number to enable * @sleepFlag: Specifies whether the process can sleep * * Send PortEnable to bring IOC to OPERATIONAL state. * * Returns 0 for success, non-zero for failure. */ static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) { … } /** * mpt_alloc_fw_memory - allocate firmware memory * @ioc: Pointer to MPT_ADAPTER structure * @size: total FW bytes * * If memory has already been allocated, the same (cached) value * is returned. * * Return 0 if successful, or non-zero for failure **/ int mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size) { … } /** * mpt_free_fw_memory - free firmware memory * @ioc: Pointer to MPT_ADAPTER structure * * If alt_img is NULL, delete from ioc structure. * Else, delete a secondary image in same format. **/ void mpt_free_fw_memory(MPT_ADAPTER *ioc) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port. * @ioc: Pointer to MPT_ADAPTER structure * @sleepFlag: Specifies whether the process can sleep * * Returns 0 for success, >0 for handshake failure * <0 for fw upload failure. * * Remark: If bound IOC and a successful FWUpload was performed * on the bound IOC, the second image is discarded * and memory is free'd. Both channels must upload to prevent * IOC from running in degraded mode. */ static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_downloadboot - DownloadBoot code * @ioc: Pointer to MPT_ADAPTER structure * @pFwHeader: Pointer to firmware header info * @sleepFlag: Specifies whether the process can sleep * * FwDownloadBoot requires Programmed IO access. * * Returns 0 for success * -1 FW Image size is 0 * -2 No valid cached_fw Pointer * <0 for fw upload failure. */ static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * KickStart - Perform hard reset of MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @force: Force hard reset * @sleepFlag: Specifies whether the process can sleep * * This routine places MPT adapter in diagnostic mode via the * WriteSequence register, and then performs a hard reset of adapter * via the Diagnostic register. * * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread) * or NO_SLEEP (interrupt thread, use mdelay) * force - 1 if doorbell active, board fault state * board operational, IOC_RECOVERY or * IOC_BRINGUP and there is an alt_ioc. * 0 else * * Returns: * 1 - hard reset, READY * 0 - no reset due to History bit, READY * -1 - no reset due to History bit but not READY * OR reset but failed to come READY * -2 - no reset, could not enter DIAG mode * -3 - reset but bad FW bit */ static int KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_diag_reset - Perform hard reset of the adapter. * @ioc: Pointer to MPT_ADAPTER structure * @ignore: Set if to honor and clear to ignore * the reset history bit * @sleepFlag: CAN_SLEEP if called in a non-interrupt thread, * else set to NO_SLEEP (use mdelay instead) * * This routine places the adapter in diagnostic mode via the * WriteSequence register and then performs a hard reset of adapter * via the Diagnostic register. Adapter should be in ready state * upon successful completion. * * Returns: 1 hard reset successful * 0 no reset performed because reset history bit set * -2 enabling diagnostic mode failed * -3 diagnostic reset failed */ static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * SendIocReset - Send IOCReset request to MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @reset_type: reset type, expected values are * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET * @sleepFlag: Specifies whether the process can sleep * * Send IOCReset request to the MPT adapter. * * Returns 0 for success, non-zero for failure. */ static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * initChainBuffers - Allocate memory for and initialize chain buffers * @ioc: Pointer to MPT_ADAPTER structure * * Allocates memory for and initializes chain buffers, * chain buffer control arrays and spinlock. */ static int initChainBuffers(MPT_ADAPTER *ioc) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * PrimeIocFifos - Initialize IOC request and reply FIFOs. * @ioc: Pointer to MPT_ADAPTER structure * * This routine allocates memory for the MPT reply and request frame * pools (if necessary), and primes the IOC reply FIFO with * reply frames. * * Returns 0 for success, non-zero for failure. */ static int PrimeIocFifos(MPT_ADAPTER *ioc) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_handshake_req_reply_wait - Send MPT request to and receive reply * from IOC via doorbell handshake method. * @ioc: Pointer to MPT_ADAPTER structure * @reqBytes: Size of the request in bytes * @req: Pointer to MPT request frame * @replyBytes: Expected size of the reply in bytes * @u16reply: Pointer to area where reply should be written * @maxwait: Max wait time for a reply (in seconds) * @sleepFlag: Specifies whether the process can sleep * * NOTES: It is the callers responsibility to byte-swap fields in the * request which are greater than 1 byte in size. It is also the * callers responsibility to byte-swap response fields which are * greater than 1 byte in size. * * Returns 0 for success, non-zero for failure. */ static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge * @ioc: Pointer to MPT_ADAPTER structure * @howlong: How long to wait (in seconds) * @sleepFlag: Specifies whether the process can sleep * * This routine waits (up to ~2 seconds max) for IOC doorbell * handshake ACKnowledge, indicated by the IOP_DOORBELL_STATUS * bit in its IntStatus register being clear. * * Returns a negative value on failure, else wait loop count. */ static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit * @ioc: Pointer to MPT_ADAPTER structure * @howlong: How long to wait (in seconds) * @sleepFlag: Specifies whether the process can sleep * * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt * (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register. * * Returns a negative value on failure, else wait loop count. */ static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * WaitForDoorbellReply - Wait for and capture an IOC handshake reply. * @ioc: Pointer to MPT_ADAPTER structure * @howlong: How long to wait (in seconds) * @sleepFlag: Specifies whether the process can sleep * * This routine polls the IOC for a handshake reply, 16 bits at a time. * Reply is cached to IOC private area large enough to hold a maximum * of 128 bytes of reply data. * * Returns a negative value on failure, else size of reply in WORDS. */ static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * GetLanConfigPages - Fetch LANConfig pages. * @ioc: Pointer to MPT_ADAPTER structure * * Return: 0 for success * -ENOMEM if no memory available * -EPERM if not allowed due to ISR context * -EAGAIN if no msg frames currently available * -EFAULT for non-successful reply or no reply (timeout) */ static int GetLanConfigPages(MPT_ADAPTER *ioc) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptbase_sas_persist_operation - Perform operation on SAS Persistent Table * @ioc: Pointer to MPT_ADAPTER structure * @persist_opcode: see below * * =============================== ====================================== * MPI_SAS_OP_CLEAR_NOT_PRESENT Free all persist TargetID mappings for * devices not currently present. * MPI_SAS_OP_CLEAR_ALL_PERSISTENT Clear al persist TargetID mappings * =============================== ====================================== * * NOTE: Don't use not this function during interrupt time. * * Returns 0 for success, non-zero error */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static void mptbase_raid_process_event_data(MPT_ADAPTER *ioc, MpiEventDataRaid_t * pRaidEventData) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * GetIoUnitPage2 - Retrieve BIOS version and boot order information. * @ioc: Pointer to MPT_ADAPTER structure * * Returns: 0 for success * -ENOMEM if no memory available * -EPERM if not allowed due to ISR context * -EAGAIN if no msg frames currently available * -EFAULT for non-successful reply or no reply (timeout) */ static int GetIoUnitPage2(MPT_ADAPTER *ioc) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2 * @ioc: Pointer to a Adapter Strucutre * @portnum: IOC port number * * Return: -EFAULT if read of config page header fails * or if no nvram * If read of SCSI Port Page 0 fails, * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF) * Adapter settings: async, narrow * Return 1 * If read of SCSI Port Page 2 fails, * Adapter settings valid * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF) * Return 1 * Else * Both valid * Return 0 * CHECK - what type of locking mechanisms should be used???? */ static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_readScsiDevicePageHeaders - save version and length of SDP1 * @ioc: Pointer to a Adapter Strucutre * @portnum: IOC port number * * Return: -EFAULT if read of config page header fails * or 0 if success. */ static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) { … } /** * mpt_inactive_raid_list_free - This clears this link list. * @ioc : pointer to per adapter structure **/ static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc) { … } /** * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume * * @ioc : pointer to per adapter structure * @channel : volume channel * @id : volume target id **/ static void mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id) { … } /** * mpt_raid_phys_disk_pg0 - returns phys disk page zero * @ioc: Pointer to a Adapter Structure * @phys_disk_num: io unit unique phys disk num generated by the ioc * @phys_disk: requested payload data returned * * Return: * 0 on success * -EFAULT if read of config page header fails or data pointer not NULL * -ENOMEM if pci_alloc failed **/ int mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, RaidPhysDiskPage0_t *phys_disk) { … } /** * mpt_raid_phys_disk_get_num_paths - returns number paths associated to this phys_num * @ioc: Pointer to a Adapter Structure * @phys_disk_num: io unit unique phys disk num generated by the ioc * * Return: * returns number paths **/ int mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, u8 phys_disk_num) { … } EXPORT_SYMBOL(…); /** * mpt_raid_phys_disk_pg1 - returns phys disk page 1 * @ioc: Pointer to a Adapter Structure * @phys_disk_num: io unit unique phys disk num generated by the ioc * @phys_disk: requested payload data returned * * Return: * 0 on success * -EFAULT if read of config page header fails or data pointer not NULL * -ENOMEM if pci_alloc failed **/ int mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num, RaidPhysDiskPage1_t *phys_disk) { … } EXPORT_SYMBOL(…); /** * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes * @ioc: Pointer to a Adapter Strucutre * * Return: * 0 on success * -EFAULT if read of config page header fails or data pointer not NULL * -ENOMEM if pci_alloc failed **/ int mpt_findImVolumes(MPT_ADAPTER *ioc) { … } static int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) { … } static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc) { … } static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc) { … } static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * SendEventNotification - Send EventNotification (on or off) request to adapter * @ioc: Pointer to MPT_ADAPTER structure * @EvSwitch: Event switch flags * @sleepFlag: Specifies whether the process can sleep */ static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, int sleepFlag) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * SendEventAck - Send EventAck request to MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @evnp: Pointer to original EventNotification request */ static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_config - Generic function to issue config message * @ioc: Pointer to an adapter structure * @pCfg: Pointer to a configuration structure. Struct contains * action, page address, direction, physical address * and pointer to a configuration page header * Page header is updated. * * Returns 0 for success * -EAGAIN if no msg frames currently available * -EFAULT for non-successful reply or no reply (timeout) */ int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_ioc_reset - Base cleanup for hard reset * @ioc: Pointer to the adapter structure * @reset_phase: Indicates pre- or post-reset functionality * * Remark: Frees resources with internally generated commands. */ static int mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { … } #ifdef CONFIG_PROC_FS /* { */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff... */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries. * * Returns 0 for success, non-zero for failure. */ static int procmpt_create(void) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries. * * Returns 0 for success, non-zero for failure. */ static void procmpt_destroy(void) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary. */ static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan); static int mpt_summary_proc_show(struct seq_file *m, void *v) { … } static int mpt_version_proc_show(struct seq_file *m, void *v) { … } static int mpt_iocinfo_proc_show(struct seq_file *m, void *v) { … } #endif /* CONFIG_PROC_FS } */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer. * @ioc: Pointer to MPT_ADAPTER structure * @buffer: Pointer to buffer where IOC summary info should be written * @size: Pointer to number of bytes we wrote (set by this routine) * @len: Offset at which to start writing in buffer * @showlan: Display LAN stuff? * * This routine writes (english readable) ASCII text, which represents * a summary of IOC information, to a buffer. */ void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan) { … } #ifdef CONFIG_PROC_FS static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan) { … } #endif /** * mpt_set_taskmgmt_in_progress_flag - set flags associated with task management * @ioc: Pointer to MPT_ADAPTER structure * * Returns 0 for SUCCESS or -1 if FAILED. * * If -1 is return, then it was not possible to set the flags **/ int mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc) { … } EXPORT_SYMBOL(…); /** * mpt_clear_taskmgmt_in_progress_flag - clear flags associated with task management * @ioc: Pointer to MPT_ADAPTER structure * **/ void mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc) { … } EXPORT_SYMBOL(…); /** * mpt_halt_firmware - Halts the firmware if it is operational and panic * the kernel * @ioc: Pointer to MPT_ADAPTER structure * **/ void __noreturn mpt_halt_firmware(MPT_ADAPTER *ioc) { … } EXPORT_SYMBOL(…); /** * mpt_SoftResetHandler - Issues a less expensive reset * @ioc: Pointer to MPT_ADAPTER structure * @sleepFlag: Indicates if sleep or schedule must be called. * * Returns 0 for SUCCESS or -1 if FAILED. * * Message Unit Reset - instructs the IOC to reset the Reply Post and * Free FIFO's. All the Message Frames on Reply Free FIFO are discarded. * All posted buffers are freed, and event notification is turned off. * IOC doesn't reply to any outstanding request. This will transfer IOC * to READY state. **/ static int mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag) { … } /** * mpt_Soft_Hard_ResetHandler - Try less expensive reset * @ioc: Pointer to MPT_ADAPTER structure * @sleepFlag: Indicates if sleep or schedule must be called. * * Returns 0 for SUCCESS or -1 if FAILED. * Try for softreset first, only if it fails go for expensive * HardReset. **/ int mpt_Soft_Hard_ResetHandler(MPT_ADAPTER *ioc, int sleepFlag) { … } EXPORT_SYMBOL(…); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Reset Handling */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_HardResetHandler - Generic reset handler * @ioc: Pointer to MPT_ADAPTER structure * @sleepFlag: Indicates if sleep or schedule must be called. * * Issues SCSI Task Management call based on input arg values. * If TaskMgmt fails, returns associated SCSI request. * * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) * or a non-interrupt thread. In the former, must not call schedule(). * * Note: A return of -1 is a FATAL error case, as it means a * FW reload/initialization failed. * * Returns 0 for SUCCESS or -1 if FAILED. */ int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) { … } #ifdef CONFIG_FUSION_LOGGING static void mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply) { … } #endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * ProcessEventNotification - Route EventNotificationReply to all event handlers * @ioc: Pointer to MPT_ADAPTER structure * @pEventReply: Pointer to EventNotification reply frame * @evHandlers: Pointer to integer, number of event handlers * * Routes a received EventNotificationReply to all currently registered * event handlers. * Returns sum of event handlers return values. */ static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_fc_log_info - Log information returned from Fibre Channel IOC. * @ioc: Pointer to MPT_ADAPTER structure * @log_info: U32 LogInfo reply word from the IOC * * Refer to lsi/mpi_log_fc.h. */ static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_spi_log_info - Log information returned from SCSI Parallel IOC. * @ioc: Pointer to MPT_ADAPTER structure * @log_info: U32 LogInfo word from the IOC * * Refer to lsi/sp_log.h. */ static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) { … } /* strings for sas loginfo */ static char *originator_str[] = …; static char *iop_code_str[] = …; static char *pl_code_str[] = …; static char *ir_code_str[] = …; static char *raid_sub_code_str[] = …; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_sas_log_info - Log information returned from SAS IOC. * @ioc: Pointer to MPT_ADAPTER structure * @log_info: U32 LogInfo reply word from the IOC * @cb_idx: callback function's handle * * Refer to lsi/mpi_log_sas.h. **/ static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info, u8 cb_idx) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_iocstatus_info_config - IOCSTATUS information for config pages * @ioc: Pointer to MPT_ADAPTER structure * @ioc_status: U32 IOCStatus word from IOC * @mf: Pointer to MPT request frame * * Refer to lsi/mpi.h. **/ static void mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) { … } /** * mpt_iocstatus_info - IOCSTATUS information returned from IOC. * @ioc: Pointer to MPT_ADAPTER structure * @ioc_status: U32 IOCStatus word from IOC * @mf: Pointer to MPT request frame * * Refer to lsi/mpi.h. **/ static void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); #ifdef CONFIG_PM EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); #endif EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); EXPORT_SYMBOL(…); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * fusion_init - Fusion MPT base driver initialization routine. * * Returns 0 for success, non-zero for failure. */ static int __init fusion_init(void) { … } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * fusion_exit - Perform driver unload cleanup. * * This routine frees all resources associated with each MPT adapter * and removes all %MPT_PROCFS_MPTBASEDIR entries. */ static void __exit fusion_exit(void) { … } module_init(…) …; module_exit(fusion_exit);